pedump 0.7.3 → 0.7.5

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/lib/pedump/cli.rb CHANGED
@@ -145,6 +145,12 @@ class PEdump::CLI
145
145
  opts.on "--file2va OFFSET", "Convert file offset to VA" do |offset|
146
146
  @actions << [:file2va, offset]
147
147
  end
148
+ opts.on "--rva2file RVA", "Convert RVA to file offset" do |va|
149
+ @actions << [:rva2file, va]
150
+ end
151
+ opts.on "--file2rva OFFSET", "Convert file offset to RVA" do |offset|
152
+ @actions << [:file2rva, offset]
153
+ end
148
154
 
149
155
  opts.separator ''
150
156
  opts.on "--set-os-version VER", "Patch OS version in PE header" do |ver|
@@ -287,7 +293,7 @@ class PEdump::CLI
287
293
  require 'digest/md5'
288
294
  require 'open-uri'
289
295
  require 'net/http'
290
- require 'net/http/post/multipart'
296
+ require 'pedump/multipart'
291
297
 
292
298
  stdout_sync = $stdout.sync
293
299
  $stdout.sync = true
@@ -314,12 +320,26 @@ class PEdump::CLI
314
320
 
315
321
  f.rewind
316
322
 
317
- # upload with progress
323
+ # upload with progress using manual multipart POST
318
324
  post_url = URI.parse(URL_BASE+'/upload')
319
- # UploadIO is from multipart-post
320
- uio = UploadIO.new(f, "application/octet-stream", File.basename(f.path))
321
- ppx = ProgressProxy.new(uio)
322
- req = Net::HTTP::Post::Multipart.new post_url.path, "file" => ppx
325
+ boundary = MultipartBody.generate_boundary
326
+ filename = File.basename(f.path)
327
+
328
+ # Build multipart body parts
329
+ header_part = "--#{boundary}\r\n" \
330
+ "Content-Disposition: form-data; name=\"file\"; filename=\"#{filename}\"\r\n" \
331
+ "Content-Type: application/octet-stream\r\n\r\n"
332
+ footer_part = "\r\n--#{boundary}--\r\n"
333
+
334
+ content_length = header_part.bytesize + f.size + footer_part.bytesize
335
+
336
+ req = Net::HTTP::Post.new(post_url.path)
337
+ req['Content-Type'] = "multipart/form-data; boundary=#{boundary}"
338
+ req['Content-Length'] = content_length
339
+
340
+ ppx = ProgressProxy.new(f)
341
+ req.body_stream = MultipartBody.new(header_part, ppx, footer_part, content_length)
342
+
323
343
  res = Net::HTTP.start(post_url.host, post_url.port, use_ssl: (post_url.scheme == 'https')) do |http|
324
344
  http.request(req)
325
345
  end
@@ -355,7 +375,7 @@ class PEdump::CLI
355
375
  end
356
376
  end
357
377
 
358
- puts "[.] ldr = PEdump::Loader.new(open(#{f.path.inspect}))".gray
378
+ puts "[.] ldr = PEdump::Loader.new(open(#{f.path.inspect}))"
359
379
  IRB.start
360
380
  end
361
381
 
@@ -385,13 +405,17 @@ class PEdump::CLI
385
405
  case action[0]
386
406
  when :disasm
387
407
  return
388
- when :va2file, :file2va
408
+ when :rva2file, :file2rva, :va2file, :file2va
389
409
  cmd = action[0]
390
410
  @pedump.sections(f)
391
- va = action[1] =~ /(^0x)|(h$)/i ? action[1].to_i(16) : action[1].to_i
392
- file_offset = @pedump.send(cmd, va)
393
- if file_offset
394
- printf("%s(0x%x) = 0x%x (%d)\n", cmd, va, file_offset, file_offset)
411
+ arg = action[1] =~ /(^0x)|(h$)/i ? action[1].to_i(16) : action[1].to_i
412
+ result = @pedump.send(cmd, arg)
413
+ if result
414
+ if @options[:format] == :hex
415
+ puts result.to_s(16)
416
+ else
417
+ printf("%s(0x%x) = 0x%x (%d)\n", cmd, arg, result, result)
418
+ end
395
419
  else
396
420
  @success = false
397
421
  end
