about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorWilliam Bruneau <william.bruneau@epfedu.fr>2022-02-22 14:54:54 +0100
committerWilliam Bruneau <william.bruneau@epfedu.fr>2022-02-23 08:44:51 +0100
commit321d298a5265e94fde00c3c8068dc87612ac1e5a (patch)
tree8ba3b4493e038f12ecae6e4dade2f2feab37f807
parent53f1cbece50351d59ad22b09b4606138f980f0ba (diff)
downloadmiasm-321d298a5265e94fde00c3c8068dc87612ac1e5a.tar.gz
miasm-321d298a5265e94fde00c3c8068dc87612ac1e5a.zip
Add memory breakpoints in debugger and examples
-rw-r--r--example/jitter/memory_breakpoint.py55
-rw-r--r--miasm/analysis/debugging.py72
-rw-r--r--miasm/jitter/jitload.py6
-rw-r--r--test/jitter/mem_breakpoint.py4
-rw-r--r--test/jitter/test_post_instr.py4
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