Skip to content

Instantly share code, notes, and snippets.

@DavidBuchanan314
Last active April 10, 2022 23:39
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save DavidBuchanan314/37c3f55bd4d5f9f66d952e38c71ecbba to your computer and use it in GitHub Desktop.
Save DavidBuchanan314/37c3f55bd4d5f9f66d952e38c71ecbba to your computer and use it in GitHub Desktop.
# based on https://github.com/unicorn-engine/unicorn/blob/master/bindings/python/sample_arm.py
from __future__ import print_function
from unicorn import *
from unicorn.arm_const import *
# https://github.com/raspberrypi/pico-bootrom/blob/ef22cd8ede5bc007f81d7f2416b48db90f313434/bootrom/bootrom_rt0.S#L441-L445
CODE = bytes.fromhex("""
.byte 0x11, 0x38, 0xc0, 0x7a, 0x00, 0xbd, 0x00, 0xb5
.byte 0x42, 0x40, 0x00, 0x2a, 0x00, 0xf0, 0x02, 0xf8
.byte 0xf6, 0xd2, 0x8e, 0x46, 0x70, 0x46, 0x00, 0x47
""".replace(".byte", "").replace("0x", "").replace(",", ""))
"""
Disassembly:
00: 11 38 subs r0, #0x11
02: C0 7A ldrb r0, [r0, #0xb]
04: 00 BD pop {pc}
06: 00 B5 push {lr} <--- entrypoint
08: 42 40 eors r2, r0
0a: 00 2A cmp r2, #0
0c: 00 F0 02 F8 bl #0x14
10: F6 D2 bhs #0
12: 8E 46 mov lr, r1
14: 70 46 mov r0, lr
16: 00 47 bx r0
"""
# memory address where emulation starts
ADDRESS = 0x100000
# callback for tracing basic blocks
def hook_block(uc, address, size, user_data):
print(">>> Tracing basic block at 0x%x, block size = 0x%x" %(address, size))
# callback for tracing instructions
def hook_code(uc, address, size, user_data):
print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" %(address, size))
def test_thumb():
print("Emulate THUMB code")
try:
# Initialize emulator in thumb mode
mu = Uc(UC_ARCH_ARM, UC_MODE_THUMB)
# map 2MB memory for this emulation
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
# write machine code to be emulated to memory
mu.mem_write(ADDRESS, CODE)
# initialize machine registers
mu.reg_write(UC_ARM_REG_SP, ADDRESS + 0x1000)
# tracing all basic blocks with customized callback
mu.hook_add(UC_HOOK_BLOCK, hook_block)
# tracing all instructions with customized callback
mu.hook_add(UC_HOOK_CODE, hook_code)
# emulate machine code in infinite time
# Note we start at ADDRESS | 1 to indicate THUMB mode.
try:
mu.emu_start((ADDRESS + 6) | 1, ADDRESS + len(CODE))
except:
# we'll get a segfault when the function tries to return to a nonexistent address
# (could be solved by pushing a real address onto the stack first)
pass
# now print out some registers
print(">>> Emulation done. Below is the CPU context")
r0 = mu.reg_read(UC_ARM_REG_R0)
print(">>> r0 = %u" % r0)
except UcError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_thumb()
"""
Output:
Emulate THUMB code
>>> Tracing basic block at 0x100006, block size = 0xa
>>> Tracing instruction at 0x100006, instruction size = 0x2
>>> Tracing instruction at 0x100008, instruction size = 0x2
>>> Tracing instruction at 0x10000a, instruction size = 0x2
>>> Tracing instruction at 0x10000c, instruction size = 0x4
>>> Tracing basic block at 0x100014, block size = 0x4
>>> Tracing instruction at 0x100014, instruction size = 0x2
>>> Tracing instruction at 0x100016, instruction size = 0x2
>>> Tracing basic block at 0x100010, block size = 0x2
>>> Tracing instruction at 0x100010, instruction size = 0x2
>>> Tracing basic block at 0x100000, block size = 0x6
>>> Tracing instruction at 0x100000, instruction size = 0x2
>>> Tracing instruction at 0x100002, instruction size = 0x2
>>> Tracing instruction at 0x100004, instruction size = 0x2
>>> Emulation done. Below is the CPU context
>>> r0 = 42
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment