pedump 0.2.1 → 0.3.0

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/Gemfile CHANGED
@@ -2,6 +2,8 @@ source "http://rubygems.org"
2
2
  # Add dependencies required to use your gem here.
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
+ gem "rest-client", "~> 1.6.7"
6
+ gem "progressbar", "~> 0.9.2"
5
7
 
6
8
  # Add dependencies to develop your gem here.
7
9
  # Include everything needed to run rake, tests, features, etc.
data/Gemfile.lock CHANGED
@@ -7,8 +7,12 @@ GEM
7
7
  bundler (~> 1.0)
8
8
  git (>= 1.2.5)
9
9
  rake
10
+ mime-types (1.16)
11
+ progressbar (0.9.2)
10
12
  rake (0.9.2.2)
11
13
  rcov (0.9.11)
14
+ rest-client (1.6.7)
15
+ mime-types (>= 1.16)
12
16
  rspec (2.3.0)
13
17
  rspec-core (~> 2.3.0)
14
18
  rspec-expectations (~> 2.3.0)
@@ -24,5 +28,7 @@ PLATFORMS
24
28
  DEPENDENCIES
25
29
  bundler (~> 1.0.0)
26
30
  jeweler (~> 1.6.4)
31
+ progressbar (~> 0.9.2)
27
32
  rcov
33
+ rest-client (~> 1.6.7)
28
34
  rspec (~> 2.3.0)
data/Rakefile CHANGED
@@ -49,3 +49,29 @@ task :default => :spec
49
49
  # rdoc.rdoc_files.include('README*')
50
50
  # rdoc.rdoc_files.include('lib/**/*.rb')
51
51
  #end
52
+
53
+ namespace :test do
54
+ desc "test on all files in given path"
55
+ task :all_files do
56
+ require './lib/pedump'
57
+ require './lib/pedump/cli'
58
+ path = ENV['path'] || raise("run me with path=...")
59
+ `find #{path} -type f`.split("\n").each do |fname|
60
+ puts "\n### #{fname}\n"
61
+ PEdump::CLI.new(fname).run
62
+ end
63
+ end
64
+
65
+ namespace :all_files do
66
+ desc "output file name to stderr, use with stdout redirection"
67
+ task :stderr do
68
+ require './lib/pedump'
69
+ require './lib/pedump/cli'
70
+ path = ENV['path'] || raise("run me with path=...")
71
+ `find #{path} -type f`.split("\n").each do |fname|
72
+ STDERR.puts "\n### #{fname}\n"
73
+ PEdump::CLI.new(fname).run
74
+ end
75
+ end
76
+ end
77
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 0.3.0
data/lib/pedump.rb CHANGED
@@ -303,13 +303,17 @@ class PEdump
303
303
  end
304
304
 
305
305
  def dexor
