⬢ DragonFlyBSD Kernel Audit
DF-3398 / kscan.c
← back to finding ↓ download raw
/* 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;
}