微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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)执行完毕时被调试进程可能还没有暂停,可以使用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,void * data)
{
    switch (request) {
        case PTRACE_PEEKUSR:
        case PTRACE_PEEKTEXT:
        case PTRACE_PEEKDATA:
        {
            long word;
            long ret;
            ret = __ptrace(request,addr,&word);
            if (ret == 0) {
                return word;
            } else {
                // __ptrace will set errno for us
                return -1;
            }
        }
        default:
             return __ptrace(request,data);
    }
}

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

单个应用可在ptrace下断点.

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

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