linux ptrace反调试之抢占ptrace

ptrace和debugger原理

ptrace

ptrace可以让一个进程监视和控制另一个进程的执行,并且修改被监视进程的内存、寄存器等,主要应用于断点调试和系统调用跟踪.

函数原型:

long ptrace(int request, pid_t pid, void * addr, void * data)

其中,request代表请求类型,pid代表被调试进程的pid.

 

部分ptrace request和wait

PTRACE_TRACEME
表示本进程将被其父进程跟踪,交付给这个进程的所有信号(除SIGKILL之外),都将使其停止,父进程将通过wait()获知这一情况。
它通常总是与 fork/exec 一起使用。对于每一个进程,PTRACE_TRACEME 只能被调用一次。

PTRACE_ATTACH
根据pid将调试进程附加到被调试进程上,PTRACE_ATTACH向被调试进程发送SIGSTOP信号使之停下.
但是在ptrace(PTRACE_ATTACH,pid,0,0)执行完毕时被调试进程可能还没有暂停,可以使用waitpid()等待其停下.

PTRACE_DETACH
将被调试进程与调试进程分离,使被调试进程正常运行.

PTRACE_SYSCALL
使被调试进程继续运行,但是在下一个系统调用的入口处或出口处停下,或者是执行完一条指令后停下.
例如,调试进程可以监视被调试进程系统调用入口处的参数,接着再使用SYSCALL,监视系统调用的返回值.

wait()
wait函数会延迟父进程的执行,直到被调试的进程切换为停止状态或者终止为止.

 

调试器建立调试关系的两种方式:

用gdb调试程序,可以直接gdb ./test,也可以gdb (test的进程号)。这对应着使用ptrace建立跟踪关系的两种方式:

fork:利用fork+execve执行被测试的程序,子进程在执行execve之前调用ptrace(PTRACE_TRACEME),建立了与父进程(debugger)的跟踪关系。

attach: debugger可以调用ptrace(PTRACE_ATTACH,pid,…),建立自己与进程号为pid的进程间的跟踪关系。即利用PTRACE_ATTACH,使自己变成被调试程序的父进程(用ps可以看到)。用attach建立起来的跟踪关系,可以调用ptrace(PTRACE_DETACH,pid,…)来解除。注意attach进程时的权限问题,如一个非root权限的进程是不能attach到一个root进程上的。

 

反调试

ptrace被广泛用于反调试,因为一个进程只能被ptrace一次,如果事先调用了ptrace方法,那就可以防止别人调试我们的程序.

测试程序:

#include<stdio.h>
#include<stdlib.h>
#include<sys/ptrace.h>
int main(int argc, char* argv[])
{
    ptrace(PTRACE_TRACEME);
    while(1){
        printf("Hello Ptrace!\n");
        sleep(1);
    }
    return 0;
}

编译:gcc -g -o hello-ptrace hello-ptrace.c

运行并用gdb调试,发现已经被抢占,不能attach

已经由于PTRACE_TRACEME,被父进程trace

 

检测

#include<stdio.h>
#include<sys/ptrace.h>
int main(int argc, char* argv[])
{
    if(-1 == ptrace(PTRACE_TRACEME))
    {
        printf("Debugger!\n");
        return 1;
    }
    printf("Hello Ptrace!\n");
    return 0;
}

 

反反调试

ptrace用户态源码(位于bionic/libc/bionic/ptrace.c):

long ptrace(int request, pid_t pid, void * addr, void * data)
{
    switch (request) {
        case PTRACE_PEEKUSR:
        case PTRACE_PEEKTEXT:
        case PTRACE_PEEKDATA:
        {
            long word;
            long ret;
            ret = __ptrace(request, pid, addr, &word);
            if (ret == 0) {
                return word;
            } else {
                // __ptrace will set errno for us
                return -1;
            }
        }
        default:
             return __ptrace(request, pid, addr, data);
    }
}

0表示成功,-1表示错误.

单个应用可在ptrace下断点.

定制ROM,可以将ptrace源代码修改为如果是自己的pid调用ptrace,返回-1;否则返回0.

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值