pedump 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -0
- data/Gemfile.lock +6 -0
- data/Rakefile +26 -0
- data/VERSION +1 -1
- data/lib/pedump.rb +92 -17
- data/lib/pedump/cli.rb +118 -18
- data/pedump.gemspec +8 -2
- metadata +33 -11
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.
|
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)})
|
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
|
-
|
312
|
-
|
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
|
-
|
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, :
|
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
|
-
|
550
|
-
|
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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
781
|
-
|
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
|
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
|
-
|
86
|
+
next if !@options[:force] && !@pedump.mz(f)
|
83
87
|
|
84
88
|
@actions.each do |action|
|
85
|
-
|
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 "#
|
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 "#
|
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
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
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
|
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
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
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.
|
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-
|
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.
|
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-
|
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: &
|
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: *
|
46
|
+
version_requirements: *70185231238140
|
25
47
|
- !ruby/object:Gem::Dependency
|
26
48
|
name: bundler
|
27
|
-
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: *
|
57
|
+
version_requirements: *70185231228680
|
36
58
|
- !ruby/object:Gem::Dependency
|
37
59
|
name: jeweler
|
38
|
-
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: *
|
68
|
+
version_requirements: *70185231227000
|
47
69
|
- !ruby/object:Gem::Dependency
|
48
70
|
name: rcov
|
49
|
-
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: *
|
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:
|
118
|
+
hash: 2723794485104812379
|
97
119
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
120
|
none: false
|
99
121
|
requirements:
|