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:
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:
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!