INSIGHTS | September 3, 2026

The DRM Flag That Isn’t DRM

SetWindowDisplayAffinity makes a window disappear from screenshots, screen shares, and Recall snapshots. Vendors sell that as “screenshot protection,” and procurement checklists tick it off as data-exfiltration risk mitigated. Microsoft’s own documentation for the API says otherwise. This post breaks down what the flag actually guarantees, who can route around it and how, and why a black screenshot is the beginning of a threat model rather than the end of one.

The Pitch, and the Problem with It

Open a modern secure-messaging app, password manager, or exam browser on Windows 11, hit PrtSc, and paste. The result is a black rectangle, or nothing at all. Vendor marketing calls it “screenshot protection.” Privacy blogs call it “blocks Recall.” The procurement checklist gets a tick next to data exfiltration: mitigated.

Microsoft’s own documentation for the API doing the work says otherwise:

Unlike a security feature or an implementation of Digital Rights Management (DRM), there is no guarantee that using SetWindowDisplayAffinity … will strictly protect window content.

The feature that makes a window disappear from screenshots is explicitly not a security feature, according to the people who built it. Yet vendors build a whole category of “privacy” and “DLP” features on top of it.

Microsoft is not consistent about this either. The Recall management documentation, aimed at developers whose remote desktop clients lack screen capture protection, calls adding it “an easy feature,” labels it “This DRM flag,” and points them to the very same SetWindowDisplayAffinity API whose own reference page insists it is not DRM. Two documents, one API, opposite claims.

That gap, between what the control implies and what it guarantees, is what this post takes apart. Attackers route around it without much thought. Defenders keep inheriting it as a checkbox someone else already ticked.

How the Flag Works

The Win32 function doing the work:

BOOL SetWindowDisplayAffinity(
  [in] HWND  hWnd,      // top-level window, must belong to the calling process
  [in] DWORD dwAffinity // the exclusion mode
);

Three values for the dwAffinity parameter matter:

ConstantValueBehavior in a capture
WDA_NONE0x00000000No restriction. Normal capture.
WDA_MONITOR0x00000001Window shows only on a physical monitor; captures render it black.
WDA_EXCLUDEFROMCAPTURE0x00000011Window shows only on a physical monitor; captures omit it entirely (no suspicious black box).

WDA_EXCLUDEFROMCAPTURE is the newer, “better” flag. It arrived in Windows 10 Version 2004 (build 19041). Before that, WDA_MONITOR was the only option, and it left a tell-tale black rectangle. The upgrade is cosmetic from a defense standpoint: black box versus empty space. The security boundary is identical.

The difference is in what the capture comes back with. Under WDA_MONITOR, a screenshot or a screen share contains a black rectangle sitting exactly where the window is, and whatever the window overlaps is hidden along with it. Anyone looking at that capture learns that something was being withheld, how big it was, where it sat, and, in the case of a recording, how long it stayed open and when it closed. Under WDA_EXCLUDEFROMCAPTURE, the window is not in the frame and the desktop behind it shows through, so the capture looks like the application was not running at all. The user sharing their screen has no black box to explain, and the people watching get no cue that anything was hidden.

The Desktop Window Manager (DWM) enforces the exclusion. It is the compositor that assembles every window into the final image on screen. When a capture tool asks DWM for a frame of the desktop, DWM builds that frame and leaves the flagged window out of it. The pixels still reach the physical display; they never reach the composited frame handed to the capture tool. The flag embeds nothing in the window’s content and blocks no capture tool from running. Every bypass later in this post is a version of the same idea: get the image from somewhere other than DWM’s composited output, and the exclusion never applies.

Why Developers Reach for It Anyway

It’s an attractive control because:

  • It’s one line of code. No kernel driver, no service, no secure enclave.
  • It’s OS-native. No third-party dependency to vet.
  • It defeats the lazy attacker. PrtSc, Snipping Tool, Zoom/Teams/Meet screen share, OBS via the standard desktop-duplication path: all come up empty. Against a casual insider or an over-eager AI screenshotter, that’s a win.

The Signal case is the honest version of the story. When Microsoft shipped Recall, a background feature that silently snapshots the screen every few seconds into a searchable database, Signal had no developer-facing opt-out to keep chats out of the index. So, Signal set the display-affinity flag on its window. Signal’s own engineers described it, more or less, as a “one weird trick”: abusing a media-protection flag because Microsoft gave privacy apps no proper API. That’s a defensible decision against that specific threat, an OS feature capturing through the normal compositor path. It is not a general-purpose confidentiality control, and Signal never claimed it was.

