「C语言最简main函数的反汇编代码解析」

时间:2022-07-12 05:19:12 阅读: 最新文章 文档下载
说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。
目前我们写的最简单的Main函数如下: 代码:

#include "stdafx.h"

int _man(in argc, _TCHAR* arv[]

etur 0

利用VS编译器将运行时程序反汇编,结果如下: 代码:

int _tmai(int arc, _TCHAR argv[]) {

010C13A0 push ebp

010131 mv bp,esp 10C13A3 sb esp,0Ch 010C3A push ebx 01013AA push esi 010C13AB push edi

01C13AC la di,[ep-0C0h] 1C13B ov ecx,30h

1C1B7 mo eax,0CCCCCCCh

010C3BC rep sto wod ptr es:[edi eturn 0;

010C1BE xr ex,ex }

00C13C po ed 01013C1 pop esi 01C13C2 pop ebx

10C13C3 mov sp,ebp 0013C5 pp ebp 00C13C6 ret

看起来汇编很头疼吧,那么让我们来茅塞顿开吧。首先了解一下以前几个未知半懂的汇编指令的含义: 代码:

push ebp

mov ebp,esp

puh:把一个32位操作数压入栈中,这个操作导致esp被减4 ebp被用来保存这个函数执行前的ep的值,执行完毕后用ebp恢复esp。同时,调用此函数的上层函数也用ebp做同样的事情。所以先把ebp压入堆栈,返回之前弹出,避免ebp被我们改动。 代码:

o eax,eax rt


xr a,eax常用来代替mov eax,0。清零操作。在windows中,函数返回值都是放在eax中然后返回,外部从eax中得到返回值。这就代表retr 0操作。 代码:

lea edi,[ebp0C0h]

lea取得第二个参数代表的地址放入第一个参数代表的寄存器中。 代码:

mov ecx,30

o ex0CCCCCCh rep sto dword ptr es:[ei]

stos是串存储指令,它的功能是将eax中的数据放入edi所指的地址中,同时edi会增加4个字节。Rep使指令重复执行ecx中填写的次数。

由于CPU的寄存器有限,而且操作寄存器会影响标志值,push作用是压栈,pop是退栈。即保存寄存器标志的值和寄存器本身的值,以便在函数调用完毕后恢复原有的标志值。这也是为什么我们见到在调用某个函数或者运行一个程序时,入口总是push一堆寄存器的东东,也就是这个原因。通过上面的基础知识,我们来看看man函数的反汇编解释: 代码:

int _tanit argc, _TCHAR* agv[]) {

01C13A0 puh ebp

;保存ebp,返回之前弹出,避免ebp被我们改动。push操作使esp减小,esp不变

010C1A1 mv ebp,esp

; ebp被用来保存这个函数执行前的esp的值,执行完毕后用ebp恢复esp ;原ebp值已经被压栈(位于栈顶),而新的ebp又恰恰指向栈顶

;此时ep寄存器就已经处于一个非常重要的地位,该寄存器中存储着栈中的一个地址(原ebp入栈后的栈顶)

;从该地址为基准,向上(栈底方向)能获取返回地址、参数值(假如main有参数,“获取参数值”会比较容易理解

;向下(栈顶方向)能获取函数局部变量值,而该地址处又存储着上一层函数调用时的ebp

01C13A3 sub esp,0C0h

;把esp往上移动一个范围,等于在栈中开辟一片空间存储main函数的局部变量

;由于冯诺依曼机是小端模式,所以sub操作可以理解为将esp栈顶减去,实际上是为栈增加空间

010C13A9 puh bx 01C13A push es 00C13AB push edi

;保存三个寄存器的值,main结束恢复,原来的值被破坏有可能引起系统崩溃 010C13AC la edi,[bp-00h] ;把ebp-00h加载到edi中,目的是保存局部变量的区域 010C13B2 ov ecx,30h


00C1B7 mov ea,0CCCCCCC 01013B ep stos dword tr es:edi

;从ebp-c0h开始的局部变量空间区域初始化成全部0CCCCCCh(也就it 3中断指令的机器码)

;局部变量不可能被执行,执行了就会出错。这样发生意外时执行堆栈里面的内容会引发调试中断提示开发者 retr 0;

010C13BE xo ax,eax

; 返回值将放在eax返回(这就是很多软件给秒杀爆破的原因,因为eax返回值是可以改的) }

010C3C0 pop d 010C13C pop ei 010C13C op ebx

恢复原来寄存器的值,怎么“吃”进去,怎么“吐”出来 01013C3 mv espebp ;恢复ESP栈顶指针

00C13C5 op bp

;恢复ebp,也就是恢复调用man函数之前各个寄存器的状态 010C13C6 ret

;将返回地址存入eip,退出主函数

通过以上分析,大家应该对main函数的反汇编解析有一定的概念了吧。返回去看文章开头的反汇编代码,心里肯定比刚开始看的感觉舒服多了。在实战中,我们OD的汇编代码基本也就是这个套路,当然细节还得另外分析。有什么错误,敬请大伙指正,共同学习。 参考资料:


本文来源:https://www.wddqw.com/doc/8deddac2356baf1ffc4ffe4733687e21ae45ff4a.html