pedump 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +90 -0
- data/LICENSE.txt +20 -0
- data/README.md +410 -0
- data/Rakefile +179 -0
- data/VERSION +1 -0
- data/bin/pedump +7 -0
- data/data/fs.txt +224 -0
- data/data/jc-userdb.txt +14371 -0
- data/data/sig.bin +0 -0
- data/data/signatures.txt +678 -0
- data/data/userdb.txt +14083 -0
- data/lib/pedump.rb +868 -0
- data/lib/pedump/cli.rb +804 -0
- data/lib/pedump/comparer.rb +147 -0
- data/lib/pedump/composite_io.rb +56 -0
- data/lib/pedump/core.rb +38 -0
- data/lib/pedump/core_ext/try.rb +57 -0
- data/lib/pedump/loader.rb +393 -0
- data/lib/pedump/loader/minidump.rb +351 -0
- data/lib/pedump/loader/section.rb +57 -0
- data/lib/pedump/logger.rb +67 -0
- data/lib/pedump/ne.rb +425 -0
- data/lib/pedump/ne/version_info.rb +171 -0
- data/lib/pedump/packer.rb +173 -0
- data/lib/pedump/pe.rb +121 -0
- data/lib/pedump/resources.rb +436 -0
- data/lib/pedump/security.rb +58 -0
- data/lib/pedump/sig_parser.rb +507 -0
- data/lib/pedump/tls.rb +17 -0
- data/lib/pedump/unpacker.rb +26 -0
- data/lib/pedump/unpacker/aspack.rb +858 -0
- data/lib/pedump/unpacker/upx.rb +13 -0
- data/lib/pedump/version.rb +10 -0
- data/lib/pedump/version_info.rb +171 -0
- data/misc/aspack/Makefile +3 -0
- data/misc/aspack/aspack_unlzx.c +92 -0
- data/misc/aspack/lzxdec.c +479 -0
- data/misc/aspack/lzxdec.h +56 -0
- data/misc/nedump.c +751 -0
- data/pedump.gemspec +109 -0
- metadata +227 -0
@@ -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_ */
|
data/misc/nedump.c
ADDED
@@ -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
|
+
}
|