from
emu_utils
import
*
from
unicorn
import
*
from
unicorn.arm64_const
import
*
def
trace_back_insn_with_target(insn_queue, target_reg):
for
insn
in
insn_queue:
if
(target_reg
in
insn.op_str):
if
(insn.mnemonic
=
=
'add'
):
print
(insn.mnemonic
+
'\t'
+
insn.op_str)
if
(insn.mnemonic
=
=
'ldr'
):
print
(insn.mnemonic
+
'\t'
+
insn.op_str)
if
(insn.mnemonic
=
=
'csel'
):
print
(insn.mnemonic
+
'\t'
+
insn.op_str)
def
log_hook(emu, addr, size, user_data):
disasm
=
get_disasm(emu, addr, size)
print
(
hex
(addr)
+
'\t'
+
disasm.mnemonic
+
'\t'
+
disasm.op_str)
def
step_over_hook(emu, addr, size, none):
disasm
=
get_disasm(emu, addr, size)
if
(disasm.mnemonic
=
=
'bl'
or
disasm.mnemonic
=
=
'blr'
):
emu.reg_write(UC_ARM64_REG_PC, addr
+
size)
if
(disasm.mnemonic
=
=
'ret'
):
print
(
'function returned'
)
emu.emu_stop()
if
(addr
=
=
0x3ac68
):
emu.reg_write(UC_ARM64_REG_W10,
0xEECF7326
)
def
normal_hook(emu, addr, size, insn_queue):
global
const_value, offset_value, cond, cond_value, uncond_value
disasm
=
get_disasm(emu, addr, size)
reg_maps
=
get_reg_maps()
insn_queue.insert(
0
, disasm)
if
(
len
(insn_queue) >
8
):
insn_queue.pop()
if
(disasm.mnemonic
=
=
'csel'
):
cond_value
=
emu.reg_read(reg_maps[disasm.op_str.split(
', '
)[
1
]])
uncond_value
=
emu.reg_read(reg_maps[disasm.op_str.split(
', '
)[
2
]])
cond
=
disasm.op_str.split(
', '
)[
3
]
if
(disasm.mnemonic
=
=
'cset'
):
cond_value
=
1
uncond_value
=
0
cond
=
disasm.op_str.split(
', '
)[
1
]
if
(disasm.mnemonic
=
=
'ldr'
):
if
(
len
(disasm.op_str.split(
', '
))
=
=
3
):
offset_value
=
emu.reg_read(
reg_maps[disasm.op_str.split(
', '
)[
1
].split(
'['
)[
1
]])
elif
(
len
(disasm.op_str.split(
', '
))
=
=
4
):
offset_value
=
emu.reg_read(
reg_maps[disasm.op_str.split(
', '
)[
1
].split(
'['
)[
1
]])
cond_value
*
=
8
if
(disasm.mnemonic
=
=
'add'
and
'#'
not
in
disasm.op_str
and
'w'
not
in
disasm.op_str):
const_value
=
emu.reg_read(reg_maps[disasm.op_str.split(
', '
)[
2
]])
if
(disasm.mnemonic
=
=
'br'
):
print
(
'on br insn'
)
target_reg
=
disasm.op_str
trace_back_insn_with_target(insn_queue, target_reg)
print
(
hex
(const_value),
hex
(offset_value),
cond, cond_value, uncond_value)
cond_addr
=
emu.mem_read(offset_value
+
cond_value,
4
)
cond_addr
=
(
int
.from_bytes(
cond_addr, byteorder
=
'little'
)
+
const_value) &
0xffffffff
uncond_addr
=
emu.mem_read(offset_value
+
uncond_value,
4
)
uncond_addr
=
(
int
.from_bytes(
uncond_addr, byteorder
=
'little'
)
+
const_value) &
0xffffffff
patch_asm
=
b''
patch_asm
+
=
get_asm(
'b'
+
cond
+
' '
+
hex
(cond_addr), addr
-
4
)
patch_asm
+
=
get_asm(
'b '
+
hex
(uncond_addr), addr)
emu.reg_write(UC_ARM64_REG_PC, addr
+
size)
def
emulate_execution(filename, start_addr, hook_func, user_data):
emu
=
Uc(UC_ARCH_ARM64, UC_MODE_LITTLE_ENDIAN)
textSec
=
get_section(filename,
'.text'
)
dataSec
=
get_section(filename,
'.data'
)
textSec_entry
=
textSec.header[
'sh_addr'
]
textSec_size
=
textSec.header[
'sh_size'
]
textSec_raw
=
textSec.header[
'sh_offset'
]
TEXT_BASE
=
textSec_entry >>
12
<<
12
TEXT_SIZE
=
(textSec_size
+
0x1000
) >>
12
<<
12
TEXT_RBASE
=
textSec_raw >>
12
<<
12
dataSec_entry
=
dataSec.header[
'sh_addr'
]
dataSec_size
=
dataSec.header[
'sh_size'
]
dataSec_raw
=
dataSec.header[
'sh_offset'
]
DATA_BASE
=
dataSec_entry >>
12
<<
12
DATA_SIZE
=
(dataSec_size
+
0x1000
) >>
12
<<
12
DATA_RBASE
=
dataSec_raw >>
12
<<
12
VOID_1_BASE
=
0x00000000
VOID_1_SIZE
=
TEXT_BASE
VOID_2_BASE
=
TEXT_BASE
+
TEXT_SIZE
VOID_2_SIZE
=
DATA_BASE
-
VOID_2_BASE
STACK_BASE
=
DATA_BASE
+
DATA_SIZE
STACK_SIZE
=
0xFFFFFFFF
-
STACK_BASE >>
12
<<
12
emu.mem_map(VOID_1_BASE, VOID_1_SIZE)
emu.mem_map(TEXT_BASE, TEXT_SIZE)
emu.mem_map(DATA_BASE, DATA_SIZE)
emu.mem_map(VOID_2_BASE, VOID_2_SIZE)
emu.mem_map(STACK_BASE, STACK_SIZE)
emu.mem_write(TEXT_BASE, read(filename)[TEXT_RBASE:TEXT_RBASE
+
TEXT_SIZE])
emu.mem_write(DATA_BASE, read(filename)[DATA_RBASE:DATA_RBASE
+
DATA_SIZE])
emu.reg_write(UC_ARM64_REG_FP, STACK_BASE
+
0x1000
)
emu.reg_write(UC_ARM64_REG_SP, STACK_BASE
+
STACK_SIZE
/
/
2
)
emu.hook_add(UC_HOOK_CODE, log_hook)
emu.hook_add(UC_HOOK_CODE, step_over_hook, user_data)
emu.hook_add(UC_HOOK_CODE, hook_func, user_data)
emu.emu_start(start_addr,
0x0
)
if
__name__
=
=
'__main__'
:
filename
=
'./libsec2023.so'
start_addr
=
0x3ac68
insn_queue
=
[]
emulate_execution(filename, start_addr, normal_hook, insn_queue)