Skip to content
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

unicorn 2.1.1: SMC doesn't work. #2029

Open
wallds opened this issue Oct 12, 2024 · 1 comment
Open

unicorn 2.1.1: SMC doesn't work. #2029

wallds opened this issue Oct 12, 2024 · 1 comment
Milestone

Comments

@wallds
Copy link

wallds commented Oct 12, 2024

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
Copy link
Member

wtdcode commented Oct 12, 2024

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

PhilippTakacs added a commit to PhilippTakacs/unicorn that referenced this issue Oct 21, 2024
PhilippTakacs added a commit to PhilippTakacs/unicorn that referenced this issue Oct 22, 2024
PhilippTakacs added a commit to PhilippTakacs/unicorn that referenced this issue Oct 31, 2024
When SMC access the memory region more then once the
tb must be rebuild multible times.

fixes unicorn-engine#2029
wtdcode pushed a commit that referenced this issue Oct 31, 2024
* enable notdirty_write for snapshots when possible

Snapshots only happens when the priority of the memory region is smaller
then the snapshot_level. After a snapshot notdirty can be set.

* disable notdirty_write for self modifying code

When SMC access the memory region more then once the
tb must be rebuild multible times.

fixes #2029

* notdirty_write better hook check

Check all relevant memory hooks before enabling notdirty write.
This also checks if the memory hook is registered for the affected
region. So it is possible to use notdirty write and have some hooks
on different addresses.

* notdirty_write check for addr_write in snapshot case

* self modifying code clear recursive mem access

when self modifying code does unaligned memory accese sometimes
uc->size_recur_mem is changed but for notdirty write not changed back.
This causes mem_hooks to be missed. To fix this uc->size_recur_mem is
set to 0 before each cpu_exec() call.
@wtdcode wtdcode added this to the Unicorn 2.1.2 milestone Dec 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants