玩转ptrace(二)

openEuler在虚拟机的网络配置 ethernet0.virtualDev 可以配置成其他类型的虚拟网络适配器。常见的选项包括:vlance - 用于模拟 AMD PCnet32 LANCE 网络适配器,支持10Mbps。e1000 - 用于模拟 Intel E1000 千兆网络适配器,支持1Gbps。e1000e - 用于模拟更现代的 Intel E1000e 千兆网络适配器。vmxnet - 用于 VMware 的自定义网络适配器,性能更好但需要安装 VMware Tools。 阅读详情

转自:http://blog.youkuaiyun.com/silentvoid/article/details/1477515

by Pradeep Padala

Created 2002-11-01 02:00

翻译: Magic.D

 

在第一部分中我们已经看到ptrace怎么获取子进程的系统调用以及改变系统调用的参数。在这篇文章中,我们将要研究如何在子进程中设置断点和往运行中的程序里插入代码。实际上调试器就是用这种方法来设置断点和执行调试句柄。与前面一样,这里的所有代码都是针对i386平台的。

 

附着在进程上

 

在第一部分钟,我们使用ptrace(PTRACE_TRACEME, …)来跟踪一个子进程,如果你只是想要看进程是怎么进行系统调用和跟踪程序的,这个做法是不错的。但如果你要对运行中的进程进行调试,则需要使用 ptrace( PTRACE_ATTACH, ….)

 

当 ptrace( PTRACE_ATTACH, …)在被调用的时候传入了子进程的pid时, 它大体是与ptrace( PTRACE_TRACEME, …)的行为相同的,它会向子进程发送SIGSTOP信号,于是我们可以察看和修改子进程,然后使用 ptrace( PTRACE_DETACH, …)来使子进程继续运行下去。

 

下面是调试程序的一个简单例子

 

int main()
...{   
   int i;
    for(i = 0;i < 10; ++i) ...{
        printf("My counter: %d ", i);
        sleep(2);
    }
    return 0;
}

 

将上面的代码保存为dummy2.c。按下面的方法编译运行:

gcc -o dummy2 dummy2.c
./dummy2 &

 

现在我们可以用下面的代码来附着到dummy2上。

 

#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <linux/user.h>   /**//* For user_regs_struct 
                             etc. */
int main(int argc, char *argv[])
...{   
    pid_t traced_process;
    struct user_regs_struct regs;
    long ins;
    if(argc != 2) ...{
        printf("Usage: %s <pid to be traced> ",
               argv[0], argv[1]);
        exit(1);
    }
    traced_process = atoi(argv[1]);
    ptrace(PTRACE_ATTACH, traced_process, 
           NULL, NULL);
    wait(NULL);
    ptrace(PTRACE_GETREGS, traced_process, 
           NULL, &regs);
    ins = ptrace(PTRACE_PEEKTEXT, traced_process, 
                 regs.eip, NULL);
    printf("EIP: %lx Instruction executed: %lx ", 
           regs.eip, ins);
    ptrace(PTRACE_DETACH, traced_process, 
           NULL, NULL);
    return 0;
}

 

上面的程序仅仅是附着在子进程上,等待它结束,并测量它的eip( 指令指针)然后释放子进程。

 

设置断点

 

调试器是怎么设置断点的呢?通常是将当前将要执行的指令替换成trap指令,于是被调试的程序就会在这里停滞,这时调试器就可以察看被调试程序的信息了。被调试程序恢复运行以后调试器会把原指令再放回来。这里是一个例子:

 

#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <linux/user.h>

const int long_size = sizeof(long);

void getdata(pid_t child, long addr, 
             char *str, int len)
...{   
    char *laddr;
    int i, j;
    union u ...{
            long val;
            char chars[long_size];
    }data;

    i = 0;
    j = len / long_size;
    laddr = str;

    while(i < j) ...{
        data.val = ptrace(PTRACE_PEEKDATA, child, 
                          addr + i * 4, NULL);
        memcpy(laddr, data.chars, long_size);
        ++i;
        laddr += long_size;
    }
    j = len % long_size;
    if(j != 0) ...{
        data.val = ptrace(PTRACE_PEEKDATA, child, 
                          addr + i * 4, NULL);
        memcpy(laddr, data.chars, j);
    }
    str[len] = '';
}

void putdata(pid_t child, long addr, 
             char *str, int len)
