diff options
| -rw-r--r-- | miasm/arch/x86/arch.py | 7 | ||||
| -rw-r--r-- | miasm/arch/x86/sem.py | 4 | ||||
| -rw-r--r-- | miasm/core/cpu.py | 3 | ||||
| -rw-r--r-- | miasm/expression/simplifications_common.py | 10 | ||||
| -rw-r--r-- | miasm/loader/elf_init.py | 2 | ||||
| -rw-r--r-- | miasm/os_dep/win_api_x86_32.py | 80 |
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) |