pedump 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -98,6 +98,17 @@ namespace :test do
98
98
  end
99
99
  end
100
100
  end
101
+
102
+ desc "test on corkami binaries"
103
+ task :corkami do
104
+ require './lib/pedump'
105
+ require './lib/pedump/cli'
106
+ path = "samples/corkami"
107
+ `find #{path} -type f`.split("\n").each do |fname|
108
+ STDERR.puts "\n### #{fname}\n"
109
+ PEdump::CLI.new(fname).run
110
+ end
111
+ end
101
112
  end
102
113
 
103
114
  def check_file url
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.2
1
+ 0.4.3
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'logger'
3
+ require 'stringio'
4
+ require 'pedump/composite_io'
5
+ require 'pedump/pe'
3
6
  require 'pedump/version'
4
7
 
5
8
  # pedump.rb by zed_0xff
@@ -135,22 +138,6 @@ class PEdump
135
138
  :lfanew
136
139
  )
137
140
 
138
- class PE < Struct.new(
139
- :signature, # "PE\x00\x00"
140
- :image_file_header,
141
- :image_optional_header,
142
- :section_table
143
- )
144
- alias :ifh :image_file_header
145
- alias :ioh :image_optional_header
146
- def x64?
147
- ifh && ifh.Machine == 0x8664
148
- end
149
- def dll?
150
- ifh && ifh.flags.include?('DLL')
151
- end
152
- end
153
-
154
141
  # http://msdn.microsoft.com/en-us/library/ms809762.aspx
155
142
  class IMAGE_FILE_HEADER < create_struct( 'v2V3v2',
156
143
  :Machine, # w
@@ -307,6 +294,7 @@ class PEdump
307
294
  )
308
295
  class IMAGE_SECTION_HEADER
309
296
  alias :flags :Characteristics
297
+ alias :va :VirtualAddress
310
298
  def flags_desc
311
299
  r = ''
312
300
  f = self.flags.to_i
@@ -455,54 +443,7 @@ class PEdump
455
443
  nil
456
444
  else
457
445
  f.seek pe_offset
458
- pe_sig = f.read 4
459
- logger.error "[!] 'NE' format is not supported!" if pe_sig == "NE\x00\x00"
460
- if pe_sig != "PE\x00\x00"
461
- if @force
462
- logger.warn "[?] no PE signature (want: 'PE\\x00\\x00', got: #{pe_sig.inspect})"
463
- else
464
- logger.error "[?] no PE signature (want: 'PE\\x00\\x00', got: #{pe_sig.inspect}). (not forced)"
465
- return nil
466
- end
467
- end
468
- PE.new(pe_sig).tap do |pe|
469
- pe.image_file_header = IMAGE_FILE_HEADER.read(f)
470
- if pe.ifh.SizeOfOptionalHeader > 0
471
- if pe.x64?
472
- pe.image_optional_header = IMAGE_OPTIONAL_HEADER64.read(f, pe.ifh.SizeOfOptionalHeader)
473
- else
474
- pe.image_optional_header = IMAGE_OPTIONAL_HEADER32.read(f, pe.ifh.SizeOfOptionalHeader)
475
- end
476
- end
477
-
478
- if (nToRead=pe.ifh.NumberOfSections) > 0xffff
479
- if @force.is_a?(Numeric) && @force > 1
480
- logger.warn "[!] too many sections (#{pe.ifh.NumberOfSections}). forced. reading all"
481
- else
482
- logger.warn "[!] too many sections (#{pe.ifh.NumberOfSections}). not forced, reading first 65535"
483
- nToRead = 65535
484
- end
485
- end
486
- pe.section_table = []
487
- nToRead.times do
488
- break if f.eof?
489
- pe.section_table << IMAGE_SECTION_HEADER.read(f)
490
- end
491
-
492
- # if pe.section_table.empty?
493
- # pe.section_table << IMAGE_SECTION_HEADER.new("")
494
- # logger.warn "[?] no sections, appending empty one"
495
- # end
496
-
497
- if pe.section_table.any?
498
- # zero all missing values of last section
499
- pe.section_table.last.tap do |last_section|
500
- last_section.each_pair do |k,v|
501
- last_section[k] = 0 if v.nil?
502
- end
503
- end
504
- end
505
- end
446
+ PE.read f, :force => @force
506
447
  end
507
448
  end
508
449
  end
@@ -591,7 +532,12 @@ class PEdump
591
532
  ImportedFunction.new(nil,nil,t & (2**(bits-1)-1)) # 0x7fff_ffff(_ffff_ffff)
592
533
  elsif va=va2file(t)
593
534
  f.seek va
594
- ImportedFunction.new(f.read(2).unpack('v').first, f.gets("\x00").chop)
535
+ if f.eof?
536
+ logger.warn "[?] import va 0x#{va.to_s(16)} beyond EOF"
537
+ nil
538
+ else
539
+ ImportedFunction.new(f.read(2).unpack('v').first, f.gets("\x00").chop)
540
+ end
595
541
  else
596
542
  nil
597
543
  end
@@ -632,34 +578,65 @@ class PEdump
632
578
  return @exports if @exports
633
579
  return nil unless pe(f) && pe(f).ioh && f
634
580
  dir = @pe.ioh.DataDirectory[IMAGE_DATA_DIRECTORY::EXPORT]
635
- return [] if !dir || (dir.va == 0 && dir.size == 0)
581
+ return nil if !dir || (dir.va == 0 && dir.size == 0)
636
582
  va = @pe.ioh.DataDirectory[IMAGE_DATA_DIRECTORY::EXPORT].va
637
583
  file_offset = va2file(va)
638
584
  return nil unless file_offset
639
585
  f.seek file_offset
586
+ if f.eof?
587
+ logger.info "[?] exports info beyond EOF"
588
+ return nil
589
+ end
640
590
  @exports = IMAGE_EXPORT_DIRECTORY.read(f).tap do |x|
641
591
  x.entry_points = []
642
592
  x.name_ordinals = []
643
593
  x.names = []
644
594
  if x.Name.to_i != 0 && (va = va2file(x.Name))
645
595
  f.seek va
646
- x.name = f.gets("\x00").chop
596
+ if f.eof?
597
+ logger.warn "[?] export va 0x#{va.to_s(16)} beyond EOF"
598
+ nil
599
+ else
600
+ x.name = f.gets("\x00").chomp("\x00")
601
+ end
647
602
  end
648
603
  if x.NumberOfFunctions.to_i != 0
649
604
  if x.AddressOfFunctions.to_i !=0 && (va = va2file(x.AddressOfFunctions))
650
605
  f.seek va
651
- x.entry_points = f.read(x.NumberOfFunctions*4).unpack('V*')
606
+ x.entry_points = []
607
+ x.NumberOfFunctions.times do
608
+ if f.eof?
609
+ logger.warn "[?] got EOF while reading exports entry_points"
610
+ break
611
+ end
612
+ x.entry_points << f.read(4).unpack('V').first
613
+ end
652
614
  end
653
615
  if x.AddressOfNameOrdinals.to_i !=0 && (va = va2file(x.AddressOfNameOrdinals))
654
616
  f.seek va
655
- x.name_ordinals = f.read(x.NumberOfNames*2).unpack('v*').map{ |o| o+x.Base }
617
+ x.name_ordinals = []
618
+ x.NumberOfNames.times do
619
+ if f.eof?
620
+ logger.warn "[?] got EOF while reading exports name_ordinals"
621
+ break
622
+ end
623
+ x.name_ordinals << f.read(2).unpack('v').first + x.Base
624
+ end
656
625
  end
657
626
  end
658
627
  if x.NumberOfNames.to_i != 0 && x.AddressOfNames.to_i !=0 && (va = va2file(x.AddressOfNames))
659
628
  f.seek va
660
- x.names = f.read(x.NumberOfNames*4).unpack('V*').map do |va|
629
+ x.names = []
630
+ x.NumberOfNames.times do
631
+ if f.eof?
632
+ logger.warn "[?] got EOF while reading exports names"
633
+ break
634
+ end
635
+ x.names << f.read(4).unpack('V').first
636
+ end
637
+ x.names.map! do |va|
661
638
  f.seek va2file(va)
662
- f.gets("\x00").chop
639
+ f.gets("\x00").to_s.chomp("\x00")
663
640
  end
664
641
  end
665
642
  end
@@ -746,6 +723,8 @@ class PEdump
746
723
  :OffsetToData, :Size, :CodePage, :Reserved
747
724
 
748
725
  def va2file va
726
+ return nil if va.nil?
727
+
749
728
  sections.each do |s|
750
729
  if (s.VirtualAddress...(s.VirtualAddress+s.VirtualSize)).include?(va)
751
730
  return va - s.VirtualAddress + s.PointerToRawData
@@ -486,8 +486,8 @@ class PEdump::CLI
486
486
  data.name.inspect,
487
487
  data.Characteristics.to_i,
488
488
  Time.at(data.TimeDateStamp.to_i).utc.strftime('"%Y-%m-%d %H:%M:%S"'),
489
- data.MajorVersion, data.MinorVersion,
490
- data.Base
489
+ data.MajorVersion.to_i, data.MinorVersion.to_i,
490
+ data.Base.to_i
491
491
 
492
492
  if @options[:verbose] > 0
493
493
  [%w'Names', %w'EntryPoints Functions', %w'Ordinals NameOrdinals'].each do |x|
@@ -498,25 +498,26 @@ class PEdump::CLI
498
498
  end
499
499
 
500
500
  printf "# nFuncs=%d nNames=%d\n",
501
- data.NumberOfFunctions,
502
- data.NumberOfNames
501
+ data.NumberOfFunctions.to_i,
502
+ data.NumberOfNames.to_i
503
503
 
504
504
  return unless data.name_ordinals.any? || data.entry_points.any? || data.names.any?
505
505
 
506
506
  puts
507
507
 
508
508
  ord2name = {}
509
- data.NumberOfNames.times do |i|
510
- ord2name[data.name_ordinals[i]] ||= []
511
- ord2name[data.name_ordinals[i]] << data.names[i]
509
+ if data.names && data.names.any?
510
+ data.NumberOfNames.times do |i|
511
+ ord2name[data.name_ordinals[i]] ||= []
512
+ ord2name[data.name_ordinals[i]] << data.names[i]
513
+ end
512
514
  end
513
515
 
514
516
  printf "%5s %8s %s\n", "ORD", "ENTRY_VA", "NAME"
515
- data.NumberOfFunctions.times do |i|
516
- ep = data.entry_points[i]
517
+ data.entry_points.each_with_index do |ep,i|
517
518
  names = ord2name[i+data.Base].try(:join,', ')
518
519
  next if ep.to_i == 0 && names.nil?
519
- printf "%5d %8x %s\n", i + data.Base, ep, names
520
+ printf "%5x %8x %s\n", i + data.Base, ep, names
520
521
  end
521
522
  end
522
523
 
@@ -0,0 +1,33 @@
1
+ class PEdump
2
+ class CompositeIO
3
+ def initialize(*ios)
4
+ @ios = ios.flatten
5
+ @pos = 0
6
+ end
7
+
8
+ def read(amount = nil, buf = nil)
9
+ buf ||= ''; buf1 = ''
10
+
11
+ # truncates buffer to zero length if nothing read
12
+ @ios.first.read(amount,buf)
13
+
14
+ @ios[1..-1].each do |io|
15
+ break if amount && buf.size >= amount
16
+ io.read(amount ? (amount-buf.size) : nil, buf1)
17
+ buf << buf1
18
+ end
19
+
20
+ @pos += buf.size
21
+
22
+ buf.size > 0 ? buf : (amount ? nil : buf )
23
+ end
24
+
25
+ def tell
26
+ @pos
27
+ end
28
+
29
+ def eof?
30
+ @ios.all?(&:eof?)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,89 @@
1
+ class PEdump
2
+ class PE < Struct.new(
3
+ :signature, # "PE\x00\x00"
4
+ :image_file_header,
5
+ :image_optional_header, # includes data directory
6
+ :section_table
7
+ )
8
+ alias :ifh :image_file_header
9
+ alias :ioh :image_optional_header
10
+ alias :sections :section_table
11
+ alias :sections= :section_table=
12
+ def x64?
13
+ ifh && ifh.Machine == 0x8664
14
+ end
15
+ def dll?
16
+ ifh && ifh.flags.include?('DLL')
17
+ end
18
+
19
+
20
+ def self.read f, args = nil
21
+ force = args.is_a?(Hash) && args[:force]
22
+
23
+ pe_offset = f.tell
24
+ pe_sig = f.read 4
25
+ logger.error "[!] 'NE' format is not supported!" if pe_sig == "NE\x00\x00"
26
+ if pe_sig != "PE\x00\x00"
27
+ if force
28
+ logger.warn "[?] no PE signature (want: 'PE\\x00\\x00', got: #{pe_sig.inspect})"
29
+ else
30
+ logger.error "[?] no PE signature (want: 'PE\\x00\\x00', got: #{pe_sig.inspect}). (not forced)"
31
+ return nil
32
+ end
33
+ end
34
+ PE.new(pe_sig).tap do |pe|
35
+ pe.image_file_header = IMAGE_FILE_HEADER.read(f)
36
+ if pe.ifh.SizeOfOptionalHeader > 0
37
+ if pe.x64?
38
+ pe.image_optional_header = IMAGE_OPTIONAL_HEADER64.read(f, pe.ifh.SizeOfOptionalHeader)
39
+ else
40
+ pe.image_optional_header = IMAGE_OPTIONAL_HEADER32.read(f, pe.ifh.SizeOfOptionalHeader)
41
+ end
42
+ end
43
+
44
+ if (nToRead=pe.ifh.NumberOfSections) > 0xffff
45
+ if force.is_a?(Numeric) && force > 1
46
+ logger.warn "[!] too many sections (#{pe.ifh.NumberOfSections}). forced. reading all"
47
+ else
48
+ logger.warn "[!] too many sections (#{pe.ifh.NumberOfSections}). not forced, reading first 65535"
49
+ nToRead = 65535
50
+ end
51
+ end
52
+ pe.sections = []
53
+ nToRead.times do
54
+ break if f.eof?
55
+ pe.sections << IMAGE_SECTION_HEADER.read(f)
56
+ end
57
+
58
+ if pe.sections.any?
59
+ # zero all missing values of last section
60
+ pe.sections.last.tap do |last_section|
61
+ last_section.each_pair do |k,v|
62
+ last_section[k] = 0 if v.nil?
63
+ end
64
+ end
65
+ end
66
+
67
+ pe_end = f.tell
68
+ if s=pe.sections.find{ |s| (pe_offset...pe_end).include?(s.va) }
69
+ if !f.respond_to?(:seek)
70
+ # already called with CompositeIO ?
71
+ logger.error "[!] section with va=0x#{s.va.to_s(16)} overwrites PE header! 2nd time?!"
72
+
73
+ elsif pe_end-pe_offset < 0x100_000
74
+ logger.warn "[!] section with va=0x#{s.va.to_s(16)} overwrites PE header! trying to rebuild..."
75
+ f.seek pe_offset
76
+ data = f.read(s.va-pe_offset)
77
+ f.seek s.PointerToRawData
78
+ io = CompositeIO.new(StringIO.new(data), f)
79
+ return PE.read(io, args)
80
+ else
81
+ logger.error "[!] section with va=0x#{s.va.to_s(16)} overwrites PE header! too big to rebuild!"
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ def self.logger; PEdump.logger; end
88
+ end
89
+ end
@@ -2,7 +2,7 @@ class PEdump
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 4
5
- PATCH = 2
5
+ PATCH = 3
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.2"
8
+ s.version = "0.4.3"
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 = "2011-12-19"
12
+ s.date = "2011-12-20"
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"]
@@ -35,17 +35,20 @@ Gem::Specification.new do |s|
35
35
  "data/userdb.txt",
36
36
  "lib/pedump.rb",
37
37
  "lib/pedump/cli.rb",
38
+ "lib/pedump/composite_io.rb",
38
39
  "lib/pedump/packer.rb",
40
+ "lib/pedump/pe.rb",
39
41
  "lib/pedump/sig_parser.rb",
40
42
  "lib/pedump/version.rb",
41
43
  "lib/pedump/version_info.rb",
42
44
  "pedump.gemspec",
43
- "samples/65535sects.7z",
44
45
  "samples/calc.7z",
45
- "samples/imports_badterm.exe",
46
- "samples/imports_vterm.exe",
46
+ "samples/corkami.7z",
47
47
  "samples/zlib.dll",
48
48
  "spec/65535sects_spec.rb",
49
+ "spec/composite_io_spec.rb",
50
+ "spec/dllord_spec.rb",
51
+ "spec/foldedhdr_spec.rb",
49
52
  "spec/imports_badterm_spec.rb",
50
53
  "spec/imports_vterm_spec.rb",
51
54
  "spec/pe_spec.rb",
@@ -53,7 +56,8 @@ Gem::Specification.new do |s|
53
56
  "spec/resource_spec.rb",
54
57
  "spec/sig_all_packers_spec.rb",
55
58
  "spec/sig_spec.rb",
56
- "spec/spec_helper.rb"
59
+ "spec/spec_helper.rb",
60
+ "spec/virtsectblXP_spec.rb"
57
61
  ]
58
62
  s.homepage = "http://github.com/zed-0xff/pedump"
59
63
  s.licenses = ["MIT"]
Binary file
@@ -1,16 +1,8 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
  require File.expand_path(File.dirname(__FILE__) + '/../lib/pedump')
3
3
 
4
- describe 'a PE file with 65535 sections' do
5
- before :all do
6
- fname = File.expand_path(File.dirname(__FILE__) + '/../samples/65535sects.exe')
7
- File.open(fname,"rb") do |f|
8
- @pedump = PEdump.new(fname)
9
- @sections = @pedump.sections(f)
10
- end
11
- end
12
-
4
+ describe 'corkami/65535sects.exe' do
13
5
  it "should have 65535 sections" do
14
- @sections.size.should == 65535
6
+ sample.sections.size.should == 65535
15
7
  end
16
8
  end
@@ -0,0 +1,72 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/pedump/composite_io')
3
+
4
+ describe PEdump::CompositeIO do
5
+ it "concatenates" do
6
+ io = PEdump::CompositeIO.new(
7
+ StringIO.new('foo'),
8
+ StringIO.new('bar'),
9
+ StringIO.new('baz')
10
+ )
11
+ io.read.should == 'foobarbaz'
12
+ end
13
+
14
+ it "reads sequentally" do
15
+ io = PEdump::CompositeIO.new(
16
+ StringIO.new('foo1'),
17
+ StringIO.new('bar2'),
18
+ StringIO.new('baz')
19
+ )
20
+ io.read(3).should == 'foo'
21
+ io.read(3).should == '1ba'
22
+ io.read(3).should == 'r2b'
23
+ io.read(3).should == 'az'
24
+ end
25
+
26
+ it "behaves like StringIO" do
27
+ io1 = StringIO.new('foo')
28
+ io2 = PEdump::CompositeIO.new(StringIO.new('foo'))
29
+
30
+ io1.read.should == io2.read # 'foo'
31
+ io1.read.should == io2.read # ''
32
+ io1.read(3).should == io2.read(3) # nil
33
+ end
34
+
35
+ it "tracks number of bytes read" do
36
+ io = PEdump::CompositeIO.new(
37
+ StringIO.new('foo1'),
38
+ StringIO.new('bar2'),
39
+ StringIO.new('baz')
40
+ )
41
+ io.tell.should == 0
42
+ io.read(3)
43
+ io.tell.should == 3
44
+ io.read(4)
45
+ io.tell.should == 7
46
+ io.read
47
+ io.tell.should == 11
48
+ io.read
49
+ io.tell.should == 11
50
+ io.read 10
51
+ io.tell.should == 11
52
+ end
53
+
54
+ it "chains eof? call" do
55
+ io = PEdump::CompositeIO.new(
56
+ StringIO.new('foo1'),
57
+ StringIO.new('bar2'),
58
+ StringIO.new('baz')
59
+ )
60
+ io.eof?.should be_false
61
+ io.read(3)
62
+ io.eof?.should be_false
63
+ io.read(4)
64
+ io.eof?.should be_false
65
+ io.read
66
+ io.eof?.should be_true
67
+ io.read
68
+ io.eof?.should be_true
69
+ io.read 10
70
+ io.eof?.should be_true
71
+ end
72
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/pedump')
3
+
4
+ describe 'corkami/dllord.dll' do
5
+ it "should have 1 import" do
6
+ sample.imports.size.should == 1
7
+ sample.imports.map(&:module_name).should == %w'msvcrt.dll'
8
+ sample.imports.map do |iid|
9
+ (iid.original_first_thunk + iid.first_thunk).uniq.map(&:name)
10
+ end.flatten.should == ["printf"]
11
+ end
12
+
13
+ it "exports at least 2 entries" do
14
+ sample.exports.Base.should == 0x313
15
+ sample.exports.name.should be_nil
16
+ sample.exports.names.should be_empty
17
+ sample.exports.name_ordinals.should be_empty
18
+ sample.exports.entry_points[0].should == 0xffff_ffff
19
+ sample.exports.entry_points[1].should == 0x1008
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/pedump')
3
+
4
+ [ 'corkami/foldedhdr.exe', 'corkami/foldedhdrW7.exe' ].each do |fname|
5
+ describe fname do
6
+ before :all do
7
+ @sample = sample
8
+ end
9
+
10
+ it "should have 2 imports" do
11
+ @sample.imports.size.should == 2
12
+ @sample.imports.map(&:module_name).should == %w'kernel32.dll msvcrt.dll'
13
+ @sample.imports.map do |iid|
14
+ (iid.original_first_thunk + iid.first_thunk).uniq.map(&:name)
15
+ end.flatten.should == ["ExitProcess", "printf"]
16
+ end
17
+
18
+ it "should have 1 section" do
19
+ @sample.sections.size.should == 1
20
+ s = @sample.sections.first
21
+ s.VirtualSize.should == 0x1000
22
+ s.VirtualAddress.should == 0x1000
23
+ s.SizeOfRawData.should == 0x200
24
+ s.PointerToRawData.should == 0x200
25
+ s.flags.should == 0xa0000000
26
+ end
27
+ end
28
+ end
@@ -1,58 +1,52 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
  require File.expand_path(File.dirname(__FILE__) + '/../lib/pedump')
3
3
 
4
- describe 'Imports' do
4
+ describe 'corkami/imports_badterm.exe' do
5
5
  # PE with a 'bad' imports terminator, just the dll name is empty
6
6
  # http://code.google.com/p/corkami/source/browse/trunk/asm/PE/imports_badterm.asm
7
- describe "imports_badterm.exe" do
8
- before :all do
9
- fname = File.expand_path(File.dirname(__FILE__) + '/../samples/imports_badterm.exe')
10
- File.open(fname,"rb") do |f|
11
- @pedump = PEdump.new(fname)
12
- @imports = @pedump.imports(f)
13
- end
14
- end
7
+ before :all do
8
+ @imports = sample.imports
9
+ end
15
10
 
16
- it "should have 2 IMAGE_IMPORT_DESCRIPTORs" do
17
- @imports.size.should == 2
18
- end
11
+ it "should have 2 IMAGE_IMPORT_DESCRIPTORs" do
12
+ @imports.size.should == 2
13
+ end
19
14
 
20
- it "should have only IMAGE_IMPORT_DESCRIPTORs" do
21
- @imports.map(&:class).uniq.should == [PEdump::IMAGE_IMPORT_DESCRIPTOR]
22
- end
15
+ it "should have only IMAGE_IMPORT_DESCRIPTORs" do
16
+ @imports.map(&:class).uniq.should == [PEdump::IMAGE_IMPORT_DESCRIPTOR]
17
+ end
23
18
 
24
- it "should have all entries thunks equal" do
25
- @imports.each do |iid|
26
- iid.first_thunk.should == iid.original_first_thunk
27
- end
19
+ it "should have all entries thunks equal" do
20
+ @imports.each do |iid|
21
+ iid.first_thunk.should == iid.original_first_thunk
28
22
  end
23
+ end
29
24
 
30
- describe "1st image_import_descriptor" do
31
- it "should be from kernel32.dll" do
32
- @imports[0].module_name.should == "kernel32.dll"
33
- end
34
- it "should have 1 function" do
35
- @imports[0].first_thunk.size.should == 1
36
- end
37
- it "should have ExitProcess" do
38
- @imports[0].first_thunk.first.name.should == "ExitProcess"
39
- @imports[0].first_thunk.first.hint.should == 0
40
- @imports[0].first_thunk.first.ordinal.should be_nil
41
- end
25
+ describe "1st image_import_descriptor" do
26
+ it "should be from kernel32.dll" do
27
+ @imports[0].module_name.should == "kernel32.dll"
28
+ end
29
+ it "should have 1 function" do
30
+ @imports[0].first_thunk.size.should == 1
31
+ end
32
+ it "should have ExitProcess" do
33
+ @imports[0].first_thunk.first.name.should == "ExitProcess"
34
+ @imports[0].first_thunk.first.hint.should == 0
35
+ @imports[0].first_thunk.first.ordinal.should be_nil
42
36
  end
37
+ end
43
38
 
44
- describe "2nd image_import_descriptor" do
45
- it "should be from msvcrt.dll" do
46
- @imports[1].module_name.should == "msvcrt.dll"
47
- end
48
- it "should have 1 function" do
49
- @imports[1].first_thunk.size.should == 1
50
- end
51
- it "should have printf" do
52
- @imports[1].first_thunk.first.name.should == "printf"
53
- @imports[1].first_thunk.first.hint.should == 0
54
- @imports[1].first_thunk.first.ordinal.should be_nil
55
- end
39
+ describe "2nd image_import_descriptor" do
40
+ it "should be from msvcrt.dll" do
41
+ @imports[1].module_name.should == "msvcrt.dll"
42
+ end
43
+ it "should have 1 function" do
44
+ @imports[1].first_thunk.size.should == 1
45
+ end
46
+ it "should have printf" do
47
+ @imports[1].first_thunk.first.name.should == "printf"
48
+ @imports[1].first_thunk.first.hint.should == 0
49
+ @imports[1].first_thunk.first.ordinal.should be_nil
56
50
  end
57
51
  end
58
52
  end
@@ -1,58 +1,52 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
  require File.expand_path(File.dirname(__FILE__) + '/../lib/pedump')
3
3
 
4
- describe 'Imports' do
4
+ describe 'corkami/imports_vterm.exe' do
5
5
  # http://code.google.com/p/corkami/source/browse/trunk/asm/PE/imports_vterm.asm
6
6
  #describe "import terminator in virtual space" do
7
- describe "imports_vterm.exe" do
8
- before :all do
9
- fname = File.expand_path(File.dirname(__FILE__) + '/../samples/imports_vterm.exe')
10
- File.open(fname,"rb") do |f|
11
- @pedump = PEdump.new(fname)
12
- @imports = @pedump.imports(f)
13
- end
14
- end
7
+ before :all do
8
+ @imports = sample.imports
9
+ end
15
10
 
16
- it "should have 2 IMAGE_IMPORT_DESCRIPTORs" do
17
- @imports.size.should == 2
18
- end
11
+ it "should have 2 IMAGE_IMPORT_DESCRIPTORs" do
12
+ @imports.size.should == 2
13
+ end
19
14
 
20
- it "should have only IMAGE_IMPORT_DESCRIPTORs" do
21
- @imports.map(&:class).uniq.should == [PEdump::IMAGE_IMPORT_DESCRIPTOR]
22
- end
15
+ it "should have only IMAGE_IMPORT_DESCRIPTORs" do
16
+ @imports.map(&:class).uniq.should == [PEdump::IMAGE_IMPORT_DESCRIPTOR]
17
+ end
23
18
 
24
- it "should have all entries thunks equal" do
25
- @imports.each do |iid|
26
- iid.first_thunk.should == iid.original_first_thunk
27
- end
19
+ it "should have all entries thunks equal" do
20
+ @imports.each do |iid|
21
+ iid.first_thunk.should == iid.original_first_thunk
28
22
  end
23
+ end
29
24
 
30
- describe "1st image_import_descriptor" do
31
- it "should be from kernel32.dll" do
32
- @imports[0].module_name.should == "kernel32.dll"
33
- end
34
- it "should have 1 function" do
35
- @imports[0].first_thunk.size.should == 1
36
- end
37
- it "should have ExitProcess" do
38
- @imports[0].first_thunk.first.name.should == "ExitProcess"
39
- @imports[0].first_thunk.first.hint.should == 0
40
- @imports[0].first_thunk.first.ordinal.should be_nil
41
- end
25
+ describe "1st image_import_descriptor" do
26
+ it "should be from kernel32.dll" do
27
+ @imports[0].module_name.should == "kernel32.dll"
28
+ end
29
+ it "should have 1 function" do
30
+ @imports[0].first_thunk.size.should == 1
31
+ end
32
+ it "should have ExitProcess" do
33
+ @imports[0].first_thunk.first.name.should == "ExitProcess"
34
+ @imports[0].first_thunk.first.hint.should == 0
35
+ @imports[0].first_thunk.first.ordinal.should be_nil
42
36
  end
37
+ end
43
38
 
44
- describe "2nd image_import_descriptor" do
45
- it "should be from msvcrt.dll" do
46
- @imports[1].module_name.should == "msvcrt.dll"
47
- end
48
- it "should have 1 function" do
49
- @imports[1].first_thunk.size.should == 1
50
- end
51
- it "should have printf" do
52
- @imports[1].first_thunk.first.name.should == "printf"
53
- @imports[1].first_thunk.first.hint.should == 0
54
- @imports[1].first_thunk.first.ordinal.should be_nil
55
- end
39
+ describe "2nd image_import_descriptor" do
40
+ it "should be from msvcrt.dll" do
41
+ @imports[1].module_name.should == "msvcrt.dll"
42
+ end
43
+ it "should have 1 function" do
44
+ @imports[1].first_thunk.size.should == 1
45
+ end
46
+ it "should have printf" do
47
+ @imports[1].first_thunk.first.name.should == "printf"
48
+ @imports[1].first_thunk.first.hint.should == 0
49
+ @imports[1].first_thunk.first.ordinal.should be_nil
56
50
  end
57
51
  end
58
52
  end
@@ -3,12 +3,22 @@ require File.expand_path(File.dirname(__FILE__) + '/../lib/pedump/packer')
3
3
 
4
4
  describe "PEdump::Packer" do
5
5
  describe "matchers" do
6
- PEdump::SigParser.parse(:raw => true).each do |sig|
7
- data = sig.re.join
8
- next if data == "This program cannot be run in DOS mo"
9
- it "should find #{sig.name}" do
10
- PEdump::Packer.of(data).map(&:name).should include(sig.name)
6
+ if ENV['SLOW']
7
+ PEdump::SigParser.parse(:raw => true).each do |sig|
8
+ data = sig.re.join
9
+ next if data == "This program cannot be run in DOS mo"
10
+ it "should find #{sig.name}" do
11
+ a = PEdump::Packer.of(data).map(&:name)
12
+ a.size.should > 0
13
+
14
+ a = sig.name.split - a.join(' ').split - ['Exe','PE']
15
+ a.delete_if{ |x| x[/[vV\.\/()\[\]]/] }
16
+ p a if a.size > 1
17
+ a.size.should < 2
18
+ end
11
19
  end
20
+ else
21
+ pending "SLOW"
12
22
  end
13
23
  end
14
24
  end
@@ -8,5 +8,22 @@ require 'pedump'
8
8
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
9
 