...{   
    char *laddr;
    int i, j;
    union u ...{
            long val;
            char chars[long_size];
    }data;

    i = 0;
    j = len / long_size;
    laddr = str;
    while(i < j) ...{
        memcpy(data.chars, laddr, long_size);
        ptrace(PTRACE_POKEDATA, child, 
               addr + i * 4, data.val);
        ++i;
        laddr += long_size;
    }
    j = len % long_size;
    if(j != 0) ...{
        memcpy(data.chars, laddr, j);
        ptrace(PTRACE_POKEDATA, child, 
               addr + i * 4, data.val);
    }
}

int main(int argc, char *argv[])
...{   
    pid_t traced_process;
    struct user_regs_struct regs, newregs;
    long ins;
    /**//* int 0x80, int3 */
    char code[] = ...{0xcd,0x80,0xcc,0};
    char backup[4];
    if(argc != 2) ...{
        printf("Usage: %s <pid to be traced> ", 
               argv[0], argv[1]);
        exit(1);
    }
    traced_process = atoi(argv[1]);
    ptrace(PTRACE_ATTACH, traced_process, 
           NULL, NULL);
    wait(NULL);
    ptrace(PTRACE_GETREGS, traced_process, 
           NULL, &regs);
    /**//* Copy instructions into a backup variable */
    getdata(traced_process, regs.eip, backup, 3);
    /**//* Put the breakpoint */
    putdata(traced_process, regs.eip, code, 3);
    /**//* Let the process continue and execute 
       the int 3 instruction */
    ptrace(PTRACE_CONT, traced_process, NULL, NULL);
    wait(NULL);
    printf("The process stopped, putting back "
           "the original instructions ");
    printf("Press <enter> to continue ");
    getchar();
    putdata(traced_process, regs.eip, backup, 3);
    /**//* Setting the eip back to the original 
       instruction to let the process continue */
    ptrace(PTRACE_SETREGS, traced_process, 
           NULL, &regs);
    ptrace(PTRACE_DETACH, traced_process, 
           NULL, NULL);
    return 0;

}

 

上面的程序将把三个byte的内容进行替换以执行trap指令,等被调试进程停滞以后,我们把原指令再替换回来并把eip修改为原来的值。下面的图中演示了指令的执行过程

 

 

 

1. 进程停滞后

2. 替换入trap指令

 

 

3.断点成功,控制权交给了调试器

4. 继续运行,将原指令替换回来并将eip复原

 

 

在了解了断点的机制以后,往运行中的程序里面添加指令也不再是难事了,下面的代码会使原程序多出一个”hello world”的输出

 

这时一个简单的”hello world”程序,当然为了我们的特殊需要作了点修改:

 

void main()
...{
__asm__("
         jmp forward
backward:
         popl   %esi      # Get the address of 
                          # hello world string
         movl   $4, %eax  # Do write system call
         movl   $2, %ebx
         movl   %esi, %ecx
         movl   $12, %edx
         int    $0x80
         int3             # Breakpoint. Here the 
                          # program will stop and 
                          # give control back to 
                          # the parent
forward:
         call   backward
         .string "Hello World/n""
       );
}
 

使用 gcc –o hello hello.c来编译它。

 

在backward和forward之间的跳转是为了使程序能够找到”hello world” 字符串的地址。

 

使用GDB我们可以得到上面那段程序的机器码。启动GDB,然后对程序进行反汇编:

 

(gdb) disassemble main
Dump of assembler code for function main:
0x80483e0 <main>:       push   %ebp
0x80483e1 <main+1>:     mov    %esp,%ebp
0x80483e3 <main+3>:     jmp    0x80483fa <forward>
End of assembler dump.
(gdb) disassemble forward
Dump of assembler code for function forward:
0x80483fa <forward>:    call   0x80483e5 <backward>
0x80483ff <forward+5>:  dec    %eax
0x8048400 <forward+6>:  gs
0x8048401 <forward+7>:  insb   (%dx),%es:(%edi)
0x8048402 <forward+8>:  insb   (%dx),%es:(%edi)
0x8048403 <forward+9>:  outsl  %ds:(%esi),(%dx)
0x8048404 <forward+10>: and    %dl,0x6f(%edi)
0x8048407 <forward+13>: jb     0x8048475
0x8048409 <forward+15>: or     %fs:(%eax),%al
0x804840c <forward+18>: mov    %ebp,%esp
0x804840e <forward+20>: pop    %ebp
0x804840f <forward+21>: ret
End of assembler dump.
(gdb) disassemble backward
Dump of assembler code for function backward:
0x80483e5 <backward>:   pop    %esi
0x80483e6 <backward+1>: mov    $0x4,%eax
0x80483eb <backward+6>: mov    $0x2,%ebx
0x80483f0 <backward+11>:        mov    %esi,%ecx
0x80483f2 <backward+13>:        mov    $0xc,%edx
0x80483f7 <backward+18>:        int    $0x80
0x80483f9 <backward+20>:        int3
End of assembler dump.
 

 

我们需要使用从man+3到backward+20之间的字节码,总共41字节。使用GDB中的x命令来察看机器码。

 

(gdb) x/40bx main+3
<main+3>: eb 15 5e b8 04 00 00 00
<backward+6>: bb 02 00 00 00 89 f1 ba
<backward+14>: 0c 00 00 00 cd 80 cc
<forward+1>: e6 ff ff ff 48 65 6c 6c
<forward+9>: 6f 20 57 6f 72 6c 64 0a

 

已经有了我们想要执行的指令,还等什么呢?只管把它们根前面那个例子一样插入到被调试程序中去!

 

代码:

int main(int argc, char *argv[])
...{   
pid_t traced_process;
    struct user_regs_struct regs, newregs;
    long ins;
    int len = 41;
    char insertcode[] =
        "/xeb/x15/x5e/xb8/x04/x00"
        "/x00/x00/xbb/x02/x00/x00/x00/x89/xf1/xba"
        "/x0c/x00/x00/x00/xcd/x80/xcc/xe8/xe6/xff"
        "/xff/xff/x48/x65/x6c/x6c/x6f/x20/x57/x6f"
        "/x72/x6c/x64/x0a/x00";
    char backup[len];
    if(argc != 2) ...{
        printf("Usage: %s <pid to be traced> ", 
               argv[0], argv[1]);
        exit(1);
    }
    traced_process = atoi(argv[1]);
    ptrace(PTRACE_ATTACH, traced_process, 
           NULL, NULL);
    wait(NULL);
    ptrace(PTRACE_GETREGS, traced_process, 
           NULL, &regs);
    getdata(traced_process, regs.eip, backup, len);
    putdata(traced_process, regs.eip, 
            insertcode, len);
    ptrace(PTRACE_SETREGS, traced_process, 
           NULL, &regs);
    ptrace(PTRACE_CONT, traced_process, 
           NULL, NULL);
    wait(NULL);
    printf("The process stopped, Putting back "
           "the original instructions ");
    putdata(traced_process, regs.eip, backup, len);
    ptrace(PTRACE_SETREGS, traced_process, 
           NULL, &regs);
    printf("Letting it continue with "
           "original flow ");
    ptrace(PTRACE_DETACH, traced_process,
           NULL, NULL);
    return 0;
}

将代码插入到自由空间

 

在前面的例子中我们将代码直接插入到了正在执行的指令流中,然而,调试器可能会被这种行为弄糊涂,所以我们决定把指令插入到进程中的自由空间中去。通过察看/proc/pid/maps可以知道这个进程中自由空间的分布。接下来这个函数可以找到这个内存映射的起始点:

long freespaceaddr(pid_t pid)
...{
    FILE *fp;
    char filename[30];
    char line[85];
    long addr;
    char str[20];
    sprintf(filename, "/proc/%d/maps", pid);
    fp = fopen(filename, "r");
    if(fp == NULL)
        exit(1);
    while(fgets(line, 85, fp) != NULL) ...{
        sscanf(line, "%lx-%*lx %*s %*s %s", &addr, 
               str, str, str, str);
        if(strcmp(str, "00:00") == 0)
            break;
    }
    fclose(fp);
    return addr;
}

在/proc/pid/maps中的每一行都对应了进程中一段内存区域。主函数的代码如下:

