pedump 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,56 @@
1
+ #ifndef _LZXDEC_H_
2
+ #define _LZXDEC_H_ "ASPack's lzx-alike raw stream decoder"
3
+
4
+ //#include <windows.h>
5
+
6
+ /* ------------------------------------------------------------------------- */
7
+
8
+ /* bit reader context */
9
+ typedef struct _LZX_BITRDR {
10
+ BYTE* SrcData; /* input raw data */
11
+ UINT SrcSize; /* raw data size */
12
+ UINT CurOffs; /* current offset */
13
+ DWORD BitBuff; /* bits buffer */
14
+ UINT BitFree; /* bits counter */
15
+ } LZX_BITRDR, *PLZX_BITRDR;
16
+
17
+ /* sliding window dictionary */
18
+ typedef struct _LZX_SWD {
19
+ BYTE* Window; /* window memory */
20
+ UINT WndLen; /* size of window */
21
+ UINT CurOfs; /* current offset */
22
+ } LZX_SWD, *PLZX_SWD;
23
+
24
+ /* huffman decoder context */
25
+ typedef struct _LZX_HUFF {
26
+ LZX_BITRDR* BitRdr; /* bit stream reader */
27
+ UINT SymLim[16]; /* max symbol for x bits */
28
+ UINT SymIdx[16]; /* symbol index for x bits */
29
+ UINT SymNum; /* total number of symbols */
30
+ UINT* Symbol; /* symbols array for x len */
31
+ BYTE* Length; /* symbols length array */
32
+ } LZX_HUFF, *PLZX_HUFF;
33
+
34
+ /* general decoder context */
35
+ typedef struct _LZX_CONTEXT {
36
+ LZX_BITRDR BitRdr; /* source reader / bit-buffer */
37
+ UINT LstOfs[3]; /* saved last phrases offsets */
38
+ BYTE* LstMem; /* free huffman heap mem ptr */
39
+ LZX_SWD Window; /* sliding window dictionary */
40
+ LZX_HUFF HufBase; /* general huffman decoder */
41
+ LZX_HUFF HufLens; /* lengths huffman decoder */
42
+ LZX_HUFF HufOffs; /* offsets huffman decoder */
43
+ LZX_HUFF HufSpec; /* special huffman decoder */
44
+ BOOL HasOffs; /* offsets decoder used flag */
45
+ BYTE HufTbl[6144]; /* huffman tables heap memory */
46
+ } LZX_CONTEXT, *PLZX_CONTEXT;
47
+
48
+ /* ------------------------------------------------------------------------- */
49
+
50
+ /* general aspack stream decoder */
51
+ /* return decoded size or -1 in case of errors */
52
+ INT DecodeLZX(LZX_CONTEXT* Ctx, BYTE* Src, BYTE* Dst, UINT PSize, UINT USize);
53
+
54
+ /* ------------------------------------------------------------------------- */
55
+
56
+ #endif /* _LZXDEC_H_ */
@@ -0,0 +1,751 @@
1
+ /* Windows/DOS NE (New Executable) dumper
2
+ *
3
+ * Copyright (C) 2012 Daniel Collins <solemnwarning@solemnwarning.net>
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ *
12
+ * * Redistributions in binary form must reproduce the above copyright
13
+ * notice, this list of conditions and the following disclaimer in the
14
+ * documentation and/or other materials provided with the distribution.
15
+ *
16
+ * * Neither the name of the developer nor the names of its contributors
17
+ * may be used to endorse or promote products derived from this software
18
+ * without specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ * DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE FOR ANY DIRECT, INDIRECT,
24
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
26
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ */
31
+
32
+ /* Version history:
33
+ *
34
+ * 2012-01-12:
35
+ * Initial release
36
+ */
37
+
38
+ #include <stdio.h>
39
+ #include <unistd.h>
40
+ #include <stdlib.h>
41
+ #include <string.h>
42
+
43
+ #define FLAG_CAT(dest, src, cond) \
44
+ if(cond) { \
45
+ strcat(dest, dest[0] ? (" | " src) : src); \
46
+ }
47
+
48
+ #define MZ_MAGIC 0x5A4D
49
+
50
+ struct mz_header {
51
+ unsigned short magic;
52
+ unsigned short bytes_in_last_block;
53
+ unsigned short blocks_in_file;
54
+ unsigned short num_relocs;
55
+ unsigned short header_paragraphs;
56
+ unsigned short min_extra_paragraphs;
57
+ unsigned short max_extra_paragraphs;
58
+ unsigned short ss;
59
+ unsigned short sp;
60
+ unsigned short checksum;
61
+ unsigned short ip;
62
+ unsigned short cs;
63
+ unsigned short reloc_table_offset;
64
+ unsigned short overlay_number;
65
+ };
66
+
67
+ #define NE_MAGIC 0x454E
68
+
69
+ #define NE_FLAG_SINGLEDATA 0x0001
70
+ #define NE_FLAG_MULTIPLEDATA 0x0002
71
+ #define NE_FLAG_LIBRARY 0x8000
72
+
73
+ #define NE_EXE_WINDOWS 0x02
74
+
75
+ struct ne_header {
76
+ /* Offsets relative to beginning of NE header */
77
+
78
+ unsigned short magic;
79
+ unsigned char linker_ver;
80
+ unsigned char linker_rev;
81
+ unsigned short entry_table_offset;
82
+ unsigned short entry_table_size;
83
+ unsigned int whole_file_crc;
84
+ unsigned short flags;
85
+ unsigned short auto_data_segment;
86
+ unsigned short init_heap_size;
87
+ unsigned short init_stack_size;
88
+ unsigned short ip;
89
+ unsigned short cs;
90
+ unsigned short ss;
91
+ unsigned short sp;
92
+ unsigned short seg_table_entries;
93
+ unsigned short mod_ref_table_entries;
94
+ unsigned short non_res_name_table_entries;
95
+ unsigned short seg_table_offset;
96
+ unsigned short res_table_offset;
97
+ unsigned short res_name_table_offset;
98
+ unsigned short mod_ref_table_offset;
99
+ unsigned short import_table_offset;
100
+ unsigned int non_res_name_table_offset; /* Relative to start of file */
101
+ unsigned short entry_table_movable_entries;
102
+ unsigned short seg_sector_size_shift;
103
+ unsigned short res_table_entries;
104
+ unsigned char exe_type;
105
+ };
106
+
107
+ struct import_table {
108
+ unsigned char name_len;
109
+ char name[256];
110
+ };
111
+
112
+ struct export_table {
113
+ unsigned char name_len;
114
+ char name[256];
115
+
116
+ unsigned short ordinal;
117
+ } __attribute__((__packed__));
118
+
119
+ struct entry_bundle {
120
+ unsigned char bundle_entries;
121
+ unsigned char segment_indicator;
122
+ };
123
+
124
+ struct fixed_entry {
125
+ unsigned char flags;
126
+ unsigned short seg_offset;
127
+ } __attribute__((__packed__));
128
+
129
+ struct moveable_entry {
130
+ unsigned char flags;
131
+ unsigned short padding;
132
+ unsigned char seg_num;
133
+ unsigned short seg_offset;
134
+ } __attribute__((__packed__));
135
+
136
+ #define SEG_TYPE_MASK 0x0007
137
+ #define SEG_CODE 0x0000
138
+ #define SEG_DATA 0x0001
139
+ #define SEG_MOVEABLE 0x0010
140
+ #define SEG_PRELOAD 0x0040
141
+ #define SEG_RELOCINFO 0x0100
142
+ #define SEG_DISCARD 0xF000
143
+
144
+ struct segment_table {
145
+ unsigned short offset; /* Measured in sectors, zero means no data */
146
+ unsigned short size; /* Measured in bytes, zero means 64KiB */
147
+ unsigned short flags;
148
+ unsigned short alloc; /* Minimum allocation size, zero means 64KiB */
149
+ };
150
+
151
+ #define RELOC_LOBYTE 0x00
152
+ #define RELOC_SEGMENT 0x02
153
+ #define RELOC_FAR_ADDR 0x03
154
+ #define RELOC_OFFSET 0x05
155
+
156
+ #define RELOC_TARGET_MASK 0x03
157
+ #define RELOC_INTERNALREF 0x00
158
+ #define RELOC_IMPORTORDINAL 0x01
159
+ #define RELOC_IMPORTNAME 0x02
160
+ #define RELOC_OSFIXUP 0x03
161
+ #define RELOC_ADDITIVE 0x04
162
+
163
+ struct segment_reloc {
164
+ unsigned char src_type;
165
+ unsigned char flags;
166
+ unsigned short offset;
167
+
168
+ union {
169
+ struct {
170
+ unsigned char seg_num;
171
+ unsigned char zero;
172
+ unsigned short offset;
173
+ } internalref;
174
+
175
+ struct {
176
+ unsigned short mod_index;
177
+ unsigned short name_offset;
178
+ } importname;
179
+
180
+ struct {
181
+ unsigned short mod_index;
182
+ unsigned short ordinal;
183
+ } importordinal;
184
+
185
+ struct {
186
+ unsigned short fixup_type;
187
+ unsigned short zero;
188
+ } osfixup;
189
+
190
+ unsigned char target_b[4];
191
+ unsigned short target_w[2];
192
+ };
193
+ };
194
+
195
+ #define RESOURCE_HO 0x8000
196
+
197
+ struct resource_table_type {
198
+ unsigned short type_id;
199
+ unsigned short res_count;
200
+ unsigned int padding;
201
+ };
202
+
203
+ #define RESOURCE_MOVEABLE 0x0010
204
+ #define RESOURCE_PURE 0x0020
205
+ #define RESOURCE_PRELOAD 0x0040
206
+
207
+ struct resource_table_entry {
208
+ unsigned short offset;
209
+ unsigned short length;
210
+
211
+ unsigned short flags;
212
+ unsigned short res_id;
213
+
214
+ unsigned int padding;
215
+ };
216
+
217
+ struct import_entry {
218
+ char module[256];
219
+
220
+ char name[256];
221
+ int ordinal;
222
+
223
+ struct import_entry *next;
224
+ };
225
+
226
+ FILE *fh;
227
+
228
+ size_t read_data(char *buf, size_t offset, size_t size) {
229
+ if(fseek(fh, offset, SEEK_SET) == -1) {
230
+ return 0;
231
+ }
232
+
233
+ size_t s = 0, r;
234
+
235
+ while(s < size) {
236
+ if((r = fread(buf + s, 1, size - s, fh)) == 0) {
237
+ break;
238
+ }
239
+
240
+ s += r;
241
+ }
242
+
243
+ if(ferror(fh)) {
244
+ fprintf(stderr, "Read error\n");
245
+ exit(1);
246
+ }
247
+
248
+ return s;
249
+ }
250
+
251
+ void add_import(struct import_entry **list, const char *module, const char *name, int ordinal) {
252
+ while(*list && strcasecmp((*list)->module, module) < 0) {
253
+ list = &((*list)->next);
254
+ }
255
+
256
+ if(name) {
257
+ while(*list && strcasecmp((*list)->module, module) == 0 && strcasecmp((*list)->name, name) < 0) {
258
+ list = &((*list)->next);
259
+ }
260
+
261
+ if(*list && strcasecmp((*list)->name, name) == 0) {
262
+ return;
263
+ }
264
+ }else{
265
+ while(*list && strcasecmp((*list)->module, module) == 0 && (*list)->ordinal < ordinal) {
266
+ list = &((*list)->next);
267
+ }
268
+
269
+ if(*list && (*list)->ordinal == ordinal) {
270
+ return;
271
+ }
272
+ }
273
+
274
+ struct import_entry *import = malloc(sizeof(struct import_entry));
275
+ if(!import) {
276
+ fprintf(stderr, "Memory allocation failed\n");
277
+ exit(1);
278
+ }
279
+
280
+ strcpy(import->module, module);
281
+ strcpy(import->name, name ? name : "");
282
+ import->ordinal = ordinal;
283
+
284
+ import->next = *list;
285
+ *list = import;
286
+ }
287
+
288
+ void dump_imports(struct import_entry *imports) {
289
+ printf("Imported names:\n");
290
+
291
+ while(imports) {
292
+ if(imports->name[0]) {
293
+ printf("\t%s\t%s\n", imports->module, imports->name);
294
+ }else{
295
+ printf("\t%s\t@%d\n", imports->module, imports->ordinal);
296
+ }
297
+
298
+ imports = imports->next;
299
+ }
300
+ }
301
+
302
+ void free_imports(struct import_entry *imports) {
303
+ while(imports) {
304
+ struct import_entry *d = imports;
305
+ imports = imports->next;
306
+
307
+ free(d);
308
+ }
309
+ }
310
+
311
+ void dump_names(unsigned int res_off, unsigned int table_entries, unsigned int entry_table_off) {
312
+ unsigned int res_num = 0;
313
+ struct export_table exp;
314
+
315
+ while(res_num < table_entries && read_data((char*)&exp, res_off, sizeof(exp)) >= 2) {
316
+ if(exp.name_len == 0) {
317
+ break;
318
+ }
319
+
320
+ res_off += exp.name_len + 1;
321
+ read_data((char*)&(exp.ordinal), res_off, 2);
322
+ res_off += 2;
323
+
324
+ exp.name[exp.name_len] = '\0';
325
+
326
+ if(res_num++ == 0) {
327
+ continue;
328
+ }
329
+
330
+ /* Step through entry point table to get address */
331
+
332
+ char entry_txt[64] = "WARNING: Entry point not found";
333
+
334
+ unsigned int entry_off = entry_table_off, ordinal = 1, i;
335
+ struct entry_bundle bundle;
336
+
337
+ while(read_data((char*)&bundle, entry_off, sizeof(bundle)) >= 1 && bundle.bundle_entries && ordinal <= exp.ordinal) {
338
+ entry_off += sizeof(bundle);
339
+
340
+ if(bundle.segment_indicator == 0) {
341
+ ordinal += bundle.bundle_entries;
342
+ continue;
343
+ }
344
+
345
+ for(i = 0; i < bundle.bundle_entries; i++) {
346
+ unsigned short seg = 0, off;
347
+
348
+ if(bundle.segment_indicator == 0xFF) {
349
+ struct moveable_entry entry;
350
+ entry_off += read_data((char*)&entry, entry_off, sizeof(entry));
351
+
352
+ seg = entry.seg_num;
353
+ off = entry.seg_offset;
354
+ }else{
355
+ struct fixed_entry entry;
356
+ entry_off += read_data((char*)&entry, entry_off, sizeof(entry));
357
+
358
+ seg = bundle.segment_indicator;
359
+ off = entry.seg_offset;
360
+ }
361
+
362
+ if(ordinal++ == exp.ordinal && seg) {
363
+ sprintf(entry_txt, "Entry point segment: %hu, offset: 0x%04hX", seg, off);
364
+ break;
365
+ }
366
+ }
367
+ }
368
+
369
+ printf("\t%s\t@%hu\t; %s\n", exp.name, exp.ordinal, entry_txt);
370
+ }
371
+ }
372
+
373
+ void dump_ep_table(unsigned int entry_off) {
374
+ printf("Entry point table:\n");
375
+
376
+ unsigned int ordinal = 1, i;
377
+ struct entry_bundle bundle;
378
+
379
+ while(read_data((char*)&bundle, entry_off, sizeof(bundle)) >= 1 && bundle.bundle_entries) {
380
+ entry_off += sizeof(bundle);
381
+
382
+ if(bundle.segment_indicator == 0) {
383
+ ordinal += bundle.bundle_entries;
384
+ continue;
385
+ }
386
+
387
+ for(i = 0; i < bundle.bundle_entries; i++) {
388
+ if(bundle.segment_indicator == 0xFF) {
389
+ struct moveable_entry entry;
390
+ entry_off += read_data((char*)&entry, entry_off, sizeof(entry));
391
+
392
+ printf("\tOrdinal:\t%u\n", ordinal);
393
+ printf("\tType:\t\tMoveable\n");
394
+ printf("\tSegment number:\t%u\n", (unsigned int)entry.seg_num);
395
+ printf("\tOffset:\t\t0x%04hX\n", entry.seg_offset);
396
+ printf("\tFlags:\t\t0x%02X\n\n", (unsigned int)entry.flags);
397
+ }else{
398
+ struct fixed_entry entry;
399
+ entry_off += read_data((char*)&entry, entry_off, sizeof(entry));
400
+
401
+ printf("\tOrdinal:\t%u\n", ordinal);
402
+ printf("\tType:\t\tFixed\n");
403
+ printf("\tSegment number:\t%u\n", (unsigned int)bundle.segment_indicator);
404
+ printf("\tOffset:\t\t0x%04hX\n", entry.seg_offset);
405
+ printf("\tFlags:\t\t0x%02X\n\n", (unsigned int)entry.flags);
406
+ }
407
+
408
+ ordinal++;
409
+ }
410
+ }
411
+ }
412
+
413
+ void get_resource_id(char *buf, unsigned int res_table_off, unsigned short id) {
414
+ if(id & RESOURCE_HO) {
415
+ sprintf(buf, "%hu", id & ~RESOURCE_HO);
416
+ }else{
417
+ struct import_table name;
418
+
419
+ read_data((char*)&name, res_table_off + id, sizeof(name));
420
+ name.name[name.name_len] = '\0';
421
+
422
+ sprintf(buf, "\"%s\"", name.name);
423
+ }
424
+ }
425
+
426
+ void dump_resources(unsigned int res_table_off) {
427
+ unsigned int res_off = res_table_off;
428
+
429
+ unsigned short shift_count;
430
+ res_off += read_data((char*)&shift_count, res_off, sizeof(shift_count));
431
+
432
+ struct resource_table_type rt;
433
+
434
+ while(read_data((char*)&rt, res_off, sizeof(rt)) >= 2 && rt.type_id) {
435
+ res_off += sizeof(rt);
436
+
437
+ char type_id[260];
438
+ get_resource_id(type_id, res_table_off, rt.type_id);
439
+
440
+ unsigned int i;
441
+ struct resource_table_entry re;
442
+
443
+ for(i = 0; i < rt.res_count; i++) {
444
+ read_data((char*)&re, res_off, sizeof(re));
445
+
446
+ char res_id[260];
447
+ get_resource_id(res_id, res_table_off, re.res_id);
448
+
449
+ unsigned int off = (unsigned int)(1 << shift_count) * re.offset;
450
+
451
+ char flags[64] = "";
452
+
453
+ FLAG_CAT(flags, "MOVEABLE", re.flags & RESOURCE_MOVEABLE);
454
+ FLAG_CAT(flags, "PURE", re.flags & RESOURCE_PURE);
455
+ FLAG_CAT(flags, "PRELOAD", re.flags & RESOURCE_PRELOAD);
456
+
457
+ printf("Resource table entry at 0x%04X:\n", res_off);
458
+ printf("\tType ID:\t%s\n", type_id);
459
+ printf("\tResource ID:\t%s\n", res_id);
460
+ printf("\tData offset:\t0x%04X\n", off);
461
+ printf("\tData length:\t0x%04hX\n", re.length);
462
+ printf("\tFlags:\t\t0x%04hX (%s)\n\n", re.flags, flags);
463
+
464
+ res_off += sizeof(re);
465
+ }
466
+ }
467
+ }
468
+
469
+ #define DUMP_IMPORTS (int)(1<<0)
470
+ #define DUMP_SEGMENTS (int)(1<<1)
471
+ #define DUMP_RELOCATION (int)(1<<2)
472
+ #define DUMP_NONRES (int)(1<<3)
473
+ #define DUMP_RESIDENT (int)(1<<4)
474
+ #define DUMP_ENTRY (int)(1<<5)
475
+ #define DUMP_NE (int)(1<<6)
476
+ #define DUMP_MZ (int)(1<<7)
477
+ #define DUMP_RESOURCE (int)(1<<8)
478
+
479
+ int main(int argc, char **argv) {
480
+ int opt;
481
+
482
+ int to_dump = 0;
483
+
484
+ while((opt = getopt(argc, argv, "isrnNehmR")) != -1) {
485
+ switch(opt) {
486
+ case '?':
487
+ goto USAGE;
488
+
489
+ case 'i':
490
+ to_dump |= DUMP_IMPORTS;
491
+ break;
492
+
493
+ case 's':
494
+ to_dump |= DUMP_SEGMENTS;
495
+ break;
496
+
497
+ case 'r':
498
+ to_dump |= DUMP_RELOCATION;
499
+ break;
500
+
501
+ case 'n':
502
+ to_dump |= DUMP_NONRES;
503
+ break;
504
+
505
+ case 'N':
506
+ to_dump |= DUMP_RESIDENT;
507
+ break;
508
+
509
+ case 'e':
510
+ to_dump |= DUMP_ENTRY;
511
+ break;
512
+
513
+ case 'h':
514
+ to_dump |= DUMP_NE;
515
+ break;
516
+
517
+ case 'm':
518
+ to_dump |= DUMP_MZ;
519
+ break;
520
+
521
+ case 'R':
522
+ to_dump |= DUMP_RESOURCE;
523
+ break;
524
+ };
525
+ }
526
+
527
+ if(optind + 1 != argc || !to_dump) {
528
+ USAGE:
529
+
530
+ fprintf(stderr, "Usage: %s -hisrnNemR <file>\n", argv[0]);
531
+
532
+ fprintf(stderr, "\t-h\tDump NE EXE header\n");
533
+ fprintf(stderr, "\t-i\tDump detected imports\n");
534
+ fprintf(stderr, "\t-s\tDump segment table\n");
535
+ fprintf(stderr, "\t-r\tDump relocation information\n");
536
+ fprintf(stderr, "\t-n\tDump exported non-resident names\n");
537
+ fprintf(stderr, "\t-N\tDump exported resident names\n");
538
+ fprintf(stderr, "\t-e\tDump entry points\n");
539
+ fprintf(stderr, "\t-m\tDump MZ (DOS EXE) header\n");
540
+ fprintf(stderr, "\t-R\tDump resource table\n");
541
+
542
+ return 1;
543
+ }
544
+
545
+ if(!(fh = fopen(argv[optind], "rb"))) {
546
+ fprintf(stderr, "Cannot open file\n");
547
+ return 1;
548
+ }
549
+
550
+ struct mz_header mz;
551
+
552
+ if(read_data((char*)&mz, 0, sizeof(mz)) != sizeof(mz) || mz.magic != MZ_MAGIC) {
553
+ fprintf(stderr, "EXE (MZ) header missing or incomplete\n");
554
+ return 1;
555
+ }
556
+
557
+ if(to_dump & DUMP_MZ) {
558
+ printf("MZ header information:\n");
559
+ printf("\tNumber of pages:\t%hu\n", mz.blocks_in_file);
560
+ printf("\tBytes in last page:\t%hu\n", mz.bytes_in_last_block);
561
+ printf("\tRelocation table off.:\t0x%04hX\n", mz.reloc_table_offset);
562
+ printf("\tNumber of relocations:\t%hu\n", mz.num_relocs);
563
+ printf("\tHeader size:\t\t0x%04X\n", (unsigned int)mz.header_paragraphs * 16);
564
+ printf("\tMinimum extra memory:\t0x%04X\n", (unsigned int)mz.min_extra_paragraphs * 16);
565
+ printf("\tMaximum extra memory:\t0x%04X\n", (unsigned int)mz.max_extra_paragraphs * 16);
566
+ printf("\tInitial CS:IP:\t\t0x%04hX:%04hX\n", mz.cs, mz.ip);
567
+ printf("\tInitial SS:SP:\t\t0x%04hX:%04hX\n", mz.ss, mz.sp);
568
+ printf("\tWhole file checksum:\t0x%04hX\n", mz.checksum);
569
+ printf("\tOverlay number:\t\t%hu\n\n", mz.overlay_number);
570
+ }
571
+
572
+ if(mz.reloc_table_offset == 0x40) {
573
+ unsigned int ne_offset;
574
+ struct ne_header ne;
575
+
576
+ if(read_data((char*)&ne_offset, 0x3C, 4) != 4 || read_data((char*)&ne, ne_offset, sizeof(ne)) != sizeof(ne) || ne.magic != NE_MAGIC) {
577
+ goto NOT_NE;
578
+ }
579
+
580
+ if(to_dump & DUMP_NE) {
581
+ printf("NE header information:\n");
582
+
583
+ printf("\tHeader offset:\t\t0x%04X\n", ne_offset);
584
+ printf("\tLinker version:\t\t%u.%u\n", (unsigned int)ne.linker_ver, (unsigned int)ne.linker_rev);
585
+ printf("\tEntry point table:\t0x%04X\n", ne_offset + ne.entry_table_offset);
586
+ printf("\tWhole file CRC-32:\t0x%08X\n", ne.whole_file_crc);
587
+
588
+ char flags[64] = "";
589
+
590
+ FLAG_CAT(flags, "NOAUTODATA", (ne.flags & 0x0003) == 0);
591
+ FLAG_CAT(flags, "SINGLEDATA", ne.flags & 0x0001);
592
+ FLAG_CAT(flags, "MULTIPLEDATA", ne.flags & 0x0002);
593
+ FLAG_CAT(flags, "LIBRARY", ne.flags & 0x8000);
594
+
595
+ printf("\tFlags\t\t\t0x%04X (%s)\n", (unsigned int)ne.flags, flags);
596
+
597
+ printf("\tAutomatic data segment:\t%hu\n", ne.auto_data_segment);
598
+
599
+ printf("\tDynamic heap size:\t0x%04hX\n", ne.init_heap_size);
600
+ printf("\tDynamic stack size:\t0x%04hX\n", ne.init_stack_size);
601
+
602
+ printf("\tInitial CS:IP:\t\t0x%04hX:%04hX\n", ne.cs, ne.ip);
603
+ printf("\tInitial SS:SP:\t\t0x%04hX:%04hX\n", ne.ss, ne.sp);
604
+
605
+ printf("\tNumber of segments:\t%hu\n", ne.seg_table_entries);
606
+
607
+ printf("\tSegment table offset:\t0x%04X\n", ne_offset + ne.seg_table_offset);
608
+ printf("\tResource table offset:\t0x%04X\n", ne_offset + ne.res_table_offset);
609
+ printf("\tResident name table:\t0x%04X\n", ne_offset + ne.res_name_table_offset);
610
+ printf("\tModule reference table:\t0x%04X\n", ne_offset + ne.mod_ref_table_offset);
611
+ printf("\tImported name table:\t0x%04X\n", ne_offset + ne.import_table_offset);
612
+ printf("\tNonResident name table:\t0x%04X\n", ne.non_res_name_table_offset);
613
+
614
+ printf(
615
+ "\tExecutable type:\t0x%02X (%s)\n\n",
616
+ (unsigned int)ne.exe_type,
617
+ (ne.exe_type == 0x02 ? "WINDOWS" : "UNKNOWN")
618
+ );
619
+ }
620
+
621
+ unsigned int segments_offset = ne_offset + ne.seg_table_offset, seg_num = 0;
622
+ struct segment_table seg;
623
+
624
+ struct import_entry *imports = NULL;
625
+
626
+ while(seg_num++ < ne.seg_table_entries && read_data((char*)&seg, segments_offset, sizeof(seg)) == sizeof(seg)) {
627
+ unsigned int seg_offset = seg.offset * (1 << ne.seg_sector_size_shift);
628
+
629
+ if(to_dump & DUMP_SEGMENTS) {
630
+ char flags[64] = "";
631
+
632
+ FLAG_CAT(flags, "CODE", (seg.flags & SEG_TYPE_MASK) == SEG_CODE);
633
+ FLAG_CAT(flags, "DATA", (seg.flags & SEG_TYPE_MASK) == SEG_DATA);
634
+ FLAG_CAT(flags, "MOVEABLE", seg.flags & SEG_MOVEABLE);
635
+ FLAG_CAT(flags, "PRELOAD", seg.flags & SEG_PRELOAD);
636
+ FLAG_CAT(flags, "RELOCINFO", seg.flags & SEG_RELOCINFO);
637
+ FLAG_CAT(flags, "DISCARD", seg.flags & SEG_DISCARD);
638
+
639
+ printf("Segment #%u:\n", seg_num);
640
+ printf("\tData offset:\t\t\t0x%04X\n", seg_offset);
641
+ printf("\tData length:\t\t\t0x%04X\n", (unsigned int)(seg.size ? seg.size : 65536));
642
+ printf("\tMinimum allocation size:\t0x%04X\n", (unsigned int)(seg.size ? seg.size : 65536));
643
+ printf("\tFlags:\t\t\t\t0x%04hX (%s)\n\n", seg.flags, flags);
644
+ }
645
+
646
+ segments_offset += sizeof(seg);
647
+
648
+ if(seg.flags & SEG_RELOCINFO) {
649
+ unsigned int reloc_offset = seg_offset + seg.size;
650
+ unsigned short num_records, i;
651
+
652
+ read_data((char*)&num_records, reloc_offset, 2);
653
+ reloc_offset += 2;
654
+
655
+ for(i = 0; i < num_records; i++) {
656
+ struct segment_reloc reloc;
657
+
658
+ read_data((char*)&reloc, reloc_offset, sizeof(reloc));
659
+
660
+ if(to_dump & DUMP_RELOCATION) {
661
+ unsigned short offset = reloc.offset;
662
+
663
+ char src_type[64] = "", flags[64] = "";
664
+
665
+ FLAG_CAT(src_type, "LOBYTE", reloc.src_type == RELOC_LOBYTE);
666
+ FLAG_CAT(src_type, "SEGMENT", reloc.src_type == RELOC_SEGMENT);
667
+ FLAG_CAT(src_type, "FAR_ADDR", reloc.src_type == RELOC_FAR_ADDR);
668
+ FLAG_CAT(src_type, "OFFSET", reloc.src_type == RELOC_OFFSET);
669
+
670
+ FLAG_CAT(flags, "INTERNALREF", reloc.flags & RELOC_INTERNALREF);
671
+ FLAG_CAT(flags, "IMPORTORDINAL", reloc.flags & RELOC_IMPORTORDINAL);
672
+ FLAG_CAT(flags, "IMPORTNAME", reloc.flags & RELOC_IMPORTNAME);
673
+ FLAG_CAT(flags, "OSFIXUP", reloc.flags & RELOC_OSFIXUP);
674
+
675
+ FLAG_CAT(flags, "ADDITIVE", reloc.flags & RELOC_ADDITIVE);
676
+
677
+ printf("Relocation entry for segment #%u at 0x%04hX:\n", seg_num, reloc_offset);
678
+ printf("\tSource type:\t\t0x%02X (%s)\n", (unsigned int)reloc.src_type, src_type);
679
+ printf("\tFlags:\t\t\t0x%02X (%s)\n", (unsigned int)reloc.flags, flags);
680
+
681
+ do {
682
+ printf("\tOffset within segment:\t0x%04hX\n", offset);
683
+ read_data((char*)&offset, seg_offset + offset, 2);
684
+ } while(!(reloc.flags & RELOC_ADDITIVE) && offset != 0xFFFF);
685
+
686
+ printf("\tTarget bytes:\t\t%02X %02X %02X %02X\n", (unsigned int)reloc.target_b[0], (unsigned int)reloc.target_b[1], (unsigned int)reloc.target_b[2], (unsigned int)reloc.target_b[3]);
687
+ printf("\tTarget words:\t\t%04hX %04hX\n", reloc.target_w[0], reloc.target_w[1]);
688
+
689
+ putchar('\n');
690
+ }
691
+
692
+ reloc_offset += sizeof(reloc);
693
+
694
+ struct import_table mod_name, import;
695
+
696
+ if(reloc.flags & (RELOC_IMPORTNAME | RELOC_IMPORTORDINAL)) {
697
+ unsigned short mod_offset;
698
+ read_data((char*)&mod_offset, ne_offset + ne.mod_ref_table_offset + (2 * (reloc.importordinal.mod_index - 1)), 2);
699
+
700
+ read_data((char*)&mod_name, ne_offset + ne.import_table_offset + mod_offset, sizeof(mod_name));
701
+ mod_name.name[mod_name.name_len] = '\0';
702
+ }
703
+
704
+ if(reloc.flags == RELOC_IMPORTNAME) {
705
+ read_data((char*)&import, ne_offset + ne.import_table_offset + reloc.importname.name_offset, sizeof(import));
706
+ import.name[import.name_len] = '\0';
707
+
708
+ add_import(&imports, mod_name.name, import.name, -1);
709
+ }
710
+
711
+ if(reloc.flags == RELOC_IMPORTORDINAL) {
712
+ add_import(&imports, mod_name.name, NULL, reloc.importordinal.ordinal);
713
+ }
714
+ }
715
+ }
716
+ }
717
+
718
+ if(to_dump & DUMP_RESIDENT) {
719
+ printf("Resident names table:\n");
720
+ dump_names(ne_offset + ne.res_name_table_offset, 0xFFFFFFFF, ne_offset + ne.entry_table_offset);
721
+ putchar('\n');
722
+ }
723
+
724
+ if(to_dump & DUMP_NONRES) {
725
+ printf("Non-Resident names table:\n");
726
+ dump_names(ne.non_res_name_table_offset, ne.non_res_name_table_entries, ne_offset + ne.entry_table_offset);
727
+ putchar('\n');
728
+ }
729
+
730
+ if(to_dump & DUMP_ENTRY) {
731
+ dump_ep_table(ne_offset + ne.entry_table_offset);
732
+ }
733
+
734
+ if(to_dump & DUMP_RESOURCE) {
735
+ dump_resources(ne_offset + ne.res_table_offset);
736
+ }
737
+
738
+ if(to_dump & DUMP_IMPORTS) {
739
+ dump_imports(imports);
740
+ }
741
+
742
+ free_imports(imports);
743
+ }else{
744
+ NOT_NE:
745
+ printf("Supplied file does not appear to be in NE format\n");
746
+ }
747
+
748
+ fclose(fh);
749
+
750
+ return 0;
751
+ }