Security News

Cybersecurity news aggregator

🪟
HIGH Vulnerabilities Reddit r/netsec

UnDefend: Chaotic Eclipse's third Defender zero-day blocks all signature updates from a standard user — no admin required

The "UnDefend" zero-day exploit is a low-privilege attack that permanently disables Windows Defender signature updates by using file locking primitives to block access to critical definition and backup files, all from a standard user account without requiring privilege escalation. The article does not provide a CVSS score, specific affected Windows/Defender version ranges, a fixed version, or a workaround.
Read Full Article →

Line 209 of UnDefend.cpp , inside WDKillerCallback , reads: // if you are reading this, you are autistic. The researcher who wrote BlueHammer, who wrote RedSun, who left Windows Defender unpatched for three weeks before Microsoft touched it — they knew people would read this code. They left a comment for the audience they expected. This is the third zero-day from Nightmare-Eclipse in April 2026. BlueHammer patched Tuesday. RedSun still open. UnDefend dropped this week, no CVE yet, no patch on the horizon. Each one is a different weapon against the same target. Unlike the first two, UnDefend requires no privilege escalation. It runs as a standard user. It doesn’t need SYSTEM. It doesn’t use oplocks or object namespace symlinks or Cloud Files APIs. What it does is simpler and in some ways more dangerous: it makes Defender permanently unable to update its signatures, from an account with no special access, using file locking primitives that have existed since Windows NT. The README adds one more detail that isn’t in the code: “Now funnily enough, I found a way to lie to the EDR web console to show that defender is up and running with the latest update even if it’s not. I was thinking about publishing the code but after thinking about it, it will cause waaay too much damage so I think I’ll keep that stuff stashed for now.” Same author. Same month. Same decision: publish the proof, withhold the weapon. In BlueHammer it was two comment characters separating the PoC from a full domain credential harvest. In UnDefend it’s unshipped code separating a noisy DoS from a silent, invisible persistence enabler. Let’s walk the code. What the Tool Actually Does UnDefend.cpp is 452 lines. It has four independent mechanisms that collectively lock Defender out of its own update pipeline. No mechanism depends on another — if one fails, the others still run. Standard user throughout. The entry point ( wmain ) does three things before entering its main loop: Reads HKLM\SOFTWARE\Microsoft\Windows Defender\ProductAppDataPath to find Defender’s data directory Constructs the Definition Updates subdirectory path Immediately calls TryLockBackup() That third step is why rollback doesn’t save you. Mechanism One: Kill the Rollback Before the Fight Starts TryLockBackup() runs before any threads are spawned. It opens two files: wcscat (gbackupfile1, L " \\ Backup \\ mpavbase.lkg" ); wcscat (gbackupfile2, L " \\ Backup \\ mpavbase.vdm" ); mpavbase.vdm is the active virus definition module. mpavbase.lkg is the last-known-good backup — the copy Defender falls back to when an update fails or corrupts the active signatures. The open call is NtCreateFile with no sharing flags at all — the fourth sharing parameter is NULL : ntstat = NtCreateFile ( & hlock1 , GENERIC_READ | SYNCHRONIZE | GENERIC_EXECUTE, & objattr , & iostat , NULL , FILE_ATTRIBUTE_NORMAL, NULL , // <-- no sharing FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT, NULL , NULL ); FILE_SYNCHRONOUS_IO_ALERT means the kernel holds the thread’s I/O context synchronously — this is an internal NT flag that Defender’s own file operations use. The open succeeds because nothing has locked these files yet. Once it succeeds, LockFileEx places a blocking exclusive byte-range lock across the full file: LockFileEx (hlock1, LOCKFILE_EXCLUSIVE_LOCK, NULL , li.LowPart, li.HighPart, & ov ); Now: if a signature update fails and Defender tries to reload from backup, it calls NtCreateFile on mpavbase.lkg and gets STATUS_SHARING_VIOLATION . The fallback is gone. Defender is stuck on whatever signatures it had when TryLockBackup() ran. Mechanism Two: The Staging Directory Race The main loop in wmain watches Definition Updates\ — the directory where Windows Update stages new signature packages before Defender loads them. It uses ReadDirectoryChangesW : ReadDirectoryChangesW (hmonitordir, notifydata, sizeof (notifydata), TRUE , FILE_NOTIFY_CHANGE_SIZE, & retbytes , NULL , NULL ); FILE_NOTIFY_CHANGE_SIZE specifically. Not FILE_NOTIFY_CHANGE_LAST_WRITE . The notification fires on file size changes, which means the write must already be in progress or complete before the callback triggers. This is intentional: the attacker doesn’t want to race against an empty file, they want to grab a file with content that Defender is about to load. When a notification arrives with FILE_ACTION_MODIFIED , the main loop spawns UpdateBlockerThread for that file. The thread opens the file: stat = NtCreateFile ( & hlock , GENERIC_READ | SYNCHRONIZE, & objattr , & iostat , NULL , FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE | FILE_SHARE_DELETE, // <-- no FILE_SHARE_READ FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL , NULL ); The sharing flags are the mechanism. FILE_SHARE_WRITE | FILE_SHARE_DELETE is explicitly present — which means Windows Update’s write process can keep writing. FILE_SHARE_READ is explicitly absent — which means any process that tries to open this file for reading gets STATUS_SHARING_VIOLATION . Defender’s si...

Share this article