---
# System prepended metadata

title: MOV圖靈完備
tags: [Reverse]

---

# MOV圖靈完備
###### tags: `Reverse`

## stack
1. MoVfuscator使用自己的stack(原則上在bss上,STACK_SIZE=0x200000)
2. 
    ```c
    mov old_esp, esp
    mov esp, new_esp
    ```
3. esp移動(esp = esp - 4)
    ```c
    mov esp, [esp-0x100060] or mov esp, [esp-0x200068] 
    ```

## 使用SIGNAL
```c
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
```
1. SIGSEGV :arrow_right: 用來執行library function
![](https://i.imgur.com/7VQ6Qj9.png)
2. SIGILL :arrow_right: 用來jmp to master_loop

## 其他structure
1. DISCARD_SIZE = 0x200000
    all byte in discard = 1
3. STACK_SIZE =0x200000
4. branch_temp : 暫存要跳的目的地
5. stack_temp : push用,暫存要push的data
6. sel_on = {&discard, &on}
    on = 0 (init, set at beginning of master_loop)
    toggle_execution = 1 (boolean, init)
    > on用來控制branch是否要執行
    > on=1 : branch不執行(不跳)
    > 反之則先存下target並讓on=0
7. sel_target = {&discard, &target}
    target = 0 (init)
8. sel_data = &discard
    data_p = 0 (init)

## mov模擬其他指令
### equality test and branches
- x == y?
    - case1 : x != y (x=5, y=3)
        ```c
        mov [x], 0 // [5] = 0
        mov [y], 1 // [3] = 1
        mov R, [x] // R = 0
        ```    
    - case2 : x == y (x = y = 3)
        ```c
        mov [x], 0 // [3] = 0
        mov [y], 1 // [3] = 1
        mov R, [x] // R = 1
        ```
- branch : 
`if x == y then x = 100`
    > 想法:
    >   設置一個selector,分別指向100及x原本的值所在位址
    >   int* sel_data[] = {&discard, &data}
    >   如果x != y就把100 assign給discard
    >   反之x = y就assign給x
    ```c
    mov eax, [x]
    mov [eax], 0 
    mov eax, [y]
    mov [eax], 1 
    mov eax, [x] 
    mov eax, sel_data[eax*4]
    mov [eax], 100
    ```
    - case 1 (x = 5, y = 3)
        ```c
        mov eax, [x] 
        mov [eax], 0 // [5] = 0
        mov eax, [y] 
        mov [eax], 1 // [3] = 1
        mov eax, [x] // eax = 0
        mov eax, sel_data[eax*4] // eax = &discard
        mov [eax], 100 // discard = 100
        ```
    - case 2 (x = y = 3)
        ```c
        mov eax, [x] 
        mov [eax], 0 // [3] = 0
        mov eax, [y] 
        mov [eax], 1 // [3]= 1
        mov eax, [x] // eax = 1
        mov eax, sel_data[eax*4] // eax = &discard
        mov [eax], 100 // discard = 100
        ```
        :::info
        問題是!不能隨意再任意位置寫!
        sol: 每次取一個byte,並用一個256byte的array EQ來進行equality test
        ```c
        section .bss
        EQ: resb 256 //reserve 256bytes

        section .text
        mov al, [x]
        mov byte [EQ+eax], 0
        mov al, [y]
        mov byte [EQ+eax], 1
        mov al, [x] //al=0 if x!=y, al=1 if x=y
        mov al, [EQ+eax*4]
        ```
        :::
    
- extend if/else
        - toggle_execution : 一個switch,boolean
        - sel_on = {&discard, &on} : selector
            sel_on[toggle_execution*4]
        - on : 1表branch not taken(不跳),此時sel_data指向真資料(data)
            0表branch taken(跳),sel_data指向假資料(discard)

### 算術指令
:::success
inc byte : 利用一個increment function
```c
unsigned char inc[]={
1, 2, 3, 4, 5, ..., 255, 0
};
//找2+1就去inc[2]
```
dec byte
```c
unsigned char dec[]={
255, 0, 1, 2, ..., 254 
};
//找3-1就去dec[3]
```
:::
1. alu_add
    ```c 
    num1 + num2 (32bit)
    1. eax, ebx, ecx, edx清成0
    2. carry_bit = 0
    3. for i in range(4):
        al = num1[i]
        cl = num2[i]
        ebx = carry_bit = 0
        dl = [eax + ecx] && 0x00ff
        dh = [eax + ecx] && 0xff00 //有進位才=1
        result[i] = [edx + ebx] && 0x00ff //edx
                                          //加上前一輪結果的carry_bit
        carry_bit = [edx + ebx] && 0xff00 
    4. eax = result
    ```
4. sub
    ```c 
    num1 - num2 (32bit) 
    //(num1 + (~num2) + 1 = num1 - num2)
    1. for i in range(4):
        num2[i] = ~num2[i] && 0xff
    2. eax, ebx, ecx, edx清成0
    3. carry_bit = 1
    4. for i in range(4):
        al = num1[i]
        cl = num2'[i]
        ebx = carry_bit = 0
        dl = [eax + ecx] && 0x00ff
        dh = [eax + ecx] && 0xff00 //有進位才=1
        result[i] = [edx + ebx] && 0x00ff //加上前一輪結果的carry_bit
        carry_bit = [edx + ebx] && 0xff00 
    5. eax = result
    ```
    
### cmp
```c
cmp x, y: x-y,並用cf(carry flag), sf(sign flag)
1. alu_x = x
   alu_y = y
   alu_t = y //sub will destroy y
2. alu_x - alu_y 
3. alu_y = alu_t = y
4. al = alu_c
    > if x=y, alu_s=alu_c=0
    > if x>y, alu_s > 0, alu_c = 0
    > if x<y, alu_s < 0, alu_c = 1
   al = alu_false[eax]
   cf = al (如果x<y,carry flag設成1)
5. al = alu_s[3]
    > if x<y --> alu_s < 0 == 0xffff... --> al=0xffff
   sf = al & 0x80 >> 7
    > if x<y --> sf = 1
6. eax, edx = 0
7. dl = alu_s[0]
   
```   

### 邏輯算數指令
:::success
and bit
`char and[2][2]={{0, 0}, {0,1}} //1 & 0 --> and[1][0]`
or bit
`char or[2][2]={{0, 1}, {1, 1}} //0 | 1 --> or[0][1]`
not bit
`char not[2]={1, 0}`
:::
1. and
    ```c
    num1 & num2
    1. for i in range(4):
        eax, edx = 0
        eax = num1[i]
        edx = num2[i]
        eax = eax & 0xff
        result[i] = [eax + edx] 
    ```

### push & pop
1. push
    ```c
    push x //x為要push的東西
    I. esp = esp-4 (移動esp)
        1. edx = on
           data_p = off curr_esp
        3. eax = sel_data[edx*4]
            > on=1: eax = &data_p > off curr_esp
            > on=0: eax = &discard
        4. curr_esp = curr_esp - 4
    II. 將x放在curr_esp上
        1. edx = on
           data_p = curr_esp
        2. eax = sel_data[edx*4]
            > on=1: eax = &data_p > curr_esp
            > on=0: eax = &discard
        3. edx = x
        4. in_curr_esp = x

    ```
## 如何跳出loop(halt)
- read address 0
    `mov eax, [0]`
- 用來執行外部function
    ```c
    ex fgets()
    1. 放參數
        esp = #1參數
        esp+4 = #2參數
        ...
    2. mov _plt, off _fgets //把fgets在plt中的address放進_plt中
    3. eax = on
    4. eax = fault[eax*4]
        > on=1: eax = 0 (&fault)
        > on=0: eax = &not_fault
    5. mov eax, [eax] //因為eax=0,Segmentation fault
                     //執行指定好的signal_handler()
    6. 執行結果會在eax
       mov input, eax
    ```

## 整理
1. 每個variable都有一個selector
    `int* selector[] = {&dummy_data, &data}`
2. master_loop
    1. 設定新的esp
    2. disable toggle_execution(讓sel_on指向&dispatch)
        ![](https://i.imgur.com/MmrChDm.png)
    3. 接著把old_esp + 4(放binary path)存在stack_temp中
    4. push binary_path
        ![](https://i.imgur.com/zZiQNFf.png)

    