about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorCaroline Leman <carolinele@users.noreply.github.com>2020-01-25 11:48:54 +0100
committerCaroline Leman <carolinele@users.noreply.github.com>2020-01-28 00:57:07 +0100
commit78107cdcf06294f0e394806d852a610c08308761 (patch)
treef3296fe43cf06620bb04c7c08d162c1e4cf672fb
parent49c7dfc4714aaf4e6fd854bdde6cc1081c92453a (diff)
downloadmiasm-78107cdcf06294f0e394806d852a610c08308761.tar.gz
miasm-78107cdcf06294f0e394806d852a610c08308761.zip
Win_API: Fix VirtualProtect when splitting access rights
Diffstat (limited to '')
-rw-r--r--miasm/os_dep/win_api_x86_32.py66
1 files changed, 46 insertions, 20 deletions
diff --git a/miasm/os_dep/win_api_x86_32.py b/miasm/os_dep/win_api_x86_32.py
index 5e2fb680..7780a9e4 100644
--- a/miasm/os_dep/win_api_x86_32.py
+++ b/miasm/os_dep/win_api_x86_32.py
@@ -185,6 +185,7 @@ class c_winobjs(object):
         self.events_pool = {}
         self.find_data = None
 
+        self.allocated_pages = {}
         self.current_datetime = datetime.datetime(
             year=2017, month=8, day=21,
             hour=13, minute=37,
@@ -757,31 +758,54 @@ def kernel32_VirtualProtect(jitter):
         old = jitter.vm.get_mem_access(args.lpvoid)
         jitter.vm.set_u32(args.lpfloldprotect, ACCESS_DICT_INV[old])
 
-    protect_addr = args.lpvoid - (args.lpvoid % winobjs.alloc_align)
-    for addr, data in jitter.vm.get_all_memory().items():
-        size = data["size"]
-        # Exact match
-        if addr == protect_addr and args.dwsize == size:
+    paddr = args.lpvoid - (args.lpvoid % winobjs.alloc_align)
+    psize = args.dwsize
+    for addr, items in list(winobjs.allocated_pages.items()):
+        alloc_addr, alloc_size = items
+        if not (alloc_addr <= paddr and
+                paddr + psize <= alloc_addr + alloc_size):
+            continue
+        size = jitter.vm.get_all_memory()[addr]["size"]
+        # Page is included in Protect area
+        if (paddr <= addr < addr + size <= paddr + psize):
             log.warn("set page %x %x", addr, ACCESS_DICT[flnewprotect])
             jitter.vm.set_mem_access(addr, ACCESS_DICT[flnewprotect])
             continue
-        # Split memory area
-        if addr <= protect_addr < protect_addr + args.dwsize <= addr + size:
-            part1 = jitter.vm.get_mem(addr, protect_addr + args.dwsize - addr)
-            part2 = jitter.vm.get_mem(protect_addr + args.dwsize,  addr + size - protect_addr - args.dwsize)
+
+        # Page is partly in Protect area: splitting is needed
+        if (addr <= paddr < addr + size or
+            addr <= paddr + psize < addr + size):
+
             old_access = jitter.vm.get_mem_access(addr)
+
+            # splits = [
+            #     addr -> max(paddr, addr)
+            #     max(paddr, addr) -> min(addr + size, paddr + psize)
+            #     min(addr + size, paddr + psize) -> addr + size
+            # ]
+            splits = [
+                (addr, old_access,
+                 jitter.vm.get_mem(addr, max(paddr, addr) - addr)),
+                (max(paddr, addr), ACCESS_DICT[flnewprotect],
+                 jitter.vm.get_mem(
+                     max(paddr, addr),
+                     min(addr + size, paddr + psize) - max(paddr, addr))),
+                (min(addr + size, paddr + psize), old_access,
+                 jitter.vm.get_mem(
+                     min(addr + size, paddr + psize),
+                     addr + size - min(addr + size, paddr + psize)))
+            ]
+
             jitter.vm.remove_memory_page(addr)
-            log.warn("create page %x %x", addr, old_access)
-            log.warn("create page %x %x", protect_addr + args.dwsize, ACCESS_DICT[flnewprotect])
-            jitter.vm.add_memory_page(addr, old_access, part1, "VirtualProtect split")
-            jitter.vm.add_memory_page(protect_addr + args.dwsize, ACCESS_DICT[flnewprotect], part2, "VirtualProtect split")
-            continue
-        # Multi page
-        if (addr <= protect_addr < addr + size or
-            addr < protect_addr + args.dwsize <= addr + size):
-            log.warn("set page %x %x", addr, ACCESS_DICT[flnewprotect])
-            jitter.vm.set_mem_access(addr, ACCESS_DICT[flnewprotect])
-            continue
+            for split_addr, split_access, split_data in splits:
+                if not split_data:
+                    continue
+                log.warn("create page %x %x", split_addr,
+                         ACCESS_DICT[flnewprotect])
+                jitter.vm.add_memory_page(
+                    split_addr, split_access, split_data,
+                    "VirtualProtect split ret 0x%X" % ret_ad)
+                winobjs.allocated_pages[split_addr] = (alloc_addr, alloc_size)
     jitter.func_ret_stdcall(ret_ad, 1)
 
 
@@ -795,6 +819,7 @@ def kernel32_VirtualAlloc(jitter):
 
     if args.lpvoid == 0:
         alloc_addr = winobjs.heap.next_addr(args.dwsize)
+        winobjs.allocated_pages[alloc_addr] = (alloc_addr, args.dwsize)
         jitter.vm.add_memory_page(
             alloc_addr, ACCESS_DICT[args.flprotect], b"\x00" * args.dwsize,
             "Alloc in %s ret 0x%X" % (whoami(), ret_ad))
@@ -805,6 +830,7 @@ def kernel32_VirtualAlloc(jitter):
             jitter.vm.set_mem_access(args.lpvoid, ACCESS_DICT[args.flprotect])
         else:
             alloc_addr = winobjs.heap.next_addr(args.dwsize)
+            winobjs.allocated_pages[alloc_addr] = (alloc_addr, args.dwsize)
             # alloc_addr = args.lpvoid
             jitter.vm.add_memory_page(
                 alloc_addr, ACCESS_DICT[args.flprotect], b"\x00" * args.dwsize,