有没有办法通过逆向工程来恢复结构。指向该结构的指针由 DLL 中用于导出的唯一函数返回
Posted
技术标签:
【中文标题】有没有办法通过逆向工程来恢复结构。指向该结构的指针由 DLL 中用于导出的唯一函数返回【英文标题】:Is there any way to restore struct by reverse engineering. Pointer to that struct is returned by the only function for export inside DLL 【发布时间】:2012-06-15 12:52:30 【问题描述】:有点...我有一个 DLL,它导出唯一的单个函数 CreateInterface 从反汇编然后反编译的代码:
int __cdecl CreateInterface(const char *a1, int a2)
//many crazy things
这里它的返回类型为 int,但实际上它是指向某个结构的指针。 从主 exe 加载此库,然后以这种方式使用:
int (__stdcall *__cdecl Sys_GetFactory(int (__stdcall *hModule)()))()
int (__stdcall *result)(); // eax@1
result = hModule;
if ( hModule )
result = GetProcAddress(hModule, "CreateInterface");
return result;
void some_funct()
FARPROC net_interface = Sys_GetFactory(pModule);
int s_pClientNet = ((int (__cdecl *)(_DWORD, _DWORD))net_interface)("INetClient_003", 0);
在被初始化之后,它就是这样使用的:
int result = (*(int (__stdcall **)(int, int, int, int))(*(_DWORD *)s_pClientNet + 60))(
login,
password,
mw_account_struct,
mw_account_struct_size);
所以.. 回到结构。无论如何要恢复它,而不是通过如此疯狂的方式调用所需的函数?我的意思是(s_pClientNet + 60) 附言当然,我没有 dll 源、def 文件等,甚至不知道目标类/结构中可以包含哪些函数...... 我唯一知道的是对 s_pClientNet + 60 之类的函数的一些调用
【问题讨论】:
一些问题:你怎么知道返回的类型是一个指向结构的指针?即使您知道,它不是应该以这种方式使用(即作为不透明类型)吗? 为什么您需要获取/了解结构内容? ehm,因为返回值被用作类/结构的指针来调用像s_pClientNet + 60这样的函数,所以s_pClientNet是指向开始的指针,而60是某个函数的偏移量。 我不知道该类/结构中的所有函数,我可以看到 +60? +48 等等,还有多少人?所以我希望也许有一些方法可以重建结构字段 【参考方案1】:嗯,这看起来可能是一个 C++ 类。有一个额外的间接级别,我敢打赌它是一个 vtable。 s_pClientNet 绝对是一个指针,但 +60 发生在 取消引用它之后。 vpointers 通常是类中的第一个元素,所以这是更多的证据。基本上不可能重新创建一个编译为相同布局的 C++ 类,除非你真的很幸运。但是你可以手动管理一些片段。
typedef int(*login_fcn_t)(int, int, int, int);
struct ClientInterfaceVtable
_DWORD reserved[60];
login_fcn_t login_fcn;
;
struct ClientInterface
ClientInterfaceVtable *vpointer;
/// other fields
;
现在,将s_pClientNet
转换为ClientInterface *
后,您应该可以通过s_pClientNet->vpointer->login_fcn(login, etc.);
调用登录方法
在发现更多字段后,您总是可以尝试创建一个多态 C++ 类,并查看是否可以推送定义直到找到匹配项,但这不具有可移植性。
编辑:
嗯,我刚刚意识到代码没有传递this
指针。如果我对 vtable 没有完全错误,那么这表明这是一个静态方法,也许是某种工厂方法。
【讨论】:
Static method can't be virtual.【参考方案2】:这几乎是不可能的,AFAIK 无法保证结构的布局和对齐方式,因此每个编译器可能会以不同的方式布局结构。即使是同一个编译器也可能通过修饰符和/或编译器选项有不同的数据布局。
【讨论】:
【参考方案3】:我不知道自动识别结构的任何方法,但是如果您使用 IDA,您可以在 IDA 内部定义结构,然后更改调用签名以显式使用它(更改返回值到该结构类型并强制重新分析)。
这可能有助于您更快地分析结构并了解程序行为,但最终将主要是手动分析。
可能有一些用于 IDA/OllyDbg 的脚本可以帮助解决这个问题,因此可能值得一看 http://www.openrce.org/downloads/
【讨论】:
以上是关于有没有办法通过逆向工程来恢复结构。指向该结构的指针由 DLL 中用于导出的唯一函数返回的主要内容,如果未能解决你的问题,请参考以下文章