1 // scans process memory for a given string, prints offsets of occurences
2 // will ignore matches where the match is split over a mapping boundary
10 #include <sys/ptrace.h>
21 struct range *mappings;
22 size_t mappings_used = 0;
23 #define FOR_EACH_MAPPING FOR_EACH_IN_ARRAY(mappings, mappings_used, mapping)
25 bool is_mapped(void *addr) {
27 if (mapping->a <= addr && mapping->b > addr) return true;
31 int main(int argc, char **argv) {
33 if (argc != 3) xperror("invocation: anondump <pid> <searchstr>", 0);
34 TPRINTF(maps_path, "/proc/%s/maps", argv[1])
35 char *maps = CHK_PTR(slurp_file(maps_path, NULL, JH_SLURP_NO_STAT), "unable to read /proc/$pid/maps", 1);
39 size_t arglen = strlen(argv[2])*4;
40 for (int i=0; i<strlen(argv[2]); i++) {
41 argbuf[i*4] = argv[2][i];
47 if (ptrace(PTRACE_ATTACH, atoi(argv[1]), NULL, NULL)) {
48 fputs("warning: unable to ptrace\n", stderr);
53 TPRINTF(mem_path, "/proc/%s/mem", argv[1])
54 int memfd = fail_on_neg(open(mem_path, O_RDONLY), "unable to open /proc/$pid/mem", 1);
56 size_t n_mappings = count_char_occurences(maps, '\n');
57 mappings = CHK_PTR(calloc(n_mappings+1, sizeof(struct range)), "memory allocation failed", 1);
60 for (char *line = strtok(maps, "\n"); line != NULL; line = strtok(NULL, "\n")) {
61 struct range *mapping = &mappings[mappings_used++];
62 mapping->line = CHK_PTR(strdup(line), "memory allocation failed", 1);
63 if (sscanf(line, "%p-%p", &mapping->a, &mapping->b) != 2) xperror("sscanf failed", 0);
67 size_t len = mapping->b - mapping->a;
68 char *copy = CHK_PTR(malloc(len), "malloc failed", 1);
72 if ((read_res=pread(memfd, copy+read_done, len-read_done, (off_t)mapping->a-read_done)) != (ssize_t)len) {
74 fputs("warning: some read failed\n", stderr);
77 read_done += read_res;
82 char *ptr = memmem(copy + pos, len, argv[2], strlen(argv[2]));
83 if (ptr == NULL) break;
85 printf("at %p in %s\n", mapping->a + pos, mapping->line);