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

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

Exported fn(): _LastMsgBoxInfo_HookAllApps@8 - 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个啊?不懂,跪求解释。
...全文
320 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
EP 2015-02-04
  • 打赏
  • 举报
回复
非常感谢,分不多,只能再加20分,抱歉
zara 2015-02-04
  • 打赏
  • 举报
回复
汇编里没有高级语言里的类型的,无论是 ULONG 还是 HANDLE 抑或是 HWND 都只是 dword 而已;一个指针无论指向怎样类型的数据,它也只是个 dword 大小的地址而已。
高级语言里的类型转换,也说明了类型的虚的性质,只是为了方便理解和谨于操作之类的考虑。
EP 2015-02-04
  • 打赏
  • 举报
回复
引用 7 楼 zara 的回复:
晕,我上面看错了,以为上面的汇编代码是被下面的 c 调用的,原来就是 c 的反汇编。 是 4 个参数,第一个 push esi 不是,只是后面使用了 esi,函数结束前不是有个 pop esi 的吗,这个是恢复 esi 的。 有个寄存器的使用约定可能要提一下,函数可以随意使用 eax/edx/ecx 而无须做任何的保护;如果使用了 esi/edi/ebx 的话,就需要先行保存,函数结束前进行恢复。这同时意味着,如果要在个 call 后继续使用刚才的 eax/edx/ecx 的话,就要你自己进行保存恢复的操作了。这是涉及到的个题外话。
非常感谢,其实我还有一点不解,是在汇编代码中似乎没有看到任何参数类型,您如果愿意解答就解答,不解答的话,晚上我就结贴给分,非常感谢。
zara 2015-02-04
  • 打赏
  • 举报
回复
晕,我上面看错了,以为上面的汇编代码是被下面的 c 调用的,原来就是 c 的反汇编。
是 4 个参数,第一个 push esi 不是,只是后面使用了 esi,函数结束前不是有个 pop esi 的吗,这个是恢复 esi 的。
有个寄存器的使用约定可能要提一下,函数可以随意使用 eax/edx/ecx 而无须做任何的保护;如果使用了 esi/edi/ebx 的话,就需要先行保存,函数结束前进行恢复。这同时意味着,如果要在个 call 后继续使用刚才的 eax/edx/ecx 的话,就要你自己进行保存恢复的操作了。这是涉及到的个题外话。
EP 2015-02-04
  • 打赏
  • 举报
回复
引用 5 楼 zara 的回复:
你这个函数,实际的通过栈的参数应该是 3 个,即 a2, a3, a4 这三个;无论是 ida 分析的提示(就三个 arg_??)还是函数最后 retn 0ch (0ch/4=3)都提示了这个。 void *this 是通过 ecx 传递的,这也是个 c/c++ 的约定吧;也有乱用的。 至于 call 之前有 5 个 push,要看具体代码了,比较可能是临时使用了 esi/edi/ebx ,后面应该有两个相应的 pop 指令的;如果不是这样,将 qt_mt312_2() 函数的反汇编结果贴上来看看?
为了方便您好看,所以把我用IDA得到的C代码和反汇编的代码都贴出来,上面的汇编代码就是底下qt_mt312_2函数反汇编的结果。由于您的提示,我想多问一嘴,就是关于这个所谓的 this 指针,如果我想进行api的拦截的话是否需要在函数声明中加上呢(我感觉应该要加,不知道对不对)? 我这里说的call之前的五个push就是指的是上面汇编中的:

text:39D28F8C                 push    esi
.text:39D28F8D                 mov     esi, ecx
.text:39D28F8F                 push    [esp+4+arg_8]
.text:39D28F93                 push    [esp+8+arg_4]
.text:39D28F97                 push    1
.text:39D28F99                 push    [esp+10h+arg_0]
这五个,心生疑惑所以提出来,不管怎么样,非常感谢您花费宝贵的时间来解答我的困惑。
zara 2015-02-04
  • 打赏
  • 举报
