HEAP_ADDRESS
=
STACK_ADDRESS
+
0x8000
def
malloc(
*
args):
global
HEAP_ADDRESS
sz
=
ql.uc.reg_read(UC_ARM64_REG_X0)
ql.uc.reg_write(UC_ARM64_REG_X0, HEAP_ADDRESS)
HEAP_ADDRESS
+
=
(sz
+
15
) & ~
15
def
free(
*
args):
pass
def
calloc(
*
args):
global
HEAP_ADDRESS
n
=
ql.uc.reg_read(UC_ARM64_REG_X0)
sz
=
ql.uc.reg_read(UC_ARM64_REG_X1)
*
n
ql.uc.reg_write(UC_ARM64_REG_X0, HEAP_ADDRESS)
HEAP_ADDRESS
+
=
(sz
+
15
) & ~
15
def
realloc(
*
args):
global
HEAP_ADDRESS
ptr
=
ql.uc.reg_read(UC_ARM64_REG_X0)
sz
=
ql.uc.reg_read(UC_ARM64_REG_X1)
if
ptr !
=
0
:
if
sz
=
=
0
:
return
data
=
ql.uc.mem_read(ptr, sz)
ql.uc.mem_write(HEAP_ADDRESS, bytes(data))
ql.uc.reg_write(UC_ARM64_REG_X0, HEAP_ADDRESS)
HEAP_ADDRESS
+
=
(sz
+
15
) & ~
15
MALLOC_ADDR, FREE_ADDR, CALLOC_ADDR, REALLOC_ADDR
=
libc.get_funcs(memory_info, memory_data,
'libc.so'
, [
'malloc'
,
'free'
,
'calloc'
,
'realloc'
])
IL2CPP_BASE_DATA, IL2CPP_BASE_ADDR, IL2CPP_BASE_END
=
libc.read_so(memory_info, memory_data,
"libil2cpp.so"
)
print
(f
'malloc 0x{MALLOC_ADDR:x}'
)
print
(f
'free 0x{FREE_ADDR:x}'
)
print
(f
'calloc 0x{CALLOC_ADDR:x}'
)
print
(f
'dlsym 0x{DLSYM_ADDR:x}'
)
ql.uc.mem_write(MALLOC_ADDR, b
'\xC0\x03\x5F\xD6'
)
ql.uc.mem_write(FREE_ADDR, b
'\xC0\x03\x5F\xD6'
)
ql.uc.mem_write(CALLOC_ADDR, b
'\xC0\x03\x5F\xD6'
)
ql.uc.mem_write(REALLOC_ADDR, b
'\xC0\x03\x5F\xD6'
)
ql.uc.hook_add(UC_HOOK_CODE, malloc,
None
, MALLOC_ADDR, MALLOC_ADDR
+
4
)
ql.uc.hook_add(UC_HOOK_CODE, free,
None
, FREE_ADDR, FREE_ADDR
+
4
)
ql.uc.hook_add(UC_HOOK_CODE, calloc,
None
, CALLOC_ADDR, CALLOC_ADDR
+
4
)
ql.uc.hook_add(UC_HOOK_CODE, realloc,
None
, REALLOC_ADDR, REALLOC_ADDR
+
4
)