pedump 0.4.10 → 0.4.11

Sign up to get free protection for your applications and to get access to all the features.
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: