mercredi 8 janvier 2014

How to debug ARM binary under x86 linux box

I'm having fun solving challenges from the root-me website. I work from a linux box. As most challenges are made for linux/x86, this is not a problem.

But there are some chall made for linux/ARM:

mitsurugi@mitsu:~/chall/R$ uname -a
Linux mitsu 3.2.0-4-686-pae #1 SMP Debian 3.2.51-1 i686 GNU/Linux
mitsurugi@mitsu:~/chall/R$ file chall9.bin
chall9.bin: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, for GNU/Linux 2.6.16, not stripped

And I didn't want to install an ARM system. So I used qemu and gdb. How does it works:

First, you have to install gdb-multiarch:
mitsurugi@mitsu:~/chall/R$ apt-cache search gdb-multiarch
gdb-multiarch - The GNU Debugger (with support for multiple architectures)

Then, launch qemu-arm from one-side with the gdb server internal function, and from another side, gdb-multiarch:
mitsurugi@mitsu:~/chall/mitsu/R$ qemu-arm -g 1234 ./chall9.bin

And from another terminal with gdb-multiarch, you have to load the same file (chall9.bin), set architecture to arm and finally connect to the gdb server:

mitsurugi@mitsu:~/chall/R$ gdb-multiarch -q -nx
(gdb) file chall9.bin
Reading symbols from /home/mitsurugi/chall/R/chall9.bin...done.
(gdb) set architecture arm
The target architecture is assumed to be arm
(gdb) target remote
Remote debugging using
[New Remote target]
[Switching to Remote target]
0x00008150 in _start ()
(gdb) disass main
Dump of assembler code for function main:
   0x00008290 <+0>:    mov    r12, sp
   0x00008294 <+4>:    push    {r4, r11, r12, lr, pc}
   0x00008298 <+8>:    sub    r11, r12, #4
   0x0000829c <+12>:    sub    sp, sp, #36    ; 0x24
   0x000082a0 <+16>:    str    r0, [r11, #-40]    ; 0x28
   0x000082a4 <+20>:    str    r1, [r11, #-44]    ; 0x2c
   0x000082a8 <+24>:    ldr    r3, [r11, #-40]    ; 0x28
   0x000082ac <+28>:    cmp    r3, #1
   0x000082b0 <+32>:    bgt    0x82c0 <main+48>
   0x000082b4 <+36>:    mvn    r3, #0
   0x000082b8 <+40>:    str    r3, [r11, #-48]    ; 0x30
   0x000082bc <+44>:    b    0x8448 <main+440>
   0x000082c0 <+48>:    mov    r3, #0
   0x000082c4 <+52>:    str    r3, [r11, #-28]
   0x000082c8 <+56>:    mov    r0, #32
   0x000082cc <+60>:    bl    0x8248 <xmalloc>
   0x000082d0 <+64>:    mov    r3, r0
   0x000082d4 <+68>:    str    r3, [r11, #-32]
   0x000082d8 <+72>:    b    0x832c <main+156>
   0x000082dc <+76>:    ldr    r3, [r11, #-28]

Ok, time to learn some ARM assembly :-)

3 commentaires:

  1. elango@ubuntu:~/practice$ qemu-arm -version
    qemu-arm version 2.0.0 (Debian 2.0.0+dfsg-2ubuntu1.11), Copyright (c) 2003-2008 Fabrice Bellard
    elango@ubuntu:~/practice$ file Test
    Test: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), BuildID[md5/uuid]=e9607f8a8db3aced5eb230400beb0f85, not stripped
    elango@ubuntu:~/practice$ qemu-arm -g 1234 ./Test
    /usr/lib/ No such file or directory

  2. Never too late than never for an answer.

    It doesn't work because you have a dynamically linked binary. So, the binary try to find the linker file in order to resolve symbols. And in your x86 file hierarchy, you don't have a /usr/lib/ file, so qemu stops.

    Two solutions:
    -use static binaries only
    -use the -L flags of qemu which makes a kind of "soft" chroot for the Library research path

  3. I asked the dynamic linked case at: