def get_memory_map(): api.Listmemory() t = api.pluginvalue_to_t_table(api.Plugingetvalue(api.VAL_MEMORY)) rv = rpc.GetMemoryMapResult() for i in xrange(t.data.n): mi = rv.memories.add() m = api.void_to_t_memory(api.Getsortedbyselection(t.data, i)) module = api.Findmodule(m.base) module_name = ("'%s'" % module.name) if module else '' mi.access = m.access mi.base = m.base mi.name = str(module_name) mi.size = m.size return rv
def RemoteAllocRWE(addr, size, alloc_type='commit'): """ Allocate memory in debuggee as RWE :param addr: Address or None or 0 :param size: Size, must be greater than 0 :param alloc_type: 'commit' or 'reserve' :return: Address of new allocated memory or None if failed """ at = {'commit': D.MEM_COMMIT, 'reserve': D.MEM_RESERVE}.get(alloc_type) if at is None: raise Exception('Invalid argument: `alloc_type`') rv = C.windll.kernel32.VirtualAllocEx(api.Plugingetvalue(api.VAL_HPROCESS), addr, size, at, D.PAGE_EXECUTE_READWRITE) if not rv: last_error = C.windll.kernel32.GetLastError() if last_error: print >> sys.stderr, '[-] VirtualAllocEx failed with error: %x' % last_error return rv
def jump_to_from(is_to, base, remote_base, to=None): rv = rpc.JumpToFromResult() ptrdiff = 0 if base != remote_base: ptrdiff = remote_base - base if is_to: api.Setcpu( 0, int(to + ptrdiff), 0, 0, api.CPU_ASMHIST | api.CPU_ASMCENTER | api.CPU_ASMFOCUS | api.CPU_REDRAW) rv.result = rpc.JumpToFromResult.JR_OK return rv dmp = api.pluginvalue_to_t_dump(api.Plugingetvalue(api.VAL_CPUDASM)) va = int(dmp.sel0) if va: rv.va = va - ptrdiff rv.result = rpc.JumpToFromResult.JR_OK else: rv.result = rpc.JumpToFromResult.JR_FAILED return rv
def safe_read_chunked_memory_region_as_one(base, size): mbi = D.MEMORY_BASIC_INFORMATION() VirtualQueryEx = C.windll.kernel32.VirtualQueryEx VirtualProtectEx = C.windll.kernel32.VirtualProtectEx GRANULARITY = 0x1000 h_process = wintypes.HANDLE(api.Plugingetvalue(api.VAL_HPROCESS)) try: rv = bytearray(size) except MemoryError: return guarded = list() gpoints = dict() protect = 0 queried = VirtualQueryEx(h_process, C.c_void_p(base), C.byref(mbi), C.sizeof(mbi)) if queried: protect = mbi.Protect else: print >> sys.stderr, 'safe_read_chunked_memory_region_as_one: VirtualQueryEx() failed' if queried and mbi.Protect & D.PAGE_GUARD: g = {'ea': base, 'size': GRANULARITY, 'p': mbi.Protect} gpoints[base] = 0 ea = base while True: ea -= GRANULARITY if VirtualQueryEx(h_process, C.c_void_p(ea), C.byref(mbi), C.sizeof(mbi)) and\ (mbi.Protect & D.PAGE_GUARD) != 0 and g['p'] == mbi.Protect: g['ea'] -= GRANULARITY g['size'] += GRANULARITY else: break guarded.append(g) for i in range(base + GRANULARITY, base + size, GRANULARITY): p_addr = C.c_void_p(i) if VirtualQueryEx(h_process, p_addr, C.byref(mbi), C.sizeof(mbi)) and\ mbi.Protect & D.PAGE_GUARD: prevaddr = i - GRANULARITY if prevaddr in gpoints and guarded[gpoints[prevaddr]]['p'] == mbi.Protect: idx = gpoints[prevaddr] else: guarded.append({'ea': i, 'size': 0, 'p': mbi.Protect}) idx = len(guarded) - 1 guarded[idx]['size'] += GRANULARITY gpoints[i] = idx ea = base + size - GRANULARITY if ea in gpoints: while True: ea += GRANULARITY if VirtualQueryEx(h_process, C.c_void_p(ea), C.byref(mbi), C.sizeof(mbi)) and\ mbi.Protect & D.PAGE_GUARD: guarded[-1]['size'] += GRANULARITY else: break # turn off page guard before read dummy = C.c_long() for g in guarded: for off in range(0, g['size'], GRANULARITY): g['ok'] = VirtualProtectEx(h_process, C.c_void_p(g['ea'] + off), GRANULARITY, C.c_long(g['p'] & ~D.PAGE_GUARD), C.byref(dummy)) for i in range(base, base + size, GRANULARITY): p_addr = C.c_void_p(i) if VirtualQueryEx(h_process, p_addr, C.byref(mbi), C.sizeof(mbi)): if mbi.Protect & D.PAGE_GUARD: # TODO pass mem = unsafe_read_process_memory(i, GRANULARITY) if mem is None: continue mem = mem[1] if mem: off = i - base rv[off:off + GRANULARITY] = mem for g in guarded: for off in range(0, g['size'], GRANULARITY): if not g['ok']: continue if not VirtualProtectEx(h_process, C.c_void_p(g['ea'] + off), GRANULARITY, C.c_long(g['p']), C.byref(dummy)): print >> sys.stderr, 'VirtualProtectEx(ptr 0x%08X, size 0x%08X, protect 0x%08X) failed' %\ (g['ea'] + off, GRANULARITY, g['p']) if rv and len(rv) > size: rv = rv[:size] return size, rv, protect
def update_modules_meta(): global modules_meta global modules_exports modules_meta = dict() modules_exports = dict() me32 = D.MODULEENTRY32() me32.dwSize = C.sizeof(D.MODULEENTRY32) pid = api.Plugingetvalue(api.VAL_PROCESSID) h_snap = C.windll.kernel32.CreateToolhelp32Snapshot(D.TH32CS_SNAPMODULE, pid) if h_snap == 0xFFFFFFFF: print >> sys.stderr, 'get_modules_meta(): Unable to open Toolhelp32 snapshot' return modules_meta # available_modules = set() ret = C.windll.kernel32.Module32First(h_snap, C.pointer(me32)) if ret == 0: C.windll.kernel32.CloseHandle(h_snap) print >> sys.stderr, 'get_modules_meta(): Module32First() failed' return modules_meta while ret: modname = path.splitext(path.basename(me32.szExePath))[0].lower() if modname not in modules_meta or modules_meta[modname]['base'] != me32.modBaseAddr: mem = safe_read_chunked_memory_region_as_one(me32.modBaseAddr, me32.modBaseSize) print 'get_modules_meta(): %s at 0x%08X' % (modname, me32.modBaseAddr) if mem: pe = PEHelper(me32.modBaseAddr, modname, mem[1]) exps = pe.get_exports() if modname in modules_meta: modules_meta[modname]['base'].append(me32.modBaseAddr) modules_meta[modname]['size'].append(me32.modBaseSize) modules_meta[modname]['end'].append(me32.modBaseAddr + me32.modBaseSize) modules_meta[modname]['apis'].append(exps) # re_match_mod_ordinals = re.compile(r'%s\.#\d+' % modname, re.I) modules_exports.update(pe.get_ea_to_longname_map()) # modules_exports = dict(filter(lambda (k, v): not re_match_mod_ordinals.match(v), modules_exports.items())) else: mi = { 'path': [me32.szExePath], 'base': [me32.modBaseAddr], 'size': [me32.modBaseSize], 'apis': [exps], 'end': [me32.modBaseAddr + me32.modBaseSize] } modules_meta[modname] = mi modules_exports.update(pe.get_ea_to_longname_map()) ret = C.windll.kernel32.Module32Next(h_snap, C.pointer(me32)) C.windll.kernel32.CloseHandle(h_snap) # t = oa.pluginvalue_to_t_table(oa.Plugingetvalue(oa.VAL_MODULES)) # # for i in xrange(t.data.n): # m = oa.void_to_t_module(oa.Getsortedbyselection(t.data, i)) # modname = path.splitext(path.basename(m.path))[0].lower() # if modname in modules_meta and modules_meta[modname]['base'] == m.base: # continue # available_modules.add(modname) # externals = list() # for off in xrange(m.codesize): # name = bytearray(oa.TEXTLEN) # if oa.Findname(m.codebase + off, oa.NM_EXPORT, name): # name = str(name.replace('\x00', '')) # externals.append({'ea': m.codebase + off, 'name': name}) # modules_exports[m.codebase + off] = '%s.%s' % (modname, name) # mi = { # 'path': m.path, # 'base': m.base, # 'size': m.size, # 'apis': externals, # 'end': m.base + m.size # } # # modules_meta[modname] = mi # for name in filter(lambda x: x not in available_modules, modules_meta.keys()): # del modules_meta[name] return modules_meta # sorted(rv, key=lambda x: x['base'])
def RemoteFree(addr, size): if not addr: raise Exception('Invalid argument: `addr`') return C.windll.kernel32.VirtualFreeEx( api.Plugingetvalue(api.VAL_HPROCESS), addr, size, D.MEM_RELEASE)