DF-3398 / kscan.c
/* DF-3398 kmem scanner: locate cfg_alias allocations by their alias-IP * signature (offset +8) and inspect the OOB write targets. * usage: kscan <start_hex> <end_hex> */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <stdint.h> #define ALIAS_RANGE 64511 #define CFG_ALIAS_SZ (24 + 3 * (ALIAS_RANGE * 8)) #define TGT_OFF (CFG_ALIAS_SZ + 8) /* idx=64512 write offset */ static int fd; int main(int argc, char **argv) { uint64_t start = strtoull(argv[1], NULL, 16); uint64_t end = strtoull(argv[2], NULL, 16); static unsigned char buf[1 << 20]; uint64_t a; int nfound = 0; fd = open("/dev/kmem", O_RDONLY); if (fd < 0) { perror("/dev/kmem"); return 1; } for (a = start; a < end; a += sizeof(buf)) { ssize_t n = pread(fd, buf, sizeof(buf), (off_t)a); uint64_t o; if (n <= 0) continue; for (o = 0; o + 16 <= (uint64_t)n; o += 8) { uint32_t w; memcpy(&w, buf + o + 8, 4); if (w == 0x0A00020F || w == 0x0A000210) { uint64_t alias = a + o; uint64_t t = alias + TGT_OFF; unsigned char q[16]; const char *which = (w == 0x0A00020F) ? "nat1(10.0.2.15)" : "nat2(10.0.2.16)"; uint64_t nxt; memcpy(&nxt, buf + o, 8); printf("alias @0x%llx %s next=0x%llx\n", (unsigned long long)alias, which, (unsigned long long)nxt); if (pread(fd, q, 16, (off_t)t) == 16) { uint64_t v; memcpy(&v, q, 8); printf(" +8-past-end qword = 0x%016llx %s\n", (unsigned long long)v, (v != 0) ? " <== NON-ZERO (OOB write landed)" : ""); } nfound++; } } } printf("scan done, %d alias candidates\n", nfound); return 0; } |