Skip to content

Instantly share code, notes, and snippets.

@JamesHagerman
Last active March 30, 2023 06:43
Show Gist options
  • Save JamesHagerman/8d7bfac873fa6b0109b2e68f58d34f35 to your computer and use it in GitHub Desktop.
Save JamesHagerman/8d7bfac873fa6b0109b2e68f58d34f35 to your computer and use it in GitHub Desktop.
Some quick notes on disassembling 16bit ARM (STM32F4) code using radare2

Disassembling 1bitsy examples using radare2

Note that because radare2 uses Capstone to disassemble ARM code, there are issues with the disassembly. arm-none-eabi-objdump -d compiledbinary.elf actually does a better job in some cases. For example, msr isn't decompiled correctly...

First, you have to either strip the default ELF binaries the default Makefiles build when you run make OR you need to just compile .bin files using something like:

make binaryname.bin

Once you have a .bin file, you can then load it into radare2 and disassemble it. Keep in mind you'll need to use the following flags to configure r2 to look for ARM, 16bit, and Cortex specific opcodes (-a arm -b 16 -e asm.cpu=cortex):

r2 -a arm -b 16 -e asm.cpu=cortex miniblink.bin
> aaa (to analyze the binary)
> afl (to show the functions it's found)
> pdf @fcn.000001f8 (to show main())
> pdf @0x00000230 (to show gpio_toggle())

Then, enter Visual mode if you'd like:

> VV

And walk through the graph using the n and N keys. Use p and P to change the graph view mode!

Left image here is Radare, Right is GDB:

radare2 compared to arm-none-eabi-objdump

Disassembling ARM binary in R2 (REDUX!!)

This time, I'm trying to disassemble the Bitcrazy Crazyflie 1.0 firmware. The file is called cf1.elf.

First reason I'm trying to disassemble this is so I can run the code and have a breakpoint trigger in r2 when the code hites somewhere in this function: crtpCommanderRpytDecodeSetpoint in this file: src/modules/src/crtp_commander_rpyt.c on line 175

Second it to do the same, when any change happens to variable values inside the function crtpCommanderRpytDecodeSetpoint in the file src/modules/src/crtp_commander_rpyt.c.

This is the area of the code where I can see the setpoint variables being sent over the radio link.

GSoC work

Since I last touched this stuff, a GSoC happened in the r2 world. I'm not sure the status of that work, but if nothing else, it doesn't seem to support target extended-remote /dev/ttyACM0 which I was partially hoping someone would build.

Alas, I'll probably have to build it myself.

Attempt to Disassemble locally: PASS!

r2 -a arm -b 16 -e asm.cpu=cortex cf1.elf 
Warning: Cannot initialize dynamic strings   (oops. Not sure why this is happening...)
> aaa
> e asm.pseudo=true  (to help n0bs like me read ARM ASM)
> afl (to show the functions it's found)
> pdf @main (to show main())
> pdf @sym.crtpCommanderRpytDecodeSetpoint (to show crtpCommanderRpytDecodeSetpoint())

And that matches these similar set of gdb commands (Except that r2 is way easier to read...):

arm-none-eabi-gdb cf1.elf
(gdb) disassemble main
(gdb) disassemble crtpCommanderRpytDecodeSetpoint

Attempt to run code on STM32: OOPS!

Network hackery

Well, because r2 has issues just connecting right to /dev/ttyACM0 where the Black Magic Probe is sitting with it's own GDB server AND since we actually want to see the packets being sent out by r2 and received by the BMP, we link everything up through some command line hackery:

Note: This assumes you have the Black Magic probe on /dev/ttyACM0 (gdb extended-remote target) and /dev/ttyACM1 (UART)

stty -F /dev/ttyACM0 raw -onlcr -iexten -echo -echoe -echok -echoctl -echoke
nc -vkl -p 2000 > /dev/ttyACM0 < /dev/ttyACM0

Remember: when youre done with this hackery, run this to get a sane terminal back on /dev/ttyACM0

stty sane < /dev/ttyACM0

Actually connect r2 to the Black Magic probe

r2 -a arm -b 16 -e asm.cpu=cortex -d gdb://127.0.0.1:2000/1 cf1.elf 
> 

Once that's

@JamesHagerman
Copy link
Author

I've updated this with some notes on getting STM32F4 code decompiled correctly inside of radare.

In short, you've gotta define the asm.cpu radare2 config variables correctly otherwise some opcodes will be marked as invalid by radare2.

@JamesHagerman
Copy link
Author

Also, if you're landing here and have not yet had the enjoyment of consuming the amazing work Azeria/@azeria-labs has done on ARM assembly, it's entirely worth a read!

https://azeria-labs.com/writing-arm-assembly-part-1/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment