Participatory Extensible Security

In the past, I’ve explained how security products combine sensors and throttles with threat intelligence to protect users and devices from attack. I’ve also outlined how the evolution of software, including increased complexity and a focus on privacy, have made it harder than ever for sensors and throttles to function effectively, leading to security and reliability risk.

The Current Landscape

Today in the Windows ecosystem, we have a few cases of “participatory extensible security” (PES). PES is extensible on both sides:

  • An “enlightened” client can participate by asking for security help
  • Any security product can extend protection to any client

One PES example is the IOfficeAntivirus interface, which gets called on file downloads and document opens to tell installed antivirus software “I got a new file. Scan it for viruses?” (This direct call isn’t entirely redundant behavior in a world with Real-time Protection, but it’s close).

The more prominent example of PES is an API called AMSI — the Antimalware Scan Interface. I’ve blogged about AMSI before but the tl;dr is that it is an API contract where an (arbitrary) AMSI client can ask an (arbitrary) AMSI security provider “Hey, what do you think of this. Does it look malicious?

This allows the client application (a script engine, a document editor, etc) the ability to choose the best place to put a sensor/throttle pair– for instance, Word can call AMSI right after a document is decrypted and immediately before its powerful script content is about to be executed. This is great for several reasons:

  1. The client doesn’t need to know anything about the security provider.
  2. The security provider doesn’t need to try to hook the (potentially new or unknown) client.
  3. The security provider gets the content to be scanned in whatever form the client believes will best reveal signs of malice.
  4. If the content is determined to be malicious, the client can show a meaningful error message and/or offer advice or remediations.

That’s great stuff!

Unfortunately, the flexibility and simplicity of this API contract has its downsides. In particular, the API was designed in the style of most Microsoft extensibility APIs of the late 1990s: a series of registry keys point to a set of DLLs that are loaded and then executed in process of the calling app. This is theoretically good for performance because it means that an AMSI scan does not require spawning new processes or marshalling data cross-process. Unfortunately, it’s very bad for reliability. If an AMSI provider crashes or otherwise corrupts the memory of the process into which it was loaded, the AMSI client crashes. Because it’s a native code crash, there’s usually no meaningful error message, so a buggy AMSI provider can cause crashes across multiple clients without the user realizing what’s happening or that there’s a common culprit. Even if AMSI providers are rock solid in terms of reliability, implementations can silently degrade performance — most AMSI clients and providers do not show UI or any other indication that a scan is in progress or what provider is conducting it. A user could install a new product that dramatically hinders the performance of every AMSI client and suffer poor experiences for years without understanding why: “This PC is sometimes just slow, I guess.” In addition to the possibility of a single slow implementation, AMSI permits multiple providers on a single device. The performance impact of a single provider might be acceptable, but three or more? A final issue is that Windows now supports certain types of processes called Protected Processes (or Protected Process Lite) that rely on Windows Code Integrity enforcement to allow only DLLs bearing certain digital signatures to load. If an AMSI provider isn’t signed with the required signature, the LoadLibrary call will fail, that AMSI provider will be skipped, and the user’s Event Log will record a code integrity violation.

Beyond the mechanics of how AMSI providers load and run, another issue is that the API contract for AMSI is probably a bit too generic:

HRESULT AmsiScanBuffer(
[in] HAMSICONTEXT amsiContext,
[in] PVOID buffer,
[in] ULONG length,
[in] LPCWSTR contentName,
[in, optional] HAMSISESSION amsiSession,
[out] AMSI_RESULT *result );

AMSI callers calling AmsiScanBuffer in new scenarios means that AMSI providers can abruptly start getting data of sorts they’ve never seen before. For example, a few years back SharePoint started calling AMSI on inbound HTTPS request headers and bodies. In the latest Windows Insider builds, the Run dialog will call AMSI on content pasted in from the Internet to combat ClickFix attacks. AMSI’s flexibility meant that existing security products didn’t need to be redeveloped with awareness of the new call sources and data, but it also introduces the risk that one of those products might misunderstand what it’s scanning and cause a false positive, performance issue, or even a crash. Even if the scan call succeeds, the value of the call depends upon the security product having meaningful threat intelligence against whatever sorts of threats might be found in the caller’s buffer. Scanning for malicious Win32 native code in a buffer containing a command line string isn’t going to be very useful, for example.

