2010-08-10 65 views
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 

可能有人步,告诉我这里发生了什么?

+0

@ x0n - 这是作业标签? – 2010-08-10 21:14:46

+0

这不是家庭作业,我只是不擅长组装。 – Iron 2010-08-10 21:22:39

+0

删除了作业标签。 – x0n 2010-08-10 21:23:39

回答

6

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

该第一行获取存储在地址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。还有一些函数指针的数组,但是到达edx的指针(也是未对齐的偶数倍的偏移量)的双重间接使我认为这是一个struct而不是一个函数指针数组或者一个C++类的vtable。

换句话说,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,和你的汇编代码段不检查的函数指针NULL指针。因此,它必须是来自t_tableDRAWFUNCt_dumpSPECFUNC

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

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


我想补充一点,我认为这是一个遗憾,OllyDbg来源不可用。我当时的印象是,它所包含的静态链接反汇编工具正处于某种“GPL许可证”下,但我一直没有得到OllyDbg的消息。

+0

+1比我的更好的描述。 :-) – Pretzel 2010-08-10 20:39:32

+0

“这可能是一个调用......”会更精确,不是?你不知道它到底是什么。 – x0n 2010-08-10 20:57:02

+0

@ x0n。不,我认为我有一个很好的想法是什么。我有OllyDbg的一些经验。例如,我绝对没有写过“OllyDbg可能是用一种不确定的高级语言写成的”。它是用MSVC 2005编译的,我拥有该领域特定的知识。当然,这个代码片段可能是内联汇编,但是写了一个OllyDbg插件或三个OllyDbg插件主机测试工具...我想我知道它是什么。 XOFF。 – 2010-08-10 21:01:02

0

它已经一段时间,因为我做了ASM(1997年),甚至当时我只是在做I386 ASM所以原谅我,如果我的回答是不是所有的有用......

不幸的是,这4行代码唐对我说的不多。它主要是将东西加载到CPU寄存器并调用函数。

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

然后,无论位于复制到AX中的地址处的函数是否正在执行。

+0

它是否修改它在DWORD PTR的东西已经是DWORD PTR'd? – Iron 2010-08-10 20:31:36

+0

我没有看到任何修改正在进行,但CALL'ing EAX可能会调用某些可以改变的东西。我不能说不知道那里有什么...... – Pretzel 2010-08-10 20:34:27

+0

我很确定它将DS指向的值* [ECX]加载到EDX中,而不是简单地将ECX复制到EDX,就像x0n所说的那样。 – zwol 2010-08-10 20:35:07

2

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

这是非常基本的程序集。它使我怀疑你正在用调试器做什么以及你的任务是否到期;-)

+0

我正在通过调试东西来学习程序集,所以毫不奇怪它是基本的。我已经掌握了它做了什么,但是我没有在“MOV ECX,DWORD PTR [地址]”,然后是“MOV EDX,DWORD PTR [ECX]”中看到一点,所以我认为它可能会做一些不明显的事情。 因此无论如何,这是否意味着xxxxxxxx是指向函数的指针,还是指向函数指针的指针? – Iron 2010-08-10 20:34:23

+0

除了意思之外,它并不意味着什么。你不能推断那里有一个“功能”,或者即使函数作为一个概念存在于任何高级语言编译过程中(或者即使涉及更高级的语言,tbh也是如此)。为了逆向工程这个代码,你需要对生成它的编译器有深入的了解。 – x0n 2010-08-10 20:36:17

+0

我知道这是MSVC++,可能是2005年。 – Iron 2010-08-10 20:38:34

0

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

MOV ECX,DWORD PTR DS:[xxxxxxxx] 

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

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++类,包括虚拟方法,请参阅我的文章here