/* SPDX-License-Identifier: BSD-3-Clause */ /* Copyright (c) 2026 Open-IOV contributors */ /* scan3.c - scan all writable memory of a process for qwords equal to any of the given 64-bit needles; print every hit address. usage: scan3 PID 0xNEEDLE [0xNEEDLE ...] */ #define _GNU_SOURCE #include #include #include #include #include #include #define MAXR 4096 #define MAXN 64 static struct { uint64_t lo, hi; } wr[MAXR]; static int nwr; static uint64_t needle[MAXN]; static int nn; static void load_maps(int pid) { char path[64], line[1024]; snprintf(path, sizeof path, "/proc/%d/maps", pid); FILE *f = fopen(path, "r"); if (!f) { perror("maps"); exit(1); } while (fgets(line, sizeof line, f)) { uint64_t lo, hi; char perms[16]; if (sscanf(line, "%lx-%lx %15s", &lo, &hi, perms) < 3) continue; if (strchr(perms, 'w') && nwr < MAXR) { wr[nwr].lo = lo; wr[nwr].hi = hi; nwr++; } } fclose(f); } int main(int argc, char **argv) { if (argc < 3) { fprintf(stderr, "usage: scan3 PID 0xNEEDLE [...]\n"); return 1; } int pid = atoi(argv[1]); for (int i = 2; i < argc && nn < MAXN; i++) needle[nn++] = strtoull(argv[i], 0, 16); load_maps(pid); printf("writable=%d needles=%d\n", nwr, nn); char mp[64]; snprintf(mp, sizeof mp, "/proc/%d/mem", pid); int fd = open(mp, O_RDONLY); if (fd < 0) { perror("mem"); return 1; } size_t CH = 4 << 20; uint8_t *buf = malloc(CH + 64); int hits = 0; for (int r = 0; r < nwr; r++) { uint64_t a = wr[r].lo; while (a < wr[r].hi) { size_t n = (size_t)((wr[r].hi - a) < CH ? (wr[r].hi - a) : CH); ssize_t got = pread(fd, buf, n, (off_t)a); if (got <= 0) { if (n > (256u << 10)) { n = 256u << 10; continue; } a += 4096; continue; } if ((size_t)got < n) n = got; n -= n % 8; uint64_t *w = (uint64_t *)buf; for (size_t i = 0; i < n / 8; i++) { uint64_t v = w[i]; for (int k = 0; k < nn; k++) { if (v == needle[k]) { printf("hit 0x%lx = 0x%lx\n", a + i * 8, v); hits++; } } } a += n; } } printf("hits=%d\n", hits); return 0; }