@@ -652,7 +676,7 @@ class PEdump::CLI
652
676
 
653
677
  def dump_clr_streams data
654
678
  clr_header = @pedump.clr_header
655
- clr_data_file_ofs = clr_header.MetaData.va.to_i > 0 && @pedump.va2file(clr_header.MetaData.va)
679
+ clr_data_file_ofs = clr_header.MetaData.va.to_i > 0 && @pedump.rva2file(clr_header.MetaData.va)
656
680
 
657
681
  fmt = "%8x %8x %-32s\n"
658
682
  printf fmt.tr('x','s'), *%w'offset size name'
@@ -675,7 +699,7 @@ class PEdump::CLI
675
699
  blob_stream = @pedump.clr_streams.find{ |s| s.name == "#Blob" }
676
700
 
677
701
  clr_header = @pedump.clr_header
678
- clr_data_file_ofs = clr_header.MetaData.va.to_i > 0 && @pedump.va2file(clr_header.MetaData.va)
702
+ clr_data_file_ofs = clr_header.MetaData.va.to_i > 0 && @pedump.rva2file(clr_header.MetaData.va)
679
703
  blob_file_ofs = blob_stream.offset + clr_data_file_ofs if blob_stream
680
704
  blob_size = blob_stream&.size
681
705
 
@@ -892,7 +916,7 @@ class PEdump::CLI
892
916
  if @options[:verbose] > 0
893
917
  [%w'Names', %w'EntryPoints Functions', %w'Ordinals NameOrdinals'].each do |x|
894
918
  va = data["AddressOf"+x.last]
895
- ofs = @pedump.va2file(va) || '?'
919
+ ofs = @pedump.rva2file(va) || '?'
896
920
  printf("# %-12s rva=0x%08x file_offset=%8s\n", x.first, va, ofs) if va
897
921
  end
898
922
  end
@@ -1132,7 +1156,7 @@ class PEdump::CLI
1132
1156
  exit(1)
1133
1157
  end
1134
1158
  if entry.size != 0
1135
- _copy_stream @pedump.io, $stdout, entry.size, @pedump.va2file(entry.va)
1159
+ _copy_stream @pedump.io, $stdout, entry.size, @pedump.rva2file(entry.va)
1136
1160
  end
1137
1161
  end
1138
1162
 
@@ -102,7 +102,7 @@ class PEdump
102
102
  dir = hdr.ManagedNativeHeader
103
103
  return nil if !dir || (dir.va.to_i == 0 && dir.size.to_i == 0)
104
104
 
105
- file_offset = va2file(dir.va)
105
+ file_offset = rva2file(dir.va)
106
106
  return nil unless file_offset
107
107
 
108
108
  f.seek(file_offset)
data/lib/pedump/clr.rb CHANGED
@@ -584,7 +584,7 @@ class PEdump
584
584
  dir = @pe.ioh.DataDirectory[IMAGE_DATA_DIRECTORY::CLR_Header]
585
585
  return nil if !dir || (dir.va == 0 && dir.size == 0)
586
586
 
587
- file_offset = va2file(dir.va)
587
+ file_offset = rva2file(dir.va)
588
588
  return nil unless file_offset
589
589
 
590
590
  if f.checked_seek(file_offset)
@@ -601,7 +601,7 @@ class PEdump
601
601
  dir = hdr&.MetaData
602
602
  return nil if !dir || (dir.va.to_i == 0 || dir.size.to_i == 0)
603
603
 
604
- file_offset = va2file(dir.va)
604
+ file_offset = rva2file(dir.va)
605
605
  return nil unless file_offset
606
606
 
607
607
  if f.checked_seek(file_offset)
@@ -635,7 +635,7 @@ class PEdump
635
635
  streams.each do |stream|
636
636
  next unless stream.name == '#Strings'
637
637
 
638
- unless f.checked_seek(va2file(dir.va) + stream.offset)
638
+ unless f.checked_seek(rva2file(dir.va) + stream.offset)
639
639
  logger.warn "[?] Error seeking to CLR strings stream"
640
640
  return nil
641
641
  end
@@ -678,7 +678,7 @@ class PEdump
678
678
  streams.each do |stream|
679
679
  next if stream.name != '#~' && stream.name != '#-' # Metadata Table Stream
680
680
 
681
- unless f.checked_seek(va2file(dir.va) + stream.offset)
681
+ unless f.checked_seek(rva2file(dir.va) + stream.offset)
682
682
  logger.warn "[?] Error seeking to CLR table stream"
683
683
  return nil
684
684
  end
@@ -0,0 +1,29 @@
1
+ module PEdump::Colors
2
+ def gray(str)
3
+ "\e[1;30m#{str}\e[0m"
4
+ end
5
+
6
+ def red(str)
7
+ "\e[1;31m#{str}\e[0m"
8
+ end
9
+
10
+ def green(str)
11
+ "\e[1;32m#{str}\e[0m"
12
+ end
13
+
14
+ def yellow(str)
15
+ "\e[1;33m#{str}\e[0m"
16
+ end
17
+
18
+ def redish(str)
19
+ "\e[0;31m#{str}\e[0m"
20
+ end
21
+
22
+ def greenish(str)
23
+ "\e[0;32m#{str}\e[0m"
24
+ end
25
+
26
+ def yellowish(str)
27
+ "\e[0;33m#{str}\e[0m"
28
+ end
29
+ end
@@ -1,4 +1,5 @@
1
1
  require 'pedump'
2
+ require 'pedump/colors'
2
3
  require 'pedump/loader'
3
4
 
4
5
  ########################################################################
@@ -9,6 +10,8 @@ class PEdump::Comparer
9
10
  attr_accessor :verbose
10
11
  attr_accessor :ignored_data_dirs, :ignored_sections
11
12
 
13
+ include PEdump::Colors
14
+
12
15
  METHODS = [:sections, :data_dirs, :imports, :resources, :pe_hdr]
13
16
 
14
17
  def initialize ldr1, ldr2
@@ -53,12 +56,12 @@ class PEdump::Comparer
53
56
 
54
57
  if !s2
55
58
  r = false
56
- printf "[!] extra section %-12s in %s\n".red, s1.name.inspect, f1
59
+ printf red("[!] extra section %-12s in %s\n"), s1.name.inspect, f1
57
60
  elsif s1.data == s2.data
58
- printf "[.] section: %s == %s\n".green, s1.name, s2.name if @verbose
61
+ printf green("[.] section: %s == %s\n"), s1.name, s2.name if @verbose
59
62
  else
60
63
  r = false
61
- printf "[!] section: %s != %s\n".red, s1.name, s2.name
64
+ printf red("[!] section: %s != %s\n"), s1.name, s2.name
62
65
  self.class.cmp_ios *[s1,s2].map{ |section| StringIO.new(section.data) }
63
66
  end
64
67
  end
@@ -81,14 +84,14 @@ class PEdump::Comparer
81
84
 
82
85
  if d1.va != d2.va && d1.size != d2.size
83
86
  r = false
84
- printf "[!] data_dir: %-12s: SIZE & VA: %6x %6x | %6x %6x\n".red, d1.type,
87
+ printf red("[!] data_dir: %-12s: SIZE & VA: %6x %6x | %6x %6x\n"), d1.type,
85
88
  d1.va, d1.size, d2.va, d2.size
86
89
  elsif d1.va != d2.va
87
90
  r = false
88
- printf "[!] data_dir: %-12s: VA : %x != %x\n".red, d1.type, d1.va, d2.va
91
+ printf red("[!] data_dir: %-12s: VA : %x != %x\n"), d1.type, d1.va, d2.va
89
92
  elsif d1.size != d2.size
90
93
  r = false
91
- printf "[!] data_dir: %-12s: SIZE : %x != %x\n".red, d1.type, d1.size, d2.size
94
+ printf red("[!] data_dir: %-12s: SIZE : %x != %x\n"), d1.type, d1.size, d2.size
92
95
  end
93
96
  end
94
97
  r
@@ -98,7 +101,7 @@ class PEdump::Comparer
98
101
  @ldr1.pedump.imports.each_with_index do |iid1,idx|
99
102
  iid2 = @ldr2.pedump.imports[idx]
100
103
  if iid1 != iid2
101
- puts "[!] diff imports".red
104
+ puts red("[!] diff imports")
102
105
  return false
103
106
  end
104
107
  end