int main(int argc, char *argv[])
...{   
    pid_t traced_process;
    struct user_regs_struct oldregs, regs;
    long ins;
    int len = 41;
    char insertcode[] =
        "/xeb/x15/x5e/xb8/x04/x00"
        "/x00/x00/xbb/x02/x00/x00/x00/x89/xf1/xba"
        "/x0c/x00/x00/x00/xcd/x80/xcc/xe8/xe6/xff"
        "/xff/xff/x48/x65/x6c/x6c/x6f/x20/x57/x6f"
        "/x72/x6c/x64/x0a/x00";
    char backup[len];
    long addr;
    if(argc != 2) ...{
        printf("Usage: %s <pid to be traced> ", 
               argv[0], argv[1]);
        exit(1);
    }
    traced_process = atoi(argv[1]);
    ptrace(PTRACE_ATTACH, traced_process, 
           NULL, NULL);
    wait(NULL);
    ptrace(PTRACE_GETREGS, traced_process, 
           NULL, &regs);
    addr = freespaceaddr(traced_process);
    getdata(traced_process, addr, backup, len);
    putdata(traced_process, addr, insertcode, len);
    memcpy(&oldregs, &regs, sizeof(regs));
    regs.eip = addr;
    ptrace(PTRACE_SETREGS, traced_process, 
           NULL, &regs);
    ptrace(PTRACE_CONT, traced_process, 
           NULL, NULL);
    wait(NULL);
    printf("The process stopped, Putting back "
           "the original instructions ");
    putdata(traced_process, addr, backup, len);
    ptrace(PTRACE_SETREGS, traced_process, 
           NULL, &oldregs);
    printf("Letting it continue with "
           "original flow ");
    ptrace(PTRACE_DETACH, traced_process, 
           NULL, NULL);
    return 0;
}

ptrace的幕后工作

那么,在使用ptrace的时候,内核里发生了声么呢?这里有一段简要的说明:

 

当一个进程调用了 ptrace( PTRACE_TRACEME, …)之后,内核为该进程设置了一个标记,注明该进程将被跟踪。内核中的相关原代码如下:

 

Source: arch/i386/kernel/ptrace.c
if (request == PTRACE_TRACEME) {
    /* are we already being traced? */
    if (current->ptrace & PT_PTRACED)
        goto out;
    /* set the ptrace bit in the process flags. */
    current->ptrace |= PT_PTRACED;
    ret = 0;
    goto out;
}

 

一次系统调用完成之后,内核察看那个标记,然后执行trace系统调用(如果这个进程正处于被跟踪状态的话)。其汇编的细节可以在 arh/i386/kernel/entry.S中找到。

 

现在让我们来看看这个sys_trace()函数(位于 arch/i386/kernel/ptrace.c )。它停止子进程,然后发送一个信号给父进程,告诉它子进程已经停滞,这个信号会激活正处于等待状态的父进程,让父进程进行相关处理。父进程在完成相关操作以后就调用ptrace( PTRACE_CONT, …)或者 ptrace( PTRACE_SYSCALL, …), 这将唤醒子进程,内核此时所作的是调用一个叫wake_up_process() 的进程调度函数。其他的一些系统架构可能会通过发送SIGCHLD给子进程来达到这个目的。

 

小结:

ptrace函数可能会让人们觉得很奇特,因为它居然可以检测和修改一个运行中的程序。这种技术主要是在调试器和系统调用跟踪程序中使用。它使程序员可以在用户级别做更多有意思的事情。已经有过很多在用户级别下扩展操作系统得尝试,比如UFO,一个用户级别的文件系统扩展,它使用ptrace来实现一些安全机制。

 

作者:

Pradeep Padala,

 p_padala@yahoo.com

http://www.cise.ufl.edu/~ppadala

 


康耐视VisionPro必学技巧:用CogCopyRegionTool实现图像拼接与局部替换 本文深入探讨了康耐视VisionPro中CogCopyRegionTool的高级应用,重点解析如何利用其精确的像素级复制与坐标对齐功能,实现工业视觉中的多相机图像拼接与印刷品局部替换。通过实战案例与代码示例,详细指导了从坐标标定、画布创建到顺序复制的完整流程,并分享了性能优化与常见避坑指南,帮助工程师高效解决复杂图像合成难题。 阅读详情

相关推荐

编译CycloneDDS和CycloneDDS-CXX踩过的坑——CMake Error at CMakeLists.txt:227 (find_package):

最近编译CycloneDDS和CycloneDDS-CXX踩了两个坑,花了不少时间。做个简单的记录,免得以后又踩到。注意:CycloneDDS-CXX编译依赖CycloneDDS,因此必须先编译CycloneDDS需要严格按照步骤进行,否则要入坑步骤如下,1先编译CycloneDDS以上步骤完成CycloneDDS的编译和安装,生成的bin include lib等位于install目录下面。

usstmiracle的博客 1900

ptrace系统调用的实现

