有没有办法通过逆向工程来恢复结构。指向该结构的指针由 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 中用于导出的唯一函数返回的主要内容,如果未能解决你的问题,请参考以下文章

结构体指针在使用完free后,该指针所指向的内存区域是啥,这个指针是变成了NULL,还是野指针。

使用指向结构数组的指针不会返回完整的数组

C语言 指向结构体变量的指针

数据结构 | SkipList(跳表)

程序的错误输出,使用指向结构数组的指针

C语言数据结构——链表