HTML自动获取地址,如何动态获取API入口地址

在本文中介绍另一个相对独立的技术:动态获取API 入口地址。文章附带

的源码有两个工程:GetApiAddr 为一个独立的动态获取 API 入口地址的程序;另一个 Virus

为在上一篇文章基础上进行扩展的病毒程序,这个程序把工程目录下的 test.exe 复制一份

为 test_virus.exe并在这个文件上添加动态获取API入口地址的代码,如果程序运行成功,

打开 test_virus.exe后会弹出动态获取的函数MessageBox的内存地址。

为什么要动态获取

在 Windows的安装目录下有许多dll文件,这些dll文件其实就是一些功能模块,说白

了就是里面存放了一些具有一定功能的函数俗称API,应用程序要在windows平台上运行必

须要调用这些函数。Windows在启动的时候会把一些重要的模块(如Kernel32.dll)装入内

存,这些文件装入内存后,里面的每一个功能函数就对应了一个确定的内存地址,应用程序

调用这些函数时只要把用到的参数压入堆栈,call 对应的函数地址就可以了。高级语言编

程时编译器会在生成的可执行文件中保存这些函数的地址信息,一个完整的exe 文件运行时

系统会自动对这些函数地址进行修正,我们不需要关注其底层细节。但作为一个病毒,它的

任务是把自己复制到其它可执行文件中去执行,病毒代码本身并不是一个完整的exe 文件,

但宿主文件并不会自动给病毒代码服务,让病毒代码里的API可以正常调用,所以病毒代码

必须有自己动态获取API地址的能力。

动态获取 API 入口地址也不难,只要调用两个 API 就可以实现:LoadLibrary 和

GetProcAddress,这两个函数都是位于 kernel32.dll 中的,前者为导入 dll 文件,后者通

过函数名在这个dll文件中得到函数地址。但这两个也是系统的API,病毒代码里这两个函

数的地址怎样得到呢?

原理

这个技术的原理是一些前辈们总结的经验,这里简单说一下。Windows在进入应用程序

之前是运行在模块kernel32.dll的某个函数中的(通过对windows的反汇编可以发现)。按

照运行原理,进入应用程序之前要先把返回地址(该地址位于kernel32.dll中)压入栈中,

再转向应用程序去执行,也就是说在刚刚进入应用程序后栈顶是一个位于 kernel32.dll 中

的地址,我们得到这个地址后向可以向系统内存的低地址进行搜索得到kernel32.dll的装

载基址。因为 dll 文件也是标准的 PE 文件,所以得到装载基址后,可以通过搜索

kernel32.dll的导出表得到GetProcAddress的内存地址,然后用这个函数和kernel32.dll

的基址得到LoadLibrary的地址,于是问题解决了。

VC 编译器出现的问题

做底层工作很少不与编译器打交道,上面的原理放在不同的编译器上就要有不同的解决

方法。VC 编译器生成的可执行文件在执行你自己的代码之前已经进行了很多额外的操作,

我们称之为启动函数。如果你试图用[esp]来得到返回地址的话你不会成功,因为执行你的

代码的时候已经经过了多次的压栈操作,栈顶早已不是想要的返回地址了,所以我们必须通

过对可执行文件的反汇编跟踪得到都经过了哪些变换,从而在程序中得到这个地址。

下面对工程目录下的test工程进行反汇编,来介绍一下分析思路。

1. 用OllyDbg载入生成的test.exe文件,指针停在00403510处的启动函数处(这个

地址与大家的可能不一样)。此处你会发现栈顶值为7C817077,这个地址正好位于

kernel32.dll中。开始的几句指令是编译器标志:push ebp   mov ebp , esp

2. 执行完这两句之后 ebp 所指的内存恰是栈顶,后面又执行了很多代码,这些代码执

行完后 esp早已被改了,但是ebp 没有变(按编译器的原则这个值基本不变)。

3. 向下到004035F4处,这里是一个call,正好去调用我们的主函数代码,跟踪进入。

4. 进入之后发现又执行了一次 push ebp    mov ebp , esp,再向下,ebp的值又基本

没有变。

好了,我们开始分析一下吧。进入启动函数执行完push ebp   mov ebp , esp后,ebp

所指向的地址正好是(存放返回地址的地址)-4,也就是在进入主函数之前,我们可以通

过[ebp+4]得到返回地址。进入主函数之后,又执行了一次这个过程,此时[ebp]就是原ebp

的值,我们可以通过[[ebp]+4]得到返回地址。代码如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值