SLAE Assignment #7 – Custom Shellcode Crypter

Final assignment of the SecurityTube SLAE Exam! In this assignment I’ll develop a custom crypter/decrypter for shellcode.

Disclaimer:

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: SLAE-890

Sources, as always, on my github page. Now let’s roll.

Since I’m a big fan of the AES algorithm, I wanted to create something around this. Luckily, there’s a tiny, lightweight AES implementation out there that I could utilize. It’s called “Tiny AES 128 in C” and you can find it here: https://github.com/kokke/tiny-AES128-C

So, let’s take a look at the crypter. It’s generating a random 128 bit (16 byte) encryption key by doing this:


unsigned char * generate_random_key(void)
{
	srand(time(NULL));
	for (int i=0;i<16;i++)
		key[i] = rand() % 256;

	return key;
}

We can then use this key to encrypt the provided shellcode bytes. We’re doing CBC (cipher block chaining) and the code to encrypt looks like this:


	uint8_t iv[]  = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

	unsigned char* dst_buffer = malloc(strlen(shellcode));

	AES128_CBC_encrypt_buffer(dst_buffer, shellcode, strlen(shellcode), key, iv);

Pretty simple, eh?

An example output of the crypter looks like this:

Selection_100.png

EZ. Now let’s take a look at the decrypter. First, we decrypt the shellcode with a given AES key. Code looks like that:


	// Initalization vector
	uint8_t iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

	// allocate destination buffer -> here we'll decrypt the shellcode into
	unsigned char * dst_buffer = malloc(strlen(encrypted_shellcode));

	int (*ret)() = (int(*)())dst_buffer;

	printf("[*] Decrypting AES Shellcode (beep-bleep-blop) ...\n\n");

	for (int offset=0; offset < strlen(encrypted_shellcode);offset+=16)
	{
		if (offset == 0)
			// first round requires passing key and IV
			AES128_CBC_decrypt_buffer(dst_buffer+offset, encrypted_shellcode+offset, 16, aes_key, iv);
		else
			AES128_CBC_decrypt_buffer(dst_buffer+offset, encrypted_shellcode+offset, 16, 0, 0);
	}


Once that’s done, we jump into the decrypted shellcode, executing it. After that, it’s just cleaning up (and avoiding memory leaks).


	ret();

	// fr33 buff0rz
	free(dst_buffer);

Example output of a decrypter, loaded with the execve-stack payload:

Selection_101

Looking good!

Not 100% happy with the code since it requires recompiling for every new shellcode/key, but I ran out of time so I couldn’t finish something fancier (using ARGV or STDIN as input). Will do that maybe at a later time 😉

Bye folks … have a nice day!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s