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 +1 -1
- data/lib/pedump.rb +13 -3
- data/lib/pedump/packer.rb +9 -1
- data/lib/pedump/resources.rb +42 -13
- data/lib/pedump/version.rb +1 -1
- data/pedump.gemspec +3 -2
- data/spec/bad_imports_spec.rb +20 -0
- metadata +4 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.11
|
data/lib/pedump.rb
CHANGED
@@ -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
|
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
|
-
|
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 >
|
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
|
data/lib/pedump/packer.rb
CHANGED
@@ -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
|
-
|
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,
|
data/lib/pedump/resources.rb
CHANGED
@@ -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.
|
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
|
306
|
-
if (@@loopchk3[
|
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
|
-
|
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
|
-
|
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
|
-
|
381
|
+
file_offset,
|
358
382
|
entry.data.Size,
|
359
383
|
entry.data.CodePage,
|
360
384
|
entry.data.Reserved
|
361
385
|
)
|
362
386
|
else
|
363
|
-
|
364
|
-
|
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
|
394
|
+
end
|
395
|
+
r.flatten.compact
|
367
396
|
end
|
368
397
|
end
|
data/lib/pedump/version.rb
CHANGED
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.4.
|
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-
|
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.
|
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-
|
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:
|
225
|
+
hash: -1370513960600577087
|
225
226
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
226
227
|
none: false
|
227
228
|
requirements:
|