-
-
[原创]iOS内核修改之过某音等PT_DENY_ATTACH反动态ptrace调试
-
发表于:
2021-4-1 16:39
23888
-
[原创]iOS内核修改之过某音等PT_DENY_ATTACH反动态ptrace调试
现在很多iOS App都有PT_DENY_ATTACH反调试, 造成debugserver无法附加调试.
1 2 3 4 | debugserver - @(
for arm64.
Attaching to process 1468. ..
Segmentation fault: 11
|
光是用Frida调动Hook进行分析难度和工作量很大,里还有很多动态跳转,静态分析难度重重.
重新打包IPA,之前hook ptrace或sysctl等方法跳过检测也已经失效,因为现在都是直接调用syscall调用内核接口.
1 2 3 4 5 6 7 8 9 10 11 | static __attribute__((always_inline)) void asm_ptrace() {
__asm__( "mov X0, #31\n"
"mov X1, #0\n"
"mov X2, #0\n"
"mov X3, #0\n"
"mov X16, #26\n"
"svc #0x80\n"
);
}
|
所以比较好的解决方法就是对内核进行修改.先看一下ptrace内核的源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | int
ptrace(struct proc * p, struct ptrace_args * uap, int32_t * retval)
{
/ / ....
if (uap - >req = = PT_DENY_ATTACH) {
/ / ....
proc_lock(p);
if (ISSET(p - >p_lflag, P_LTRACED)) {
proc_unlock(p);
/ / ...
exit1(p, W_EXITCODE(ENOTSUP, 0 ), retval);
thread_exception_return();
/ * NOTREACHED * /
}
SET (p - >p_lflag, P_LNOATTACH); / / p_lflag | = 0x00001000
proc_unlock(p);
return 0 ;
}
|
实现PT_DENY_ATTACH很简单,就是对相关进程proc的p_lflag加上P_LNOATTACH标识位.
那调试就是去掉P_LNOATTACH就行,那就要找到当前系统所有的进程信息,所有进程都放在了kernproc
1 2 3 4 5 | / * Components of the first process - - never freed. * /
struct proc proc0 = { .p_comm = "kernel_task" , .p_name = "kernel_task" };
SECURITY_READ_ONLY_LATE(proc_t) kernproc = &proc0;
proc_t XNU_PTRAUTH_SIGNED_PTR( "initproc" ) initproc;
|
再找到相关进程的proc,查看proc的结构,也就是所有的内核kernproc(proc0)的子进程都放在了p_list里
1 2 3 | struct proc {
LIST_ENTRY(proc) p_list; / * List of all processes. * /
* * * *
|
找到kernproc在内核的地址,然后通tfp0(task for pid 0)调用
mach_vm_read读取kernproc,遍历kernproc的p_list找到相当进程的proc,对p_lflag,进行修改,再mach_vm_write写回内存即可.
1 2 3 4 | if (proc - >p_pid = = pid) {
proc - >p_lflag & = P_LNOATTACH; / / P_LNOATTACH = 0x1000
mach_vm_write (...&proc - >p_lflag...)
}
|
debugserver此时已经可以进行调试.
有兴趣一起研究iOS内核开发交流可Q: 3.1.0.4.1.9.0.6.2 (倒序) 简单的如tfp0是什么,怎么实现就不要来问我了
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-4-1 17:22
被alice编辑
,原因: