pedump 0.4.15 → 0.4.16

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 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: