decompiling - 反编译后的 __thiscall 表达式是指向函数的指针吗?

标签 decompiling decompiler ida

我正在使用 IDA Pro 6.3 对 Win32 .dll 进行静态分析,并将 Hex-Rays 反编译器与 IDA 反汇编器结合使用。我想了解这一行的作用。

v4 = (*(int (__thiscall **)(int, int))(*(_DWORD *)dword_10087418 + 4))(dword_10087418, v11);

它的格式类似于函数调用。当在子例程调用中使用指向函数的指针时,这就是反编译代码的样子吗?

谢谢。

最佳答案

这很可能是 C++,而不是普通的 C。这正是 Visual C++ 生成的虚拟方法调用的样子。我想说的是:

  • dword_10087418 是指向对象的指针。它要么是全局变量,要么是静态变量,而不是局部变量。
  • 该对象有一个虚拟方法表,代码正在调用该表中的第二个函数。
  • 假设 Hex-Rays 已正确识别函数参数,则被调用的函数采用一个 32 位参数。返回类型不清楚。
  • C++ 调用很可能非常简单,类似于 SomeClass::Instance->func(arg)

如果您不熟悉 C++ 对象布局,您应该阅读 C++ Under the Hood , Reversing: Secrets of Reverse EngineeringInside the C++ Object Model 。 IDA Pro Book 也有一个关于该主题的简短部分。


如果您需要简短的摘要,请继续阅读。请记住,所有这些都是 MSVC 的实现细节,其他编译器的做法有所不同,他们可以随意更改它。 (另外,我通过不提及虚拟/多重继承来简化事情)。当类使用虚函数时,编译器会构建该类中所有此类函数的表,并将指向该表的指针作为该类的每个对象的第一个隐藏成员。然后,从表中调用虚函数就很简单:

mov ecx, esi   ; pretend that esi contains a pointer 
               ; to the object whose method is being called
               ; also known as "this"
               ; __thiscall functions expect to find this pointer in ecx
               ;  and all later arguments on the stack
mov edx, [ecx] ; get the vtable address
push edi       ; set up some integer-sized argument
call [edx + 4] ; call the second function in the vtable

这基本上就是这行代码正在做的事情:

(*(int (__thiscall **)(int, int))(*(_DWORD *)dword_10087418 + 4))(dword_10087418, v11)
                                  ^-----------------------^
                                  dereference pointer to get the address of the vtable
                                  (it's the first piece of data in the object)
                                 ^-----------------------------^
                                 add 4 bytes to get address of the second function
^------------------------------------------------------------------------------------^
cast that pointer to a particular function pointer and call it
(cast is invisible in assembler code, so it's just a call)

请注意,由于成员函数需要访问 this,因此编译器也必须传递它。这是一个在 C++ 中不可见的细节,但 this 被视为函数的附加参数 - 因此您会看到两个参数,但函数只接受一个(MSVC 的 thiscall 约定)要求 this 指针在 ecx 中传递)。 IDA 不会费心隐藏该指针,因为这会让人感到困惑。


更多建议:获取ms_rtti IDA 的脚本并运行它以查找 DLL 中的虚拟方法表,然后搜索对 dword_10087418 的其他引用以查看写入了哪些值 - 您应该能够确定与哪个 vtable 关联该对象,然后找出正在调用哪个函数。

如果您为相关类和虚函数表定义 stub 结构类型,然后告诉 IDA 该指针使用该结构类型,则可以使 Hex-Rays 以更易读的方式显示代码。

关于decompiling - 反编译后的 __thiscall 表达式是指向函数的指针吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16576824/

相关文章:

c# - 有人可以反编译我的 C# 应用程序并覆盖保护机制吗?

编译器 C 去 Brainfuck(骚扰教授)?

c++ - 在 C++ Disasm 中需要帮助

c++ - (g++) 剥离函数名

flash - 如何在我的服务器上自动反编译 SWF 文件?

java - 保护嵌入在 Java 桌面应用程序中的用户名/密码

java - 通过文法构建Java Decompiler会出现什么问题?

64-bit - 无法在 Ubuntu 12.04.3 64 位上启动 JD-GUI

c# - 反编译使用预编译工具生成的aspx页面

C 数学函数与 _BYTE 和