about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm/arch/x86/arch.py7
-rw-r--r--miasm/arch/x86/sem.py4
-rw-r--r--miasm/core/cpu.py3
-rw-r--r--miasm/expression/simplifications_common.py10
-rw-r--r--miasm/loader/elf_init.py2
-rw-r--r--miasm/os_dep/win_api_x86_32.py80
6 files changed, 92 insertions, 14 deletions
diff --git a/miasm/arch/x86/arch.py b/miasm/arch/x86/arch.py
index d1802045..127dded4 100644
--- a/miasm/arch/x86/arch.py
+++ b/miasm/arch/x86/arch.py
@@ -481,7 +481,7 @@ class instruction_x86(instruction):
         expr = self.args[0]
         if not expr.is_int():
             return
-        addr = expr.arg + int(self.offset)
+        addr = (int(expr) + int(self.offset)) & int(expr.mask)
         loc_key = loc_db.get_or_create_offset_location(addr)
         self.args[0] = ExprLoc(loc_key, expr.size)
 
@@ -1913,7 +1913,10 @@ def modrm2expr(modrm, parent, w8, sx=0, xmm=0, mm=0, bnd=0):
         if parent.disp.value is None:
             return None
         o.append(ExprInt(int(parent.disp.expr), admode))
-    expr = ExprOp('+', *o)
+    if len(o) == 1:
+        expr = o[0]
+    else:
+        expr = ExprOp('+', *o)
     if w8 == 0:
         opmode = 8
     elif sx == 1:
diff --git a/miasm/arch/x86/sem.py b/miasm/arch/x86/sem.py
index b0fcd054..86a933a0 100644
--- a/miasm/arch/x86/sem.py
+++ b/miasm/arch/x86/sem.py
@@ -1162,7 +1162,9 @@ def setalc(_, instr):
 def bswap(_, instr, dst):
     e = []
     if dst.size == 16:
-        result = m2_expr.ExprCompose(dst[8:16], dst[:8])
+        # BSWAP referencing a 16-bit register is undefined
+        # Seems to return 0 actually
+        result = m2_expr.ExprInt(0, 16)
     elif dst.size == 32:
         result = m2_expr.ExprCompose(
             dst[24:32], dst[16:24], dst[8:16], dst[:8])
diff --git a/miasm/core/cpu.py b/miasm/core/cpu.py
index ec8d95bc..aee22c97 100644
--- a/miasm/core/cpu.py
+++ b/miasm/core/cpu.py
@@ -1589,6 +1589,9 @@ class imm_noarg(object):
 
         assert(m2_expr.is_expr(e))
         self.expr = e
+        if self.expr is None:
+            log.debug('cannot fromstring int %r', text)
+            return None, None
         return start, stop
 
     def decodeval(self, v):
diff --git a/miasm/expression/simplifications_common.py b/miasm/expression/simplifications_common.py
index f68b8ed5..ae3494c1 100644
--- a/miasm/expression/simplifications_common.py
+++ b/miasm/expression/simplifications_common.py
@@ -71,26 +71,28 @@ def simp_cst_propagation(e_s, expr):
                 shifter = int(int2) % int2.size
                 out = (int(int1) << shifter) | (int(int1) >> (int2.size - shifter))
             elif op_name == '/':
+                assert int(int2), "division by 0"
                 out = int(int1) // int(int2)
             elif op_name == '%':
+                assert int(int2), "division by 0"
                 out = int(int1) % int(int2)
             elif op_name == 'sdiv':
-                assert int(int2)
+                assert int(int2), "division by 0"
                 tmp1 = mod_size2int[int1.size](int(int1))
                 tmp2 = mod_size2int[int2.size](int(int2))
                 out = mod_size2uint[int1.size](tmp1 // tmp2)
             elif op_name == 'smod':
-                assert int(int2)
+                assert int(int2), "division by 0"
                 tmp1 = mod_size2int[int1.size](int(int1))
                 tmp2 = mod_size2int[int2.size](int(int2))
                 out = mod_size2uint[int1.size](tmp1 % tmp2)
             elif op_name == 'umod':
-                assert int(int2)
+                assert int(int2), "division by 0"
                 tmp1 = mod_size2uint[int1.size](int(int1))
                 tmp2 = mod_size2uint[int2.size](int(int2))
                 out = mod_size2uint[int1.size](tmp1 % tmp2)
             elif op_name == 'udiv':
-                assert int(int2)
+                assert int(int2), "division by 0"
                 tmp1 = mod_size2uint[int1.size](int(int1))
                 tmp2 = mod_size2uint[int2.size](int(int2))
                 out = mod_size2uint[int1.size](tmp1 // tmp2)
diff --git a/miasm/loader/elf_init.py b/miasm/loader/elf_init.py
index 14f4dc7c..72d08302 100644
--- a/miasm/loader/elf_init.py
+++ b/miasm/loader/elf_init.py
@@ -92,6 +92,8 @@ class WRel32(StructWrapper):
     wrapped._fields.append(("type", "u08"))
 
     def get_sym(self):
+        if isinstance(self.parent.linksection, NullSection):
+            return None
         return self.parent.linksection.symtab[self.cstr.info >> 8].name
 
     def get_type(self):
diff --git a/miasm/os_dep/win_api_x86_32.py b/miasm/os_dep/win_api_x86_32.py
index 2816dd3b..568a646d 100644
--- a/miasm/os_dep/win_api_x86_32.py
+++ b/miasm/os_dep/win_api_x86_32.py
@@ -1670,16 +1670,82 @@ 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
+    # according to MSDN:
+    # "Note that, if cbMultiByte is 0, the function fails."
+    if args.cbmultibyte == 0:
+        raise ValueError
+    # according to MSDN:
+    # "Alternatively, this parameter can be set to -1 if the string is
+    #  null-terminated."
+    if args.cbmultibyte == 0xffffffff:
+        src_len = 0
+        while jitter.vm.get_mem(args.lpmultibytestr + src_len, 1) != b'\0':
+            src_len += 1
+        src = jitter.vm.get_mem(args.lpmultibytestr, src_len)
+    else:
+        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):
@@ -1955,7 +2021,7 @@ def msvcrt_memset(jitter):
 def msvcrt_strrchr(jitter):
     ret_ad, args = jitter.func_args_cdecl(['pstr','c'])
     s = get_win_str_a(jitter, args.pstr)
-    c = int_to_byte(args.c)
+    c = int_to_byte(args.c).decode()
     ret = args.pstr + s.rfind(c)
     log.info("strrchr(%x '%s','%s') = %x" % (args.pstr,s,c,ret))
     jitter.func_ret_cdecl(ret_ad, ret)
@@ -1963,7 +2029,7 @@ def msvcrt_strrchr(jitter):
 def msvcrt_wcsrchr(jitter):
     ret_ad, args = jitter.func_args_cdecl(['pstr','c'])
     s = get_win_str_w(jitter, args.pstr)
-    c = int_to_byte(args.c)
+    c = int_to_byte(args.c).decode()
     ret = args.pstr + (s.rfind(c)*2)
     log.info("wcsrchr(%x '%s',%s) = %x" % (args.pstr,s,c,ret))
     jitter.func_ret_cdecl(ret_ad, ret)