diff --git a/manticore/native/manticore.py b/manticore/native/manticore.py index 7ddcd82fb..2cf5c2218 100644 --- a/manticore/native/manticore.py +++ b/manticore/native/manticore.py @@ -26,7 +26,6 @@ def __init__(self, path_or_state, argv=None, workspace_url=None, policy='random' if isinstance(path_or_state, str): if not os.path.isfile(path_or_state): raise OSError(f'{path_or_state} is not an existing regular file') - initial_state = _make_initial_state(path_or_state, argv=argv, **kwargs) else: initial_state = path_or_state @@ -79,6 +78,19 @@ def decree(cls, path, concrete_start='', **kwargs): except KeyError: # FIXME(mark) magic parsing for DECREE should raise better error raise Exception(f'Invalid binary: {path}') + @property + def binary_path(self): + """ + Assumes that self._initial_state.platform.program always + refers to current program. Might not be true in case program + calls execve(). + """ + return self._initial_state.platform.program + + ############################### + # Hook Callback Methods + ############################### + def init(self, f): ''' A decorator used to register a hook function to run before analysis begins. Hook @@ -137,32 +149,40 @@ def _hook_callback(self, state, pc, instruction): for cb in self._hooks.get(None, []): cb(state) - ############################################################################# - ############################################################################# - ############################################################################# - # Move all the following elsewhere Not all manticores have this - def _get_symbol_address(self, symbol): - ''' - Return the address of |symbol| within the binary - ''' + ############################### + # Symbol Resolution + ############################### + + def resolve(self, symbol): + """ + A helper method used to resolve a symbol name into a memory address when + injecting hooks for analysis. + + :param symbol: function name to be resolved + :type symbol: string + + :param line: if more functions present, optional line number can be included + :type line: int or None + """ + + with open(self.binary_path, 'rb') as f: - # XXX(yan) This is a bit obtuse; once PE support is updated this should - # be refactored out - if self._binary_type == 'ELF': - self._binary_obj = ELFFile(open(self._binary, 'rb')) + elffile = ELFFile(f) - if self._binary_obj is None: - return NotImplementedError("Symbols aren't supported") + # iterate over sections and identify symbol table section + for section in elffile.iter_sections(): + if not isinstance(section, SymbolTableSection): + continue - for section in self._binary_obj.iter_sections(): - if not isinstance(section, SymbolTableSection): - continue + # get list of symbols by name + symbols = section.get_symbol_by_name(symbol) + if not symbols: + continue - symbols = section.get_symbol_by_name(symbol) - if not symbols: - continue + # return first indexed memory address for the symbol, + return symbols[0].entry['st_value'] - return symbols[0].entry['st_value'] + raise ValueError(f"The {self.binary_path} ELFfile does not contain symbol {symbol}") def _make_initial_state(binary_path, **kwargs): diff --git a/manticore/platforms/decree.py b/manticore/platforms/decree.py index 53a2f7a6e..cd7171b99 100644 --- a/manticore/platforms/decree.py +++ b/manticore/platforms/decree.py @@ -102,6 +102,8 @@ def __init__(self, programs, **kwargs): ''' programs = programs.split(",") super().__init__(path=programs[0], **kwargs) + + self.program = programs[0] self.clocks = 0 self.files = [] self.syscall_trace = [] diff --git a/tests/test_manticore.py b/tests/test_manticore.py index 605d15f19..a0a164753 100644 --- a/tests/test_manticore.py +++ b/tests/test_manticore.py @@ -64,6 +64,15 @@ def test_hook_dec_err(self): def tmp(state): pass + def test_symbol_resolution(self): + dirname = os.path.dirname(__file__) + self.m = Manticore(os.path.join(dirname, 'binaries', 'basic_linux_amd64')) + self.assertTrue(self.m.resolve('sbrk'), 0x449ee0) + + def test_symbol_resolution_fail(self): + with self.assertRaises(ValueError): + self.m.resolve("does_not_exist") + def test_integration_basic_stdin(self): import struct dirname = os.path.dirname(__file__)