Overview
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.
Summary
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
Enumeration
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 10.10.10.178
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 //10.10.10.178:Sharename
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.
Data
IPC$
Secure$
Users
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.
Decryption
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
Else
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, _
passwordIterations)
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, _
CryptoStreamMode.Read)
Dim plainTextBytes As Byte()
ReDim plainTextBytes(cipherTextBytes.Length)
Dim decryptedByteCount As Integer
decryptedByteCount = cryptoStream.Read(plainTextBytes, _
0, _
plainTextBytes.Length)
memoryStream.Close()
cryptoStream.Close()
Dim plainText As String
plainText = Encoding.ASCII.GetString(plainTextBytes, _
0, _
decryptedByteCount)
Return plainText
End Function
Public Sub Main()
Dim Phone = DecryptString("fTEzAfYDoz1YzkqhQkH6GQFYKp1XY5hm7bjOP86yYxE=")
Console.WriteLine(Phone)
Console.WriteLine(IsValidPhoneNumber(Phone))
'Console.WriteLine(IsValidPhoneNumber("299-999-9999"))
End Sub
Private r As New Random
Private Function GeneratePhoneNumber() As String
Dim npa, nxx, xxxx As String
Do
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]))")
Do
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 :)
Root
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.
Comments