C调用简单函数的反汇编分析记录

11 篇文章 0 订阅

       前两天摆弄了一下windows下的反汇编工具OllyDbg, 用起来不错,于是自己写了一个C的小程序反汇编试试。程序很简单,定义了两个自定义函数,add () 和 sub (),并传入参数。因为传入参数都只是两个,而且都是int型,总共8字节,所以这样的函数不需要用传入参数块首地址的方式传参,一般这样的函数调用都是简单函数。

此次尝试使用的OllyDbg版本为2.01 ,使用的C编译器为gcc 3.4.0 (mingw special), 运行平台为win 7 x64 sp1。

C源代码:

#include <stdio.h>

int add (int, int);
int sub (int, int);


int add (int _x, int _y) {
	int tmp = _x + _y;
	return tmp;
}

int sub (int _x, int _y) {
	int tmp = _x - _y;
	return tmp;
}

int
 main (int argc, char** argv) {
	int x = 20;
	int y = 19;
	int res_add, res_sub;
	
	res_add = add (x, y);
	res_sub = sub (x, y);
	 
	printf ("add = %d, sub = %d\n", res_add, res_sub);
	return 0;
 }
C语言编译出的可执行文件,其函数的调用多半是遵循下面的步骤: (我的电脑用的32位机)

1) push ebp  ; 将当前上下文中的ebp值压入堆栈,

2) mov ebp, esp ;  将当前的esp 值存入ebp, 之后ebp的值基本上不变,就用ebp 结合esi 得到压入栈中的函数参数,

3) 参数压栈,此时会改变esp的值,但之前上下文中的值已经压入栈中,还可以还原回来。

4) call fxn  ; 调用函数, fxn用函数起始地址代替(偏移地址)

由于这次写的C程序使用了printf (),所以可以以此作为目标,查看到底在调用哪个函数后(单步执行)控制台输出了数据。

使用OllyDbg反汇编:


这里只截取了编译出的代码部分;可以看到,在反汇编后,OllyDbg会自动将cs:si指向程序起始运行位置。但目前我还说不清楚这个位置到底是在什么的起始位置,是初始化结束后,还是main 的位置?希望高人指点。

此后一直按F8 (单步执行)运行到地址为0x00401253的位置,看到代码为  call 004011e0,即是调用函数,当单步执行后,发现控制台马上输出了字符串,说明调用两个函数和printf 的就是在这个 地址为0x004011e0的函数中。重新载入exe , 步入执行这条指令。


发现函数中又调用了很多函数,有的地址有标注,有的没有,但可以通过查看它们所在的偏移地址知道到底是属于哪个模块(dll 或者 exe等 PE文件)。通过视图-> 内存映射得到所有的内存块描述:

由此可以查看函数属于哪个地址段,在kernel32.dll还是在 msvcrt.dll等。这样就好猜测函数到底是不是用户定义函数了。

接着上面说,进入调用的0x004011e0函数后,得到刚才的代码,出现大量的call函数(其中很多地址都是0x0040... 开头的可能就是引入头文件时定义的一些函数)。再使用F8 单步执行,查看什么时候控制台出现字符串输出。当运行到0x00401228处的代码后,输出了,由此可以再次进入这个函数试试。重新载入,到0x00401228 处的代码(call 004012fa),这回看到了比较熟悉的注释:printf (),在地址0x00401371处, call <jmp.&msvcrt.printf>

在调用之前还分析出了printf 格式字符串中的两个%d,都是用mov 指令从栈中转移到指定位置的(为调用printf 准备的参数栈)。我们都知道C的普通函数返回值(若有的话)都存储在eax中。这里是从eax 传入到printf 参数栈中合适的位置。说明调用的函数就是前面的call 004012e4和 call 00401200,看来这两个函数找到了!

最后分析一下函数的调用过程,只取其中一个函数0x004012d0分析,这个函数应该就是我们定义的add () 函数。


在调用之前,会有参数压栈过程,但是这里常规的push ebp 和 mov ebp,esp 却在call 00401738和 call 00401490之前,而这两个函数做什么用,目前我不清楚。C stdcall 都是参数从左到右压栈,于是可以看到0x00401324 和0x0040132B处的代码是先压入14, 再压入13,又通过eax将数据转移到esp适当的位置,等待函数调用。进入函数:

如此这里出现了一直寻找的push ebp 和 mov ebp, esp ,之后就可以通过ebp访问传入的参数了。当然,调用结束后,还要恢复调用前上下文的esp和ebp,这里就交给了leave和retn处理。32位机中,leave 同

mov esp, ebp

pop ebp


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值