回复
你这个函数,实际的通过栈的参数应该是 3 个,即 a2, a3, a4 这三个;无论是 ida 分析的提示(就三个 arg_??)还是函数最后 retn 0ch (0ch/4=3)都提示了这个。
void *this 是通过 ecx 传递的,这也是个 c/c++ 的约定吧;也有乱用的。
至于 call 之前有 5 个 push,要看具体代码了,比较可能是临时使用了 esi/edi/ebx ,后面应该有两个相应的 pop 指令的;如果不是这样,将 qt_mt312_2() 函数的反汇编结果贴上来看看?
EP 2015-02-04
  • 打赏
  • 举报
回复
引用 2 楼 shenmafuyunnan 的回复:
[quote=引用 1 楼 zara 的回复:] 这个程序看着约定上不一样,有些怪异,不同环境的模块组合起来的? 前面一组的代码,[ebp+8] 开始应该是参数。参数的个数,一是可以看 +8 这里最多加到多少,通常一个 dword 是一个参数;或者是看调用这个函数的那个 call 指令后对 esp 加了多少,一般是 /4 后是参数的个数。参数的类型,不是导出函数安装约定形成函数名的话,就只能从函数里是怎么使用这个参数来揣摩了;多是比较麻烦的。 后面那些代码,又是另外个方式,应该直接通过 esp 来访问参数的,没有如上面的那边通过 ebp 。参数个数应该就是两,也可以通过 call 指令后对 esp 的调整来确认下。08/4 里的 08 不是 [esp+08] 里的 08,而是两个 push 指令操作了 2 个 dword 所涉及到的 08 个字节。 你这个分析需求,难点恐怕不在参数这里,而是如何对数据进行加工部分了。
1.您说的很对,我确切的需求不再这个地方,但是现阶段我不得不分析这些汇编。第一个代码我只是为了测试一下网上找到的文章是否正确,结果发现函数之后基本上全是jmp,很郁闷。我用...代替这些jmp指令,后面10013210地址的汇编代码是函数名后的第一个jump所指向的地址,所以贴出来了。 2.关于第一个函数的约定,是直接截得源代码里的代码,所以会比较怪,在windows,里可以认为BOOL , DWORD 是int,WINAPI 是 __stdcall,希望不在windows平台编程的大神有所了解。 3.最后一个函数是我在前一个反汇编看不懂后,重新对我需要分析的代码反汇编的结果,结果我也看不懂,于是就贴上去了,希望不要混淆。所以最后一个代码是在软件的实际工作环境xp中反汇编的。 我顺便想问问,一个函数的参数入栈的结束是以ret结束还是call结束或者是其他;参数的个数是看push的次数还是什么,希望能详细解释下。如果受益匪浅的话,可以加分的。 ps:很久没弄汇编,都忘了很多,但是今天晚上下班我会回家重新温习的,肤浅之处希望不要计较。[/quote] 最后问个问题,答完就可以结帖了,并再送一点分。下面这段是反汇编后的结果,最下面的函数是用IDA f5插件的结果,我想问问能不能给我仔细的讲讲为什么是四个参数而不是五个(因为我看到call之前有5个push),以及如何判断参数的类型(这个可讲可不讲,先谢谢了)

:39D28F8C                 public qt_mt312_2
.text:39D28F8C qt_mt312_2      proc near               ; DATA XREF: .rdata:off_39F671F8o
.text:39D28F8C
.text:39D28F8C arg_0           = dword ptr  4
.text:39D28F8C arg_4           = dword ptr  8
.text:39D28F8C arg_8           = dword ptr  0Ch
.text:39D28F8C
.text:39D28F8C                 push    esi
.text:39D28F8D                 mov     esi, ecx
.text:39D28F8F                 push    [esp+4+arg_8]
.text:39D28F93                 push    [esp+8+arg_4]
.text:39D28F97                 push    1
.text:39D28F99                 push    [esp+10h+arg_0]
.text:39D28F9D                 call    qt_mt312_415
.text:39D28FA2                 mov     dword ptr [esi], offset qt_mt312_2502
.text:39D28FA8                 mov     eax, esi
.text:39D28FAA                 pop     esi
.text:39D28FAB                 retn    0Ch
.text:39D28FAB qt_mt312_2      endp

