C语言04_IF语句逆向分析上

全局变量和局部变量

全局变量在exe运行的时候就已经存在 ,其他函数都可以修改

  • 生命周期:从程序启动 → 程序结束,一直存在。
  • 存储位置:存放在全局数据区,不是栈。
  • 默认初始值:如果不赋值,默认等于 0
  • 局部变量
  • 只有当函数调用时才会分配空间,且一定要有初值.
  • 局部变量的作用范围仅限于当前函数自己,其他函数无法使用
  • 当函数执行完毕后,局部变量将变成垃圾数据,可以随时被其他数据所覆盖.
  • 局部变量的反汇编识别:

[ebp-0x4]

[ebp-0x8]

[ebp-0xC]

全局变量的反汇编识别:
MOV 寄存器,byte/word/dword ptr ds:[0x12345678]
通过寄存器的宽度,或者byte/word/dword 来判断全局变量的宽度

函数
如果看不到参数的具体情况 需要跟进到函数内部查看

如何判断函数有几个参数,已经分别是什么:


一般情况:

步骤一:观察调用处的代码

push 3
push 2
push 1
call 0040100f

步骤二:找到平衡堆栈的代码继续论证

call 0040100f
add esp,0Ch

或者函数内部

ret 4/8/0xC/0x10


最后,两者一综合,函数的参数个数基本确定.

也就是push和平栈对的上就行

还有一种特殊情况

上面的分析存在的问题:

1、参数传递未必都是通过堆栈,还可能通过使用寄存器.

比如:

push ebx
push eax
mov ecx,dword ptr ds:[esi]
mov edx,dword ptr ds:[edi]
push 45
push 33
call 函数地址

2、函数调用处的代码无法查看.

00401050 push ebp 观察步骤:
00401051 mov ebp,esp
00401053 sub esp,48h 1、不考虑ebp、esp
00401056 push ebx
00401057 push esi 2、只找给别人赋值的寄存器
00401058 push edi eax/ecx/edx/ebx/esi/edi
00401059 push ecx
0040105A lea edi,[ebp-48h] 3、找到以后追查其来源,如果,该寄存器中的值
0040105D mov ecx,12h 不是在函数内存赋值的,那一定是传进来的参数.
00401062 mov eax,0CCCCCCCCh
00401067 rep stos dword ptr [edi]
00401069 pop ecx
0040106A mov dword ptr [ebp-8],edx
0040106D mov dword ptr [ebp-4],ecx
00401070 mov eax,dword ptr [ebp-4]
00401073 add eax,dword ptr [ebp-8]
00401076 add eax,dword ptr [ebp+8]
00401079 mov [g_x (00427958)],eax
0040107E pop edi
0040107F pop esi
00401080 pop ebx
00401081 mov esp,ebp
00401083 pop ebp
00401084 ret 4

找到用寄存器赋值的语句 比如 0040106A mov dword ptr [ebp-8],edx 0040106D mov dword ptr [ebp-4],ecx 这俩句指令 前面虽然有ecx的赋值 最开始也有push ecx ,所以这里的ecx想当于临时使用
ecx edx是参数 看结尾是内平栈 2 + 1 = 3 所以有三个参数

海哥总结的公式:公式一:寄存器 + ret 4 = 参数个数

公式二:寄存器 + [ebp+8] +[ebp+0x] = 参数个数

IF语句逆向分析

汇编中的jcc指令跟我们在编译器中写的刚好相反
Pasted image 20260827085557.png
但实际上是一致的 jle(小于等于则跳不执行) 大于就执行 同代码

还原if和jcc

函数调用处代码:

push 5 分析:
push 4 两个参数
call 0040100f
add esp,8
函数内部代码:

00401030 push ebp
00401031 mov ebp,esp
00401033 sub esp,40h
00401036 push ebx
00401037 push esi
00401038 push edi
00401039 lea edi,[ebp-40h]
0040103C mov ecx,10h
00401041 mov eax,0CCCCCCCCh
00401046 rep stos dword ptr [edi]
00401048 mov eax,dword ptr [ebp+8]
0040104B cmp eax,dword ptr [ebp+0Ch]
0040104E jle 00401059
00401050 mov ecx,dword ptr [ebp+8]
00401053 mov dword ptr [004225c4],ecx
00401059 pop edi
0040105A pop esi
0040105B pop ebx
0040105C mov esp,ebp
0040105E pop ebp
0040105F ret
函数内部功能分析:

1、分析参数:
ebp+8 ebp+0xc

2、分析局部变量

没有ebp-的变量

3、分析全局变量
004225c4

4、功能分析
00401048 mov eax,dword ptr [ebp+8]
0040104B cmp eax,dword ptr [ebp+0Ch]
比较参数1和参数2的大小 cmp只影响标志位 如果x>y
那么把参数1赋值给ecx 并写道全局变量004225c4
00401050 mov ecx,dword ptr [ebp+8]
00401053 mov dword ptr [004225c4],ecx
5、返回值分析
没有出现eax赋值的情况

而且也可以知道调用约定是cdcel

练习

调用处代码:

push 5
push 4
call 0040100f
add esp,8

函数内部:

00401030 push ebp
00401031 mov ebp,esp
00401033 sub esp,44h
00401036 push ebx
00401037 push esi
00401038 push edi
00401039 lea edi,[ebp-44h]
0040103C mov ecx,11h
00401041 mov eax,0CCCCCCCCh
00401046 rep stos dword ptr [edi]
00401048 mov eax,[004225c4]
0040104D mov dword ptr [ebp-4],eax
00401050 mov ecx,dword ptr [ebp+8]
00401053 cmp ecx,dword ptr [ebp+0Ch]
00401056 jg 00401064
00401058 mov edx,dword ptr [ebp+0Ch]
0040105B add edx,dword ptr [ebp-4]
0040105E mov dword ptr [004225c4],edx
00401064 pop edi
00401065 pop esi
00401066 pop ebx
00401067 mov esp,ebp
00401069 pop ebp
0040106A ret

函数内部功能分析:

1、分析参数:

ebp+8 ebp+0xc
2、分析局部变量
一个变量

3、分析全局变量
004225c4
4、功能分析
先把全局变量的初始值0 赋值给eax 然后新建一个局部变量eax赋值eax 比较参数1和参数2的大小 如果小于等于则通过edx(参数2) 与局部变量相加 然后把这个值给全局变量
5、返回值分析
eax = 0;

6、代码还原

#include<stdio.h>
#include "stdafx.h"  
int a;
void IfFunction(int x,int y)
{
	int b = a;
	if (x<=y)
	{
		a = y + b;
	}
}
int main(int argc,char* argv[])
{
	IfFunction(2, 3);
	return 0;
}

反汇编窗口

上一篇 C语言03_数据类型_if语句
因特叁

因特叁管理员

动物世界

本月创作热力图

目录