@@ -133,9 +136,9 @@ class PEdump::Comparer
133
136
  bytes = ios.map(&:readbyte)
134
137
  if bytes.uniq.size > 1
135
138
  ndiff += 1
136
- printf ("\t%08x:"+" %02x"*ios.size).yellow+"\n", ios[0].pos-1, *bytes
139
+ printf(yellow("\t%08x:"+" %02x"*ios.size)+"\n", ios[0].pos-1, *bytes)
137
140
  if ndiff >= 5
138
- puts "\t...".yellow
141
+ puts yellow("\t...")
139
142
  break
140
143
  end
141
144
  end
@@ -21,13 +21,13 @@ class PEdump
21
21
 
22
22
  MINIDUMP_LOCATION_DESCRIPTOR = IOStruct.new 'LL', :DataSize, :Rva
23
23
 
24
- class MINIDUMP_DIRECTORY < IOStruct.new 'L', :StreamType, :Location
25
- def self.read io
26
- r = super
27
- r.Location = MINIDUMP_LOCATION_DESCRIPTOR.read(io)
28
- r
29
- end
30
- end
24
+ # Using nested struct - Location is automatically parsed
25
+ MINIDUMP_DIRECTORY = IOStruct.new(
26
+ fields: {
27
+ StreamType: 'uint32_t',
28
+ Location: MINIDUMP_LOCATION_DESCRIPTOR,
29
+ }
30
+ )
31
31
 
32
32
  MINIDUMP_MEMORY_INFO = IOStruct.new 'QQLLQLLLL',
33
33
  :BaseAddress,
data/lib/pedump/logger.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'awesome_print' # for colored tty logging
1
+ require 'pedump/colors'
2
2
 
3
3
  class PEdump
4
4
  class Logger < ::Logger
@@ -39,6 +39,8 @@ class PEdump
39
39
  end
40
40
 
41
41
  class ColoredLogger < ::Logger
42
+ include PEdump::Colors
43
+
42
44
  def initialize *args
43
45
  super
44
46
  @formatter = proc do |severity,_,_,msg|
@@ -58,7 +60,7 @@ class PEdump
58
60
  when 'DEBUG'
59
61
  :gray
60
62
  end
61
- "#{color ? msg.send(color) : msg}\n"
63
+ "#{color ? send(color, msg) : msg}\n"
62
64
  end
63
65
  end
64
66
  @level = WARN
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ class PEdump
4
+ class CLI
5
+ # Streaming multipart body for file uploads
6
+ class MultipartBody
7
+ BOUNDARY_CHARS = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a
8
+
9
+ def self.generate_boundary
10
+ "----PEdumpUpload#{Array.new(32) { BOUNDARY_CHARS.sample }.join}"
11
+ end
12
+
13
+ def initialize(header, file_io, footer, total_size)
14
+ @parts = [
15
+ StringIO.new(header),
16
+ file_io,
17
+ StringIO.new(footer)
18
+ ]
19
+ @part_index = 0
20
+ @size = total_size
21
+ end
22
+
23
+ attr_reader :size
24
+
25
+ def read(length = nil, outbuf = nil)
26
+ outbuf ||= String.new
27
+ outbuf.clear
28
+ outbuf.force_encoding(Encoding::BINARY)
29
+
30
+ return nil if @part_index >= @parts.length
31
+
32
+ while @part_index < @parts.length
33
+ chunk = if length
34
+ @parts[@part_index].read(length - outbuf.bytesize)
35
+ else
36
+ @parts[@part_index].read
37
+ end
38
+
39
+ if chunk
40
+ outbuf << chunk
41
+ break if length && outbuf.bytesize >= length
42
+ else
43
+ @part_index += 1
44
+ end
45
+ end
46
+
47
+ outbuf.empty? && length ? nil : outbuf
48
+ end
49
+
50
+ def rewind
51
+ @parts.each(&:rewind)
52
+ @part_index = 0
53
+ end
54
+ end
55
+ end
56
+ end
data/lib/pedump/packer.rb CHANGED
@@ -73,7 +73,7 @@ class PEdump
73
73
  elsif va == 0 && pe.dll?
74
74
  pedump.logger.debug "[.] it's a DLL with no EntryPoint"
75
75
  nil
76
- elsif !(ofs = pedump.va2file(va))
76
+ elsif !(ofs = pedump.rva2file(va))
77
77
  pedump.logger.error "[?] can't find EntryPoint RVA (0x#{va.to_s(16)}) file offset"
78
78
  nil
79
79
  else
@@ -403,7 +403,7 @@ class PEdump
403
403
  end
404
404
  end
405
405
  when IMAGE_RESOURCE_DATA_ENTRY
406
- file_offset = va2file(entry.data.OffsetToData, :quiet => (@pe_res_errors > MAX_ERRORS))
406
+ file_offset = rva2file(entry.data.OffsetToData, :quiet => (@pe_res_errors > MAX_ERRORS))
407
407
  unless file_offset
408
408
  @pe_res_errors += 1
409
409
  if @pe_res_errors > MAX_ERRORS
@@ -1,3 +1,5 @@
1
+ #coding: binary
2
+
1
3
  class PEdump
2
4
  module SigParser
3
5
 
@@ -47,8 +49,6 @@ class PEdump
47
49
  puts "[=] #{sigs.size-n0} sigs from #{File.basename(fname)}\n\n" if args[:verbose]
48
50
  end
49
51
 
50
- bins = Hash.new{ |k,v| k[v] = ''.force_encoding('binary') }
51
-
52
52
  # convert strings to Regexps
53
53
  sigs = sigs.values
54
54
  sigs.each_with_index do |sig,idx|
@@ -57,16 +57,14 @@ class PEdump
57
57
  sig.size = a.size
58
58
  end.map do |x|
59
59
  case x
60
- when /\A\?\?\Z/
61
- bins[sig] << '.'
62
- '.'
63
- when /\A.\?/,/\?.\Z/
64
- puts "[?] #{x.inspect} -> \"??\" in #{sig.name}" if args[:verbose]
65
- bins[sig] << '.'
60
+ when /\A\?\?\z/
66
61
  '.'
67
- when /\A[a-f0-9]{2}\Z/i
62
+ when /\A\h\?\z/ # 'f?'
63
+ "[\\x#{x[0]}0-\\x#{x[0]}f]"
64
+ when /\A\?\h\z/ # '?4'
65
+ '[' + (0..15).map{ |i| "\\x#{i.to_s(16)}#{x[1]}" }.join + ']'
66
+ when /\A[a-f0-9]{2}\z/i
68
67
  x = x.to_i(16).chr
69
- bins[sig] << x
70
68
  if args[:raw]
71
69
  x
72
70
  elsif args[:raword]
@@ -89,34 +87,6 @@ class PEdump
89
87
  sigs.delete_if{ |sig| !sig.re || sig.re.index('BAD_RE') }
90
88
  return sigs if args[:raw] || args[:raword]
91
89
 
92
- # require 'awesome_print'
93
- # bins.each do |bin_sig, bin|
94
- # next if bin.size < 5
95
- # #next unless bin_sig.name['UPX']
96
- #
97
- # bin_re = Regexp.new(bin_sig.re.join, Regexp::MULTILINE)
98
- # was = false
99
- # sigs.each do |sig|
100
- # next if sig.size < 5 || sig == bin_sig
101
- # #next unless sig.name['UPX']
102
- #
103
- # re = Regexp.new(sig.re.join, Regexp::MULTILINE)
104
- # if bin.index(re) == 0
105
- # rd = _re_diff(bin_re.source, re.source)
106
- # if rd.any? && rd.size <= 4
107
- # #if sig.name.split.first.upcase != bin_sig.name.split.first.upcase
108
- # puts "\n[.] #{bin_sig.name.yellow}\n#{bin_re.source.inspect.red}" unless was
109
- # puts "[=] #{sig.name}"
110
- # puts re.source.inspect.green
111
- # p rd
112
- # was = true
113
- # #end
114
- # end
115
- # end
116
- # end
117
- # end
118
-
119
-
120
90
  optimize sigs if args[:optimize]
121
91
 
122
92
  # convert re-arrays to Regexps
@@ -141,6 +111,7 @@ class PEdump
141
111
  return if sig.name == "JAR Archive"
142
112
  return if sig.name == "Turbo / Borland Pascal v7.x Unit"
143
113
  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
114
+ return if sig.re =~ /T RU E/
144
115
 
145
116
  sig.name.sub!(/^\*\s+/, '')
146
117
  sig.name.sub!(/\s+\(h\)$/, '')
@@ -172,8 +143,8 @@ class PEdump
172
143
 
173
144
  # too short signatures
174
145
  if sig.re.split.delete_if{ |x| x['?'] }.size < 3
175
- require 'awesome_print'
176
- puts sig.inspect.red
146
+ puts "[?] too short signature: #{sig.inspect}" if args[:verbose]
147
+ return
177
148
  end
178
149
 
179
150
  # fs.txt contains a lot of signatures that copied from other sources
@@ -223,12 +194,6 @@ class PEdump
223
194
  return if d.all?(&:empty?) # no different words => can keep ANY name
224
195
 
225
196
 
226
- # if name1 =~ /pecompact/i
227
- # require 'awesome_print'
228
- # puts "[d] #{name1}".yellow
229
- # puts "[d] #{name2}".yellow
230
- # end
231
-
232
197
  # [["v1.14/v1.20"], ["v1.14,", "v1.20"]]]
233
198
  # [["EXEShield", "v0.3b/v0.3", "v0.6"], ["Shield", "v0.3b,", "v0.3"]]]
234
199
  2.times do |i|
@@ -241,9 +206,6 @@ class PEdump
241
206
  end
242
207
  end
243
208
 
244
- # require 'awesome_print'
245
- # puts "[d] #{name1.yellow} #{name2.green}"
246
-
247
209
  a = name1.split
248
210
  b = name2.split
249
211
 
@@ -282,12 +244,6 @@ class PEdump
282
244
  new_name = new_name_head
283
245
  new_name << [a.join(' '), b.join(' ')].delete_if{|x| x.empty?}.join(' / ')
284
246
  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
291
247
  new_name = new_name.join(' ')
292
248
  end
293
249
 
data/lib/pedump/te.rb CHANGED
@@ -4,33 +4,33 @@ class PEdump
4
4
  # https://formats.kaitai.io/uefi_te/index.html
5
5
  # http://ho.ax/tag/efi/
6
6
  # https://github.com/gdbinit/TELoader
7
-
8
- EFI_IMAGE_DATA_DIRECTORY = IOStruct.new( "VV", :va, :size )
7
+
8
+ EFI_IMAGE_DATA_DIRECTORY = IOStruct.new("VV", :va, :size)
9
9
  EFI_IMAGE_DATA_DIRECTORY::TYPES = %w'BASERELOC DEBUG'
10
- EFI_IMAGE_DATA_DIRECTORY::TYPES.each_with_index do |type,idx|
11
- EFI_IMAGE_DATA_DIRECTORY.const_set(type,idx)
10
+ EFI_IMAGE_DATA_DIRECTORY::TYPES.each_with_index do |type, idx|
11
+ EFI_IMAGE_DATA_DIRECTORY.const_set(type, idx)
12
12
  end
13
13
 
14
- class EFI_TE_IMAGE_HEADER < IOStruct.new 'vvCCvVVQ',
15
- :Signature,
16
- :Machine,
17
- :NumberOfSections,
18
- :Subsystem,
19
- :StrippedSize,
20
- :AddressOfEntryPoint,
21
- :BaseOfCode,
22
- :ImageBase,
23
- :DataDirectory # readed manually: EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]
24
-
25
- REAL_SIZE = SIZE + EFI_IMAGE_DATA_DIRECTORY::SIZE * 2
14
+ # Using hash format with nested struct array for DataDirectory
15
+ class EFI_TE_IMAGE_HEADER < IOStruct.new(
16
+ fields: {
17
+ Signature: 'uint16_t',
18
+ Machine: 'uint16_t',
19
+ NumberOfSections: 'uint8_t',
20
+ Subsystem: 'uint8_t',
21
+ StrippedSize: 'uint16_t',
22
+ AddressOfEntryPoint: 'uint32_t',
23
+ BaseOfCode: 'uint32_t',
24
+ ImageBase: 'uint64_t',
25
+ DataDirectory: { type: EFI_IMAGE_DATA_DIRECTORY, count: 2 },
26
+ }
27
+ )
28
+ REAL_SIZE = SIZE
26
29
 
27
30
  attr_accessor :sections
28
31
 
