Skip to content

Instantly share code, notes, and snippets.

@fser
Created January 29, 2016 07:11
Show Gist options
  • Save fser/2f657e52be5f7f3fe350 to your computer and use it in GitHub Desktop.
Save fser/2f657e52be5f7f3fe350 to your computer and use it in GitHub Desktop.
Executing ARM code using Unicorn engine
#!/usr/bin/env python
# based on sample_arm.py in Unicorn engine's sourcetree.
from __future__ import print_function
from unicorn import *
from unicorn.arm_const import *
from struct import pack, unpack
def objdump2dic(dump):
inst = []
for line in dump.split('\n'):
if '' == line or '>:' in line:
next
else:
dic = dict(zip(('addr', 'inst', 'human'), line.split(None,2)))
dic['addr'] = int(dic['addr'].replace(':',''), 16)
dic['inst'] = int(dic['inst'], 16)
inst.append(dic)
return inst
prog = objdump2dic('''00000000 <fact-0x4>:
0: e3a01001 mov r1, #1
00000004 <fact>:
4: e0010190 mul r1, r0, r1
8: e2400001 sub r0, r0, #1
c: e3500001 cmp r0, #1
10: 0a000000 beq 18 <done>
14: eafffffa b 4 <fact>
00000018 <done>:
18: e7f000f0 udf #0
''')
for inst in prog:
ARM_CODE += pack('<I', inst['inst'])
# equivalent
# other = ''.join(map(lambda x : pack('<I', x['inst']), prog))
# callback used to stop emulation
def hook_code(uc, address, size, user_data):
if (address == 0x18):
uc.emu_stop()
# Test ARM
def test_arm():
print("Emulate ARM code")
try:
# Initialize emulator in ARM mode
mu = Uc(UC_ARCH_ARM, UC_MODE_ARM)
# map 2MB memory for this emulation from 0x000000
mu.mem_map(0, 2 * 1024 * 1024)
# write machine code to be emulated to memory
mu.mem_write(ADDRESS, ARM_CODE)
# initialize machine registers
mu.reg_write(UC_ARM_REG_R0, 4)
mu.reg_write(UC_ARM_REG_R1, 0x0)
# tracing all instructions with customized callback
mu.hook_add(UC_HOOK_CODE, hook_code)
# emulate machine code in infinite time
mu.emu_start(ADDRESS, ADDRESS + len(ARM_CODE))
# now print out some registers
print(">>> Emulation done. Below is the CPU context")
r0 = mu.reg_read(UC_ARM_REG_R0)
r1 = mu.reg_read(UC_ARM_REG_R1)
print(">>> R0 = 0x%x" %r0)
print(">>> R1 = 0x%x" %r1)
except UcError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
print ('\n'.join(map(lambda e : e['human'], prog)))
test_arm()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment