BMP Polyglot - Metasploit
This page contains detailed information about how to use the encoder/x86/bmp_polyglot metasploit module. For list of all metasploit modules, visit the Metasploit Module Library.
Module Overview
Name: BMP Polyglot
Module: encoder/x86/bmp_polyglot
Source code: modules/encoders/x86/bmp_polyglot.rb
Disclosure date: -
Last modification time: 2017-07-24 06:26:21 +0000
Supported architecture(s): x86
Supported platform(s): All
Target service / protocol: -
Target network port(s): -
List of CVEs: -
Encodes a payload in such a way that the resulting binary blob is both valid x86 shellcode and a valid bitmap image file (.bmp). The selected bitmap file to inject into must use the BM (Windows 3.1x/95/NT) header and the 40-byte Windows 3.1x/NT BITMAPINFOHEADER. Additionally the file must use either 24 or 32 bits per pixel as the color depth and no compression. This encoder makes absolutely no effort to remove any invalid characters.
Module Ranking and Traits
Module Ranking:
- manual: The exploit is unstable or difficult to exploit and is basically a DoS. This ranking is also used when the module has no use unless specifically configured by the user (e.g.: exploit/windows/smb/psexec). More information about ranking can be found here.
Basic Usage
msf > use encoder/x86/bmp_polyglot
msf encoder(bmp_polyglot) > show targets
... a list of targets ...
msf encoder(bmp_polyglot) > set TARGET target-id
msf encoder(bmp_polyglot) > show options
... show and set options ...
msf encoder(bmp_polyglot) > exploit
Required Options
- BitmapFile: The .bmp file to inject into
Go back to menu.
Msfconsole Usage
Here is how the encoder/x86/bmp_polyglot module looks in the msfconsole:
msf6 > use encoder/x86/bmp_polyglot
msf6 encoder(x86/bmp_polyglot) > show info
Name: BMP Polyglot
Module: encoder/x86/bmp_polyglot
Platform: All
Arch: x86
Rank: Manual
Provided by:
Spencer McIntyre
Description:
Encodes a payload in such a way that the resulting binary blob is
both valid x86 shellcode and a valid bitmap image file (.bmp). The
selected bitmap file to inject into must use the BM (Windows
3.1x/95/NT) header and the 40-byte Windows 3.1x/NT BITMAPINFOHEADER.
Additionally the file must use either 24 or 32 bits per pixel as the
color depth and no compression. This encoder makes absolutely no
effort to remove any invalid characters.
Module Options
This is a complete list of options available in the encoder/x86/bmp_polyglot module:
msf6 encoder(x86/bmp_polyglot) > show options
Module options (encoder/x86/bmp_polyglot):
Name Current Setting Required Description
---- --------------- -------- -----------
BitmapFile yes The .bmp file to inject into
Advanced Options
Here is a complete list of advanced options supported by the encoder/x86/bmp_polyglot module:
msf6 encoder(x86/bmp_polyglot) > show advanced
Module advanced options (encoder/x86/bmp_polyglot):
Name Current Setting Required Description
---- --------------- -------- -----------
VERBOSE false no Enable detailed status messages
WORKSPACE no Specify the workspace for this module
Go back to menu.
Error Messages
This module may fail with the following error messages:
- Bad .bmp, failed to calculate jmp for size
- Bad .bmp, not enough image data for stego operation
- Invalid number of storage bits
- Bad .bmp DIB header, must be 40-byte BITMAPINFOHEADER
- Bad .bmp DIB header, bits per pixel must be must be either 24 or 32
- Bad .bmp DIB header, compression can not be used
- Bad .bmp header, must be 0x424D (BM)
- Bad destego stub size
Check for the possible causes from the code snippets below found in the module source code. This can often times help in identifying the root cause of the problem.
Bad .bmp, failed to calculate jmp for size
Here is a relevant code snippet related to the "Bad .bmp, failed to calculate jmp for size" error message:
237: # - is also a valid x86 jmp instruction to land on the assembly stub
238: def calc_new_size(orig_size, stub_length)
239: minimum_jump = BM_HEADER_SIZE + DIB_HEADER_SIZE - 2 # -2 for the offset of the size in the BM header
240: calc = SizeCalculator.new(orig_size + stub_length, minimum_jump)
241: size = calc.calculate.to_i
242: raise EncodingError, 'Bad .bmp, failed to calculate jmp for size' if size < orig_size
243:
244: jump = calc.size_to_jmp(size)
245: pre_pad = jump - minimum_jump
246: post_pad = size - orig_size - stub_length - pre_pad
247: return { :new_size => size, :post_pad => post_pad, :pre_pad => pre_pad }
Bad .bmp, not enough image data for stego operation
Here is a relevant code snippet related to the "Bad .bmp, not enough image data for stego operation" error message:
251: # shellcode buffer into the image data
252: def calc_required_lsbs(sc_len, data_len)
253: return 1 if sc_len * 8 <= data_len
254: return 2 if sc_len * 4 <= data_len
255: return 4 if sc_len * 2 <= data_len
256: raise EncodingError, 'Bad .bmp, not enough image data for stego operation'
257: end
258:
259: # asm stub that will extract the payload from the least significant bits of
260: # the binary data which directly follows it
261: def make_destego_stub(shellcode_size, padding, lsbs = 1)
Invalid number of storage bits
Here is a relevant code snippet related to the "Invalid number of storage bits" error message:
257: end
258:
259: # asm stub that will extract the payload from the least significant bits of
260: # the binary data which directly follows it
261: def make_destego_stub(shellcode_size, padding, lsbs = 1)
262: raise RuntimeError, 'Invalid number of storage bits' unless [1, 2, 4].include?(lsbs)
263: gen_regs = [ 'eax', 'ebx', 'ecx', 'edx' ].shuffle
264: ptr_regs = [ 'edi', 'esi' ].shuffle
265: # declare logical registers
266: dst_addr_reg = Rex::Poly::LogicalRegister::X86.new('dst_addr', ptr_regs.pop)
267: src_addr_reg = Rex::Poly::LogicalRegister::X86.new('src_addr', ptr_regs.pop)
Bad .bmp DIB header, must be 40-byte BITMAPINFOHEADER
Here is a relevant code snippet related to the "Bad .bmp DIB header, must be 40-byte BITMAPINFOHEADER" error message:
373: data
374: end
375:
376: def validate_dib_header(dib_header)
377: size, _, _, _, bbp, compression, _, _, _, _, _ = dib_header.unpack('VVVvvVVVVVV')
378: raise EncodingError, 'Bad .bmp DIB header, must be 40-byte BITMAPINFOHEADER' if size != DIB_HEADER_SIZE
379: raise EncodingError, 'Bad .bmp DIB header, bits per pixel must be must be either 24 or 32' if bbp != 24 && bbp != 32
380: raise EncodingError, 'Bad .bmp DIB header, compression can not be used' if compression != 0
381: end
382:
383: def encode(buf, badchars = nil, state = nil, platform = nil)
Bad .bmp DIB header, bits per pixel must be must be either 24 or 32
Here is a relevant code snippet related to the "Bad .bmp DIB header, bits per pixel must be must be either 24 or 32" error message:
374: end
375:
376: def validate_dib_header(dib_header)
377: size, _, _, _, bbp, compression, _, _, _, _, _ = dib_header.unpack('VVVvvVVVVVV')
378: raise EncodingError, 'Bad .bmp DIB header, must be 40-byte BITMAPINFOHEADER' if size != DIB_HEADER_SIZE
379: raise EncodingError, 'Bad .bmp DIB header, bits per pixel must be must be either 24 or 32' if bbp != 24 && bbp != 32
380: raise EncodingError, 'Bad .bmp DIB header, compression can not be used' if compression != 0
381: end
382:
383: def encode(buf, badchars = nil, state = nil, platform = nil)
384: in_bmp = File.open(datastore['BitmapFile'], 'rb')
Bad .bmp DIB header, compression can not be used
Here is a relevant code snippet related to the "Bad .bmp DIB header, compression can not be used" error message:
375:
376: def validate_dib_header(dib_header)
377: size, _, _, _, bbp, compression, _, _, _, _, _ = dib_header.unpack('VVVvvVVVVVV')
378: raise EncodingError, 'Bad .bmp DIB header, must be 40-byte BITMAPINFOHEADER' if size != DIB_HEADER_SIZE
379: raise EncodingError, 'Bad .bmp DIB header, bits per pixel must be must be either 24 or 32' if bbp != 24 && bbp != 32
380: raise EncodingError, 'Bad .bmp DIB header, compression can not be used' if compression != 0
381: end
382:
383: def encode(buf, badchars = nil, state = nil, platform = nil)
384: in_bmp = File.open(datastore['BitmapFile'], 'rb')
385:
Bad .bmp header, must be 0x424D (BM)
Here is a relevant code snippet related to the "Bad .bmp header, must be 0x424D (BM)" error message:
387: dib_header = in_bmp.read(DIB_HEADER_SIZE)
388: image_data = in_bmp.read
389: in_bmp.close
390:
391: header, original_size, _, _, original_offset = header.unpack('vVvvV')
392: raise EncodingError, 'Bad .bmp header, must be 0x424D (BM)' if header != 0x4d42
393: validate_dib_header(dib_header)
394:
395: lsbs = calc_required_lsbs(buf.length, image_data.length)
396:
397: details = calc_new_size(original_size, DESTEGO_STUB_SIZE)
Bad destego stub size
Here is a relevant code snippet related to the "Bad destego stub size" error message:
397: details = calc_new_size(original_size, DESTEGO_STUB_SIZE)
398: destego_stub = make_destego_stub(buf.length, details[:post_pad], lsbs)
399: if destego_stub.length != DESTEGO_STUB_SIZE
400: # this is likely a coding error caused by updating the make_destego_stub
401: # method but not the DESTEGO_STUB_SIZE constant
402: raise EncodingError, 'Bad destego stub size'
403: end
404:
405: pre_image_data = make_pad(details[:pre_pad]) + destego_stub + make_pad(details[:post_pad])
406: new_offset = original_offset + pre_image_data.length
407:
Go back to menu.
Related Pull Requests
- #8716 Merged Pull Request: Print_Status -> Print_Good (And OCD bits 'n bobs)
- #8338 Merged Pull Request: Fix msf/core and self.class msftidy warnings
- #6655 Merged Pull Request: use MetasploitModule as a class name
- #6648 Merged Pull Request: Change metasploit class names
- #6441 Merged Pull Request: Add an x86/Bitmap polyglot encoder
Go back to menu.
See Also
Check also the following modules related to this module:
- encoder/x86/add_sub
- encoder/x86/alpha_mixed
- encoder/x86/alpha_upper
- encoder/x86/avoid_underscore_tolower
- encoder/x86/avoid_utf8_tolower
- encoder/x86/bloxor
- encoder/x86/call4_dword_xor
- encoder/x86/context_cpuid
- encoder/x86/context_stat
- encoder/x86/context_time
- encoder/x86/countdown
- encoder/x86/fnstenv_mov
- encoder/x86/jmp_call_additive
- encoder/x86/nonalpha
- encoder/x86/nonupper
- encoder/x86/opt_sub
- encoder/x86/service
- encoder/x86/shikata_ga_nai
- encoder/x86/single_static_bit
- encoder/x86/unicode_mixed
- encoder/x86/unicode_upper
- encoder/x86/xor_dynamic
Authors
Spencer McIntyre
Version
This page has been produced using Metasploit Framework version 6.1.24-dev. For more modules, visit the Metasploit Module Library.
Go back to menu.