【问题标题】:How to read this decompiled statement?如何阅读这个反编译的语句?
【发布时间】:2020-11-06 09:08:41
【问题描述】:

当我反编译一个函数时,我得到了以下代码

((void(__thiscall**)(int))(*v4 + 4))(v4);

*v4 在这种情况下是一个虚拟表。实在是分不出来(谁先解决,具体是什么意思)。

请您帮助我逐步解决此问题,以便我了解其工作原理。

【问题讨论】:

  • 看起来 v4 可能是“this”指针,它取消引用以获取 vtable,将其索引以获取方法,将结果转换为函数调用,然后传递“this”到那个函数(这将是一个成员函数)。
  • When I threw this into Visual Studio I was surprised that it got accepted - 你是什么意思?该语句不会自行编译。也许您可以显示您将其复制到 VS 项目中的代码。
  • * 之后的 __thiscall 对我来说看起来像是语法错误。
  • 给定 +4,并假设是 32 位程序,它可能是该类中第二个声明的虚拟方法被调用。
  • @selbie 你说得对,我现在已经编辑了那部分,也谢谢大家我现在明白了

标签: c++ assembly decompiler


【解决方案1】:
((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(++) 中会自动取消引用,但我不知道这也适用于指向函数指针的指针。显然,确实如此。

【讨论】:

    【解决方案2】:
    (
        (   // 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 条目。

    【讨论】:

    • 另一个奇怪的事情是通过双指针调用函数实际上在任何 GCC、Clang 或 MSVC 上编译。这里发生了一些非常可疑的事情。也许反编译软件只是无法输出某些解引用...
    【解决方案3】:

    这个语句使用了微软的一些奇怪的调用约定规范,但它基本上只是一个强制转换,然后是一个调用。

    (void(**)(int))这个类型是一个指针,指向一个以int为参数并返回void的函数的指针。

    __thiscall 是微软编译器仅支持的调用约定说明符,如您所见here

    (*v4 + 4)这部分只是解引用v4,然后加4,所以我猜*v4是一个指针,v4的类型类似于void **

    总结一下,这个语句取消引用 v4,给这个值加 4,把这个新指针转换为一个指向函数的指针,然后通过传递 v4 来调用它。

    正如其他人所指出的,v4 作为 int 传递很奇怪。但是,由于架构似乎是 x86,这不应该破坏任何东西,因为 int 和指针应该具有相同的 32 位大小。

    【讨论】:

      猜你喜欢
      • 2021-12-07
      • 1970-01-01
      • 2017-11-18
      • 2017-04-20
      • 2018-06-24
      • 2016-05-12
      • 2013-08-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多