pedump 0.4.10 → 0.4.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.10
1
+ 0.4.11
@@ -18,7 +18,8 @@ require 'pedump/ne/version_info'
18
18
  class PEdump
19
19
  attr_accessor :fname, :logger, :force, :io
20
20
 
21
- VERSION = Version::STRING
21
+ VERSION = Version::STRING
22
+ MAX_ERRORS = 100
22
23
 
23
24
  @@logger = nil
24
25
 
@@ -394,7 +395,11 @@ class PEdump
394
395
 
395
396
  # TODO: not all VirtualAdresses == 0 case
396
397
 
397
- logger.error "[?] can't find file_offset of VA 0x#{va.to_i.to_s(16)}" unless h[:quiet]
398
+ if h[:quiet]
399
+ logger.debug "[?] can't find file_offset of VA 0x#{va.to_i.to_s(16)} (quiet=true)"
400
+ else
401
+ logger.error "[?] can't find file_offset of VA 0x#{va.to_i.to_s(16)}"
402
+ end
398
403
  nil
399
404
  end
400
405
 
@@ -519,7 +524,12 @@ class PEdump
519
524
  logger.warn "[?] non-empty last IMAGE_IMPORT_DESCRIPTOR: #{t.inspect}" unless t.empty?
520
525
  @imports = r.each do |x|
521
526
  if x.Name.to_i != 0 && (ofs = va2file(x.Name))
527
+ begin
522
528
  f.seek ofs
529
+ rescue
530
+ logger.warn "[?] cannot seek to #{ofs} (VA=0x#{x.Name.to_i.to_s(16)} for reading imports, skipped"
531
+ next
532
+ end
523
533
  x.module_name = f.gets("\x00").to_s.chomp("\x00")
524
534
  end
525
535
  [:original_first_thunk, :first_thunk].each do |tbl|
@@ -680,7 +690,7 @@ class PEdump
680
690
  x.names[i] = f.gets("\x00").to_s.chomp("\x00")
681
691
  rescue
682
692
  nErrors += 1
683
- if nErrors > 100
693
+ if nErrors > MAX_ERRORS
684
694
  logger.warn "[?] too many errors getting export names, stopped on #{i} of #{x.names.size}"
685
695
  x.names = x.names[0,i]
686
696
  break
@@ -99,7 +99,15 @@ class PEdump
99
99
  h[:deep] = 1 if h[:deep] == true
100
100
  h[:deep] = 0 if h[:deep] == false
101
101
 
102
- f.seek(h[:ep_offset]) # offset of PE EntryPoint from start of file
102
+ begin
103
+ f.seek(h[:ep_offset]) # offset of PE EntryPoint from start of file
104
+ rescue
105
+ if h[:pedump] && h[:pedump].logger
106
+ h[:pedump].logger.warn "[?] failed to seek to EP at #{h[:ep_offset]}, skipping packer detect"
107
+ end
108
+ return
109
+ end
110
+
103
111
  r = Array(of_data(f.read(max_size)))
104
112
  return r if r && r.any? && h[:deep] < 2
105
113
  r += scan_whole_file(f,
@@ -267,6 +267,8 @@ class PEdump
267
267
  @@loopchk1 = Hash.new(0)
268
268
  @@loopchk2 = Hash.new(0)
269
269
  @@loopchk3 = Hash.new(0)
270
+ @@nErrors1 = 0
271
+ @@nErrors2 = 0
270
272
  elsif (@@loopchk1[f.tell] += 1) > 1
271
273
  PEdump.logger.error "[!] #{self}: loop1 detected at file pos #{f.tell}" if @@loopchk1[f.tell] < 2
272
274
  return nil
@@ -286,27 +288,39 @@ class PEdump
286
288
  r.entries << IMAGE_RESOURCE_DIRECTORY_ENTRY.read(f)
287
289
  end
288
290
  #r.entries.uniq!
289
- r.entries.each do |entry|
291
+ r.entries.each_with_index do |entry,idx|
290
292
  entry.name =
291
- if entry.Name.to_i & 0x8000_0000 > 0
293
+ if (entry.Name.to_i & 0x8000_0000 > 0) && f.checked_seek(base + entry.Name & 0x7fff_ffff)
292
294
  # Name is an address of unicode string
293
- f.seek base + entry.Name & 0x7fff_ffff
294
295
  nChars = f.read(2).to_s.unpack("v").first.to_i
295
296
  begin
296
297
  f.read(nChars*2).force_encoding('UTF-16LE').encode!('UTF-8')
297
298
  rescue
298
299
  PEdump.logger.error "[!] #{self} failed to read entry name: #{$!}"
300
+ if (@@nErrors1+=1) > MAX_ERRORS
301
+ PEdump.logger.warn "[?] too many errors getting resource names, stopped on #{idx} of #{r.entries.size}"
302
+ r.entries = r.entries[0,idx]
303
+ break
304
+
305
+ end
299
306
  "???"
300
307
  end
301
308
  else
302
309
  # Name is a numeric id
303
310
  "##{entry.Name}"
304
311
  end
305
- if entry.OffsetToData && f.checked_seek(base + entry.OffsetToData & 0x7fff_ffff)
306
- if (@@loopchk3[f.tell] += 1) > 1
312
+ if entry.OffsetToData
313
+ if (@@loopchk3[entry.OffsetToData] += 1) > 1
307
314
  PEdump.logger.error "[!] #{self}: loop3 detected at file pos #{f.tell}" if @@loopchk3[f.tell] < 2
315
+ if (@@nErrors2+=1) > MAX_ERRORS
316
+ PEdump.logger.warn "[?] too many errors getting resource data, stopped on #{idx} of #{r.entries.size}"
317
+ r.entries = r.entries[0,idx]
318
+ break
319
+
320
+ end
308
321
  next
309
322
  end
323
+ next unless f.checked_seek(base + entry.OffsetToData & 0x7fff_ffff)
310
324
  entry.data =
311
325
  if entry.OffsetToData & 0x8000_0000 > 0
312
326
  # child is a directory
@@ -326,7 +340,9 @@ class PEdump
326
340
  def _scan_pe_resources f=@io, dir=nil
327
341
  dir ||= resource_directory(f)
328
342
  return nil unless dir
329
- dir.entries.map do |entry|
343
+ @pe_res_errors ||= 0
344
+ r = []
345
+ dir.entries.each_with_index do |entry,idx|
330
346
  case entry.data
331
347
  when IMAGE_RESOURCE_DIRECTORY
332
348
  if dir == @resource_directory # root resource directory
@@ -337,32 +353,45 @@ class PEdump
337
353
  else
338
354
  entry.name
339
355
  end
340
- _scan_pe_resources(f,entry.data).each do |res|
356
+ r += _scan_pe_resources(f,entry.data).each do |res|
341
357
  res.type = entry_type
342
358
  res.parse f
343
359
  end
344
360
  else
345
- _scan_pe_resources(f,entry.data).each do |res|
361
+ r += _scan_pe_resources(f,entry.data).each do |res|
346
362
  res.name = res.name == "##{res.lang}" ? entry.name : "#{entry.name} / #{res.name}"
347
363
  res.id ||= entry.Name if entry.Name.is_a?(Numeric) && entry.Name < 0x8000_0000
348
364
  end
349
365
  end
350
366
  when IMAGE_RESOURCE_DATA_ENTRY
351
- Resource.new(
367
+ file_offset = va2file(entry.data.OffsetToData, :quiet => (@pe_res_errors > MAX_ERRORS))
368
+ unless file_offset
369
+ @pe_res_errors += 1
370
+ if @pe_res_errors > MAX_ERRORS
371
+ PEdump.logger.warn "[?] too many errors getting resource data, stopped on #{idx} of #{dir.entries.size}"
372
+ break
373
+ end
374
+ end
375
+ r << Resource.new(
352
376
  nil, # type
353
377
  entry.name,
354
378
  nil, # id
355
379
  entry.Name, # lang
356
380
  #entry.data.OffsetToData + @resource_data_base,
357
- va2file(entry.data.OffsetToData),
381
+ file_offset,
358
382
  entry.data.Size,
359
383
  entry.data.CodePage,
360
384
  entry.data.Reserved
361
385
  )
362
386
  else
363
- logger.error "[!] invalid resource entry: #{entry.data.inspect}"
364
- nil
387
+ if entry.data
388
+ logger.error "[!] invalid resource entry: #{entry.data.inspect}"
389
+ else
390
+ # show NULL entries only in verbose mode
391
+ logger.info "[!] invalid resource entry: #{entry.data.inspect}"
392
+ end
365
393
  end
366
- end.flatten.compact
394
+ end
395
+ r.flatten.compact
367
396
  end
368
397
  end
@@ -2,7 +2,7 @@ class PEdump
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 4
5
- PATCH = 10
5
+ PATCH = 11
6
6
  BUILD = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "pedump"
8
- s.version = "0.4.10"
8
+ s.version = "0.4.11"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Andrey \"Zed\" Zaikin"]
12
- s.date = "2012-12-10"
12
+ s.date = "2012-12-11"
13
13
  s.description = "dump headers, sections, extract resources of win32 PE exe,dll,etc"
14
14
  s.email = "zed.0xff@gmail.com"
15
15
  s.executables = ["pedump"]
@@ -59,6 +59,7 @@ Gem::Specification.new do |s|
59
59
  "misc/nedump.c",
60
60
  "pedump.gemspec",
61
61
  "spec/65535sects_spec.rb",
62
+ "spec/bad_imports_spec.rb",
62
63
  "spec/composite_io_spec.rb",
63
64
  "spec/dllord_spec.rb",
64
65
  "spec/foldedhdr_spec.rb",
@@ -0,0 +1,20 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/pedump')
3
+
4
+ describe 'bad_imports.exe' do
5
+ before :all do
6
+ @imports = sample.imports
7
+ end
8
+
9
+ it "should have IMAGE_IMPORT_DESCRIPTOR" do
10
+ @imports.size.should == 1
11
+ end
12
+
13
+ it "should have only IMAGE_IMPORT_DESCRIPTORs" do
14
+ @imports.map(&:class).uniq.should == [PEdump::IMAGE_IMPORT_DESCRIPTOR]
15
+ end
16
+
17
+ it "should not detect packer" do
18
+ sample.packer.should be_nil
19
+ end
20
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pedump
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.10
4
+ version: 0.4.11
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-10 00:00:00.000000000 Z
12
+ date: 2012-12-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multipart-post
@@ -189,6 +189,7 @@ files:
189
189
  - misc/nedump.c
190
190
  - pedump.gemspec
191
191
  - spec/65535sects_spec.rb
192
+ - spec/bad_imports_spec.rb
192
193
  - spec/composite_io_spec.rb
193
194
  - spec/dllord_spec.rb
194
195
  - spec/foldedhdr_spec.rb
@@ -221,7 +222,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
221
222
  version: '0'
222
223
  segments:
223
224
  - 0
224
- hash: 1643171094839400469
225
+ hash: -1370513960600577087
225
226
  required_rubygems_version: !ruby/object:Gem::Requirement
226
227
  none: false
227
228
  requirements: