我尝试在x86_64 Ubuntu 16.04 LTS上的C程序下交叉编译,使用以下内容 命令:
# gcc version 5.4.0 20160609 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.4)
$ arm-linux-gnueabihf-gcc --static -g leg.c
源代码:
#include <stdio.h>
#include <fcntl.h>
int key1(){
asm("mov r3, pc\n");
}
int key2(){
asm(
"push {r6}\n"
"add r6, pc, $1\n"
"bx r6\n"
".code 16\n"
"mov r3, pc\n"
"add r3, $0x4\n"
"push {r3}\n"
"pop {pc}\n"
".code 32\n"
"pop {r6}\n"
);
}
int key3(){
asm("mov r3, lr\n");
}
int main(){
int key=0;
printf("Daddy has very strong arm! : ");
scanf("%d", &key);
if( (key1()+key2()+key3()) == key ){
printf("Congratz!\n");
int fd = open("flag", O_RDONLY);
char buf[100];
int r = read(fd, buf, 100);
write(0, buf, r);
}
else{
printf("I have strong leg :P\n");
}
return 0;
}
源代码来自pwnable.kr上的问题分支。本地编译无助于解决问题,在这里我只是想学习ARM程序集。
当我在打印并尝试输入后尝试执行它时程序挂起:Daddy has very strong arm! : <input here>
。
调试程序后,我发现在函数key2()
中执行第4~5行时会发生这种情况:
add r6, pc, $1
bx r6
运行时行为是:
; original assembly
│0x104b0 <key2> push {r7}
│0x104b2 <key2+2> add r7, sp, #0
│0x104b4 <key2+4> push {r6}
│0x104b6 <key2+6> addw r6, pc, #1
│0x104ba <key2+10> bx r6
; @0x104b4, before addw r6, pc, #1
r6 0x0 0
pc 0x104b6 0x104b6 <key2+6>
; @0x104b6, after addw r6, pc, #1
r6 0x104b9 66745
pc 0x104ba 0x104ba <key2+10>
; @0x104ba, after bx r6
r6 0x104b9 66745
pc 0x104b8 0x104b8 <key2+8>
; new assembly after bx r6
|0x104b8 <key2+8> lsls r1, r0, #24
│0x104ba <key2+10> bx r6 <-- jumps back to 0x104b8, infinite loop
在检查了其他人的解决方案之后,他们说add r6, pc, #1
和bx r6
用于从ARM模式切换到Thumb模式。 pwnable.kr提供的服务器上的应用程序运行顺畅。
我的问题是交叉编译程序挂起的原因?我做错了吗?如果它是一个bug,它是gcc进行交叉编译的bug,还是qemu-arm-static的bug?
非常感谢!
我用来调试的命令:
# in Console #1
$ qemu-arm-static -g 10101 ./a.out
# in Console #2
$ gdb-multiarch -q
gdb> file a.out
gdb> target remote :10101
修改
正如@Jester建议的那样,key2
函数是以Thumb
模式编译的。添加-marm
作为编译选项以强制执行ARM
模式。问题解决了。 More on arm-linux-gnueabi-gcc options