-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UC_ERR_EXCEPTION when hook UC_HOOK_INSN_INVALID #1972
Comments
I have looked into your example script and used my playground (#1980) to verify the issue. However, I am using a single stepping approach, not multiple internal emulation loops as you do with emu_start. But I tested both versions. Unicorn seems not to be the problem, it seems to me that the binding implementation contains the bug. Your example should have thrown the exception directly after the first hook, as you return false, which should exit the loop. That is probably easy to fix in the binding script. |
I had another look - give this python script a try, you can continue the execution after the exception, if it has been catched. from unicorn import *
from unicorn.x86_const import *
uc = Uc(UC_ARCH_X86, UC_MODE_64)
"""
nop
nop
xsaves byte ptr [rcx]
<garbage>
"""
code_to_execute = b"\x90\x90\x0F\xC7\x29\xFF\xFF\xFF"
code_length = len(code_to_execute)
base_address = 0x0
memory_size = 0x1000
pc = base_address
uc.mem_map(base_address, memory_size)
uc.mem_write(base_address, code_to_execute)
def hook_invalid_instruction_0(uc, user_data):
current_pc = uc.reg_read(UC_X86_REG_RIP)
print("Invalid instruction hooked (0): 0x{:x}".format(current_pc))
return False
def hook_invalid_instruction_1(uc, user_data):
current_pc = uc.reg_read(UC_X86_REG_RIP)
print("Invalid instruction hooked (1): 0x{:x}".format(current_pc))
uc.reg_write(UC_X86_REG_RIP, current_pc + 1)
return True
def hook_code(uc, address, size, user_data):
instruction_bytes = "<unknown>"
if size < memory_size:
instruction_bytes = uc.mem_read(address, size)
instruction_bytes = instruction_bytes.hex()
print("Executing: 0x{:x}, size: 0x{:x}, code: {}".format(address, size, instruction_bytes))
uc.hook_add(UC_HOOK_INSN_INVALID, hook_invalid_instruction_0)
uc.hook_add(UC_HOOK_INSN_INVALID, hook_invalid_instruction_1)
uc.hook_add(UC_HOOK_CODE, hook_code)
step_index = 0
print("Emulation start")
while pc < code_length:
print("Execution step: {}, pc: {}".format(step_index, pc))
try:
uc.emu_start(begin = pc, until = code_length, count = 1)
except:
pass
pc = uc.reg_read(UC_X86_REG_RIP)
step_index += 1
print("Emulation end") |
Thank you for your attempt and reply! In fact, I am currently mitigating the exception in this way. Similar to your implementation, I will catch this exception after UC_HOOK_INSN_INVALID returns and skip the execution of the current code by modifying the PC register. However, I believe this is not an "elegant" solution. As mentioned in PR #1132, initially Unicorn could skip illegal instructions without returning any error. I currently do not have time to delve into the code implementation of Unicorn. I believe that certain exceptions may have occurred in subsequent versions causing this feature to not work properly anymore. |
I'm working on
dev
branch.As mentioned at PR #1132 , my code is that:
but i got outputs:
It seems that return value of
UC_HOOK_INSN_INVALID
function not working. I want to ignore the invalid instruction, how could I do it?The text was updated successfully, but these errors were encountered: