Update sample for MRS hook

This commit is contained in:
lazymio 2022-02-27 15:28:18 +01:00
parent dd96cab9bf
commit 7f8ff1af6a
No known key found for this signature in database
GPG Key ID: DFF27E34A47CB873
3 changed files with 115 additions and 1 deletions

View File

@ -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()

View File

@ -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),

View File

@ -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;
} }