电脑疯子技术论坛|电脑极客社区

微信扫一扫 分享朋友圈

已有 511 人浏览分享

逆向分析篇四:if语句

[复制链接]
511 0
一、前言

if语句是属于流程控制语句一种,流程控制语句是进行逆向分析和还原高级代码的基础对于想从事
逆向分析工作流程控制语句是很重要的。

二、if语句分析

if语句是分支结构的重要组成部分。if语句的功能是先运算条件进行比较,然后根据比较结果选择对应的语句块来执行
if 语句只能判断两种情况∶"0"为假值,"非0"为真值。如果为真值,则进入语句块内执行语句;如果为假值,则跳过
if语句块,继续运行程序的其他语句。要注意的是,if语句转换的条件跳转指令与if语句的判断结果是相反的。

源代码:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int index = 0;
    if (index==0)
    {
        printf("index = 0\n");
    }
    system("pause");
    return 0;
}

Debug x86

在IDA中if语句的流程图和执行伪汇编代码。

QQ截图20221017104450.png

在dbg x32中if语句的执行伪汇编代码。

QQ截图20221017104531.png

if的比较条件为index == 0,如果成立,即为真值,则进入if语句块内执行语句。转换后的汇编代码使用的条件
指令JNE判断结果为不等于0则跳转,因为按照if语句的规定,满足if判定的表达式才能执行if的语句块,而汇编
语言的条件跳转却是满足某条件则跳转。

//将ebp栈底指针入栈,以便程序执行结束可以进行恢复
00C91850  push        ebp
//将栈底变成新的栈顶
00C91851  mov         ebp,esp
//开辟一块0CCH大小的堆栈空间
00C91853  sub         esp,0CCh
//ebx入栈
00C91859  push        ebx
//esi(源地址)入栈
00C9185A  push        esi
//edi(目的地址)入栈
00C9185B  push        edi
//将ebp-0Ch地址处的值放入到edi中
00C9185C  lea         edi,[ebp-0Ch]
//ecx =3,为循环次数3次
00C9185F  mov         ecx,3
将开辟内存空间全部初始化成0CCCCCCCCh。
00C91864  mov         eax,0CCCCCCCCh
//上边代码都是在做前期初始化操作,开辟新的内存空间和堆栈,把之前栈顶与栈底放入新堆栈中,并将内存空间初始化成C
00C91869  rep stos    dword ptr es:[edi]  
00C9186B  mov         ecx,0C9C00Eh  
00C91870  call        00C9131B
//上边三行代码其实就是int main()
// [ebp-8] = 0
00C91875  mov         dword ptr [ebp-8],0
//使用cmp指令,将ebp-8地址处的4字节与0相减,根据结果改变标志位
00C9187C  cmp         dword ptr [ebp-8],0
//jne为不相则跳转
00C91880  jne         00C9188F
//0C97B30h = (index = 0)
00C91882  push        0C97B30h
//调用printf函数,把0C97B30h当参数传进去
00C91887  call        00C910CD
//进行平栈,堆栈平衡操作
00C9188C  add         esp,4
//esi = esp
00C9188F  mov         esi,esp
//0C97B40h = pause
00C91891  push        0C97B40h
//调用system函数,把pause当参数传进去
00C91896  call        dword ptr ds:[00C9B170h]
//进行平栈,堆栈平衡操作
00C9189C  add         esp,4
//其实下边三行做的操作是return 0,函数返回
00C9189F  cmp         esi,esp  
00C918A1  call        00C9123F  
00C918A6  xor         eax,eax
   
//下边代码是在做恢复操作,把一开始开辟的堆栈和放入到堆栈地址进行恢复操作
00C918A8  pop         edi  
00C918A9  pop         esi  
00C918AA  pop         ebx  
00C918AB  add         esp,0CCh  
00C918B1  cmp         ebp,esp  
00C918B3  call        00C9123F  
00C918B8  mov         esp,ebp  
00C918BA  pop         ebp  
00C918BB  ret

Release x32

66698.png

66697.png

Release进行判断,if判断条件为true,直接省略掉了index赋值与判断,直接调用if语句里面的打印语句。

//5E2108h = (index = 0)
005E1040  push        5E2108h
//调用printf函数,把0C97B30h当参数传进去
005E1045  call        005E1010
//0C97B40h = pause
005E104A  push        5E2114h
//调用system函数,把pause当参数传进去
005E104F  call        dword ptr ds:[005E2078h]
//进行平栈,堆栈平衡操作
005E1055  add         esp,8
//eax = 0
005E1058  xor         eax,eax
//把值返回
005E105A  ret

Debug x64

66696.png

66695.png

在64位程序中,默认使用的是 fastcall, fastcall用的不是堆栈传参而是使用了寄存器传参。

// [rbp-4] = 0
00007FF7DD69187B  mov         dword ptr [rbp+4],0
//使用cmp指令,将rbp+4地址处的4字节与0相减,根据结果改变标志位
00007FF7DD691882  cmp         dword ptr [rbp+4],0
//jne为不相则跳转
00007FF7DD691886  jne         00007FF7DD691894
//将00007FF7DD699C28h地址的值放入到rcx寄存器里
00007FF7DD691888  lea         rcx,[00007FF7DD699C28h]
//调用printf函数,把rcx当参数传进去
00007FF7DD69188F  call        00007FF7DD691190
//将00007FF7DD699C38h地址的值放入到rcx寄存器里
00007FF7DD691894  lea         rcx,[00007FF7DD699C38h]
//调用system函数,把pause当参数传进去
00007FF7DD69189B  call        qword ptr [00007FF7DD6A0300h]
//eax = 0
00007FF7DD6918A1  xor         eax,eax
//将rbp+00000000000000E8h地址里的值放入到rsp寄存器里
00007FF7DD6918A3  lea         rsp,[rbp+00000000000000E8h]
00007FF7DD6918AA  pop         rdi  
00007FF7DD6918AB  pop         rbp  
00007FF7DD6918AC  ret  

Release x64

66694.png

66628.png

//将00007FF6EE632260h地址里的值放入到rcx寄存器里
00007FF6EE631074  lea         rcx,[00007FF6EE632260h]
//调用printf函数,把rcx当参数传进去
00007FF6EE63107B  call        00007FF6EE631010
//将00007FF6EE63226Ch地址里的值放入到rcx寄存器里
00007FF6EE631080  lea         rcx,[00007FF6EE63226Ch]
//调用system函数,把pause当参数传进去
00007FF6EE631087  call        qword ptr [00007FF6EE6320F8h]
//eax = 0
00007FF6EE63108D  xor         eax,eax
//进行平栈
00007FF6EE63108F  add         rsp,28h  
00007FF6EE631093  ret

先执行各类影响标志位的指令
其后是各种条件跳转指令
jxx   XXXX   

如果遇到以上指令序列,可高度怀疑它是一个由if语句组成的单分支结构,根据比较信息与条件跳转指令找到
其跳转相反的逻辑,即可恢复分支结构原型。由于循环结构中也会出现类似的代码,因此在分析过程中还需
要结合上下文分析。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

关注

0

粉丝

9021

主题
精彩推荐
热门资讯
网友晒图
图文推荐

Powered by Pcgho! X3.4

© 2008-2022 Pcgho Inc.