diff options
| -rw-r--r-- | miasm/analysis/data_flow.py | 15 | ||||
| -rw-r--r-- | miasm/arch/arm/sem.py | 6 | ||||
| -rw-r--r-- | miasm/jitter/jitload.py | 15 | ||||
| -rw-r--r-- | miasm/os_dep/win_api_x86_32.py | 145 | ||||
| -rw-r--r-- | test/arch/arm/arch.py | 5 |
5 files changed, 164 insertions, 22 deletions
diff --git a/miasm/analysis/data_flow.py b/miasm/analysis/data_flow.py index 40a3b94e..7340c023 100644 --- a/miasm/analysis/data_flow.py +++ b/miasm/analysis/data_flow.py @@ -9,7 +9,7 @@ from miasm.ir.ir import AssignBlock, IRBlock from miasm.expression.expression import ExprLoc, ExprMem, ExprId, ExprInt,\ ExprAssign, ExprOp, ExprWalk, ExprSlice, \ is_function_call, ExprVisitorCallbackBottomToTop -from miasm.expression.simplifications import expr_simp +from miasm.expression.simplifications import expr_simp, expr_simp_explicit from miasm.core.interval import interval from miasm.expression.expression_helper import possible_values from miasm.analysis.ssa import get_phi_sources_parent_block, \ @@ -133,7 +133,7 @@ class DiGraphDefUse(DiGraph): def __init__(self, reaching_defs, - deref_mem=False, *args, **kwargs): + deref_mem=False, apply_simp=False, *args, **kwargs): """Instantiate a DiGraph @blocks: IR blocks """ @@ -146,7 +146,8 @@ class DiGraphDefUse(DiGraph): super(DiGraphDefUse, self).__init__(*args, **kwargs) self._compute_def_use(reaching_defs, - deref_mem=deref_mem) + deref_mem=deref_mem, + apply_simp=apply_simp) def edge_attr(self, src, dst): """ @@ -157,18 +158,20 @@ class DiGraphDefUse(DiGraph): return self._edge_attr[(src, dst)] def _compute_def_use(self, reaching_defs, - deref_mem=False): + deref_mem=False, apply_simp=False): for block in viewvalues(self._blocks): self._compute_def_use_block(block, reaching_defs, - deref_mem=deref_mem) + deref_mem=deref_mem, + apply_simp=apply_simp) - def _compute_def_use_block(self, block, reaching_defs, deref_mem=False): + def _compute_def_use_block(self, block, reaching_defs, deref_mem=False, apply_simp=False): for index, assignblk in enumerate(block): assignblk_reaching_defs = reaching_defs.get_definitions(block.loc_key, index) for lval, expr in viewitems(assignblk): self.add_node(AssignblkNode(block.loc_key, index, lval)) + expr = expr_simp_explicit(expr) if apply_simp else expr read_vars = expr.get_r(mem_read=deref_mem) if deref_mem and lval.is_mem(): read_vars.update(lval.ptr.get_r(mem_read=deref_mem)) diff --git a/miasm/arch/arm/sem.py b/miasm/arch/arm/sem.py index 7d72b956..027c3a6a 100644 --- a/miasm/arch/arm/sem.py +++ b/miasm/arch/arm/sem.py @@ -1752,6 +1752,9 @@ mnemo_condm0 = {'add': add, 'sdiv': sdiv, 'udiv': udiv, + 'mrc': mrc, + 'mcr': mcr, + 'mul': mul, 'umull': umull, 'umlal': umlal, @@ -1810,9 +1813,6 @@ mnemo_condm1 = {'adds': add, 'bics': bics, 'mvns': mvns, - 'mrc': mrc, - 'mcr': mcr, - 'mrs': mrs, 'msr': msr, diff --git a/miasm/jitter/jitload.py b/miasm/jitter/jitload.py index 34690425..85d5636f 100644 --- a/miasm/jitter/jitload.py +++ b/miasm/jitter/jitload.py @@ -393,13 +393,16 @@ class Jitter(object): self.pc = pc self.run = True - def continue_run(self, step=False): + def continue_run(self, step=False, trace=False): """PRE: init_run. Continue the run of the current session until iterator returns or run is set to False. If step is True, run only one time. + If trace is True, activate trace log option until execution stops Return the iterator value""" + if trace: + self.set_trace_log() while self.run: try: return next(self.run_iterator) @@ -409,8 +412,9 @@ class Jitter(object): self.run_iterator = self.runiter_once(self.pc) if step is True: - return None - + break + if trace: + self.set_trace_log(False, False, False) return None @@ -422,17 +426,18 @@ class Jitter(object): self.init_run(addr) return self.continue_run() - def run_until(self, addr): + def run_until(self, addr, trace=False): """PRE: init_run. Continue the run of the current session until iterator returns, run is set to False or addr is reached. + If trace is True, activate trace log option until execution stops 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() + return self.continue_run(trace=trace) def init_stack(self): self.vm.add_memory_page( diff --git a/miasm/os_dep/win_api_x86_32.py b/miasm/os_dep/win_api_x86_32.py index 46f5783c..e83a3993 100644 --- a/miasm/os_dep/win_api_x86_32.py +++ b/miasm/os_dep/win_api_x86_32.py @@ -1670,16 +1670,69 @@ def kernel32_GetVolumeInformationW(jitter): def kernel32_MultiByteToWideChar(jitter): + MB_ERR_INVALID_CHARS = 0x8 + CP_ACP = 0x000 + CP_1252 = 0x4e4 + ret_ad, args = jitter.func_args_stdcall(["codepage", "dwflags", "lpmultibytestr", "cbmultibyte", "lpwidecharstr", "cchwidechar"]) - src = get_win_str_a(jitter, args.lpmultibytestr) - l = len(src) + 1 - if args.cchwidechar != 0: - set_win_str_w(jitter, args.lpwidecharstr, src) - jitter.func_ret_stdcall(ret_ad, l) + if args.codepage != CP_ACP and args.codepage != CP_1252: + raise NotImplementedError + src = jitter.vm.get_mem(args.lpmultibytestr, args.cbmultibyte) + if args.dwflags & MB_ERR_INVALID_CHARS: + # will raise an exception if decoding fails + s = src.decode("cp1252", errors="replace").encode("utf-16le") + else: + # silently replace undecodable chars with U+FFFD + s = src.decode("cp1252", errors="replace").encode("utf-16le") + if args.cchwidechar > 0: + # return value is number of bytes written + retval = min(args.cchwidechar, len(s)) + jitter.vm.set_mem(args.lpwidecharstr, s[:retval]) + else: + # return value is number of bytes to write + # i.e., size of dest. buffer to allocate + retval = len(s) + jitter.func_ret_stdcall(ret_ad, retval) + + +def kernel32_WideCharToMultiByte(jitter): + """ + int WideCharToMultiByte( + UINT CodePage, + DWORD dwFlags, + _In_NLS_string_(cchWideChar)LPCWCH lpWideCharStr, + int cchWideChar, + LPSTR lpMultiByteStr, + int cbMultiByte, + LPCCH lpDefaultChar, + LPBOOL lpUsedDefaultChar + ); + + """ + CP_ACP = 0x000 + CP_1252 = 0x4e4 + + ret, args = jitter.func_args_stdcall([ + 'CodePage', 'dwFlags', 'lpWideCharStr', 'cchWideChar', + 'lpMultiByteStr', 'cbMultiByte', 'lpDefaultChar', 'lpUsedDefaultChar', + ]) + if args.CodePage != CP_ACP and args.CodePage != CP_1252: + raise NotImplementedError + src = jitter.vm.get_mem(args.lpWideCharStr, args.cchWideChar * 2) + dst = src.decode("utf-16le").encode("cp1252", errors="replace") + if args.cbMultiByte > 0: + # return value is the number of bytes written + retval = min(args.cbMultiByte, len(dst)) + jitter.vm.set_mem(args.lpMultiByteStr, dst[:retval]) + else: + # return value is the size of the buffer to allocate + # to get the multibyte string + retval = len(dst) + jitter.func_ret_stdcall(ret, retval) def my_GetEnvironmentVariable(jitter, funcname, get_str, set_str, mylen): @@ -1913,6 +1966,7 @@ def ntdll_LdrLoadDll(jitter): libname = s.lower() ad = winobjs.runtime_dll.lib_get_add_base(libname) + log.info("Loading %r ret 0x%x", s, ad) jitter.vm.set_u32(args.modhandle, ad) jitter.func_ret_stdcall(ret_ad, 0) @@ -2382,13 +2436,88 @@ def user32_GetKeyboardType(jitter): jitter.func_ret_stdcall(ret_ad, ret) + +class startupinfo(object): + """ + typedef struct _STARTUPINFOA { + /* 00000000 */ DWORD cb; + /* 00000004 */ LPSTR lpReserved; + /* 00000008 */ LPSTR lpDesktop; + /* 0000000C */ LPSTR lpTitle; + /* 00000010 */ DWORD dwX; + /* 00000014 */ DWORD dwY; + /* 00000018 */ DWORD dwXSize; + /* 0000001C */ DWORD dwYSize; + /* 00000020 */ DWORD dwXCountChars; + /* 00000024 */ DWORD dwYCountChars; + /* 00000028 */ DWORD dwFillAttribute; + /* 0000002C */ DWORD dwFlags; + /* 00000030 */ WORD wShowWindow; + /* 00000032 */ WORD cbReserved2; + /* 00000034 */ LPBYTE lpReserved2; + /* 00000038 */ HANDLE hStdInput; + /* 0000003C */ HANDLE hStdOutput; + /* 00000040 */ HANDLE hStdError; + } STARTUPINFOA, *LPSTARTUPINFOA; + + """ + # TODO: fill with relevant values + # for now, struct is just a placeholder + cb = 0x0 + lpReserved = 0x0 + lpDesktop = 0x0 + lpTitle = 0x0 + dwX = 0x0 + dwY = 0x0 + dwXSize = 0x0 + dwYSize = 0x0 + dwXCountChars = 0x0 + dwYCountChars = 0x0 + dwFillAttribute = 0x0 + dwFlags = 0x0 + wShowWindow = 0x0 + cbReserved2 = 0x0 + lpReserved2 = 0x0 + hStdInput = 0x0 + hStdOutput = 0x0 + hStdError = 0x0 + + def pack(self): + return struct.pack('IIIIIIIIIIIIHHIIII', + self.cb, + self.lpReserved, + self.lpDesktop, + self.lpTitle, + self.dwX, + self.dwY, + self.dwXSize, + self.dwYSize, + self.dwXCountChars, + self.dwYCountChars, + self.dwFillAttribute, + self.dwFlags, + self.wShowWindow, + self.cbReserved2, + self.lpReserved2, + self.hStdInput, + self.hStdOutput, + self.hStdError) + def kernel32_GetStartupInfo(jitter, funcname, set_str): - ret_ad, args = jitter.func_args_stdcall(["ptr"]) + """ + void GetStartupInfo( + LPSTARTUPINFOW lpStartupInfo + ); - s = b"\x00" * 0x2c + b"\x81\x00\x00\x00" + b"\x0a" + Retrieves the contents of the STARTUPINFO structure that was specified + when the calling process was created. + + https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getstartupinfow - jitter.vm.set_mem(args.ptr, s) + """ + ret_ad, args = jitter.func_args_stdcall(["ptr"]) + jitter.vm.set_mem(args.ptr, startupinfo().pack()) jitter.func_ret_stdcall(ret_ad, args.ptr) diff --git a/test/arch/arm/arch.py b/test/arch/arm/arch.py index 55b9a9c2..740655da 100644 --- a/test/arch/arm/arch.py +++ b/test/arch/arm/arch.py @@ -237,6 +237,11 @@ reg_tests_arm = [ '110f11ee'), ('XXXXXXXX MCR p15, 0x0, R8, c2, c0, 0x0', '108f02ee'), + ('XXXXXXXX MRCNE p15, 0x0, R0, c1, c1, 0x0', + '110f111e'), + ('XXXXXXXX MCRCC p15, 0x0, R8, c2, c0, 0x1', + '308f023e'), + ] ts = time.time() |