pedump 0.5.4 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
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 http://pedump.me/03ad7400080678c6b1984f995d36fd04
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[4..-9].sub(/\A(#{Regexp::escape(key)}){3}/,'').xor(key)
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#{va.to_i.to_s(16)} (quiet=true)"
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#{va.to_i.to_s(16)}"
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
- return unless pe(h) # also calls mz(h)
435
- rich_hdr h
436
- resources h
437
- imports h # also calls tls(h)
438
- exports h
439
- packer h
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) && pe.ioh && pe.ioh.DataDirectory
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 ne?
456
- @pe ? false : (@ne ? true : (pe ? false : (ne ? true : false)))
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
- @pe ? true : (@ne ? false : (pe ? true : false ))
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
@@ -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
- decoded_size = DecodeLZX(&LZX, packed_data, unpacked_data, packed_size, unpacked_size);
42
- if ( decoded_size < 0 || decoded_size < unpacked_size ) {
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", argv[0]);
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.4 ruby lib
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.5.4"
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 = "2020-01-25"
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.7.10".freeze
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
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
74
- s.add_runtime_dependency(%q<rainbow>.freeze, [">= 0"])
75
- s.add_runtime_dependency(%q<awesome_print>.freeze, [">= 0"])
76
- s.add_runtime_dependency(%q<iostruct>.freeze, [">= 0.0.4"])
77
- s.add_runtime_dependency(%q<multipart-post>.freeze, [">= 2.0.0"])
78
- s.add_runtime_dependency(%q<progressbar>.freeze, [">= 0"])
79
- s.add_runtime_dependency(%q<zhexdump>.freeze, [">= 0.0.2"])
80
- s.add_development_dependency(%q<rspec>.freeze, ["~> 3.9.0"])
81
- s.add_development_dependency(%q<rspec-its>.freeze, ["~> 1.3.0"])
82
- s.add_development_dependency(%q<bundler>.freeze, ["~> 2.1.4"])
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.1.4"])
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.5.4
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: 2020-01-25 00:00:00.000000000 Z
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.1.4
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.1.4
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
- rubyforge_project:
223
- rubygems_version: 2.7.10
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: []