Browse Source

Address x86/Bmp polyglot encoder feedback

Spencer McIntyre 4 years ago
parent
commit
24290dc169
1 changed files with 44 additions and 48 deletions
  1. 44
    48
      modules/encoders/x86/bmp_polyglot.rb

+ 44
- 48
modules/encoders/x86/bmp_polyglot.rb View File

@@ -52,6 +52,20 @@ get_bit:                ; <-----------------------------------------------------
52 52
 # calculate the smallest increase of a 32-bit little endian integer which is
53 53
 # also a valid x86 jmp opcode of the specified minimum size.
54 54
 class SizeCalculator
55
+
56
+  BYTE_NOPS = [
57
+    0x42, # inc edx
58
+    0x45, # inc ebp
59
+    0x4a, # dec edx
60
+    0x4d, # dec ebp
61
+    0x90, # xchg eax, eax / nop
62
+    0xf5, # cmc
63
+    0xf8, # clc
64
+    0xf9, # stc
65
+    0xfc, # cld
66
+    0xfd  # std
67
+  ]
68
+
55 69
   def initialize(size, minimum_jump)
56 70
     @original_size = size
57 71
     raise if minimum_jump < 0 || minimum_jump > 0xff
@@ -72,30 +86,30 @@ class SizeCalculator
72 86
     size = [ @original_size ].pack('V').unpack('CCCC')
73 87
 
74 88
     0.upto(2) do |i|
75
-      b0 = size[i]
76
-      b1 = size[i + 1]
77
-      b2 = size[i + 2].to_i
78
-      b3 = size[i + 3].to_i
79
-      b4 = size[i + 4].to_i
89
+      byte_0 = size[i]
90
+      byte_1 = size[i + 1]
91
+      byte_2 = size[i + 2].to_i
92
+      byte_3 = size[i + 3].to_i
93
+      byte_4 = size[i + 4].to_i
80 94
       min_jmp = (@minimum_jump - 5 - i)
81 95
 
82
-      if [b2, b3, b4].inject{ |sum, x| sum + x } > 0  # this jmp would be too large
83
-        if b0 > 0xfd
96
+      if byte_2 + byte_3 + byte_4 > 0  # this jmp would be too large
97
+        if byte_0 > 0xfd
84 98
           size = increment_size(size, i)
85 99
         end
86
-        size[i] = round_up_to_nop(b0)
100
+        size[i] = round_up_to_nop(byte_0)
87 101
         next
88 102
       end
89 103
 
90
-      if b0 > 0xe9
91
-        if b0 > 0xfd
104
+      if byte_0 > 0xe9
105
+        if byte_0 > 0xfd
92 106
           size = increment_size(size, i)
93 107
         end
94
-        size[i] = round_up_to_nop(b0)
108
+        size[i] = round_up_to_nop(byte_0)
95 109
       else
96 110
         size[i] = 0xe9
97
-        b1 = min_jmp if b1 < min_jmp
98
-        size[i + 1] = b1
111
+        byte_1 = min_jmp if byte_1 < min_jmp
112
+        size[i + 1] = byte_1
99 113
         return size.pack('CCCC').unpack('V')[0]
100 114
       end
101 115
     end
@@ -106,24 +120,24 @@ class SizeCalculator
106 120
     size = [ @original_size ].pack('V').unpack('CCCC')
107 121
 
108 122
     0.upto(2) do |i|
109
-      b0 = size[i]
110
-      b1 = size[i + 1]
123
+      byte_0 = size[i]
124
+      byte_1 = size[i + 1]
111 125
       min_jmp = (@minimum_jump - 2 - i)
112 126
 
113
-      if b0 > 0xeb
114
-        if b0 > 0xfd
127
+      if byte_0 > 0xeb
128
+        if byte_0 > 0xfd
115 129
           size = increment_size(size, i)
116 130
         end
117
-        size[i] = round_up_to_nop(b0)
131
+        size[i] = round_up_to_nop(byte_0)
118 132
       else
119 133
         size[i] = 0xeb
120
-        if b1 > 0x7f
121
-          b1 = min_jmp
134
+        if byte_1 > 0x7f
135
+          byte_1 = min_jmp
122 136
           size = increment_size(size, i + 1)
123
-        elsif b1 < min_jmp
124
-          b1 = min_jmp
137
+        elsif byte_1 < min_jmp
138
+          byte_1 = min_jmp
125 139
         end
126
-        size[i + 1] = b1
140
+        size[i + 1] = byte_1
127 141
         return size.pack('CCCC').unpack('V')[0]
128 142
       end
129 143
     end
@@ -158,21 +172,7 @@ class SizeCalculator
158 172
   end
159 173
 
160 174
   def round_up_to_nop(opcode)
161
-    byte_nops = [
162
-      0x42, # inc edx
163
-      0x45, # inc ebp
164
-      0x4a, # dec edx
165
-      0x4d, # dec ebp
166
-      0x90, # xchg eax, eax / nop
167
-      0xf5, # cmc
168
-      0xf8, # clc
169
-      0xf9, # stc
170
-      0xfc, # cld
171
-      0xfd  # std
172
-    ]
173
-    byte_nops.each do |nop|
174
-      return nop if opcode <= nop
175
-    end
175
+    BYTE_NOPS.find { |nop| opcode <= nop }
176 176
   end
177 177
 
178 178
 end
@@ -278,7 +278,6 @@ class Metasploit4 < Msf::Encoder
278 278
     get_eip_nop = Proc.new { |b| [0x90, 0x40 + b.regnum_of([bit_reg, byte_reg, dst_addr_reg, src_addr_reg].sample), 0x48 + b.regnum_of([bit_reg, byte_reg, dst_addr_reg, src_addr_reg].sample)].sample.chr }
279 279
     get_eip = Proc.new { |b|
280 280
       [
281
-        Proc.new { |b| get_eip_nop.call(b) + "\xe8\x00\x00\x00\x00" + (0x58 + b.regnum_of(src_addr_reg)).chr },
282 281
         Proc.new { |b| "\xe8" + [0, 1].sample.chr + "\x00\x00\x00" + get_eip_nop.call(b) + (0x58 + b.regnum_of(src_addr_reg)).chr },
283 282
         Proc.new { |b| "\xe8\xff\xff\xff\xff" + (0xc0 + b.regnum_of([bit_reg, byte_reg, dst_addr_reg, src_addr_reg].sample)).chr + (0x58 + b.regnum_of(src_addr_reg)).chr },
284 283
       ].sample.call(b)
@@ -378,24 +377,24 @@ class Metasploit4 < Msf::Encoder
378 377
     data
379 378
   end
380 379
 
381
-  def validate_dib_header(bmp)
382
-    dib_header = bmp.read(DIB_HEADER_SIZE)
380
+  def validate_dib_header(dib_header)
383 381
     size, _, _, _, bbp, compression, _, _, _, _, _ = dib_header.unpack('VVVvvVVVVVV')
384 382
     raise EncodingError, 'Bad .bmp DIB header, must be 40-byte BITMAPINFOHEADER' if size != DIB_HEADER_SIZE
385 383
     raise EncodingError, 'Bad .bmp DIB header, bits per pixel must be must be either 24 or 32' if bbp != 24 && bbp != 32
386 384
     raise EncodingError, 'Bad .bmp DIB header, compression can not be used' if compression != 0
387
-    dib_header
388 385
   end
389 386
 
390 387
   def encode(buf, badchars = nil, state = nil, platform = nil)
391 388
     in_bmp = File.open(datastore['BitmapFile'], 'rb')
392 389
 
393 390
     header = in_bmp.read(BM_HEADER_SIZE)
391
+    dib_header = in_bmp.read(DIB_HEADER_SIZE)
392
+    image_data = in_bmp.read
393
+    in_bmp.close
394
+
394 395
     header, original_size, _, _, original_offset = header.unpack('vVvvV')
395 396
     raise EncodingError, 'Bad .bmp header, must be 0x424D (BM)' if header != 0x4d42
396
-
397
-    dib_header = validate_dib_header(in_bmp)
398
-    image_data = in_bmp.read
397
+    validate_dib_header(dib_header)
399 398
 
400 399
     lsbs = calc_required_lsbs(buf.length, image_data.length)
401 400
 
@@ -413,11 +412,8 @@ class Metasploit4 < Msf::Encoder
413 412
     bmp_img = ''
414 413
     bmp_img << [0x4d42, details[:new_size], 0, 0, new_offset].pack('vVvvV')
415 414
     bmp_img << dib_header
416
-
417 415
     bmp_img << pre_image_data
418 416
     bmp_img << stegoify(buf, image_data, lsbs)
419
-
420
-    in_bmp.close
421 417
     bmp_img
422 418
   end
423 419
 end

Loading…
Cancel
Save