10
10
  RSpec.configure do |config|
11
-
11
+ end
12
+
13
+ def sample
14
+ @pedump ||=
15
+ begin
16
+ fname =
17
+ if self.example
18
+ # called from it(...)
19
+ self.example.full_description.split.first
20
+ else
21
+ # called from before(:all)
22
+ self.class.metadata[:example_group][:description_args].first
23
+ end
24
+ fname = File.expand_path(File.dirname(__FILE__) + '/../samples/' + fname)
25
+ File.open(fname,"rb") do |f|
26
+ PEdump.new(fname).dump
27
+ end
28
+ end
12
29
  end
@@ -0,0 +1,12 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/pedump')
3
+
4
+ describe 'corkami/virtsectblXP.exe' do
5
+ it "should have 2 imports" do
6
+ sample.imports.size.should == 2
7
+ sample.imports.map(&:module_name).should == %w'kernel32.dll msvcrt.dll'
8
+ sample.imports.map do |iid|
9
+ (iid.original_first_thunk + iid.first_thunk).uniq.map(&:name)
10
+ end.flatten.should == ["ExitProcess", "printf"]
11
+ end
12
+ 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.2
4
+ version: 0.4.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-19 00:00:00.000000000 Z
12
+ date: 2011-12-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multipart-post
16
- requirement: &70341710237060 !ruby/object:Gem::Requirement
16
+ requirement: &70155235875660 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.1.4
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70341710237060
24
+ version_requirements: *70155235875660
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: progressbar
27
- requirement: &70341710236340 !ruby/object:Gem::Requirement
27
+ requirement: &70155235891480 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.9.2
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70341710236340
35
+ version_requirements: *70155235891480
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70341710257880 !ruby/object:Gem::Requirement
38
+ requirement: &70155235890940 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 2.3.0
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70341710257880
46
+ version_requirements: *70155235890940
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: bundler
49
- requirement: &70341710257240 !ruby/object:Gem::Requirement
49
+ requirement: &70155235890060 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.0.0
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70341710257240
57
+ version_requirements: *70155235890060
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: jeweler
60
- requirement: &70341710256380 !ruby/object:Gem::Requirement
60
+ requirement: &70155235889180 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 1.6.4
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70341710256380
68
+ version_requirements: *70155235889180
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rcov
71
- requirement: &70341710255420 !ruby/object:Gem::Requirement
71
+ requirement: &70155235888640 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70341710255420
79
+ version_requirements: *70155235888640
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: awesome_print
82
- requirement: &70341710253940 !ruby/object:Gem::Requirement
82
+ requirement: &70155235888120 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70341710253940
90
+ version_requirements: *70155235888120
91
91
  description: dump headers, sections, extract resources of win32 PE exe,dll,etc
92
92
  email: zed.0xff@gmail.com
93
93
  executables:
@@ -114,17 +114,20 @@ files:
114
114
  - data/userdb.txt
115
115
  - lib/pedump.rb
116
116
  - lib/pedump/cli.rb
117
+ - lib/pedump/composite_io.rb
117
118
  - lib/pedump/packer.rb
119
+ - lib/pedump/pe.rb
118
120
  - lib/pedump/sig_parser.rb
119
121
  - lib/pedump/version.rb
120
122
  - lib/pedump/version_info.rb
121
123
  - pedump.gemspec
122
- - samples/65535sects.7z
123
124
  - samples/calc.7z
124
- - samples/imports_badterm.exe
125
- - samples/imports_vterm.exe
125
+ - samples/corkami.7z
126
126
  - samples/zlib.dll
127
127
  - spec/65535sects_spec.rb
128
+ - spec/composite_io_spec.rb
129
+ - spec/dllord_spec.rb
130
+ - spec/foldedhdr_spec.rb
128
131
  - spec/imports_badterm_spec.rb
129
132
  - spec/imports_vterm_spec.rb
130
133
  - spec/pe_spec.rb
@@ -133,6 +136,7 @@ files:
133
136
  - spec/sig_all_packers_spec.rb
134
137
  - spec/sig_spec.rb
135
138
  - spec/spec_helper.rb
139
+ - spec/virtsectblXP_spec.rb
136
140
  homepage: http://github.com/zed-0xff/pedump
137
141
  licenses:
138
142
  - MIT
@@ -148,7 +152,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
148
152
  version: '0'
149
153
  segments:
150
154
  - 0
151
- hash: 1913101081356959317
155
+ hash: 2848967461238967885
152
156
  required_rubygems_version: !ruby/object:Gem::Requirement
153
157
  none: false
154
158
  requirements:
Binary file
Binary file
Binary file