def test_instruction_semantics_call(self): # call #0xdead raw = b'\xb0\x12\xad\xde' ip = 0xc0de ins, _ = decode_instruction(ip, raw) state = blank_state() state.cpu.registers['R0'] = BitVecVal(ip + len(raw), 16) # ip preincrement state.cpu.registers['R1'] = BitVecVal(0x1234, 16) new_states = state.cpu.step_call(state, ins) self.assertEqual(len(new_states), 1) new_state = new_states[0] lo = new_state.memory[0x1232] hi = new_state.memory[0x1233] pushed_val = Concat(hi, lo) self.assertEqual(intval(pushed_val), ip + len(raw)) self.assertEqual(intval(new_state.cpu.registers['R1']), 0x1232) self.assertEqual(intval(new_state.cpu.registers['R0']), 0xdead)
def test_instruction_semantics_jl(self): # jl #0x124e raw = b'\x0c\x38' ip = 0x1234 ins, ins_len = decode_instruction(ip, raw) state = blank_state() state.cpu.registers['R0'] = BitVecVal( ip + ins_len, 16) # ip is always preincremented expected_taken = 0x124e expected_not_taken = 0x1236 new_states = state.cpu.step_jl(state, ins) self.assertEqual(len(new_states), 2) taken_states = [ st for st in new_states if intval(st.cpu.registers['R0']) == expected_taken ] not_taken_states = [ st for st in new_states if intval(st.cpu.registers['R0']) == expected_not_taken ] self.assertEqual(len(taken_states), 1) self.assertEqual(len(not_taken_states), 1)
def test_jmp_decode(self): # should be jmp #0x446a raw = b'\x06\x3c' ip = 0x445c instruction, _ = decode_instruction(ip, raw + b'\xFF\xFF\xFF') self.assertIsInstance(instruction, JumpInstruction) self.assertEqual(instruction.raw, list(raw)) self.assertEqual(instruction.opcode, Opcode.JMP) target = instruction.target target = simplify(target).as_long() self.assertEqual(target, 0x446a)
def test_jz_decode(self): raw = b'\x06\x24' # should be jz #0x4438 ip = 0x442a instruction, _ = decode_instruction(ip, raw + b'\xFF\xFF\xFF') self.assertIsInstance(instruction, JumpInstruction) self.assertEqual(instruction.raw, list(raw)) self.assertEqual(instruction.opcode, Opcode.JZ) target = instruction.target target = simplify(target).as_long() self.assertEqual(target, 0x4438)
def test_reti_decode(self): # should be "reti pc" raw = b'\x00\x13' ip = 0x4484 instruction, _ = decode_instruction(ip, raw + b'\xFF\xFF\xFF') self.assertIsInstance(instruction, SingleOperandInstruction) self.assertEqual(instruction.raw, list(raw)) self.assertEqual(instruction.opcode, Opcode.RETI) self.assertEqual(instruction.width, OperandWidth.WORD) self.assertEqual(instruction.addressing_mode, AddressingMode.DIRECT) self.assertEqual(instruction.register, Register.R0) self.assertEqual(instruction.operand, None)
def test_call_decode(self): raw = b'\xb0\x12\x58\x45' ip = 0x4458 instruction, _ = decode_instruction(ip, raw + b'\xFF\xFF\xFF') self.assertIsInstance(instruction, SingleOperandInstruction) self.assertEqual(instruction.raw, list(raw)) self.assertEqual(instruction.opcode, Opcode.CALL) self.assertEqual(instruction.width, OperandWidth.WORD) self.assertEqual(instruction.addressing_mode, AddressingMode.IMMEDIATE) operand = instruction.operand operand = simplify(operand).as_long() self.assertEqual(operand, 0x4558)
def test_push_constant_generator_decode(self): # should be "push 0x2" raw = b'\x23\x12' ip = 0x454c instruction, _ = decode_instruction(ip, raw + b'\xFF\xFF\xFF') self.assertIsInstance(instruction, SingleOperandInstruction) self.assertEqual(instruction.raw, list(raw)) self.assertEqual(instruction.opcode, Opcode.PUSH) self.assertEqual(instruction.width, OperandWidth.WORD) self.assertEqual(instruction.addressing_mode, AddressingMode.CONSTANT2) self.assertEqual(instruction.register, Register.R3) self.assertEqual(instruction.operand, None)
def test_push_immediate_decode(self): # should be "push 0xa" raw = b'\x30\x12\x0a\x00' ip = 0x4472 instruction, _ = decode_instruction(ip, raw + b'\xFF\xFF\xFF') self.assertIsInstance(instruction, SingleOperandInstruction) self.assertEqual(instruction.raw, list(raw)) self.assertEqual(instruction.opcode, Opcode.PUSH) self.assertEqual(instruction.width, OperandWidth.WORD) self.assertEqual(instruction.addressing_mode, AddressingMode.IMMEDIATE) operand = instruction.operand operand = simplify(operand).as_long() self.assertEqual(operand, 0xa)
def test_mov_reg_reg_decode(self): raw = b'\x0b\x4f' # should be mov r15, r11 ip = 0x455a instruction, _ = decode_instruction(ip, raw + b'\xFF\xFF\xFF') self.assertIsInstance(instruction, DoubleOperandInstruction) self.assertEqual(instruction.raw, list(raw)) self.assertEqual(instruction.opcode, Opcode.MOV) self.assertEqual(instruction.width, OperandWidth.WORD) self.assertEqual(instruction.source_addressing_mode, AddressingMode.DIRECT) self.assertEqual(instruction.source_register, Register.R15) self.assertEqual(instruction.source_operand, None) self.assertEqual(instruction.dest_addressing_mode, AddressingMode.DIRECT) self.assertEqual(instruction.dest_register, Register.R11) self.assertEqual(instruction.dest_operand, None)
def test_instruction_semantics_mov(self): # mov #0xdead, r6 raw = b'\x36\x40\xad\xde' ip = 0x1234 ins, _ = decode_instruction(ip, raw) state = blank_state() new_states = state.cpu.step_mov(state, ins) self.assertEqual(len(new_states), 1) new_state = new_states[0] self.assertEqual(intval(new_state.cpu.registers['R6']), 0xdead)
def test_instruction_semantics_jmp(self): # should be jmp #0x446a raw = b'\x06\x3c' ip = 0x445c ins, _ = decode_instruction(ip, raw) state = blank_state() new_states = state.cpu.step_jmp(state, ins) self.assertEqual(len(new_states), 1) new_ip = new_states[0].cpu.registers['R0'] new_ip = simplify(new_ip).as_long() self.assertEqual(new_ip, 0x446a)
def test_instruction_semantics_sub(self): # sub.b #0x21, r15 raw = b'\x7f\x80\x21\x00' ip = 0x1234 ins, _ = decode_instruction(ip, raw) state = blank_state() state.cpu.registers['R15'] = BitVecVal(0x80, 16) new_states = state.cpu.step_sub(state, ins, enable_unsound_optimizations=False) for st in new_states: self.assertEqual(intval(st.cpu.registers['R15']), 0x80 - 0x21)
def test_instruction_semantics_add(self): # add #0xc0de, r15 raw = b'\x3f\x50\xde\xc0' ip = 0x1234 ins, _ = decode_instruction(ip, raw) state = blank_state() state.cpu.registers['R15'] = BitVecVal(0x1111, 16) new_states = state.cpu.step_add(state, ins, enable_unsound_optimizations=False) for st in new_states: self.assertEqual(intval(st.cpu.registers['R15']), 0xc0de + 0x1111)
def test_instruction_semantics_swpb(self): # swpb r6 raw = b'\x86\x10' ip = 0x1234 ins, _ = decode_instruction(ip, raw) state = blank_state() state.cpu.registers['R6'] = BitVecVal(0xdead, 16) new_states = state.cpu.step_swpb(state, ins) self.assertEqual(len(new_states), 1) new_state = new_states[0] self.assertEqual(intval(new_state.cpu.registers['R6']), 0xadde)
def test_instruction_semantics_bis(self): # bis #0x0f0f, r6 raw = b'\x36\xd0\x0f\x0f' ip = 0x1234 ins, _ = decode_instruction(ip, raw) state = blank_state() state.cpu.registers['R6'] = BitVecVal(0xdead, 16) new_states = state.cpu.step_bis(state, ins) self.assertEqual(len(new_states), 1) new_state = new_states[0] self.assertEqual(intval(new_state.cpu.registers['R6']), 0xdfaf)
def test_call_absolute_decode(self): # call &0x1234 raw = b'\x92\x12\x34\x12' ip = 0xc0de instruction, _ = decode_instruction(ip, raw + b'\xFF\xFF\xFF') self.assertIsInstance(instruction, SingleOperandInstruction) self.assertEqual(instruction.raw, list(raw)) self.assertEqual(instruction.opcode, Opcode.CALL) self.assertEqual(instruction.width, OperandWidth.WORD) self.assertEqual(instruction.addressing_mode, AddressingMode.ABSOLUTE) self.assertEqual(instruction.register, Register.R2) operand = instruction.operand operand = simplify(operand).as_long() self.assertEqual(operand, 0x1234)
def test_mov_offset_reg_decode(self): raw = b'\x5f\x44\xfc\xff' # should be mov.b -0x4(r4), r15 ip = 0x453a instruction, _ = decode_instruction(ip, raw + b'\xFF\xFF\xFF') self.assertIsInstance(instruction, DoubleOperandInstruction) self.assertEqual(instruction.raw, list(raw)) self.assertEqual(instruction.opcode, Opcode.MOV) self.assertEqual(instruction.width, OperandWidth.BYTE) self.assertEqual(instruction.source_addressing_mode, AddressingMode.INDEXED) self.assertEqual(instruction.source_register, Register.R4) source_operand = instruction.source_operand source_operand = simplify(source_operand).as_signed_long() self.assertEqual(source_operand, -0x4) self.assertEqual(instruction.dest_addressing_mode, AddressingMode.DIRECT) self.assertEqual(instruction.dest_register, Register.R15) self.assertEqual(instruction.dest_operand, None)
def test_instruction_semantics_sxt_negative(self): # sxt r6 raw = b'\x86\x11' ip = 0x1234 ins, _ = decode_instruction(ip, raw) state = blank_state() state.cpu.registers['R6'] = BitVecVal(0x008c, 16) new_states = state.cpu.step_sxt(state, ins) self.assertEqual(len(new_states), 4) for new_state in new_states: # TODO: Check flags self.assertEqual(intval(new_state.cpu.registers['R6']), 0xff8c)
def test_call_symbolic_decode(self): # call 0x1234 # (or call 0x1234(r0)) raw = b'\x90\x12\x32\x12' ip = 0xc0de instruction, _ = decode_instruction(ip, raw + b'\xFF\xFF\xFF') self.assertIsInstance(instruction, SingleOperandInstruction) self.assertEqual(instruction.raw, list(raw)) self.assertEqual(instruction.opcode, Opcode.CALL) self.assertEqual(instruction.width, OperandWidth.WORD) self.assertEqual(instruction.addressing_mode, AddressingMode.SYMBOLIC) self.assertEqual(instruction.register, Register.R0) # 0x1232 instead of 0x1234 because -2 from instruction width operand = instruction.operand operand = simplify(operand).as_long() self.assertEqual(operand, 0x1232)
def test_mov_reg_offset_decode(self): raw = b'\x81\x4f\x04\x00' # should be mov r15, 0x4(r1) ip = 0x4512 instruction, _ = decode_instruction(ip, raw + b'\xFF\xFF\xFF') self.assertIsInstance(instruction, DoubleOperandInstruction) self.assertEqual(instruction.raw, list(raw)) self.assertEqual(instruction.opcode, Opcode.MOV) self.assertEqual(instruction.width, OperandWidth.WORD) self.assertEqual(instruction.source_addressing_mode, AddressingMode.DIRECT) self.assertEqual(instruction.source_register, Register.R15) self.assertEqual(instruction.source_operand, None) self.assertEqual(instruction.dest_addressing_mode, AddressingMode.INDEXED) self.assertEqual(instruction.dest_register, Register.R1) dest_operand = instruction.dest_operand dest_operand = simplify(dest_operand).as_signed_long() self.assertEqual(dest_operand, 0x4)
def test_mov_symbolic_decode(self): # mov 0x2400, r1 raw = b'\x11\x40\xfe\x23' ip = 0xc0de instruction, _ = decode_instruction(ip, raw + b'\xFF\xFF\xFF') self.assertIsInstance(instruction, DoubleOperandInstruction) self.assertEqual(instruction.raw, list(raw)) self.assertEqual(instruction.opcode, Opcode.MOV) self.assertEqual(instruction.width, OperandWidth.WORD) self.assertEqual(instruction.source_addressing_mode, AddressingMode.SYMBOLIC) self.assertEqual(instruction.source_register, Register.R0) source_operand = instruction.source_operand source_operand = source_operand.as_long() self.assertEqual(source_operand, 0x2400 - 2) self.assertEqual(instruction.dest_addressing_mode, AddressingMode.DIRECT) self.assertEqual(instruction.dest_register, Register.R1) self.assertEqual(instruction.dest_operand, None)
def test_mov_offset_offset_decode(self): raw = b'\x9f\x4f\x86\x45\x00\x24' # should be mov 0x4586(r15), 0x2400(r15) ip = 0x441c instruction, _ = decode_instruction(ip, raw + b'\xFF\xFF\xFF') self.assertIsInstance(instruction, DoubleOperandInstruction) self.assertEqual(instruction.raw, list(raw)) self.assertEqual(instruction.opcode, Opcode.MOV) self.assertEqual(instruction.width, OperandWidth.WORD) self.assertEqual(instruction.source_addressing_mode, AddressingMode.INDEXED) self.assertEqual(instruction.source_register, Register.R15) source_operand = instruction.source_operand source_operand = simplify(source_operand).as_signed_long() self.assertEqual(source_operand, 0x4586) self.assertEqual(instruction.dest_addressing_mode, AddressingMode.INDEXED) self.assertEqual(instruction.dest_register, Register.R15) dest_operand = instruction.dest_operand dest_operand = simplify(dest_operand).as_signed_long() self.assertEqual(dest_operand, 0x2400)
def test_instruction_semantics_bit_cflag_set(self): # bit #0xff00, r15 raw = b'\x3f\xb0\x00\xff' ip = 0x1234 ins, _ = decode_instruction(ip, raw) state = blank_state() state.cpu.registers['R15'] = BitVecVal(0x8000, 16) new_states = state.cpu.step_bit(state, ins, enable_unsound_optimizations=False) new_states = [st for st in new_states if st.path.is_sat()] # only sat states for st in new_states: flag_reg = intval(st.cpu.registers['R2']) c_flag = (flag_reg & st.cpu.registers.mask_C) != 0 self.assertTrue(c_flag)
def test_instruction_semantics_xor_zflag_set(self): # xor #0x21, r15 raw = b'\x3f\xe0\x21\x00' ip = 0x1234 ins, _ = decode_instruction(ip, raw) state = blank_state() state.cpu.registers['R15'] = BitVecVal(0x0021, 16) new_states = state.cpu.step_xor(state, ins, enable_unsound_optimizations=False) new_states = [st for st in new_states if st.path.is_sat()] # only sat states for st in new_states: flag_reg = intval(st.cpu.registers['R2']) z_flag = (flag_reg & st.cpu.registers.mask_Z) != 0 self.assertTrue(z_flag)
def test_instruction_semantics_add_vflag_set(self): # add #0x0123, r15 raw = b'\x3f\x50\x23\x01' ip = 0x1234 ins, _ = decode_instruction(ip, raw) state = blank_state() state.cpu.registers['R15'] = BitVecVal(0x7fff, 16) new_states = state.cpu.step_add(state, ins, enable_unsound_optimizations=False) new_states = [st for st in new_states if st.path.is_sat()] # only sat states for st in new_states: flag_reg = intval(st.cpu.registers['R2']) v_flag = (flag_reg & st.cpu.registers.mask_V) != 0 self.assertTrue(v_flag)
def test_instruction_semantics_cmp_vflag_unset(self): # cmp.b #0x21, r15 raw = b'\x7f\x90\x21\x00' ip = 0x1234 ins, _ = decode_instruction(ip, raw) state = blank_state() state.cpu.registers['R15'] = BitVecVal(0x30, 16) new_states = state.cpu.step_cmp(state, ins, enable_unsound_optimizations=False) new_states = [st for st in new_states if st.path.is_sat()] # only sat states for st in new_states: flag_reg = intval(st.cpu.registers['R2']) v_flag = (flag_reg & st.cpu.registers.mask_V) != 0 self.assertFalse(v_flag)
def test_instruction_semantics_push(self): # push #0xdead raw = b'\x30\x12\xad\xde' ip = 0x1234 ins, _ = decode_instruction(ip, raw) state = blank_state() state.cpu.registers['R1'] = BitVecVal(0x1234, 16) new_states = state.cpu.step_push(state, ins) self.assertEqual(len(new_states), 1) new_state = new_states[0] lo = new_state.memory[0x1232] hi = new_state.memory[0x1233] pushed_val = Concat(hi, lo) self.assertEqual(intval(pushed_val), 0xdead) self.assertEqual(intval(new_state.cpu.registers['R1']), 0x1232)