Skip to content

Commit

Permalink
Merge pull request #83 from mrexodia/avx-emulation
Browse files Browse the repository at this point in the history
AVX emulation
  • Loading branch information
mrexodia authored Jan 20, 2024
2 parents adc648e + 3106426 commit 5f5e4b6
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 4 deletions.
6 changes: 5 additions & 1 deletion src/dumpulator/details.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
29 changes: 26 additions & 3 deletions src/dumpulator/dumpulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -1749,13 +1749,25 @@ 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

if instr.id == X86_INS_RDRAND:
# 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)
Expand All @@ -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}")
Expand All @@ -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
Expand All @@ -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")

0 comments on commit 5f5e4b6

Please sign in to comment.