diff --git a/src/dumpulator/details.py b/src/dumpulator/details.py index f3b6505..0a326fd 100644 --- a/src/dumpulator/details.py +++ b/src/dumpulator/details.py @@ -265,6 +265,10 @@ def __init__(self, uc: Uc, x64): "fs_base": UC_X86_REG_FS_BASE, "gs_base": UC_X86_REG_GS_BASE, } + for i in range(8): + reg = UC_X86_REG_ST0 + i + self._regmap[f"st{i}"] = reg + self._regmap[f"st({i})"] = reg if unicorn.__version__[0] < '2': self._regmap.update({ "riz": UC_X86_REG_RIZ, @@ -340,7 +344,7 @@ def __init__(self, uc: Uc, x64): def _resolve_reg(self, regname): uc_reg = self._regmap.get(regname, None) if uc_reg is None: - raise Exception(f"Unknown register '{regname}'") + raise KeyError(f"Unknown register '{regname}'") #if not self._x64 and regname.startswith("r"): # raise Exception(f"Register {regname} is not available in 32-bit mode") return uc_reg diff --git a/src/dumpulator/dumpulator.py b/src/dumpulator/dumpulator.py index 38eff19..9617b55 100644 --- a/src/dumpulator/dumpulator.py +++ b/src/dumpulator/dumpulator.py @@ -1450,6 +1450,7 @@ def _get_regs(instr, include_write=False): def _hook_code(uc: Uc, address, size, dp: Dumpulator): try: + uc.ctl_remove_cache(address, address + 16) code = b"" try: code = dp.read(address, min(size, 15)) @@ -1693,7 +1694,6 @@ def op_mem(op: X86Op, *, aligned: bool): mem_address = 0 if op.mem.base == X86_REG_RIP: mem_address += instr.address + instr.size - raise NotImplementedError("TODO: check if the disp is already adjusted") else: base = op.mem.base if base != X86_REG_INVALID: @@ -1749,6 +1749,9 @@ def op_write(index: int, value: int, *, aligned=False): else: raise NotImplementedError() + def op_bits(index: int): + return instr.operands[index].size * 8 + def cip_next(): dp.regs.cip += instr.size @@ -1756,6 +1759,15 @@ def cip_next(): # TODO: PRNG based on dmp hash op_write(0, 42) cip_next() + elif instr.id == X86_INS_RDTSCP: + # TODO: properly implement + dp.regs.rdx = 0 + dp.regs.rax = 0 + dp.regs.rcx = 0 + cip_next() + elif instr.id == X86_INS_RDGSBASE: + op_write(0, dp.regs.gs_base) + cip_next() elif instr.id in [X86_INS_VMOVDQU, X86_INS_VMOVUPS]: src = op_read(1) op_write(0, src) @@ -1774,9 +1786,16 @@ def cip_next(): src = (src & 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) | (xmm1 << 128) op_write(0, src) cip_next() - + elif instr.id == X86_INS_VPBROADCASTQ: + src = op_read(1) & 0xFFFFFFFFFFFFFFFF + result = 0 + for _ in range(op_bits(0) // 64): + result <<= 64 + result |= src + op_write(0, result) + cip_next() else: - dp.error(f"unsupported: {instr.mnemonic} {instr.op_str}") + dp.error(f"unsupported: {hex(instr.address)}|{instr.mnemonic} {instr.op_str}") # Unsupported instruction return False dp.debug(f"emulated: {hex(instr.address)}|{instr.bytes.hex()}|{instr.mnemonic} {instr.op_str}") @@ -1794,6 +1813,7 @@ def _hook_invalid(uc: Uc, dp: Dumpulator): try: code = dp.read(address, 15) instr = next(dp.cs.disasm(code, address, 1)) + dp.debug(f"invalid hook {hex(address)}|{code.hex()}|{instr.mnemonic} {instr.op_str}") # TODO: add a hook if _emulate_unsupported_instruction(dp, instr): # Resume execution with a context switch @@ -1807,5 +1827,8 @@ def _hook_invalid(uc: Uc, dp: Dumpulator): pass # Unsupported instruction except IndexError: pass # Invalid memory access (NOTE: this should not be possible actually) + except Exception as err: + print(f"Unexpected exception {type(err)}") + traceback.print_exc() dp.error(f"invalid instruction at {hex(address)}") raise NotImplementedError("TODO: throw invalid instruction exception")