From 9239c21487b524cf0f87b4ffa4828793713fbecd Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sun, 26 Oct 2008 14:20:38 +0000 Subject: [PATCH] Add hfwget.c from hermesap-0.2 --- hfwget.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 hfwget.c diff --git a/hfwget.c b/hfwget.c new file mode 100644 index 0000000..c3f0952 --- /dev/null +++ b/hfwget.c @@ -0,0 +1,221 @@ +/* + * Hermes AP firmware extractor for Windows drivers (c) 2003 by Mark Smith + * This may be distributed freely under the GPL v2 so long as this copyright + * notice is included. + */ +#include +#include +#include +#include + +#define false 0 +#define true (!0) + +struct _segarray { + unsigned int offset; + unsigned int size; + unsigned char *data; +}; + +struct _plugarray { + unsigned int code; + unsigned int targ_off; + unsigned int length; +}; + +struct firmwareblock { + struct _segarray *segarray; + unsigned int halfentry; + struct _plugarray *plugarray; +} *firmware; + + +void savefirmware(unsigned char *data, unsigned int flen, unsigned int signature, unsigned char hexchar); + +/* + * Main + */ +int main(int argc, char *argv[]) +{ + FILE *input, *output; + unsigned char *data, *offset, *end, *hexstringoffs, *page1start, *peheader; + unsigned char hexstring[16]; + unsigned int i, j, flen, found, imagebase, vfwoffs, fwblock; + + printf("Lucent Firmware Extractor v1.0 alpha\n(c) 2003 Mark Smith (username 'Mark' on HermesAP board)\n"); + + // Attempt to load file + if (argc != 2) { + printf("Usage: %s wl???.sys\n", argv[0]); + return -1; + } + + if ((input = fopen(argv[1], "rb")) == NULL) { + printf("Unable to open %s, aborting.\n", argv[1]); + return -1; + } + + // Get file length + fseek(input, 0L, SEEK_END); + flen = ftell(input); + printf("File %s length %u (0x%08x)\n", argv[1], flen, flen); + + // Rewind file pointer + fseek(input, 0L, SEEK_SET); + + // Allocate memory and load the file + data = malloc(flen); + fread(data, 1, flen, input); + printf("Memory allocated and file read OK\n"); + fclose(input); + + // Dump Tertiary firmware + printf("\nAttempting to dump tertiary firmware:\n"); + savefirmware(data, flen, 0xfbfe4461, 'T'); + printf("\nAttempting to dump station firmware:\n"); + savefirmware(data, flen, 0x63fc600f, 'R'); + + free(data); + printf("\nAll dumps complete.\n\n"); + return 0; +} + +void savefirmware(unsigned char *data, unsigned int flen, unsigned int signature, unsigned char hexchar) +{ + FILE *output; + unsigned char *offset, *end, *hexstringoffs, *page1start, *peheader; + unsigned char hexstring[16]; + unsigned int i, j, found, imagebase, vfwoffs, fwblock; + + // Find the ?1XXYYZZ.HEX string + offset = data; + end = (unsigned char *)((unsigned int)data + flen); + for (found = false; found == false && offset != NULL; ) { + offset = memchr(offset, hexchar, (unsigned int)(end - offset)); + + if (offset != NULL) { + if (memcmp(".HEX", offset + 8, 4) == 0) { + hexstringoffs = offset; + found = true; + } else + offset++; + } + } + + if (offset == NULL) { + printf("%c-firmware not found!\n", hexchar); + exit(-1); + } + + strncpy(hexstring, offset, 13); + hexstring[13] = 0; + + printf("Found firmware %s at file offset 0x%08x\n", hexstring, offset-data); + printf("Searching for firmware start signature 0x%08x...\n", signature); + + // Really should use a mask here, but its not necessary for the moment. + offset -= 4; + for (found = false; offset > data && found == false; offset--) + if (*(unsigned int *)offset == signature) + found = true; + + if (found == false) { + printf("Signature not found!\n"); + exit(-2); + } else { + page1start = offset; + + printf("Found at file offset 0x%08x\n", page1start - data); + } + + peheader = (unsigned char *)(*(unsigned int *)(data + 0x3c)); + printf("Reading DOS driver header...\nPE header located at file offset 0x%08x\n", peheader); + imagebase = (unsigned int)(*(unsigned int *)((unsigned int)peheader + (unsigned int)data + 0x34)); + vfwoffs = (unsigned int)((unsigned int)page1start - (unsigned int)data + imagebase); + printf("PE imagebase is 0x%08x, therefore virtual offset of firmware is 0x%08x\n", + imagebase, vfwoffs); + + printf("Now searching for driver's tertiary firmware table...\n"); + offset = end; + vfwoffs -= 3; // kludge for driver firmware structure: one redundant dword at start. + for (found = false; offset > data && found == false; offset--) + if (*(unsigned int *)offset == vfwoffs) + found = true; + + fwblock = (unsigned int)offset - 7 + imagebase - (unsigned int)data; + if (found == false) { + printf("Tertiary table not found - contact Mark!\n"); + exit(-3); + } else { + printf("Found at virtual offset 0x%08x\n", fwblock); + } + + printf("Finding main firmware table....\n"); + offset = end; + for (found = false; offset > data && found == false; offset--) + if (*(unsigned int *)offset == fwblock) + found = true; + + firmware = (struct firmwareblock *)++offset; + if (found == false) { + printf("Main table not found - contact Mark!\n"); + exit(-4); + } else { + printf("Found at file offset 0x%08x\n", offset - data); + } + + + printf("Entry point at 0x%08x\n", firmware->halfentry * 2); + (unsigned int)firmware->segarray += (unsigned int)data - imagebase; + for (i = 0; i < 4 && firmware->segarray[i].offset != 0; i++) { + (unsigned int)firmware->segarray[i].data -= imagebase - 4; + printf("Segment: %d File offs: 0x%08x Target mem: 0x%08x Length 0x%08x\n", + i, + firmware->segarray[i].data, + firmware->segarray[i].offset, + firmware->segarray[i].size); + } + printf("Plugrecords at file offset 0x%08x\n", (unsigned int)firmware->plugarray - imagebase); + + hexstring[9] = 0; + strcat(hexstring, "hfw"); + + printf("Dumping to %s...\n", hexstring); + if ((output = fopen(hexstring, "wb")) == NULL) { + printf("Unable to open %s, aborting.\n", hexstring); + exit(-5); + } + + (unsigned int)firmware->plugarray += (unsigned int)data - imagebase; + + fprintf(output, "HFW1\nENTRY %08X\n", firmware->halfentry * 2); + for (i = 0; firmware->plugarray[i].code != 0; i++) { + fprintf(output, "PLUG %08X %08X %08X\n", + firmware->plugarray[i].code, + firmware->plugarray[i].targ_off, + firmware->plugarray[i].length); + } + + for (i = 0; firmware->segarray[i].offset != 0; i++) { + (unsigned int)firmware->segarray[i].data += (unsigned int)data; + if (i != 0) + fprintf(output, "\n"); + fprintf(output, "SEG %08X %08X %08X", + firmware->segarray[i].offset, + firmware->segarray[i].size, + 0); + + for (j = 0; j < firmware->segarray[i].size; j += 2) { + if ((j % 16) == 0) + fprintf(output, "\nDATA"); + + fprintf(output, " %02X%02X", + firmware->segarray[i].data[j], + firmware->segarray[i].data[j + 1]); + } + } + + fputc('\n', output); + fclose(output); + printf("Dump of %s complete.\n", hexstring); +} -- 2.11.4.GIT