首页
社区
课程
招聘
[旧帖] 求一段c++程序反汇编代码的详细解释 0.00雪花
发表于: 2012-5-8 09:07 7855

[旧帖] 求一段c++程序反汇编代码的详细解释 0.00雪花

2012-5-8 09:07
7855
int add(int x,int y)
{
	return x+y;
}


用VC6反汇编出来的代码:

2:    int add(int x,int y)
3:    {
00401030 55                   push        ebp
00401031 8B EC                mov         ebp,esp
00401033 83 EC 40             sub         esp,40h
00401036 53                   push        ebx
00401037 56                   push        esi
00401038 57                   push        edi
00401039 8D 7D C0             lea         edi,[ebp-40h]
0040103C B9 10 00 00 00       mov         ecx,10h
00401041 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401046 F3 AB                rep stos    dword ptr [edi]
4:        return x+y;
00401048 8B 45 08             mov         eax,dword ptr [ebp+8]
0040104B 03 45 0C             add         eax,dword ptr [ebp+0Ch]
5:    }
0040104E 5F                   pop         edi
0040104F 5E                   pop         esi
00401050 5B                   pop         ebx
00401051 8B E5                mov         esp,ebp
00401053 5D                   pop         ebp
00401054 C3                   ret


求解释
00401048 8B 45 08             mov         eax,dword ptr [ebp+8]
0040104B 03 45 0C             add         eax,dword ptr [ebp+0Ch]


这两句之外的语句,最好能给出函数调用之前,调用时的大体图。

要详细的。别只说“初始化,保护现场”之类的。

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
支持
分享
最新回复 (14)
雪    币: 2676
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
2:    int add(int x,int y)
3:    {
00401030 55                   push        ebp        ;保护ebp
00401031 8B EC                mov         ebp,esp      ;创建栈帧
00401033 83 EC 40             sub         esp,40h    ;分配局部变量空间,vc在debug模式会自动多分配0x40空间,防止意外栈破坏
00401036 53                   push        ebx    ;保护寄存器
00401037 56                   push        esi    ;保护寄存器
00401038 57                   push        edi    ;保护寄存器
00401039 8D 7D C0             lea         edi,[ebp-40h]    ;局部变量起始地址
0040103C B9 10 00 00 00       mov         ecx,10h        ;局部变量字节数/4
00401041 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401046 F3 AB                rep stos    dword ptr [edi]    ;使用0xCC填充局部变量,用于判断栈破坏,0xCC对应int 3指令,若不小心跳到栈上执行将触发调试中断
4:        return x+y;
00401048 8B 45 08             mov         eax,dword ptr [ebp+8]
0040104B 03 45 0C             add         eax,dword ptr [ebp+0Ch]
5:    }
0040104E 5F                   pop         edi    ;下面就是恢复寄存器,销毁栈帧了
0040104F 5E                   pop         esi
00401050 5B                   pop         ebx
00401051 8B E5                mov         esp,ebp
00401053 5D                   pop         ebp
00401054 C3                   ret
2012-5-8 09:22
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
dword ptr [ebp+8] => x,
dword ptr [ebp+0Ch] => y
之外的语句是调试版填充CC指令(int 3)的,没什么大用。
2012-5-8 09:26
0
雪    币: 93
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
DrX
4
vc在debug模式会自动多分配0x40空间。
原来如此。
2012-5-8 09:28
0
雪    币: 30
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
调用一个函数时,会先保存当前代码所在函数ebp,esp,然后进入子函数,此时esp ebp指针指向函数栈,(int *)[esp+8]就是第一/第二个参数(不同的调用方式压参数入栈的顺序不同)
2012-5-18 02:11
0
雪    币: 527
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
威武,又学习了 填充cc的用处原来是干这个啊
2012-5-18 10:06
0
雪    币: 692
活跃值: (40)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
7
这个我感觉,不是说多分配40H的空间,这应该是编译器给函数开辟的栈,存放函数的局部变量,从ebp-4表示第一个局部变量就可以看出来。各位觉得呢?
2012-5-18 12:56
0
雪    币: 5
活跃值: (421)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
该函数又没有任何局部变量,为局部变量分配空间的说法说不过去吧。。。
2楼的说法有道理,就是不明白什么情况下会触发到这种保护?
2012-6-5 09:59
0
雪    币: 166
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
。。。。。。。。
2012-6-5 10:06
0
雪    币: 293
活跃值: (287)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
没碰到过0xcc被执行的,只是会碰到oxCCCCCCCC内存不能为read write的错误,溢出一般会直接把0xcc覆盖掉,一般不会把返回地址填成上面的0xcc地址吧,这个可能性非常小
2012-6-5 10:38
0
雪    币: 692
活跃值: (40)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
11
在DEBUG下,即使函数没有任何的局部变量,编译器也会为函数开辟栈和为局部变量分配内存。C语言的局部变量的作用域就是这么实现的么
2012-6-5 10:58
0
雪    币: 293
活跃值: (287)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
哎呦,这样的好处就是可以发现死循环了啦,如果像如下的递归调用
void  test()
{
   test();
}
debug下面就可以发现程序提前退出了,在调用test之后的代码一句都没有运行。
而release运行就只有jmp  $ 构成了一个死循环,调试的时候还以为机器卡主了~
2012-6-5 14:50
0
雪    币: 5
活跃值: (41)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
push        ebp
mov         ebp,esp
sub         esp,40h

