about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm/analysis/data_flow.py15
-rw-r--r--miasm/arch/arm/sem.py6
-rw-r--r--miasm/jitter/jitload.py15
-rw-r--r--miasm/os_dep/win_api_x86_32.py145
-rw-r--r--test/arch/arm/arch.py5
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()