about summary refs log tree commit diff
path: root/unicorn_mode
diff options
context:
space:
mode:
Diffstat (limited to 'unicorn_mode')
-rwxr-xr-xunicorn_mode/build_unicorn_support.sh6
-rw-r--r--unicorn_mode/helper_scripts/unicorn_dumper_gdb.py10
-rw-r--r--unicorn_mode/helper_scripts/unicorn_dumper_pwndbg.py4
-rw-r--r--unicorn_mode/helper_scripts/unicorn_loader.py41
4 files changed, 48 insertions, 13 deletions
diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh
index baca2171..097a2dc9 100755
--- a/unicorn_mode/build_unicorn_support.sh
+++ b/unicorn_mode/build_unicorn_support.sh
@@ -198,10 +198,12 @@ $MAKECMD -j1 || exit 1
 echo "[+] Build process successful!"
 
 echo "[*] Installing Unicorn python bindings..."
+XOPT=
+$PYTHONBIN -m pip install --help 2>/dev/null | grep -q break-system-packages && XOPT=--break-system-packages
 cd unicorn/bindings/python || exit 1
 if [ -z "$VIRTUAL_ENV" ]; then
   echo "[*] Info: Installing python unicornafl using --user"
-  THREADS=$CORES $PYTHONBIN -m pip install --user --force .|| exit 1
+  THREADS=$CORES $PYTHONBIN -m pip install --user $XOPT --force .|| exit 1
 else
   echo "[*] Info: Installing python unicornafl to virtualenv: $VIRTUAL_ENV"
   THREADS=$CORES $PYTHONBIN -m pip install --force .|| exit 1
@@ -211,7 +213,7 @@ echo "[*] Installing Unicornafl python bindings..."
 cd bindings/python || exit 1
 if [ -z "$VIRTUAL_ENV" ]; then
   echo "[*] Info: Installing python unicornafl using --user"
-  THREADS=$CORES $PYTHONBIN -m pip install --user --force .|| exit 1
+  THREADS=$CORES $PYTHONBIN -m pip install --user $XOPT --force .|| exit 1
 else
   echo "[*] Info: Installing python unicornafl to virtualenv: $VIRTUAL_ENV"
   THREADS=$CORES $PYTHONBIN -m pip install --force .|| exit 1
diff --git a/unicorn_mode/helper_scripts/unicorn_dumper_gdb.py b/unicorn_mode/helper_scripts/unicorn_dumper_gdb.py
index 1ac4c9f3..a202ac0e 100644
--- a/unicorn_mode/helper_scripts/unicorn_dumper_gdb.py
+++ b/unicorn_mode/helper_scripts/unicorn_dumper_gdb.py
@@ -89,8 +89,8 @@ def dump_arch_info():
 
 def dump_regs():
     reg_state = {}
-    for reg in current_arch.all_registers:
-        reg_val = get_register(reg)
+    for reg in gef.arch.registers:
+        reg_val = gef.arch.register(reg)
         reg_state[reg.strip().strip("$")] = reg_val
 
     return reg_state
@@ -101,7 +101,9 @@ def dump_process_memory(output_dir):
     final_segment_list = []
 
     # GEF:
-    vmmap = get_process_maps()
+    vmmap = gef.memory.maps
+    memory = GefMemoryManager()
+    
     if not vmmap:
         print("No address mapping information found")
         return final_segment_list
@@ -126,7 +128,7 @@ def dump_process_memory(output_dir):
         if entry.is_readable() and not "(deleted)" in entry.path:
             try:
                 # Compress and dump the content to a file
