Created
January 29, 2016 07:11
-
-
Save fser/2f657e52be5f7f3fe350 to your computer and use it in GitHub Desktop.
Executing ARM code using Unicorn engine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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