当我反编译一个函数时,我得到了以下代码
((void(__thiscall**)(int))(*v4 + 4))(v4);
*v4在此上下文中是一个虚拟表。我真的无法分解(谁先解决了问题,以及它的确切含义(。
我恳请你帮助我一步一步地解决这个问题,这样我就能理解它是如何工作的。
(
( // these parens around the type declaration are a cast
void (__thiscall**)(int) // this type declaration:
// a pointer to pointer to function taking int parameter
)
(*v4 + 4) // this is a pointer expression
// this pointer is being cast to a function
) // this is a function pointer
( // these paren's invoke the function
v4 // this is the parameter being passed to the function
);
唯一奇怪的是,作为参数传递的v4
并不是强制转换所说的int,而是一个指针。
看起来v4
是一个对象,而vtable是该对象的第一个成员,所以*v4
指的是vtable。*v4+4
是指第5个vtable条目。
((void(__thiscall**)(int))(*v4 + 4))(v4);
^^ pointer
^^^ dereference it
^^^^^^^ add 4
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cast to void (__thiscall**)(int)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Call with v4 as the parameter
void (__thiscall**)(int)
是指向函数的指针的指针,该函数具有int
参数。
推测:
v4
是对象的地址*v4
从对象中读取vtable指针*v4 + 4
是vtable中我们要调用的函数指针所在的插槽。它是指向该函数指针的指针- 第一个参数是
this
注意,我们调用的是指向函数指针的指针。函数指针在C(++(中是自动取消引用的,但我不知道这也适用于指向函数指针的指针。显然,确实如此。
这句话使用了微软的一些奇怪的调用约定规范,但它基本上只是一个强制转换,后面是一个调用。
(void(**)(int))
此类型是指向以int为参数的函数的指针,并返回void。
__thiscall
是一个只有Microsoft编译器支持的调用约定说明符,正如您在这里看到的
(*v4 + 4)
这部分只是取消引用v4,然后添加4,所以我猜*v4是一个指针,v4的类型类似于void **
总而言之,此语句取消引用v4,将4添加到此值,将此新指针强制转换为指向函数指针的指针,然后通过传递v4来调用它。
正如其他人所指出的,v4作为int传递是很奇怪的。然而,由于体系结构似乎是x86,这不应该破坏任何东西,因为int和指针应该具有相同的32位大小。