-                seg_content = read_memory(entry.page_start, entry.size)
+                seg_content = memory.read(entry.page_start, entry.size)
                 if seg_content == None:
                     print(
                         "Segment empty: @0x{0:016x} (size:UNKNOWN) {1}".format(
diff --git a/unicorn_mode/helper_scripts/unicorn_dumper_pwndbg.py b/unicorn_mode/helper_scripts/unicorn_dumper_pwndbg.py
index 7e97f6a7..76eaf54f 100644
--- a/unicorn_mode/helper_scripts/unicorn_dumper_pwndbg.py
+++ b/unicorn_mode/helper_scripts/unicorn_dumper_pwndbg.py
@@ -111,12 +111,14 @@ def dump_regs():
     reg_state = {}
     for reg in pwndbg.gdblib.regs.all:
         reg_val = pwndbg.gdblib.regs[reg]
+        if reg_val is None:
+            continue
         # current dumper script looks for register values to be hex strings
         #         reg_str = "0x{:08x}".format(reg_val)
         #         if "64" in get_arch():
         #             reg_str = "0x{:016x}".format(reg_val)
         #         reg_state[reg.strip().strip('$')] = reg_str
-        reg_state[reg.strip().strip("$")] = reg_val
+        reg_state[reg.strip().strip("$")] = int(reg_val)
     return reg_state
 
 
diff --git a/unicorn_mode/helper_scripts/unicorn_loader.py b/unicorn_mode/helper_scripts/unicorn_loader.py
index c48a7572..a83e7000 100644
--- a/unicorn_mode/helper_scripts/unicorn_loader.py
+++ b/unicorn_mode/helper_scripts/unicorn_loader.py
@@ -21,10 +21,10 @@ import zlib
 
 # Unicorn imports
 from unicornafl import *
-from unicornafl.arm_const import *
-from unicornafl.arm64_const import *
-from unicornafl.x86_const import *
-from unicornafl.mips_const import *
+from unicorn.arm_const import *
+from unicorn.arm64_const import *
+from unicorn.x86_const import *
+from unicorn.mips_const import *
 
 # If Capstone libraries are availible (only check once)
 try:
@@ -87,9 +87,10 @@ class UnicornSimpleHeap(object):
 
     _uc = None  # Unicorn engine instance to interact with
     _chunks = []  # List of all known chunks
+    _chunks_freed = [] # List of all freed chunks
     _debug_print = False  # True to print debug information
 
-    def __init__(self, uc, debug_print=False):
+    def __init__(self, uc, debug_print=False, uaf_check=False):
         self._uc = uc
         self._debug_print = debug_print
 
@@ -101,12 +102,23 @@ class UnicornSimpleHeap(object):
         #    - Allocate at least 1 4k page of memory to make Unicorn happy
         #    - Add guard pages at the start and end of the region
         total_chunk_size = UNICORN_PAGE_SIZE + ALIGN_PAGE_UP(size) + UNICORN_PAGE_SIZE
+
+        if size == 0:
+            return 0
+        
         # Gross but efficient way to find space for the chunk:
         chunk = None
         for addr in range(self.HEAP_MIN_ADDR, self.HEAP_MAX_ADDR, UNICORN_PAGE_SIZE):
             try:
                 self._uc.mem_map(addr, total_chunk_size, UC_PROT_READ | UC_PROT_WRITE)
                 chunk = self.HeapChunk(addr, total_chunk_size, size)
+
+                if self.uaf_check:
+                    for chunk_freed in self._chunks_freed:
+                        if chunk_freed.is_buffer_in_chunk(chunk.data_addr, 1):
+                            self._chunks_freed.remove(chunk_freed)
+                            break
+
                 if self._debug_print:
                     print(
                         "Allocating 0x{0:x}-byte chunk @ 0x{1:016x}".format(
@@ -148,6 +160,9 @@ class UnicornSimpleHeap(object):
         return new_chunk_addr
 
     def free(self, addr):
+        if addr == 0:
+            return False
+        
         for chunk in self._chunks:
             if chunk.is_buffer_in_chunk(addr, 1):
                 if self._debug_print:
@@ -157,9 +172,14 @@ class UnicornSimpleHeap(object):
                         )
                     )
                 self._uc.mem_unmap(chunk.actual_addr, chunk.total_size)
+
+                if self.uaf_check:
+                    self._chunks_freed.append(chunk)
+                    
                 self._chunks.remove(chunk)
                 return True
-        return False
+        # Freed an object that doesn't exist. Maybe 'dobule-free' or 'invalid free' vulnerability here.
+        self._uc.force_crash(UcError(UC_ERR_FETCH_UNMAPPED))
 
     # Implements basic guard-page functionality
     def __check_mem_access(self, uc, access, address, size, value, user_data):
@@ -179,6 +199,15 @@ class UnicornSimpleHeap(object):
                     # Force a memory-based crash
                     uc.force_crash(UcError(UC_ERR_READ_PROT))
 
+        if self.uaf_check:
+            for chunk in self._chunks_freed:
+                if address >= chunk.actual_addr and (
+                    (address + size) <= (chunk.actual_addr + chunk.total_size)
+                ):
+                    if chunk.is_buffer_in_chunk(address, size):
+                        print("Use-after-free @ 0x{0:016x}".format(address))
+                        uc.force_crash(UcError(UC_ERR_FETCH_UNMAPPED))
+
 
 # ---------------------------
 # ---- Loading function