diff options
| author | William Bruneau <william.bruneau@epfedu.fr> | 2022-02-22 14:54:54 +0100 |
|---|---|---|
| committer | William Bruneau <william.bruneau@epfedu.fr> | 2022-02-23 08:44:51 +0100 |
| commit | 321d298a5265e94fde00c3c8068dc87612ac1e5a (patch) | |
| tree | 8ba3b4493e038f12ecae6e4dade2f2feab37f807 | |
| parent | 53f1cbece50351d59ad22b09b4606138f980f0ba (diff) | |
| download | miasm-321d298a5265e94fde00c3c8068dc87612ac1e5a.tar.gz miasm-321d298a5265e94fde00c3c8068dc87612ac1e5a.zip | |
Add memory breakpoints in debugger and examples
| -rw-r--r-- | example/jitter/memory_breakpoint.py | 55 | ||||
| -rw-r--r-- | miasm/analysis/debugging.py | 72 | ||||
| -rw-r--r-- | miasm/jitter/jitload.py | 6 | ||||
| -rw-r--r-- | test/jitter/mem_breakpoint.py | 4 | ||||
| -rw-r--r-- | test/jitter/test_post_instr.py | 4 |
5 files changed, 122 insertions, 19 deletions
diff --git a/example/jitter/memory_breakpoint.py b/example/jitter/memory_breakpoint.py new file mode 100644 index 00000000..fc41eae8 --- /dev/null +++ b/example/jitter/memory_breakpoint.py @@ -0,0 +1,55 @@ +from __future__ import print_function +import logging +from miasm.analysis.sandbox import Sandbox_Win_x86_32 +from miasm.core.locationdb import LocationDB +from miasm.jitter.csts import PAGE_WRITE, PAGE_READ, EXCEPT_BREAKPOINT_MEMORY + + +parser = Sandbox_Win_x86_32.parser(description="Displays accesses to a specified memory space") +parser.add_argument("filename", help="PE Filename") +parser.add_argument("memory_address", + help="Starting address of the memory space") +parser.add_argument("size", + help="Size of the address space") +parser.add_argument("--access", + help="Access type", + choices=["r", "w", "rw"], + default="rw") +options = parser.parse_args() + +# Create sandbox +loc_db = LocationDB() +sb = Sandbox_Win_x86_32(loc_db, options.filename, options, globals()) + +# Add a memory breakpoint +address = int(options.memory_address, 0) +size = int(options.size, 0) +access_type = 0 +if 'r' in options.access: + access_type |= PAGE_WRITE +if 'w' in options.access: + access_type |= PAGE_READ +sb.jitter.vm.add_memory_breakpoint(address, size, access_type) +# And add a custom handler for memory breakpoints +def memory_breakpoint_handler(jitter): + memory_read = jitter.vm.get_memory_read() + if len(memory_read) > 0: + print("Read at instruction 0x%s:" % jitter.pc) + for start_address, end_address in memory_read: + print("- from %s to %s" % (hex(start_address), hex(end_address))) + + memory_write = jitter.vm.get_memory_write() + if len(memory_write) > 0: + print("Write at instruction 0x%s:" % jitter.pc) + for start_address, end_address in memory_write: + print("- from %s to %s" % (hex(start_address), hex(end_address))) + + # Cleanup + jitter.vm.set_exception(jitter.vm.get_exception() ^ EXCEPT_BREAKPOINT_MEMORY) + jitter.vm.reset_memory_access() + + return True +sb.jitter.add_exception_handler(EXCEPT_BREAKPOINT_MEMORY, memory_breakpoint_handler) + +# Run +sb.run() diff --git a/miasm/analysis/debugging.py b/miasm/analysis/debugging.py index 56ef8646..849c8a4a 100644 --- a/miasm/analysis/debugging.py +++ b/miasm/analysis/debugging.py @@ -79,8 +79,9 @@ class Debugguer(object): "myjit : jitter instance" self.myjit = myjit self.bp_list = [] # DebugBreakpointSoft list - self.hw_bp_list = [] # DebugBreakpointHard list + self.mem_bp_list = [] # DebugBreakpointMemory list self.mem_watched = [] # Memory areas watched + self.init_memory_breakpoint() def init_run(self, addr): self.myjit.init_run(addr) @@ -95,14 +96,20 @@ class Debugguer(object): def init_memory_breakpoint(self): "Set exception handler on EXCEPT_BREAKPOINT_MEMORY" - raise NotImplementedError("Not implemented") + def exception_memory_breakpoint(jitter): + "Stop the execution and return an identifier" + return ExceptionHandle.memoryBreakpoint() + + self.myjit.add_exception_handler(csts.EXCEPT_BREAKPOINT_MEMORY, + exception_memory_breakpoint) + def add_memory_breakpoint(self, addr, size, read=False, write=False): "add mem bp @[addr, addr + size], on read/write/both" access_type = DebugBreakpointMemory.get_access_type(read=read, write=write) dbm = DebugBreakpointMemory(addr, size, access_type) - self.hw_bp_list.append(dbm) + self.mem_bp_list.append(dbm) self.myjit.vm.add_memory_breakpoint(addr, size, access_type) def remove_breakpoint(self, dbs): @@ -117,7 +124,7 @@ class Debugguer(object): def remove_memory_breakpoint(self, dbm): "remove the DebugBreakpointMemory instance" - self.hw_bp_list.remove(dbm) + self.mem_bp_list.remove(dbm) self.myjit.vm.remove_memory_breakpoint(dbm.addr, dbm.access_type) def remove_memory_breakpoint_by_addr_access(self, addr, read=False, @@ -125,7 +132,7 @@ class Debugguer(object): "remove breakpoints @ addr" access_type = DebugBreakpointMemory.get_access_type(read=read, write=write) - for bp in self.hw_bp_list: + for bp in self.mem_bp_list: if bp.addr == addr and bp.access_type == access_type: self.remove_memory_breakpoint(bp) @@ -156,12 +163,24 @@ class Debugguer(object): print("Breakpoint reached @0x%08x" % res.addr) elif isinstance(res, ExceptionHandle): if res == ExceptionHandle.memoryBreakpoint(): - print("Memory breakpoint reached!") + print("Memory breakpoint reached at instruction 0x%s" % self.myjit.pc) + + memory_read = self.myjit.vm.get_memory_read() + if len(memory_read) > 0: + print("Read:") + for start_address, end_address in memory_read: + print("- from %s to %s" % (hex(start_address), hex(end_address))) + memory_write = self.myjit.vm.get_memory_write() + if len(memory_write) > 0: + print("Write:") + for start_address, end_address in memory_write: + print("- from %s to %s" % (hex(start_address), hex(end_address))) # Remove flag except_flag = self.myjit.vm.get_exception() self.myjit.vm.set_exception(except_flag ^ res.except_flag) - + # Clean memory access data + self.myjit.vm.reset_memory_access() else: raise NotImplementedError("Unknown Except") else: @@ -250,6 +269,14 @@ class DebugCmd(cmd.Cmd, object): for i, b in enumerate(bp_list): print("%d\t0x%08x" % (i, b.addr)) + def print_memory_breakpoints(self): + bp_list = self.dbg.mem_bp_list + if len(bp_list) == 0: + print("No memory breakpoints.") + else: + for _, bp in enumerate(bp_list): + print(str(bp)) + def print_watchmems(self): watch_list = self.dbg.mem_watched if len(watch_list) == 0: @@ -324,6 +351,7 @@ class DebugCmd(cmd.Cmd, object): "r": "run", "i": "info", "b": "breakpoint", + "m": "memory_breakpoint", "s": "step", "d": "dump" } @@ -391,6 +419,7 @@ class DebugCmd(cmd.Cmd, object): "registers", "display", "breakpoints", + "memory_breakpoint", "watchmem" ] @@ -404,6 +433,10 @@ class DebugCmd(cmd.Cmd, object): # Breakpoint self.print_breakpoints() + if arg.startswith("m"): + # Memory breakpoints + self.print_memory_breakpoints() + if arg.startswith("d"): # Display self.update_display_mode() @@ -436,6 +469,31 @@ class DebugCmd(cmd.Cmd, object): print("\tbreakpoint 0x11223344") print("\tbreakpoint 1122 0xabcd") + def do_memory_breakpoint(self, arg): + if arg == "": + self.help_memory_breakpoint() + return + args = arg.split(" ") + if len(args) > 3 or len(args) <= 1: + self.help_memory_breakpoint() + return + address = int(args[0], 0) + size = int(args[1], 0) + if len(args) == 2: + self.dbg.add_memory_breakpoint(address, size, read=True, write=True) + else: + self.dbg.add_memory_breakpoint(address, + size, + read=('r' in args[2]), + write=('w' in args[2])) + + def help_memory_breakpoint(self): + print("Add memory breakpoints to memory space defined by a starting") + print("address and a size on specified access type (default is 'rw').") + print("Example:") + print("\tmemory_breakpoint 0x11223344 0x100 r") + print("\tmemory_breakpoint 1122 10") + def do_step(self, arg): if arg == "": nb = 1 diff --git a/miasm/jitter/jitload.py b/miasm/jitter/jitload.py index d92bf6ad..fb1c1f72 100644 --- a/miasm/jitter/jitload.py +++ b/miasm/jitter/jitload.py @@ -294,13 +294,7 @@ class Jitter(object): return True - def exception_memory_breakpoint(jitter): - "Stop the execution and return an identifier" - return ExceptionHandle.memoryBreakpoint() - self.add_exception_handler(EXCEPT_CODE_AUTOMOD, exception_automod) - self.add_exception_handler(EXCEPT_BREAKPOINT_MEMORY, - exception_memory_breakpoint) def add_breakpoint(self, addr, callback): """Add a callback associated with addr. diff --git a/test/jitter/mem_breakpoint.py b/test/jitter/mem_breakpoint.py index bd51e692..9ec9a06d 100644 --- a/test/jitter/mem_breakpoint.py +++ b/test/jitter/mem_breakpoint.py @@ -71,9 +71,7 @@ jitter.vm.set_mem(0xFFFFFF800901EBEC, decode_hex("FD7BBEA901008052FD030091A26300 jitter.set_trace_log() -jitter.exceptions_handler.callbacks[EXCEPT_BREAKPOINT_MEMORY] = [] -jitter.add_exception_handler(EXCEPT_BREAKPOINT_MEMORY, - mem_breakpoint_handler) +jitter.add_exception_handler(EXCEPT_BREAKPOINT_MEMORY, mem_breakpoint_handler) jitter.vm.add_memory_breakpoint(0xFFFFFF8009080000, 0x8000000, PAGE_READ | PAGE_WRITE) jitter.init_run(0xFFFFFF800901EBEC) diff --git a/test/jitter/test_post_instr.py b/test/jitter/test_post_instr.py index 5a690e6b..896ce597 100644 --- a/test/jitter/test_post_instr.py +++ b/test/jitter/test_post_instr.py @@ -36,9 +36,7 @@ jitter.set_trace_log() def do_not_raise_me(jitter): raise ValueError("Should not be here") -jitter.exceptions_handler.callbacks[EXCEPT_BREAKPOINT_MEMORY] = [] -jitter.add_exception_handler(EXCEPT_BREAKPOINT_MEMORY, - do_not_raise_me) +jitter.add_exception_handler(EXCEPT_BREAKPOINT_MEMORY, do_not_raise_me) jitter.vm.add_memory_breakpoint(0x11000-4, 4, PAGE_READ | PAGE_WRITE) # The memory write pending will raise automod exception |