5

我在 ollydbg 中找到了这几行汇编:

MOV ECX,DWORD PTR DS:[xxxxxxxx] ; xxxxxxxx is an address
MOV EDX,DWORD PTR DS:[ECX]
MOV EAX,DWORD PTR DS:[EDX+116]
CALL EAX

有人可以过来告诉我这里发生了什么吗?

4

4 回答 4

6

这是对存储在结构中的函数指针的调用。

第一行获取存储在 address 的指针DS:xxxxxxxx。方括号表示地址的取消引用,就像*在 C 中一样。来自内存的值即将用作指针;它被放入ecx寄存器。

MOV ECX,DWORD PTR DS:[xxxxxxxx] ; xxxxxxxx is an address

第二行取消引用上面获得的指针。该值ecx现在用作地址,该地址已被取消引用。在内存中找到的值是另一个指针。第二个指针被放入edx寄存器中。

MOV EDX,DWORD PTR DS:[ECX]

第三行再次取消引用内存;这一次,访问发生在与上面获得的指针相距0x116字节的地址偏移处。这不能被 4 整除,所以这个函数指针似乎不是来自 C++ vtable。这次从内存中获得的值存储在寄存器中eax

MOV EAX,DWORD PTR DS:[EDX+116]

最后,执行指向的函数eax。这只是通过函数指针调用函数。该函数似乎接受零参数,但我有一个关于修改我的答案的问题:PUSH这个片段之前是否有指令?这些将是函数参数。问号表示这个函数可能会返回一个值,从我们的角度来看我们无法判断。

CALL EAX

总的来说,代码片段看起来像是从插件库调用 OllyDbg 的扩展函数。OllyDbg ABI 指定了struct包含一些函数指针的各种 s。还有函数指针数组,但双间接到达edx-held 指针(也是未对齐的偶数倍偏移量)让我认为这是一个struct而不是函数指针数组或 C++类的虚表。

换句话说,xxxxxxxx是一个指向一个struct包含函数指针的指针。

在 OllyDbg 源文件 PlugIn.h 中有一些候选struct定义。这是一个例子:

typedef struct t_sorted {              // Descriptor of sorted table
  char           name[MAX_PATH];       // Name of table, as appears in error
  int            n;                    // Actual number of entries
  int            nmax;                 // Maximal number of entries
  int            selected;             // Index of selected entry or -1
  ulong          seladdr;              // Base address of selected entry
  int            itemsize;             // Size of single entry
  ulong          version;              // Unique version of table
  void           *data;                // Entries, sorted by address
  SORTFUNC       *sortfunc;            // Function which sorts data or NULL
  DESTFUNC       *destfunc;            // Destructor function or NULL
  int            sort;                 // Sorting criterium (column)
  int            sorted;               // Whether indexes are sorted
  int            *index;               // Indexes, sorted by criterium
  int            suppresserr;          // Suppress multiple overflow errors
} t_sorted;

这些示例是允许的NULL,并且您的 asm 代码段不会检查NULL函数指针中的指针。因此,它必须DRAWFUNC来自t_tableSPECFUNCt_dump

您可以创建一个包含头文件并使用的小项目,printf()offsetof()确定其中任何一个的偏移量是否为 0x116。

否则,我想 OllyDbg 的内部都是用同样的风格编写的。因此,struct在 OllyDbg 中可能有用于各种目的的私有定义(未在 Plugin.h 文件中发布)。


我想补充一下,我认为 OllyDbg 资源不可用是一种耻辱。我的印象是它包含的静态链接反汇编程序是在某种 ?GPL 许可下,但我没有任何运气将源代码提供给 OllyDbg。

于 2010-08-10T20:34:47.657 回答
2

从地址 xxxxxxx 中取出 32 位数字,放入 ECX 寄存器,然后将此值作为地址,读取该值并放入 EDX 寄存器,最后将该数字加 116,将该地址的值读入 EAX。然后它开始在现在保存在 EAX 中的地址处执行代码。当该代码遇到返回操作码时,将在调用指令之后继续执行。

这是非常基本的组装。这让我想知道您正在使用调试器做什么以及您的任务何时到期;-)

于 2010-08-10T20:31:51.140 回答
0

自从我做 ASM(1997 年)以来已经有一段时间了,即使那时我也只做 i386 ASM,所以如果我的回答不是那么有帮助,请原谅我......

不幸的是,这 4 行代码并没有告诉我太多。它主要只是将东西加载到 CPU 寄存器中并调用一个函数。

具体来说,它看起来像是数据或指针正在从该地址加载到您的 CX 寄存器中。然后将该值从 CX 复制到 DX。所以你有位于 DX 中的 CX 指针的值。然后 DX 中的值加上 116 的偏移量被复制到 AX 寄存器(你的累加器?)

然后将执行位于复制到 AX 中的该地址处的任何函数。

于 2010-08-10T20:30:25.123 回答
0

考虑到有关编译器是 MSVC 的评论,我 99% 确定这是一个虚拟方法调用。

MOV ECX,DWORD PTR DS:[xxxxxxxx]

指向类实例的指针从全局变量加载到 ECX 中。(注意:默认的 __thiscall 调用约定使用 ECX 传递实例指针,也就是this指针)。

MOV EDX,DWORD PTR DS:[ECX]

vftable(虚函数表)指针通常是类布局中的第一项。这里指针被加载到 EDX 中。

MOV EAX,DWORD PTR DS:[EDX+116]

将表中偏移量 116 (0x74) 处的方法指针加载到 EAX 中。由于每个指针是 4 个字节,这是该类的第 30 个虚拟方法 (116/4 + 1)。

CALL EAX

该方法被调用。

在原始 C++ 中,它看起来像这样:

g_pObject1->method30();

要了解更多关于 MSVC 对 C++ 类的实现,包括虚方法,请参阅我的文章

于 2010-08-25T22:27:21.790 回答