pedump 0.5.4 → 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CODE_OF_CONDUCT.md +76 -0
- data/Gemfile +1 -2
- data/Gemfile.lock +25 -23
- data/README.md +104 -11
- data/Rakefile +41 -6
- data/VERSION +1 -1
- data/data/comp_id.txt +776 -0
- data/lib/pedump/cli.rb +144 -34
- data/lib/pedump/loader/section.rb +5 -3
- data/lib/pedump/loader.rb +28 -6
- data/lib/pedump/ne.rb +1 -1
- data/lib/pedump/pe.rb +63 -54
- data/lib/pedump/rich.rb +562 -0
- data/lib/pedump/te.rb +62 -0
- data/lib/pedump.rb +86 -18
- data/misc/aspack/aspack_unlzx.c +5 -3
- data/pedump.gemspec +20 -29
- metadata +12 -23
data/lib/pedump.rb
CHANGED
@@ -17,6 +17,7 @@ require 'pedump/security'
|
|
17
17
|
require 'pedump/packer'
|
18
18
|
require 'pedump/ne'
|
19
19
|
require 'pedump/ne/version_info'
|
20
|
+
require 'pedump/te'
|
20
21
|
|
21
22
|
# pedump.rb by zed_0xff
|
22
23
|
#
|
@@ -29,8 +30,9 @@ class PEdump
|
|
29
30
|
VERSION = Version::STRING
|
30
31
|
MAX_ERRORS = 100
|
31
32
|
MAX_IMAGE_IMPORT_DESCRIPTORS = 1000
|
32
|
-
MAX_EXPORT_NUMBER_OF_NAMES = 16384 # got 7977 in
|
33
|
+
MAX_EXPORT_NUMBER_OF_NAMES = 16384 # got 7977 in https://pedump.me/03ad7400080678c6b1984f995d36fd04
|
33
34
|
GOOD_FUNCTION_NAME_RE = /\A[\x21-\x7f]+\Z/
|
35
|
+
SUPPORTED_SIGNATURES = ['MZ', 'ZM', 'VZ']
|
34
36
|
|
35
37
|
@@logger = nil
|
36
38
|
|
@@ -259,7 +261,7 @@ class PEdump
|
|
259
261
|
|
260
262
|
# http://ntcore.com/files/richsign.htm
|
261
263
|
class RichHdr < String
|
262
|
-
attr_accessor :offset, :key # xor key
|
264
|
+
attr_accessor :offset, :skip, :key # xor key
|
263
265
|
|
264
266
|
class Entry < Struct.new(:version,:id,:times)
|
265
267
|
def inspect
|
@@ -268,8 +270,21 @@ class PEdump
|
|
268
270
|
end
|
269
271
|
|
270
272
|
def self.from_dos_stub stub
|
273
|
+
#stub.hexdump
|
271
274
|
key = stub[stub.index('Rich')+4,4]
|
272
275
|
start_idx = stub.index(key.xor('DanS'))
|
276
|
+
skip = 0
|
277
|
+
if start_idx
|
278
|
+
skip = 4
|
279
|
+
else
|
280
|
+
PEdump.logger.warn "[?] cannot find rich_hdr start_idx, using heuristics"
|
281
|
+
start_idx = stub.index("$\x00\x00\x00\x00\x00\x00\x00")
|
282
|
+
unless start_idx
|
283
|
+
PEdump.logger.warn "[?] heuristics failed :("
|
284
|
+
return nil
|
285
|
+
end
|
286
|
+
start_idx += 8
|
287
|
+
end
|
273
288
|
end_idx = stub.index('Rich')+8
|
274
289
|
if stub[end_idx..-1].tr("\x00",'') != ''
|
275
290
|
t = stub[end_idx..-1]
|
@@ -277,14 +292,16 @@ class PEdump
|
|
277
292
|
PEdump.logger.error "[!] non-zero dos stub after rich_hdr: #{t.inspect}"
|
278
293
|
return nil
|
279
294
|
end
|
295
|
+
#stub[start_idx, end_idx-start_idx].hexdump
|
280
296
|
RichHdr.new(stub[start_idx, end_idx-start_idx]).tap do |x|
|
281
297
|
x.key = key
|
282
298
|
x.offset = stub.offset + start_idx
|
299
|
+
x.skip = skip
|
283
300
|
end
|
284
301
|
end
|
285
302
|
|
286
303
|
def dexor
|
287
|
-
self[
|
304
|
+
self[skip..-9].sub(/\A(#{Regexp::escape(key)}){3}/,'').xor(key)
|
288
305
|
end
|
289
306
|
|
290
307
|
def decode
|
@@ -322,9 +339,9 @@ class PEdump
|
|
322
339
|
@mz ||= f && MZ.read(f).tap do |mz|
|
323
340
|
if mz.signature != 'MZ' && mz.signature != 'ZM'
|
324
341
|
if @force
|
325
|
-
logger.warn "[?] no MZ signature. want: 'MZ' or 'ZM', got: #{mz.signature.inspect}"
|
342
|
+
#logger.warn "[?] no MZ signature. want: 'MZ' or 'ZM', got: #{mz.signature.inspect}"
|
326
343
|
else
|
327
|
-
logger.error "[!] no MZ signature. want: 'MZ' or 'ZM', got: #{mz.signature.inspect}. (not forced)"
|
344
|
+
#logger.error "[!] no MZ signature. want: 'MZ' or 'ZM', got: #{mz.signature.inspect}. (not forced)"
|
328
345
|
return nil
|
329
346
|
end
|
330
347
|
end
|
@@ -380,6 +397,13 @@ class PEdump
|
|
380
397
|
def va2file va, h={}
|
381
398
|
return nil if va.nil?
|
382
399
|
|
400
|
+
va0 = va # save for log output of original addr
|
401
|
+
if pe?
|
402
|
+
# most common case, do nothing
|
403
|
+
elsif te?
|
404
|
+
va = va - te_shift()
|
405
|
+
end
|
406
|
+
|
383
407
|
sections.each do |s|
|
384
408
|
if (s.VirtualAddress...(s.VirtualAddress+s.VirtualSize)).include?(va)
|
385
409
|
offset = va - s.VirtualAddress
|
@@ -411,9 +435,9 @@ class PEdump
|
|
411
435
|
# TODO: not all VirtualAdresses == 0 case
|
412
436
|
|
413
437
|
if h[:quiet]
|
414
|
-
logger.debug "[?] can't find file_offset of VA 0x#{
|
438
|
+
logger.debug "[?] can't find file_offset of VA 0x#{va0.to_i.to_s(16)} (quiet=true)"
|
415
439
|
else
|
416
|
-
logger.error "[?] can't find file_offset of VA 0x#{
|
440
|
+
logger.error "[?] can't find file_offset of VA 0x#{va0.to_i.to_s(16)}"
|
417
441
|
end
|
418
442
|
nil
|
419
443
|
end
|
@@ -431,16 +455,22 @@ class PEdump
|
|
431
455
|
end
|
432
456
|
|
433
457
|
def _dump_handle h
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
458
|
+
if pe(h) # also calls mz(h)
|
459
|
+
rich_hdr h
|
460
|
+
resources h
|
461
|
+
imports h # also calls tls(h)
|
462
|
+
exports h
|
463
|
+
packer h
|
464
|
+
elsif te(h)
|
465
|
+
end
|
440
466
|
end
|
441
467
|
|
442
468
|
def data_directory f=@io
|
443
|
-
pe(f)
|
469
|
+
if pe(f)
|
470
|
+
pe.ioh && pe.ioh.DataDirectory
|
471
|
+
elsif te(f)
|
472
|
+
te.DataDirectory
|
473
|
+
end
|
444
474
|
end
|
445
475
|
|
446
476
|
def sections f=@io
|
@@ -448,16 +478,52 @@ class PEdump
|
|
448
478
|
pe.section_table
|
449
479
|
elsif ne(f)
|
450
480
|
ne.segments
|
481
|
+
elsif te(f)
|
482
|
+
te.sections
|
451
483
|
end
|
452
484
|
end
|
453
485
|
alias :section_table :sections
|
454
486
|
|
455
|
-
def
|
456
|
-
|
487
|
+
def supported_file? f=@io
|
488
|
+
pos = f.tell
|
489
|
+
sig = f.read(2)
|
490
|
+
f.seek(pos)
|
491
|
+
if SUPPORTED_SIGNATURES.include?(sig)
|
492
|
+
true
|
493
|
+
else
|
494
|
+
unless @not_supported_sig_warned
|
495
|
+
msg = "no supported signature. want: #{SUPPORTED_SIGNATURES.join("/")}, got: #{sig.inspect}"
|
496
|
+
if @force
|
497
|
+
logger.warn "[?] #{msg}"
|
498
|
+
else
|
499
|
+
logger.error "[!] #{msg}. (not forced)"
|
500
|
+
end
|
501
|
+
@not_supported_sig_warned = true
|
502
|
+
end
|
503
|
+
false
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
def _detect_format
|
508
|
+
return :pe if @pe
|
509
|
+
return :ne if @ne
|
510
|
+
return :te if @te
|
511
|
+
return :pe if pe()
|
512
|
+
return :ne if ne()
|
513
|
+
return :te if te()
|
514
|
+
nil
|
457
515
|
end
|
458
516
|
|
459
517
|
def pe?
|
460
|
-
|
518
|
+
_detect_format() == :pe
|
519
|
+
end
|
520
|
+
|
521
|
+
def ne?
|
522
|
+
_detect_format() == :ne
|
523
|
+
end
|
524
|
+
|
525
|
+
def te?
|
526
|
+
_detect_format() == :te
|
461
527
|
end
|
462
528
|
|
463
529
|
##############################################################################
|
@@ -502,6 +568,8 @@ class PEdump
|
|
502
568
|
pe_imports(f)
|
503
569
|
elsif ne(f)
|
504
570
|
ne(f).imports
|
571
|
+
else
|
572
|
+
[]
|
505
573
|
end
|
506
574
|
end
|
507
575
|
|
@@ -589,7 +657,7 @@ class PEdump
|
|
589
657
|
nil
|
590
658
|
else
|
591
659
|
hint = f.read(2).unpack('v').first
|
592
|
-
name = f.gets("\x00").chomp("\x00")
|
660
|
+
name = f.gets("\x00").to_s.chomp("\x00")
|
593
661
|
if !name.empty? && name !~ GOOD_FUNCTION_NAME_RE
|
594
662
|
n_bad_names += 1
|
595
663
|
if n_bad_names > MAX_ERRORS
|
data/misc/aspack/aspack_unlzx.c
CHANGED
@@ -30,6 +30,7 @@ int unpack(BYTE*packed_data, size_t packed_size, size_t unpacked_size){
|
|
30
30
|
LZX_CONTEXT LZX;
|
31
31
|
BYTE* unpacked_data = NULL;
|
32
32
|
size_t decoded_size;
|
33
|
+
int r;
|
33
34
|
|
34
35
|
bzero(&LZX, sizeof(LZX));
|
35
36
|
|
@@ -38,8 +39,9 @@ int unpack(BYTE*packed_data, size_t packed_size, size_t unpacked_size){
|
|
38
39
|
return(ERR_NO_MEM);
|
39
40
|
}
|
40
41
|
|
41
|
-
|
42
|
-
|
42
|
+
r = DecodeLZX(&LZX, packed_data, unpacked_data, packed_size, unpacked_size);
|
43
|
+
decoded_size = (size_t)r;
|
44
|
+
if ( r < 0 || decoded_size < unpacked_size ) {
|
43
45
|
free(unpacked_data);
|
44
46
|
fprintf(stderr,"ERR_UNPACK\n");
|
45
47
|
return(ERR_UNPACK);
|
@@ -58,7 +60,7 @@ int main(int argc, char*argv[]){
|
|
58
60
|
if(argc != 3){
|
59
61
|
fprintf(stderr, "ASPack unLZX\n");
|
60
62
|
fprintf(stderr, "usage: %s <packed_size> <unpacked_size>\n", argv[0]);
|
61
|
-
fprintf(stderr, "(data is read from stdin and written to stdout)\n"
|
63
|
+
fprintf(stderr, "(data is read from stdin and written to stdout)\n");
|
62
64
|
return 1;
|
63
65
|
}
|
64
66
|
|
data/pedump.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: pedump 0.
|
5
|
+
# stub: pedump 0.6.3 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "pedump".freeze
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.6.3"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["Andrey \"Zed\" Zaikin".freeze]
|
14
|
-
s.date = "
|
14
|
+
s.date = "2021-12-07"
|
15
15
|
s.description = "dump headers, sections, extract resources of win32 PE exe,dll,etc".freeze
|
16
16
|
s.email = "zed.0xff@gmail.com".freeze
|
17
17
|
s.executables = ["pedump".freeze]
|
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
"README.md"
|
21
21
|
]
|
22
22
|
s.files = [
|
23
|
+
"CODE_OF_CONDUCT.md",
|
23
24
|
"Gemfile",
|
24
25
|
"Gemfile.lock",
|
25
26
|
"LICENSE.txt",
|
@@ -27,6 +28,7 @@ Gem::Specification.new do |s|
|
|
27
28
|
"Rakefile",
|
28
29
|
"VERSION",
|
29
30
|
"bin/pedump",
|
31
|
+
"data/comp_id.txt",
|
30
32
|
"data/fs.txt",
|
31
33
|
"data/jc-userdb.txt",
|
32
34
|
"data/sig.bin",
|
@@ -47,8 +49,10 @@ Gem::Specification.new do |s|
|
|
47
49
|
"lib/pedump/packer.rb",
|
48
50
|
"lib/pedump/pe.rb",
|
49
51
|
"lib/pedump/resources.rb",
|
52
|
+
"lib/pedump/rich.rb",
|
50
53
|
"lib/pedump/security.rb",
|
51
54
|
"lib/pedump/sig_parser.rb",
|
55
|
+
"lib/pedump/te.rb",
|
52
56
|
"lib/pedump/tls.rb",
|
53
57
|
"lib/pedump/unpacker.rb",
|
54
58
|
"lib/pedump/unpacker/aspack.rb",
|
@@ -64,45 +68,32 @@ Gem::Specification.new do |s|
|
|
64
68
|
]
|
65
69
|
s.homepage = "http://github.com/zed-0xff/pedump".freeze
|
66
70
|
s.licenses = ["MIT".freeze]
|
67
|
-
s.rubygems_version = "2.
|
71
|
+
s.rubygems_version = "3.2.22".freeze
|
68
72
|
s.summary = "dump win32 PE executable files with a pure ruby".freeze
|
69
73
|
|
70
74
|
if s.respond_to? :specification_version then
|
71
75
|
s.specification_version = 4
|
76
|
+
end
|
72
77
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
s.add_development_dependency(%q<jeweler>.freeze, ["~> 2.3.9"])
|
84
|
-
else
|
85
|
-
s.add_dependency(%q<rainbow>.freeze, [">= 0"])
|
86
|
-
s.add_dependency(%q<awesome_print>.freeze, [">= 0"])
|
87
|
-
s.add_dependency(%q<iostruct>.freeze, [">= 0.0.4"])
|
88
|
-
s.add_dependency(%q<multipart-post>.freeze, [">= 2.0.0"])
|
89
|
-
s.add_dependency(%q<progressbar>.freeze, [">= 0"])
|
90
|
-
s.add_dependency(%q<zhexdump>.freeze, [">= 0.0.2"])
|
91
|
-
s.add_dependency(%q<rspec>.freeze, ["~> 3.9.0"])
|
92
|
-
s.add_dependency(%q<rspec-its>.freeze, ["~> 1.3.0"])
|
93
|
-
s.add_dependency(%q<bundler>.freeze, ["~> 2.1.4"])
|
94
|
-
s.add_dependency(%q<jeweler>.freeze, ["~> 2.3.9"])
|
95
|
-
end
|
78
|
+
if s.respond_to? :add_runtime_dependency then
|
79
|
+
s.add_runtime_dependency(%q<rainbow>.freeze, [">= 0"])
|
80
|
+
s.add_runtime_dependency(%q<awesome_print>.freeze, [">= 0"])
|
81
|
+
s.add_runtime_dependency(%q<iostruct>.freeze, [">= 0.0.4"])
|
82
|
+
s.add_runtime_dependency(%q<multipart-post>.freeze, [">= 2.0.0"])
|
83
|
+
s.add_runtime_dependency(%q<zhexdump>.freeze, [">= 0.0.2"])
|
84
|
+
s.add_development_dependency(%q<rspec>.freeze, ["~> 3.9.0"])
|
85
|
+
s.add_development_dependency(%q<rspec-its>.freeze, ["~> 1.3.0"])
|
86
|
+
s.add_development_dependency(%q<bundler>.freeze, ["~> 2.2.3"])
|
87
|
+
s.add_development_dependency(%q<jeweler>.freeze, ["~> 2.3.9"])
|
96
88
|
else
|
97
89
|
s.add_dependency(%q<rainbow>.freeze, [">= 0"])
|
98
90
|
s.add_dependency(%q<awesome_print>.freeze, [">= 0"])
|
99
91
|
s.add_dependency(%q<iostruct>.freeze, [">= 0.0.4"])
|
100
92
|
s.add_dependency(%q<multipart-post>.freeze, [">= 2.0.0"])
|
101
|
-
s.add_dependency(%q<progressbar>.freeze, [">= 0"])
|
102
93
|
s.add_dependency(%q<zhexdump>.freeze, [">= 0.0.2"])
|
103
94
|
s.add_dependency(%q<rspec>.freeze, ["~> 3.9.0"])
|
104
95
|
s.add_dependency(%q<rspec-its>.freeze, ["~> 1.3.0"])
|
105
|
-
s.add_dependency(%q<bundler>.freeze, ["~> 2.
|
96
|
+
s.add_dependency(%q<bundler>.freeze, ["~> 2.2.3"])
|
106
97
|
s.add_dependency(%q<jeweler>.freeze, ["~> 2.3.9"])
|
107
98
|
end
|
108
99
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pedump
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrey "Zed" Zaikin
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rainbow
|
@@ -66,20 +66,6 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 2.0.0
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: progressbar
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :runtime
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
70
|
name: zhexdump
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,14 +114,14 @@ dependencies:
|
|
128
114
|
requirements:
|
129
115
|
- - "~>"
|
130
116
|
- !ruby/object:Gem::Version
|
131
|
-
version: 2.
|
117
|
+
version: 2.2.3
|
132
118
|
type: :development
|
133
119
|
prerelease: false
|
134
120
|
version_requirements: !ruby/object:Gem::Requirement
|
135
121
|
requirements:
|
136
122
|
- - "~>"
|
137
123
|
- !ruby/object:Gem::Version
|
138
|
-
version: 2.
|
124
|
+
version: 2.2.3
|
139
125
|
- !ruby/object:Gem::Dependency
|
140
126
|
name: jeweler
|
141
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -159,6 +145,7 @@ extra_rdoc_files:
|
|
159
145
|
- LICENSE.txt
|
160
146
|
- README.md
|
161
147
|
files:
|
148
|
+
- CODE_OF_CONDUCT.md
|
162
149
|
- Gemfile
|
163
150
|
- Gemfile.lock
|
164
151
|
- LICENSE.txt
|
@@ -166,6 +153,7 @@ files:
|
|
166
153
|
- Rakefile
|
167
154
|
- VERSION
|
168
155
|
- bin/pedump
|
156
|
+
- data/comp_id.txt
|
169
157
|
- data/fs.txt
|
170
158
|
- data/jc-userdb.txt
|
171
159
|
- data/sig.bin
|
@@ -186,8 +174,10 @@ files:
|
|
186
174
|
- lib/pedump/packer.rb
|
187
175
|
- lib/pedump/pe.rb
|
188
176
|
- lib/pedump/resources.rb
|
177
|
+
- lib/pedump/rich.rb
|
189
178
|
- lib/pedump/security.rb
|
190
179
|
- lib/pedump/sig_parser.rb
|
180
|
+
- lib/pedump/te.rb
|
191
181
|
- lib/pedump/tls.rb
|
192
182
|
- lib/pedump/unpacker.rb
|
193
183
|
- lib/pedump/unpacker/aspack.rb
|
@@ -204,7 +194,7 @@ homepage: http://github.com/zed-0xff/pedump
|
|
204
194
|
licenses:
|
205
195
|
- MIT
|
206
196
|
metadata: {}
|
207
|
-
post_install_message:
|
197
|
+
post_install_message:
|
208
198
|
rdoc_options: []
|
209
199
|
require_paths:
|
210
200
|
- lib
|
@@ -219,9 +209,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
219
209
|
- !ruby/object:Gem::Version
|
220
210
|
version: '0'
|
221
211
|
requirements: []
|
222
|
-
|
223
|
-
|
224
|
-
signing_key:
|
212
|
+
rubygems_version: 3.2.22
|
213
|
+
signing_key:
|
225
214
|
specification_version: 4
|
226
215
|
summary: dump win32 PE executable files with a pure ruby
|
227
216
|
test_files: []
|