当前位置: 代码迷 >> 汇编语言 >> 解析动态链接库函数参数个数及部类求指导
  详细解决方案

解析动态链接库函数参数个数及部类求指导

热度:222   发布时间:2016-05-02 04:28:43.0
解析动态链接库函数参数个数及类型求指导
由于工作需要,要绕开一个软件直接去提取数据,这些数据是MFC直接序列化写在硬盘里,可以看到内容但是无法解读,通过调用dumpbin工具,我看了这个软件自带的dll文件,写数据的操作极有可能是在这些dll中,于是我想通过注入钩子的方法拦截参数来猜测数据经过了怎样的加工。这样就需要得到函数的参数个数及类型。我在网上看看了看相关的资料,于是就进行了操作,发现并不像想的那么容易,因此特来求教。
比如《windows核心编程》中22章的LastMsgBoxInfo例子的 
BOOL WINAPI LastMsgBoxInfo_HookAllApps(BOOL bInstall, DWORD dwThreadId) 中有两个参数,但是对dll的反编译结果:
环境:win7 64位旗舰版 反编译软件W32Dsm10

Exported fn(): [email protected] - Ord:0001h
:1001124E E9BD1F0000              jmp 10013210

* Referenced by a CALL at Address:
|:100139CF   |

* Reference To: MSVCR90D._except_handler4_common, Ord:01A8h |
:10011253 E9C43B0000              Jmp 10014E1C

* Referenced by a CALL at Address:
|:10011C86   |

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10016833(U)|
:10011258 E9630B0000              jmp 10011DC0

* Reference To: KERNEL32.lstrlenA, Ord:04B5h|
:1001125D E972460000              Jmp 100158D4

 .... 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1001124E(U)|
:10013210 55                      push ebp
:10013211 8BEC                    mov ebp, esp
:10013213 81ECCC000000            sub esp, 000000CC
:10013219 53                      push ebx
:1001321A 56                      push esi
:1001321B 57                      push edi
:1001321C 8DBD34FFFFFF            lea edi, dword ptr [ebp+FFFFFF34]
:10013222 B933000000              mov ecx, 00000033
:10013227 B8CCCCCCCC              mov eax, CCCCCCCC
:1001322C F3                      repz
:1001322D AB                      stosd
:1001322E 837D0800                cmp dword ptr [ebp+08], 00000000
:10013232 7462                    je 10013296
:10013234 833DBCC1011000          cmp dword ptr [1001C1BC], 00000000
:1001323B 741B                    je 10013258
:1001323D 6898A90110              push 1001A998
:10013242 A104C00110              mov eax, dword ptr [1001C004]
:10013247 83C006                  add eax, 00000006
:1001324A 50                      push eax
:1001324B 6838A90110              push 1001A938
:10013250 E8EADFFFFF              call 1001123F
:10013255 83C40C                  add esp, 0000000C

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1001323B(C)
|
:10013258 8BF4                    mov esi, esp

根据网上的方法,发现好像找不到参数,因为反编译后面一直在jmp,不知道在哪个地方获取参数,希望有大神给我解惑。

另外有一个未知函数,反汇编如下:
环境:xp sp3(虚拟机) 反编译软件W32Dsm10

Exported fn(): file_settings_getArea - Ord:005Fh
:10001306 FF742408                push [esp+08]
:1000130A B9FCB50110              mov ecx, 1001B5FC
:1000130F FF742408                push [esp+08]
:10001313 E8E64D0000              call 100060FE
:10001318 C3                      ret

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10001010(U)|
:10001319 8BC1                    mov eax, ecx
:1000131B 802000                  and byte ptr [eax], 00
:1000131E C3                      ret

其中里面的两个 push [esp+08] 让我很不能理解,这个函数的参数是不是 08/4 = 2个啊?不懂,跪求解释。
------解决思路----------------------
这个程序看着约定上不一样,有些怪异,不同环境的模块组合起来的?
前面一组的代码,[ebp+8] 开始应该是参数。参数的个数,一是可以看 +8 这里最多加到多少,通常一个 dword 是一个参数;或者是看调用这个函数的那个 call 指令后对 esp 加了多少,一般是 /4 后是参数的个数。参数的类型,不是导出函数安装约定形成函数名的话,就只能从函数里是怎么使用这个参数来揣摩了;多是比较麻烦的。
后面那些代码,又是另外个方式,应该直接通过 esp 来访问参数的,没有如上面的那边通过 ebp 。参数个数应该就是两,也可以通过 call 指令后对 esp 的调整来确认下。08/4 里的 08 不是 [esp+08] 里的 08,而是两个 push 指令操作了 2 个 dword 所涉及到的 08 个字节。

你这个分析需求,难点恐怕不在参数这里,而是如何对数据进行加工部分了。
------解决思路----------------------
1. 那些 jmp 不用在意的,这个只是对外部引用函数的一个调用方式而已,而且,这些 jmp 指令是在自己的程序里的,不是在那些外部函数里。
2. 我上面说的约定是对参数和局部变量的使用方式,不是你提及的这个意思。通常都是采用 ebp 来进行的,如 [ebp+??] 指向参数,[ebp-??] 则是函数的局部变量,当然了函数开始时要有将 ebp 压栈并将 esp 赋予 ebp 的操作;有些编译器会将 ebp 也作为普通的通用寄存器来使用,而直接用 esp 来访问参数和局部变量,由于 esp 的易变性,这样的用法就会对程序的分析带来一定的困难,象你上面的第二组函数。
3. 最后一个函数倒没多大的意义吧。

函数参数入栈的结束,当然是以 call 来的。参数的个数是看针对这次 call 有几个 push 或 call 后给 esp 加了多少,要注意的是不是前面有几个 push 就都是参数的,有些可能是临时保存下寄存器甚至是更后面的 call 的参数,同样 call 后的 esp 加也有可能是部分为更前面的 call 来做的;或者是函数的采用 ret ?? 来进行参数入栈平衡的话就看 ?? (??/4)。所以可靠的方法还是看函数里对参数的使用,或是采用 ret ?? 方式的话。
------解决思路----------------------
晕,我上面看错了,以为上面的汇编代码是被下面的 c 调用的,原来就是 c 的反汇编。
是 4 个参数,第一个 push esi 不是,只是后面使用了 esi,函数结束前不是有个 pop esi 的吗,这个是恢复 esi 的。
有个寄存器的使用约定可能要提一下,函数可以随意使用 eax/edx/ecx 而无须做任何的保护;如果使用了 esi/edi/ebx 的话,就需要先行保存,函数结束前进行恢复。这同时意味着,如果要在个 call 后继续使用刚才的 eax/edx/ecx 的话,就要你自己进行保存恢复的操作了。这是涉及到的个题外话。
------解决思路----------------------
汇编里没有高级语言里的类型的,无论是 ULONG 还是 HANDLE 抑或是 HWND 都只是 dword 而已;一个指针无论指向怎样类型的数据,它也只是个 dword 大小的地址而已。
高级语言里的类型转换,也说明了类型的虚的性质,只是为了方便理解和谨于操作之类的考虑。
  相关解决方案