逆向分析篇四:if语句
一、前言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语句的流程图和执行伪汇编代码。
在dbg x32中if语句的执行伪汇编代码。
if的比较条件为index == 0,如果成立,即为真值,则进入if语句块内执行语句。转换后的汇编代码使用的条件
指令JNE判断结果为不等于0则跳转,因为按照if语句的规定,满足if判定的表达式才能执行if的语句块,而汇编
语言的条件跳转却是满足某条件则跳转。
//将ebp栈底指针入栈,以便程序执行结束可以进行恢复
00C91850push ebp
//将栈底变成新的栈顶
00C91851mov ebp,esp
//开辟一块0CCH大小的堆栈空间
00C91853sub esp,0CCh
//ebx入栈
00C91859push ebx
//esi(源地址)入栈
00C9185Apush esi
//edi(目的地址)入栈
00C9185Bpush edi
//将ebp-0Ch地址处的值放入到edi中
00C9185Clea edi,
//ecx =3,为循环次数3次
00C9185Fmov ecx,3
将开辟内存空间全部初始化成0CCCCCCCCh。
00C91864mov eax,0CCCCCCCCh
//上边代码都是在做前期初始化操作,开辟新的内存空间和堆栈,把之前栈顶与栈底放入新堆栈中,并将内存空间初始化成C
00C91869rep stos dword ptr es:
00C9186Bmov ecx,0C9C00Eh
00C91870call 00C9131B
//上边三行代码其实就是int main()
// = 0
00C91875mov dword ptr ,0
//使用cmp指令,将ebp-8地址处的4字节与0相减,根据结果改变标志位
00C9187Ccmp dword ptr ,0
//jne为不相则跳转
00C91880jne 00C9188F
//0C97B30h = (index = 0)
00C91882push 0C97B30h
//调用printf函数,把0C97B30h当参数传进去
00C91887call 00C910CD
//进行平栈,堆栈平衡操作
00C9188Cadd esp,4
//esi = esp
00C9188Fmov esi,esp
//0C97B40h = pause
00C91891push 0C97B40h
//调用system函数,把pause当参数传进去
00C91896call dword ptr ds:
//进行平栈,堆栈平衡操作
00C9189Cadd esp,4
//其实下边三行做的操作是return 0,函数返回
00C9189Fcmp esi,esp
00C918A1call 00C9123F
00C918A6xor eax,eax
//下边代码是在做恢复操作,把一开始开辟的堆栈和放入到堆栈地址进行恢复操作
00C918A8pop edi
00C918A9pop esi
00C918AApop ebx
00C918ABadd esp,0CCh
00C918B1cmp ebp,esp
00C918B3call 00C9123F
00C918B8mov esp,ebp
00C918BApop ebp
00C918BBret
Release x32
Release进行判断,if判断条件为true,直接省略掉了index赋值与判断,直接调用if语句里面的打印语句。
//5E2108h = (index = 0)
005E1040push 5E2108h
//调用printf函数,把0C97B30h当参数传进去
005E1045call 005E1010
//0C97B40h = pause
005E104Apush 5E2114h
//调用system函数,把pause当参数传进去
005E104Fcall dword ptr ds:
//进行平栈,堆栈平衡操作
005E1055add esp,8
//eax = 0
005E1058xor eax,eax
//把值返回
005E105Aret
Debug x64
在64位程序中,默认使用的是 fastcall, fastcall用的不是堆栈传参而是使用了寄存器传参。
// = 0
00007FF7DD69187Bmov dword ptr ,0
//使用cmp指令,将rbp+4地址处的4字节与0相减,根据结果改变标志位
00007FF7DD691882cmp dword ptr ,0
//jne为不相则跳转
00007FF7DD691886jne 00007FF7DD691894
//将00007FF7DD699C28h地址的值放入到rcx寄存器里
00007FF7DD691888lea rcx,
//调用printf函数,把rcx当参数传进去
00007FF7DD69188Fcall 00007FF7DD691190
//将00007FF7DD699C38h地址的值放入到rcx寄存器里
00007FF7DD691894lea rcx,
//调用system函数,把pause当参数传进去
00007FF7DD69189Bcall qword ptr
//eax = 0
00007FF7DD6918A1xor eax,eax
//将rbp+00000000000000E8h地址里的值放入到rsp寄存器里
00007FF7DD6918A3lea rsp,
00007FF7DD6918AApop rdi
00007FF7DD6918ABpop rbp
00007FF7DD6918ACret
Release x64
//将00007FF6EE632260h地址里的值放入到rcx寄存器里
00007FF6EE631074lea rcx,
//调用printf函数,把rcx当参数传进去
00007FF6EE63107Bcall 00007FF6EE631010
//将00007FF6EE63226Ch地址里的值放入到rcx寄存器里
00007FF6EE631080lea rcx,
//调用system函数,把pause当参数传进去
00007FF6EE631087call qword ptr
//eax = 0
00007FF6EE63108Dxor eax,eax
//进行平栈
00007FF6EE63108Fadd rsp,28h
00007FF6EE631093ret
先执行各类影响标志位的指令
其后是各种条件跳转指令
jxx XXXX
如果遇到以上指令序列,可高度怀疑它是一个由if语句组成的单分支结构,根据比较信息与条件跳转指令找到
其跳转相反的逻辑,即可恢复分支结构原型。由于循环结构中也会出现类似的代码,因此在分析过程中还需
要结合上下文分析。
页:
[1]