最近遇到这样一个问题,机器跑着跑着画面冻结了,打开top看到Xorg的cpu占用率100%。想用gdb挂上去看一下,结果gdb一直卡着挂不上去。后来又换用perf分析,结果发现进程99%的时间花在了一个ioctl调用。这个ioctl操作的是nvidia显卡,进程实际上是卡在了nvidia的驱动中。 我对gdb挂不上去这件事感到很好奇,之前除了因为进程已经被另一个gdb调试而导致gdb挂不上去之外,...

imred的专栏 3110

商店销售预测(回归&随机森林)

通过准备线性回归的数据,我们发现了一些有趣的见解,包括周末的销售增长,公共部门支付工资时的销售增长,以及11月和12月的销售增长。如果我们选择包括这些,我们可能会得到更好的结果,但在这个时候,我们不会用它来做任何预测,而是将转向另一种可能给我们更好的结果的技术。在Kaggle竞赛中,要求我们应用时间序列预测,根据厄瓜多尔大型杂货零售商Corporación Favorita的数据预测商店销售情况,建立一个模型,准确地预测在不同商店销售的商品的单位销量。在快速查看我们的训练数据集之后,我们可以看到有很多零。

qq_45791012的博客 4751

ptrace

任何发给子进程的信号 signal(SIGKILL 除外)将导致子进程暂停运行,而它的父进程会通过 wait() 获得通知。

lyndon 1367

手把手教你用CODESYS将旧笔记本改造成软PLC(含证书配置避坑指南)

本文提供了一份详尽的指南,教你如何利用CODESYS平台将闲置旧笔记本改造为一台功能完整的软PLC。内容涵盖从硬件评估、系统实时性优化、软件安装与驱动配置,到关键的证书授权管理避坑指南,旨在帮助自动化工程师和爱好者低成本搭建稳定可靠的学习与开发平台。

weixin_29190573的博客 280

保姆级教程:用ArcGIS Pro搞定云南30米分辨率DEM地形图(附数据下载与配色方案)

本文提供了一份详细的ArcGIS Pro教程,指导用户如何制作云南30米分辨率DEM地形图。从数据下载、预处理到镶嵌与质量控制,再到地形分析与可视化,全流程覆盖云南复杂地形的处理要点。特别包含数据下载链接、配色方案及常见问题解决方案,适合地理信息分析新手和专业人士。

weixin_30467199的博客 309

Linux源码分析之Ptrace

本文摘自互联网,如有侵权,请联系我。一、函数说明1.函数使用说明名字ptrace – 进程跟踪形式#include <sys/ptrace.h> int ptrace(int request, int pid, int addr, int data); 描述Ptrace 提供了一种父进程可以控制子进程运行,并可以检查和改变它的核心image。它主要用于实现断点调试。一个被跟踪的进程运行中,直到发生

七月冷雨 8599

从Wi-Fi到蓝牙:手把手教你用Cadence Virtuoso搭建一个2.4GHz锁相环频率综合器(含PFD/CP/VCO模块设计)

本文详细介绍了如何在Cadence Virtuoso中设计一个2.4GHz锁相环频率综合器(PLL),涵盖从系统架构到模块级设计的全流程。重点解析了PFD、CP和VCO等核心模块的设计技巧与仿真验证方法,帮助模拟集成电路设计师掌握高频PLL的实现要点,满足Wi-Fi和蓝牙等无线通信标准的要求。

weixin_30315723的博客 418

使用PTRACE_TRACEME反调试的原理

介绍和演示使用(PTRACE_TRACEME, 0, NULL, NULL)进行反调试的底层原理

aka_yoo的博客 865

2024高教社杯数学建模国赛B题丨国一原创论文解析及源码超详细分享!

继续分享一篇2024国赛B题的国奖论文,包含可运行源代码jupyter,国赛B题通常比较聚焦实际复杂系统的多目标优化决策,主要偏重算法实现与概率建模解决开放性的管理问题。而且高度开放,无标准答案,学科交叉复杂,如资源调度、交通优化、海洋探测等。比较建议有一定统计学基础的同学参加。

ihui永不放弃 6740

CD-SSB和NCD-SSB相关内容

NR中,PSS/SSS 和PBCH总是绑定的,因此也称为SSB block。频域由下往上,第121个SC(k = 120)的中心频率,就是SSB的GSCN对应的SSREF(同步参考频率)的出处如上,同步栅格映射到SSB 的RE位置是10个PRB的位置,然后指向RE index 0,即第121个子载波的中心频率;UE获得N_offset_GSCN后,即可结合当前SSB的GSCN推算下一个SSB的GSCN =N_Reference_GSCN(当前SSB的GSCN) + N_offset_GSCN。

