diff options
| author | Rusty Wagner <rusty.wagner@gmail.com> | 2024-03-05 19:50:13 -0500 |
|---|---|---|
| committer | Rusty Wagner <rusty.wagner@gmail.com> | 2024-03-05 20:34:34 -0500 |
| commit | e093c21ed880ac3eb72119be15093ee04f8ce299 (patch) | |
| tree | 9f720ebdc0ae415734b1199ed341668c69710a94 /arch/armv7/test_lift.py | |
| parent | 0609276712622908254065546102381466033141 (diff) | |
Move architecture modules into the API repo
Diffstat (limited to 'arch/armv7/test_lift.py')
| -rwxr-xr-x | arch/armv7/test_lift.py | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/arch/armv7/test_lift.py b/arch/armv7/test_lift.py new file mode 100755 index 00000000..2e12dbe4 --- /dev/null +++ b/arch/armv7/test_lift.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python + +test_cases = \ +[ + # umaal r0, r1, r2, r3 + ('A', b'\x92\x03\x41\xe0', 'LLIL_SET_REG_SPLIT.d(r1,r0,LLIL_ADD.q(LLIL_MULU_DP.d(LLIL_REG.d(r3),LLIL_REG.d(r2)),LLIL_ADD.q(LLIL_REG.d(r1),LLIL_REG.d(r0))))'), + # umlal r0, r1, r2, r3 + ('A', b'\x92\x03\xa1\xe0', 'LLIL_SET_REG_SPLIT.d(r1,r0,LLIL_ADD.q(LLIL_MULU_DP.d(LLIL_REG.d(r3),LLIL_REG.d(r2)),LLIL_REG_SPLIT.d(r1,r0)))'), + # umlals r0, r1, r2, r3 + ('A', b'\x92\x03\xb1\xe0', 'LLIL_SET_REG_SPLIT.d{nz}(r1,r0,LLIL_ADD.q(LLIL_MULU_DP.d(LLIL_REG.d(r3),LLIL_REG.d(r2)),LLIL_REG_SPLIT.d(r1,r0)))'), + # umulls r0, r1, r2, r3 + ('A', b'\x92\x03\x81\xe0', 'LLIL_SET_REG_SPLIT.d(r1,r0,LLIL_MULU_DP.d(LLIL_REG.d(r2),LLIL_REG.d(r3)))'), + # smull r0, r1, r2, r3 + ('A', b'\x92\x03\xc1\xe0', 'LLIL_SET_REG_SPLIT.d(r1,r0,LLIL_MULS_DP.d(LLIL_REG.d(r2),LLIL_REG.d(r3)))'), + # teq r0, #0 + ('A', b'\x00\x00\x30\xe3', 'LLIL_XOR.d{cnz}(LLIL_REG.d(r0),LLIL_CONST.d(0x0))'), + # teq r1, #1 + ('A', b'\x01\x00\x31\xe3', 'LLIL_XOR.d{cnz}(LLIL_REG.d(r1),LLIL_CONST.d(0x1))'), + # teq r2, #2 + ('A', b'\x02\x00\x32\xe3', 'LLIL_XOR.d{cnz}(LLIL_REG.d(r2),LLIL_CONST.d(0x2))'), + # teq r3, #3 + ('A', b'\x03\x00\x33\xe3', 'LLIL_XOR.d{cnz}(LLIL_REG.d(r3),LLIL_CONST.d(0x3))'), + + # sxth r0, r1, ror #0 + ('A', b'\x71\x00\xbf\xe6', 'LLIL_SET_REG.d(r0,LLIL_SX.d(LLIL_LOW_PART.w(LLIL_REG.d(r1))))'), + # sxth r0, r1, ror #0x8 + ('A', b'\x71\x04\xbf\xe6', 'LLIL_SET_REG.d(r0,LLIL_SX.d(LLIL_LOW_PART.w(LLIL_ROR.d(LLIL_REG.d(r1),LLIL_CONST.b(0x8)))))'), + # sxth r0, r1, ror #0x10 + ('A', b'\x71\x08\xbf\xe6', 'LLIL_SET_REG.d(r0,LLIL_SX.d(LLIL_LOW_PART.w(LLIL_ROR.d(LLIL_REG.d(r1),LLIL_CONST.b(0x10)))))'), + # sxth r0, r1, ror #0x18 + ('A', b'\x71\x0c\xbf\xe6', 'LLIL_SET_REG.d(r0,LLIL_SX.d(LLIL_LOW_PART.w(LLIL_ROR.d(LLIL_REG.d(r1),LLIL_CONST.b(0x18)))))'), + + # ror r0, r1 + ('A', b'\x70\x01\xa0\xe1', 'LLIL_SET_REG.d(r0,LLIL_ROR.d(LLIL_REG.d(r0),LLIL_AND.b(LLIL_REG.d(r1),LLIL_CONST.b(0xFF))))'), + # ror r0, 7 + ('A', b'\xe0\x03\xa0\xe1', 'LLIL_SET_REG.d(r0,LLIL_ROR.d(LLIL_REG.d(r0),LLIL_AND.b(LLIL_CONST.d(0x7),LLIL_CONST.b(0xFF))))'), + # rors r0, r1 + ('A', b'\x70\x01\xb0\xe1', 'LLIL_SET_REG.d(r0,LLIL_ROR.d{*}(LLIL_REG.d(r0),LLIL_AND.b(LLIL_REG.d(r1),LLIL_CONST.b(0xFF))))'), + # rors r0, 7 + ('A', b'\xe0\x03\xb0\xe1', 'LLIL_SET_REG.d(r0,LLIL_ROR.d{*}(LLIL_REG.d(r0),LLIL_AND.b(LLIL_CONST.d(0x7),LLIL_CONST.b(0xFF))))'), + # vadd.f32 s0, s1, s2 + ('A', b'\x81\x0a\x30\xee', 'LLIL_SET_REG.d(s0,LLIL_FADD.d(LLIL_REG.d(s1),LLIL_REG.d(s2)))'), + # vsub.f32 s0, s1, s2 + ('A', b'\xc1\x0a\x30\xee', 'LLIL_SET_REG.d(s0,LLIL_FSUB.d(LLIL_REG.d(s1),LLIL_REG.d(s2)))'), + # vmul.f32 s0, s1, s2 + ('A', b'\x81\x0a\x20\xee', 'LLIL_SET_REG.d(s0,LLIL_FMUL.d(LLIL_REG.d(s1),LLIL_REG.d(s2)))'), + # vdiv.f32 s0, s1, s2 + ('A', b'\x81\x0a\x80\xee', 'LLIL_SET_REG.d(s0,LLIL_FDIV.d(LLIL_REG.d(s1),LLIL_REG.d(s2)))'), + # svc #0; svc #1; svc #2; svc #3 + ('A', b'\x00\x00\x00\xef', 'LLIL_SET_REG.d(syscall_info,LLIL_CONST.d(0x0)); LLIL_SYSCALL()'), + ('A', b'\x01\x00\x00\xef', 'LLIL_SET_REG.d(syscall_info,LLIL_CONST.d(0x1)); LLIL_SYSCALL()'), + ('A', b'\x02\x00\x00\xef', 'LLIL_SET_REG.d(syscall_info,LLIL_CONST.d(0x2)); LLIL_SYSCALL()'), + ('A', b'\x03\x00\x00\xef', 'LLIL_SET_REG.d(syscall_info,LLIL_CONST.d(0x3)); LLIL_SYSCALL()'), + # svcle #0xDEAD + ('A', b'\xAD\xDE\x00\xdf', 'LLIL_IF(LLIL_FLAG_COND(LowLevelILFlagCondition.LLFC_SLE,None),1,4); LLIL_SET_REG.d(syscall_info,LLIL_CONST.d(0xDEAD)); LLIL_SYSCALL(); LLIL_GOTO(4)'), + # svcgt #0xdead + ('A', b'\xad\xde\x00\xcf', 'LLIL_IF(LLIL_FLAG_COND(LowLevelILFlagCondition.LLFC_SGT,None),1,4); LLIL_SET_REG.d(syscall_info,LLIL_CONST.d(0xDEAD)); LLIL_SYSCALL(); LLIL_GOTO(4)'), + # mov r0, r1 + ('A', b'\x01\x00\xa0\xe1', 'LLIL_SET_REG.d(r0,LLIL_REG.d(r1))'), + # nop + ('A', b'\x00\xf0\x20\xe3', 'LLIL_NOP()'), + # vmov.i32 d16, #0 + ('A', b'\x10\x00\xc0\xf2', 'LLIL_SET_REG.q(d16,LLIL_CONST.q(0x0))'), + # vmov.i32 q8, #0 + ('A', b'\x50\x00\xc0\xf2', 'LLIL_SET_REG.o(q8,LLIL_OR.o(LLIL_CONST.q(0x0),LLIL_LSL.o(LLIL_CONST.q(0x0),LLIL_CONST.q(0x40))))'), + # vmov.i32 d16, #1 + ('A', b'\x11\x00\xc0\xf2', 'LLIL_SET_REG.q(d16,LLIL_CONST.q(0x100000001))'), + # vmov.i32 q8, #1 + ('A', b'\x51\x00\xc0\xf2', 'LLIL_SET_REG.o(q8,LLIL_OR.o(LLIL_CONST.q(0x100000001),LLIL_LSL.o(LLIL_CONST.q(0x100000001),LLIL_CONST.q(0x40))))'), + # vmov.i16 d16, #0 + ('A', b'\x10\x08\xc0\xf2', 'LLIL_SET_REG.q(d16,LLIL_CONST.q(0x0))'), + # vmov.i16 d16, #1 + ('A', b'\x11\x08\xc0\xf2', 'LLIL_SET_REG.q(d16,LLIL_CONST.q(0x1000100010001))'), + # vmov.i8 d16, #1 + ('A', b'\x11\x0e\xc0\xf2', 'LLIL_SET_REG.q(d16,LLIL_CONST.q(0x101010101010101))'), + # vmov.i8 q8, #1 + ('A', b'\x51\x0e\xc0\xf2', 'LLIL_SET_REG.o(q8,LLIL_OR.o(LLIL_CONST.q(0x101010101010101),LLIL_LSL.o(LLIL_CONST.q(0x101010101010101),LLIL_CONST.q(0x40))))'), + # vstr s0, [r3, #0x8] + ('A', b'\x02\x0a\x83\xed', 'LLIL_STORE.d(LLIL_ADD.d(LLIL_REG.d(r3),LLIL_CONST.d(0x8)),LLIL_REG.d(s0))'), + # vstr d16, [r3, #0x8] + ('A', b'\x02\x0b\xc3\xed', 'LLIL_STORE.q(LLIL_ADD.d(LLIL_REG.d(r3),LLIL_CONST.d(0x8)),LLIL_REG.q(d16))'), + # mov r2, r0 + ('T', b'\x02\x46', 'LLIL_SET_REG.d(r2,LLIL_REG.d(r0))'), + # cmp r1, r2 + ('T', b'\x91\x42', 'LLIL_SUB.d{*}(LLIL_REG.d(r1),LLIL_REG.d(r2))'), + # cmp r1, r2, lsl #7 + ('T', b'\xb1\xeb\xc2\x1f', 'LLIL_SUB.d{*}(LLIL_REG.d(r1),LLIL_LSL.d(LLIL_REG.d(r2),LLIL_CONST.d(0x7)))'), + # uadd8 r5, r2, r12 + ('T', b'\x82\xfa\x4c\xf5', 'LLIL_SET_REG.d(temp0,LLIL_ADD.b(LLIL_LOW_PART.b(LLIL_REG.d(r2)),LLIL_LOW_PART.b(LLIL_REG.d(r12)))); LLIL_SET_REG.d(temp1,LLIL_ADD.b(LLIL_LOW_PART.b(LLIL_LSR.d(LLIL_REG.d(r2),LLIL_CONST.b(0x8))),LLIL_LOW_PART.b(LLIL_LSR.d(LLIL_REG.d(r12),LLIL_CONST.b(0x8))))); LLIL_SET_REG.d(temp2,LLIL_ADD.b(LLIL_LOW_PART.b(LLIL_LSR.d(LLIL_REG.d(r2),LLIL_CONST.b(0x10))),LLIL_LOW_PART.b(LLIL_LSR.d(LLIL_REG.d(r12),LLIL_CONST.b(0x10))))); LLIL_SET_REG.d(temp3,LLIL_ADD.b(LLIL_LOW_PART.b(LLIL_LSR.d(LLIL_REG.d(r2),LLIL_CONST.b(0x18))),LLIL_LOW_PART.b(LLIL_LSR.d(LLIL_REG.d(r12),LLIL_CONST.b(0x18))))); LLIL_SET_REG.d(r5,LLIL_OR.d(LLIL_OR.d(LLIL_LSL.d(LLIL_REG.b(temp3),LLIL_CONST.b(0x18)),LLIL_LSL.d(LLIL_REG.b(temp2),LLIL_CONST.b(0x10))),LLIL_OR.d(LLIL_LSL.d(LLIL_REG.b(temp1),LLIL_CONST.b(0x8)),LLIL_REG.b(temp0))))'), + # ldrex r0, [r1, #4] + ('T', b'\x51\xe8\x01\x0f', 'LLIL_SET_REG.d(r0,LLIL_LOAD.d(LLIL_ADD.d(LLIL_REG.d(r1),LLIL_CONST.d(0x4))))'), + # ldrexb r0, [r1] + ('T', b'\xd1\xe8\x4f\x0f', 'LLIL_SET_REG.d(r0,LLIL_ZX.d(LLIL_LOAD.b(LLIL_REG.d(r1))))'), + # ldrexh r0, [r1] + ('T', b'\xd1\xe8\x5f\x0f', 'LLIL_SET_REG.d(r0,LLIL_ZX.d(LLIL_LOAD.w(LLIL_REG.d(r1))))'), + # umlal r0, r1, r2, r3 + ('T', b'\xe2\xfb\x03\x01', 'LLIL_SET_REG_SPLIT.d(r1,r0,LLIL_ADD.q(LLIL_MULU_DP.d(LLIL_REG.d(r3),LLIL_REG.d(r2)),LLIL_REG_SPLIT.d(r1,r0)))'), + # sbfx r0, r1, 0, 1 (starting at b0, width 1, so extract b0) + ('T', b'\x41\xf3\x00\x00', 'LLIL_SET_REG.d(r0,LLIL_ASR.d(LLIL_LSL.d(LLIL_REG.d(r1),LLIL_CONST.b(0x1F)),LLIL_CONST.b(0x1F)))'), + # sbfx r0, r1, 1, 2 (starting at b1, width 2, so extract b2b1) + ('T', b'\x41\xf3\x41\x00', 'LLIL_SET_REG.d(r0,LLIL_ASR.d(LLIL_LSL.d(LLIL_REG.d(r1),LLIL_CONST.b(0x1D)),LLIL_CONST.b(0x1E)))'), + # sbfx r0, r1, 20, 30 (starting at b20, width 30... gets clamped, so b31b30...b20 + ('T', b'\x41\xf3\x1d\x50', 'LLIL_SET_REG.d(r0,LLIL_ASR.d(LLIL_LSL.d(LLIL_REG.d(r1),LLIL_CONST.b(0x0)),LLIL_CONST.b(0x14)))') +] + +import re +import sys +import binaryninja +from binaryninja import binaryview +from binaryninja import lowlevelil +from binaryninja.enums import LowLevelILOperation + +def il2str(il): + sz_lookup = {1:'.b', 2:'.w', 4:'.d', 8:'.q', 16:'.o'} + if isinstance(il, lowlevelil.LowLevelILInstruction): + size_code = sz_lookup.get(il.size, '?') if il.size else '' + flags_code = '' if not hasattr(il, 'flags') or not il.flags else '{%s}'%il.flags + + # print size-specified IL constants in hex + if il.operation in [LowLevelILOperation.LLIL_CONST, LowLevelILOperation.LLIL_CONST_PTR] and il.size: + tmp = il.operands[0] + if tmp < 0: tmp = (1<<(il.size*8))+tmp + tmp = '0x%X' % tmp if il.size else '%d' % il.size + return 'LLIL_CONST%s(%s)' % (size_code, tmp) + else: + return '%s%s%s(%s)' % (il.operation.name, size_code, flags_code, ','.join([il2str(o) for o in il.operands])) + elif isinstance(il, list): + return '[' + ','.join([il2str(x) for x in il]) + ']' + else: + return str(il) + +# TODO: make this less hacky +def instr_to_il(data, platform): + # mov pc, lr + RETURN = { 'linux-armv7': b'\x0e\xf0\xa0\xe1', + 'linux-thumb2': b'\xf7\x46' + }[platform] + RETURN_LIFTED = 'LLIL_JUMP(LLIL_REG.d(lr))' + + platform = binaryninja.Platform[platform] + # make a pretend function that returns + bv = binaryview.BinaryView.new(data + RETURN) + bv.add_function(0, plat=platform) + assert len(bv.functions) == 1 + + result = [] + #for block in bv.functions[0].low_level_il: + for block in bv.functions[0].lifted_il: + for il in block: + result.append(il2str(il)) + result = '; '.join(result) + # strip return fence + if result.endswith(RETURN_LIFTED): + result = result[0:result.index(RETURN_LIFTED)] + # strip trailing separator + if result.endswith('; '): + result = result[0:-2] + + return result + +def il_str_to_tree(ilstr): + result = '' + depth = 0 + for c in ilstr: + if c == '(': + result += '\n' + depth += 1 + result += ' '*depth + elif c == ')': + depth -= 1 + elif c == ',': + result += '\n' + result += ' '*depth + elif c == ';': + result += '\n' + depth = 0 + elif c == ' ': + pass + else: + result += c + return result + +def test_all(): + for (test_i, (arch_name, data, expected)) in enumerate(test_cases): + platform = {'A':'linux-armv7', 'T':'linux-thumb2'}[arch_name] + actual = instr_to_il(data, platform) + + #print(f'{test_i:04d} {data.hex()} {actual}') + + if actual != expected: + print('MISMATCH AT TEST %d!' % test_i) + print('\t input: %s' % data.hex()) + print('\texpected: %s' % expected) + print('\t actual: %s' % actual) + print('\t tree:') + print(il_str_to_tree(actual)) + + return False + + return True + +if __name__ == '__main__': + if test_all(): + print('success!') + sys.exit(0) + else: + sys.exit(-1) + +if __name__ == 'test_lift': + if test_all(): + print('success!') |
