逆向知識第八講,if語句在匯編中表達的方式


           逆向知識第八講,if語句在匯編中表達的方式

一丶if else的最簡單情況還原(無分支情況)

高級代碼:

#include "stdafx.h"

int main(int argc, char* argv[])
{
    unsigned int nNumber = 0;
    scanf("%ud",&nNumber);

    if(argc == 0)
    {
        nNumber = 0;                //第一種情況下無分支
    }
    else
    {
        nNumber = -1;
    }

    return nNumber;
}

 

總共兩種情況,我們看下Release中怎么優化的把(注意,優化方式選擇O2,速度優先)

匯編代碼:

 

可以看到我們熟悉的代碼了.也就是昨天的三目運算.

總共三行匯編代碼.

還原套路一樣,還是 代入大於0 小於0 還有==0,看看最終結果是什么.

鑒於昨天還原過代碼了,這里這屆代入,還原出高級代碼.

argc > 0的情況下
if(argc > 0) eax = -1
argc < 0的情況下
if(argc < 0) eax =-1
argc == 0的情況下
if(argc == 0) eax = 0

綜合三種情況,可以得出具體的條件了.  其中 ><這樣寫是在高級語言中不能這樣寫的,

所以得出的還原代碼為

if(argc == 0) eax =0 
else eax == -1

 

 二丶if else 的第二種情況(減少分支)

高級代碼:

  

// MyCode.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

int main(int argc, char* argv[])
{
    unsigned int nNumber = 0;
    scanf("%ud",&nNumber);

    if(argc == nNumber)
    {
        printf("%d",nNumber / 8);
    }
    else
    {
        printf("%d",nNumber / 5);
    }

    return nNumber;
}

對應匯編代碼:

  

這個主要涉及找上下界問題

1.地址:  1018 101C 分別保存了局部變量的值

2.地址:  1023  比較了argc和局部變量Var4的值

3.地址:  1025  jnz跳轉,因為1023地址的比較會影響標志位 由此判定, argc和var4比較,jnz(不相等)但因為匯編中是反條件,所以是相等的情況下

4.因為jnz是一個地址,所以這個地址是一個下界,那么jnz上面的比較代碼則是上界,在其內部,我們還原為if語句塊(先不用管里面具體干啥)

還原if語句塊

if(argc == var4) printf("%d",var4 / 8);

還原else語句塊

else  printf("%d",var4 / 5);

在下方我們發現了相同的匯編代碼,也就是把retn放到上面去了,這個主要是為了減少分支.

三丶if else 第第三種形式,代碼外提的情況

代碼外提的情況下,主要在優化方式的選擇上,我們知道 o2(優化方式是速度優先)  現在我們改成o1(也就是體積優先了)

這個時候就會出現代碼外提.

高級代碼:

  

// MyCode.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

int main(int argc, char* argv[])
{
    unsigned int nNumber = 0;
    scanf("%ud",&nNumber);

    if(argc == nNumber)
    {
        printf("Hello");
    }
    else 
    {
        printf("World");
    }
    
    return nNumber;
}

切換為o1

protect -> setting即可.

對應匯編代碼:

  

首先,找if else的時候,先確定上下界

地址: 101A位置   尋得了 if的上界

地址: 101E位置  尋得了 if的下界

注意: 中間划掉了兩個指令,這兩個指令是流水線優化,平棧的指令.所以沒有幫助,划掉

地址: 1025位置,其指令跳轉的地址是一個增量,那么則確定是else的下界

地址:  1027位置 尋得了else的上界

其實簡單來說,第一個跳轉位置,跳轉到哪里的一塊區域,是一個if的語句塊而跳轉的位置則是else語句塊的上界,其上面固定一個jmp(注意其地址跳轉是一個增量)那么跳轉的地址是else的下界

重點代碼外提:

我們可以看到 我們的if語句塊中 push了一個 hello,我們的else語句塊中,push了一個 word

那么除了if else 直接調用的printf,這樣也是可以的.因為參數是一樣的.平棧都是相等的.所以可以提到外面來打印輸出.

 四丶多分支if elseif  .... else的還原

這個其實很簡單了.如果是多分支,則尋找上界下界即可.

因為編譯器做的東西很多了.

高級代碼:

  

// Test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

int main(int argc, char* argv[])
{
  unsigned int nVar_4 = 5;
  scanf("%d", &nVar_4);

  // argc == 0 ? 0 : -1
  if (argc == 0)
  {
    printf("argc == 0\r\n");
  }
  else if(argc == 1)
  {
    printf("argc == 1\r\n");
  }
  else if(argc == 2)
  {
    printf("argc == 2\r\n");
  }
  else if(argc == 3)
  {
    printf("argc == 3\r\n");
  }
  else
  {
    printf("else\r\n");
  }
  
  printf("haha\r\n");
  printf("haha\r\n");
  printf("haha\r\n");
  printf("haha\r\n");
  printf("haha\r\n");
    return nVar_4;
}

對應匯編代碼:

  

看到這種,直接判斷為 if else if else if else這種語句,然后尋找上下界即可.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM