# 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

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 = ¬_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)

3. 接著把old_esp + 4(放binary path)存在stack_temp中
4. push binary_path
