Created
June 2, 2016 03:37
-
-
Save mattypiper/d4d90bc5b8fb9a56fa2d4f2383a2eda7 to your computer and use it in GitHub Desktop.
ARM Assembly, Emulation, Disassembly using Keystone, Unicorn, and Capstone
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/python | |
import sys | |
from keystone import * | |
from unicorn import * | |
from unicorn.arm_const import * | |
from capstone import * | |
from capstone.arm import * | |
from capstone.x86 import * | |
# architectures and modes for the assembler, disassembler, and emulator | |
ks_arch = KS_ARCH_ARM | |
ks_mode = KS_MODE_THUMB | |
cs_arch = CS_ARCH_ARM | |
cs_mode = CS_MODE_THUMB | |
emu_arch = UC_ARCH_ARM | |
emu_mode = UC_MODE_THUMB | |
# declare assembler, disassembler, and emulator objects | |
ks = Ks(ks_arch, ks_mode) | |
cs = Cs(cs_arch, cs_mode) | |
cs_arm = Cs(cs_arch, CS_MODE_ARM) | |
emu = Uc(emu_arch, emu_mode) | |
# the program | |
code = 'eors r0, r0;' | |
code += 'adds r0, #0x42;' | |
code += 'mov r1, #0x1111;' | |
code += 'movt r1, #0x1111;' | |
code += 'mov r2, #0x2222;' | |
code += 'movt r2, #0x2222;' | |
code += 'push {r0, r1, r2};' | |
code += 'pop {r3};' | |
# callback for tracing instructions | |
def hook_code(uc, address, size, user_data): | |
#global cs | |
#print 'address = 0x{:x}, size = {}'.format(address, size) | |
code = uc.mem_read(address, size) | |
code = ''.join(map(chr, code)) | |
asm = list(cs.disasm(code, size)) | |
if len(asm) == 0: | |
print '>>> 0x{:x}\t{}\tdisasm failure'.format(address, code.encode('hex')) | |
for ins in asm: | |
print '>>> 0x{:x}\t{}\t{} {}'.format(address, code.encode('hex'), ins.mnemonic, ins.op_str) | |
def hook_intr(uc, intno, user_data): | |
print 'Interrupt 0x{:x}'.format(intno) | |
def dumpSimple(mu): | |
sp = mu.reg_read(UC_ARM_REG_SP) | |
pc = mu.reg_read(UC_ARM_REG_PC) | |
lr = mu.reg_read(UC_ARM_REG_LR) | |
r0 = mu.reg_read(UC_ARM_REG_R0) | |
r1 = mu.reg_read(UC_ARM_REG_R1) | |
r2 = mu.reg_read(UC_ARM_REG_R2) | |
r3 = mu.reg_read(UC_ARM_REG_R3) | |
print 'SP = 0x{:08x}'.format(sp) | |
print 'PC = 0x{:08x}'.format(pc) | |
print 'LR = 0x{:08x}'.format(lr) | |
print 'R0 = 0x{:08x}'.format(r0) | |
print 'R1 = 0x{:08x}'.format(r1) | |
print 'R2 = 0x{:08x}'.format(r2) | |
print 'R3 = 0x{:08x}'.format(r3) | |
def dumpMem(mu, addr, size): | |
x = mu.mem_read(addr, size) | |
x = ''.join(map(chr, x)) | |
wrap = 16 | |
group = 4 | |
for i in xrange(0, len(x), wrap): | |
k = i + wrap if i + wrap < len(x) else len(x) | |
sys.stdout.write('0x{:x} | '.format(addr+i)) | |
for j in xrange(i, k): | |
sys.stdout.write('{}'.format(x[j].encode('hex'))) | |
if j % group == group-1: sys.stdout.write(' ') | |
sys.stdout.write('\n') | |
# assemble the program | |
thumb_code, count = ks.asm(code) | |
# convert list to str for emulator | |
thumb_code = ''.join(map(chr, thumb_code)) | |
# emulator setup | |
emu.hook_add(UC_HOOK_CODE, hook_code) | |
emu.hook_add(UC_HOOK_INTR, hook_intr) | |
text_base = 0x1000 | |
text_size = 0x1000 | |
stack_base = 0xf000 | |
stack_size = 0x1000 | |
emu.mem_map(text_base, text_size) | |
emu.mem_write(text_base, thumb_code) | |
emu.mem_map(stack_base, stack_size) | |
emu.mem_write(stack_base, '\x00'*stack_size) | |
# initialize registers | |
emu.reg_write(UC_ARM_REG_SP, stack_base + 0xff0) | |
emu.reg_write(UC_ARM_REG_R0, 0x1234) | |
emu.reg_write(UC_ARM_REG_R1, 0x5678) | |
emu.reg_write(UC_ARM_REG_R2, 0xdead) | |
emu.reg_write(UC_ARM_REG_R3, 0xbeef) | |
emu.reg_write(UC_ARM_REG_R4, 0xcafe) | |
emu.reg_write(UC_ARM_REG_R5, 0xbabe) | |
emu.reg_write(UC_ARM_REG_R6, 0x1337) | |
emu.reg_write(UC_ARM_REG_R7, 0xfeed) | |
emu.reg_write(UC_ARM_REG_R8, 0xface) | |
emu.reg_write(UC_ARM_REG_R9, 0xbaad) | |
emu.reg_write(UC_ARM_REG_R10, 0xd00d) | |
emu.reg_write(UC_ARM_REG_R11, 0xcaa7) | |
print '--- Start context ---' | |
dumpSimple(emu) | |
dumpMem(emu, stack_base + 0xfd0, 0x20) | |
print '\nStarting emulator...' | |
emu.emu_start(text_base, text_base + len(thumb_code)) | |
print '\n--- End context ---' | |
dumpSimple(emu) | |
print '\n--- Stack View ---' | |
dumpMem(emu, stack_base + 0xfd0, 0x20) | |
print '\n--- Dead listing ---' | |
asm = list(cs.disasm(thumb_code, len(thumb_code))) | |
for ins in asm: | |
print '>>> {} {}'.format(ins.mnemonic, ins.op_str) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Output: