高级话题:用ASM直接调用没有参数信息的dll库函数!

作者:不及格的程序员-八神

1. 背景资料

通常开发者获取到的通用dll函数库都会有说明文件,里面对dll库中公开的函数都会有api接口说明,比如函数的名称,返回值,参数类型以及参数的数量.

但是有时开发者也会找到一些dll库函数,这些库函数只能获取到函数名称,而没有关于函数的参数信息.

这种dll一般是来自第三方的,或是偷来的(我的项目中就是属于此类,我知道这个dll函数的功能很不错,我就是想将它嵌入到我的程序中.)).

对于前者,具有资料完备API编程信息,我们可以在c++,vb或.NET平台中轻松编写调用接口来执行dll中的函数,而后者由于没有参数信息,想调用就不那么简单了.

通常系统自带的dll函数库都会有api说明,或者也可以通过某些工具来获取dll库中的函数描述信息.

可是一些第三方的dll函数可能不会将函数信息写到dll中,这样我们就不能够获取参数信息了,也就无法调用了,真的没办法吗?

 

2. 解决办法

即然没有参数信息就没有办法声明函数的调用接口,不过没关系.

我想到一种简单的方式:用汇编语言来直接调用.

首先要有完整的第三方程序,先看看第三方程序在汇编语言层面上是如何调用函数的(通过反汇编).

通过调试软件(如:windbg,od,softace等)将第三方的程序运行起来,然后在我们需要的那个dll模块函数上加断点,分析它的汇编码.

其实很简单的,如果函数需要参数,那就看看它是通过栈的方式传的参数还是通过寄存器来传的参数.

一般汇编语言中参数都是传的参数地址,而不是值.另外传递参数的规则也要弄清.

如果传参方式是栈方式传参数,还要区分是调用者清除栈还是被调用者清除栈.

比如下面代码是调用md5加密,我就是用栈方式传递两个指针参数给函数.

    mov eax,dword ptr [cb] //传入待加密字符串地址

    push eax //参数2 入栈

    mov eax,dword ptr [result] //反回值字符串地址

    push eax //参数1 入栈

    call pFun //执行函数

结果result里就是我们加密后的结果了.

上面代码使用的是调用者清除栈方式,而清除栈方式是被调用者清除栈(通过反汇编可以发现指定函数里是使用哪种清栈方式.): 如果需要我们清除栈,那就在上面代码的最后写 add esp,8 代表释放两个指针参数的空间8个字节.

关于函数清栈方式参见我的另一篇随笔:函数的可变数目参数 与 栈

 

3. 如何加载dll与函数地址

 我使用win32 api 来加载dll库与函数地址,使用方式:

HINSTANCE dll = LoadLibrary(L"d:\\*******.dll");

FARPROC pFun = GetProcAddress(dll,"要调用的函数名称");

_asm

{

  mov eax,dword ptr [cb]

  push eax

  mov eax,dword ptr [result] 

  push eax

  call pFun

}

 

4. 注意事项

需要特别注意的是,对于(传入的/返回的)参数指针指向的数据区域大小需要多次试验,因为有时从汇编中很难发现局部变量的长度,所以尽量将我们声明的变量地址空间多一些.

还有就是dll函数的清栈方式,要仔细观察反汇编的结果,看看它用的是哪种调用方式,这样才能保障栈平横,不至于缓冲区溢出.

Advertisements
此条目发表在C++分类目录。将固定链接加入收藏夹。

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

You are commenting using your WordPress.com account. Log Out /  更改 )

Google+ photo

You are commenting using your Google+ account. Log Out /  更改 )

Twitter picture

You are commenting using your Twitter account. Log Out /  更改 )

Facebook photo

You are commenting using your Facebook account. Log Out /  更改 )

Connecting to %s