質問: linuxで/ proc / $ pid / memから読み取るにはどうすればよいですか? linux proc(5) manページ は、/proc/$pid/mem「プロセスのメモリのページにアクセスするために使用できます」。しかし、それを使用する簡単な試みは私に与えるだけです$ cat /proc/$$/mem /proc/self/mem cat: /proc/3065/mem: no such process cat: /proc/self/mem: input/output error 自分のメモリを印刷できないcatができないのはなぜですか(/proc/self/mem)?そして、シェルのメモリ(/proc/$$/mem、明らかにプロセスが存在します)?どのようにして/proc/$pid/mem、それで?
回答: ここに私がcで書いた小さなプログラムがあります:使用法:memdump <pid> memdump <pid> <ip-address> <port> プログラムは、/ proc/$ pid/mapsを使用してプロセスのすべてのマップされたメモリ領域を検索し、それらの領域を/ proc/$ pid/memから一度に1ページずつ読み取ります。これらのページは、標準出力またはipアドレスと指定したtcpポートに書き込まれます。コード(androidでテスト済み、スーパーユーザー権限が必要):#include <stdio.h> #include <stdlib.h> #include <limits.h> #include <sys/ptrace.h> #include <sys/socket.h> #include <arpa/inet.h> void dump_memory_region(file* pmemfile, unsigned long start_address, long length, int serversocket) { unsigned long address; int pagelength = 4096; unsigned char page[pagelength]; fseeko(pmemfile, start_address, seek_set); for (address=start_address; address < start_address + length; address += pagelength) { fread(&page, 1, pagelength, pmemfile); if (serversocket == -1) { // write to stdout fwrite(&page, 1, pagelength, stdout); } else { send(serversocket, &page, pagelength, 0); } } } int main(int argc, char **argv) { if (argc == 2 || argc == 4) { int pid = atoi(argv[1]); long ptraceresult = ptrace(ptrace_attach, pid, null, null); if (ptraceresult < 0) { printf("unable to attach to the pid specified\n"); return; } wait(null); char mapsfilename[1024]; sprintf(mapsfilename, "/proc/%s/maps", argv[1]); file* pmapsfile = fopen(mapsfilename, "r"); char memfilename[1024]; sprintf(memfilename, "/proc/%s/mem", argv[1]); file* pmemfile = fopen(memfilename, "r"); int serversocket = -1; if (argc == 4) { unsigned int port; int count = sscanf(argv[3], "%d", &port); if (count == 0) { printf("invalid port specified\n"); return; } serversocket = socket(af_inet, sock_stream, 0); if (serversocket == -1) { printf("could not create socket\n"); return; } struct sockaddr_in serversocketaddress; serversocketaddress.sin_addr.s_addr = inet_addr(argv[2]); serversocketaddress.sin_family = af_inet; serversocketaddress.sin_port = htons(port); if (connect(serversocket, (struct sockaddr *) &serversocketaddress, sizeof(serversocketaddress)) < 0) { printf("could not connect to server\n"); return; } } char line[256]; while (fgets(line, 256, pmapsfile) != null) { unsigned long start_address; unsigned long end_address; sscanf(line, "%08lx-%08lx\n", &start_address, &end_address); dump_memory_region(pmemfile, start_address, end_address - start_address, serversocket); } fclose(pmapsfile); fclose(pmemfile); if (serversocket != -1) { close(serversocket); } ptrace(ptrace_cont, pid, null, null); ptrace(ptrace_detach, pid, null, null); } else { printf("%s <pid>\n", argv[0]); printf("%s <pid> <ip-address> <port>\n", argv[0]); exit(0); } }