import struct import unittest from manticore.core.cpu.x86 import * from manticore.core.smtlib import Operators from manticore.core.memory import * import mockmem class ROOperand(object): ''' Mocking class for operand ronly ''' def __init__(self, size, value): self.size = size self.value = value def read(self): return self.value & ((1< 2: v = values.get(reg_name, 0) self.assertEqual(cpu.read_register(reg_name),v) def testRegisterCacheAccess(self): cpu = self.cpu cpu.ESI = 0x12345678 self.assertEqual(cpu.ESI, 0x12345678) cpu.SI = 0xAAAA self.assertEqual(cpu.SI, 0xAAAA) cpu.RAX = 0x12345678aabbccdd self.assertEqual(cpu.ESI, 0x1234AAAA) cpu.SI = 0xAAAA self.assertEqual(cpu.SI, 0xAAAA) def testFlagAccess(self): cpu = self.cpu cpu.RFLAGS = 0 self.assertFalse(cpu.CF) self.assertFalse(cpu.PF) self.assertFalse(cpu.AF) self.assertFalse(cpu.ZF) self.assertFalse(cpu.SF) self.assertFalse(cpu.DF) self.assertFalse(cpu.OF) #flag to register CF cpu.CF = True self.assertTrue( cpu.RFLAGS&self._flags['CF'] !=0) cpu.CF = False self.assertTrue( cpu.RFLAGS&self._flags['CF'] ==0) #register to flag CF cpu.RFLAGS |= self._flags['CF'] self.assertTrue(cpu.CF) cpu.RFLAGS &= ~self._flags['CF'] self.assertFalse(cpu.CF) #flag to register PF cpu.PF = True self.assertTrue( cpu.RFLAGS&self._flags['PF'] !=0) cpu.PF = False self.assertTrue( cpu.RFLAGS&self._flags['PF'] ==0) #register to flag PF cpu.RFLAGS |= self._flags['PF'] self.assertTrue(cpu.PF) cpu.RFLAGS &= ~self._flags['PF'] self.assertFalse(cpu.PF) #flag to register AF cpu.AF = True self.assertTrue( cpu.RFLAGS&self._flags['AF'] !=0) cpu.AF = False self.assertTrue( cpu.RFLAGS&self._flags['AF'] ==0) #register to flag AF cpu.RFLAGS |= self._flags['AF'] self.assertTrue(cpu.AF) cpu.RFLAGS &= ~self._flags['AF'] self.assertFalse(cpu.AF) #flag to register ZF cpu.ZF = True self.assertTrue( (cpu.RFLAGS&self._flags['ZF']) !=0) cpu.ZF = False self.assertTrue( cpu.RFLAGS&self._flags['ZF'] ==0) #register to flag ZF cpu.RFLAGS |= self._flags['ZF'] self.assertTrue(cpu.ZF) cpu.RFLAGS &= ~self._flags['ZF'] self.assertFalse(cpu.ZF) #flag to register SF cpu.SF = True self.assertTrue( cpu.RFLAGS&self._flags['SF'] !=0) cpu.SF = False self.assertTrue( cpu.RFLAGS&self._flags['SF'] ==0) #register to flag SF cpu.RFLAGS |= self._flags['SF'] self.assertTrue(cpu.SF) cpu.RFLAGS &= ~self._flags['SF'] self.assertFalse(cpu.SF) #flag to register DF cpu.DF = True self.assertTrue( cpu.RFLAGS&self._flags['DF'] !=0) cpu.DF = False self.assertTrue( cpu.RFLAGS&self._flags['DF'] ==0) #register to flag DF cpu.RFLAGS |= self._flags['DF'] self.assertTrue(cpu.DF) cpu.RFLAGS &= ~self._flags['DF'] self.assertFalse(cpu.DF) #flag to register OF cpu.OF = True self.assertTrue( cpu.RFLAGS&self._flags['OF'] !=0) cpu.OF = False self.assertTrue( cpu.RFLAGS&self._flags['OF'] ==0) #register to flag cpu.RFLAGS |= self._flags['OF'] self.assertTrue(cpu.OF) cpu.RFLAGS &= ~self._flags['OF'] self.assertFalse(cpu.OF) def _check_flags_CPAZSIDO(self, c, p, a, z, s, i, d, o): self.assertEqual(self.cpu.CF, c) self.assertEqual(self.cpu.PF, p) self.assertEqual(self.cpu.AF, a) self.assertEqual(self.cpu.ZF, z) self.assertEqual(self.cpu.SF, s) self.assertEqual(self.cpu.IF, i) self.assertEqual(self.cpu.DF, d) self.assertEqual(self.cpu.OF, o) def _construct_flag_bitfield(self, flags): return reduce(operator.or_, (self._flags[f] for f in flags)) def _construct_sym_flag_bitfield(self, flags): return reduce(operator.or_, (BitVecConstant(32, self._flags[f]) for f in flags)) def test_set_eflags(self): self.assertEqual(self.cpu.EFLAGS, 0) flags = ['CF', 'PF', 'AF', 'ZF', 'SF'] self.cpu.EFLAGS = self._construct_flag_bitfield(flags) self._check_flags_CPAZSIDO(1, 1, 1, 1, 1, 0, 0, 0) def test_get_eflags(self): self.assertEqual(self.cpu.EFLAGS, 0) flags = ['CF', 'AF', 'SF'] self.cpu.CF = 1 self.cpu.AF = 1 self.cpu.SF = 1 self.cpu.DF = 0 self.assertEqual(self.cpu.EFLAGS, self._construct_flag_bitfield(flags)) def test_set_sym_eflags(self): def check_flag(obj, flag): equal = obj.operands[0] extract = equal.operands[0] assert isinstance(obj, Bool) assert extract.begining == self._flag_offsets[flag] assert extract.end == extract.begining flags = ['CF', 'PF', 'AF', 'ZF'] sym_bitfield = self._construct_sym_flag_bitfield(flags) self.cpu.EFLAGS = sym_bitfield check_flag(self.cpu.CF, 'CF') check_flag(self.cpu.PF, 'PF') check_flag(self.cpu.AF, 'AF') check_flag(self.cpu.ZF, 'ZF') def test_get_sym_eflags(self): def flatten_ors(x): ''' Retrieve all nodes of a BitVecOr expression tree ''' assert isinstance(x, BitVecOr) if any(isinstance(op, BitVecOr) for op in x.operands): ret = [] for op in x.operands: if isinstance(op, BitVecOr): ret += flatten_ors(op) else: ret.append(op) return ret else: return list(x.operands) self.cpu.CF = 1 self.cpu.AF = 1 a = BitVecConstant(32, 1) != 0 b = BitVecConstant(32, 0) != 0 self.cpu.ZF = a self.cpu.SF = b flags = flatten_ors(self.cpu.EFLAGS) self.assertTrue(isinstance(self.cpu.EFLAGS, BitVecOr)) self.assertEqual(len(flags), 8) self.assertEqual(self.cpu.CF, 1) self.assertEqual(self.cpu.AF, 1) self.assertIs(self.cpu.ZF, a) self.assertIs(self.cpu.SF, b) def testRegisterAccess(self): cpu = self.cpu #initially zero self.assertEqual(cpu.EAX, 0) cpu.EAX += 1 self.assertEqual(cpu.EAX, 1) cpu.EAX = 0x8000000 self.assertEqual(cpu.EAX, 0x8000000) cpu.EAX = 0xff000000 self.assertEqual(cpu.EAX, 0xff000000) cpu.EAX = 0x00ff0000 self.assertEqual(cpu.EAX, 0x00ff0000) cpu.EAX = 0x0000ff00 self.assertEqual(cpu.EAX, 0x0000ff00) cpu.EAX = 0xff self.assertEqual(cpu.EAX, 0xff) #overflow shall be discarded #self.assertRaises@@@@@@@@@@@@cpu.EAX = 0x100000000 cpu.EAX = 0x100000000 self.assertEqual(cpu.EAX, 0x00000000) #partial register access cpu.EAX = 0x11223344 self.assertEqual(cpu.EAX, 0x11223344) self.assertEqual(cpu.AX, 0x3344) self.assertEqual(cpu.AH, 0x33) self.assertEqual(cpu.AL, 0x44) #partial register mod cpu.AL=0xDD self.assertEqual(cpu.EAX, 0x112233DD) self.assertEqual(cpu.AX, 0x33DD) self.assertEqual(cpu.AH, 0x33) self.assertEqual(cpu.AL, 0xDD) cpu.AH=0xCC self.assertEqual(cpu.EAX, 0x1122CCDD) self.assertEqual(cpu.AX, 0xCCDD) self.assertEqual(cpu.AH, 0xCC) self.assertEqual(cpu.AL, 0xDD) #partial register mod is truncated cpu.AL=0xDD self.assertEqual(cpu.EAX, 0x1122CCDD) self.assertEqual(cpu.AX, 0xCCDD) self.assertEqual(cpu.AH, 0xCC) self.assertEqual(cpu.AL, 0xDD) cpu.EDX = 0x8048c50 self.assertEqual(cpu.EDX, 0x8048c50) #initially zero self.assertEqual(cpu.ECX, 0) cpu.ECX += 1 self.assertEqual(cpu.ECX, 1) cpu.ECX = 0x8000000 self.assertEqual(cpu.ECX, 0x8000000) cpu.ECX = 0xff000000 self.assertEqual(cpu.ECX, 0xff000000) cpu.ECX = 0x00ff0000 self.assertEqual(cpu.ECX, 0x00ff0000) cpu.ECX = 0x0000ff00 self.assertEqual(cpu.ECX, 0x0000ff00) cpu.ECX = 0xff self.assertEqual(cpu.ECX, 0xff) #overflow shall be discarded #self.assertRaises@@@@@@@@@@@@cpu.ECX = 0x100000000 cpu.ECX = 0x100000000 self.assertEqual(cpu.ECX, 0x00000000) #partial register access cpu.ECX = 0x11223344 self.assertEqual(cpu.ECX, 0x11223344) self.assertEqual(cpu.CX, 0x3344) self.assertEqual(cpu.CH, 0x33) self.assertEqual(cpu.CL, 0x44) #partial register mod cpu.CL=0xDD self.assertEqual(cpu.ECX, 0x112233DD) self.assertEqual(cpu.CX, 0x33DD) self.assertEqual(cpu.CH, 0x33) self.assertEqual(cpu.CL, 0xDD) cpu.CH=0xCC self.assertEqual(cpu.ECX, 0x1122CCDD) self.assertEqual(cpu.CX, 0xCCDD) self.assertEqual(cpu.CH, 0xCC) self.assertEqual(cpu.CL, 0xDD) #partial register mod is truncated cpu.CL=0xDD self.assertEqual(cpu.ECX, 0x1122CCDD) self.assertEqual(cpu.CX, 0xCCDD) self.assertEqual(cpu.CH, 0xCC) self.assertEqual(cpu.CL, 0xDD) def test_le_or(self): cs = ConstraintSet() mem = SMemory64(cs) cpu = AMD64Cpu(mem) mem.mmap(0x1000,0x1000,'rwx') cpu.write_int(0x1000, 0x4142434445464748, 64) cpu.write_int(0x1000, cpu.read_int(0x1000, 32) | 0, 32) addr1 = cs.new_bitvec(64) cs.add(addr1 == 0x1004) cpu.write_int(addr1, 0x58, 8) self.assertEqual(cpu.read_int(0x1000,32), 0x45464748) addr1 = cs.new_bitvec(64) cs.add(addr1 == 0x1000) cpu.write_int(addr1, 0x59, 8) solutions = solver.get_all_values(cs, cpu.read_int(0x1000,32)) self.assertEqual(len(solutions), 1) self.assertEqual(solutions[0], 0x45464759) cpu.write_int(0x1000, cpu.read_int(0x1000,32) | 0, 32) cpu.write_int(0x1000, cpu.read_int(0x1000,32) | 0, 32) cpu.write_int(0x1000, cpu.read_int(0x1000,32) | 0, 32) solutions = solver.get_all_values(cs, cpu.read_int(0x1000,32)) self.assertEqual(len(solutions), 1) self.assertEqual(solutions[0], 0x45464759) def test_cache_001(self): cs = ConstraintSet() mem = SMemory64(ConstraintSet()) cpu = AMD64Cpu(mem) mem.mmap(0x1000,0x1000,'rwx') cpu.write_int(0x1000, 0x4142434445464748, 64) #print cpu.mem_cache cpu.write_int(0x1004, 0x5152535455565758, 64) #print cpu.mem_cache cpu.write_int(0x1008, 0x6162636465666768, 64) #print cpu.mem_cache #print hex(cpu.read_int(0x1000,32)) #print hex(cpu.read_int(0x1000,32)) #print hex(cpu.read_int(0x1000,32)) #print hex(cpu.read_int(0x1000,32)) #print hex(cpu.read_int(0x1000,32)) self.assertEqual(cpu.read_int(0x1000,32), 0x45464748) cpu.write_int( 0x1000, 0x45464748,32) self.assertEqual(cpu.read_int(0x1000,32), 0x45464748) self.assertEqual(cpu.read_int(0x1004,32), 0x55565758) self.assertEqual(cpu.read_int(0x1008,32), 0x65666768) self.assertEqual(cpu.read_int(0x1008,64), 0x6162636465666768) self.assertEqual(cpu.read_int(0x1000,64), 0x5556575845464748) #cpu.writeback() for i in xrange(0x10): self.assertEqual(mem[i+0x1000], 'HGFEXWVUhgfedcba'[i]) self.assertItemsEqual(mem.read(0x1000,0x10), 'HGFEXWVUhgfedcba') def test_cache_002(self): cs = ConstraintSet() mem = SMemory64(cs) cpu = AMD64Cpu(mem) #alloc/map a little mem addr = mem.mmap(0x1000, 0x1000, 'rwx') self.assertEqual(addr, 0x1000) cpu.write_int(0x1000, 0x4142434445464748, 64) cpu.write_int(0x1004, 0x5152535455565758, 64) cpu.write_int(0x1008, 0x6162636465666768, 64) self.assertEqual(cpu.read_int(0x1000,32), 0x45464748) self.assertEqual(cpu.read_int(0x1004,32), 0x55565758) self.assertEqual(cpu.read_int(0x1008,32), 0x65666768) self.assertEqual(cpu.read_int(0x1008,64), 0x6162636465666768) self.assertEqual(cpu.read_int(0x1000,64), 0x5556575845464748) #cpu.writeback() for i in xrange(0x10): self.assertEqual(mem[i+0x1000], 'HGFEXWVUhgfedcba'[i]) def test_cache_003(self): cs = ConstraintSet() mem = SMemory64(cs) cpu = AMD64Cpu(mem) #alloc/map a little mem addr = mem.mmap(0x1000, 0x1000, 'rwx') self.assertEqual(addr, 0x1000) cpu.write_int(0x1000, 0x4142434445464748, 64) cpu.write_int(0x1008, 0x6162636465666768, 64) self.assertEqual(cpu.read_int(0x1000,64), 0x4142434445464748) self.assertEqual(cpu.read_int(0x1008,64), 0x6162636465666768) for i in range(8): self.assertEqual( cpu.read_int(0x1000+i, 8), ord("HGFEDCBA"[i]) ) for i in range(8): self.assertEqual( cpu.read_int(0x1008+i, 8), ord("hgfedcba"[i]) ) addr1 = cs.new_bitvec(64) cs.add(addr1 == 0x1004) cpu.write_int(addr1, 0x58, 8) # 48 47 46 45 58 43 42 41 68 67 66 65 64 63 62 61 value = cpu.read_int(0x1004, 16) self.assertItemsEqual(solver.get_all_values(cs, value), [0x4358] ) addr2 = cs.new_bitvec(64) cs.add(Operators.AND(addr2>=0x1000, addr2<=0x100c)) cpu.write_int(addr2, 0x5959, 16) solutions = solver.get_all_values(cs, cpu.read_int(addr2, 32) ) self.assertEqual( len(solutions), 0x100c-0x1000+1 ) self.assertEqual( set(solutions), set([0x45465959, 0x41425959, 0x58455959, 0x65665959, 0x67685959, 0x43585959, 0x68415959, 0x42435959, 0x66675959, 0x62635959, 0x64655959, 0x63645959, 0x61625959])) def test_cache_004(self): import random cs = ConstraintSet() mem = SMemory64(cs) cpu = AMD64Cpu(mem) #alloc/map a little mem addr = mem.mmap(0x1000, 0x1000, 'rwx') self.assertEqual(addr, 0x1000) memory = ['\x00'] *0x1000 written = set() for _ in xrange(1000): address = random.randint(0x1000,0x2000-8) [written.add(i) for i in range(address,address+8)] value = random.randint(0x0,0xffffffffffffffff) memory[address-0x1000:address-0x1000+8] = list(struct.pack(' 5: cpu.read_int(random.randint(0x1000,0x2000-8), random.choice([8,16,32,64])) written = list(written) random.shuffle(written) for address in written: size = random.choice([8,16,32,64]) if address > 0x2000-size/8: continue pattern = {8:'B', 16:' 0x80483f0 : sarb %cl,0x0(%eax) eax 0xffffd000 -12288 ecx 0x3d1ce0ff 1025302783 eip 0x80483f4 0x80483f4 eflags 0x287 [ CF PF SF IF ] 0xffffd000: 0xff ''' cs = ConstraintSet() mem = SMemory32(cs) cpu = I386Cpu(mem) mem.mmap(0x0804d000, 0x1000, 'rwx') mem.mmap(0xffffb000, 0x1000, 'rwx') mem[0x804d600] = '\xd2' mem[0x804d601] = '\x78' mem[0x804d602] = '\x00' mem[0x804d603] = '\xff' addr = cs.new_bitvec(32) ; cs.add(addr == 0xffffb000) value = cs.new_bitvec(8) ; cs.add(value == 0x8f) mem[addr] = value cpu.EAX = cs.new_bitvec(32) cs.add(cpu.EAX == 0xffffb000) cpu.CL = cs.new_bitvec(8) cs.add(cpu.CL == 0xff) cpu.EIP = 0x804d600 cpu.CF = cs.new_bool(); cs.add(cpu.CF == True) cpu.PF = cs.new_bool(); cs.add(cpu.PF == True) cpu.SF = cs.new_bool(); cs.add(cpu.SF == True) done = False while not done: try: cpu.execute() done = True except ConcretizeRegister,e: symbol = getattr(cpu, e.reg_name) values = solver.get_all_values(cs, symbol) self.assertEqual(len(values), 1) setattr(cpu, e.reg_name, values[0]) condition = True condition = Operators.AND(condition, cpu.read_int(0xffffb000, 8) == 0xff) condition = Operators.AND(condition, cpu.CL == 0xff) condition = Operators.AND(condition, cpu.CF == True) condition = Operators.AND(condition, cpu.PF == True) condition = Operators.AND(condition, cpu.SF == True) with cs as temp_cs: temp_cs.add(condition) self.assertTrue(solver.check(temp_cs)) with cs as temp_cs: temp_cs.add(condition == False) self.assertFalse(solver.check(temp_cs)) if __name__ == '__main__': unittest.main()