1

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

Community
  • 1
  • 1
Xin
  • 1,300
  • 2
  • 14
  • 27
  • 1
    Apparently you compiled the `key2` function as thumb code, when it was expected to be arm. – Jester Feb 24 '17 at 01:51
  • @Jester Yes, that seems to be the case. Do you know how should I compiled `key2` as arm code? – Xin Feb 24 '17 at 01:55
  • Try `-mno-thumb` (no idea what your gcc defaults to, mine defaults to arm) – Jester Feb 24 '17 at 01:56
  • 1
    @Jester Thank you very much. I did the trick using `-marm`. The gcc I use doesn't recognize `-mno-thumb`. – Xin Feb 24 '17 at 02:03

0 Answers0