unicorn-engine / unicorn

Unicorn CPU emulator framework (ARM, AArch64, M68K, Mips, Sparc, PowerPC, RiscV, S390x, TriCore, X86)
http://www.unicorn-engine.org
GNU General Public License v2.0
7.33k stars 1.31k forks source link

Segfault when executing invalid instruction #1869

Closed mrj0n3s closed 4 months ago

mrj0n3s commented 10 months ago

Executing invalid instructions crashes unicorn2, this got partially fixed with https://github.com/unicorn-engine/unicorn/issues/1842.

On the dev branch executing the following opcodes "F0 38", "F0 39", "F0 A6", "F0 A7" still results in a crash, unicorn 1.0.3 doesn't crash. I'm emulating larger binaries, and my main issue is that the code branches to these invalid instructions and unicorn crashes before the code_hook is being executed. Is there a way for me to get the next instruction pointer without executing the actual instruction, so that I could check if the instruction is invalid and stop the emulation before unicorn crashes?

from unicorn import *
from unicorn.x86_const import *
import struct

def code_hook(mu, access, address, size, value, user_data):
    return True

for p in [61496, 61497, 61606, 61607, 65496, 65497, 65498, 65499, 65500, 65501, 65502, 65503, 65512, 65513, 65514, 65515, 65516, 65517, 65518, 65519]:
    #on dev these still crash unicorn
    if p in [61496, 61497, 61606, 61607]:
        continue
    uc = unicorn.Uc(UC_ARCH_X86, UC_MODE_32)
    uc.hook_add(UC_HOOK_MEM_READ, code_hook)

    uc.mem_map(0xFFFF0000, 0x2000)
    uc.reg_write(UC_X86_REG_ESP, 0xFFFF1000)
    uc.reg_write(UC_X86_REG_EBP, 0xFFFF1000)

    addr = 0x1000
    code = struct.pack('>H',p)
    uc.mem_map(0, 0x10000)
    uc.mem_write(addr, code)
    print(p, code)
    try:
        uc.emu_start(addr, addr + len(code), count=2)
    except:
        pass
wtdcode commented 10 months ago

I confirmed this is a bug even in today qemu upstream. I will try to draft a patch to qemu.

wtdcode commented 4 months ago

Patched also queued by upstream qemu, closing.