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.64k stars 1.35k forks source link

unicorn 2.1.1: SMC doesn't work. #2029

Open wallds opened 1 month ago

wallds commented 1 month ago
from unicorn import *
from unicorn.x86_const import *
from capstone import *
from capstone.x86_const import *
from capstone.x86 import *

CODE = b'\x48\x89\x05\x10\x00\x00\x00' # mov qword ptr [rip+0x10], rax
CODE += b'\x66\xc7\x05\x00\x00\x00\x00\x48\x05' # mov word ptr [rip], 0x0548;
CODE += b'\x8b\x80\x78\x56\x34\x12' # [orig] mov eax, dword ptr [rax + 0x12345678]; [after SMC] 480578563412 add rax, 0x12345678
CODE += b'\xf4' # hlt

def hook_code(uc: Uc, address, size, user_data):
    code = uc.mem_read(address, size)
    print(hex(address), size, code.hex(), '\t', end='')
    insn = list(cs.disasm(code, address, 1))
    if insn:
        insn = insn[0]
        print(insn.mnemonic, insn.op_str)
    else:
        print('[ERROR]: disasm')

def hook_mem_read(uc, access, address, size, value, user_data):
    print('[mem_read]:', access, hex(address), hex(value), size)

def hook_mem_write(uc, access, address, size, value, user_data):
    print('[mem_write]:', access, hex(address), hex(value), size)

def hook_mem_invalid(uc, access, address, size, value, user_data):
    print(f"[mem_invalid]:", hex(uc.reg_read(UC_X86_REG_RIP)), access, hex(address), size, value)
    return False

uc = Uc(UC_ARCH_X86, UC_MODE_64)  # unicorn 2.1.1
cs = Cs(CS_ARCH_X86, CS_MODE_64)  # capstone 5.0.3

CODE_BASE = 0x1000
STACK_BASE = 0x20000

uc.mem_map(CODE_BASE, 0x1000, UC_PROT_ALL)
uc.mem_map(STACK_BASE, 0x2000, UC_PROT_ALL)

uc.hook_add(UC_HOOK_CODE, hook_code)
if 'y' in input('add memory read/write hooks? (y/n) >>>').lower():
    uc.hook_add(UC_HOOK_MEM_READ, hook_mem_read)
    uc.hook_add(UC_HOOK_MEM_WRITE, hook_mem_write)
uc.hook_add(UC_HOOK_MEM_INVALID, hook_mem_invalid)

uc.mem_write(CODE_BASE, CODE)
uc.reg_write(UC_X86_REG_RSP, STACK_BASE + 0x1800)
try:
    uc.emu_start(CODE_BASE, -1)
except Exception as e:
    print(e)

hi, This code will get a UC_ERR_READ_UNMAPPED error. It seems that the code memory cache has not been updated.

add memory read/write hooks? (y/n) >>>n
0x1000 7 48890510000000         mov qword ptr [rip + 0x10], rax
0x1007 9 66c705000000004805     mov word ptr [rip], 0x548
0x1010 6 480578563412   add rax, 0x12345678
[mem_invalid]: 0x1010 19 0x12345678 4 0
Invalid memory read (UC_ERR_READ_UNMAPPED)

But when I add memory read/write hooks it works fine.

add memory read/write hooks? (y/n) >>>y
0x1000 7 48890510000000         mov qword ptr [rip + 0x10], rax
[mem_write]: 17 0x1017 0x0 8
0x1007 9 66c705000000004805     mov word ptr [rip], 0x548
[mem_write]: 17 0x1010 0x548 2
0x1007 9 66c705000000004805     mov word ptr [rip], 0x548
[mem_write]: 17 0x1010 0x548 2
0x1010 6 480578563412   add rax, 0x12345678
0x1016 1 f4     hlt
wtdcode commented 1 month ago

Ah, it seems we leave out invalid mem hooks? Need to investigate.