/* This program fixes the MS-DOS floppy disk image that was used in the Honeynet Project's Scan of the Month for October. http://www.honeynet.org/scans/scan24/ Written by Eloy Paris Usage: gcc -o fix-image fix-image.c ./fix-image */ #include #include #include #include struct cluster_def { unsigned starting_cluster; unsigned nclusters; }; /* Where our files are */ struct cluster_def clusters[] = { {2, 40}, /* JIMMYJ~1.DOC */ {42, 31}, /* COVERP~1.JPG */ {73, 5} /* SCHEDU~1.EXE */ }; #define FAT1_START_OFFSET 0x200 #define FAT2_START_OFFSET 0x1400 #define FAT_SIZE 0x1200 #define DIR_ENTRY_SIZE 32 struct rootdir_entry { unsigned offset; unsigned char data[DIR_ENTRY_SIZE]; }; struct rootdir_entry rootdir_entries[] = { { 0x2600, { 0x42, 0x64, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0xbc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff } }, { 0x2620, { 0x01, 0x4a, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x79, 0x00, 0x0f, 0x00, 0xbc, 0x20, 0x00, 0x4a, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x65, 0x00, 0x2e, 0x00 } }, { 0x2640, /* JIMMYJ~1.DOC */ { 0x4a, 0x49, 0x4d, 0x4d, 0x59, 0x4a, 0x7e, 0x31, 0x44, 0x4f, 0x43, 0x20, 0x00, 0x68, 0x38, 0x46, 0x2b, 0x2d, 0x2b, 0x2d, 0x00, 0x00, 0x4f, 0x75, 0x8f, 0x2c, 0x02, 0x00, 0x00, 0x50, 0x00, 0x00 } }, { 0x2660, { 0x42, 0x67, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff } }, { 0x2680, { 0x01, 0x63, 0x00, 0x6f, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x0f, 0x00, 0xf4, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x70, 0x00 } }, { 0x26a0, { 0x43, 0x4f, 0x56, 0x45, 0x52, 0x50, 0x7e, 0x31, 0x4a, 0x50, 0x47, 0x20, 0x00, 0x6d, 0x4d, 0x46, 0x2b, 0x2d, 0x2b, 0x2d, 0x00, 0x00, 0xda, 0x43, 0x2b, 0x2d, 0x2a, 0x00, 0xe1, 0x3c, 0x00, 0x00 } }, { 0x26c0, { 0x42, 0x69, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x0f, 0x00, 0x55, 0x78, 0x00, 0x65, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff } }, { 0x26e0, { 0x01, 0x53, 0x00, 0x63, 0x00, 0x68, 0x00, 0x65, 0x00, 0x64, 0x00, 0x0f, 0x00, 0x55, 0x75, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x56, 0x00, 0x00, 0x00, 0x69, 0x00, 0x73, 0x00 } }, { 0x2700, /* SCHEDU~1.EXE */ { 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x7e, 0x31, 0x45, 0x58, 0x45, 0x20, 0x00, 0x53, 0x53, 0x46, 0x2b, 0x2d, 0x2b, 0x2d, 0x00, 0x00, 0x90, 0x42, 0xb8, 0x2c, 0x49, 0x00, 0x00, 0x0a, 0x00, 0x00 } } }; void die(const char *mesg, ...); unsigned read_fat(unsigned char *fat, unsigned index); void set_fat(unsigned char *fat, unsigned index, unsigned cluster); void dump(const unsigned char *data, unsigned len); int main(int argc, char **argv) { FILE *image; unsigned char *fat1, *fat2; unsigned i, j; if (argc != 2) die("Usage: %s ms-dos_image", argv[0]); if ( (fat1 = (unsigned char *) malloc(FAT_SIZE) ) == NULL) die("Can't allocate memory for FAT1"); if ( (fat2 = (unsigned char *) malloc(FAT_SIZE) ) == NULL) { free(fat1); die("Can't allocate memory for FAT2"); } if ( (image = fopen(argv[1], "r+") ) == NULL) { free(fat1); free(fat2); die("Can't open floppy disk image %s", argv[1]); } /* Compare the two FATs */ printf("Comparing FATs... "); fseek(image, FAT1_START_OFFSET, SEEK_SET); fread(fat1, FAT_SIZE, 1, image); fseek(image, FAT2_START_OFFSET, SEEK_SET); fread(fat2, FAT_SIZE, 1, image); if (memcmp(fat1, fat2, FAT_SIZE) ) { free(fat1); free(fat2); fclose(image); die("FATs are not equal"); } else printf("OK\n"); /* Fix FATs */ for (i = 0; i < sizeof(clusters)/sizeof(struct cluster_def); i++) { for (j = clusters[i].starting_cluster; j < clusters[i].starting_cluster + clusters[i].nclusters - 1; j++) { set_fat(fat1, j, j + 1); } set_fat(fat1, j, 0xff8); } memcpy(fat2, fat1, FAT_SIZE); fseek(image, FAT1_START_OFFSET, SEEK_SET); fwrite(fat1, FAT_SIZE, 1, image); fseek(image, FAT2_START_OFFSET, SEEK_SET); fwrite(fat2, FAT_SIZE, 1, image); #if 0 dump(fat1, FAT_SIZE); #endif /* Fix root directory */ for (i = 0; i < sizeof(rootdir_entries)/sizeof(struct rootdir_entry); i++) { fseek(image, rootdir_entries[i].offset, SEEK_SET); fwrite(&rootdir_entries[i].data, DIR_ENTRY_SIZE, 1, image); } #if 0 /* Schedule */ fseek(image, rootdir_entries[2] , SEEK_SET); fread(direntry, DIR_ENTRY_SIZE, 1, image); *(unsigned *) (direntry + 28) = 2560; /* Fix file size */ fseek(image, rootdir_entries[2] , SEEK_SET); fwrite(direntry, DIR_ENTRY_SIZE, 1, image); /* Cover */ fseek(image, rootdir_entries[1] , SEEK_SET); fread(direntry, DIR_ENTRY_SIZE, 1, image); *(short *) (direntry + 26) = clusters[1].starting_cluster; fseek(image, rootdir_entries[1] , SEEK_SET); fwrite(direntry, DIR_ENTRY_SIZE, 1, image); /* Recover deleted file */ fseek(image, ROOTDIR_START_OFFSET, SEEK_SET); fread(direntry, DIR_ENTRY_SIZE, 3, image); direntry[64] = 'J'; direntry[32] = 0x1; direntry[0] = 0x42; fseek(image, ROOTDIR_START_OFFSET, SEEK_SET); fwrite(direntry, DIR_ENTRY_SIZE, 3, image); #endif free(fat1); free(fat2); fclose(image); return 0; } void die(const char *mesg, ...) { va_list ap; va_start(ap, mesg); vfprintf(stderr, mesg, ap); fputc('\n', stderr); va_end(ap); exit(1); } unsigned read_fat(unsigned char *fat, unsigned index) { unsigned offset; unsigned cluster; offset = index*12/8; if (index % 2) cluster = ( *(unsigned *) (fat + offset) ) >> 4; else cluster = ( *(unsigned *) (fat + offset) ) & 0x0fff; return cluster; } void set_fat(unsigned char *fat, unsigned index, unsigned cluster) { unsigned offset; offset = index*12/8; if (index % 2) { *( (unsigned *) (fat + offset)) &= 0x000f; *( (unsigned *) (fat + offset)) |= (cluster << 4); } else { *(unsigned *) (fat + offset) &= 0xf000; *(unsigned *) (fat + offset) |= (cluster & 0x0fff); } } void dump(const unsigned char *data, unsigned len) { unsigned i, j; for (i = 0; i <= len/16; i++) { printf("%08x ", i*16); for (j = 0; j < 16; j++) { if (i*16 + j < len) printf("%02hhx", data[i*16 + j]); else printf(" "); if (j & 1) printf(" "); } for (j = 0; j < 16; j++) if (i*16 + j < len) printf("%c", isprint(data[i*16 + j]) ? data[i*16 + j] : '.'); printf("\n"); } printf("\n"); }