x86彙編反編譯到c語言之——(2)if語句

Just_4_fun發表於2021-11-29

一. 測試的C語句及編譯後的x86彙編程式碼

int a;
int b;

int main(void) {
    int c;

    if (c)
            a = 4;
        else
            b = 5;

    return 0;
}
 1 .text:0000000000400457                 push    rbp
 2 .text:0000000000400458                 mov     rbp, rsp
 3 .text:000000000040045B                 sub     rsp, 10h
 4 .text:000000000040045F                 mov     [rbp-10], rsp
 5 .text:0000000000400463                 lea     rax, [rbp-4]
 6 .text:0000000000400467                 movsxd  rax, dword ptr [rax]
 7 .text:000000000040046A                 cmp     eax, 0
 8 .text:000000000040046D                 jz      short loc_400483
 9 .text:000000000040046F                 lea     rax, a
10 .text:0000000000400476                 push    rax
11 .text:0000000000400477                 mov     rax, 4
12 .text:000000000040047E                 pop     rdi
13 .text:000000000040047F                 mov     [rdi], eax
14 .text:0000000000400481                 jmp     short loc_400495
15 .text:0000000000400483 ; ---------------------------------------------------------------
16 .text:0000000000400483
17 .text:0000000000400483 loc_400483:                             ; CODE XREF: main+16↑j
18 .text:0000000000400483                 lea     rax, b
19 .text:000000000040048A                 push    rax
20 .text:000000000040048B                 mov     rax, 5
21 .text:0000000000400492                 pop     rdi
22 .text:0000000000400493                 mov     [rdi], eax
23 .text:0000000000400495
24 .text:0000000000400495 loc_400495:                             ; CODE XREF: main+2A↑j
25 .text:0000000000400495                 mov     rax, 0
26 .text:000000000040049C                 jmp     short loc_4004A5
27 .text:000000000040049E ; ---------------------------------------------------------------
28 .text:000000000040049E                 mov     rax, 0
29 .text:00000000004004A5
30 .text:00000000004004A5 loc_4004A5:                             ; CODE XREF: main+45↑j
31 .text:00000000004004A5                 mov     rsp, rbp
32 .text:00000000004004A8                 pop     rbp
33 .text:00000000004004A9                 retn

 

二. x86彙編到虛擬機器彙編

  第4句"mov [rbp-10], rsp",記憶體地址 [rbp-10]在第2句"mov rbp, rsp"賦值,所以第4句轉化為

"mov [rsp-10], rsp",再來判斷rsp的值,rsp在第3句"sub rsp, 10h",所以第4句轉化為"mov [rsp-10], rsp-10",

此時可以定義變數v1,v1地址為[rsp-10],生成虛擬機器彙編語句v1 = &v1。

  第8句"jz short loc_400483"也是我們重點關注的語句,因為這是一條條件跳轉,程式的執行流可能因為

這條語句不再是順序執行。第8句的跳轉判斷cpu flag暫存器標誌位z位是否為0,所以搜尋最近一條影響標誌位

的語句,這條語句就是第7句"cmp eax, 0",向上搜尋修改eax的語句,第6句"movsxd  rax, dword ptr [rax]",

這是一條讀記憶體操作,繼續向上尋找誰修改了rax,找到第5句"lea rax, [rbp-4]",則生成變數v2,v2地址為

[rbp-4],並生成if語句,if語句條件判斷為v2。

  繼續向下分析彙編語句,接下來的彙編語句是if語句的then部分,遇到第13句"mov [rdi], eax",這是一條

寫記憶體操作,分析記憶體地址和值。記憶體地址在rdi中,第12句"pop rdi",繼續搜尋最近的壓棧操作,遇到第10句

"push rax",繼續分析rax的值,第9句"lea rax, a",則rdi為a的地址。再來追尋eax,第11句"mov rax, 4",

則生成虛擬機器彙編語句a = 4。第14句jmp生成一條goto標籤,then部分直到組合語言地址小於地址loc_400483

的最大值為止。

  再來分析第8句"jz short loc_400483",跳轉到loc_400483,接下來的語句是if的else部分,分析看到第22

句"mov     [rdi], eax",這是一條寫記憶體操作,分析記憶體地址和值。記憶體地址在rdi中,第21句"pop     rdi",

繼續搜尋最近的壓棧操作,第19句"push rax",繼續分析rax的值,第18句"lea rax, b",則rdi為b的地址。再來

追尋eax,第20句"mov rax, 5",則生成虛擬機器彙編語句b = 5。此時判斷彙編指令的地址是否大於第14句生成的

goto標籤,如果大於或等於則結束else部分。

 

 

三. 虛擬機器彙編到c語言

 

  1. 虛擬機器組合語言

  code段如下:

                 |OP_GET_LOCAL|

                 |1|

                 |OP_JUMP_IF_FALSE|

                 |0xXX|

                 |0xXX|  

                 |OP_POP|

                 |OP_CONSTANT|

                 |0|

                 |OP_SET_GLOBAL|

                 |2|

                 |OP_JUMP|

                 |0xYY|

         |0xYY|

     0xXXXX:|OP_POP|

         |OP_CONSTANT|

         |1|

         |OP_SET_GLOBAL|

      |3|

  0xYYYY:|其他指令|

 

  常量段為:

  |4|

  |5|

  |a|

  |b|

 

  Local段為:

  |v1|

  |v2|

  上面的語句執行過程為,OP_GET_LOCAL 1將變數v2 push到棧中,OP_JUMP_IF_FALSE判斷棧頂v2

是否為真,如果為真則不跳轉,執行then分支,反之跳轉到0xXXXX處執行else分支。then分支中先將棧頂v2

彈出,然後將常量4壓入棧,然後將4寫入變數a。然後跳轉到0xYYYY處執行後面的語句。else分支中先將

棧頂v2彈出,然後將常量5壓入棧,然後將5寫入變數b。

 

 

  2. 反編譯為c語言

  遇到OP_JUMP_IF_FALSE,生成if語句,if的條件為棧頂元素,追蹤操作棧頂的操作,為

OP_GET_LOCAL,則if語句的條件為v2。

  順序分析到OP_SET_GLOBAL 2,此條語句寫公共變數a,值為OP_CONSTANT 0壓入的4,生成語句

a = 4。OP_JUMP 生成一條標籤,if語句的then部分結束,因為此時彙編地址已經到達0xXXXX了。

  再來分析從0xXXXX開始處的指令,OP_SET_GLOBAL  3,此條語句寫公共變數b,值為

OP_CONSTANT 1壓入的5,生成語句b = 5。此時結束else分支,因為彙編地址已經到達OP_JUMP

生成的標籤。

 

  

相關文章