如何逆向工程C库?

7
假设我有一个动态库(.so)在Linux上。我还有一个现有的应用程序使用该库。该库已经被剥离。我想为该库生成一些(大致的)头文件,以便我可以编写另一个使用它的程序。
使用objdump很容易看到库中有哪些函数,并使用ltrace查看每次调用时的情况。
如何找出函数参数?
一些想法:我可以使用LD_PRELOAD或dlsym类型的技巧来加载一个假库,该假库在调用原始库中的任何函数时都会查看堆栈。我也可以在交换机中执行某些操作,以转储寄存器(这是在ARM上,所以我想应该是r0-r3)。通过更多的工作(通过查看反汇编),可能还可以弄清楚寄存器是否包含将被取消引用的指针,然后让交换机函数转储该指针处的内容。
从那里到“该函数以以下字段的结构体指针作为其第一个参数...”似乎是一个很大的步骤。是否有自动化工具可用于此类事情?
注意:我对函数的运行方式不感兴趣,只想知道如何为它们提供正确的数据。

1
我认为这个任务无法有效地自动化。你几乎肯定需要深入函数实现,查看每个参数的使用方式,并参考相关的ABI规范将“int32 in r0,指向[sp-8]处的内容的指针”映射到C函数签名。 - user395760
@delnan: 那种事情似乎可以通过脚本完成,不是吗?至少一个对ABI和汇编解析十分聪明的脚本。 (此外,它可以使用运行应用程序的数据:其中可能包括函数读取或写入的确切内存字节 :) - Alex I
1个回答

4
一个不错的起点是使用诸如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也不能自动检测到每个信息,因为它取决于许多因素,可能非常困难 :)

1
如果您想尝试自己编写一个类似于您描述的脚本,我建议使用带有Python绑定的capstone-engine库。 - japedo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接