【问题标题】:reading and writing on memory process on linuxlinux上内存进程的读写
【发布时间】:2019-04-08 17:36:44
【问题描述】:

我写了一个小程序来读写进程的内存,但我不明白为什么它不起作用。 这是我的代码:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/ptrace.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>


int main()
{
pid_t pid=3169;
char mem_file_name[2048];
 int mem_fd;
 int offset=0;
 char buf[1005128];

sprintf(mem_file_name, "/proc/%d/mem", pid);
mem_fd = open(mem_file_name, O_RDWR,S_IRWXU);
printf("1 %s\n",strerror(errno));
ptrace(PTRACE_ATTACH, pid, NULL, NULL);
printf("2 %s\n",strerror(errno));
waitpid(pid, NULL, 0);
printf("3 %s\n",strerror(errno));
lseek(mem_fd, offset, SEEK_SET);
printf("4 %s\n",strerror(errno));
read(mem_fd, buf, _SC_PAGE_SIZE);
printf("5 %s\n",strerror(errno));
ptrace(PTRACE_DETACH, pid, NULL, NULL);
printf("6 %s\n",strerror(errno));
printf("%s\n",buf );
}

这是我的输出:

1 Success
2 Success
3 Success
4 Success
5 Input/output error
6 Input/output error

我用

编译
gcc -Wall -Wextra main.c

我以 root 权限运行

sudo ./a.out

在此示例中,我仅尝试从进程中读取,但它不起作用。 我的想法是dump一个进程的内存,但是不知道为什么读不出来。

ps 我知道有一些工具可以转储进程的内存,但是我想创建一个小程序来练习。

【问题讨论】:

  • 首先,对于大多数系统调用,errno 的值是 undefined,除非之前的函数确实失败了。当他们失败时,他们会用一个特定的返回值(通常是-1)来指示它,你不能使用errno来检查一个函数是否失败,因为它的值是(如上所述)undefined .您需要阅读您使用的函数的文档(如the manual pages)。

标签: c memory process operating-system


【解决方案1】:

您的代码有几个问题。

您的主要问题是您尝试从偏移量 0 读取,这是未映射到您的进程的进程地址 0x00000000。

int offset=0;
...
lseek(mem_fd, offset, SEEK_SET);

这就像在地址零处从你的记忆中读取:

int offset=0;
char* p = 0x0;
printf("%d data",p[offset]);

您只能通过 /proc/PID/mem 在您的进程中有效和映射地址的偏移处读取内存。

例如,如果你想通过这个 API 读取你 buf 变量的内存,你可以通过寻找它的地址来读取它:

lseek(mem_fd, (off_t)buf, SEEK_SET); /* note that on 64 bit you need to use lseek64 and off64_t */
read(mem_fd, buf, _SC_PAGE_SIZE); /* this should work */

注意事项:

【讨论】:

  • 谢谢你的回答,但输出是一样的,所以它似乎不起作用。通过将偏移量设置为 0,我打算从进程开始读取。我认为这是正确的,因为手册中的“lseek() 函数重新定位了与文件描述符 fd 关联的打开文件的偏移量”
  • dario,请记住/proc/PID/mem 不是常规文件!就像您的进程的内存空间中没有连续的数据流一样。这是一个将内存作为文件类对象读取的接口,但底层机制并没有真正改变。如果你的意思是“进程的开始”映射到你的进程空间的最低地址,那么你需要找出它是什么(我建议查看/proc/PID/maps)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-10
  • 2012-08-13
相关资源
最近更新 更多