Sub Encoder (optimised) - Metasploit


This page contains detailed information about how to use the encoder/x86/opt_sub metasploit module. For list of all metasploit modules, visit the Metasploit Module Library.

Module Overview


Name: Sub Encoder (optimised)
Module: encoder/x86/opt_sub
Source code: modules/encoders/x86/opt_sub.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 using a series of SUB instructions and writing the encoded value to ESP. This concept is based on the known SUB encoding approach that is widely used to manually encode payloads with very restricted allowed character sets. It will not reset EAX to zero unless absolutely necessary, which helps reduce the payload by 10 bytes for every 4-byte chunk. ADD support hasn't been included as the SUB instruction is more likely to avoid bad characters anyway. The payload requires a base register to work off which gives the start location of the encoder payload in memory. If not specified, it defaults to ESP. If the given register doesn't point exactly to the start of the payload then an offset value is also required. Note: Due to the fact that many payloads use the FSTENV approach to get the current location in memory there is an option to protect the start of the payload by setting the 'OverwriteProtect' flag to true. This adds 3-bytes to the start of the payload to bump ESP by 32 bytes so that it's clear of the top of the payload.

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/opt_sub
msf encoder(opt_sub) > show targets
    ... a list of targets ...
msf encoder(opt_sub) > set TARGET target-id
msf encoder(opt_sub) > show options
    ... show and set options ...
msf encoder(opt_sub) > exploit

Go back to menu.

Msfconsole Usage


Here is how the encoder/x86/opt_sub module looks in the msfconsole:

msf6 > use encoder/x86/opt_sub

msf6 encoder(x86/opt_sub) > show info

       Name: Sub Encoder (optimised)
     Module: encoder/x86/opt_sub
   Platform: All
       Arch: x86
       Rank: Manual

Provided by:
  OJ Reeves <[email protected]>

Description:
  Encodes a payload using a series of SUB instructions and writing the 
  encoded value to ESP. This concept is based on the known SUB 
  encoding approach that is widely used to manually encode payloads 
  with very restricted allowed character sets. It will not reset EAX 
  to zero unless absolutely necessary, which helps reduce the payload 
  by 10 bytes for every 4-byte chunk. ADD support hasn't been included 
  as the SUB instruction is more likely to avoid bad characters 
  anyway. The payload requires a base register to work off which gives 
  the start location of the encoder payload in memory. If not 
  specified, it defaults to ESP. If the given register doesn't point 
  exactly to the start of the payload then an offset value is also 
  required. Note: Due to the fact that many payloads use the FSTENV 
  approach to get the current location in memory there is an option to 
  protect the start of the payload by setting the 'OverwriteProtect' 
  flag to true. This adds 3-bytes to the start of the payload to bump 
  ESP by 32 bytes so that it's clear of the top of the payload.

Module Options


This is a complete list of options available in the encoder/x86/opt_sub module:

msf6 encoder(x86/opt_sub) > show options

Module options (encoder/x86/opt_sub):

   Name              Current Setting  Required  Description
   ----              ---------------  --------  -----------
   OverwriteProtect  false            no        Indicate if the encoded payload requires protection against being overwritten
   ValidCharSet                       no        Specify a known set of valid chars (ALPHA, ALPHANUM, FILEPATH)

Advanced Options


Here is a complete list of advanced options supported by the encoder/x86/opt_sub module:

msf6 encoder(x86/opt_sub) > show advanced

Module advanced options (encoder/x86/opt_sub):

   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:

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 character set contains characters that are required for this encoder to function.


Here is a relevant code snippet related to the "Bad character set contains characters that are required for this encoder to function." error message:

156:	
157:	    all_bytes_valid = @required_bytes.bytes.reduce(true) { |a, byte| a && @valid_bytes.include?(byte) }
158:	
159:	    # determine if we have any invalid characters that we rely on.
160:	    unless all_bytes_valid
161:	      raise EncodingError, "Bad character set contains characters that are required for this encoder to function."
162:	    end
163:	
164:	    unless @asm['PUSH'][@base_reg]
165:	      raise EncodingError, "Invalid base register"
166:	    end

Invalid base register


Here is a relevant code snippet related to the "Invalid base register" error message:

160:	    unless all_bytes_valid
161:	      raise EncodingError, "Bad character set contains characters that are required for this encoder to function."
162:	    end
163:	
164:	    unless @asm['PUSH'][@base_reg]
165:	      raise EncodingError, "Invalid base register"
166:	    end
167:	
168:	    # get the offset from the specified base register, or default to zero if not specifed
169:	    reg_offset = (datastore['BufferOffset'] || 0).to_i
170:	

Unable to find AND-able chars resulting 0 in the valid character set.


Here is a relevant code snippet related to the "Unable to find AND-able chars resulting 0 in the valid character set." error message:

171:	    # calculate two opposing values which we can use for zeroing out EAX
172:	    @clear1, @clear2 = find_opposite_bytes(@valid_chars)
173:	
174:	    # if we can't then we bomb, because we know we need to clear out EAX at least once
175:	    unless @clear1
176:	      raise EncodingError, "Unable to find AND-able chars resulting 0 in the valid character set."
177:	    end
178:	
179:	    # with everything set up, we can now call the encoding routine
180:	    state.decoder_stub = encode_payload(state.buf, reg_offset, datastore['OverwriteProtect'])
181:	

Couldn't offset base register.


Here is a relevant code snippet related to the "Couldn't offset base register." error message:

281:	    base_reg_offset = data.length
282:	
283:	    # Write out a stubbed placeholder for the offset instruction based on
284:	    # the base register, we'll update this later on when we know how big our payload is.
285:	    encoded, _ = sub_3(0, 0)
286:	    raise EncodingError, "Couldn't offset base register." if encoded.nil?
287:	    data << create_sub(encoded)
288:	
289:	    # finally push the value of EAX back into ESP
290:	    data << @asm['PUSH']['EAX']
291:	    data << @asm['POP']['ESP']

Couldn't encode payload


Here is a relevant code snippet related to the "Couldn't encode payload" error message:

305:	        data << zero_eax
306:	        encoded, previous = sub_3(chunk, 0)
307:	      end
308:	
309:	      # if we're still nil here, then we have an issue
310:	      raise EncodingError, "Couldn't encode payload" if encoded.nil?
311:	
312:	      data << create_sub(encoded)
313:	    end
314:	
315:	    # Now that the entire payload has been generated, we figure out offsets

Couldn't encode protection


Here is a relevant code snippet related to the "Couldn't encode protection" error message:

317:	    # our decoder
318:	    total_offset = reg_offset + data.length + (chunks.length * 4) - 1
319:	    encoded, _ = sub_3(total_offset, 0)
320:	
321:	    # if we're still nil here, then we have an issue
322:	    raise EncodingError, "Couldn't encode protection" if encoded.nil?
323:	    patch = create_sub(encoded)
324:	
325:	    # patch in the correct offset back at the start of our payload
326:	    data[base_reg_offset .. base_reg_offset + patch.length] = patch
327:	

Go back to menu.


Go back to menu.

See Also


Check also the following modules related to this module:

Authors


OJ Reeves <oj[at]buffered.io>

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.