The Fix?

None of the problems here are insurmountable, we just need to invest and adjust the engineering tradeoffs to reflect more modern needs. Off the top of my head, I’m hoping we’ll see:

  1. Telemetry for the AMSI providers to understand their real-world performance impact
  2. UX for the user to understand how their security software impacts performance and reliability
  3. An API contract that does not result in loading foreign code into every AMSI caller
  4. A richer API contract that allows for more context on what’s being scanned
  5. A richer API contract that allows for more result codes

I’m hopeful that one day we’ll be able to fold the legacy AMSI features into the upcoming Windows Endpoint Security Platform that is being built as a part of the Windows Resiliency Initiative.

Spring 10Ks

After two solid half-marathons early this year, I was excited for the start of the 10K season to see whether I could keep improving my times. I had mixed results.

Cap10K

On Sunday, April 12th, I awoke at 5:20 before my alarm, had a cup of coffee and a banana. I left the house at 6:40, but the entrance ramp to MoPac was closed so I had to take a slower detour. I got to my usual parking lot at 7:10 and there were plenty of spaces. Considering the drizzle, I put on a poncho and headed to the PortaPotty for a (alarmingly productive) pre-race bathroom break. I managed to get into the back of Corral B before it closed. While waiting for the race to start, I had a pack of Jelly Belly Energy beans and an Apple Cinnamon Gu packet– the latter a mistake, as it felt like it was going to come up later in the race. This was my second bad experience with pre-race apple cinnamon snacks.

Every mediocre race can yield a list of excuses about why it didn’t go well, and this was no exception.

  • It was drizzling and somewhat muggy throughout. I’d failed to prepare all of my gear the day before, and couldn’t find either of my usual tank tops to run in.
  • The runners in Corral B were slow (with a non-trivial number of people already walking in the first half mile) and it was very crowded, so my start was slow. Still, I managed a respectable first 5K at 28:17, but would need a negative split if I wanted to achieve my goal of PR (<52:25). Alas, my second half fell apart.
  • My MP3 player was in a state where it wasn’t allowing me to choose one artist to play, so I switched over to play music from my COROS Pace 3 watch, but even at maximum volume, it was too quiet to hear. So most of my run was just the sound of runners’ feet and the occasional band. :'(

The “King of the Hill” hill wasn’t nearly as steep or long as I remembered, and I managed to run it and the following long slope without stopping. My favorite sign was one around mile 4 that had a drawing of Rocky from Project Hail Mary with the words “AMAZE AMAZE AMAZE” on it.

Alas, I ended up well behind my goal and even my backup goal (under an hour), but it wasn’t a bad time (1:01:36), just somewhat disappointing.

More photos / Timecard

Chart from my Coros Pace3 running watch:

Austin Sunshine Run 10K

I first started running the Sunshine Run after a disappointing showing in the 2024 Cap10K but it hadn’t proven to be a good consolation race, with slow times in both 2024 and 2025. Still, I had high hopes for this year, because I felt like most of the blame for my slow Cap10K belonged on the weather.

The morning of the race, I was well behind schedule because I needed to drop my son at a swim meet, so I didn’t get to the parking lot until 7:32, not long before the 8am start. I managed a worryingly-productive visit to a PortaPotty and got into the race corral a hundred feet behind the time-targeted groups. As a much smaller race (~3K participants), I successfully managed to weave through the slow starters and managed a 7:43 mile. I was feeling good. The weather was absolutely perfect, sunny, with temps in the high 50s and a light wind. My new MP3 player worked well enough with my JLab headphones.

