diff options
| -rw-r--r-- | miasm/jitter/jitload.py | 11 | ||||
| -rw-r--r-- | miasm/os_dep/common.py | 8 | ||||
| -rw-r--r-- | miasm/os_dep/win_api_x86_32.py | 124 |
3 files changed, 114 insertions, 29 deletions
diff --git a/miasm/jitter/jitload.py b/miasm/jitter/jitload.py index 68f9c40d..34690425 100644 --- a/miasm/jitter/jitload.py +++ b/miasm/jitter/jitload.py @@ -422,6 +422,17 @@ class Jitter(object): self.init_run(addr) return self.continue_run() + def run_until(self, addr): + """PRE: init_run. + Continue the run of the current session until iterator returns, run is + set to False or addr is reached. + Return the iterator value""" + + def stop_exec(jitter): + jitter.remove_breakpoints_by_callback(stop_exec) + return False + self.add_breakpoint(addr, stop_exec) + return self.continue_run() def init_stack(self): self.vm.add_memory_page( diff --git a/miasm/os_dep/common.py b/miasm/os_dep/common.py index 4a92ef2a..74100817 100644 --- a/miasm/os_dep/common.py +++ b/miasm/os_dep/common.py @@ -71,15 +71,15 @@ class heap(object): self.addr &= self.mask ^ (self.align - 1) return ret - def alloc(self, jitter, size, perm=PAGE_READ | PAGE_WRITE): + def alloc(self, jitter, size, perm=PAGE_READ | PAGE_WRITE, cmt=""): """ @jitter: a jitter instance @size: the size to allocate @perm: permission flags (see vm_alloc doc) """ - return self.vm_alloc(jitter.vm, size, perm) + return self.vm_alloc(jitter.vm, size, perm=perm, cmt=cmt) - def vm_alloc(self, vm, size, perm=PAGE_READ | PAGE_WRITE): + def vm_alloc(self, vm, size, perm=PAGE_READ | PAGE_WRITE, cmt=""): """ @vm: a VmMngr instance @size: the size to allocate @@ -91,7 +91,7 @@ class heap(object): addr, perm, b"\x00" * (size), - "Heap alloc by %s" % get_caller_name(2) + "Heap alloc by %s %s" % (get_caller_name(2), cmt) ) return addr diff --git a/miasm/os_dep/win_api_x86_32.py b/miasm/os_dep/win_api_x86_32.py index e42f8006..9d86e833 100644 --- a/miasm/os_dep/win_api_x86_32.py +++ b/miasm/os_dep/win_api_x86_32.py @@ -157,6 +157,9 @@ class c_winobjs(object): self.cryptcontext_num = 0 self.cryptcontext = {} self.phhash_crypt_md5 = 0x55555 + # key used by EncodePointer and DecodePointer + # (kernel32) + self.ptr_encode_key = 0xabababab self.files_hwnd = {} self.windowlong_dw = 0x77700 self.module_cur_hwnd = 0x88800 @@ -272,7 +275,7 @@ class mdl(object): def kernel32_HeapAlloc(jitter): ret_ad, args = jitter.func_args_stdcall(["heap", "flags", "size"]) - alloc_addr = winobjs.heap.alloc(jitter, args.size) + alloc_addr = winobjs.heap.alloc(jitter, args.size, cmt=hex(ret_ad)) jitter.func_ret_stdcall(ret_ad, alloc_addr) @@ -420,6 +423,36 @@ def kernel32_CloseHandle(jitter): ret_ad, _ = jitter.func_args_stdcall(["hwnd"]) jitter.func_ret_stdcall(ret_ad, 1) +def kernel32_EncodePointer(jitter): + """ + PVOID EncodePointer( + _In_ PVOID Ptr + ); + + Encoding globally available pointers helps protect them from being + exploited. The EncodePointer function obfuscates the pointer value + with a secret so that it cannot be predicted by an external agent. + The secret used by EncodePointer is different for each process. + + A pointer must be decoded before it can be used. + + """ + ret, args = jitter.func_args_stdcall(1) + jitter.func_ret_stdcall(ret, args[0] ^ winobjs.ptr_encode_key) + return True + +def kernel32_DecodePointer(jitter): + """ + PVOID DecodePointer( + PVOID Ptr + ); + + The function returns the decoded pointer. + + """ + ret, args = jitter.func_args_stdcall(1) + jitter.func_ret_stdcall(ret, args[0] ^ winobjs.ptr_encode_key) + return True def user32_GetForegroundWindow(jitter): ret_ad, _ = jitter.func_args_stdcall(0) @@ -505,7 +538,7 @@ def advapi32_CryptHashData(jitter): data = jitter.vm.get_mem(args.pbdata, args.dwdatalen) log.debug('will hash %X', args.dwdatalen) - log.debug(repr(data[:10]) + "...") + log.debug(repr(data[:0x10]) + "...") winobjs.cryptcontext[args.hhash].h.update(data) jitter.func_ret_stdcall(ret_ad, 1) @@ -518,12 +551,18 @@ def advapi32_CryptGetHashParam(jitter): raise ValueError("unknown crypt context") if args.param == 2: + # HP_HASHVAL # XXX todo: save h state? h = winobjs.cryptcontext[args.hhash].h.digest() + jitter.vm.set_mem(args.pbdata, h) + jitter.vm.set_u32(args.dwdatalen, len(h)) + elif args.param == 4: + # HP_HASHSIZE + ret = winobjs.cryptcontext[args.hhash].h.digest_size + jitter.vm.set_u32(args.pbdata, ret) + jitter.vm.set_u32(args.dwdatalen, 4) else: raise ValueError('not impl', args.param) - jitter.vm.set_mem(args.pbdata, h) - jitter.vm.set_u32(args.dwdatalen, len(h)) jitter.func_ret_stdcall(ret_ad, 1) @@ -606,7 +645,7 @@ def kernel32_CreateFile(jitter, funcname, get_str): h = open(sb_fname, 'r+b') ret = winobjs.handle_pool.add(sb_fname, h) else: - log.warning("FILE %r DOES NOT EXIST!", fname) + log.warning("FILE %r (%s) DOES NOT EXIST!", fname, sb_fname) elif args.dwcreationdisposition == 1: # create new if os.access(sb_fname, os.R_OK): @@ -1114,21 +1153,22 @@ def kernel32_GetCommandLineW(jitter): def shell32_CommandLineToArgvW(jitter): ret_ad, args = jitter.func_args_stdcall(["pcmd", "pnumargs"]) cmd = get_win_str_w(jitter, args.pcmd) + if cmd.startswith('"') and cmd.endswith('"'): + cmd = cmd[1:-1] log.info("CommandLineToArgv %r", cmd) tks = cmd.split(' ') addr = winobjs.heap.alloc(jitter, len(cmd) * 2 + 4 * len(tks)) addr_ret = winobjs.heap.alloc(jitter, 4 * (len(tks) + 1)) o = 0 for i, t in enumerate(tks): - jitter.set_win_str_w(addr + o, t) + set_win_str_w(jitter, addr + o, t) jitter.vm.set_u32(addr_ret + 4 * i, addr + o) o += len(t)*2 + 2 - jitter.vm.set_u32(addr_ret + 4 * i, 0) + jitter.vm.set_u32(addr_ret + 4 * (i+1), 0) jitter.vm.set_u32(args.pnumargs, len(tks)) jitter.func_ret_stdcall(ret_ad, addr_ret) - def cryptdll_MD5Init(jitter): ret_ad, args = jitter.func_args_stdcall(["ad_ctx"]) index = len(winobjs.cryptdll_md5_h) @@ -1335,7 +1375,7 @@ def ntoskrnl_RtlGetVersion(jitter): 0x2, # min vers 0x666, # build nbr 0x2, # platform id - ) + jitter.set_win_str_w("Service pack 4") + ) + encode_win_str_w("Service pack 4") jitter.vm.set_mem(args.ptr_version, s) jitter.func_ret_stdcall(ret_ad, 0) @@ -1521,7 +1561,7 @@ def kernel32_lstrcpy(jitter): def msvcrt__mbscpy(jitter): ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2"]) s2 = get_win_str_w(jitter, args.ptr_str2) - jitter.set_win_str_w(args.ptr_str1, s2) + set_win_str_w(jitter, args.ptr_str1, s2) jitter.func_ret_cdecl(ret_ad, args.ptr_str1) def msvcrt_wcscpy(jitter): @@ -1535,7 +1575,7 @@ def kernel32_lstrcpyn(jitter): if len(s2) >= args.mlen: s2 = s2[:args.mlen - 1] log.info("Copy '%r'", s2) - jitter.set_win_str_a(args.ptr_str1, s2) + set_win_str_a(jitter, args.ptr_str1, s2) jitter.func_ret_stdcall(ret_ad, args.ptr_str1) @@ -1637,7 +1677,8 @@ def kernel32_MultiByteToWideChar(jitter): "cchwidechar"]) src = get_win_str_a(jitter, args.lpmultibytestr) l = len(src) + 1 - set_win_str_w(jitter, args.lpwidecharstr, src) + if args.cchwidechar != 0: + set_win_str_w(jitter, args.lpwidecharstr, src) jitter.func_ret_stdcall(ret_ad, l) @@ -2879,7 +2920,7 @@ class win32_find_data(object): for k, v in viewitems(kargs): setattr(self, k, v) - def toStruct(self): + def toStruct(self, encode_str=encode_win_str_w): s = struct.pack('=IQQQIIII', self.fileattrib, self.creationtime, @@ -2889,10 +2930,10 @@ class win32_find_data(object): self.filesizelow, self.dwreserved0, self.dwreserved1) - fname = self.cfilename.encode('utf-8') + b'\x00' * MAX_PATH + fname = encode_str(self.cfilename) + b'\x00' * MAX_PATH fname = fname[:MAX_PATH] s += fname - fname = self.alternamefilename.encode('utf-8') + b'\x00' * 14 + fname = encode_str(self.alternamefilename) + b'\x00' * 14 fname = fname[:14] s += fname return s @@ -2929,33 +2970,66 @@ class find_data_mngr(object): return fname - -def kernel32_FindFirstFileA(jitter): - ret_ad, args = jitter.func_args_stdcall(["pfilepattern", "pfindfiledata"]) - - filepattern = get_win_str_a(jitter, args.pfilepattern) +def my_FindFirstFile(jitter, pfilepattern, pfindfiledata, get_win_str, encode_str): + filepattern = get_win_str(jitter, pfilepattern) h = winobjs.find_data.findfirst(filepattern) fname = winobjs.find_data.findnext(h) fdata = win32_find_data(cfilename=fname) - jitter.vm.set_mem(args.pfindfiledata, fdata.toStruct()) + jitter.vm.set_mem(pfindfiledata, fdata.toStruct(encode_str=encode_str)) + return h + +def kernel32_FindFirstFileA(jitter): + ret_ad, args = jitter.func_args_stdcall(["pfilepattern", "pfindfiledata"]) + h = my_FindFirstFile(jitter, args.pfilepattern, args.pfindfiledata, + get_win_str_a, encode_win_str_a) + jitter.func_ret_stdcall(ret_ad, h) + +def kernel32_FindFirstFileW(jitter): + ret_ad, args = jitter.func_args_stdcall(["pfilepattern", "pfindfiledata"]) + h = my_FindFirstFile(jitter, args.pfilepattern, args.pfindfiledata, + get_win_str_w, encode_win_str_w) jitter.func_ret_stdcall(ret_ad, h) +def kernel32_FindFirstFileExA(jitter): + ret_ad, args = jitter.func_args_stdcall([ + "lpFileName", + "fInfoLevelId", + "lpFindFileData", + "fSearchOp", + "lpSearchFilter", + "dwAdditionalFlags"]) + h = my_FindFirstFile(jitter, args.lpFileName, args.lpFindFileData, + get_win_str_a, encode_win_str_a) + jitter.func_ret_stdcall(ret_ad, h) -def kernel32_FindNextFileA(jitter): - ret_ad, args = jitter.func_args_stdcall(["handle", "pfindfiledata"]) +def kernel32_FindFirstFileExW(jitter): + ret_ad, args = jitter.func_args_stdcall([ + "lpFileName", + "fInfoLevelId", + "lpFindFileData", + "fSearchOp", + "lpSearchFilter", + "dwAdditionalFlags"]) + h = my_FindFirstFile(jitter, args.lpFileName, args.lpFindFileData, + get_win_str_w, encode_win_str_w) + jitter.func_ret_stdcall(ret_ad, h) +def my_FindNextFile(jitter, encode_str): + ret_ad, args = jitter.func_args_stdcall(["handle", "pfindfiledata"]) fname = winobjs.find_data.findnext(args.handle) if fname is None: + winobjs.lastwin32error = 0x12 # ERROR_NO_MORE_FILES ret = 0 else: ret = 1 fdata = win32_find_data(cfilename=fname) - jitter.vm.set_mem(args.pfindfiledata, fdata.toStruct()) - + jitter.vm.set_mem(args.pfindfiledata, fdata.toStruct(encode_str=encode_str)) jitter.func_ret_stdcall(ret_ad, ret) +kernel32_FindNextFileA = lambda jitter: my_FindNextFile(jitter, encode_win_str_a) +kernel32_FindNextFileW = lambda jitter: my_FindNextFile(jitter, encode_win_str_w) def kernel32_GetNativeSystemInfo(jitter): ret_ad, args = jitter.func_args_stdcall(["sys_ptr"]) |