iOS 应用攻防-ptrace

1,670 阅读2分钟

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就基本攻破了。


下章研究sysctl