diff options
Diffstat (limited to 'lldb_target.py')
| -rw-r--r-- | lldb_target.py | 72 |
1 files changed, 36 insertions, 36 deletions
diff --git a/lldb_target.py b/lldb_target.py index e016005..f587b37 100644 --- a/lldb_target.py +++ b/lldb_target.py @@ -1,14 +1,32 @@ import lldb -from angr.errors import SimConcreteMemoryError, \ - SimConcreteRegisterError -from angr_targets.concrete import ConcreteTarget -from angr_targets.memory_map import MemoryMap - from arch import x86 from snapshot import ProgramState -class LLDBConcreteTarget(ConcreteTarget): +class MemoryMap: + """Description of a range of mapped memory. + + Inspired by https://github.com/angr/angr-targets/blob/master/angr_targets/memory_map.py, + meaning we initially used angr and I wanted to keep the interface when we + switched to a different tool. + """ + def __init__(self, start_address, end_address, name, perms): + self.start_address = start_address + self.end_address = end_address + self.name = name + self.perms = perms + + def __str__(self): + return f'MemoryMap[0x{self.start_address:x}, 0x{self.end_address:x}]' \ + f': {self.name}' + +class ConcreteRegisterError(Exception): + pass + +class ConcreteMemoryError(Exception): + pass + +class LLDBConcreteTarget: def __init__(self, executable: str, argv: list[str] = []): """Construct an LLDB concrete target. Stop at entry. @@ -35,36 +53,25 @@ class LLDBConcreteTarget(ConcreteTarget): raise RuntimeError(f'[In LLDBConcreteTarget.__init__]: Failed to' f' launch process.') - def set_breakpoint(self, addr, **kwargs): + def set_breakpoint(self, addr): command = f'b -a {addr} -s {self.module.GetFileSpec().GetFilename()}' result = lldb.SBCommandReturnObject() self.interpreter.HandleCommand(command, result) - def remove_breakpoint(self, addr, **kwargs): + def remove_breakpoint(self, addr): command = f'breakpoint delete {addr}' result = lldb.SBCommandReturnObject() self.interpreter.HandleCommand(command, result) - def is_running(self): - return self.process.GetState() == lldb.eStateRunning - def is_exited(self): - """Not part of the angr interface, but much more useful than - `is_running`. + """Signals whether the concrete process has exited. :return: True if the process has exited. False otherwise. """ return self.process.GetState() == lldb.eStateExited - def wait_for_running(self): - while self.process.GetState() != lldb.eStateRunning: - pass - - def wait_for_halt(self): - while self.process.GetState() != lldb.eStateStopped: - pass - def run(self): + """Continue execution of the concrete process.""" state = self.process.GetState() if state == lldb.eStateExited: raise RuntimeError(f'Tried to resume process execution, but the' @@ -73,16 +80,10 @@ class LLDBConcreteTarget(ConcreteTarget): self.process.Continue() def step(self): + """Step forward by a single instruction.""" thread: lldb.SBThread = self.process.GetThreadAtIndex(0) thread.StepInstruction(False) - def stop(self): - self.process.Stop() - - def exit(self): - self.debugger.Terminate() - print(f'Program exited with status {self.process.GetState()}') - def _get_register(self, regname: str) -> lldb.SBValue: """Find a register by name. @@ -92,7 +93,7 @@ class LLDBConcreteTarget(ConcreteTarget): frame = self.process.GetThreadAtIndex(0).GetFrameAtIndex(0) reg = frame.FindRegister(regname) if reg is None: - raise SimConcreteRegisterError( + raise ConcreteRegisterError( f'[In LLDBConcreteTarget._get_register]: Register {regname}' f' not found.') return reg @@ -101,7 +102,7 @@ class LLDBConcreteTarget(ConcreteTarget): reg = self._get_register(regname) val = reg.GetValue() if val is None: - raise SimConcreteRegisterError( + raise ConcreteRegisterError( f'[In LLDBConcreteTarget.read_register]: Register has an' f' invalid value of {val}.') @@ -112,7 +113,7 @@ class LLDBConcreteTarget(ConcreteTarget): error = lldb.SBError() reg.SetValueFromCString(hex(value), error) if not error.success: - raise SimConcreteRegisterError( + raise ConcreteRegisterError( f'[In LLDBConcreteTarget.write_register]: Unable to set' f' {regname} to value {hex(value)}!') @@ -120,7 +121,7 @@ class LLDBConcreteTarget(ConcreteTarget): err = lldb.SBError() content = self.process.ReadMemory(addr, size, err) if not err.success: - raise SimConcreteMemoryError(f'Error when reading {size} bytes at' + raise ConcreteMemoryError(f'Error when reading {size} bytes at' f' address {hex(addr)}: {err}') return content @@ -128,7 +129,7 @@ class LLDBConcreteTarget(ConcreteTarget): err = lldb.SBError() res = self.process.WriteMemory(addr, value, err) if not err.success or res != len(value): - raise SimConcreteMemoryError(f'Error when writing to address' + raise ConcreteMemoryError(f'Error when writing to address' f' {hex(addr)}: {err}') def get_mappings(self) -> list[MemoryMap]: @@ -146,7 +147,6 @@ class LLDBConcreteTarget(ConcreteTarget): mmap.append(MemoryMap(region.GetRegionBase(), region.GetRegionEnd(), - 0, # offset? name if name is not None else '<none>', perms)) return mmap @@ -167,7 +167,7 @@ def record_snapshot(target: LLDBConcreteTarget) -> ProgramState: state.set(regname, conc_val) except KeyError: pass - except SimConcreteRegisterError: + except ConcreteRegisterError: if regname in rflags: state.set(regname, rflags[regname]) @@ -178,7 +178,7 @@ def record_snapshot(target: LLDBConcreteTarget) -> ProgramState: try: data = target.read_memory(mapping.start_address, size) state.write_memory(mapping.start_address, data) - except SimConcreteMemoryError: + except ConcreteMemoryError: # Unable to read memory from mapping pass |