这里的具体含义应该是先保存原来的堆栈栈底地址,然后再把当前的ESP做为新的栈底,再把ESP的指针向上移动64个字节做为新的栈顶,在这里需要注意看一下,这里的40H是十六进制的40

push        ebx
push        esi
push        edi

在这里先保存一下原来的三个寄存器 EBX,ESI,EDI
在这里也顺便讲一下,因为在下面马上要执行rep stos    dword ptr [edi] 指令
ESI,EDI是指针寄存器,代表是源指针地址和目标地址,而EBX是做为临时内存寻址方式需要临时存放地址用的,这三个寄存器在下面的指令中都需要用得上,所以才保存这三个寄存器,(由此可见,每个寄存器都有相应的具体功能,CPU是不会随便使用无关的寄存器)。

lea         edi,[ebp-40h]
mov         ecx,10h
mov         eax,0CCCCCCCCh
rep stos    dword ptr [edi]

这几句是把从栈顶开始,以CX做为计数器,计数器为16次,每次填充大小为4个字节,向下填充64个字节的CC断点,也就是64个INT3断点,也可以看做是把这个栈的内存地址初始化。

eax,dword ptr [ebp+8]
add         eax,dword ptr [ebp+0Ch]

根据C调用约定 对二个参数进行相加
在这里要说明一下
根据函数尾部的 ret  可以判断出此函数为
_cdecl调用约定

如果是retn 8 则说明是_stdcall调用约定。

这里赋值的EAX也正是调用约定做为返回值的保存寄存器。

pop         edi
pop         esi
pop         ebx

根据上面的,按顺序还原EDI,ESI,EBX三个寄存器,保持寄存器数据完整性。

mov         esp,ebp
pop         ebp

重新回来原来的栈底,在这个函数外面应该还有一个add esp,8 的代码来保持堆栈平衡。

根据上面的汇编根本上可以判断此程序为C代码,并非MFC代码。因为少了有异常处理相关的处理。

以上讲的为小弟个人的理解,有不对的地方,还请大家多指出一下。

在这里还有一点问题就是为什么要开辟64个字节的内存块,而不是32或是128 这个64有什么具体含义呢,还请大家也多讲讲看。
2012-7-3 14:32
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
00401039 8D 7D C0             lea         edi,[ebp-40h]
0040103C B9 10 00 00 00       mov         ecx,10h
00401041 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401046 F3 AB                rep stos    dword ptr [edi]
说明是编译类型是Debug 版的, 没有做优化。 这些CCCCCC,是用来防止缓冲区溢出覆盖返回地址的, 这个也是某些情况下程序为什么编译成Debug 版可以工作, release版不能工作的原因。
2012-7-3 14:58
0
雪    币: 5
活跃值: (41)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
为什么是64个字节呢
2012-7-3 15:22
0
游客
登录 | 注册 方可回帖
返回
//