几行我已经在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
可能有人步,告诉我这里发生了什么?
几行我已经在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
可能有人步,告诉我这里发生了什么?
这是存储在结构中的函数指针的调用。
该第一行获取存储在地址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_table
的DRAWFUNC
或t_dump
的SPECFUNC
。
您可以创建一个包含头文件的小项目,并使用printf()
和offsetof()
来确定其中的任一个是否在0x116的偏移处。
否则,我想像OllyDbg的内部是用同样的风格写的。所以在OllyDbg中可能会有私人的struct
定义(未在Plugin.h文件中发布)用于各种目的。
我想补充一点,我认为这是一个遗憾,OllyDbg来源不可用。我当时的印象是,它所包含的静态链接反汇编工具正处于某种“GPL许可证”下,但我一直没有得到OllyDbg的消息。
+1比我的更好的描述。 :-) – Pretzel 2010-08-10 20:39:32
“这可能是一个调用......”会更精确,不是?你不知道它到底是什么。 – x0n 2010-08-10 20:57:02
@ x0n。不,我认为我有一个很好的想法是什么。我有OllyDbg的一些经验。例如,我绝对没有写过“OllyDbg可能是用一种不确定的高级语言写成的”。它是用MSVC 2005编译的,我拥有该领域特定的知识。当然,这个代码片段可能是内联汇编,但是写了一个OllyDbg插件或三个OllyDbg插件主机测试工具...我想我知道它是什么。 XOFF。 – 2010-08-10 21:01:02
它已经一段时间,因为我做了ASM(1997年),甚至当时我只是在做I386 ASM所以原谅我,如果我的回答是不是所有的有用......
不幸的是,这4行代码唐对我说的不多。它主要是将东西加载到CPU寄存器并调用函数。
具体来说,它看起来像数据或指针正在从该地址加载到您的CX寄存器。然后将该值从CX复制到DX。所以你有位于DX的CX指针的值。那么DX中的值加上116的偏移量将被复制到AX寄存器中(您的累加器?)
然后,无论位于复制到AX中的地址处的函数是否正在执行。
把地址为xxxxxxx的32位数字放到ECX寄存器中,然后用这个数值作为地址并读取数值并把它放入EDX寄存器,最后在这个数字上加116,并读取该数值地址到EAX。然后它开始执行现在在EAX中保存的地址的代码。当代码遇到返回操作码时,执行将在调用指令后继续。
这是非常基本的程序集。它使我怀疑你正在用调试器做什么以及你的任务是否到期;-)
我正在通过调试东西来学习程序集,所以毫不奇怪它是基本的。我已经掌握了它做了什么,但是我没有在“MOV ECX,DWORD PTR [地址]”,然后是“MOV EDX,DWORD PTR [ECX]”中看到一点,所以我认为它可能会做一些不明显的事情。 因此无论如何,这是否意味着xxxxxxxx是指向函数的指针,还是指向函数指针的指针? – Iron 2010-08-10 20:34:23
除了意思之外,它并不意味着什么。你不能推断那里有一个“功能”,或者即使函数作为一个概念存在于任何高级语言编译过程中(或者即使涉及更高级的语言,tbh也是如此)。为了逆向工程这个代码,你需要对生成它的编译器有深入的了解。 – x0n 2010-08-10 20:36:17
我知道这是MSVC++,可能是2005年。 – Iron 2010-08-10 20:38:34
我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。
@ x0n - 这是作业标签? – 2010-08-10 21:14:46
这不是家庭作业,我只是不擅长组装。 – Iron 2010-08-10 21:22:39
删除了作业标签。 – x0n 2010-08-10 21:23:39