pedump 0.4.14 → 0.4.15
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +0 -2
- data/Rakefile +6 -5
- data/VERSION +1 -1
- data/data/fs.txt +37 -1408
- data/data/jc-userdb.txt +14371 -0
- data/data/sig.bin +0 -0
- data/lib/pedump/sig_parser.rb +89 -11
- data/lib/pedump/version.rb +1 -1
- data/pedump.gemspec +3 -5
- data/spec/sig_spec.rb +6 -1
- metadata +33 -48
data/data/sig.bin
CHANGED
Binary file
|
data/lib/pedump/sig_parser.rb
CHANGED
@@ -6,9 +6,14 @@ class PEdump
|
|
6
6
|
TEXT_SIGS_FILES = [
|
7
7
|
File.join(DATA_ROOT, "data", "userdb.txt"),
|
8
8
|
File.join(DATA_ROOT, "data", "signatures.txt"),
|
9
|
-
File.join(DATA_ROOT, "data", "
|
9
|
+
File.join(DATA_ROOT, "data", "jc-userdb.txt"),
|
10
|
+
File.join(DATA_ROOT, "data", "fs.txt"), # has special parse options!
|
10
11
|
]
|
11
12
|
|
13
|
+
SPECIAL_PARSE_OPTIONS = {
|
14
|
+
File.join(DATA_ROOT, "data", "fs.txt") => {:fix1 => true}
|
15
|
+
}
|
16
|
+
|
12
17
|
class OrBlock < Array; end
|
13
18
|
|
14
19
|
class << self
|
@@ -19,19 +24,20 @@ class PEdump
|
|
19
24
|
sigs = {}; sig = nil
|
20
25
|
|
21
26
|
args[:fnames].each do |fname|
|
22
|
-
n0 = sigs.size
|
27
|
+
n0 = sigs.size; add_sig_args = args.dup
|
28
|
+
add_sig_args.merge!(SPECIAL_PARSE_OPTIONS[fname] || {})
|
23
29
|
File.open(fname,'r:utf-8') do |f|
|
24
30
|
while line = f.gets
|
25
31
|
case line.strip
|
26
32
|
when /^[<;#]/, /^$/ # comments & blank lines
|
27
33
|
next
|
28
34
|
when /^\[(.+)=(.+)\]$/
|
29
|
-
_add_sig(sigs, Packer.new($1, $2, true),
|
30
|
-
when /^\[([^=]+)\]
|
35
|
+
_add_sig(sigs, Packer.new($1, $2, true), add_sig_args )
|
36
|
+
when /^\[([^=]+)\](\s+\/\/.+)?$/
|
31
37
|
sig = Packer.new($1)
|
32
38
|
when /^signature = (.+)$/
|
33
39
|
sig.re = $1
|
34
|
-
_add_sig(sigs, sig,
|
40
|
+
_add_sig(sigs, sig, add_sig_args)
|
35
41
|
when /^ep_only = (.+)$/
|
36
42
|
sig.ep_only = ($1.strip.downcase == 'true')
|
37
43
|
else raise line
|
@@ -61,7 +67,13 @@ class PEdump
|
|
61
67
|
when /\A[a-f0-9]{2}\Z/i
|
62
68
|
x = x.to_i(16).chr
|
63
69
|
bins[sig] << x
|
64
|
-
args[:raw]
|
70
|
+
if args[:raw]
|
71
|
+
x
|
72
|
+
elsif args[:raword]
|
73
|
+
x.ord
|
74
|
+
else
|
75
|
+
Regexp::escape(x)
|
76
|
+
end
|
65
77
|
else
|
66
78
|
puts "[?] unknown re element: #{x.inspect} in #{sig.inspect}" if args[:verbose]
|
67
79
|
"BAD_RE"
|
@@ -72,10 +84,10 @@ class PEdump
|
|
72
84
|
a = sig.name.split(/-+>/,2).map(&:strip)
|
73
85
|
sig.name = "#{a[0]} (#{a[1]})"
|
74
86
|
end
|
75
|
-
sig.re.pop while sig.re.last == '??'
|
87
|
+
sig.re.pop while sig.re && sig.re.last == '??'
|
76
88
|
end
|
77
89
|
sigs.delete_if{ |sig| !sig.re || sig.re.index('BAD_RE') }
|
78
|
-
return sigs if args[:raw]
|
90
|
+
return sigs if args[:raw] || args[:raword]
|
79
91
|
|
80
92
|
# require 'awesome_print'
|
81
93
|
# bins.each do |bin_sig, bin|
|
@@ -125,6 +137,9 @@ class PEdump
|
|
125
137
|
# bad sigs
|
126
138
|
return if sig.re[/\A538BD833C0A30:::::/]
|
127
139
|
return if sig.name == "Name of the Packer v1.0"
|
140
|
+
return if sig.name == "Alias PIX/Vivid IMG Graphics format"
|
141
|
+
return if sig.name == "JAR Archive"
|
142
|
+
return if sig.name == "Turbo / Borland Pascal v7.x Unit"
|
128
143
|
return if sig.re == "54 68 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20 6D 6F" # dos stub
|
129
144
|
|
130
145
|
sig.name.sub!(/^\*\s+/, '')
|
@@ -135,10 +150,47 @@ class PEdump
|
|
135
150
|
sig.name.sub! 'RLP ','RLPack '
|
136
151
|
sig.name.sub! '.beta', ' beta'
|
137
152
|
sig.name.sub! '(com)','[com]'
|
153
|
+
sig.name.gsub!(/ V(\d)/, " v\\1") # V1.1 -> v1.1
|
138
154
|
sig.name = sig.name.split(/\s*-+>\s*/).join(' -> ') # fix spaces around '->'
|
155
|
+
sig.name = sig.name.split(' ').delete_if do |x|
|
156
|
+
# delete words: vX.X, v?.?, ?.?, x.x
|
157
|
+
x =~ /\Av?[?x]\.[?x]\Z/i
|
158
|
+
end.join(' ')
|
139
159
|
|
140
160
|
sig.re = sig.re.strip.upcase.tr(':','?')
|
141
161
|
sig.re = sig.re.scan(/../).join(' ') if sig.re.split.first.size > 2
|
162
|
+
|
163
|
+
# sig contains entirely zeroes or masks or only both
|
164
|
+
a_bad = [%w'00', %w'??', %w'00 ??', %w'90', %w'90 ??']
|
165
|
+
# ?a, 0? => ??, ??
|
166
|
+
a_cur = sig.re.split.map{ |x| x['?'] ? '??' : x }.uniq.sort
|
167
|
+
return if a_bad.include?(a_cur)
|
168
|
+
|
169
|
+
# first byte is unique and all others are zeroes or masks
|
170
|
+
a_cur = sig.re.split[1..-1].map{ |x| x['?'] ? '??' : x }.uniq.sort
|
171
|
+
return if a_bad.include?(a_cur)
|
172
|
+
|
173
|
+
# too short signatures
|
174
|
+
# if sig.re.split.delete_if{ |x| x['?'] }.size < 6
|
175
|
+
# require 'awesome_print'
|
176
|
+
# puts sig.inspect.red
|
177
|
+
# end
|
178
|
+
|
179
|
+
# fs.txt contains a lot of signatures that copied from other sources
|
180
|
+
# BUT have all 01 replaced with '??'
|
181
|
+
# // replaced the file with filtered one (see 'fs-good' below) // zzz
|
182
|
+
if args[:fix1]
|
183
|
+
sigs.keys.each do |re|
|
184
|
+
if re.gsub("01","??") == sig.re
|
185
|
+
puts "[.] fix1: rejecting #{sig.name} - already present with 01 in place" if args[:verbose]
|
186
|
+
return
|
187
|
+
end
|
188
|
+
end
|
189
|
+
# File.open("fs-good.txt","a") do |f|
|
190
|
+
# f << "[#{sig.name}=#{sig.re.tr(' ','')}]\n"
|
191
|
+
# end
|
192
|
+
end
|
193
|
+
|
142
194
|
if sigs[sig.re]
|
143
195
|
a = [sig, sigs[sig.re]].map{ |x| x.name.upcase.split('->').first.tr('V ','') }
|
144
196
|
return if a[0][a[1]] || a[1][a[0]]
|
@@ -161,7 +213,6 @@ class PEdump
|
|
161
213
|
d.map! do |x|
|
162
214
|
x - [
|
163
215
|
'EXE','[EXE]',
|
164
|
-
'vx.x','v?.?',
|
165
216
|
'DLL','(DLL)','[DLL]',
|
166
217
|
'[LZMA]','(LZMA)','LZMA',
|
167
218
|
'-','~','(pack)','(1)','(2)',
|
@@ -264,14 +315,41 @@ class PEdump
|
|
264
315
|
sigs.delete_if{ |sig| sig.re.empty? }
|
265
316
|
end
|
266
317
|
|
267
|
-
def
|
318
|
+
def _name2wordonly name
|
319
|
+
name.downcase.split(/[^a-z0-9_.]+/).join(' ').strip
|
320
|
+
end
|
321
|
+
|
322
|
+
def optimize_names sigs
|
268
323
|
# replaces all duplicate names with references to one name
|
269
324
|
# saves ~30k out of ~200k mem
|
270
325
|
h = {}
|
326
|
+
|
327
|
+
# find shortest names
|
271
328
|
sigs.each do |sig|
|
272
|
-
|
329
|
+
t = _name2wordonly(sig.name)
|
330
|
+
if h[t]
|
331
|
+
# keep shortest name
|
332
|
+
if h[t] != sig.name
|
333
|
+
#print "[d] #{[h[t], sig.name].inspect} -> "
|
334
|
+
h[t] = [h[t], sig.name].sort_by(&:size).first
|
335
|
+
#puts h[t]
|
336
|
+
else
|
337
|
+
# fully identical names
|
338
|
+
end
|
339
|
+
else
|
340
|
+
h[t] = sig.name
|
341
|
+
end
|
273
342
|
end
|
274
343
|
|
344
|
+
# assign names back to sigs
|
345
|
+
sigs.each{ |sig| sig.name = h[_name2wordonly(sig.name)] }
|
346
|
+
|
347
|
+
puts "[.] sigs merge: #{h.size} unique names"
|
348
|
+
end
|
349
|
+
|
350
|
+
def optimize sigs
|
351
|
+
optimize_names sigs
|
352
|
+
|
275
353
|
print "[.] sigs merge: #{sigs.size}"; _optimize(sigs); puts " -> #{sigs.size}"
|
276
354
|
|
277
355
|
# try to merge signatures with same name, size & ep_only
|
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.15"
|
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-28"
|
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"]
|
@@ -29,6 +29,7 @@ Gem::Specification.new do |s|
|
|
29
29
|
"VERSION",
|
30
30
|
"bin/pedump",
|
31
31
|
"data/fs.txt",
|
32
|
+
"data/jc-userdb.txt",
|
32
33
|
"data/sig.bin",
|
33
34
|
"data/signatures.txt",
|
34
35
|
"data/userdb.txt",
|
@@ -104,7 +105,6 @@ Gem::Specification.new do |s|
|
|
104
105
|
s.add_development_dependency(%q<bundler>, [">= 0"])
|
105
106
|
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
106
107
|
s.add_development_dependency(%q<what_methods>, [">= 0"])
|
107
|
-
s.add_development_dependency(%q<looksee>, [">= 0"])
|
108
108
|
else
|
109
109
|
s.add_dependency(%q<multipart-post>, ["~> 1.1.4"])
|
110
110
|
s.add_dependency(%q<progressbar>, [">= 0"])
|
@@ -113,7 +113,6 @@ Gem::Specification.new do |s|
|
|
113
113
|
s.add_dependency(%q<bundler>, [">= 0"])
|
114
114
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
115
115
|
s.add_dependency(%q<what_methods>, [">= 0"])
|
116
|
-
s.add_dependency(%q<looksee>, [">= 0"])
|
117
116
|
end
|
118
117
|
else
|
119
118
|
s.add_dependency(%q<multipart-post>, ["~> 1.1.4"])
|
@@ -123,7 +122,6 @@ Gem::Specification.new do |s|
|
|
123
122
|
s.add_dependency(%q<bundler>, [">= 0"])
|
124
123
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
125
124
|
s.add_dependency(%q<what_methods>, [">= 0"])
|
126
|
-
s.add_dependency(%q<looksee>, [">= 0"])
|
127
125
|
end
|
128
126
|
end
|
129
127
|
|
data/spec/sig_spec.rb
CHANGED
@@ -31,6 +31,11 @@ describe "PEdump::Packer" do
|
|
31
31
|
next unless row =~ /^\[(.*)=(.*)\]$/
|
32
32
|
s = ''
|
33
33
|
title,hexstring = $1,$2
|
34
|
+
|
35
|
+
# bad sigs
|
36
|
+
next if hexstring == '909090909090909090909090909090909090909090909090909090909090909090909090'
|
37
|
+
next if hexstring == 'E9::::0000000000000000'
|
38
|
+
|
34
39
|
(hexstring.size/2).times do |i|
|
35
40
|
c = hexstring[i*2,2]
|
36
41
|
if c == '::'
|
@@ -52,7 +57,7 @@ describe "PEdump::Packer" do
|
|
52
57
|
# puts "\t= #{x}"
|
53
58
|
# end
|
54
59
|
else
|
55
|
-
puts "[?] #{title}"
|
60
|
+
puts "[?] #{title}: #{hexstring}"
|
56
61
|
n += 1
|
57
62
|
end
|
58
63
|
end
|
metadata
CHANGED
@@ -1,144 +1,128 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pedump
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.14
|
5
4
|
prerelease:
|
5
|
+
version: 0.4.15
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Andrey "Zed" Zaikin
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
+
prerelease: false
|
16
|
+
type: :runtime
|
15
17
|
name: multipart-post
|
16
18
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
19
|
requirements:
|
19
20
|
- - ~>
|
20
21
|
- !ruby/object:Gem::Version
|
21
22
|
version: 1.1.4
|
22
|
-
type: :runtime
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
25
23
|
none: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
25
|
requirements:
|
27
26
|
- - ~>
|
28
27
|
- !ruby/object:Gem::Version
|
29
28
|
version: 1.1.4
|
29
|
+
none: false
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
|
+
prerelease: false
|
32
|
+
type: :runtime
|
31
33
|
name: progressbar
|
32
34
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
35
|
requirements:
|
35
36
|
- - ! '>='
|
36
37
|
- !ruby/object:Gem::Version
|
37
38
|
version: '0'
|
38
|
-
type: :runtime
|
39
|
-
prerelease: false
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
39
|
none: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
41
|
requirements:
|
43
42
|
- - ! '>='
|
44
43
|
- !ruby/object:Gem::Version
|
45
44
|
version: '0'
|
45
|
+
none: false
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
|
+
prerelease: false
|
48
|
+
type: :runtime
|
47
49
|
name: awesome_print
|
48
50
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
51
|
requirements:
|
51
52
|
- - ! '>='
|
52
53
|
- !ruby/object:Gem::Version
|
53
54
|
version: '0'
|
54
|
-
type: :runtime
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
55
|
none: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
57
|
requirements:
|
59
58
|
- - ! '>='
|
60
59
|
- !ruby/object:Gem::Version
|
61
60
|
version: '0'
|
61
|
+
none: false
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
|
+
prerelease: false
|
64
|
+
type: :development
|
63
65
|
name: rspec
|
64
66
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
67
|
requirements:
|
67
68
|
- - ! '>='
|
68
69
|
- !ruby/object:Gem::Version
|
69
70
|
version: '0'
|
70
|
-
type: :development
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
71
|
none: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
73
|
requirements:
|
75
74
|
- - ! '>='
|
76
75
|
- !ruby/object:Gem::Version
|
77
76
|
version: '0'
|
77
|
+
none: false
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
|
+
prerelease: false
|
80
|
+
type: :development
|
79
81
|
name: bundler
|
80
82
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
83
|
requirements:
|
83
84
|
- - ! '>='
|
84
85
|
- !ruby/object:Gem::Version
|
85
86
|
version: '0'
|
86
|
-
type: :development
|
87
|
-
prerelease: false
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
89
87
|
none: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
89
|
requirements:
|
91
90
|
- - ! '>='
|
92
91
|
- !ruby/object:Gem::Version
|
93
92
|
version: '0'
|
93
|
+
none: false
|
94
94
|
- !ruby/object:Gem::Dependency
|
95
|
+
prerelease: false
|
96
|
+
type: :development
|
95
97
|
name: jeweler
|
96
98
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
99
|
requirements:
|
99
100
|
- - ! '>='
|
100
101
|
- !ruby/object:Gem::Version
|
101
102
|
version: '0'
|
102
|
-
type: :development
|
103
|
-
prerelease: false
|
104
|
-
version_requirements: !ruby/object:Gem::Requirement
|
105
103
|
none: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
105
|
requirements:
|
107
106
|
- - ! '>='
|
108
107
|
- !ruby/object:Gem::Version
|
109
108
|
version: '0'
|
109
|
+
none: false
|
110
110
|
- !ruby/object:Gem::Dependency
|
111
|
+
prerelease: false
|
112
|
+
type: :development
|
111
113
|
name: what_methods
|
112
114
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
|
-
requirements:
|
115
|
-
- - ! '>='
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
115
|
requirements:
|
123
116
|
- - ! '>='
|
124
117
|
- !ruby/object:Gem::Version
|
125
118
|
version: '0'
|
126
|
-
- !ruby/object:Gem::Dependency
|
127
|
-
name: looksee
|
128
|
-
requirement: !ruby/object:Gem::Requirement
|
129
119
|
none: false
|
130
|
-
requirements:
|
131
|
-
- - ! '>='
|
132
|
-
- !ruby/object:Gem::Version
|
133
|
-
version: '0'
|
134
|
-
type: :development
|
135
|
-
prerelease: false
|
136
120
|
version_requirements: !ruby/object:Gem::Requirement
|
137
|
-
none: false
|
138
121
|
requirements:
|
139
122
|
- - ! '>='
|
140
123
|
- !ruby/object:Gem::Version
|
141
124
|
version: '0'
|
125
|
+
none: false
|
142
126
|
description: dump headers, sections, extract resources of win32 PE exe,dll,etc
|
143
127
|
email: zed.0xff@gmail.com
|
144
128
|
executables:
|
@@ -159,6 +143,7 @@ files:
|
|
159
143
|
- VERSION
|
160
144
|
- bin/pedump
|
161
145
|
- data/fs.txt
|
146
|
+
- data/jc-userdb.txt
|
162
147
|
- data/sig.bin
|
163
148
|
- data/signatures.txt
|
164
149
|
- data/userdb.txt
|
@@ -224,20 +209,20 @@ rdoc_options: []
|
|
224
209
|
require_paths:
|
225
210
|
- lib
|
226
211
|
required_ruby_version: !ruby/object:Gem::Requirement
|
227
|
-
none: false
|
228
212
|
requirements:
|
229
213
|
- - ! '>='
|
230
214
|
- !ruby/object:Gem::Version
|
231
215
|
version: '0'
|
232
216
|
segments:
|
233
217
|
- 0
|
234
|
-
hash: -
|
235
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
218
|
+
hash: -4443824394784718020
|
236
219
|
none: false
|
220
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
237
221
|
requirements:
|
238
222
|
- - ! '>='
|
239
223
|
- !ruby/object:Gem::Version
|
240
224
|
version: '0'
|
225
|
+
none: false
|
241
226
|
requirements: []
|
242
227
|
rubyforge_project:
|
243
228
|
rubygems_version: 1.8.24
|