/* readmem.c dumps the virtual memory of a linux process using ptrace+/dev/pid/mem (c) 2007 Y. Guillot distributed under the terms of the WtfPLv2 */ // define this to dump to separate files (gcc -DSEPARATE_DUMP_FILES) //#define SEPARATE_DUMP_FILES #ifdef TARGET_64 // for 64bit target (see /proc/cpuinfo addr size virtual) #define MEM_MAX (1ULL << 48) #else #define MEM_MAX (1ULL << 32) #endif #define _LARGEFILE64_SOURCE #include #include #include #include #include #include #include #include #include int main(int argc, char **argv) { if (argc < 2) { printf("usage: readmem \n"); exit(1); } char buf[128]; int pid = atoi(argv[1]); snprintf(buf, sizeof(buf), "/proc/%d/mem", pid); int fd = open(buf, O_RDONLY); if (fd == -1) { fprintf(stderr, "open failed: %m\n"); exit(1); } int fdo = -1; #ifndef SEPARATE_DUMP_FILES snprintf(buf, sizeof(buf), "memdump_%d", pid); fdo = open(buf, O_WRONLY | O_CREAT, 0644); if (fdo == -1) { fprintf(stderr, "open2 failed: %m\n"); close(fd); exit(1); } #endif long ptret = ptrace(PTRACE_ATTACH, pid, 0, 0); if (ptret == -1) { fprintf(stderr, "ptrace failed: %s\n", strerror(errno)); close(fdo); close(fd); exit(1); } unsigned char page[4096]; unsigned long long offset = 0; #ifdef SEPARATE_DUMP_FILES unsigned long long lastoff = -1; #endif while (offset < MEM_MAX) { lseek64(fd, offset, SEEK_SET); ssize_t ret; ret = read(fd, page, sizeof(page)); if (ret >= 0) fprintf(stderr, "got page at %llx\n", offset); else if (!(offset & 0xfffffff)) fprintf(stderr, "fail %llx\r", offset); if (ret > 0) { #ifdef SEPARATE_DUMP_FILES if (offset != lastoff + sizeof(page)) { if (fdo != -1) close(fdo); snprintf(buf, sizeof(buf), "memdump_%d_%08llx", pid, offset); fdo = open(buf, O_WRONLY | O_CREAT, 0644); if (fdo == -1) { fprintf(stderr, "open failed: %m\n"); ptrace(PTRACE_DETACH, pid, 0, 0); close(fd); exit(1); } } lastoff = offset; #endif write(fdo, page, sizeof(page)); } offset += sizeof(page); } ptrace(PTRACE_DETACH, pid, 0, 0); close(fdo); close(fd); return 0; }