29
32
  def self.read io, args = {}
30
33
  super(io).tap do |te|
31
- te.DataDirectory = 2.times.map do
32
- EFI_IMAGE_DATA_DIRECTORY.read(io)
33
- end
34
34
  te.sections = PE.read_sections(io, te.NumberOfSections, args)
35
35
  end
36
36
  end
data/lib/pedump/tls.rb CHANGED
@@ -1,17 +1,15 @@
1
1
  class PEdump
2
- IMAGE_TLS_DIRECTORY32 = IOStruct.new 'V6',
3
- :StartAddressOfRawData,
4
- :EndAddressOfRawData,
5
- :AddressOfIndex,
6
- :AddressOfCallBacks,
7
- :SizeOfZeroFill,
8
- :Characteristics
2
+ TLS_DIRECTORY_FIELDS = %i[
3
+ StartAddressOfRawData
4
+ EndAddressOfRawData
5
+ AddressOfIndex
6
+ AddressOfCallBacks
7
+ SizeOfZeroFill
8
+ Characteristics
9
+ ].freeze
9
10
 
10
- IMAGE_TLS_DIRECTORY64 = IOStruct.new 'Q4V2',
11
- :StartAddressOfRawData,
12
- :EndAddressOfRawData,
13
- :AddressOfIndex,
14
- :AddressOfCallBacks,
15
- :SizeOfZeroFill,
16
- :Characteristics
11
+ # 32-bit: all fields are 32-bit (V6)
12
+ # 64-bit: first 4 fields are 64-bit pointers (Q4), last 2 are 32-bit (V2)
13
+ IMAGE_TLS_DIRECTORY32 = IOStruct.new('V6', *TLS_DIRECTORY_FIELDS)
14
+ IMAGE_TLS_DIRECTORY64 = IOStruct.new('Q4V2', *TLS_DIRECTORY_FIELDS)
17
15
  end
@@ -788,13 +788,13 @@ class PEdump::Unpacker::ASPack
788
788
  ###
789
789
 
790
790
  rebuild_tls :step => 1
791
- sorted_obj_tbl = @obj_tbl.sort_by{ |x| @ldr.pedump.va2file(x.va) }
791
+ sorted_obj_tbl = @obj_tbl.sort_by{ |x| @ldr.pedump.rva2file(x.va) }
792
792
  sorted_obj_tbl.each_with_index do |obj,idx|
793
793
  # restore section flags, if any
794
794
  @ldr.va2section(obj.va).flags = obj.flags if obj.flags
795
795
 
796
796
  next if obj.size < 0 # empty section
797
- #file_offset = @ldr.pedump.va2file(obj.va)
797
+ #file_offset = @ldr.pedump.rva2file(obj.va)
798
798
  #@io.seek file_offset
799
799
  packed_size =
800
800
  if idx == sorted_obj_tbl.size - 1
@@ -802,7 +802,7 @@ class PEdump::Unpacker::ASPack
802
802
  obj.size
803
803
  else
804
804
  # subtract this file_offset from next object file_offset
805
- @ldr.pedump.va2file(sorted_obj_tbl[idx+1].va) - @ldr.pedump.va2file(obj.va)
805
+ @ldr.pedump.rva2file(sorted_obj_tbl[idx+1].va) - @ldr.pedump.rva2file(obj.va)
806
806
  end
807
807
  #packed_data = @io.read packed_size
808
808
  packed_data = @ldr[obj.va, packed_size]
@@ -840,7 +840,7 @@ if __FILE__ == $0
840
840
  next unless packer = Array(pedump.packer(f)).first
841
841
  next unless packer.name =~ /aspack/i
842
842
 
843
- STDERR.puts "\n=== #{fname}".green
843
+ STDERR.puts "\n=== #{fname}"
844
844
 
845
845
  f.rewind
846
846
  unpacker = PEdump::Unpacker::ASPack.new(f,
@@ -1,7 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class PEdump
2
- module Version
3
- STRING = File.read(File.join(File.dirname(File.dirname(File.dirname(__FILE__))), 'VERSION')).strip
4
- MAJOR, MINOR, PATCH = STRING.split('.').map(&:to_i)
5
- BUILD = nil
6
- end
4
+ VERSION = '0.7.5'
7
5
  end