The failure mode is the marketing leap: a product that “defeats normal screenshots” gets sold as one that “protects sensitive data,” with no threat model in between.

Who This Does Not Stop

Every control ever shipped can be bypassed, so the useful question is who can bypass this one, holding what access. Three capability tiers cover it.

Tier 0: The User Who Avoids the Blocked Path

Even with zero special access, plenty of capture paths never touch the DWM-composited surface the flag protects.

  • The analog hole: a phone camera pointed at the monitor. The pixels that reach a retina reach a camera sensor the same way. No API closes this, and Microsoft’s docs concede as much.
  • Context that breaks DWM: the protection only works while DWM is composing the desktop, a limit Microsoft states in its documentation. Remote Desktop sessions disable DWM, so a window invisible to a local screenshot can render perfectly over RDP. Certain remote-assistance and mirroring stacks, and some virtual-display configurations, land in the same bucket. The control silently fails open, which is the worst way for a control to fail.
  • VM quirks: in basic VMs without GPU acceleration, the compositor path can differ enough that the exclusion doesn’t behave as advertised.

None of these require privilege escalation. They require not using the one capture method the flag was designed to block. Tier 0 is where most real-world leakage happens, and it leaves almost nothing behind on the host.

Tier 1: The Local User Willing to Run Code

The window belongs to a process, and processes on a user’s own machine are not a trust boundary against that user. IOActive consultant Taha Draidia recently published the concrete version of this in Signal Windows Desktop: contentProtection Bypass, which takes apart Signal Desktop’s screen-capture protection. Signal reaches this same Win32 call through Electron’s setContentProtection() wrapper, so the write-up doubles as a case study in what the flag is worth.

Flip the flag back from inside the process. Draidia tested the obvious approach first: call SetWindowDisplayAffinity(hwnd, WDA_NONE) on Signal’s window from another process. That fails with ERROR_ACCESS_DENIED, and running elevated fails the same way, because the kernel check compares the caller’s process identity against the window’s owner rather than its privilege level. Administrator rights do nothing here. CreateRemoteThread into Signal’s own process satisfies the check, and the protection turns off with no error, no prompt, and nothing on screen to mark the change.

Capture below the compositor. DWM removes the window while assembling the desktop image, so the removal exists only in the copy DWM hands out. Capture that reads frames lower in the stack and closer to the hardware never receives that copy, and may see the window intact. The flag protects one rendering path rather than the content.

This explains where the protection breaks down, not how to build something that breaks it. Anyone who can run code in the user’s session can neutralize the flag, and the barrier is measured in API calls rather than in exploit development. The control is therefore exactly as strong as whatever stops code execution in that session.

Tier 2: Kernel, Driver, or Physical Access

The flag does not apply here at all. DWM checks the exclusion while it builds the desktop image, so code running at or below the display driver gets the pixels without that check ever happening. Independent kernel-mode research makes the point from the other direction: the proof-of-concept driver DWMShield skips the public API entirely and calls the undocumented internal routine GreProtectSpriteContent directly, passing a target window handle over an IOCTL from a non-elevated client. It reaches the same DWM enforcement point Draidia’s work identified, but from underneath the ownership check rather than by satisfying it — the mirror image of the CreateRemoteThread approach in Tier 1, and a separate piece of research rather than an extension of it.

The Actual DRM, for Comparison

The irony in the title is that real DRM exists on the same platform and works on a different principle.

Hardware-backed protected media paths (Widevine L1, PlayReady SL3000, FairPlay) decrypt and composite content inside a Trusted Execution Environment, a secure media path that user-mode and often kernel-mode capture cannot reach. That’s why screen-recording a premium streaming-video service yields a black frame even with admin rights: the pixels never exist in a framebuffer the OS will hand out.

The flag that isn’t DRM, side by side with the DRM that is:

 SetWindowDisplayAffinityHardware DRM (protected media path)
Enforced byDWM composition, kernel-side owner check on the flagSecure hardware / TEE
Where the viewable image livesNormal framebuffer; omitted only from the copy handed to captureInside the TEE; never in a framebuffer the OS can hand out
What it coversOne top-level window at a time, per HWND, re-applied for every new windowThe content stream itself, wherever it plays
Stops normal screenshotsYesYes
Kept out of Recall snapshotsYesYes (Microsoft: Recall won’t store DRM content)
Stops a local user with adminNo (admin enables injection)Yes
Survives process injectionNoYes
Survives RDP / DWM-off contextsNo (fails open)Yes
Stops a phone cameraNoNo
Who can disable itAny code running inside the owning processNo software path; requires defeating the hardware
How it failsOpen and silent: no error, no log, no visual changeClosed: the license refuses to bind, playback stops or drops quality
Cost to adoptOne API call per window, no licensingDevice certification, license server, key management; SL3000 is device-only
Microsoft’s own classification“Not a security feature or DRM”Actual content protection

