首页 > 技术文章 > ptrace 人人小站 - http://zhan.renren.com/tag?value=ptrace

robbychan 2013-09-08 18:42 原文

学了一周的ptrace,很多细节没有研究到。勉强交个自己打及格分的报告吧。希望高手轻喷~

    Ptracelinux提供的系统函数。具体可以在子进程处设置断点。当子进程到达断点时,暂停并通知父进程。此时,父进程可以看到子进程所有内存状态。并且可以直接获取或者修改寄存器等数据。甚至可以插入代码到子进程中。

    网上有很多利用ptrace漏洞的。大概思路是说,可以调试超级权限的进程,插入代码到其中,使普通用户具备超级权限。具体感兴趣的同学可以上网学习。

    插入代码有两个思路。一个思路是,直接将代码指令插入到子进程eip指向的内存空间。这里需要注意的是,peektextpoketext都是以4个字节为单位,对内存进行读写。所以,如果需要对原来的代码段指令进行备份,应该以4个字节为单位进行备份。不然,可能会在代码中出现乱码。这些乱码对应的指令代码可能会访问没有权限的位置。就会出现段错误。

    另一个思路是,将代码指令插入到子进程对应的自由空间中。并且将eip设置到对应的位置,使子进程可以执行替代后的指令。进程被分配的空间,可以在/proc/pid/maps文件里面看到。这里需要注意,如果插入指令,最好找代码段,并且对源代码进行备份。我看到一份资料里面,作者将指令插入到bss段里面,然后将eip设为bss段的起始位置。因为bss段可读可写不可执行,当指令执行到这个线性地址空间,当然因为访问权限不够出现段错误。

下面是一些参数和基本用法。

PTRACE_ME

ptrace(PTRACE_ME,0,0,0)

子进程进入调试模式。

 

PTRACE_CONT

ptrace(PTRACE_CONT,pid,0,0)

让子进程继续执行,子进程不再进入调试模式。

 

PTRACE_SYSCALL

ptrace(PTRACE_SYSCALL,pid,0,0)

1、进入系统功能调用之前

2、退出系统功能调用之后

3、子进程结束

PTRACE_SINGLESTEP

Ptrace(PTRACE_SINGLESTEP,pid,0,0)

子进程单步执行

PTRACE_ATTACH

ptrace(PTRACE_ATTACH,pid,0,0)

设置子进程为调试模式。

具体:设置pid对应的子进程为当前进程的子进程。设置子进程为调试模式。

 

PTRACE_DETACH

解除子进程的调试

 

PTRACE_PEEKTEXT

PTRACE_POKETEXT

long  ptrace(PTRACE_PEEKTEXT, int pid , long offset , 0);

从代码段的offset处取得数据。数据大小是4个字节。

ptrace(PTRACE_POKETEXT, int pid , long offset , long data);

将数据data写入到代码段的offset处。数据大小是4个字节。

 

PTRACE_PEEKDATA

PTRACE_POKEDATA

long  ptrace(PTRACE_PEEKDATA, int pid , long offset , 0);

从数据段的offset处取得数据。数据大小是4个字节。

ptrace(PTRACE_POKEDATA, int pid , long offset , long data);

将数据data写入到数据段的offset处。数据大小是4个字节。

 

 

PTRACE_PEEKUSER

PTRACE_POKEUSER

从用户区域取得数据,返回值在offset处取4个字节

long reg = ptrace(PTRACE_PEEKUSER , int pid , long offset  ,NULL);

将数据写入到user区。写入的是4个字节。

ptrace(PTRACE_POKEUSER, int pid , long offset , long data);

其中,data是写入的long型数据。

Offset/4可以取EAX(如下)等。

#define EBX 0

#define ECX 1

#define EDX 2

#define ESI 3

#define EDI 4

#define EBP 5

#define EAX 6

#define DS 7

#define ES 8

#define FS 9

#define GS 10

#define ORIG_EAX 11

#define EIP 12

#define CS  13

#define EFL 14

#define UESP 15

#define SS   16

用户区的结构体:

struct user32 {

  struct user_regs_struct32 regs; /* Where the registers are actually stored */

  int u_fpvalid;            /* True if math co-processor being used. */

                            /* for this mess. Not yet used. */

  struct user_i387_ia32_struct i387;      /* Math Co-processor registers. */

/* The rest of this junk is to help gdb figure out what goes where */

  __u32 u_tsize;  /* Text segment size (pages). */

  __u32 u_dsize; /* Data segment size (pages). */

  __u32 u_ssize; /* Stack segment size (pages). */

  __u32 start_code;     /* Starting virtual address of text. */

  __u32 start_stack;  /* Starting virtual address of stack area.

                               This is actually the bottom of the stack,

                               the top of the stack is always found in the

                               esp register.  */

  __u32 signal;              /* Signal that caused the core dump. */

  int reserved;                   /* No __u32er used */

  __u32 u_ar0;   /* Used by gdb to help find the values for */

                            /* the registers. */

  __u32 u_fpstate;     /* Math Co-processor pointer. */

  __u32 magic;          /* To uniquely identify a core file */

  char u_comm[32];          /* User command that was responsible */

  int u_debugreg[8];

};

 

 

 

PTRACE_GETREGS

PTRACE_SETREGS

取得寄存器的值

struct user_regs_struct regs

ptrace(PTRACE_GETREGS , int pid , NULL , & regs);

设置寄存器的值

struct user_regs_struct regs

ptrace(PTRACE_SETREGS , int pid , NULL , & regs);

 

struct user_regs_struct {

       unsigned long      bx;

       unsigned long      cx;

       unsigned long      dx;

       unsigned long      si;

       unsigned long      di;

       unsigned long      bp;

       unsigned long      ax;

       unsigned long      ds;

       unsigned long      es;

       unsigned long      fs;

       unsigned long      gs;

       unsigned long      orig_ax;

       unsigned long      ip;

       unsigned long      cs;

       unsigned long      flags;

       unsigned long      sp;

       unsigned long      ss;

};

PTRACE_GETFPREGS,

PTRACE_SETFPREGS


推荐阅读