【问题标题】:Read strings with ptrace (linux)使用 ptrace (linux) 读取字符串
【发布时间】:2016-03-26 02:48:21
【问题描述】:

我是堆栈新手,对 C 语言相对较新。我尝试使用 ptrace 从另一个进程读取进程内存。到目前为止,我设法从另一个进程读取和更改数字。但是用字符串我找不到办法。这是我的代码:

int errno;
//the string we want to read is 8 bytes long
long len = 8;
const int buflen = (len / sizeof(long)) + 1;
void *buffer;
long *base;
char *data;
int i;
//the process pid i want to track
pid_t pid = 2984;
//the address that the string we want to read resides 
void *addr = (unsigned long int*) 0x7ffe03f6e088 ;

buffer = calloc(buflen, sizeof(long));
if (NULL == buffer)
{
    perror("Fault at allocation: ");    
}

base = (long *) buffer; 

ptrace(PTRACE_ATTACH, pid, NULL, NULL);

for (i = 0; i < buflen; i++) {
    if(ptrace(PTRACE_PEEKDATA, pid , addr + (sizeof(long) * i),NULL) !=  -1)
    {
    *(base + i) = ptrace(PTRACE_PEEKDATA, pid , addr + (sizeof(long) * i),
                     NULL);
    }else
    {
        fprintf(stderr, "Value of errno: %s\n", strerror(errno));
    }
}

ptrace(PTRACE_DETACH, pid, NULL, NULL);

/* Pop a null at the end, since we're printing this string. */
*((char *) buffer + len) = '\0';

data = (char *)buffer;  

printf("%p[\"%s\"]\n",addr, data);
free(buffer);

还有输出:

errno 的值:没有这样的过程
errno 的值:没有这个过程
0x7ffe03f6e088[""]

但是,当 addr 指向一个数字时,进程 ID 是正确的,并且类似的代码可以工作。请帮帮我。

[编辑]
下面是tracee进程代码:

char *a = "lala";
pid_t child;
printf("Char length: %ld\n", strlen(a));
printf("Char value: %s\n", a);
//the address I use to read variable
printf("Char address: %p\n", &a);
//make the process sleep so I can halt it manually
sleep(3);

【问题讨论】:

  • 你确定 PID 是正确的,因为当你重启一个程序时,一个 PID 不能保证是一样的。
  • 是的,我确定是因为我在运行跟踪器进程之前停止了目标进程......所以仅出于测试目的,我硬编码了 PID 号和停止进程的字符串地址。
  • ptrace(PTRACE_ATTACH, pid, NULL, NULL);的返回值是多少?
  • 抱歉耽搁了……@MarkPlotnick ptrace(PTRACE_ATTACH, pid, NULL, NULL) 的结果是-1。然而,在不更改代码的情况下重试后,仅跟踪进程及其硬编码的 PID 和地址我得到结果:0x7fff1d224748["�@"]。 ptrace(PTRACE_ATTACH, pid, NULL, NULL) 仍然是-1。
  • 这里有两个选择:(1) 让 tracee 打印 printf("Char address: %p\n", a); 并按原样运行您的跟踪代码 (2) 保留 tracee 代码并修改您的跟踪进程,使其读入来自目标的sizeof(char *) 字节,将结果(在适当的数字移位后,如果您需要使用多个 ptrace 请求将其全部读取)存储在addr 中,然后按原样继续。

标签: c linux ptrace


【解决方案1】:

您的跟踪进程正在打印 char* 指针本身的地址,而不是字符串开头的地址。

这里有两个选择:(1) 让 tracee 打印 printf("Char address: %p\n", a); 并按原样运行您的跟踪代码 (2) 保留 tracee 代码原样并修改您的跟踪进程,使其从 sizeof(char *) 字节中读取目标,将结果存储在addr 中(在适当的数字移位后,如果您需要使用多个 ptrace 请求来读取它),然后按原样继续。

——马克·普洛特尼克

【讨论】:

    【解决方案2】:

    手册页说:

    PTRACE_ATTACH 附加到pid中指定的进程,使其成为tracee 的调用过程。被跟踪者被发送一个 SIGSTOP,但是 不一定会因完成而停止 这个电话;使用 waitpid(2) 等待被跟踪者停止。 请参阅“附加和分离”小节了解 附加信息。 (地址和数据被忽略。)

    只需附加一个wait() 函数来等待孩子进入停止状态。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-14
      相关资源
      最近更新 更多