Update sample for MRS hook
This commit is contained in:
parent
dd96cab9bf
commit
7f8ff1af6a
@ -10,6 +10,9 @@ from unicorn.arm64_const import *
|
|||||||
# code to be emulated
|
# code to be emulated
|
||||||
ARM64_CODE = b"\xab\x05\x00\xb8\xaf\x05\x40\x38" # str x11, [x13]; ldrb x15, [x13]
|
ARM64_CODE = b"\xab\x05\x00\xb8\xaf\x05\x40\x38" # str x11, [x13]; ldrb x15, [x13]
|
||||||
|
|
||||||
|
# MSR code
|
||||||
|
ARM64_MRS_CODE = b"\x62\xd0\x3b\xd5" # mrs x2, tpidrro_el0
|
||||||
|
|
||||||
# memory address where emulation starts
|
# memory address where emulation starts
|
||||||
ADDRESS = 0x10000
|
ADDRESS = 0x10000
|
||||||
|
|
||||||
@ -82,7 +85,40 @@ def test_arm64_read_sctlr():
|
|||||||
except UcError as e:
|
except UcError as e:
|
||||||
print("ERROR: %s" % e)
|
print("ERROR: %s" % e)
|
||||||
|
|
||||||
|
def test_arm64_hook_mrs():
|
||||||
|
def _hook_mrs(uc, reg, cp_reg, _):
|
||||||
|
print(f">>> Hook MRS instruction: reg = 0x{reg:x}(UC_ARM64_REG_X2) cp_reg = {cp_reg}")
|
||||||
|
uc.reg_write(reg, 0x114514)
|
||||||
|
print(">>> Write 0x114514 to X")
|
||||||
|
|
||||||
|
# Skip MRS instruction
|
||||||
|
return True
|
||||||
|
|
||||||
|
print("Test hook MRS instruction")
|
||||||
|
try:
|
||||||
|
# Initialize emulator in ARM mode
|
||||||
|
mu = Uc(UC_ARCH_ARM64, UC_MODE_ARM)
|
||||||
|
|
||||||
|
# Map an area for code
|
||||||
|
mu.mem_map(0x1000, 0x1000)
|
||||||
|
|
||||||
|
# Write code
|
||||||
|
mu.mem_write(0x1000, ARM64_MRS_CODE)
|
||||||
|
|
||||||
|
# Hook MRS instruction
|
||||||
|
mu.hook_add(UC_HOOK_INSN, _hook_mrs, None, 1, 0, UC_ARM64_INS_MRS)
|
||||||
|
|
||||||
|
# Start emulation
|
||||||
|
mu.emu_start(0x1000, 0x1000 + len(ARM64_MRS_CODE))
|
||||||
|
|
||||||
|
print(f">>> X2 = {mu.reg_read(UC_ARM64_REG_X2):x}")
|
||||||
|
|
||||||
|
except UcError as e:
|
||||||
|
print("ERROR: %s" % e)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
test_arm64()
|
test_arm64()
|
||||||
print("=" * 26)
|
print("=" * 26)
|
||||||
test_arm64_read_sctlr()
|
test_arm64_read_sctlr()
|
||||||
|
print("=" * 26)
|
||||||
|
test_arm64_hook_mrs()
|
||||||
|
@ -10,6 +10,7 @@ import os.path
|
|||||||
import sys
|
import sys
|
||||||
import weakref
|
import weakref
|
||||||
import functools
|
import functools
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
from . import x86_const, arm_const, arm64_const, unicorn_const as uc
|
from . import x86_const, arm_const, arm64_const, unicorn_const as uc
|
||||||
|
|
||||||
@ -182,6 +183,7 @@ UC_HOOK_INSN_OUT_CB = ctypes.CFUNCTYPE(
|
|||||||
ctypes.c_int, ctypes.c_uint32, ctypes.c_void_p
|
ctypes.c_int, ctypes.c_uint32, ctypes.c_void_p
|
||||||
)
|
)
|
||||||
UC_HOOK_INSN_SYSCALL_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_void_p)
|
UC_HOOK_INSN_SYSCALL_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_void_p)
|
||||||
|
UC_HOOK_INSN_SYS_CB = ctypes.CFUNCTYPE(ctypes.c_uint32, uc_engine, ctypes.c_uint32, ctypes.c_void_p, ctypes.c_void_p)
|
||||||
UC_MMIO_READ_CB = ctypes.CFUNCTYPE(
|
UC_MMIO_READ_CB = ctypes.CFUNCTYPE(
|
||||||
ctypes.c_uint64, uc_engine, ctypes.c_uint64, ctypes.c_int, ctypes.c_void_p
|
ctypes.c_uint64, uc_engine, ctypes.c_uint64, ctypes.c_int, ctypes.c_void_p
|
||||||
)
|
)
|
||||||
@ -666,6 +668,16 @@ class Uc(object):
|
|||||||
(cb, data) = self._callbacks[user_data]
|
(cb, data) = self._callbacks[user_data]
|
||||||
return cb(self, port, size, data)
|
return cb(self, port, size, data)
|
||||||
|
|
||||||
|
@_catch_hook_exception
|
||||||
|
def _hook_insn_sys_cb(self, handle, reg, pcp_reg, user_data):
|
||||||
|
cp_reg = ctypes.cast(pcp_reg, ctypes.POINTER(uc_arm64_cp_reg)).contents
|
||||||
|
|
||||||
|
uc_arm64_cp_reg_tuple = namedtuple("uc_arm64_cp_reg_tuple", ["crn", "crm", "op0", "op1", "op2", "val"])
|
||||||
|
|
||||||
|
(cb, data) = self._callbacks[user_data]
|
||||||
|
|
||||||
|
return cb(self, reg, uc_arm64_cp_reg_tuple(cp_reg.crn, cp_reg.crm, cp_reg.op0, cp_reg.op1, cp_reg.op2, cp_reg.val), data)
|
||||||
|
|
||||||
@_catch_hook_exception
|
@_catch_hook_exception
|
||||||
def _hook_insn_out_cb(self, handle, port, size, value, user_data):
|
def _hook_insn_out_cb(self, handle, port, size, value, user_data):
|
||||||
# call user's callback with self object
|
# call user's callback with self object
|
||||||
@ -773,6 +785,8 @@ class Uc(object):
|
|||||||
cb = ctypes.cast(UC_HOOK_INSN_OUT_CB(self._hook_insn_out_cb), UC_HOOK_INSN_OUT_CB)
|
cb = ctypes.cast(UC_HOOK_INSN_OUT_CB(self._hook_insn_out_cb), UC_HOOK_INSN_OUT_CB)
|
||||||
if arg1 in (x86_const.UC_X86_INS_SYSCALL, x86_const.UC_X86_INS_SYSENTER): # SYSCALL/SYSENTER instruction
|
if arg1 in (x86_const.UC_X86_INS_SYSCALL, x86_const.UC_X86_INS_SYSENTER): # SYSCALL/SYSENTER instruction
|
||||||
cb = ctypes.cast(UC_HOOK_INSN_SYSCALL_CB(self._hook_insn_syscall_cb), UC_HOOK_INSN_SYSCALL_CB)
|
cb = ctypes.cast(UC_HOOK_INSN_SYSCALL_CB(self._hook_insn_syscall_cb), UC_HOOK_INSN_SYSCALL_CB)
|
||||||
|
if arg1 in (arm64_const.UC_ARM64_INS_MRS, arm64_const.UC_ARM64_INS_MSR, arm64_const.UC_ARM64_INS_SYS, arm64_const.UC_ARM64_INS_SYSL):
|
||||||
|
cb = ctypes.cast(UC_HOOK_INSN_SYS_CB(self._hook_insn_sys_cb), UC_HOOK_INSN_SYS_CB)
|
||||||
status = _uc.uc_hook_add(
|
status = _uc.uc_hook_add(
|
||||||
self._uch, ctypes.byref(_h2), htype, cb,
|
self._uch, ctypes.byref(_h2), htype, cb,
|
||||||
ctypes.cast(self._callback_count, ctypes.c_void_p),
|
ctypes.cast(self._callback_count, ctypes.c_void_p),
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
// ldrb w15, [x13]
|
// ldrb w15, [x13]
|
||||||
#define ARM64_CODE_EB ARM64_CODE
|
#define ARM64_CODE_EB ARM64_CODE
|
||||||
|
|
||||||
|
// mrs x2, tpidrro_el0
|
||||||
|
#define ARM64_MRS_CODE "\x62\xd0\x3b\xd5"
|
||||||
|
|
||||||
// memory address where emulation starts
|
// memory address where emulation starts
|
||||||
#define ADDRESS 0x10000
|
#define ADDRESS 0x10000
|
||||||
|
|
||||||
@ -204,7 +207,7 @@ static void test_arm64_sctlr()
|
|||||||
|
|
||||||
err = uc_open(UC_ARCH_ARM64, UC_MODE_LITTLE_ENDIAN | UC_MODE_ARM, &uc);
|
err = uc_open(UC_ARCH_ARM64, UC_MODE_LITTLE_ENDIAN | UC_MODE_ARM, &uc);
|
||||||
if (err != UC_ERR_OK) {
|
if (err != UC_ERR_OK) {
|
||||||
printf("Failed on uc_emu_start() with error returned: %u\n", err);
|
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SCTLR_EL1. See arm reference.
|
// SCTLR_EL1. See arm reference.
|
||||||
@ -232,6 +235,64 @@ static void test_arm64_sctlr()
|
|||||||
uc_close(uc);
|
uc_close(uc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t hook_mrs(uc_engine *uc, uc_arm64_reg reg,
|
||||||
|
const uc_arm64_cp_reg *cp_reg, void *user_data)
|
||||||
|
{
|
||||||
|
uint64_t r_x2 = 0x114514;
|
||||||
|
|
||||||
|
printf(">>> Hook MSR instruction. Write 0x114514 to X2.\n");
|
||||||
|
|
||||||
|
uc_reg_write(uc, reg, &r_x2);
|
||||||
|
|
||||||
|
// Skip
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_arm64_hook_mrs()
|
||||||
|
{
|
||||||
|
uc_engine *uc;
|
||||||
|
uc_err err;
|
||||||
|
uint64_t r_x2;
|
||||||
|
uc_hook hk;
|
||||||
|
|
||||||
|
printf("Hook MRS instruction.\n");
|
||||||
|
|
||||||
|
err = uc_open(UC_ARCH_ARM64, UC_MODE_LITTLE_ENDIAN | UC_MODE_ARM, &uc);
|
||||||
|
if (err != UC_ERR_OK) {
|
||||||
|
printf("Failed on uc_open() with error returned: %u\n", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL);
|
||||||
|
if (err != UC_ERR_OK) {
|
||||||
|
printf("Failed on uc_mem_map() with error returned: %u\n", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = uc_mem_write(uc, 0x1000, ARM64_MRS_CODE, sizeof(ARM64_MRS_CODE));
|
||||||
|
if (err != UC_ERR_OK) {
|
||||||
|
printf("Failed on uc_mem_write() with error returned: %u\n", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = uc_hook_add(uc, &hk, UC_HOOK_INSN, hook_mrs, NULL, 1, 0,
|
||||||
|
UC_ARM64_INS_MRS);
|
||||||
|
if (err != UC_ERR_OK) {
|
||||||
|
printf("Failed on uc_hook_add() with error returned: %u\n", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = uc_emu_start(uc, 0x1000, 0x1000 + sizeof(ARM64_MRS_CODE) - 1, 0, 0);
|
||||||
|
if (err != UC_ERR_OK) {
|
||||||
|
printf("Failed on uc_emu_start() with error returned: %u\n", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = uc_reg_read(uc, UC_ARM64_REG_X2, &r_x2);
|
||||||
|
if (err != UC_ERR_OK) {
|
||||||
|
printf("Failed on uc_reg_read() with error returned: %u\n", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(">>> X2 = 0x%" PRIx64 "\n", r_x2);
|
||||||
|
|
||||||
|
uc_close(uc);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv, char **envp)
|
int main(int argc, char **argv, char **envp)
|
||||||
{
|
{
|
||||||
test_arm64_mem_fetch();
|
test_arm64_mem_fetch();
|
||||||
@ -243,5 +304,8 @@ int main(int argc, char **argv, char **envp)
|
|||||||
printf("-------------------------\n");
|
printf("-------------------------\n");
|
||||||
test_arm64_sctlr();
|
test_arm64_sctlr();
|
||||||
|
|
||||||
|
printf("-------------------------\n");
|
||||||
|
test_arm64_hook_mrs();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user