asd199086的博客 3433

PTRACE_TRACEME 与反调试

是 Linux 的经典反调试手段,因为系统限制调试是独占的,一个进程只能有一个 debugger。静默跟踪:父进程可通过 PTRACE_SEIZE(非侵入式跟踪)或直接忽略跟踪事件,避免触发信号暂停,使子进程看似未被调试。即使父进程不进行任何实际跟踪操作,该插槽已被占用,导致外部调试器无法通过常规手段附加。利用时间差:在子进程调用 PTRACE_TRACEME 前,父进程或外部程序能快速附加调试器,仍可拦截子进程。设置标记不代表子进程立刻就会被中断,必须收到停止信号时才会被父进程捕获。

dilvx的博客 1717

UCIE Specification详解(三)

Protocol Layer(协议层)以及Die-to-Die Adapter

Crazzy_M的博客 1768

玩转ptrace(二) [转]

code:http://ftp.ssc.com/pub/lj/listings/issue104/6210.tgz 英文原文http://www.linuxjournal.com/article/6210-------------------------------------------------------------------------------------------------

scancsdn的专栏 422

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

【转】玩转ptrace(二)

【转】玩转ptrace(二)

code09的专栏 929

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Playing with ptrace, Part II — 玩转ptrace(二)

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34004750的博客 162

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

[转] Playing with ptrace, Part II — 玩转ptrace(二)

Playing with ptrace, Part IIby Pradeep Padala p_padala@yahoo.com http://www.cise.ufl.edu/~ppadalaCreated 2002-11-01 02:00 翻译: Magic.D E-mail: adamgic@163.com 在第一部分中我们已经看到ptrace怎么获取子进程的系统调用以及改变系统调用的参数。...

weixin_30814319的博客 316

[转] Playing with ptrace, Part I…

Playing with ptrace, Part II by Pradeep Padala p_padala@yahoo.com http://www.cise.ufl.edu/~ppadala Created 2002-11-01 02:00 翻译: Magic.D E-mail: adamgic@163.com 在第一部分中我们已经看到ptrace怎么获取子进程的系统调用以及改变系统

eltaera的专栏 561

linux ptrace 图文详解(二) PTRACE_TRACEME 跟踪程序

本文介绍了gdb加载被调试程序进行调试运行的底层实现原理:PTRACE_TRACEME 的实现细节。

h_b__k的博客 1816

玩转ptrace(一)

by Pradeep PadalaCreated 2002-11-01 02:00翻译: Magic.D E-mail: adamgic@163.com译者序:在开发Hust Online Judge的过程中,查阅了不少资料,关于调试器技术的资料在网上是很少,即便是UNIX编程巨著《UNIX环境高级编程》中,相关内容也不多,直到我在http://www.linuxjournal.c

5839

玩转ptrace

原文地址:http://www.cnblogs.com/catch/p/3476280.html点击打开链接 二点击打开链接 [译] 玩转ptrace (一) [本文翻译自这里: http://www.linuxjournal.com/article/6100?page=0,0,作者:Pradeep Padaia]   你是否曾经想过怎样才能拦截系统调用?你是否曾经想过通过修改一

yang_chen_shi_wo的博客 373

linux ptrace反调试之抢占ptrace

ptrace和debugger原理 ptrace ptrace可以让一个进程监视和控制另一个进程的执行,并且修改被监视进程的内存、寄存器等,主要应用于断点调试和系统调用跟踪. 函数原型: long ptrace(int request, pid_t pid, void * addr, void * data) 其中,request代表请求类型,pid代表被调试进程的pid. 部分...

whatday的专栏 1821

ptrace的使用流程

参考链接: https://blog.youkuaiyun.com/imred/article/details/90141080 一、tracer和tracee的跟踪状态建立 两种方式:一种情况是tracer是tracee的父进程,进程tracee主动调用PTRACE_TRACEME.另外一种是进程tracer调用PTRACE_ATTACH或者或PTRACE_SEIZE。 处理PTRACE_ATTACH请求...

海棠花的博客 3705
上一篇: 玩转ptrace(一)
下一篇: Ubuntu 10.04 下ssh,ftp,tftp服务配置
小文兄弟
博客等级 码龄17年 28粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值