mu = Uc(UC_ARCH_ARM64, UC_MODE_ARM)
BASE_ADDR = 0x40000000
BASE_SIZE = 4 * 1024 * 1024
mu.mem_map(BASE_ADDR, BASE_SIZE)
STACK_ADDR = 0x10000000
STACK_SIZE = 0x00100000
mu.mem_map(STACK_ADDR, STACK_SIZE)
logger.debug(f"Memory map {hex(STACK_ADDR)} - {hex(STACK_ADDR + STACK_SIZE)}")
mu.reg_write(UC_ARM64_REG_SP, STACK_ADDR + STACK_SIZE)
ks = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN)
assembly_code = ';'.join([
'STP X0, X30, [SP,#-0x50]',
'LDR W0, =2',
'STP X0, X1, [SP,#-0x10]!',
'LDR W0, [X30,W0,UXTW#2]',
'ADD X30, X30, W0,UXTW',
'LDP X0, X1, [SP],#0x10',
])
encoding, count = ks.asm(assembly_code.strip())
logger.debug(f"Assembly code {bytes(encoding).hex()}, bytes count {count}")
mu.mem_write(BASE_ADDR, bytes(encoding))
def hook_code(uc: Uc, address: int, size: int, user_data):
inst = uc.mem_read(address, size)
md = Cs(CS_ARCH_ARM64, CS_MODE_ARM)
for i in md.disasm(inst, address):
logger.debug(f">>> {hex(i.address)}:\t{i.mnemonic}\t{i.op_str}")
mu.hook_add(UC_HOOK_CODE, hook_code)
def hook_mem_read_unmapped(uc: Uc, access: int, address: int, size: int, value, user_data):
logger.debug(f">>> Tracing memory read at {hex(address)}, size: {hex(size)}")
mu.hook_add(UC_HOOK_MEM_READ_UNMAPPED, hook_mem_read_unmapped)
def hook_mem_read(uc: Uc, access: int, address: int, size: int, value, user_data):
data = uc.mem_read(address, size)
logger.debug(f">>> Tracing memory read at {hex(address)}, size: {hex(size)}, data: {data.hex()}")
mu.hook_add(UC_HOOK_MEM_READ, hook_mem_read)
mu.reg_write(UC_ARM64_REG_X30, 0x40000000)
mu.emu_start(BASE_ADDR, BASE_ADDR + (4 * count))
sp_value = mu.reg_read(UC_ARM64_REG_SP)
logger.debug(f"After simulate sp value: {hex(sp_value)}")
logger.debug(f"After simulate X0 value: {hex(mu.reg_read(UC_ARM64_REG_X0))}")
logger.debug(f"After simulate X30 value: {hex(mu.reg_read(UC_ARM64_REG_X30))}")