Revision ad797ce7f8c1b6f92c47e21e0cf3798c47134ad7 authored by yan on 11 September 2018, 21:32:40 UTC, committed by yan on 11 September 2018, 21:32:40 UTC
1 parent 3ff1d46
test_cpu_manual.py
import struct
import unittest
from manticore.core.cpu.x86 import *
from manticore.core.smtlib import Operators
from manticore.core.memory import *
from tests import mockmem
from functools import reduce
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<<self.size)-1)
class RWOperand(ROOperand):
''' Mocking class for operand rw '''
def write(self, value):
self.value = value & ((1<<self.size)-1)
return self.value
sizes = {'RAX': 64, 'EAX': 32, 'AX': 16, 'AL': 8, 'AH': 8, 'RCX': 64, 'ECX': 32, 'CX': 16, 'CL': 8, 'CH': 8, 'RDX': 64, 'EDX': 32, 'DX': 16, 'DL': 8, 'DH': 8, 'RBX': 64, 'EBX': 32, 'BX': 16, 'BL': 8, 'BH': 8, 'RSP': 64, 'ESP': 32, 'SP': 16, 'SPL': 8, 'RBP': 64, 'EBP': 32, 'BP': 16, 'BPL': 8, 'RSI': 64, 'ESI': 32, 'SI': 16, 'SIL': 8, 'RDI': 64, 'EDI': 32, 'DI': 16, 'DIL': 8, 'R8': 64, 'R8D': 32, 'R8W': 16, 'R8B': 8, 'R9': 64, 'R9D': 32, 'R9W': 16, 'R9B': 8, 'R10': 64, 'R10D': 32, 'R10W': 16, 'R10B': 8, 'R11': 64, 'R11D': 32, 'R11W': 16, 'R11B': 8, 'R12': 64, 'R12D': 32, 'R12W': 16, 'R12B': 8, 'R13': 64, 'R13D': 32, 'R13W': 16, 'R13B': 8, 'R14': 64, 'R14D': 32, 'R14W': 16, 'R14B': 8, 'R15': 64, 'R15D': 32, 'R15W': 16, 'R15B': 8, 'ES': 16, 'CS': 16, 'SS': 16, 'DS': 16, 'FS': 16, 'GS': 16, 'RIP': 64, 'EIP':32, 'IP': 16, 'RFLAGS': 64, 'EFLAGS': 32, 'FLAGS': 16, 'XMM0': 128, 'XMM1': 128, 'XMM2': 128, 'XMM3': 128, 'XMM4': 128, 'XMM5': 128, 'XMM6': 128, 'XMM7': 128, 'XMM8': 128, 'XMM9': 128, 'XMM10': 128, 'XMM11': 128, 'XMM12': 128, 'XMM13': 128, 'XMM14': 128, 'XMM15': 128, 'YMM0': 256, 'YMM1': 256, 'YMM2': 256, 'YMM3': 256, 'YMM4': 256, 'YMM5': 256, 'YMM6': 256, 'YMM7': 256, 'YMM8': 256, 'YMM9': 256, 'YMM10': 256, 'YMM11': 256, 'YMM12': 256, 'YMM13': 256, 'YMM14': 256, 'YMM15': 256}
def to_bytelist(bs):
return [bytes([b]) for b in bs]
class SymCPUTest(unittest.TestCase):
_multiprocess_can_split_ = True
_flag_offsets = {
'CF': 0,
'PF': 2,
'AF': 4,
'ZF': 6,
'SF': 7,
'IF': 9,
'DF': 10,
'OF': 11,
}
_flags={
'CF': 0x00001,
'PF': 0x00004,
'AF': 0x00010,
'ZF': 0x00040,
'SF': 0x00080,
'DF': 0x00400,
'OF': 0x00800,
'IF': 0x00200,}
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<<self.size)-1)
class RWOperand(ROOperand):
''' Mocking class for operand rw '''
def write(self, value):
self.value = value & ((1<<self.size)-1)
return self.value
def setUp(self):
mem = mockmem.Memory()
self.cpu = I386Cpu(mem) #TODO reset cpu in between tests...
#TODO mock getchar/putchar in case the instructon access memory directly
def tearDown(self):
self.cpu = None
def assertItemsEqual(self, a, b):
# Required for Python3 compatibility
self.assertEqual(sorted(a), sorted(b))
def assertEqItems(self, a, b):
if isinstance(b, bytes):
b = [bytes([x]) for x in b]
return self.assertItemsEqual(a, b)
def testInitialRegState(self):
cpu = self.cpu
#'CR0', 'CR1', 'CR2', 'CR3', 'CR4', 'CR5', 'CR6', 'CR7', 'CR8',
# 'DR0', 'DR1', 'DR2', 'DR3', 'DR4', 'DR5', 'DR6', 'DR7',
#'MM0', 'MM1', 'MM2', 'MM3', 'MM4', 'MM5', 'MM6', 'MM7',
# 'ST0', 'ST1', 'ST2', 'ST3', 'ST4', 'ST5', 'ST6', 'ST7'
values = {
'RFLAGS': 0x0,
'TOP': 0x7,
'FP0': (0,0),
'FP1': (0,0),
'FP2': (0,0),
'FP3': (0,0),
'FP4': (0,0),
'FP5': (0,0),
'FP6': (0,0),
'FP7': (0,0),
'CS': 0x0,
'SS': 0x0,
'DS': 0x0,
'ES': 0x0}
for reg_name in cpu.canonical_registers:
if len(reg_name) > 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 range(0x10):
self.assertEqual(mem[i+0x1000], b'HGFEXWVUhgfedcba'[i:i+1])
self.assertEqual(mem.read(0x1000,0x10), to_bytelist(b'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 range(0x10):
self.assertEqual(mem[i+0x1000], b'HGFEXWVUhgfedcba'[i:i+1])
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 = bytearray(0x1000)
written = set()
for _ in range(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('<Q',value))
cpu.write_int(address, value, 64)
if random.randint(0,10) > 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:'<H', 32:'<L', 64:'<Q'} [size]
start = address - 0x1000
self.assertEqual(cpu.read_int(address, size),
struct.unpack(pattern, bytes(memory[start:start + (size // 8)]))[0])
def test_cache_005(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)
self.assertRaises(Exception, cpu.write_int, 0x1000-1, 0x414243445464748, 64)
self.assertRaises(Exception, cpu.write_int, 0x2000-7, 0x414243445464748, 64)
self.assertRaises(Exception, cpu.read_int, 0x1000-1, 0x414243445464748, 64)
self.assertRaises(Exception, cpu.read_int, 0x2000-7, 0x414243445464748, 64)
#alloc/map a little mem
addr = mem.mmap(0x7000, 0x1000, 'r')
self.assertEqual(addr, 0x7000)
self.assertRaises(Exception, cpu.write_int, 0x7000-1, 0x414243445464748, 64)
self.assertRaises(Exception, cpu.write_int, 0x8000-7, 0x414243445464748, 64)
self.assertRaises(Exception, cpu.read_int, 0x7000-1, 0x414243445464748, 64)
self.assertRaises(Exception, cpu.read_int, 0x8000-7, 0x414243445464748, 64)
self.assertRaises(Exception, cpu.write_int, 0x7100, 0x414243445464748, 64)
#alloc/map a little mem
addr = mem.mmap(0xf000, 0x1000, 'w')
self.assertEqual(addr, 0xf000)
self.assertRaises(Exception, cpu.write_int, 0xf000-1, 0x414243445464748, 64)
self.assertRaises(Exception, cpu.write_int, 0x10000-7, 0x414243445464748, 64)
self.assertRaises(Exception, cpu.read_int, 0xf000-1, 0x414243445464748, 64)
self.assertRaises(Exception, cpu.read_int, 0x10000-7, 0x414243445464748, 64)
self.assertRaises(Exception, cpu.read_int, 0xf100, 0x414243445464748, 64)
def test_IDIV_concrete(self):
cs = ConstraintSet()
mem = SMemory32(cs)
cpu = I386Cpu(mem)
#alloc/map a little mem
code = mem.mmap(0x1000, 0x1000, 'rwx')
stack = mem.mmap(0xf000, 0x1000, 'rw')
mem[code:code+3] = '\xf7\x7d\xf4'
cpu.EIP = code
cpu.EAX = 116
cpu.EBP=stack+0x700
cpu.write_int(cpu.EBP - 0xc, 100, 32)
cpu.execute()
self.assertEqual(cpu.EAX, 1)
def test_IDIV_symbolic(self):
cs = ConstraintSet()
mem = SMemory32(cs)
cpu = I386Cpu(mem)
#alloc/map a little mem
code = mem.mmap(0x1000, 0x1000, 'rwx')
stack = mem.mmap(0xf000, 0x1000, 'rw')
mem[code:code+3] = '\xf7\x7d\xf4'
cpu.EIP = code
cpu.EAX = cs.new_bitvec(32, 'EAX')
cs.add(cpu.EAX == 116)
cpu.EBP = cs.new_bitvec(32, 'EBP')
cs.add(cpu.EBP == stack+0x700)
value = cs.new_bitvec(32, 'VALUE')
cpu.write_int(cpu.EBP - 0xc, value, 32)
cs.add(value == 100)
cpu.execute()
cs.add(cpu.EAX == 1)
self.assertTrue(solver.check(cs))
def test_IDIV_grr001(self):
cs = ConstraintSet()
mem = SMemory32(cs)
cpu = I386Cpu(mem)
#alloc/map a little mem
code = mem.mmap(0x1000, 0x1000, 'rwx')
mem[code:code+2] = '\xf7\xf9'
cpu.EIP = code
cpu.EAX = 0xffffffff
cpu.EDX = 0xffffffff
cpu.ECX = 0x32
cpu.execute()
self.assertEqual(cpu.EAX, 0)
def test_IDIV_grr001_symbolic(self):
cs = ConstraintSet()
mem = SMemory32(cs)
cpu = I386Cpu(mem)
#alloc/map a little mem
code = mem.mmap(0x1000, 0x1000, 'rwx')
mem[code:code+2] = '\xf7\xf9'
cpu.EIP = code
cpu.EAX = cs.new_bitvec(32, 'EAX')
cs.add(cpu.EAX == 0xffffffff)
cpu.EDX = cs.new_bitvec(32, 'EDX')
cs.add(cpu.EDX == 0xffffffff)
cpu.ECX = cs.new_bitvec(32, 'ECX')
cs.add(cpu.ECX == 0x32)
cpu.execute()
cs.add(cpu.EAX == 0)
self.assertTrue(solver.check(cs))
def test_ADC_001(self):
'''INSTRUCTION: 0x0000000067756f91: adc esi, edx'''
cs = ConstraintSet()
mem = SMemory32(cs)
cpu = I386Cpu(mem)
#alloc/map a little mem
code = mem.mmap(0x1000, 0x1000, 'rwx')
mem[code:code+2] = '\x13\xf2'
cpu.EIP = code
cpu.ESI = 0x0
cpu.EDX = 0xffffffff
cpu.CF = True
cpu.execute()
self.assertEqual(cpu.EDX, 0xffffffff)
self.assertEqual(cpu.ESI, 0)
self.assertEqual(cpu.CF, True)
def test_ADC_001_symbolic(self):
'''INSTRUCTION: 0x0000000067756f91: adc esi, edx'''
cs = ConstraintSet()
mem = SMemory32(cs)
cpu = I386Cpu(mem)
#alloc/map a little mem
code = mem.mmap(0x1000, 0x1000, 'rwx')
mem[code:code+2] = '\x13\xf2'
cpu.EIP = code
cpu.ESI = cs.new_bitvec(32, 'ESI')
cs.add(cpu.ESI == 0)
cpu.EDX = cs.new_bitvec(32, 'EDX')
cs.add(cpu.EDX == 0xffffffff)
cpu.CF = cs.new_bool('CF')
cs.add(cpu.CF)
cpu.execute()
cs.add(cpu.ESI == 0)
cs.add(cpu.EDX == 0xffffffff)
cs.add(cpu.CF)
self.assertTrue(solver.check(cs))
# regression test for issue #560
def test_AND_1(self):
''' Instruction AND
Groups:
0x7ffff7de390a: and rax, 0xfc000000
'''
mem = Memory64()
cpu = AMD64Cpu(mem)
mem.mmap(0x7ffff7de3000, 0x1000, 'rwx')
mem[0x7ffff7de390a] = '\x48'
mem[0x7ffff7de390b] = '\x25'
mem[0x7ffff7de390c] = '\x00'
mem[0x7ffff7de390d] = '\x00'
mem[0x7ffff7de390e] = '\x00'
mem[0x7ffff7de390f] = '\xfc'
cpu.PF = True
cpu.RAX = 0x7ffff7ff7658
cpu.OF = False
cpu.ZF = False
cpu.CF = False
cpu.RIP = 0x7ffff7de390a
cpu.SF = False
cpu.execute()
self.assertEqual(mem[0x7ffff7de390a], b'\x48')
self.assertEqual(mem[0x7ffff7de390b], b'\x25')
self.assertEqual(mem[0x7ffff7de390c], b'\x00')
self.assertEqual(mem[0x7ffff7de390d], b'\x00')
self.assertEqual(mem[0x7ffff7de390e], b'\x00')
self.assertEqual(mem[0x7ffff7de390f], b'\xfc')
self.assertEqual(cpu.PF, True)
self.assertEqual(cpu.RAX, 0x7ffff4000000)
self.assertEqual(cpu.OF, False)
self.assertEqual(cpu.ZF, False)
self.assertEqual(cpu.CF, False)
self.assertEqual(cpu.RIP, 0x7ffff7de3910)
self.assertEqual(cpu.SF, False)
def test_CMPXCHG8B_symbolic(self):
'''CMPXCHG8B'''
cs = ConstraintSet()
mem = SMemory32(cs)
cpu = I386Cpu(mem)
#alloc/map a little mem
code = mem.mmap(0x1000, 0x1000, 'rwx')
data = mem.mmap(0x2000, 0x1000, 'rwx')
mem[code:code+5] = '\xf0\x0f\xc7\x0f;'
cpu.EIP = code
cpu.EDI = cs.new_bitvec(32, 'EDI')
cs.add( Operators.OR(cpu.EDI == 0x2000, cpu.EDI == 0x2100, cpu.EDI == 0x2200 ) )
self.assertEqual(sorted(solver.get_all_values(cs, cpu.EDI)),[0x2000,0x2100,0x2200])
self.assertEqual(cpu.read_int(0x2000,64), 0)
self.assertEqual(cpu.read_int(0x2100,64), 0)
self.assertEqual(cpu.read_int(0x2200,64), 0)
self.assertItemsEqual(solver.get_all_values(cs, cpu.read_int(cpu.EDI,64)), [0])
#self.assertEqual(cpu.read_int(cpu.EDI,64), 0 )
cpu.write_int(0x2100, 0x4142434445464748, 64)
cpu.EAX = cs.new_bitvec(32, 'EAX')
cs.add( Operators.OR(cpu.EAX == 0x41424344, cpu.EAX == 0x0badf00d, cpu.EAX == 0xf7f7f7f7 ) )
cpu.EDX= 0x45464748
cpu.execute()
self.assertTrue(solver.check(cs))
self.assertItemsEqual(solver.get_all_values(cs, cpu.read_int(cpu.EDI,64)), [0, 4702394921427289928])
def test_POPCNT(self):
'''POPCNT EAX, EAX
CPU Dump
Address Hex dump
00333689 F3 0F B8 C0
'''
cs = ConstraintSet()
mem = SMemory32(cs)
cpu = I386Cpu(mem)
#alloc/map a little mem
code = mem.mmap(0x1000, 0x1000, 'rwx')
mem[code:code+4] = '\xF3\x0F\xB8\xC0'
cpu.EIP = code
cpu.EAX = 0x75523C33
cpu.execute()
self.assertEqual(cpu.EAX, 0x10)
self.assertEqual(cpu.ZF, False)
def test_DEC_1(self):
''' Instruction DEC_1
Groups: mode64
0x41e10a: dec ecx
'''
mem = Memory64()
cpu = AMD64Cpu(mem)
mem.mmap(0x0041e000, 0x1000, 'rwx')
mem[0x0041e10a] = '\xff'
mem[0x0041e10b] = '\xc9'
cpu.AF = False
cpu.OF = False
cpu.ZF = False
cpu.RIP = 0x41e10a
cpu.PF = False
cpu.SF = False
cpu.ECX = 0xd
cpu.execute()
self.assertItemsEqual(mem[0x41e10a:0x41e10c], to_bytelist(b'\xff\xc9'))
self.assertEqual(cpu.AF, False)
self.assertEqual(cpu.OF, False)
self.assertEqual(cpu.ZF, False)
self.assertEqual(cpu.RIP, 4317452)
self.assertEqual(cpu.PF, True)
self.assertEqual(cpu.SF, False)
self.assertEqual(cpu.ECX, 12)
def test_PUSHFD_1(self):
''' Instruction PUSHFD_1
Groups: not64bitmode
0x8065f6f: pushfd
'''
mem = Memory32()
cpu = I386Cpu(mem)
mem.mmap(0x08065000, 0x1000, 'rwx')
mem.mmap(0xffffc000, 0x1000, 'rwx')
mem[0xffffc600:0xffffc609] = b'\x00\x00\x00\x00\x02\x03\x00\x00\x00'
mem[0x08065f6f] = b'\x9c'
cpu.EIP = 0x8065f6f
cpu.EBP = 0xffffb600
cpu.ESP = 0xffffc604
cpu.CF = True
cpu.OF = True
cpu.AF = True
cpu.ZF = True
cpu.PF = True
cpu.execute()
self.assertItemsEqual(mem[0xffffc600:0xffffc609], to_bytelist(b'\x55\x08\x00\x00\x02\x03\x00\x00\x00'))
self.assertEqual(mem[0x8065f6f], b'\x9c')
self.assertEqual(cpu.EIP, 0x8065f70)
self.assertEqual(cpu.EBP, 0xffffb600)
self.assertEqual(cpu.ESP, 0xffffc600)
def test_XLATB_1(self):
''' Instruction XLATB_1
Groups:
0x8059a8d: xlatb
'''
mem = Memory32()
cpu = I386Cpu(mem)
mem.mmap(0x08059000, 0x1000, 'rwx')
mem.mmap(0xffffd000, 0x1000, 'rwx')
mem[0x08059a8d] = b'\xd7'
mem[0xffffd00a] = b'\x41'
cpu.EBX=0xffffd000
cpu.AL=0x0a
cpu.EIP = 0x8059a8d
cpu.execute()
self.assertEqual(mem[0x8059a8d], b'\xd7')
self.assertEqual(mem[0xffffd00a], b'\x41')
self.assertEqual(cpu.AL, 0x41)
self.assertEqual(cpu.EIP, 134584974)
def test_XLATB_1_symbolic(self):
''' Instruction XLATB_1
Groups:
0x8059a8d: xlatb
'''
cs = ConstraintSet()
mem = SMemory32(cs)
cpu = I386Cpu(mem)
mem.mmap(0x08059000, 0x1000, 'rwx')
mem.mmap(0xffffd000, 0x1000, 'rwx')
mem[0x8059a8d] = '\xd7'
mem[0xffffd00a] = '\x41'
cpu.EIP = 0x8059a8d
cpu.AL=0xa
cpu.EBX=0xffffd000
def test_SAR_1(self):
''' Instruction SAR_1
Groups: mode64
0x41e10a: SAR cl, EBX
Using the SAR instruction to perform a division operation does not produce the same result as the IDIV instruction. The quotient from the IDIV instruction is rounded toward zero, whereas the "quotient" of the SAR instruction is rounded toward negative infinity. This difference is apparent only for negative numbers. For example, when the IDIV instruction is used to divide -9 by 4, the result is -2 with a remainder of -1. If the SAR instruction is used to shift -9 right by two bits, the result is -3 and the "remainder" is +3; however, the SAR instruction stores only the most significant bit of the remainder (in the CF flag).
'''
mem = Memory32()
cpu = I386Cpu(mem)
mem.mmap(0x0041e000, 0x1000, 'rwx')
mem[0x0041e10a] = '\xc1'
mem[0x0041e10b] = '\xf8'
mem[0x0041e10c] = '\x02'
cpu.RIP = 0x41e10a
cpu.PF = True
cpu.SF = True
cpu.ZF = False
cpu.AF = False
cpu.OF = False
cpu.EAX = 0xfffffff7
cpu.execute()
self.assertEqual(cpu.CF, True)
self.assertEqual(cpu.SF, True)
self.assertEqual(cpu.PF, False)
self.assertEqual(cpu.ZF, False)
self.assertEqual(cpu.EAX, 0xfffffffd)
def test_SAR_1_symbolic(self):
cs = ConstraintSet()
mem = SMemory32(cs)
cpu = I386Cpu(mem)
mem.mmap(0x0041e000, 0x1000, 'rwx')
mem[0x0041e10a] = '\xc1'
mem[0x0041e10b] = '\xf8'
mem[0x0041e10c] = '\x02'
cpu.RIP = 0x41e10a
cpu.PF = cs.new_bool();cs.add(cpu.PF == True)
cpu.SF = cs.new_bool();cs.add(cpu.SF == True)
cpu.ZF = cs.new_bool();cs.add(cpu.ZF == False)
cpu.AF = cs.new_bool();cs.add(cpu.AF == False)
cpu.OF = cs.new_bool();cs.add(cpu.OF == False)
cpu.EAX = cs.new_bitvec(32);cs.add(cpu.EAX == 0xfffffff7)
done = False
while not done:
try:
cpu.execute()
#cpu.writeback()
done = True
except ConcretizeRegister as 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.EAX == 0xfffffffd)
condition = Operators.AND(condition, cpu.ZF == False)
condition = Operators.AND(condition, cpu.CF == True)
condition = Operators.AND(condition, cpu.SF == True)
condition = Operators.AND(condition, cpu.PF == False)
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))
def test_SAR_2(self):
''' Instruction SAR_2
'''
mem = Memory32()
cpu = I386Cpu(mem)
mem.mmap(0x0041e000, 0x1000, 'rwx')
mem[0x0041e10a] = '\xc0'
mem[0x0041e10b] = '\xf8'
mem[0x0041e10c] = '\x9f'
cpu.RIP = 0x41e10a
cpu.CF = True
cpu.SF = True
cpu.ZF = False
cpu.AF = False
cpu.OF = False
cpu.PF = False
cpu.EAX = 0xfffffffd
cpu.execute()
self.assertEqual(cpu.PF, True)
self.assertEqual(cpu.SF, True)
self.assertEqual(cpu.ZF, False)
self.assertEqual(cpu.OF, False)
self.assertEqual(cpu.AF, False)
self.assertEqual(cpu.EAX, 0xffffffff)
def test_SAR_2_symbolicsa(self):
cs = ConstraintSet()
mem = SMemory32(cs)
cpu = I386Cpu(mem)
mem.mmap(0x0041e000, 0x1000, 'rwx')
mem[0x0041e10a] = '\xc0'
mem[0x0041e10b] = '\xf8'
mem[0x0041e10c] = '\xff'
cpu.RIP = 0x41e10a
cpu.PF = cs.new_bool();cs.add(cpu.PF == True)
cpu.CF = cs.new_bool();cs.add(cpu.CF == False)
cpu.SF = cs.new_bool();cs.add(cpu.SF == True)
cpu.ZF = cs.new_bool();cs.add(cpu.ZF == False)
cpu.AF = cs.new_bool();cs.add(cpu.AF == False)
cpu.OF = cs.new_bool();cs.add(cpu.OF == False)
cpu.EAX = cs.new_bitvec(32);cs.add(cpu.EAX == 0xffffffff)
done = False
while not done:
try:
cpu.execute()
done = True
except ConcretizeRegister as 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.EAX == 0xffffffff)
condition = Operators.AND(condition, cpu.ZF == False)
condition = Operators.AND(condition, cpu.PF == True)
condition = Operators.AND(condition, cpu.SF == True)
condition = Operators.AND(condition, cpu.CF == 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))
def test_SAR_3_symbolic(self):
''' Instruction SAR_6
eax 0xffffd000 -12288
ecx 0x3d1ce0ff 1025302783
eip 0x80483f3 0x80483f3
eflags 0x287 [ CF PF SF IF ]
0xffffd000: 0x8f
=> 0x80483f0 <main+3>: 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 as 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))
def test_symbolic_instruction(self):
cs = ConstraintSet()
mem = SMemory32(cs)
cpu = I386Cpu(mem)
# alloc/map a little mem
code = mem.mmap(0x1000, 0x1000, 'rwx')
stack = mem.mmap(0xf000, 0x1000, 'rw')
mem[code] = BitVecConstant(8, 0x90)
cpu.EIP = code
cpu.EAX = 116
cpu.EBP = stack + 0x700
cpu.write_int(cpu.EBP - 0xc, 100, 32)
cpu.execute()
self.assertEqual(cpu.EIP, code+1)
if __name__ == '__main__':
unittest.main()
Computing file changes ...