Assignment

  • Create a custom crypter like the one shown in the “crypters” video
  • Free to use any existing encryption schema
  • Can use any programming language

Python AES Custom Crypter

For our final assignment we are going to create a custom AES crypter in Python.

We are using the PyCryptodome library for our encryption functions so need to install this into our python environment as follows:

pip install pycryptodome

I had a couple of goals for the crypter in that I wanted it to be useable rather than just a proof of concept, therefore both encrypt and decrypt from the command line and optionally run the decrypted shellcode. A few things to note about AES CBC encryption that were learned along the way are that the Key, IV and data must all have 16 bytes block size. There are very useful pad and unpad functions in the Cryptodome library to take care of this rather than some of the other quirky solutions I noted out there. Finally a shout out to hacktracking for the execute shellcode on linux via python code which I actually stumbled across via BLU3GL0W13’S Blog. Final python code is below:

#!/usr/bin/env python2
# Python AES Encrpyer and decryptor 
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
import argparse
import ctypes
from ctypes import *

def encrypt(key,shellcode,IV):
    cipher = AES.new(key,AES.MODE_CBC, IV)
    return cipher.encrypt(shellcode)

def decrypt(key,shellcode,IV):
    cipher = AES.new(key,AES.MODE_CBC, IV)
    return cipher.decrypt(shellcode)

def bytes_to_hex(data):
    output = ""
    for i in data:
        output  += "\\x" + i.encode("hex")
    return output

def encrypt_shellcode(data):
    IV = get_random_bytes(16)
    key = get_random_bytes(16)
    print("\n**** Encrypting Shellcode ****\n")
    print("Key: " + bytes_to_hex(key))
    print("IV : " +bytes_to_hex(IV) +"\n")
    print("Supplied Shellcode:\n" + bytes_to_hex(data) + "\n")
    padded = pad(data,16)
    encrypted_data = encrypt(key,padded,IV)
    print("Encrypted Shellcode:\n" + bytes_to_hex(encrypted_data)+ "\n")

def decrypt_shellcode(key,shellcode,IV,execute_shellcode):
    print("\n**** Decrypting Shellcode ****\n")
    print("Key: " + bytes_to_hex(key))
    print("IV : " +bytes_to_hex(IV) +"\n")
    print("Supplied Shellcode:\n" + bytes_to_hex(shellcode) + "\n")
    decrypted_data = decrypt(key,shellcode,IV)
    unpadded = unpad(decrypted_data,16)
    print("Decrypted shellcode:\n" + bytes_to_hex(unpadded)+ "\n")
    if execute_shellcode:
        print("Running decrypted shellcode........\n")
        run_shellcode(unpadded)

def run_shellcode(shellcode):
    libC = CDLL('libc.so.6')
    code = c_char_p(shellcode)
    sizeOfDecryptedShellcode = len(shellcode)
    memAddrPointer = c_void_p(libC.valloc(sizeOfDecryptedShellcode))
    codeMovePointer = memmove(memAddrPointer, code, sizeOfDecryptedShellcode)
    protectMemory = libC.mprotect(memAddrPointer, sizeOfDecryptedShellcode, 7)
    run = cast(memAddrPointer, CFUNCTYPE(c_void_p))
    run()

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-e", "--encrypt", help="AES encrypt shellcode ", action="store_true")
    parser.add_argument("-d", "--decrypt", help="AES decrypt shellcode ", action="store_true")
    parser.add_argument("-i", "--iv", help="IV for decryption, supplied as Hex", action="store")
    parser.add_argument("-k", "--key", help="Key for decryption, supplied as Hex", action="store")
    parser.add_argument("-r", "--run", help="Run shellcode after decryption", action="store_true")
    parser.add_argument("shellcode", help="Shellcode, supplied as Hex")
    args = parser.parse_args()
    shellcode_bytes = args.shellcode.replace("x","").replace('"','').decode('hex')
    if args.encrypt:
        encrypt_shellcode(shellcode_bytes)
    if args.decrypt:
        key_bytes = args.key.replace("x","").replace('"','').decode('hex')
        iv_bytes = args.iv.replace("x","").replace('"','').decode('hex')
        decrypt_shellcode(key_bytes,shellcode_bytes,iv_bytes,args.run)

if __name__ == "__main__":
    main()

So finally to test. The encrypt function takes any shellcode passed to it on the command line and generates a random 16 byte key and IV before encrypting the shellcode and outputting it with the IV and Key. So we take the linux/x86/exec whoami shellcode we analysed in Assignment 5 with GDB and pass it to the crypter as seen below.

\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x07\x00\x00\x00\x77\x68\x6f\x61\x6d\x69\x00\x57\x53\x89\xe1\xcd\x80

The crypter generates the encrypted shellcode with IV and key which we then feed back into the decryption routine with the –run flag to execute the shellcode once decrypted. As seen in the below screenshot the shellcode is successfully decrypted and executed displaying the output of “whoami” on screen.

This completes assignment seven, source code is available on GitHub https://github.com/su1s/SLAE

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student ID: SLAE-1436

Leave a Reply

Your email address will not be published. Required fields are marked *