|
18 | 18 | from .memory import * |
19 | 19 | from .modules import * |
20 | 20 | from capstone import * |
21 | | -from capstone.x86_const import * |
| 21 | +from capstone.x86 import * |
22 | 22 |
|
23 | 23 | syscall_functions = {} |
24 | 24 |
|
@@ -1162,11 +1162,42 @@ def syscall_arg(index): |
1162 | 1162 | dp.error(f"syscall index {index:x} out of range") |
1163 | 1163 | dp.raise_kill(IndexError()) |
1164 | 1164 |
|
| 1165 | +def _emulate_unsupported_instruction(dp: Dumpulator, instr: CsInsn): |
| 1166 | + if instr.id == X86_INS_RDRAND: |
| 1167 | + op: X86Op = instr.operands[0] |
| 1168 | + regname = instr.reg_name(op.reg) |
| 1169 | + if dp._x64 and op.size * 8 == 32: |
| 1170 | + regname = "r" + regname[1:] |
| 1171 | + print(f"emulated rdrand {regname}:{op.size * 8}, cip = {hex(instr.address)}+{instr.size}") |
| 1172 | + dp.regs[regname] = 42 # TODO: PRNG based on dmp hash |
| 1173 | + dp.regs.cip += instr.size |
| 1174 | + else: |
| 1175 | + # Unsupported instruction |
| 1176 | + return False |
| 1177 | + # Resume execution |
| 1178 | + return True |
| 1179 | + |
1165 | 1180 | def _hook_invalid(uc: Uc, dp: Dumpulator): |
1166 | 1181 | address = dp.regs.cip |
1167 | 1182 | # HACK: unicorn cannot gracefully exit in all contexts |
1168 | 1183 | if dp.kill_me: |
1169 | 1184 | dp.error(f"terminating emulation...") |
1170 | 1185 | return False |
1171 | 1186 | dp.error(f"invalid instruction at {address:x}") |
| 1187 | + try: |
| 1188 | + code = dp.read(address, 15) |
| 1189 | + instr = next(dp.cs.disasm(code, address, 1)) |
| 1190 | + if _emulate_unsupported_instruction(dp, instr): |
| 1191 | + # Resume execution with a context switch |
| 1192 | + assert dp.exception.type == ExceptionType.NoException |
| 1193 | + exception = ExceptionInfo() |
| 1194 | + exception.type = ExceptionType.ContextSwitch |
| 1195 | + exception.final = True |
| 1196 | + dp.exception = exception |
| 1197 | + return False # NOTE: returning True would stop emulation |
| 1198 | + except StopIteration: |
| 1199 | + pass # Unsupported instruction |
| 1200 | + except UcError: |
| 1201 | + pass # Invalid memory access (NOTE: this should not be possible actually) |
| 1202 | + raise NotImplementedError("TODO: throw invalid instruction exception") |
1172 | 1203 | return False |
0 commit comments