我想了解有关Unix / Linux的更多信息,这个问题浮现在脑海-假设我制作了一个静态/动态库(.a或.so),并丢失了c / c源代码和头文件.默认的nm输出为我提供了符号的名称,但是我需要知道返回类型和参数计数/类型才能创建标头.是否有可能以某种方式获得这些额外信息,从而对给定库的标头进行反向工程?
解决方法:
您标记了C和C,两者之间的答案略有不同.
对于C,类的方法名称在符号名称中嵌入类型信息.您只需要弄清楚编译该库的编译器是如何处理名称的.
对于C,没有真正干净的方法.您可以拆开汇编并分析要读取的寄存器和堆栈区域,而无需编写代码即可确定函数需要多少个参数.这将需要了解任何编译该库的编译器使用的调用约定.
同样,您可以查看程序集中如何使用每个参数.如果看到它在装入指令中使用,则很可能是某种指针,而如果看到它在算术中使用,则可能是某种整数.
对于返回类型,您可以检查在返回指令之前是否将任何看似有意义的东西放置在返回寄存器中.同样,这需要了解平台的调用约定.
这是我如何在ARM汇编中执行操作的示例.
我知道ARM中的参数在寄存器r0到r3中传递,并且返回值存储在寄存器r0中.考虑到这一点,我们可以开始逆向工程.让我们看一下两个函数的汇编,并尝试找出函数原型是什么.
00000000 <func1>:
0: e3510000 cmp r1, #0
4: 0a000007 beq 28 <func1+0x28>
8: e0801001 add r1, r0, r1
c: e1a03000 mov r3, r0
10: e3a00000 mov r0, #0
14: e4d32001 ldrb r2, [r3], #1
18: e1530001 cmp r3, r1
1c: e0800002 add r0, r0, r2
20: 1afffffb bne 14 <func1+0x14>
24: e12fff1e bx lr
28: e1a00001 mov r0, r1
2c: e12fff1e bx lr
如果我们在这里看一下,则在将任何内容写入之前先读取r0和r1.我们还可以看到在读取r2和r3之前将其写入.因此,我们可以推断出func1最多具有两个参数.
我们还意识到将r0移至r3,然后用作ldrb的地址,这是从内存中加载字节的指令.因此,我们推断出第一个参数是一个指针.由于该指令仅加载单个字节,因此我们也可以告诉它可能是某种某种类型的单字节数据类型的指针.
r1中的第二个参数似乎从未使用过,除非在compare和add指令中使用,因此它可能是整数.
在每个bx lr(返回调用者的指令)之前,在r0中放置了一些内容,因此我们推断该函数返回某种值.
如果将这个函数提供给我,我猜想函数原型看起来像这样:
int func1(unsigned char *, int);
原版的:
unsigned int func1(void *, unsigned int);
这是另一个功能
00000030 <func2>:
30: e0822001 add r2, r2, r1
34: e5c02000 strb r2, [r0]
38: e12fff1e bx lr
这个很简单.
我们看到r0,r1和r2都在被写入之前已被读取,因此我们可以猜测该函数具有三个参数. r0用作strb指令(存储字节)的地址,因此它很可能是指针.同样,它仅存储一个字节,因此它可能是指向字节大小的数据类型的指针.
其他两个仅在加法指令中使用,因此可能是整数.
在r0的末尾似乎没有任何内容,因此该函数要么返回第一个参数,要么不返回值.
我想原型会是以下之一
void func2(unsigned char *, int, int);
unsigned char *func2(unsigned char *, int, int);
原版的:
void func2(char *, char, char);
标签:unix,c-3,linux,c-4 来源: https://codeday.me/bug/20191123/2064993.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。