pedump 0.4.15 → 0.4.16

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.15
1
+ 0.4.16
Binary file
@@ -65,6 +65,36 @@ class PEdump
65
65
  end
66
66
  end
67
67
 
68
+ # only valid for types BITMAP, ICON & CURSOR
69
+ def restore_icon src_fname
70
+ File.open(src_fname, "rb") do |f|
71
+ parse f
72
+ if data.first == "PNG"
73
+ "\x89PNG" +f.read(self.size-4)
74
+ else
75
+ icondir = [
76
+ 0, # Reserved. Must always be 0.
77
+ 1, # image type: 1 for icon (.ICO), 2 for cursor (.CUR). Other values are invalid
78
+ 1, # number of images in the file
79
+ ].pack("v3")
80
+ bitmap_hdr = data.first # BITMAPINFOHEADER
81
+ icondirentry = ICODIRENTRY.new(
82
+ bitmap_hdr.biWidth,
83
+ bitmap_hdr.biHeight / (%w'ICON CURSOR'.include?(type) ? 2 : 1),
84
+ 0, # XXX: bColors: may be wrong here
85
+ 0,
86
+ 1,
87
+ bitmap_hdr.biBitCount,
88
+ bitmap_hdr.biSizeImage,
89
+ icondir.size + 2 + ICODIRENTRY::SIZE # offset of BMP data from the beginning of ICO file
90
+ )
91
+ # ICONDIRENTRY is 2 bytes larger than ICODIRENTRY
92
+ icondir + icondirentry.pack + "\x00\x00" + bitmap_hdr.pack + f.read(self.size)
93
+ end
94
+ end
95
+ end
96
+
97
+ # only valid for types BITMAP, ICON & CURSOR
68
98
  def bitmap_mask src_fname
69
99
  File.open(src_fname, "rb") do |f|
70
100
  parse f
@@ -175,14 +205,21 @@ class PEdump
175
205
  end
176
206
 
177
207
  def validate
178
- self.valid =
208
+ self.valid = self.file_offset &&
179
209
  case type
180
210
  when 'BITMAP','ICON','CURSOR'
181
211
  data.any?{ |x| x.is_a?(BITMAPINFOHEADER) && x.valid? } || data.first == 'PNG'
212
+ when 'GROUP_ICON'
213
+ # rough validation
214
+ data.first.is_a?(CUR_ICO_HEADER) && data.size == data.first.wNumImages.to_i+1
182
215
  else
183
216
  true
184
217
  end
185
218
  end
219
+
220
+ def valid?
221
+ valid
222
+ end
186
223
  end
187
224
 
188
225
  STRING = Struct.new(:id, :lang, :value)
@@ -171,10 +171,10 @@ class PEdump
171
171
  return if a_bad.include?(a_cur)
172
172
 
173
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
174
+ if sig.re.split.delete_if{ |x| x['?'] }.size < 3
175
+ require 'awesome_print'
176
+ puts sig.inspect.red
177
+ end
178
178
 
179
179
  # fs.txt contains a lot of signatures that copied from other sources
180
180
  # BUT have all 01 replaced with '??'
@@ -216,10 +216,18 @@ class PEdump
216
216
  'DLL','(DLL)','[DLL]',
217
217
  '[LZMA]','(LZMA)','LZMA',
218
218
  '-','~','(pack)','(1)','(2)',
219
- '19??'
219
+ '19??',
220
+ 'with:', 'with?'
220
221
  ]
221
222
  end
222
- return if d.all?(&:empty?) # no different words
223
+ return if d.all?(&:empty?) # no different words => can keep ANY name
224
+
225
+
226
+ # if name1 =~ /pecompact/i
227
+ # require 'awesome_print'
228
+ # puts "[d] #{name1}".yellow
229
+ # puts "[d] #{name2}".yellow
230
+ # end
223
231
 
224
232
  # [["v1.14/v1.20"], ["v1.14,", "v1.20"]]]
225
233
  # [["EXEShield", "v0.3b/v0.3", "v0.6"], ["Shield", "v0.3b,", "v0.3"]]]
@@ -233,21 +241,53 @@ class PEdump
233
241
  end
234
242
  end
235
243
 
244
+ # require 'awesome_print'
245
+ # puts "[d] #{name1.yellow} #{name2.green}"
246
+
236
247
  a = name1.split
237
248
  b = name2.split
249
+
250
+ # merge common head
238
251
  new_name_head = []
239
252
  while a.any? && b.any? && a.first.upcase == b.first.upcase
240
253
  new_name_head << a.shift
241
254
  b.shift
242
255
  end
256
+
257
+ # merge common tail
243
258
  new_name_tail = []
244
259
  while a.any? && b.any? && a.last.upcase == b.last.upcase
245
260
  new_name_tail.unshift a.pop
246
261
  b.pop
