在「iOS 逆向入门 - 绕过抖音反调试」中提到常用反调试手段,这里写下具体实现。
一、常用反逆向手段
1、反调试:ptrace
ptrace
被常用于防止 lldb 依附,原理是一个进程只能被 ptrace
只能被一次,先于别人调用 ptrace
则可以防止别人依附。
ptrace
有几种方式进行调用:
1)直接调用
#import <sys/ptrace.h>
ptrace(PT_DENY_ATTACH,0,0,0);
iOS SDK 中不包含 ptrace.h 头文件,无法使用此方法调用,可使用以下方法。
2)通过 dlopen
+ dlsym
调用
#import <dlfcn.h>
#import <sys/types.h>
typedef int (*ptrace_ptr_t)(int _request, pid_t _pid, caddr_t _addr, int _data);
#if !defined(PT_DENY_ATTACH)
#define PT_DENY_ATTACH 31
#endif
void disable_attach() {
void* handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);
ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace");
ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);
dlclose(handle);
}
3)通过 syscall
调用
#import <sys/syscall.h>
#if !defined(PT_DENY_ATTACH)
#define PT_DENY_ATTACH 31
#endif
void disable_attach() {
syscall(SYS_ptrace, PT_DENY_ATTACH, 0, 0, 0); // #define SYS_ptrace 26
}
4)通过汇编调用
内联 svc + ptrace 实现,相当于直接调用 ptrace(PT_DENY_ATTACH,0,0,0);
static __attribute__((always_inline)) void disable_attach() {
#ifdef __arm64__
__asm__("mov X0, #0x1F");
__asm__("mov X1, #0");
__asm__("mov X2, #0");
__asm__("mov X3, #0");
__asm__("mov X16, #0x1A");
__asm__("svc #0x80");
#endif
}
内联 svc + syscall + ptrace 实现,相当于 syscall(SYS_ptrace, PT_DENY_ATTACH, 0, 0, 0);
static __attribute__((always_inline)) void disable_attach() {
#ifdef __arm64__
__asm__("mov X0, #0x1A");
__asm__("mov X1, #0x1F");
__asm__("mov X2, #0");
__asm__("mov X3, #0");
__asm__("mov X4, #0");
__asm__("mov X16, #0");
__asm__("svc #0x80");
#endif
}
2、sysctl
通过 sysctl 去查看当前进程的信息,看有没有这个标记位即可检查当前调试状态。
#import <sys/sysctl.h>
bool isBeingAttach() {
size_t size = sizeof(struct kinfo_proc);
struct kinfo_proc info;
int ret = 0, name[4];
memset(&info, 0, sizeof(struct kinfo_proc));
name[0] = CTL_KERN;
name[1] = KERN_PROC;
name[2] = KERN_PROC_PID;
name[3] = getpid();
if (ret == (sysctl(name, 4, &info, &size, NULL, 0))) {
return ret != 0;
}
return (info.kp_proc.p_flag & P_TRACED) ? YES : NO;
}