The “big hill” I was dreading in this race was again not nearly as intimidating as expected (this is a recurring pattern), and I ran the whole thing. I didn’t take a break until mile 4, and even then it was a very brief break. Around mile 5, I dropped to a walk but after about 15 seconds a group of high-energy college kids (who’d paused for a dance break in front of the last band) started cheering me on as they came by and I got back into a run for the remainder of the race.

Frustratingly, I had no idea how close I was to getting my 10K PR or I probably could’ve snagged it without too much effort. Still, at 53:12, I crushed my goal (sub-1:00) and beat last year’s time by 10:21.

https://results.laurelt.com/asr/results?pk=8807833

Last year, I’d won a prize in the raffle and spent a ton buying a signed football for the fundraiser; this year, I again won a prize from St. Elmo Brewing in the raffle.

I really enjoyed this race and was smiling for the next few days.

-Eric

Cybersecurity Metaphors

Uneven Protection

Attacks flow like water: if you have a hole in your defenses, attacks will flow through that hole. Unless they’re trying to win a prize or show off, attackers do not bother attacking where your security posture is strongest.

Making your tallest wall taller usually isn’t useful.

Encryption

Security folks love encryption, for good reason. Proper encryption provides confidentiality (your secrets are secret) and integrity (no one can modify your encrypted data). The problem is that encryption is based on a secret key, and if you don’t protect that key, you likely haven’t done much of consequence. Effectively protecting the key is very difficult.

Enclaves

Enclaves provide a secure location to operate on secrets. Unfortunately, many implementations of secure enclaves are naive and provide no meaningful protection. One common problem is that the enclave acts as a confused deputy, fully willing to satisfy the requests of any attacker.

Spontaneously-Combusting Fire Extinguishers

The whole point of security software is to try to achieve the impossible: “prevent bad things from happening.” Unfortunately, the means of providing this protection often involves poking into the most sensitive areas of a system to attempt to detect malicious activity. This is a high-risk endeavor, and any error can end up causing the exact sort of IT disaster you were hoping to prevent.

It is crucial that security software not be a “cure that’s worse than the disease” or, as I prefer to describe it, “a fire extinguisher that intermittently spontaneously combusts and burns down the building.”

Exploiting Vulnerable Drivers

Often, attackers will attempt to prevent security software from interfering with their attack chains by abusing a vulnerable driver to kill or otherwise disable the system’s security software (antivirus/edr/etc). Because drivers run in highly-privileged OS Kernel mode, it is difficult to prevent attackers from achieving their goals if they manage to achieve code execution in the kernel.

To ensure that only legitimate code gets to run in the kernel, Windows requires that the driver code bear an Authenticode signature from a particular certificate authority. Microsoft signs these drivers only after verifying their provenance and running through various driver-verification suites to help ensure their robustness.

However, even if all of the drivers on a system are legitimate, attackers have had success in finding vulnerabilities in legitimate drivers that allow them to abuse the driver to achieve their goals. Like any code, some drivers have bugs that allow them to corrupt memory, leak data that needs to be secret, or otherwise perform functions unintended by the original author. These vulnerable drivers represent a critical attack surface that attackers abuse to achieve their own ends.

Beyond abusing drivers already present on a victim device, in a BYOVD attack (Bring your own vulnerable driver) an attacker drops a vulnerable driver onto the device, then abuses it with their malware.

To address this threat vector, Microsoft has three main mechanisms:

  1. Exploitable driver blocklist – Enforced by the Windows kernel itself, allows blocking the load of drivers known to be vulnerable.
  2. Microsoft Defender Attack Surface Reduction rule – Enforced by Microsoft Defender, prevents writing of known vulnerable drivers to the system. By preventing the write of the driver before it loads, the risk of compatibility problems is somewhat reduced (because in a legitimate scenario, the installer for the device will fail at install time rather than at runtime).
  3. Microsoft Defender Signatures – Enforced by Microsoft Defender Antivirus, blocks vulnerable drivers directly using the AV engine. This approach is appropriate only for drivers under active exploitation and with little legitimate use.

Smart App Control

Users of modern versions of Windows 11 have a powerful security feature for keeping their devices secure, known as Smart App Control.

I’ve talked about this feature a few times over the last year, but in April 2026, a powerful improvement landed. Previously, Smart App Control could not be turned back on if you ever turned it off. That limitation has been removed in Windows 11 version 25H2 (Windows Security App v1000.29554+), making the feature far more practical to use and try out.

What is Smart App Control?

While Windows’ SmartScreen AppRep feature only checks the reputation of the entry point program (typically a .exe file) from an untrusted origin (like the Internet), Windows 11’s Smart App Control goes further than SmartScreen and evaluates trust/signatures of all code (DLLs, scripts, etc) that is loaded by the Windows OS Loader and script engines. This provides a broader range of protection (somewhat akin to Gatekeeper on MacOS) and addresses AppRep bypasses like DLL hijacking. If a code file is unsigned, Windows will consult the Microsoft Defender Intelligent Security Graph in the cloud to see whether the file is known to be trustworthy and permit it to load only if so.

Beyond trust evaluation, when Smart App Control is enabled, many dangerous file types are blocked from ShellExecute() entirely if a file is from an untrusted origin.

End-users can enable Smart App Control in the Windows Security App.

Automatic Enablement

By default, Smart App Control starts in Evaluation mode, meaning that it watches as you use your device to determine whether SAC’s protections are a good match for your use cases. While SAC works great for the majority of consumers, it tends to cause too much friction on devices used by Developers and within Enterprises, because these devices commonly interact with unsigned code or code that is not broadly used by the public.

Other file types

One of the most exciting features of Smart App Control is that it blocks the Windows Shell from opening files of certain types if they originate from untrusted locations.

As of April 2026, the list of SAC-blocked-if-MotW extensions is .appref-ms, .appx, .appxbundle, .bat, .chm, .cmd, .com, .cpl, .dll, .drv, .gadget, .hta, .iso, .js, .jse, .lnk, .msc, .msp, .ocx, .pif, .ppkg, .printerexport, .ps1, .rdp, .reg, .scf, .scr, .settingcontent-ms, .sys, .url, .vb, .vbe, .vbs, .vhd, .vhdx, .vxd, .wcx, .website, .wsf, .wsh.

If you attempt to open one of these potentially dangerous files from an untrusted source, you’ll encounter the following block dialog:

Notably, this dialog box does not offer an override. If you’re confident that the file is from a trusted source, you could remove the MotW or temporarily disable SAC before opening it.

Impact on Other Features

  • When SAC is enabled, Microsoft Defender Antivirus enters a special “Hybrid” mode (similar to its passive mode). In Hybrid mode, Defender’s real-time protection feature is less-active, reducing the monitoring (BM and file open/close scans) for processes unless the system determines that the process is one that is particularly interesting (e.g. a script engine host).
  • Unfortunately, SAC’s dangerous file type list is baked into the feature and is not extensible. It does not respect the HighRiskFileTypes list from the registry or the EditFlags of the file type.

Developer Guidance

For software publishers, the best way to avoid problems with SAC blocking your app is to sign your code, already a longstanding best practice. Importantly, unlike SmartScreen AppRep (which only verifies the reputation files with an Internet origin), SAC verifies signatures on all code modules, including DLLs and packages like MSIs. That means that tricks like using a signed stub installer to drop unsigned code will not be good enough.

One early problem with Smart App Control is that the Code Integrity codepath didn’t support ECC signatures. That’s being addressed, but for broadest compatibility and least friction, you should still avoid ECC for code-signing.

Other Links

Nitty Gritty – Nearly four years ago, @n4r1B posted an amazingly low-level exploration of the underlying implementation of SAC and the Windows code integrity technology that implements it.

-Eric

Unsigned unknown: