diff --git a/manticore/core/executor.py b/manticore/core/executor.py index 1f8daa3..60786b0 100644 --- a/manticore/core/executor.py +++ b/manticore/core/executor.py @@ -479,12 +479,6 @@ class Executor(object): current_state = None except TerminateState as e: - #logger.error("MemoryException at PC: 0x{:016x}. Cause: {}\n".format(current_state.cpu.instruction.address, e.cause)) - #self.generate_testcase(current_state, "Memory Exception: " + str(e)) - #self.generate_testcase(current_state, "Invalid PC Exception" + str(e)) - #self.generate_testcase(current_state, "Program finished correctly") - #logger.error("Syscall not implemented: %s", str(e)) - #Notify this worker is done self.will_terminate_state(current_state, current_state_id, e) diff --git a/manticore/core/memory.py b/manticore/core/memory.py index 60e58d7..ba5539e 100644 --- a/manticore/core/memory.py +++ b/manticore/core/memory.py @@ -8,38 +8,25 @@ from ..utils.helpers import issymbolic logger = logging.getLogger('MEMORY') + class MemoryException(Exception): ''' Memory exceptions ''' - def __init__(self, cause, address): + def __init__(self, message, address=None): ''' Builds a memory exception. - :param cause: exception message. + :param message: exception message. :param address: memory address where the exception occurred. ''' - super(MemoryException, self, ).__init__('{} <{}>'.format(cause, address)) - self.cause = cause self.address = address + self.message = message + if address is not None and not issymbolic(address): + self.message += ' <{:x}>'.format(address) def __str__(self): - return '%s <%s>'%(self.cause, '%08x'%self.address) - -class InvalidMemoryAccess(MemoryException): - def __init__(self, address, mode): - self.mode = mode - super(InvalidMemoryAccess, self, ).__init__('Invalid mode trying to access memory in mode {}'.format(mode), address) - -class InvalidSymbolicMemoryAccess(InvalidMemoryAccess): - def __init__(self, cause, address, size, constraint): - super(InvalidSymbolicMemoryAccess, self, ).__init__(cause, address) - #the crashing constraint you need to assert - self.constraint = constraint - self.size = size - - def __str__(self): - return '%s <%s>'%(self.cause, repr(self.address)) + return self.message class ConcretizeMemory(MemoryException): @@ -53,6 +40,28 @@ class ConcretizeMemory(MemoryException): self.size = size self.policy = policy + +class InvalidMemoryAccess(MemoryException): + _message = 'Invalid memory access' + + def __init__(self, address, mode): + assert mode in 'rwx' + suffix = ' (mode:{})'.format(mode) + message = self._message + suffix + super(InvalidMemoryAccess, self, ).__init__(message, address) + self.mode = mode + + +class InvalidSymbolicMemoryAccess(InvalidMemoryAccess): + _message = 'Invalid symbolic memory access' + + def __init__(self, address, mode, size, constraint): + super(InvalidSymbolicMemoryAccess, self, ).__init__(address, mode) + #the crashing constraint you need to assert + self.constraint = constraint + self.size = size + + class Map(object): ''' A memory map. @@ -501,7 +510,7 @@ class Memory(object): return p << self.page_bit_size counter+=1 if counter >= self.memory_size/self.page_size: - raise MemoryException('Not enough memory', 0) + raise MemoryException('Not enough memory') return self._search( size, self.memory_size-size, counter ) @@ -752,7 +761,7 @@ class Memory(object): #write and read potentially symbolic bytes at symbolic indexes def read(self, addr, size): if not self.access_ok(slice(addr, addr+size), 'r'): - raise MemoryException('No access reading', addr) + raise InvalidMemoryAccess(addr, 'r') assert size > 0 result = [] @@ -806,7 +815,7 @@ class Memory(object): def write(self, addr, buf): size = len(buf) if not self.access_ok(slice(addr, addr + size), 'w'): - raise MemoryException('No access writing', addr) + raise InvalidMemoryAccess(addr, 'w') assert size > 0 stop = addr + size start = addr @@ -913,10 +922,9 @@ class SMemory(Memory): logger.debug('Reading %d bytes from symbolic address %s', size, address) try: solutions = solver.get_all_values(self.constraints, address, maxcnt=0x1000) #if more than 0x3000 exception - except TooManySolutions, e: + except TooManySolutions as e: m, M = solver.minmax(self.constraints, address) - logger.info('Got TooManySolutions on a symbolic read. Range [%x, %x]. Not crashing!', m, M) - logger.info('Memory:%s', self) + logger.debug('Got TooManySolutions on a symbolic read. Range [%x, %x]. Not crashing!', m, M) crashing_condition = True for start, end, perms, offset, name in self.mappings(): @@ -925,7 +933,7 @@ class SMemory(Memory): crashing_condition = Operators.AND(Operators.OR( (address+size).ult(start), address.uge(end) ), crashing_condition) if solver.can_be_true(self.constraints, crashing_condition): - raise InvalidSymbolicMemoryAccess('No access reading symbolic', address, size, crashing_condition) + raise InvalidSymbolicMemoryAccess(address, 'r', size, crashing_condition) #INCOMPLETE Result! We could also fork once for every map @@ -945,7 +953,7 @@ class SMemory(Memory): crashing_condition = Operators.OR(address == base, crashing_condition) if solver.can_be_true(self.constraints, crashing_condition): - raise InvalidSymbolicMemoryAccess('No access reading symbolic', address, size, crashing_condition) + raise InvalidSymbolicMemoryAccess(address, 'r', size, crashing_condition) condition = False for base in solutions: @@ -997,7 +1005,7 @@ class SMemory(Memory): crashing_condition = Operators.OR(address == base, crashing_condition) if solver.can_be_true(self.constraints, crashing_condition): - raise InvalidSymbolicMemoryAccess('No access writing symbolic', address, size, crashing_condition) + raise InvalidSymbolicMemoryAccess(address, 'w', size, crashing_condition) for offset in xrange(size): for base in solutions: @@ -1009,7 +1017,7 @@ class SMemory(Memory): for offset in xrange(size): if issymbolic(value[offset]): if not self.access_ok(address+offset, 'w'): - raise MemoryException('No access writing', address+offset) + raise InvalidMemoryAccess(address+offset, 'w') self._symbols[address+offset] = [(True, value[offset])] else: # overwrite all previous items diff --git a/manticore/core/state.py b/manticore/core/state.py index 2561145..0d72ed8 100644 --- a/manticore/core/state.py +++ b/manticore/core/state.py @@ -9,20 +9,19 @@ from ..utils.event import Signal, forward_signals #import exceptions from .cpu.abstractcpu import ConcretizeRegister -from .memory import ConcretizeMemory +from .memory import ConcretizeMemory, MemoryException from ..platforms.platform import * class StateException(Exception): ''' All state related exceptions ''' - def __init__(self, *args, **kwargs): - super(StateException, self).__init__(*args) - + pass + class TerminateState(StateException): ''' Terminates current state exploration ''' - def __init__(self, *args, **kwargs): - super(TerminateState, self).__init__(*args, **kwargs) - self.testcase = kwargs.get('testcase', False) + def __init__(self, message, testcase=False): + super(TerminateState, self).__init__(message) + self.testcase = testcase class Concretize(StateException): @@ -138,6 +137,8 @@ class State(object): expression=expression, setstate=setstate, policy=e.policy) + except MemoryException as e: + raise TerminateState(e.message, testcase=True) #Remove when code gets stable? assert self.platform.constraints is self.constraints diff --git a/manticore/platforms/windows.py b/manticore/platforms/windows.py index 9d1cb98..07a6627 100644 --- a/manticore/platforms/windows.py +++ b/manticore/platforms/windows.py @@ -581,7 +581,7 @@ class kernel32(object): try: key_str = readStringFromPointer(platform, cpu, lpSubKey, utf16) except MemoryException as me: - raise MemoryException("{}: {}".format(myname, me.cause), 0xFFFFFFFF) + raise MemoryException("{}: {}".format(myname, me.message), 0xFFFFFFFF) except SymbolicAPIArgument: raise ConcretizeArgument(platform.current, 1) @@ -645,7 +645,7 @@ class kernel32(object): try: key_str = readStringFromPointer(platform, cpu, lpSubKey, utf16) except MemoryException as me: - raise MemoryException("{}: {}".format(myname, me.cause), 0xFFFFFFFF) + raise MemoryException("{}: {}".format(myname, me.message), 0xFFFFFFFF) except SymbolicAPIArgument: raise ConcretizeArgument(platform.current, 1) @@ -744,7 +744,7 @@ class kernel32(object): try: filename = readStringFromPointer(platform, cpu, lpFileName, utf16) except MemoryException as me: - msg = "CreateFile{}: {}".format(utf16 and "W" or "A", me.cause) + msg = "CreateFile{}: {}".format(utf16 and "W" or "A", me.message) raise MemoryException(msg, 0xFFFFFFFF) except SymbolicAPIArgument: raise ConcretizeArgument(platform.current, 0) @@ -850,7 +850,7 @@ class kernel32(object): try: appname = readStringFromPointer(platform, cpu, lpApplicationName, utf16) except MemoryException as me: - msg = "{}: {}".format(myname, me.cause) + msg = "{}: {}".format(myname, me.message) raise MemoryException(msg, 0xFFFFFFFF) except SymbolicAPIArgument: raise ConcretizeArgument(platform.current, 0) @@ -858,7 +858,7 @@ class kernel32(object): try: cmdline = readStringFromPointer(platform, cpu, lpCommandLine, utf16) except MemoryException as me: - msg = "{}: {}".format(myname, me.cause) + msg = "{}: {}".format(myname, me.message) raise MemoryException(msg, 0xFFFFFFFF) except SymbolicAPIArgument: raise ConcretizeArgument(platform.current, 1) diff --git a/tests/test_memory.py b/tests/test_memory.py index ca5109a..f532151 100644 --- a/tests/test_memory.py +++ b/tests/test_memory.py @@ -1280,7 +1280,9 @@ class MemoryTest(unittest.TestCase): self.assertEqual(mem[addr], 'a') mem.mprotect(addr, size, 'w') - self.assertRaisesRegexp(MemoryException, "No access reading <%08x>"%addr, mem.__getitem__, addr) + with self.assertRaisesRegexp(InvalidMemoryAccess, 'Invalid memory access \(mode:.\) <{:x}>'.format(addr)): + _ = mem[addr] + def testmprotectFailSymbReading(self): @@ -1333,7 +1335,10 @@ class MemoryTest(unittest.TestCase): #print map(hex,sorted(solver.get_all_values(cs, x, 0x100000))), map(hex,solver.minmax(cs, x)), mem[x] #No Access Reading <4160741376> - self.assertRaisesRegexp(MemoryException, r"No access reading.*", mem.__getitem__, x) + # self.assertRaisesRegexp(MemoryException, r"No access reading.*", mem.__getitem__, x) + with self.assertRaisesRegexp(InvalidSymbolicMemoryAccess, 'Invalid symbolic memory access.*'.format(addr)): + _ = mem[x] + # mem[addr] = 'a' def testmprotectFailWriting(self): mem = Memory32() @@ -1346,7 +1351,8 @@ class MemoryTest(unittest.TestCase): addr = mem.mmap(None, size, 'wx') mem[addr] = 'a' mem.mprotect(addr, size, 'r') - self.assertRaisesRegexp(MemoryException, "No access writing <%08x>"%addr, mem.__setitem__, addr, 'a') + with self.assertRaisesRegexp(InvalidMemoryAccess, 'Invalid memory access \(mode:w\) <{:x}>'.format(addr)): + mem[addr] = 'a' def testmprotecNoReadthenOkRead(self): mem = Memory32() @@ -1359,7 +1365,8 @@ class MemoryTest(unittest.TestCase): addr = mem.mmap(None, size, 'wx') mem[addr] = 'a' - self.assertRaisesRegexp(MemoryException, "No access reading <%08x>"%addr, mem.__getitem__, addr) + with self.assertRaisesRegexp(InvalidMemoryAccess, 'Invalid memory access \(mode:r\) <{:x}>'.format(addr)): + _ = mem[addr] mem.mprotect(addr, size, 'r') self.assertEqual(mem[addr], 'a')