• Donald Ashdown

Hack the Box Nest

Updated: Dec 5, 2020


This machine starts like many machines with open samba shares and a misconfigured anonymous bind. The tempuser has plaintext credentials that leads you to move horizontally and locate a hash which cannot be cracked. This leads to reverse enginner a custom tool on the share which holds the decryption function to decrypt the hash. From here we connect to the only other port 4386, and pull down a hash and executable that we decompile and debug only to find another hash decrypt function providing us with the root password. However the root flag could not be accessed over SMB so psexec had to be used.


  • Anonymous bind to the smb server

  • Extract TempUser credentials and move horizontally

  • Decrypt c.smith's hash with the recompiled RU_scanner.

  • Debug mode on high port lets us read files to extract administrator hash and a suspicious.exe

  • re-compiling the .exe with out hash gives us the password

Tools/Blogs used

  • dot peak

  • ghidra

  • visual studio

  • impacket suite

  • smbclient

Lessons learned

  • Do not be afraid or overwhelmed when decompiling and debugging .net apps

  • Make sure to start off with debugging to confirm application execution without errors


Initially we started with an nmap scan and received no results suggesting our scans had been blocked. In this situation we know our practice lab allows for a TCP connection or the lab simply would not be possible. With a standard nmap scan only checking for port 0-1000 the knee jerk reaction is to investigate those ports 1000-65535. This also yielded no results, leaving two common paths to explore. Between scanning for UDP ports or performing a no ping scan, TCP only we could use an automated tool to check it all. But the skill is in regular practice so we will check the UDP ports manually only to find nothing is open. With our last option of scanning over TCP only we successfully have a hit.

Not being satisfied with the fact that a practice lab has only one port open, we do our due diligence and scan for all ports over TCP only we get a get at port 4386. We know the firewall is configured to block ICMP requests so we are fortunate to get a successful port find.

SMB Enumeration

With only two ports available this is a two edge sword in that we do not have to do large amounts of enumeration but we are likely going to need to dig very deep in these two ports. 445 is a common port responsible for file sharing. The first thing to always check for on SMB shares is anonymous binding. Which we can test with the built in linux package

 smbclient -L

We have a successful connection as the SMB share is misconfigured to accept anonymous binds. From here we start enumerating each individual share with smbclient package, the same command line except we remove the -L flag and specify our destination with //.

smbclient //

From here we start going through the list and have our first successful hit on the Data folder but we also have successful reads into the following folders.


Starting from the top we work our way down checking each share individually.

Initially we start with the Data share have receive a successful bind. From here we can download any file we have access to with the get command, which will be necessary as the cat or type command are not working over RPC in this instance. A informative document in the Shared folder, "Maintenance Alerts.txt" was found suggesting that there was no scheduled maintenance.

Moving to the next folder within the Data > Shared hierarchy we found a HR and Marketing folder. But we have access to only HR where we find some juicy credentials. But remember that in order to download these files you will have to use get, and put the file name in quotes.

From here we checked all remaining folders and nothing was found.

RPC Enumeration

The rpcclient is a utility initially developed for Samba and troubleshooting over windows and linux. This is also a pot of gold during a penetration test in order to access file shares, the registry, services, domain authentication and much more. Linux has a built in tool known as rpcclient that we will use to connect with our new found credentials.

From here we use the command query user to dig up any user information and we find that user C.Smith has a description that suggests he is the flag holder in the screenshot below.

Back to drawing samba board

We go back to the drawing board and connect back to our open Samba share as user TempUser and we now have more but not full access to the Data folder were we access the \IT\Configs|RU Scanner\ folder and find a golden nugget. RU_config.xml.

We find a hashed password for user c.smith.

Crack the hash

Thinking this would be an easy and routine hash crack, I quickly found that Johnny and hash-identifier were not able to identify this hash type. Nor was it base 64 which I initially thought from the = on the end.

Back to the SAMBA board

Having no success in identifying the hash, we re-visit our samba shares. Having had gone through every folder marking those we have access to, my next target was NotepadPlusPlus which yields some juicy info.

We download both files and the config.xml at first appears to have nothing until the last line where we see referenced file paths.

We take this and are able to access a directory where we do not have read permissions and would not of known that this file/folder existed. So we browse around and eventually find a juicy payload.


