DF-3398 / kpeek.c
/* kmem peek for DF-3398: resolve ip_fw3_nat_ctx -> cfg_nat -> alias, * dump bytes around alias end (the OOB write target). usage: kpeek <cpu> */ #include <sys/types.h> #include <sys/usched.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <stdint.h> #define ALIAS_RANGE 64511 #define OFF_ICMP_IN (24 + 2 * (ALIAS_RANGE * 8)) #define CFG_ALIAS_SZ (24 + 3 * (ALIAS_RANGE * 8)) static int fd; static int rd(uint64_t addr, void *buf, size_t n) { if (pread(fd, buf, n, (off_t)addr) != (ssize_t)n) return -1; return 0; } int main(int argc, char **argv) { int cpu = atoi(argv[1]); uint64_t ctxaddr, ctx, nat, alias, tgt; uint64_t v, i; unsigned char b[32]; fd = open("/dev/kmem", O_RDONLY); if (fd < 0) { perror("/dev/kmem"); return 1; } /* symbol address passed via argv[2] (from nm) */ ctxaddr = strtoull(argv[2], NULL, 16) + cpu * 8; if (rd(ctxaddr, &ctx, 8)) { perror("read ctx ptr"); return 1; } printf("nat_ctx[%d] = 0x%llx\n", cpu, (unsigned long long)ctx); if (rd(ctx, &nat, 8)) { perror("read nats"); return 1; } printf("nats[0] (cfg_nat) = 0x%llx\n", (unsigned long long)nat); if (rd(nat + 8, &alias, 8)) { perror("read alias list"); return 1; } printf("alias LIST_FIRST = 0x%llx\n", (unsigned long long)alias); printf("alias size = %d (0x%x), page-aligned: %s\n", CFG_ALIAS_SZ, CFG_ALIAS_SZ, (CFG_ALIAS_SZ % 4096 == 0) ? "yes" : "no"); /* dump alias head: next, ip, first tcp_in slots */ for (i = 0; i < 4; i++) { rd(alias + i * 8, &v, 8); printf("alias+%-4lld = 0x%016llx\n", (long long)i * 8, (unsigned long long)v); } /* the OOB target for idx=64512: alias + OFF_ICMP_IN + 8*64512 */ tgt = alias + OFF_ICMP_IN + 8ULL * 64512; printf("target(idx=64512) = alias + 0x%llx = 0x%llx\n", (unsigned long long)(OFF_ICMP_IN + 8ULL * 64512), (unsigned long long)tgt); if (rd(tgt, b, 16) == 0) { int j; printf("bytes @target:"); for (j = 0; j < 16; j++) printf(" %02x", b[j]); printf("\n"); memcpy(&v, b, 8); printf("qword @target = 0x%016llx\n", (unsigned long long)v); } else { printf("read @target FAILED (unmapped?)\n"); } return 0; } |