I try to cross-compile below C program on x86_64 Ubuntu 16.04 LTS, using following commands:
# gcc version 5.4.0 20160609 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.4)
$ arm-linux-gnueabihf-gcc --static -g leg.c
Source code:
#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;
}
The source code comes from Problem Leg on pwnable.kr. Local compilation won't help solve the problem, and here I am just trying to learn ARM assembly.
The program hangs when I try to execute it after printing and asking input: Daddy has very strong arm! : <input here>
.
After debugging the program, I find it happens when executing Line 4 ~ 5 in function key2()
:
add r6, pc, $1
bx r6
The runtime behavior is:
; 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
After checking other people's solution, they say the add r6, pc, #1
and bx r6
is for switch to Thumb mode from ARM mode. And the application on the server provided by pwnable.kr runs smoothly.
My question is why the cross-compiled program hangs? Is there I am doing wrong? If it is a bug, is it a bug from gcc doing cross-compilation, or a bug on qemu-arm-static?
Many thanks!
The command I used to debug:
# in Console #1
$ qemu-arm-static -g 10101 ./a.out
# in Console #2
$ gdb-multiarch -q
gdb> file a.out
gdb> target remote :10101
Edit
As @Jester suggests, the key2
function is compiled in Thumb
mode. Adding -marm
as compilation option to enforce ARM
mode. Problem solved. More on arm-linux-gnueabi-gcc options