We start downloading and reading all the files in the referenced and hidden location found in the config.xml "<File filename="\\HTB-NEST\Secure$\IT\Carl\Temp.txt" />

" We download the RUScanner.sln and accomponying folder for the Visual Basic and visual studio project. This finally provides us exactly what we need, to decrypt the hash we found by using the decrypt function provided to us in the code.

As we analyze the code modules individually, we notice the utils.vb contains the decryption function which is called from main. So we are able to add our encryption string into the decrypt string function and we can run the code in visual studio or .net fiddle for the password. The final code is presented below, with the encrypted password at the end.

Imports System

Imports System.Text.RegularExpressions

Imports System.Text

Imports System.Security.Cryptography

Public Module Module1

Private Function DecryptString(EncryptedString As String) As String

If String.IsNullOrEmpty(EncryptedString) Then

Return String.Empty


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

End If

End Function

Private Function Decrypt(ByVal cipherText As String, _

ByVal passPhrase As String, _

ByVal saltValue As String, _

ByVal passwordIterations As Integer, _

ByVal initVector As String, _

ByVal keySize As Integer) _

As String

Dim initVectorBytes As Byte()

initVectorBytes = Encoding.ASCII.GetBytes(initVector)

Dim saltValueBytes As Byte()

saltValueBytes = Encoding.ASCII.GetBytes(saltValue)

Dim cipherTextBytes As Byte()

cipherTextBytes = Convert.FromBase64String(cipherText)

Dim password As New Rfc2898DeriveBytes(passPhrase, _

saltValueBytes, _


Dim keyBytes As Byte()

keyBytes = password.GetBytes(CInt(keySize / 8))

Dim symmetricKey As New AesCryptoServiceProvider

symmetricKey.Mode = CipherMode.CBC

Dim decryptor As ICryptoTransform

decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes)

Dim memoryStream As IO.MemoryStream

memoryStream = New IO.MemoryStream(cipherTextBytes)

Dim cryptoStream As CryptoStream

cryptoStream = New CryptoStream(memoryStream, _

decryptor, _


Dim plainTextBytes As Byte()

ReDim plainTextBytes(cipherTextBytes.Length)

Dim decryptedByteCount As Integer

decryptedByteCount = cryptoStream.Read(plainTextBytes, _

0, _




Dim plainText As String

plainText = Encoding.ASCII.GetString(plainTextBytes, _

0, _


Return plainText

End Function

Public Sub Main()

Dim Phone = DecryptString("fTEzAfYDoz1YzkqhQkH6GQFYKp1XY5hm7bjOP86yYxE=")




End Sub

Private r As New Random

Private Function GeneratePhoneNumber() As String

Dim npa, nxx, xxxx As String


npa = r.Next(100, 999).ToString()

Loop Until New Regex("^([2-9][0-8]\d)$").IsMatch(npa)

'reg = New Regex("[2-9]((0|[2-9])\d|\d(0|[2-9]))")


nxx = r.Next(100, 999).ToString()

Loop Until New Regex("[2-9]((0|[2-9])\d|\d(0|[2-9]))").IsMatch(nxx)

xxxx = r.Next(1000, 9999).ToString()

return String.Join("-", {npa, nxx, xxxx})

End Function

Public Function IsValidPhoneNumber(Value As String) As Boolean

'Allows phone number of the format: NPA = [2-9][0-8][0-9] Nxx = [2-9][0-9][0-9] Station = [0-9][0-9][0-9][0-9]

Return Regex.Match(Value, "^[01]?[- .]?(\([2-9]\d{2}\)|[2-9]\d{2})[- .]?\d{3}[- .]?\d{4}$").Success

End Function

End Module

Password = xRxRxPANCAK3SxRxRx

User Flag

We can now connect as user Carl smith as per the config.txt and we find the flag :)


c.smiths folder contained a debug password.txt file but it is totally empty. After calling allinfo we can see that the file content is hidden in the ADS and can be downloaded.

Using the all info or more command gives us the results of the file structure.

Boom there is our password

We successfully connected in and received a basic screen. Calling the argument LIST provides us with commands available to us. So we enable debugging with the password found in the ADS file.

From here we find a password hash as we look around and we simply pop it in our decrypt function from user and get the password and have root.txt :)

Congratulations and happy pwning.

15 views0 comments