import struct
from unicorn import *
from unicorn.x86_const import *
filename = "./function"
base_adr = 0x400000
stack_adr = 0x0
stack_size = 1024 * 1024
main_start_adr = 0x000005B4 + base_adr
main_end_adr = 0x000005D5 + base_adr
super_function_start = 0x0000057B + base_adr
super_function_end = 0x000005B1 + base_adr
def read(name):
with open(name, "rb") as f:
return f.read()
def u32(data):
return struct.unpack("I", data)[0]
def p32(num):
return struct.pack("I", num)
def hook_code(mu, address, size, user_data):
# print('>>> Tracing instruction at 0x%x, instruction size = 0x%x' %(address, size))
if address == super_function_start:
esp = mu.reg_read(UC_X86_REG_ESP)
ret_adr = u32(mu.mem_read(esp, 4))
arg0 = u32(mu.mem_read(esp + 4, 4))
arg1 = u32(mu.mem_read(esp + 8, 4))
arg1_string = mu.mem_read(arg1, 16)
print("[*] super function start - original")
print(f"esp: {hex(esp)}")
print(f"ret_adr: {hex(ret_adr)}")
print(f"arg0: {arg0}")
print(f"arg1: {hex(arg1)} -> {arg1_string}")
print("")
mu.mem_write(esp + 4, p32(5))
mu.mem_write(arg1, b"batman\x00")
esp = mu.reg_read(UC_X86_REG_ESP)
ret_adr = u32(mu.mem_read(esp, 4))
arg0 = u32(mu.mem_read(esp + 4, 4))
arg1 = u32(mu.mem_read(esp + 8, 4))
arg1_string = mu.mem_read(arg1, 16)
print("[*] super function start - modify")
print(f"esp: {hex(esp)}")
print(f"ret_adr: {hex(ret_adr)}")
print(f"arg0: {arg0}")
print(f"arg1: {hex(arg1)} -> {arg1_string}")
print("")
elif address == super_function_end:
ret_val = mu.reg_read(UC_X86_REG_EAX)
print("[*] super function end")
print(f"Return value: {hex(ret_val)}")
try:
mu = Uc(UC_ARCH_X86, UC_MODE_32)
mu.mem_map(base_adr, 1024 * 1024)
mu.mem_map(stack_adr, stack_size)
mu.mem_write(base_adr, read(filename))
mu.reg_write(UC_X86_REG_ESP, stack_adr + stack_size - 1)
mu.hook_add(UC_HOOK_CODE, hook_code)
mu.emu_start(main_start_adr, main_end_adr)
except UcError as e:
print("ERROR: %s" % e)