在ubuntu中使用PTRACE_PEEKDATA进行ptrace

时间:2016-11-01 07:18:11

标签: ubuntu ptrace

我使用ubuntu 16.04 64bit来练习ptrace。当我使用PTRACE_PEEKDATA时,我很困惑。

子进程执行“ls”,我希望将字符串传递给SYS_write。 我在RCX,RDX和PTARECE_PEEKUSER中获得字符串地址和长度。 但是,当我使用PTRACE_PEEKDATA获取字符串时,结果是错误的。

这是结果:

mmmmar@acer:$ ls
ptrace  ptrace_1.c  ptrace2  ptrace_2.c  ptrace3  ptrace_3.C  ptrace4  ptrace_4.C
mmmmar@acer:$ ./ptrace4
make write call params 81, 140258879076880, 81
get str: H=���s1�H����
ptrace  ptrace_1.c  ptrace2  ptrace_2.c  ptrace3  ptrace_3.C  ptrace4  ptrace_4.C

这是我的代码(它运行在64位ubuntu上):

#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/reg.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define LONG_SIZE 8

void getdata(pid_t child,long addr,char *str,long len)
{
    char *laddr = str;
    int i = 0, j = len/LONG_SIZE;
    union u{
        long int val;
        char chars[LONG_SIZE];
    }data;
    while(i<j)
    {
        data.val = ptrace(PTRACE_PEEKDATA,child,addr + i*LONG_SIZE,NULL);
        memcpy(laddr,data.chars,LONG_SIZE);
        laddr += LONG_SIZE;
        ++i;
    }
    j = len % LONG_SIZE;
    if(j != 0)
    {
        data.val = ptrace(PTRACE_PEEKDATA,child,addr + i*LONG_SIZE,NULL);
        memcpy(laddr,data.chars,j);
    }
}

int main()
{
    pid_t child;
    child = fork();
    if(child == 0)
    {
        ptrace(PTRACE_TRACEME,0,NULL,NULL);
        execl("/bin/ls","ls",NULL);
    }
    else
    {
        long orig_rax = 0;
        long params[3] = {0};
        int status = 0;
        char *str;
        int toggle = 0;
        while(1)
        {
            wait(&status);
            if(WIFEXITED(status))
                break;
            orig_rax = ptrace(PTRACE_PEEKUSER,child,8*ORIG_RAX,NULL);
            if(orig_rax == SYS_write)
            {
                if(toggle == 0)
                {
                    toggle = 1;
                    params[0] = ptrace(PTRACE_PEEKUSER,child,8*RBX,NULL);
                    params[1] = ptrace(PTRACE_PEEKUSER,child,8*RCX,NULL);
                    params[2] = ptrace(PTRACE_PEEKUSER,child,8*RDX,NULL);
                    printf("make write call params %ld, %ld, %ld\n",params[0],params[1],params[2]);
                    str = (char*)malloc(params[2]+1);
                    memset(str,0,params[2]+1);
                    getdata(child,params[1],str,params[2]);
                    printf("get str: %s\n",str);
                    free(str);
                }
                else
                {
                    toggle = 0;
                }
            }
            ptrace(PTRACE_SYSCALL,child,NULL,NULL);
        }
    }
    return 0;
}

0 个答案:

没有答案