commit old stuff
[tools.git] / tools / strscan.c
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
3 #define _GNU_SOURCE
4 #include <unistd.h>
5 #include <stdio.h>
6 #include <assert.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <sys/wait.h>
10 #include <sys/ptrace.h>
11 #include <fcntl.h>
12 #include <jh.h>
13 #include <stdbool.h>
14 #include <string.h>
15
16 struct range {
17   void *a, *b;
18   char *line;
19 };
20
21 struct range *mappings;
22 size_t mappings_used = 0;
23 #define FOR_EACH_MAPPING FOR_EACH_IN_ARRAY(mappings, mappings_used, mapping)
24
25 bool is_mapped(void *addr) {
26   FOR_EACH_MAPPING
27     if (mapping->a <= addr && mapping->b > addr) return true;
28   return false;
29 }
30
31 int main(int argc, char **argv) {
32   // init
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);
36
37 /*
38   char argbuf[8192];
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];
42     argbuf[i*4+1] = 0;
43     argbuf[i*4+2] = 0;
44     argbuf[i*4+3] = 0;
45   }*/
46
47   if (ptrace(PTRACE_ATTACH, atoi(argv[1]), NULL, NULL)) {
48     fputs("warning: unable to ptrace\n", stderr);
49   } else {
50     wait(NULL);
51   }
52
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);
55
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);
58
59   // do magic
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);
64   }
65
66   FOR_EACH_MAPPING {
67     size_t len = mapping->b - mapping->a;
68     char *copy = CHK_PTR(malloc(len), "malloc failed", 1);
69     ssize_t read_res;
70     size_t read_done = 0;
71 read_more:;
72     if ((read_res=pread(memfd, copy+read_done, len-read_done, (off_t)mapping->a-read_done)) != (ssize_t)len) {
73       if (read_res <= 0) {
74         fputs("warning: some read failed\n", stderr);
75         continue;
76       }
77       read_done += read_res;
78       goto read_more;
79     }
80     size_t pos = 0;
81     while (1) {
82       char *ptr = memmem(copy + pos, len, argv[2], strlen(argv[2]));
83       if (ptr == NULL) break;
84       pos = ptr - copy;
85       printf("at %p in %s\n", mapping->a + pos, mapping->line);
86       pos++;
87     }
88     free(copy);
89   }
90
91   return 0;
92 }