【问题标题】:Confusing function令人困惑的功能
【发布时间】:2011-03-09 12:39:18
【问题描述】:

所以,在使用 IDA 反汇编一个 dll 时,我遇到了这个类函数:

mov eax, [ecx+4]
mov eax, [eax]
retn

我知道ecx 表示thiseax 是返回值,但我不明白它返回什么。有什么帮助吗?

【问题讨论】:

    标签: assembly reverse-engineering ida


    【解决方案1】:

    该函数从ecx 指向的任何偏移量4 处加载一个指针(到eax)。然后它跟随该指针将一个 32 位值加载到函数返回的 eax 中。

    这就是函数的作用,但如果没有更多上下文,就不可能说出的含义

    【讨论】:

    • 它很有可能返回一个带有 vtable 的类的第一个 int 或引用成员,或者返回一个没有 vtable 的结构的第二个成员。
    • 你能用 C 或 c++ 语法显示这个吗? Hex-Rays 返回:return **(DWORD **)(this+4);这实际上是函数的作用吗?
    • kotarou3,在我的回答中用“图片”解释,按照“箭头”,您可以转换为您熟悉的任何语言。您在这里假设 lang 是 C/C++,如果您谈论“this”,可能是 C++,并且任何其他暗示它可能是什么的答案都必须假设特定的运行时;我认为(但我不确定),C++ 标准没有规定必须如何完成运行时,甚至没有规定如何“在低级完成”类或对象,所以如果没有上下文,...
    【解决方案2】:

    我的程序集有点生疏,但第一条指令将一些东西加载到 EAX 中……ECX 寄存器的内容指向的东西……但它是一个字(4 个字节)的偏移量。然后,下一条指令是使用 EAX 指向的任何内容加载(覆盖)EAX。

    此符号(这些 MOV(加载)指令的第二个或“源”操作周围的方括号表示正在使用间接寻址模式。

    我猜这只是一种实现双重间接的方式。寄存器 ECX 中的地址可能指向堆栈帧,或者可能指向您提到的 C++“this”的某个属性指针。反过来,该地址保存返回值的地址。因此,此代码将地址拉入寄存器,然后使用寄存器中的地址拉出一个值(同时进入同一个寄存器)。这种方法很好,因为它保留了所有其他寄存器。

    (顺便提一下,大多数 x86 函数调用范例 --- 系统调用、DOS 函数调用等。在 stdlib C 库中的 EAX 寄存器中留下函数返回码或系统错误...errno)。

    【讨论】:

      【解决方案3】:

      真是个问题。如果 ecx 持有指向“this”结构的指针,您必须知道它是如何完成的。第一个instr,得到第二个dword,另一个指针;可能是什么?我们无法知道。这个指针现在保存在 eax 中,可能指向另一个结构或其他什么。第一个指向的值放在 eax 中,这就是 func 返回的内容。

      ecx    ------->    dword dataA   offset 0
                         dword dataB   offset 4
      
        mov eax, [ecx + 4]
      
      eax = dataB ---->  dword dataC   offset 0
      
        mov eax, [eax]
      
      eax = dataC
      

      dataC 到底是什么,取决于很多我们不知道的事情。

      【讨论】:

        【解决方案4】:
        class C
        {
            int a;
            int *b; // ecx+4
        
            int get_b()
            {
                return *b;
            }
        }
        

        当然,a*b 的实际类型未知,但它们都是 32 位类型。 a 也可以是指向 VMT 的指针,如果该类有任何虚方法或析构函数。

        【讨论】:

        • 哦,不过在这个类中,ecx+4其实就是vftable中的函数本身。那么这意味着什么......?
        • 这不会改变任何事情。指向 vtable 的 指针 存储在第一类字段中(在我的示例中为 a)。
        • 我怎样才能找到 ecx+4 是什么?
        • 好吧,您已经知道它是一个指向 32 位值的指针。您必须查看其他代码才能了解它是什么。我建议查看调用此函数的代码,但由于您提到此函数是虚拟的,您将无法简单地获取交叉引用列表。您可以在函数中放置一个断点并检查调用堆栈以找到调用它的代码。也可以找到该类的虚方法表,查看其他虚函数是否对这个值进行操作。
        【解决方案5】:

        这在很大程度上取决于原始编译器使用的调用约定。一个相当正常的设置,例如MSVC 将在 eax 寄存器中返回 32 位值。 @Gregs 回答说明了它的作用,但正如他所说,含义取决于了解实现语言和编译器的更多细节。

        如果您想了解反汇编,请尝试使用您自己的 (C/C++) 代码查看结果。这确实是了解其他人的 DLL 中发生的情况的唯一方法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-21
          • 2022-01-17
          • 2018-02-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-15
          • 1970-01-01
          相关资源
          最近更新 更多