Issue
I'm hoping someone can help me determine why this binary won't execute.
It is a closed-source, stripped ARM binary. That said, it is freely downloadable on the internet so there is a link to it at the bottom of this post.
The target is an ARM binary pulled from a firmware image. I have set up an ARM VM, but have also tried running the binary on a Pi with the same result.
Here is what I'm seeing:
root@debian-armel:/tmp/squashfs-root/usr/bin# ./my_arm_bin
Illegal instruction
That "Illegal instruction" error is not super helpful... so I dug in a little deeper.
My VM
I don't think the problem is my VM. It is a pretty standard ARM VM setup. From: https://people.debian.org/~aurel32/qemu/armel/
Using debian_squeeze_armel_standard.qcow2, initrd.img-2.6.32-5-versatile, and vmlinuz-2.6.32-5-versatile. It is launched with QEMU with a few ports forwarded (ssh,http,31337 for gdb stuff). I am able to execute other ARM binaries on the system without issue, including other binaries pulled from the same firmware image.
Also, as mentioned before I've tried dropping the binary onto a Pi with no luck. I tried both as root on the pi, as well as in a chroot'ed environment with the rootfs of the extracted firmware image, same result: Illegal Instruction.
r2 Info
rabin2 -I my_arm_bin:
Warning: Cannot initialize dynamic strings
arch arm
binsz 44831825
bintype elf
bits 32
canary false
class ELF32
crypto false
endian little
havecode true
lang c
linenum false
lsyms false
machine ARM
maxopsz 16
minopsz 1
nx false
os linux
pcalign 0
pic false
relocs false
rpath NONE
static true
stripped true
subsys linux
va true
Additional Debugging (gdb w/ gef on Pi)
So, time to attach a debugger and see exactly what instruction is actually throwing that error. This was done on a Pi.
After starting up and breaking on entry, using ni to single step, I see:
gef> x/20i $pc
=> 0x796a0: mov r11, #0
0x796a4: mov lr, #0
0x796a8: pop {r1} ; (ldr r1, [sp], #4)
0x796ac: mov r2, sp
0x796b0: push {r2} ; (str r2, [sp, #-4]!)
0x796b4: push {r0} ; (str r0, [sp, #-4]!)
0x796b8: ldr r12, [pc, #16] ; 0x796d0
0x796bc: push {r12} ; (str r12, [sp, #-4]!)
0x796c0: ldr r0, [pc, #12] ; 0x796d4
0x796c4: ldr r3, [pc, #12] ; 0x796d8
0x796c8: bl 0x4021a0
0x796cc: bl 0x401fa0
0x796d0: andeq r2, r12, #200, 2 ; 0x32
0x796d4: andeq r10, r1, r12, lsl #11
0x796d8: andeq r2, r12, #40, 2
0x796dc: ldr r3, [pc, #20] ; 0x796f8
0x796e0: ldr r2, [pc, #20] ; 0x796fc
0x796e4: add r3, pc, r3
0x796e8: ldr r2, [r3, r2]
0x796ec: cmp r2, #0
gef>
It all looks like valid ARM instructions.
In case it's relevant - All ldr instructions (0x796b8, 0x796c0, 0x796c4) in gdb are giving this message when executed: Cannot access memory at address 0x0. Some mov instructions throw this too.
At 0x796c8: bl 0x4021a0:
-> 0x796c8 bl 0x4021a0
\-> 0x4021a0 ldr pc, [pc, #-4] ; 0x4021a4
And eventually we get here:
gef> x/20i $pc
=> 0x20c1b30: push {r4, r5, r6, r7, lr}
0x20c1b34: sub sp, sp, #300 ; 0x12c
0x20c1b38: movw r12, #0
0x20c1b3c: mov r5, r3 --> Here is our illegal instruction
0x20c1b40: movt r12, #0
0x20c1b44: str r1, [sp, #4]
0x20c1b48: movw r1, #65336 ; 0xff38
0x20c1b4c: cmp r12, #0
0x20c1b50: ldr r3, [sp, #4]
0x20c1b54: str r2, [sp, #8]
0x20c1b58: ldrne r12, [r12]
0x20c1b5c: add r2, r3, #1
0x20c1b60: str r0, [sp, #12]
0x20c1b64: movw r3, #56376 ; 0xdc38
0x20c1b68: ldr r7, [sp, #8]
0x20c1b6c: movw r0, #3092 ; 0xc14
0x20c1b70: ldr lr, [sp, #328] ; 0x148
0x20c1b74: clzne r12, r12
0x20c1b78: movt r0, #685 ; 0x2ad
0x20c1b7c: movt r1, #827 ; 0x33b
And of course a copy of the binary can be found here: https://mega.nz/#!CKxBQKaI!T__d9pjpOn_rPtfvPNkkPsFWHTjg7u-vDt5AK6610ug
So are the registers just not initialized to the right values? How can that be possible?
To paraphrase from Archer: What am I not getting?... I think the core concept.
I am probably missing a critical idea here. I'm hoping someone can help fill in the blank(s).
UPDATE 1:
At @0xC0000022L suggestion I looked into making sure the ARM revision of my VM/Pi matches that of the binary. As far as I can tell they do. Just comparing a binary from the VM to my my ARM binary I'm trying to get running their ABIs match (32-bit ARMv5):
$ file my_arm_bin
my_arm_bin: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.16, stripped
$ file /usr/bin/id
/usr/bin/id: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.32, stripped
UPDATE 2:
At @perror suggestion I tried forcing the binary to execute in thumb mode. For context here is the disassembly when running in "arm" (non-thumb) mode:
gef> x/10i $pc
=> 0x20c1b38: movw r12, #0
0x20c1b3c: mov r5, r3
0x20c1b40: movt r12, #0
0x20c1b44: str r1, [sp, #4]
0x20c1b48: movw r1, #65336 ; 0xff38
0x20c1b4c: cmp r12, #0
0x20c1b50: ldr r3, [sp, #4]
0x20c1b54: str r2, [sp, #8]
0x20c1b58: ldrne r12, [r12]
0x20c1b5c: add r2, r3, #1
Forcing thumb mode, I now see:
gef> set arm force-mode thumb
gef> x/10i $pc
=> 0x20c1b38: stmia r0!, {}
0x20c1b3a: b.n 0x20c213e
0x20c1b3c: str r3, [r0, r0]
0x20c1b3e: b.n 0x20c1e82
0x20c1b40: stmia r0!, {}
0x20c1b42: b.n 0x20c21c6
0x20c1b44: asrs r4, r0, #32
0x20c1b46: b.n 0x20c1664
0x20c1b48: subs r0, r7, #4
0x20c1b4a: b.n 0x20c216c
Forcing thumb mode prior to execution, the program exits immediately with the following error:
[!] Cannot disassemble from $PC
[!] Cannot access memory at address 0x6ac
Starting the executable up, breaking and switching modes exits with an Illegal instruction error.

gdb. But, what if the CPU was executing in thumb mode ? To check, you might also simply execute the program throughsi(stepi) commands until crash. It might give you a more insightful error message. – perror Jun 19 '18 at 07:01nito step through instructions.Thank you @perror and @0xC0000022L - Your insight is much appreciated. I'm going to dig into thumb mode and ARM revision later today and will post and update. I was using
– gatorface Jun 19 '18 at 14:15nito skip function calls and keep it simple, butsimay give me some more context.nito single step, and separated my problem statement for clarity – gatorface Jun 19 '18 at 15:39