SetWindowDisplayAffinity is a hardening measure against opportunistic capture. Hardware DRM is a confidentiality control. Treating the flag as a confidentiality control is where the false sense of security begins.

What Developers Should Do

Using SetWindowDisplayAffinity is reasonable. Products go wrong when they treat that one API call as the finished control.

Set it on every top-level window, not just the main one. Affinity is a per-HWND property and every new window starts at WDA_NONE. Dialogs, tooltips, context menus, toasts, and the separate windows that WPF popups and Electron render into each get their own HWND. Flag the main window but not the dialog, and the screenshot catches the secret in full while the ordinary window behind it is the part that gets hidden.

Check the return value. The call returns FALSE on a window that isn’t top level or doesn’t belong to the calling process, and a silent failure still looks protected in code review. Treat it as a security event. On builds older than 19041, WDA_EXCLUDEFROMCAPTURE succeeds and behaves as WDA_MONITOR, so the window turns black instead of vanishing and the API never mentions the difference.

Re-read the flag. GetWindowDisplayAffinity reads the current value from any process, so the app or a monitoring agent can poll it. A change to WDA_NONE the app didn’t make means something else is writing to its process: log it, alert on it, and consider blanking the view until the app can verify its own state.

Use the supported control when one exists. Recall now has real policy: Allow Recall to be enabled (AllowRecallEnablement) and Turn off saving snapshots for Recall (DisableAIDataAnalysis), and managed devices have it removed by default. The flag was a workaround for consumer machines with no opt-out, which is still where it earns its keep.

Document the threat model. Name what the feature stops: screenshot tools, screen sharing, OS-level snapshotting. Name what it doesn’t: cameras, remote sessions, code running in the user’s session, anything at kernel level. Microsoft’s Azure Virtual Desktop documentation is the model to copy: it states plainly that the feature isn’t DRM-level protection and isn’t a substitute for one, and recommends pairing it with other controls.

Pair it with content-level controls. Reveal-on-tap for secrets, short display timeouts, redaction by default, per-session watermarking.

What Defenders Should Monitor

You cannot stop capture on a machine the user controls. You can often catch the attempt.

Injection into the protected app: the Tier 1 bypass is a common and ordinary injection, and the Signal bypass used CreateRemoteThread, the loudest option available. Watch Sysmon Event ID 10 (ProcessAccess) against that target with PROCESS_VM_WRITE, PROCESS_VM_OPERATION, or PROCESS_CREATE_THREAD; Event ID 8 (CreateRemoteThread); Event ID 25 (ProcessTampering); and Event ID 7 (ImageLoad) for unsigned modules or anything from a user-writable path.

Tamper events the app reports about itself: this depends on developers implementing the affinity re-read above, so ask whether they did. An app reporting “my window affinity changed and I didn’t change it” is a detection with almost no false-positive surface.

Capture and remote-control tooling on regulated hosts: OBS, ShareX, Snagit, ffmpeg with a screen-grab input, and support stacks such as AnyDesk, TeamViewer, and ScreenConnect. Inventory and policy rather than alerting, since none are malicious by default. The question is why a capture stack is installed on a host whose security depends on capture being hard.

Policy drift: if Recall is disabled by policy, verify it stayed disabled on the endpoint rather than trusting that the GPO exists. BYOD is the harder case, because Recall is available by default there and the user decides.

Everything a camera sees: out of reach of host telemetry. That leaves physical controls and per-session watermarking that survives a photograph. “We can’t stop the screenshot, but we can tell whose session it came from” is a more defensible promise than “the screenshot came out black.”

Conclusion

Read the flag as what it is and Microsoft’s two pages stop contradicting each other: it keeps sensitive windows out of casual captures and out of Recall on machines where the user is not the adversary, and it does nothing about the three tiers above. When a datasheet or a control matrix claims more than that, the difference is data with nothing protecting it, and another control has to cover the gap. A design that depends on a screenshot-proof window for confidentiality is a finding rather than a control.

References

INSIGHTS | August 26, 2026

Signal Windows Desktop: contentProtection Bypass

