diff options
| -rw-r--r-- | miasm/jitter/vm_mngr.c | 27 | ||||
| -rw-r--r-- | miasm/jitter/vm_mngr.h | 1 | ||||
| -rw-r--r-- | miasm/jitter/vm_mngr_py.c | 19 | ||||
| -rw-r--r-- | miasm/os_dep/win_api_x86_32.py | 53 | ||||
| -rw-r--r-- | test/jitter/vm_mngr.py | 8 | ||||
| -rwxr-xr-x | test/os_dep/win_api_x86_32.py | 47 |
6 files changed, 147 insertions, 8 deletions
diff --git a/miasm/jitter/vm_mngr.c b/miasm/jitter/vm_mngr.c index 53ec9065..0c8a0586 100644 --- a/miasm/jitter/vm_mngr.c +++ b/miasm/jitter/vm_mngr.c @@ -820,7 +820,32 @@ void add_memory_page(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a) vm_mngr->memory_pages_array[i] = *mpn_a; vm_mngr->memory_pages_number ++; +} + +void remove_memory_page(vm_mngr_t* vm_mngr, uint64_t ad) +{ + struct memory_page_node * mpn; + int i; + i = find_page_node(vm_mngr->memory_pages_array, + ad, + 0, + vm_mngr->memory_pages_number - 1); + if (i < 0) { + return; + } + + mpn = &vm_mngr->memory_pages_array[i]; + free(mpn->name); + free(mpn->ad_hp); + memmove(&vm_mngr->memory_pages_array[i], + &vm_mngr->memory_pages_array[i+1], + sizeof(struct memory_page_node) * (vm_mngr->memory_pages_number - i - 1) + ); + vm_mngr->memory_pages_number --; + vm_mngr->memory_pages_array = realloc(vm_mngr->memory_pages_array, + sizeof(struct memory_page_node) * + (vm_mngr->memory_pages_number)); } /* Return a char* representing the repr of vm_mngr_t object */ @@ -961,5 +986,3 @@ _MIASM_EXPORT uint64_t get_exception_flag(vm_mngr_t* vm_mngr) { return vm_mngr->exception_flags; } - - diff --git a/miasm/jitter/vm_mngr.h b/miasm/jitter/vm_mngr.h index 7ae44d99..946d3b48 100644 --- a/miasm/jitter/vm_mngr.h +++ b/miasm/jitter/vm_mngr.h @@ -237,6 +237,7 @@ void reset_memory_page_pool(vm_mngr_t* vm_mngr); void reset_code_bloc_pool(vm_mngr_t* vm_mngr); void dump_code_bloc_pool(vm_mngr_t* vm_mngr); void add_memory_page(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a); +void remove_memory_page(vm_mngr_t* vm_mngr, uint64_t ad); void init_memory_breakpoint(vm_mngr_t* vm_mngr); diff --git a/miasm/jitter/vm_mngr_py.c b/miasm/jitter/vm_mngr_py.c index 69e62fef..8bee0586 100644 --- a/miasm/jitter/vm_mngr_py.c +++ b/miasm/jitter/vm_mngr_py.c @@ -129,6 +129,23 @@ PyObject* vm_add_memory_page(VmMngr* self, PyObject* args) } +PyObject* vm_remove_memory_page(VmMngr* self, PyObject* args) +{ + PyObject *addr; + uint64_t page_addr; + + if (!PyArg_ParseTuple(args, "O", &addr)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(addr, page_addr); + + remove_memory_page(&self->vm_mngr, page_addr); + + Py_INCREF(Py_None); + return Py_None; + + +} PyObject* vm_set_mem_access(VmMngr* self, PyObject* args) { @@ -877,6 +894,8 @@ static PyMethodDef VmMngr_methods[] = { {"add_memory_page",(PyCFunction)vm_add_memory_page, METH_VARARGS, "add_memory_page(address, access, content [, cmt]) -> Maps a memory page at @address of len(@content) bytes containing @content with protection @access\n" "@cmt is a comment linked to the memory page"}, + {"remove_memory_page",(PyCFunction)vm_remove_memory_page, METH_VARARGS, + "remove_memory_page(address) -> removes a previously allocated memory page at @address"}, {"add_memory_breakpoint",(PyCFunction)vm_add_memory_breakpoint, METH_VARARGS, "add_memory_breakpoint(address, size, access) -> Add a memory breakpoint at @address of @size bytes with @access type"}, {"remove_memory_breakpoint",(PyCFunction)vm_remove_memory_breakpoint, METH_VARARGS, diff --git a/miasm/os_dep/win_api_x86_32.py b/miasm/os_dep/win_api_x86_32.py index 606c8792..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,14 +758,54 @@ def kernel32_VirtualProtect(jitter): old = jitter.vm.get_mem_access(args.lpvoid) jitter.vm.set_u32(args.lpfloldprotect, ACCESS_DICT_INV[old]) - log.warn("set page %x %x", args.lpvoid, args.dwsize) - for addr, data in jitter.vm.get_all_memory().items(): - size = data["size"] - # Multi-page - if addr <= args.lpvoid < addr + 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 + + # 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) + 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) @@ -778,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)) @@ -788,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, diff --git a/test/jitter/vm_mngr.py b/test/jitter/vm_mngr.py index 468fb347..0fec1734 100644 --- a/test/jitter/vm_mngr.py +++ b/test/jitter/vm_mngr.py @@ -25,3 +25,11 @@ for i, access_right in enumerate(shuffled_rights): # Check for modification for i, access_right in enumerate(shuffled_rights): assert myjit.vm.get_mem_access(base_addr + i * page_size) == access_right + +# Remove pages +for i in range(len(rights)): + myjit.vm.remove_memory_page(base_addr + i * page_size) + +# Add pages again +for i, access_right in enumerate(rights): + myjit.vm.add_memory_page(base_addr + i * page_size, access_right, data) diff --git a/test/os_dep/win_api_x86_32.py b/test/os_dep/win_api_x86_32.py index 66a4e628..6d1c9835 100755 --- a/test/os_dep/win_api_x86_32.py +++ b/test/os_dep/win_api_x86_32.py @@ -226,9 +226,54 @@ class TestWinAPI(unittest.TestCase): if i: self.assertTrue(vBool) else: self.assertFalse(vBool) + def test_VirtualXXFunctions(self): + def call_vprotect(jitter, addr, size, protect): + jitter.push_uint32_t(0x0) + jitter.push_uint32_t(protect) + jitter.push_uint32_t(size) + jitter.push_uint32_t(addr) + jitter.push_uint32_t(0) + winapi.kernel32_VirtualProtect(jitter) + + jit.push_uint32_t(0x2) + jit.push_uint32_t(0x2) + jit.push_uint32_t(0x4000) + jit.push_uint32_t(0x1000) + jit.push_uint32_t(0) + winapi.kernel32_VirtualAlloc(jit) + alloc_addr = jit.cpu.EAX + + self.assertEqual(jit.vm.get_all_memory()[alloc_addr]["size"], 0x4000) + self.assertEqual(jit.vm.get_all_memory()[alloc_addr]["access"], + winapi.ACCESS_DICT[0x2]) + + # Full area + call_vprotect(jit, alloc_addr, 0x4000, 0x1) + self.assertEqual(jit.vm.get_all_memory()[alloc_addr]["access"], + winapi.ACCESS_DICT[0x1]) + # Splits area [0--1000] [1000 -- 3000] [3000 -- 4000] + call_vprotect(jit, alloc_addr+0x1000, 0x2000, 0x40) + print(jit.vm) + for (addr, size, access) in [ + (alloc_addr, 0x1000, 0x1), + (alloc_addr + 0x1000, 0x2000, 0x40), + (alloc_addr + 0x3000, 0x1000, 0x1) + ]: + self.assertEqual(jit.vm.get_all_memory()[addr]["size"], size) + self.assertEqual(jit.vm.get_all_memory()[addr]["access"], + winapi.ACCESS_DICT[access]) + # Protect over split areas + call_vprotect(jit, alloc_addr, 0x4000, 0x4) + for (addr, size) in [ + (alloc_addr, 0x1000), + (alloc_addr + 0x1000, 0x2000), + (alloc_addr + 0x3000, 0x1000) + ]: + self.assertEqual(jit.vm.get_all_memory()[addr]["size"], size) + self.assertEqual(jit.vm.get_all_memory()[addr]["access"], + winapi.ACCESS_DICT[0x4]) if __name__ == '__main__': testsuite = unittest.TestLoader().loadTestsFromTestCase(TestWinAPI) report = unittest.TextTestRunner(verbosity=2).run(testsuite) exit(len(report.errors + report.failures)) - |