DF-0822 / dump_volhdr.c
/* DF-0822 helper: dump HAMMER2 volume header fields relevant to the exploit. */ #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <fcntl.h> #include <unistd.h> struct volhdr { uint8_t raw[65536]; }; /* offsets from hammer2_disk.h hammer2_volume_data */ #define OFF_magic 0x0000 #define OFF_allocator_size 0x0060 #define OFF_allocator_free 0x0068 #define OFF_allocator_beg 0x0070 #define OFF_mirror_tid 0x0078 #define OFF_freemap_tid 0x0090 #define OFF_bulkfree_tid 0x0098 #define OFF_icrc_sects 0x01E0 /* [8] uint32 */ #define OFF_sroot_blockset 0x0200 /* 512 bytes, 4 blockrefs x 128 */ #define OFF_icrc_volheader 0xFFFC /* blockref field offsets (struct is 128 bytes) */ #define BR_type 0 #define BR_methods 1 #define BR_key 16 /* uint64 */ #define BR_mirror_tid 24 /* uint64 */ #define BR_modify_tid 32 #define BR_data_off 40 /* uint64, low 6 bits = radix */ #define BR_update_tid 48 #define BR_check_value 56 /* iscsi32.value uint32 (first 4 of check union) */ int main(int argc, char **argv) { const char *path = argc > 1 ? argv[1] : "/tmp/h2.img"; int fd = open(path, O_RDONLY); if (fd < 0) { perror("open"); return 1; } uint8_t buf[65536]; /* volume headers are at reserved offsets; scan for magic */ uint64_t magic = 0x48414d3205172011ULL; off_t vhoff = -1; for (off_t o = 0; o + 8 <= 65536 * 4; o += 65536) { if (lseek(fd, o, SEEK_SET) < 0) break; uint64_t m; if (read(fd, &m, 8) != 8) break; if (m == magic) { vhoff = o; break; } } if (vhoff < 0) { /* try sector-aligned scan within first 4MB */ for (off_t o = 0; o + 65536 <= 4*1024*1024; o += 512) { lseek(fd, o, SEEK_SET); uint64_t m; if (read(fd, &m, 8) == 8 && m == magic) { vhoff = o; break; } } } if (vhoff < 0) { fprintf(stderr, "magic not found\n"); return 2; } printf("VOLHDR at file offset 0x%llx\n", (unsigned long long)vhoff); lseek(fd, vhoff, SEEK_SET); if (read(fd, buf, 65536) != 65536) { perror("read"); return 3; } uint64_t mirror_tid = *(uint64_t*)(buf+OFF_mirror_tid); uint64_t freemap_tid = *(uint64_t*)(buf+OFF_freemap_tid); uint64_t bulkfree_tid = *(uint64_t*)(buf+OFF_bulkfree_tid); uint64_t allocator_beg = *(uint64_t*)(buf+OFF_allocator_beg); uint64_t allocator_size = *(uint64_t*)(buf+OFF_allocator_size); uint64_t allocator_free = *(uint64_t*)(buf+OFF_allocator_free); printf("magic = 0x%016llx\n", (unsigned long long)*(uint64_t*)(buf+OFF_magic)); printf("allocator_size = 0x%016llx\n", (unsigned long long)allocator_size); printf("allocator_free = 0x%016llx\n", (unsigned long long)allocator_free); printf("allocator_beg = 0x%016llx\n", (unsigned long long)allocator_beg); printf("mirror_tid = 0x%016llx\n", (unsigned long long)mirror_tid); printf("freemap_tid = 0x%016llx\n", (unsigned long long)freemap_tid); printf("bulkfree_tid = 0x%016llx\n", (unsigned long long)bulkfree_tid); printf("icrc_sects[7]=0x%08x icrc_sects[6]=0x%08x\n", *(uint32_t*)(buf+OFF_icrc_sects+7*4), *(uint32_t*)(buf+OFF_icrc_sects+6*4)); printf("icrc_volheader = 0x%08x\n", *(uint32_t*)(buf+OFF_icrc_volheader)); /* dump sroot_blockset blockrefs */ for (int i = 0; i < 4; i++) { uint8_t *br = buf + OFF_sroot_blockset + i*128; uint8_t type = br[BR_type]; uint64_t key = *(uint64_t*)(br+BR_key); uint64_t mtid = *(uint64_t*)(br+BR_mirror_tid); uint64_t doff = *(uint64_t*)(br+BR_data_off); uint32_t chk = *(uint32_t*)(br+BR_check_value); printf("sroot[%d]: type=0x%02x methods=0x%02x copyid=0x%02x keybits=%d key=0x%016llx mirror_tid=0x%016llx data_off=0x%016llx (radix=%d) check=0x%08x\n", i, type, br[1], br[2], br[3], (unsigned long long)key, (unsigned long long)mtid, (unsigned long long)doff, (int)(doff & 0x3f), chk); } close(fd); return 0; } |