对于应用安全甲方一般会在这三个方面做防御.按逻辑分类的话应该应该分为这几类, 但如果从实现原理的话, 应该分为两类, 用API实现的 和 不用API实现的(这说的不用 API 实现, 不是指换成 inine 函数就行) . 首先使用 API 实现基本统统沦陷. 直接通过指令实现的机制还有一丝存活的可能. 逻辑的话应该分为, 反调试, 反注入, 越狱检测, hook 检测.arm64 相关知识macho 文件结构以及加载相关知识dyld 链接 dylib 相关函数等知识如何 hook 不定参数函数? 技巧在于伪造原栈的副本. 具体参考下文.通常来说必备手册// 指令格式等细节ARM Architecture Reference Manual(ARMv8, for ARMv8-A architecture profile)https://static.docs.arm.com/ddi0487/b/DDI0487B_a_armv8_arm.pdfARM Cortex -A Series Programmer’s Guide for ARMv8-Ahttp://infocenter.arm.com/help/topic/com.arm.doc.den0024a/DEN0024A_v8_architecture_PG.pdfCalling conventions for different C++ compilers and operating systemshttp://www.agner.org/optimize/calling_conventions.pdfProcedure Call Standard for the ARM 64-bit Architecture (AArch64)http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf通常来说必备源码// dyldhttps://opensource.apple.com/tarballs/dyld/// xnuhttps://opensource.apple.com/tarballs/xnu/// objchttps://opensource.apple.com/tarballs/objc4/https://github.com/RetVal/objc-runtime (可编译)// cctoolshttps://opensource.apple.com/tarballs/cctools (很全的头文件)反调试反调试从逻辑上分大概分为, 一种是直接屏蔽调试器挂载, 另一种就是根据特征手动检测调试器挂载. 当然也分为使用函数实现 和 直接使用内联 asm 实现.ptrace 反调试ptrace 反调试可以使用四种方法实现.1. 直接使用 ptrace 函数这里使用的是 dlopen + dysym.
typedef int (*PTRACE_T)(int request, pid_t pid, caddr_t addr, int data);static void AntiDebug_001() {
void *handle = dlopen(NULL, RTLD_GLOBAL | RTLD_NOW); PTRACE_T ptrace_ptr = dlsym(handle, "ptrace"); ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);}
当然也可以基于 runtime 符号查找.
// runtime to get symbol address, but must link with `// -Wl,-undefined,dynamic_lookup` or you can use `dlopen` and `dlsym`extern int ptrace(int request, pid_t pid, caddr_t addr, int data);static void AntiDebug_002() { ptrace(PT_DENY_ATTACH, 0, 0, 0); }
2. 使用 syscall 实现void AntiDebug_005() { syscall(SYS_ptrace, PT_DENY_ATTACH, 0, 0, 0); }3. 内联 svc + ptrace 实现其实这种方法等同于直接使用 ptrace, 此时系统调用号是 SYS_ptrace
static __attribute__((always_inline)) void AntiDebug_003() {
#ifdef __arm64__ __asm__("mov X0, #31\n" "mov X1, #0\n" "mov X2, #0\n" "mov X3, #0\n" "mov w16, #26\n" "svc #0x80");#endif}
4. 内联 svc + syscall + ptrace 实现其实这种方法等同于使用 syscall(SYS_ptrace, PT_DENY_ATTACH, 0, 0, 0), 这里需要注意, 此时的系统调用号是 0, 也就是 SYS_syscall
static __attribute__((always_inline)) void AntiDebug_004() {
#if