⬢ DragonFlyBSD Kernel Audit
DF-3248 / memscan.c
← back to finding ↓ download raw
/*
 * DF-3248 memscan — locate cached HPFS dirblk chunks in physical memory.
 * Reports physical addresses of:
 *   D  : dirblk headers (d_magic 0x77E40AAE, d_freeoff 2048) at any alignment
 *   F  : forged-dirent pre-markers (C1*8 C2*4 C3*8)
 *   X2 : "XSTEP2" (root2 chunk: at chunk+131; tmpfs file copy: at file+1287)
 * Analysis (mod 2048 residues) separates buffer-cache chunks from the tmpfs
 * copy of the image file.
 */
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>

#define RAMSZ	3ULL*1024*1024*1024ULL
#define WIN	8ULL*1024*1024ULL

int
main(void)
{
	int fd = open("/dev/mem", O_RDONLY);
	unsigned char patF[20] = {
		0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,
		0xC2,0xC2,0xC2,0xC2,
		0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3
	};
	unsigned char patD[8] = { 0xAE,0x0A,0xE4,0x77, 0x00,0x08,0x00,0x00 };
	unsigned char patX2[6] = { 'X','S','T','E','P','2' };
	uint64_t off;

	if (fd < 0) { perror("/dev/mem"); return (1); }
	setvbuf(stdout, NULL, _IOLBF, 0);
	for (off = 0; off < RAMSZ; off += WIN) {
		uint64_t len = WIN + 65536;
		unsigned char *p, *q, *end;
		if (off + len > RAMSZ) len = RAMSZ - off;
		p = malloc(len);
		if (p == NULL)
			continue;
		{
			ssize_t n = pread(fd, p, len, (off_t)off);
			if (n <= 0) { free(p); continue; }
			if ((uint64_t)n < len) len = n;
		}
		end = p + len;
		q = p;
		while ((q = memmem(q, end - q, patF, sizeof(patF))) != NULL) {
			printf("F %08llx\n", (unsigned long long)(off + (q - p)));
			q += 128;
		}
		q = p;
		while ((q = memmem(q, end - q, patD, sizeof(patD))) != NULL) {
			printf("D %08llx\n", (unsigned long long)(off + (q - p)));
			q += 2048;
		}
		q = p;
		while ((q = memmem(q, end - q, patX2, sizeof(patX2))) != NULL) {
			printf("X2 %08llx\n", (unsigned long long)(off + (q - p)));
			q += 8;
		}
		free(p);
	}
	printf("SCAN_DONE\n");
	return (0);
}