如何对C库进行逆向工程?
Posted
技术标签:
【中文标题】如何对C库进行逆向工程?【英文标题】:How to reverse engineer C library? 【发布时间】:2014-02-22 18:52:13 【问题描述】:假设我在 Linux 上有一个动态库 (.so)。我还有一个使用该库的现有应用程序。图书馆被剥离。我想为库生成一些(近似的)头文件,以便我可以编写另一个使用它的程序。
使用 objdump 查看库中的函数很容易,使用 ltrace 查看每个调用都非常简单。
如何确定函数参数是什么?
一些想法:我可能会使用 LD_PRELOAD 或 dlsym 类型技巧来加载一个 shim 库,该库在原始库中调用任何函数时都会查看堆栈。我也可以在转储寄存器的 shim 中做一些事情(这是在 ARM 上,所以我想它是 r0-r3)。通过更多的工作(通过查看反汇编),可能还可以确定寄存器是否包含将被取消引用的指针,然后让 shim 函数转储该指针处的内容。
似乎从那里迈出了一大步,“这个函数将指向具有以下字段的结构的指针作为其第一个参数......”是否有任何自动化工具可用于此类事情?
注意:我对函数的工作原理完全不感兴趣,只对如何为它们提供正确的数据感兴趣。
【问题讨论】:
我认为这不能有效地自动化。您几乎肯定必须深入研究函数实现以查看每个参数的使用方式,并查阅相关的 ABI 规范以将“r0 中的 int32,指向 [sp-8] 处的内容的指针”映射到 C 函数签名。 @delnan:那种东西听起来像是脚本可以做到的,不是吗?至少是一个非常聪明的关于 ABI 和解析程序集的脚本。 (此外,它可以使用来自运行应用程序的数据:其中可能包括,例如,某个函数读取或写入了哪些确切的内存字节:) 【参考方案1】:一个好的开始是反汇编程序,例如 Objdump、HopperApp 或 IDA Pro。后者会自动检测非特殊情况的参数。
如果您想自己了解这是如何工作的,我会查找不同的“调用约定”(***是一个好的开始)。
__stdcall 的示例:假设您有 x86 .so 库,并且在二进制文件中会发生类似的情况:
push 3
push 2
push 1
call func ; void func(int a, int b, int c) where a=1, b=2 and c=3
参数以相反的顺序被压入堆栈。 EAX、ECX 和 EDX 可以在函数内部使用(由调用者保存),其他寄存器必须从函数本身显式保存(由被调用者保存)。 这并没有告诉您有关参数背后的数据类型的任何信息。这通常需要更多的逆向来解决。
即使是 IDA Pro 也不会自动检测所有信息,因为它取决于很多因素并且可能非常困难 :)
【讨论】:
如果你想尝试像你自己描述的那样的脚本,我会推荐一个库,比如带有 python 绑定的 capstone-engine。以上是关于如何对C库进行逆向工程?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 iOS 私有 api 二进制文件中获取标头和函数?如何对应用程序进行逆向工程?