247
262
  end
263
+
264
+ # rm common words from middle
265
+ separators = [ "/", "->" ]
266
+ was = true
267
+ while was
268
+ was = false
269
+ b.each do |bw|
270
+ next if bw == "/" || bw == "->"
271
+ if a.include?(bw) || a.include?(bw+")") || a.include?("("+bw) || a.include?("(#{bw})")
272
+ b -= [bw]
273
+ was = true
274
+ break
275
+ end
276
+ end
277
+ end
278
+ while separators.include?(b.last)
279
+ b.pop
280
+ end
281
+
248
282
  new_name = new_name_head
249
283
  new_name << [a.join(' '), b.join(' ')].delete_if{|x| x.empty?}.join(' / ')
250
284
  new_name += new_name_tail
285
+ # if name1 =~ /pecompact/i
286
+ # p a
287
+ # p b
288
+ # p new_name_tail
289
+ # puts "[=] #{new_name.inspect}".red
290
+ # end
251
291
  new_name = new_name.join(' ')
252
292
  end
253
293
 
@@ -291,14 +331,16 @@ class PEdump
291
331
  if rd = _re_diff(sig1.re, sig2.re, max_diff)
292
332
  if rd.all?{ |x| x[0].nil? || x[0] == '.' } && sig2.re.size >= sig1.re.size
293
333
  if new_name = _merge_names(sig2.name, sig1.name)
294
- #pp ["FIRST", sig1.name, sig2.name, new_name, sig1.re.join, sig2.re.join] if new_name
334
+ # require 'pp'
335
+ # pp ["FIRST", sig1.name, sig2.name, new_name, sig1.re.join, sig2.re.join] if new_name =~ /pecompact/i
295
336
  sig1.name = new_name
296
337
  end
297
338
  sig2.ep_only ||= sig1.ep_only
298
339
  sig2.re = []
299
340
  elsif rd.all?{ |x| x[1].nil? || x[1] == '.' } && sig1.re.size >= sig2.re.size
300
341
  if new_name = _merge_names(sig2.name, sig1.name)
301
- #pp ["SECOND", sig1.name, sig2.name, new_name, sig1.re.join, sig2.re.join] if new_name
342
+ # require 'pp'
343
+ # pp ["SECOND", sig1.name, sig2.name, new_name, sig1.re.join, sig2.re.join] if new_name =~ /pecompact/i
302
344
  sig2.name = new_name
303
345
  end
304
346
  sig1.re = []
@@ -350,18 +392,18 @@ class PEdump
350
392
  def optimize sigs
351
393
  optimize_names sigs
352
394
 
353
- print "[.] sigs merge: #{sigs.size}"; _optimize(sigs); puts " -> #{sigs.size}"
395
+ # XXX no optimize from now, prefer more precise sigs
396
+ #print "[.] sigs merge: #{sigs.size}"; _optimize(sigs); puts " -> #{sigs.size}"
354
397
 
355
398
  # try to merge signatures with same name, size & ep_only
356
- sigs.group_by{ |sig|
357
- [sig.re.size, sig.name, sig.ep_only]
358
- }.values.each do |a|
359
- next if a.size == 1
360
- if merged_re = _merge(a)
361
- a.first.re = merged_re
362
- a[1..-1].each{ |sig| sig.re = nil }
399
+ sigs.group_by{ |sig| [sig.re.size, sig.name, sig.ep_only] }.
400
+ values.each do |a|
401
+ next if a.size == 1
402
+ if merged_re = _merge(a)
403
+ a.first.re = merged_re
404
+ a[1..-1].each{ |sig| sig.re = nil }
405
+ end
363
406
  end
364
- end
365
407
  print "[.] sigs merge: #{sigs.size}"; sigs.delete_if{ |x| x.re.nil? }; puts " -> #{sigs.size}"
366
408
 
367
409
 
@@ -439,6 +481,7 @@ class PEdump
439
481
  end
440
482
  prev_eq = eq
441
483
  end
484
+ dstart ||= 0
442
485
  r = dstart..dend
443
486
  r == (0..(size-1)) ? nil : r
444
487
  end
@@ -2,7 +2,7 @@ class PEdump
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 4
5
- PATCH = 15
5
+ PATCH = 16
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.15"
8
+ s.version = "0.4.16"
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-28"
12
+ s.date = "2013-01-03"
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"]
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: pedump
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.4.15
5
+ version: 0.4.16
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-28 00:00:00.000000000 Z
12
+ date: 2013-01-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  prerelease: false
@@ -215,7 +215,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
215
215
  version: '0'
216
216
  segments:
217
217
  - 0
218
- hash: -4443824394784718020
218
+ hash: -2417171475449588298
219
219
  none: false
220
220
  required_rubygems_version: !ruby/object:Gem::Requirement
221
221
  requirements: