SLAE Assignment #7 – Custom Crypter

The tasks for the 7th assignment are:

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

The programing language I am most comfortable with is python, so i wanted to make sure that it is possible to execute shellcode from within a python script. This would allow me to create one standalone script that count encrypt/decrypt shellcode, and then execute the shellcode, without having to use a second shellcode runner written in C or some other language.

I wasn’t sure how to execute the shellcode from within python until I found the following resource:

This uses the python “cytpes” library which allows python to C compatibile datatypes and libraries. This allows you to load shellcode into memory space and then execute from that memory space. The python code for this is shown below.

def RunShellcode(shellcode):
libc = CDLL(‘’)
sc = c_char_p(shellcode)
size = len(shellcode)
addr = c_void_p(libc.valloc(size))
memmove(addr, sc, size)
libc.mprotect(addr, size, 0x7)
run = cast(addr, CFUNCTYPE(c_void_p))

Encryption scheme

The encryption scheme I wanted to use was AES to provide strong encryption for the shellcode. Many people have already created shellcode encrypters/decrypters with python. I used the following as a references while creating my own:

AES encryption requires that a key and an initialization vector (IV) to be provided. Both of these need to have a length in bytes that is a multiple of 16.

For the key, I wanted the user to be able to provide a key to the crypter of their choosing. I didn’t want the user to be forced to provide a key of a fixed length like 16, so I had the crypter take any key and then generate a 16 byte long hash with the following python code.

key = pyscrypt.hash(args.key, “mysalt”, 1024, 1, 1, 16)

The IV would be created randomly when the encryption process was run, using the following.

def Encrypt(cleartext, key):
iv = urandom(AES.block_size)
cleartext = padding(cleartext)
cipher=, AES.MODE_CBC, iv)
return iv + cipher.encrypt(bytes(cleartext))

In order for the decryption process to get the IV, the Encrypt function would return the IV along with the cipher text. The decryption process would then obtain the IV by looking at the first 16 bytes of the cipher text provided by the user.

def Decrypt(ciphertext, key):
iv = ciphertext[:AES.block_size] # get IV from first 16 characters
decipher =, AES.MODE_CBC, iv)
return unpadded(decipher.decrypt(bytes(ciphertext[AES.block_size:])))

User interaction

I wanted this crypter to do both encryption and decryption, so that only one script would need to be used by the user instead of a separate encrypter and decrypter. I also wanted the user to be able to provide any encryption key and shellcode through the command line so that they wouldn’t need to edit the script and hardcode the values. The following command line arguments were used by the crypter.

  • –key – The key to use for encryption/decryption. This key was a string that would be hashed to a length of 16 bytes
  • –shellcode – The shellcode to be encrypted/decrypted. To encrypt, the shellcode needed to be provided in “\xAA” format. to decrypt, the user would provide the shellcode output from the encryption process
  • –encrypt – tell the crypter to encrypt the provided shellcode and output the ciphertext
  • –decrypt – tell the crypter to decrypt the provided shellcode and then execute the shellcode

Originally, I wanted the encryption process to output the encrypted shellcode in the “\xAA” format, the same as the way the user provided it. However, this never seemed to work quite right, so instead the encrypted output took the raw bytes, base64 encoded it, and then printed it to the screen. When the user wanted to decrypt the shellcode, they would provide the base64 encoded encrypted shellcode.

To test the crypter, I used the “execve stack” shellcode that would launch a /bin/bash shell. A successful test is shown below.

The python script can be found here:

Creating an executable

To make the crypter more portable and able to run on a system without python installed, the tool “pyInstaller” was used to create an ELF file that would have all the necessary python libraries for it to execute, shown blow.

The output from pyInstaller was an ELF file that could be used as a standalone executable.

The new executable version of the crypter was tested with the same “execve stack” shellcode, but with a different encryption key used. A successful test is shown below.

The crypter executable can be found here (warning, this is an executable file!):

With this, a portable executable was created that would allow for a user to encrypt, and then decrypt and execute their shellcode.

SLAE Student Disclaimer

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:

Student ID: SLAE- 1373