Signal Desktop on Windows ships a screen-capture protection feature that prevents the application window from appearing in screenshots or screen recordings. In this post, we walk through how we identified the underlying Windows API powering that feature, why naïve attempts to disable it fail even from a privileged process, and how we ultimately bypassed the protection by executing code within Signal’s own process context using CreateRemoteThread.

In this post we cover two distinct phases of the research:

  • Static analysis — locating the contentProtection API chain through Signal’s open source code and Electron documentation.
  • Kernel internals — reverse engineering win32kfull!NtUserSetWindowDisplayAffinity to confirm the ownership check that enforces the protection and understand exactly why cross-process calls are rejected.

Background

During an internal discussion, a colleague mentioned noticing that Signal’s window did not appear during a screen-share session. This prompted us to investigate the mechanism behind it and, naturally, to ask whether that mechanism could be bypassed.

Signal Windows Desktop contentProtection Bypass Signal Windows Desktop contentProtection Bypass

Finding the API Behind contentProtection

Signal Desktop is an Electron application and its source code is publicly available on GitHub. A ripgrep search for contentProtection across the codebase quickly identified the relevant call site:

SHELL · RIPGREP · SIGNAL-DESKTOP SOURCE
C:\Users\tahai\code\Signal-Desktop>rg contentProtection
app\main.main.ts
566:  const contentProtection = ephemeralConfig.get('contentProtection');
571:    (contentProtection ?? isContentProtectionEnabledByDefault(OS, os.release()))
3022:  if (name !== 'contentProtection') {
3026:  const contentProtection = ephemeralConfig.get('contentProtection');
3029:    if (typeof contentProtection === 'boolean') {
3030:      window.setContentProtection(contentProtection);

ts\windows\preload.preload.ts
6:installEphemeralSetting('contentProtection');

ts\util\createIPCEvents.preload.ts
208:        ((await getEphemeralSetting('contentProtection')) ??
216:      await setEphemeralSetting('contentProtection', value);

The call at line 3030, window.setContentProtection(contentProtection), is the Electron API responsible for the behaviour. Checking the Electron documentation reveals how this maps to platform-specific system calls:

On Windows, setContentProtection(true) calls SetWindowDisplayAffinity with the flag WDA_EXCLUDEFROMCAPTURE. On Windows 10 version 2004 and later the window is excluded from capture entirely. On older versions the flag falls back to WDA_MONITOR behaviour, which renders the window as a black rectangle in any capture.

This setContentProtection path is a well-trodden one outside Signal, and community write-ups describing it match what we observed. On Windows the call resolves to SetWindowDisplayAffinity(WDA_EXCLUDEFROMCAPTURE) (and on macOS to CGWindowSetSharingType(kCGWindowSharingNone)), it requires Windows 10 build 19041 — the May 2020 Update — or newer for true exclusion rather than the black-rectangle WDA_MONITOR fallback, and the exclusion happens at the Desktop Window Manager (DWM) / kernel display layer rather than in the application. As a result the window is omitted from every user-mode capture pipeline that goes through Windows Graphics Capture (WGC) — Zoom, Teams, Meet, OBS, Game Bar, and ordinary PrintScreen and BitBlt captures alike. One documented caveat worth noting for defenders is that certain DXGI / direct-GPU capture paths can, on some GPU and driver combinations, still capture a window flagged this way — the exclusion is strong but not literally universal.

Windows SetWindowDisplayAffinity()

The API signature is straightforward — a window handle followed by a DWORD affinity value:

  • WDA_NONE (0x00000000) — no restrictions
  • WDA_MONITOR (0x00000001) — content displayed only on a monitor
  • WDA_EXCLUDEFROMCAPTURE (0x00000011) — content excluded from all capture

To disable the protection, we need to call this API with a valid top-level window handle for Signal and pass WDA_NONE. Obtaining the handle is straightforward: EnumWindows() paired with GetWindowTextW() and GetWindowThreadProcessId() lets us identify Signal’s window by cross-matching title text and process name.

Disabling the Protection — Three Approaches

Approach 1 — Cross-Process API Call

With a valid handle in hand, the first attempt was direct: call SetWindowDisplayAffinity(hwnd, WDA_NONE) from a separate process. This returns immediately with ERROR_ACCESS_DENIED (5). Windows is enforcing an ownership check — a process cannot modify the display affinity of a window it does not own.

Approach 2 — Elevated Privileges

The same call was retried from a process running as Administrator. The result is identical: ERROR_ACCESS_DENIED. The check is not privilege-gated. Even a fully elevated process is rejected when calling SetWindowDisplayAffinity against a window it does not own.

Approach 3 — Remote Thread Injection (Successful)

The key constraint the previous two attempts revealed is that the call must originate from within Signal’s own process. We satisfied this using CreateRemoteThread to execute SetWindowDisplayAffinity(hwnd, WDA_NONE) inside Signal’s process context. Because the call is issued from Signal’s process, it passes the ownership check and the protection is silently removed. The proof of concept is available on GitHub.

SetWindowDisplayAffinity() — Kernel Internals

Having confirmed the ownership constraint empirically, we verified it through static analysis of the kernel implementation. The userland call chain is:

user32!SetWindowDisplayAffinity
  └─ win32u!NtUserSetWindowDisplayAffinity   [syscall boundary]

SetWindowDisplayAffinity in user32.dll is a thin wrapper around the NtUserSetWindowDisplayAffinity syscall exported by win32u.dll:

Locating the Implementation in the Kernel

In the kernel the syscall is handled across two modules. We confirmed this with the WinDbg x command:

WINDBG KD · MODULE SEARCH
1: kd> x win32*!*SetWindowDisplayAffinity*
fffff805`5d55ad40 win32k!stub_UserSetWindowDisplayAffinity
fffff805`5d51d320 win32k!_win32kstub_NtUserSetWindowDisplayAffinity
fffff805`5d4fe5ac win32k!NtUserSetWindowDisplayAffinity
fffff805`618bb180 win32kfull!NtUserSetWindowDisplayAffinity

Disassembling win32k!NtUserSetWindowDisplayAffinity shows it calls win32k!W32GetSessionState for a desktop-session sanity check, then dispatches through nt!KscpCfgDispatchUserCallTargetEsSmep — a first-layer check with no ownership logic. The ownership enforcement lives in win32kfull!NtUserSetWindowDisplayAffinity.

The Ownership Check

Working through the disassembly, the sequence is:

WINDBG KD · WIN32KFULL!NTUSERSETWINDOWDISPLAYAFFINITY — ANNOTATED
; Resolve the target window to its internal struct (via ValidateReceivingHwnd)
fffff805`618bb1ac  call  win32kfull!ValidateReceivingHwnd
fffff805`618bb1b3  mov   rdi, rax          ; rdi = window object

; Get the Win32 process object of the *current* (calling) process
fffff805`618bb1c2  call  nt!PsGetCurrentProcessWin32Process
fffff805`618bb1c7  mov   r8, rax            ; r8 = current process

; Compare: does the window's owning process match the calling process?
fffff805`618bb1db  mov   rax, [rdi+10h]     ; rax = window's thread info
fffff805`618bb1df  cmp   [rax+1D0h], r8    ; owning process == calling process?
fffff805`618bb1e6  jne   +0xe2              ; NO -> ACCESS_DENIED

; ACCESS_DENIED path
fffff805`618bb262  mov   ecx, 5             ; ERROR_ACCESS_DENIED
fffff805`618bb267  jmp   win32kfull!UserSetLastError

The check is explicit: PsGetCurrentProcessWin32Process returns the Win32 process object for the calling thread, and that value is compared against the process stored at offset 0x1D0 of the window’s owning thread structure. If they differ, the call is rejected. Administrator privilege does not factor into this path — the check is purely about process identity, which is why elevated callers receive the same ERROR_ACCESS_DENIED as unprivileged ones.

CreateRemoteThread satisfies this check because it causes the API call to execute on a thread within Signal’s own process, making PsGetCurrentProcessWin32Process return Signal’s process object — an exact match.

Going Below the API — Kernel-Level Enforcement

The ownership check above lives in the syscall handler for SetWindowDisplayAffinity, but that syscall is only the documented front door. The exclusion state it sets is ultimately applied deeper in the graphics stack, inside DWM. Independent kernel-mode research reinforces this: a proof-of-concept driver (DWMShield) skips the public API entirely and calls the undocumented internal routine win32kfull!GreProtectSpriteContent directly, passing a target HWND and the same 0x11 (WDA_EXCLUDEFROMCAPTURE) flag. It works from kernel mode by exposing a device and symbolic link, taking the target window handle over an IOCTL from a non-elevated client, and invoking GreProtectSpriteContent on its behalf — after which DWM applies the same capture-exclusion state that the official path would have produced.

That work is the mirror image of ours. Where CreateRemoteThread bypasses the kernel ownership check by making the call originate from inside the target process, the driver bypasses it from the other side — by dropping below the user-mode API to the routine that actually enforces the flag, where the per-process identity comparison never runs. It carries the usual kernel-research friction: because GreProtectSpriteContent is not exported, its address must be resolved manually and shifts on every reboot under KASLR, and the driver depends on an internal signature that Windows updates can change. But the takeaway is the same one the ownership check hints at: the capture-exclusion decision is made by DWM in kernel space, and it can be reached — by moving code into the owning process, as we did, or by reaching the enforcing routine directly, as the driver does.

Conclusion

EnumWindows is a powerful Win32 API: it allows any process, regardless of privilege, to enumerate top-level windows within the current desktop session and receive a handle to each. Those handles do not, by themselves, grant meaningful access — what can be done with a handle is gated separately by each target API’s own access controls. In the case of SetWindowDisplayAffinity, the gate is a kernel-level ownership check that correctly rejects cross-process calls from any caller, including administrators.

However, the check is bounded by process identity rather than a broader integrity or trust model. CreateRemoteThread — a documented, widely-available Windows API — provides a straightforward way to move code execution into the target process and thereby satisfy that identity check. The result is a silent, runtime removal of screen-capture protection with no indication to the user.

This finding illustrates a recurring theme in Windows security: individual API-level checks are often well-implemented, but the combination of legitimate APIs can produce outcomes the checks were not designed to prevent. Defence-in-depth controls like screen-capture protection are most effective when the device is uncompromised. Once an attacker has local code execution they are in a position to erode multiple such controls through in-process execution. Signal’s protection is a solid user-mode control. What these two paths show is only that, like any capture-exclusion built on the same DWM mechanism, it rests on the integrity of the endpoint rather than on a boundary the local attacker cannot cross.

References

INSIGHTS | October 3, 2011

Windows Vulnerability Paradox

For those who read just the first few lines, this is not a critical vulnerability. It is low impact but interesting, so keep reading.

 

This post describes the Windows vulnerability I showed during my Black Hat USA 2011 workshop “Easy and Quick Vulnerability Hunting in Windows”.

 

The Windows security update for Visual C++ 2005 SP1 Redistributable Package (MS11-025) is a security patch for a binary planting vulnerability. This kind of vulnerability occurs when someone opens or executes a file and this file (or the application used to open the file) has dependencies (like DLL files) that will be loaded and executed from the current folder or other folders than can be attacker controlled. This particular vulnerability allows an attacker to execute arbitrary code by tricking a victim user into opening a file from a network share. When the victim user opens the file, the application associated with the file is executed, and an attacker-crafted DLL file is loaded and executed by the application.

 

It’s either funny or scary (you choose) that the Windows security update meant to fix the above-described vulnerability is also vulnerable to the same kind of vulnerability it fixes, and it can be exploited to elevate privileges.

 

When installing the security update on 64-bit Windows 7, the file vcredist_x64.exe is downloaded and then executed under the System account (the most powerful Windows account, it has full privileges) with some command line options:

 

C:WindowsSoftwareDistributionDownloadInstallvcredist_x64.exe” /q:a /c:”msiexec /i vcredist.msi /qn
After being run, vcredist_x64.exe tries to launch the msiexec.exe process from theC:WindowsTempIXP000.TMPtemporary folder, which is where the vcredist.msi used in the command line option is located, but because msiexec.exe doesn’t exist there, vcredist_x64.exe will fail to run it. Then vcredist_x64.exelaunches msiexec.exefrom C:WindowsSysWOW64, where msiexec.exe is located by default on 64-bit Windows 7.

 

There is an obvious vulnerability and it can be exploited by low-privilege Windows users since theC:WindowsTempIXP000.TMP temporary folder DACL has write permissions to the Users group, so any Windows user can place in that temporary folder a file named msiexec.exe and execute arbitrary code under the System account when they attempt to install the vulnerable security update.

 

While this is an interesting vulnerability, it’s not critical at all. First, to be vulnerable you have to have the vulnerable package installed and without the security update applied. Second, for an attacker to exploit this vulnerability and elevate privileges, the option “Allow all users to install updates on this computer” must be enabled. This option is enabled on some systems, depending on configuration settings about how Windows updates are installed.

 

This presents an interesting paradox in that you’re vulnerable if you haven’t applied the vulnerable patch and you’re not vulnerable if you have applied the vulnerable patch. This means that the patch for the vulnerable patch is the vulnerable patch itself.

 

The following links provide some more technical details and video demonstrations about this vulnerability and how it can be exploited:
References