我刚刚设置了一个覆盆子pi机器,并尝试对以下代码进行逆向工程。
#include<stdio.h>
int main() {
printf("this is a test\n");
}
在大多数情况下,gdb中的以下反汇编似乎都有意义。
0x000083c8 <+0>: push {r11, lr}
0x000083cc <+4>: add r11, sp, #4
0x000083d0 <+8>: ldr r0, [pc, #8] ; 0x83e0 <main+24>
0x000083d4 <+12>: bl 0x82ec <puts>
0x000083d8 <+16>: mov r0, r3
0x000083dc <+20>: pop {r11, pc}
0x000083e0 <+24>: andeq r8, r0, r4, asr r4
0x000083e0
处的指令存在。那条指令甚至是主要功能的一部分吗?不会将在0x000083c8处推送的值弹出到pc中,立即将控制转移到其他位置吗?答案 0 :(得分:3)
当调用此函数时(即从指令0x000083c8
开始执行时),链接寄存器(LR)应该已经包含返回地址。快进到0x000083d8
: puts 函数的返回结果根据ARM C调用约定(link,link)放在R0中。然后,返回地址从堆栈弹出到PC中 - 有效地结束了该函数的执行。这意味着0x000083e0
处的说明不属于您的计划的一部分,您的检查应仅限于0x000083c8
到0x000083dc
的说明。
所以回答你的问题:
0x000083e0
处的“指令”基本上是垃圾。您可能甚至没有对此内存的执行和/或访问权限,具体取决于您的ARM内核的具体情况(它是否有MMU等?)。因此,当试图检查该位置时,seg故障是合理的结果。编辑:与下面的评论一致,0x000083e0
的内容应解释为数据,而不是说明。
答案 1 :(得分:2)
0x000083e0处的四个字节不是垃圾。它是
的PC相对负载的一部分0x000083d0 <+8>: ldr r0, [pc, #8] ; 0x83e0 <main+24>
它在评论中也显示为; 0x83e0 <main+24>
。
此处出现问题,因为您需要将字符串的地址传递给puts
,其地址可能在链接步骤中发生变化,编译器需要为此类进一步处理创建合适的代码。因此,字符串的地址在指令流中结束,但在任何执行上下文之外。