void *__thiscall qt_mt312_2(void *this, int a2, int a3, int a4)
{
  void *v4; // esi@1

  v4 = this;
  qt_mt312_415(a2, 1, a3, a4);
  *(_DWORD *)v4 = qt_mt312_2502;
  return v4;
}
zara 2015-02-03
  • 打赏
  • 举报
回复
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 ?? 方式的话。
EP 2015-02-03
  • 打赏
  • 举报
回复
引用 1 楼 zara 的回复:
这个程序看着约定上不一样,有些怪异,不同环境的模块组合起来的? 前面一组的代码,[ebp+8] 开始应该是参数。参数的个数,一是可以看 +8 这里最多加到多少,通常一个 dword 是一个参数;或者是看调用这个函数的那个 call 指令后对 esp 加了多少,一般是 /4 后是参数的个数。参数的类型,不是导出函数安装约定形成函数名的话,就只能从函数里是怎么使用这个参数来揣摩了;多是比较麻烦的。 后面那些代码,又是另外个方式,应该直接通过 esp 来访问参数的,没有如上面的那边通过 ebp 。参数个数应该就是两,也可以通过 call 指令后对 esp 的调整来确认下。08/4 里的 08 不是 [esp+08] 里的 08,而是两个 push 指令操作了 2 个 dword 所涉及到的 08 个字节。 你这个分析需求,难点恐怕不在参数这里,而是如何对数据进行加工部分了。
1.您说的很对,我确切的需求不再这个地方,但是现阶段我不得不分析这些汇编。第一个代码我只是为了测试一下网上找到的文章是否正确,结果发现函数之后基本上全是jmp,很郁闷。我用...代替这些jmp指令,后面10013210地址的汇编代码是函数名后的第一个jump所指向的地址,所以贴出来了。 2.关于第一个函数的约定,是直接截得源代码里的代码,所以会比较怪,在windows,里可以认为BOOL , DWORD 是int,WINAPI 是 __stdcall,希望不在windows平台编程的大神有所了解。 3.最后一个函数是我在前一个反汇编看不懂后,重新对我需要分析的代码反汇编的结果,结果我也看不懂,于是就贴上去了,希望不要混淆。所以最后一个代码是在软件的实际工作环境xp中反汇编的。 我顺便想问问,一个函数的参数入栈的结束是以ret结束还是call结束或者是其他;参数的个数是看push的次数还是什么,希望能详细解释下。如果受益匪浅的话,可以加分的。 ps:很久没弄汇编,都忘了很多,但是今天晚上下班我会回家重新温习的,肤浅之处希望不要计较。
zara 2015-02-03
  • 打赏
  • 举报
回复
这个程序看着约定上不一样,有些怪异,不同环境的模块组合起来的?
前面一组的代码,[ebp+8] 开始应该是参数。参数的个数,一是可以看 +8 这里最多加到多少,通常一个 dword 是一个参数;或者是看调用这个函数的那个 call 指令后对 esp 加了多少,一般是 /4 后是参数的个数。参数的类型,不是导出函数安装约定形成函数名的话,就只能从函数里是怎么使用这个参数来揣摩了;多是比较麻烦的。
后面那些代码,又是另外个方式,应该直接通过 esp 来访问参数的,没有如上面的那边通过 ebp 。参数个数应该就是两,也可以通过 call 指令后对 esp 的调整来确认下。08/4 里的 08 不是 [esp+08] 里的 08,而是两个 push 指令操作了 2 个 dword 所涉及到的 08 个字节。

你这个分析需求,难点恐怕不在参数这里,而是如何对数据进行加工部分了。

21,458

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