# 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)