一 ptrace
ptrace 介绍
Ptrace 提供了一种父进程可以控制子进程运行,并可以检查和改变它的核心image。它主要用于实现断点调试。一个被跟踪的进程运行中,直到发生一个信号。则进程被中止,并且通知其父进程。在进程中止的状态下,进程的内存空间可以被读写。父进程还可以使子进程继续执行,并选择是否是否忽略引起中止的信号,这里描述的稍微简单点, 关于iOS的调试机制 lldb -> debugserver ->ptrace
- 首先我们直接看代码
#ifndef _SYS_PTRACE_H_
#define _SYS_PTRACE_H_
#include <sys/appleapiopts.h>
#include <sys/cdefs.h>
enum {
ePtAttachDeprecated __deprecated_enum_msg("PT_ATTACH is deprecated. See PT_ATTACHEXC") = 10
};
#define PT_TRACE_ME 0 /* child declares it's being traced */
#define PT_READ_I 1 /* read word in child's I space */
#define PT_READ_D 2 /* read word in child's D space */
#define PT_READ_U 3 /* read word in child's user structure */
#define PT_WRITE_I 4 /* write word in child's I space */
#define PT_WRITE_D 5 /* write word in child's D space */
#define PT_WRITE_U 6 /* write word in child's user structure */
#define PT_CONTINUE 7 /* continue the child */
#define PT_KILL 8 /* kill the child process */
#define PT_STEP 9 /* single step the child */
#define PT_ATTACH ePtAttachDeprecated /* trace some running process */
#define PT_DETACH 11 /* stop tracing a process */
#define PT_SIGEXC 12 /* signals as exceptions for current_proc */
#define PT_THUPDATE 13 /* signal for thread# */
#define PT_ATTACHEXC 14 /* attach to running process with signal exception */
#define PT_FORCEQUOTA 30 /* Enforce quota for root */
#define PT_DENY_ATTACH 31
#define PT_FIRSTMACH 32 /* for machine-specific requests */
__BEGIN_DECLS
int ptrace(int _request, pid_t _pid, caddr_t _addr, int _data);
__END_DECLS
#endif /* !_SYS_PTRACE_H_ */
函数说明
函数原型:int ptrace(int _request, pid_t _pid, caddr_t _addr, int _data);
参数1:表明ptrace要做的事情
(可以往回查看一下dtrace窗口输出,ptrace第一个参数是14,对应宏定义PT_ATTACHEXC,看到注释,就是我们附加调试到正在运行的进程的意思)。
参数2:进程号PID
参数3:地址
参数4:数据
参数3、4根据参数1决定,具体含义没有深究。
关键的使我们看到第一个入参, 当我们在调试的时候 直接
ptrace(PT_DENY_ATTACH, 0, 0, 0);
那么在我们使用
monkeyDev工具加载的调试工程之后, 就不能对其进行基本的调试了, 应为这个PT_DENY_ATTACH的作用。
攻破ptrace
如果大家了解fishhook 的话, 那么这个就是基本的常规操作了,大家有时间充分的去了解这个库, 很是强大,基本原理一下子说不清楚,这里有一张经典图片
- 上代码
//定义指针,保存原来的函数地址
int (*ptrace_p)(int _request, pid_t _pid, caddr_t _addr, int _data);
//自定义的ptrace
int my_ptrace(int _request, pid_t _pid, caddr_t _addr, int _data){
if (_request != PT_DENY_ATTACH) {//如果不是拒绝附加
return ptrace_p(_request,_pid,_addr,_data);
}
//如果是拒绝附加,就直接return 不执行。
return 0;
}
+(void)load
{
//交换
struct rebinding ptraceBd;
ptraceBd.name = "ptrace";
ptraceBd.replacement = my_ptrace;
ptraceBd.replaced = (void *)&ptrace_p;
struct rebinding binds[] = {ptraceBd};
rebind_symbols(binds, 1);
}
到这里
ptrace就基本攻破了。