逆向知识第八讲,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,速度优先)

汇编代码:

逆向知识第八讲,if语句在汇编中表达的方式

可以看到我们熟悉的代码了.也就是昨天的三目运算.

总共三行汇编代码.

还原套路一样,还是 代入大于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 的第二种情况(减少分支)

高级代码:

#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;
}

对应汇编代码:

逆向知识第八讲,if语句在汇编中表达的方式

这个主要涉及找上下界问题

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(也就是体积优先了)

这个时候就会出现代码外提.

高级代码:

#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

逆向知识第八讲,if语句在汇编中表达的方式

protect -> setting即可.

对应汇编代码:

逆向知识第八讲,if语句在汇编中表达的方式

首先,找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的还原

这个其实很简单了.如果是多分支,则寻找上界下界即可.

因为编译器做的东西很多了.

高级代码:

#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语句在汇编中表达的方式

看到这种,直接判断为 if else if else if else这种语句,然后寻找上下界即可.

 

转载于:

作者:IBinary
出处:http://www.cnblogs.com/iBinary/

 

上一篇:逆向知识第七讲,三目运算符在汇编中的表现形式,以及编译器优化方式


下一篇:用while求n的阶乘