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