306
- self[4..-9].sub(/\A(#{Regexp::escape(key)})+/,'').xor(key)
306
+ self[4..-9].sub(/\A(#{Regexp::escape(key)}){3}/,'').xor(key)
307
307
  end
308
308
 
309
309
  def decode
310
310
  x = dexor
311
- raise "dexored size must be a multiple of 8" unless x.size%8 == 0
312
- x.unpack('vvV'*(x.size/8)).each_slice(3).map{ |slice| Entry.new(*slice)}
311
+ if x.size%8 == 0
312
+ x.unpack('vvV'*(x.size/8)).each_slice(3).map{ |slice| Entry.new(*slice)}
313
+ else
314
+ PEdump.logger.error "[?] #{self.class}: dexored size(#{x.size}) must be a multiple of 8"
315
+ nil
316
+ end
313
317
  end
314
318
  end
315
319
 
@@ -441,6 +445,8 @@ class PEdump
441
445
  def _dump_handle h
442
446
  rich_hdr(h) # includes mz(h)
443
447
  resources(h) # includes pe(h)
448
+ imports h
449
+ exports h
444
450
  end
445
451
 
446
452
  def data_directory f=nil
@@ -472,16 +478,19 @@ class PEdump
472
478
  ImportedFunction = Struct.new(:hint, :name, :ordinal)
473
479
 
474
480
  def imports f=nil
481
+ return @imports if @imports
475
482
  return nil unless pe(f) && pe(f).ioh && f
476
483
  dir = @pe.ioh.DataDirectory[IMAGE_DATA_DIRECTORY::IMPORT]
477
484
  return [] if !dir || (dir.va == 0 && dir.size == 0)
478
485
  va = @pe.ioh.DataDirectory[IMAGE_DATA_DIRECTORY::IMPORT].va
479
- f.seek va2file(va)
486
+ file_offset = va2file(va)
487
+ return nil unless file_offset
488
+ f.seek file_offset
480
489
  r = []
481
490
  until (t=IMAGE_IMPORT_DESCRIPTOR.read(f)).empty?
482
491
  r << t
483
492
  end
484
- r.each do |x|
493
+ @imports = r.each do |x|
485
494
  if x.Name.to_i != 0 && (va = va2file(x.Name))
486
495
  f.seek va
487
496
  x.module_name = f.gets("\x00").chop
@@ -539,15 +548,21 @@ class PEdump
539
548
  :AddressOfNames,
540
549
  :AddressOfNameOrdinals,
541
550
  # manual:
542
- :name, :entry_points, :names, :ordinals
551
+ :name, :entry_points, :names, :name_ordinals
543
552
 
544
553
  def exports f=nil
554
+ return @exports if @exports
545
555
  return nil unless pe(f) && pe(f).ioh && f
546
556
  dir = @pe.ioh.DataDirectory[IMAGE_DATA_DIRECTORY::EXPORT]
547
557
  return [] if !dir || (dir.va == 0 && dir.size == 0)
548
558
  va = @pe.ioh.DataDirectory[IMAGE_DATA_DIRECTORY::EXPORT].va
549
- f.seek va2file(va)
550
- IMAGE_EXPORT_DIRECTORY.read(f).tap do |x|
559
+ file_offset = va2file(va)
560
+ return nil unless file_offset
561
+ f.seek file_offset
562
+ @exports = IMAGE_EXPORT_DIRECTORY.read(f).tap do |x|
563
+ x.entry_points = []
564
+ x.name_ordinals = []
565
+ x.names = []
551
566
  if x.Name.to_i != 0 && (va = va2file(x.Name))
552
567
  f.seek va
553
568
  x.name = f.gets("\x00").chop
@@ -559,7 +574,7 @@ class PEdump
559
574
  end
560
575
  if x.AddressOfNameOrdinals.to_i !=0 && (va = va2file(x.AddressOfNameOrdinals))
561
576
  f.seek va
562
- x.ordinals = f.read(x.NumberOfFunctions*2).unpack('v*').map{ |o| o+x.Base }
577
+ x.name_ordinals = f.read(x.NumberOfNames*2).unpack('v*').map{ |o| o+x.Base }
563
578
  end
564
579
  end
565
580
  if x.NumberOfNames.to_i != 0 && x.AddressOfNames.to_i !=0 && (va = va2file(x.AddressOfNames))
@@ -658,6 +673,13 @@ class PEdump
658
673
  return va - s.VirtualAddress + s.PointerToRawData
659
674
  end
660
675
  end
676
+ # not found with regular search. assume any of VirtualSize was 0, and try with RawSize
677
+ sections.each do |s|
678
+ if (s.VirtualAddress...(s.VirtualAddress+s.SizeOfRawData)).include?(va)
679
+ return va - s.VirtualAddress + s.PointerToRawData
680
+ end
681
+ end
682
+ logger.error "[?] can't find file_offset of VA 0x#{va.to_i.to_s(16)}"
661
683
  nil
662
684
  end
663
685
 
@@ -673,11 +695,11 @@ class PEdump
673
695
  end
674
696
  f.seek res_section.PointerToRawData
675
697
  IMAGE_RESOURCE_DIRECTORY.base = res_section.PointerToRawData
676
- @resource_data_base = res_section.PointerToRawData - res_section.VirtualAddress
698
+ #@resource_data_base = res_section.PointerToRawData - res_section.VirtualAddress
677
699
  IMAGE_RESOURCE_DIRECTORY.read(f)
678
700
  end
679
701
 
680
- class Resource < Struct.new(:type, :name, :id, :lang, :file_offset, :size, :cp, :reserved, :data)
702
+ class Resource < Struct.new(:type, :name, :id, :lang, :file_offset, :size, :cp, :reserved, :data, :valid)
681
703
  def bitmap_hdr
682
704
  bmp_info_hdr = data.find{ |x| x.is_a?(BITMAPINFOHEADER) }
683
705
  raise "no BITMAPINFOHEADER for #{self.type} #{self.name}" unless bmp_info_hdr
@@ -765,23 +787,70 @@ class PEdump
765
787
  when 'GROUP_CURSOR'
766
788
  f.seek file_offset
767
789
  data << CUR_ICO_HEADER.read(f)
790
+ nRead = CUR_ICO_HEADER::SIZE
768
791
  data.last.wNumImages.times do
769
- data << CURDIRENTRY.read(f)
792
+ if nRead >= self.size
793
+ PEdump.logger.error "[!] refusing to read CURDIRENTRY beyond resource size"
794
+ break
795
+ end
796
+ data << CURDIRENTRY.read(f)
797
+ nRead += CURDIRENTRY::SIZE
770
798
  end
771
799
  when 'GROUP_ICON'
772
800
  f.seek file_offset
773
801
  data << CUR_ICO_HEADER.read(f)
802
+ nRead = CUR_ICO_HEADER::SIZE
774
803
  data.last.wNumImages.times do
775
- data << ICODIRENTRY.read(f)
804
+ if nRead >= self.size
805
+ PEdump.logger.error "[!] refusing to read ICODIRENTRY beyond resource size"
806
+ break
807
+ end
808
+ data << ICODIRENTRY.read(f)
809
+ nRead += ICODIRENTRY::SIZE
776
810
  end
777
811
  when 'STRING'
778
812
  f.seek file_offset
779
813
  16.times do
780
- nChars = f.read(2).unpack('v').first
781
- data << f.read(nChars*2).force_encoding('UTF-16LE').encode!('UTF-8')
814
+ break if f.tell >= file_offset+self.size
815
+ nChars = f.read(2).to_s.unpack('v').first.to_i
816
+ t =
817
+ if nChars*2 + 1 > self.size
818
+ # TODO: if it's not 1st string in table then truncated size must be less
819
+ PEdump.logger.error "[!] string size(#{nChars*2}) > stringtable size(#{self.size}). truncated to #{self.size-2}"
820
+ f.read(self.size-2)
821
+ else
822
+ f.read(nChars*2)
823
+ end
824
+ data <<
825
+ begin
826
+ t.force_encoding('UTF-16LE').encode!('UTF-8')
827
+ rescue
828
+ t.force_encoding('ASCII')
829
+ tt = t.size > 0x10 ? t[0,0x10].inspect+'...' : t.inspect
830
+ PEdump.logger.error "[!] cannot convert #{tt} to UTF-16"
831
+ [nChars,t].pack('va*')
832
+ end
782
833
  end
783
834
  # XXX: check if readed strings summary length is less than resource data length
784
835
  end
836
+
837
+ data.delete_if do |x|
838
+ valid = !x.respond_to?(:valid?) || x.valid?
839
+ PEdump.logger.warn "[?] ignoring invalid #{x.class}" unless valid
840
+ !valid
841
+ end
842
+ ensure
843
+ validate
844
+ end
845
+
846
+ def validate
847
+ self.valid =
848
+ case type
849
+ when 'BITMAP','ICON','CURSOR'
850
+ data.any?{ |x| x.is_a?(BITMAPINFOHEADER) && x.valid? }
851
+ else
852
+ true
853
+ end
785
854
  end
786
855
  end
787
856
 
@@ -799,7 +868,7 @@ class PEdump
799
868
 
800
869
  # see also http://www.informit.com/articles/article.aspx?p=1186882 about icons format
801
870
 
802
- BITMAPINFOHEADER = create_struct 'V3v2V6',
871
+ class BITMAPINFOHEADER < create_struct 'V3v2V6',
803
872
  :biSize, # BITMAPINFOHEADER::SIZE
804
873
  :biWidth,
805
874
  :biHeight,
@@ -812,6 +881,11 @@ class PEdump
812
881
  :biClrUsed,
813
882
  :biClrImportant
814
883
 
884
+ def valid?
885
+ self.biSize == 40
886
+ end
887
+ end
888
+
815
889
  # http://www.devsource.com/c/a/Architecture/Resources-From-PE-I/2/
816
890
  CUR_ICO_HEADER = create_struct('v3',
817
891
  :wReserved, # always 0
@@ -878,7 +952,8 @@ class PEdump
878
952
  entry.name,
879
953
  nil, # id
880
954
  entry.Name, # lang
881
- entry.data.OffsetToData + @resource_data_base,
955
+ #entry.data.OffsetToData + @resource_data_base,
956
+ va2file(entry.data.OffsetToData),
882
957
  entry.data.Size,
883
958
  entry.data.CodePage,
884
959
  entry.data.Reserved
data/lib/pedump/cli.rb CHANGED
@@ -14,10 +14,12 @@ class PEdump::CLI
14
14
 
15
15
  KNOWN_ACTIONS = (
16
16
  %w'mz dos_stub rich pe data_directory sections' +
17
- %w'strings resources resource_directory imports exports'
17
+ %w'strings resources resource_directory imports exports web'
18
18
  ).map(&:to_sym)
19
19
 
20
- DEFAULT_ALL_ACTIONS = KNOWN_ACTIONS - %w'resource_directory'.map(&:to_sym)
20
+ DEFAULT_ALL_ACTIONS = KNOWN_ACTIONS - %w'resource_directory web'.map(&:to_sym)
21
+
22
+ URL_BASE = "http://pedump.me"
21
23
 
22
24
  def initialize argv = ARGV
23
25
  @argv = argv
@@ -41,7 +43,6 @@ class PEdump::CLI
41
43
  "Output format: bin,c,dump,hex,inspect,table (default)" do |v|
42
44
  @options[:format] = v
43
45
  end
44
- # TODO: imports, exports
45
46
  KNOWN_ACTIONS.each do |t|
46
47
  opts.on "--#{t.to_s.tr('_','-')}", eval("lambda{ |_| @actions << :#{t.to_s.tr('-','_')} }")
47
48
  end
@@ -51,6 +52,9 @@ class PEdump::CLI
51
52
  opts.on "--va2file VA", "Convert RVA to file offset" do |va|
52
53
  @actions << [:va2file,va]
53
54
  end
55
+ opts.on "-W", "--web", "Upload file to a #{URL_BASE} for a nice HTML tables with image previews, candies & stuff" do
56
+ @actions << :web
57
+ end
54
58
  end
55
59
 
56
60
  if (@argv = optparser.parse(@argv)).empty?
@@ -79,10 +83,14 @@ class PEdump::CLI
79
83
  end
80
84
  end
81
85
 
82
- return if !@options[:force] && !@pedump.mz(f)
86
+ next if !@options[:force] && !@pedump.mz(f)
83
87
 
84
88
  @actions.each do |action|
85
- dump_action action,f
89
+ if action == :web
90
+ upload f
91
+ else
92
+ dump_action action,f
93
+ end
86
94
  end
87
95
  end
88
96
  end
@@ -91,6 +99,71 @@ class PEdump::CLI
91
99
  # prevents a 'Broken pipe - <STDOUT> (Errno::EPIPE)' message
92
100
  end
93
101
 
102
+ class ProgressProxy
103
+ def initialize file
104
+ @file = file
105
+ @pbar = ProgressBar.new("[.] uploading", file.size, STDOUT)
106
+ @pbar.try(:file_transfer_mode)
107
+ @pbar.bar_mark = '='
108
+ end
109
+ def read *args
110
+ @pbar.inc args.first
111
+ @file.read *args
112
+ end
113
+ def method_missing *args
114
+ @file.send *args
115
+ end
116
+ def respond_to? *args
117
+ @file.respond_to?(*args) || super(*args)
118
+ end
119
+ end
120
+
121
+ def upload f
122
+ if @pedump.mz(f).signature != 'MZ'
123
+ @pedump.logger.error "[!] refusing to upload a non-MZ file"
124
+ return
125
+ end
126
+
127
+ require 'digest/md5'
128
+ require 'open-uri'
129
+ require 'rest-client'
130
+ require 'progressbar'
131
+
132
+ stdout_sync = STDOUT.sync
133
+ STDOUT.sync = true
134
+
135
+ md5 = Digest::MD5.file(f.path).hexdigest
136
+ @pedump.logger.info "[.] md5: #{md5}"
137
+ url = "#{URL_BASE}/#{md5}/"
138
+
139
+ @pedump.logger.info "[.] checking if file already uploaded.."
140
+ begin
141
+ if (r=open(url).read) == "OK"
142
+ @pedump.logger.warn "[.] file already uploaded: #{url}"
143
+ return
144
+ else
145
+ raise "invalid server response: #{r}"
146
+ end
147
+ rescue OpenURI::HTTPError
148
+ raise unless $!.to_s == "404 Not Found"
149
+ end
150
+
151
+ f.rewind
152
+ if (r=RestClient.post(URL_BASE, :file => ProgressProxy.new(f))) != "OK"
153
+ raise "invalid server response: #{r}"
154
+ end
155
+ puts
156
+ puts "[.] analyzing..."
157
+
158
+ if (r=open(File.join(URL_BASE,md5,'analyze')).read) != "OK"
159
+ raise "invalid server response: #{r}"
160
+ end
161
+
162
+ puts "[.] uploaded: #{url}"
163
+ ensure
164
+ STDOUT.sync = stdout_sync
165
+ end
166
+
94
167
  def action_title action
95
168
  s = action.to_s.upcase.tr('_',' ')
96
169
  s += " Header" if [:mz, :pe, :rich].include?(action)
@@ -242,33 +315,52 @@ class PEdump::CLI
242
315
  end
243
316
 
244
317
  def dump_exports data
245
- printf "# module_name=%s flags=0x%x ts=%s version=%d.%d\n",
318
+ printf "# module %s\n# flags=0x%x ts=%s version=%d.%d ord_base=%d\n",
246
319
  data.name.inspect,
247
320
  data.Characteristics,
248
321
  Time.at(data.TimeDateStamp.to_i).strftime('"%Y-%m-%d %H:%M:%S"'),
249
- data.MajorVersion, data.MinorVersion
322
+ data.MajorVersion, data.MinorVersion,
323
+ data.Base
324
+
325
+ if @options[:verbose]
326
+ printf "# Names rva=0x%08x file_offset=%8d\n",
327
+ data.AddressOfNames, @pedump.va2file(data.AddressOfNames)
328
+ printf "# EntryPoints rva=0x%08x file_offset=%8d\n",
329
+ data.AddressOfFunctions, @pedump.va2file(data.AddressOfFunctions)
330
+ printf "# Ordinals rva=0x%08x file_offset=%8d\n",
331
+ data.AddressOfNameOrdinals, @pedump.va2file(data.AddressOfNameOrdinals)
332
+ end
250
333
 
251
- printf "# n_funcs=%d n_names=%d\n",
334
+ printf "# nFuncs=%d nNames=%d\n",
252
335
  data.NumberOfFunctions,
253
336
  data.NumberOfNames
254
337
 
338
+ return unless data.name_ordinals.any? || data.entry_points.any? || data.names.any?
339
+
255
340
  puts
256
341
 
342
+ ord2name = {}
343
+ data.NumberOfNames.times do |i|
344
+ ord2name[data.name_ordinals[i]] ||= []
345
+ ord2name[data.name_ordinals[i]] << data.names[i]
346
+ end
347
+
257
348
  printf "%5s %8s %s\n", "ORD", "ENTRY_VA", "NAME"
258
349
  data.NumberOfFunctions.times do |i|
259
- printf "%5s %8x %s\n",
260
- data.ordinals[i].try(:to_s,16),
261
- data.entry_points[i],
262
- data.names[i]
350
+ ep = data.entry_points[i]
351
+ names = ord2name[i+data.Base].try(:join,', ')
352
+ next if ep.to_i == 0 && names.nil?
353
+ printf "%5d %8x %s\n", i + data.Base, ep, names
263
354
  end
264
355
  end
265
356
 
266
357
  def dump_imports data
267
- fmt = "%-15s %5s %5s %s\n"
358
+ fmt = "%-15s %5s %5s %s\n"
268
359
  printf fmt, "MODULE_NAME", "HINT", "ORD", "FUNCTION_NAME"
269
360
  data.each do |iid|
270
361
  # image import descriptor
271
362
  (Array(iid.original_first_thunk) + Array(iid.first_thunk)).uniq.each do |f|
363
+ next unless f
272
364
  # imported function
273
365
  printf fmt,
274
366
  iid.module_name,
@@ -373,7 +465,7 @@ class PEdump::CLI
373
465
  fmt.each_with_index do |f,i|
374
466
  v = res.send(keys[i])
375
467
  if f['x']
376
- printf f.tr('x','s'), v < 10 ? v.to_s : "0x#{v.to_s(16)}"
468
+ printf f.tr('x','s'), v.to_i < 10 ? v.to_s : "0x#{v.to_s(16)}"
377
469
  else
378
470
  printf f, v
379
471
  end
@@ -403,10 +495,18 @@ class PEdump::CLI
403
495
  end
404
496
 
405
497
  def dump_rich_hdr data
406
- puts " LIB_ID VERSION TIMES_USED "
407
- data.decode.each do |row|
408
- printf " %5d %2x %7d %4x %7d %3x\n",
409
- row.id, row.id, row.version, row.version, row.times, row.times
498
+ if decoded = data.decode
499
+ puts " LIB_ID VERSION TIMES_USED "
500
+ decoded.each do |row|
501
+ printf " %5d %2x %7d %4x %7d %3x\n",
502
+ row.id, row.id, row.version, row.version, row.times, row.times
503
+ end
504
+ else
505
+ puts "# raw:"
506
+ puts hexdump(data)
507
+ puts
508
+ puts "# dexored:"
509
+ puts hexdump(data.dexor)
410
510
  end
411
511
  end
412
512
 
data/pedump.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "pedump"
8
- s.version = "0.2.1"
8
+ s.version = "0.3.0"
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-10"
12
+ s.date = "2011-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"]
@@ -43,17 +43,23 @@ Gem::Specification.new do |s|
43
43
  s.specification_version = 3
44
44
 
45
45
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
+ s.add_runtime_dependency(%q<rest-client>, ["~> 1.6.7"])
47
+ s.add_runtime_dependency(%q<progressbar>, ["~> 0.9.2"])
46
48
  s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
47
49
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
48
50
  s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
49
51
  s.add_development_dependency(%q<rcov>, [">= 0"])
50
52
  else
53
+ s.add_dependency(%q<rest-client>, ["~> 1.6.7"])
54
+ s.add_dependency(%q<progressbar>, ["~> 0.9.2"])
51
55
  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
52
56
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
53
57
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
54
58
  s.add_dependency(%q<rcov>, [">= 0"])
55
59
  end
56
60
  else
61
+ s.add_dependency(%q<rest-client>, ["~> 1.6.7"])
62
+ s.add_dependency(%q<progressbar>, ["~> 0.9.2"])
57
63
  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
58
64
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
59
65
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
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.2.1
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,33 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-10 00:00:00.000000000Z
12
+ date: 2011-12-11 00:00:00.000000000Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rest-client
16
+ requirement: &70185231241440 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.6.7
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70185231241440
25
+ - !ruby/object:Gem::Dependency
26
+ name: progressbar
27
+ requirement: &70185231240020 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.9.2
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70185231240020
14
36
  - !ruby/object:Gem::Dependency
15
37
  name: rspec
16
- requirement: &70303206510780 !ruby/object:Gem::Requirement
38
+ requirement: &70185231238140 !ruby/object:Gem::Requirement
17
39
  none: false
18
40
  requirements:
19
41
  - - ~>
@@ -21,10 +43,10 @@ dependencies:
21
43
  version: 2.3.0
22
44
  type: :development
23
45
  prerelease: false
24
- version_requirements: *70303206510780
46
+ version_requirements: *70185231238140
25
47
  - !ruby/object:Gem::Dependency
26
48
  name: bundler
27
- requirement: &70303206635540 !ruby/object:Gem::Requirement
49
+ requirement: &70185231228680 !ruby/object:Gem::Requirement
28
50
  none: false
29
51
  requirements:
30
52
  - - ~>
@@ -32,10 +54,10 @@ dependencies:
32
54
  version: 1.0.0
33
55
  type: :development
34
56
  prerelease: false
35
- version_requirements: *70303206635540
57
+ version_requirements: *70185231228680
36
58
  - !ruby/object:Gem::Dependency
37
59
  name: jeweler
38
- requirement: &70303206642320 !ruby/object:Gem::Requirement
60
+ requirement: &70185231227000 !ruby/object:Gem::Requirement
39
61
  none: false
40
62
  requirements:
41
63
  - - ~>
@@ -43,10 +65,10 @@ dependencies:
43
65
  version: 1.6.4
44
66
  type: :development
45
67
  prerelease: false
46
- version_requirements: *70303206642320
68
+ version_requirements: *70185231227000
47
69
  - !ruby/object:Gem::Dependency
48
70
  name: rcov
49
- requirement: &70303206648540 !ruby/object:Gem::Requirement
71
+ requirement: &70185231225760 !ruby/object:Gem::Requirement
50
72
  none: false
51
73
  requirements:
52
74
  - - ! '>='
@@ -54,7 +76,7 @@ dependencies:
54
76
  version: '0'
55
77
  type: :development
56
78
  prerelease: false
57
- version_requirements: *70303206648540
79
+ version_requirements: *70185231225760
58
80
  description: dump headers, sections, extract resources of win32 PE exe,dll,etc
59
81
  email: zed.0xff@gmail.com
60
82
  executables:
@@ -93,7 +115,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
93
115
  version: '0'
94
116
  segments:
95
117
  - 0
96
- hash: -1918854361818125320
118
+ hash: 2723794485104812379
97
119
  required_rubygems_version: !ruby/object:Gem::Requirement
98
120
  none: false
99
121
  requirements: