File hfwget.c added (mode: 100644) (index 0000000..c3f0952) |
|
1 |
|
/* |
|
2 |
|
* Hermes AP firmware extractor for Windows drivers (c) 2003 by Mark Smith |
|
3 |
|
* This may be distributed freely under the GPL v2 so long as this copyright |
|
4 |
|
* notice is included. |
|
5 |
|
*/ |
|
6 |
|
#include <stdio.h> |
|
7 |
|
#include <stdlib.h> |
|
8 |
|
#include <memory.h> |
|
9 |
|
#include <string.h> |
|
10 |
|
|
|
11 |
|
#define false 0 |
|
12 |
|
#define true (!0) |
|
13 |
|
|
|
14 |
|
struct _segarray { |
|
15 |
|
unsigned int offset; |
|
16 |
|
unsigned int size; |
|
17 |
|
unsigned char *data; |
|
18 |
|
}; |
|
19 |
|
|
|
20 |
|
struct _plugarray { |
|
21 |
|
unsigned int code; |
|
22 |
|
unsigned int targ_off; |
|
23 |
|
unsigned int length; |
|
24 |
|
}; |
|
25 |
|
|
|
26 |
|
struct firmwareblock { |
|
27 |
|
struct _segarray *segarray; |
|
28 |
|
unsigned int halfentry; |
|
29 |
|
struct _plugarray *plugarray; |
|
30 |
|
} *firmware; |
|
31 |
|
|
|
32 |
|
|
|
33 |
|
void savefirmware(unsigned char *data, unsigned int flen, unsigned int signature, unsigned char hexchar); |
|
34 |
|
|
|
35 |
|
/* |
|
36 |
|
* Main |
|
37 |
|
*/ |
|
38 |
|
int main(int argc, char *argv[]) |
|
39 |
|
{ |
|
40 |
|
FILE *input, *output; |
|
41 |
|
unsigned char *data, *offset, *end, *hexstringoffs, *page1start, *peheader; |
|
42 |
|
unsigned char hexstring[16]; |
|
43 |
|
unsigned int i, j, flen, found, imagebase, vfwoffs, fwblock; |
|
44 |
|
|
|
45 |
|
printf("Lucent Firmware Extractor v1.0 alpha\n(c) 2003 Mark Smith (username 'Mark' on HermesAP board)\n"); |
|
46 |
|
|
|
47 |
|
// Attempt to load file |
|
48 |
|
if (argc != 2) { |
|
49 |
|
printf("Usage: %s wl???.sys\n", argv[0]); |
|
50 |
|
return -1; |
|
51 |
|
} |
|
52 |
|
|
|
53 |
|
if ((input = fopen(argv[1], "rb")) == NULL) { |
|
54 |
|
printf("Unable to open %s, aborting.\n", argv[1]); |
|
55 |
|
return -1; |
|
56 |
|
} |
|
57 |
|
|
|
58 |
|
// Get file length |
|
59 |
|
fseek(input, 0L, SEEK_END); |
|
60 |
|
flen = ftell(input); |
|
61 |
|
printf("File %s length %u (0x%08x)\n", argv[1], flen, flen); |
|
62 |
|
|
|
63 |
|
// Rewind file pointer |
|
64 |
|
fseek(input, 0L, SEEK_SET); |
|
65 |
|
|
|
66 |
|
// Allocate memory and load the file |
|
67 |
|
data = malloc(flen); |
|
68 |
|
fread(data, 1, flen, input); |
|
69 |
|
printf("Memory allocated and file read OK\n"); |
|
70 |
|
fclose(input); |
|
71 |
|
|
|
72 |
|
// Dump Tertiary firmware |
|
73 |
|
printf("\nAttempting to dump tertiary firmware:\n"); |
|
74 |
|
savefirmware(data, flen, 0xfbfe4461, 'T'); |
|
75 |
|
printf("\nAttempting to dump station firmware:\n"); |
|
76 |
|
savefirmware(data, flen, 0x63fc600f, 'R'); |
|
77 |
|
|
|
78 |
|
free(data); |
|
79 |
|
printf("\nAll dumps complete.\n\n"); |
|
80 |
|
return 0; |
|
81 |
|
} |
|
82 |
|
|
|
83 |
|
void savefirmware(unsigned char *data, unsigned int flen, unsigned int signature, unsigned char hexchar) |
|
84 |
|
{ |
|
85 |
|
FILE *output; |
|
86 |
|
unsigned char *offset, *end, *hexstringoffs, *page1start, *peheader; |
|
87 |
|
unsigned char hexstring[16]; |
|
88 |
|
unsigned int i, j, found, imagebase, vfwoffs, fwblock; |
|
89 |
|
|
|
90 |
|
// Find the ?1XXYYZZ.HEX string |
|
91 |
|
offset = data; |
|
92 |
|
end = (unsigned char *)((unsigned int)data + flen); |
|
93 |
|
for (found = false; found == false && offset != NULL; ) { |
|
94 |
|
offset = memchr(offset, hexchar, (unsigned int)(end - offset)); |
|
95 |
|
|
|
96 |
|
if (offset != NULL) { |
|
97 |
|
if (memcmp(".HEX", offset + 8, 4) == 0) { |
|
98 |
|
hexstringoffs = offset; |
|
99 |
|
found = true; |
|
100 |
|
} else |
|
101 |
|
offset++; |
|
102 |
|
} |
|
103 |
|
} |
|
104 |
|
|
|
105 |
|
if (offset == NULL) { |
|
106 |
|
printf("%c-firmware not found!\n", hexchar); |
|
107 |
|
exit(-1); |
|
108 |
|
} |
|
109 |
|
|
|
110 |
|
strncpy(hexstring, offset, 13); |
|
111 |
|
hexstring[13] = 0; |
|
112 |
|
|
|
113 |
|
printf("Found firmware %s at file offset 0x%08x\n", hexstring, offset-data); |
|
114 |
|
printf("Searching for firmware start signature 0x%08x...\n", signature); |
|
115 |
|
|
|
116 |
|
// Really should use a mask here, but its not necessary for the moment. |
|
117 |
|
offset -= 4; |
|
118 |
|
for (found = false; offset > data && found == false; offset--) |
|
119 |
|
if (*(unsigned int *)offset == signature) |
|
120 |
|
found = true; |
|
121 |
|
|
|
122 |
|
if (found == false) { |
|
123 |
|
printf("Signature not found!\n"); |
|
124 |
|
exit(-2); |
|
125 |
|
} else { |
|
126 |
|
page1start = offset; |
|
127 |
|
|
|
128 |
|
printf("Found at file offset 0x%08x\n", page1start - data); |
|
129 |
|
} |
|
130 |
|
|
|
131 |
|
peheader = (unsigned char *)(*(unsigned int *)(data + 0x3c)); |
|
132 |
|
printf("Reading DOS driver header...\nPE header located at file offset 0x%08x\n", peheader); |
|
133 |
|
imagebase = (unsigned int)(*(unsigned int *)((unsigned int)peheader + (unsigned int)data + 0x34)); |
|
134 |
|
vfwoffs = (unsigned int)((unsigned int)page1start - (unsigned int)data + imagebase); |
|
135 |
|
printf("PE imagebase is 0x%08x, therefore virtual offset of firmware is 0x%08x\n", |
|
136 |
|
imagebase, vfwoffs); |
|
137 |
|
|
|
138 |
|
printf("Now searching for driver's tertiary firmware table...\n"); |
|
139 |
|
offset = end; |
|
140 |
|
vfwoffs -= 3; // kludge for driver firmware structure: one redundant dword at start. |
|
141 |
|
for (found = false; offset > data && found == false; offset--) |
|
142 |
|
if (*(unsigned int *)offset == vfwoffs) |
|
143 |
|
found = true; |
|
144 |
|
|
|
145 |
|
fwblock = (unsigned int)offset - 7 + imagebase - (unsigned int)data; |
|
146 |
|
if (found == false) { |
|
147 |
|
printf("Tertiary table not found - contact Mark!\n"); |
|
148 |
|
exit(-3); |
|
149 |
|
} else { |
|
150 |
|
printf("Found at virtual offset 0x%08x\n", fwblock); |
|
151 |
|
} |
|
152 |
|
|
|
153 |
|
printf("Finding main firmware table....\n"); |
|
154 |
|
offset = end; |
|
155 |
|
for (found = false; offset > data && found == false; offset--) |
|
156 |
|
if (*(unsigned int *)offset == fwblock) |
|
157 |
|
found = true; |
|
158 |
|
|
|
159 |
|
firmware = (struct firmwareblock *)++offset; |
|
160 |
|
if (found == false) { |
|
161 |
|
printf("Main table not found - contact Mark!\n"); |
|
162 |
|
exit(-4); |
|
163 |
|
} else { |
|
164 |
|
printf("Found at file offset 0x%08x\n", offset - data); |
|
165 |
|
} |
|
166 |
|
|
|
167 |
|
|
|
168 |
|
printf("Entry point at 0x%08x\n", firmware->halfentry * 2); |
|
169 |
|
(unsigned int)firmware->segarray += (unsigned int)data - imagebase; |
|
170 |
|
for (i = 0; i < 4 && firmware->segarray[i].offset != 0; i++) { |
|
171 |
|
(unsigned int)firmware->segarray[i].data -= imagebase - 4; |
|
172 |
|
printf("Segment: %d File offs: 0x%08x Target mem: 0x%08x Length 0x%08x\n", |
|
173 |
|
i, |
|
174 |
|
firmware->segarray[i].data, |
|
175 |
|
firmware->segarray[i].offset, |
|
176 |
|
firmware->segarray[i].size); |
|
177 |
|
} |
|
178 |
|
printf("Plugrecords at file offset 0x%08x\n", (unsigned int)firmware->plugarray - imagebase); |
|
179 |
|
|
|
180 |
|
hexstring[9] = 0; |
|
181 |
|
strcat(hexstring, "hfw"); |
|
182 |
|
|
|
183 |
|
printf("Dumping to %s...\n", hexstring); |
|
184 |
|
if ((output = fopen(hexstring, "wb")) == NULL) { |
|
185 |
|
printf("Unable to open %s, aborting.\n", hexstring); |
|
186 |
|
exit(-5); |
|
187 |
|
} |
|
188 |
|
|
|
189 |
|
(unsigned int)firmware->plugarray += (unsigned int)data - imagebase; |
|
190 |
|
|
|
191 |
|
fprintf(output, "HFW1\nENTRY %08X\n", firmware->halfentry * 2); |
|
192 |
|
for (i = 0; firmware->plugarray[i].code != 0; i++) { |
|
193 |
|
fprintf(output, "PLUG %08X %08X %08X\n", |
|
194 |
|
firmware->plugarray[i].code, |
|
195 |
|
firmware->plugarray[i].targ_off, |
|
196 |
|
firmware->plugarray[i].length); |
|
197 |
|
} |
|
198 |
|
|
|
199 |
|
for (i = 0; firmware->segarray[i].offset != 0; i++) { |
|
200 |
|
(unsigned int)firmware->segarray[i].data += (unsigned int)data; |
|
201 |
|
if (i != 0) |
|
202 |
|
fprintf(output, "\n"); |
|
203 |
|
fprintf(output, "SEG %08X %08X %08X", |
|
204 |
|
firmware->segarray[i].offset, |
|
205 |
|
firmware->segarray[i].size, |
|
206 |
|
0); |
|
207 |
|
|
|
208 |
|
for (j = 0; j < firmware->segarray[i].size; j += 2) { |
|
209 |
|
if ((j % 16) == 0) |
|
210 |
|
fprintf(output, "\nDATA"); |
|
211 |
|
|
|
212 |
|
fprintf(output, " %02X%02X", |
|
213 |
|
firmware->segarray[i].data[j], |
|
214 |
|
firmware->segarray[i].data[j + 1]); |
|
215 |
|
} |
|
216 |
|
} |
|
217 |
|
|
|
218 |
|
fputc('\n', output); |
|
219 |
|
fclose(output); |
|
220 |
|
printf("Dump of %s complete.\n", hexstring); |
|
221 |
|
} |