> For the complete documentation index, see [llms.txt](https://cl4nd3st1ne.gitbook.io/write-ups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cl4nd3st1ne.gitbook.io/write-ups/hack-the-box/machines/htb-season-8-rustykey-walk-through.md).

# HTB Season 8: RustyKey Walk-through

It has a very unexpected foothold method after which the approach is based on typical AD enumeration. This machine will take us through kerberos authentication, timeroasting, DACL abuse, protected users, COM Hijacking, and resource-based constrained delegation.

***

We’ve been given the following credentials to get started with — `rr.parker / 8#t5HE8L!W3A`

I did start with an NMap scan but it never seemed to complete properly, especially if it was a full-port scan. After a few tries I did get a passable result although several ports are still missing:

<figure><img src="/files/tHLVyVAEoehAUnSkmy9p" alt=""><figcaption></figcaption></figure>

Using the credentials we are given, I tried to access LDAP and SMB but kept hitting errors. Finally while trying Impacket’s GetNPUsers tool I got a more descriptive error:

<figure><img src="/files/tngA5NcaFhKXEseraFFY" alt=""><figcaption></figcaption></figure>

NTLM Authentication might be disabled and we need to use Kerberos Authentication instead.

Running nxc to enumerate LDAP with kerberos authentication enforced finally gives results:

<figure><img src="/files/GhhaU5HiLDjz2yGNPqXU" alt=""><figcaption></figcaption></figure>

However, SMB was still not working for me. I was using the same command structure that worked for LDAP but SMB kept throwing errors:

<figure><img src="/files/ReElXeVP8eTf49NYyzfl" alt=""><figcaption></figcaption></figure>

I was able to ultimately authenticate to SMB by providing the target as `dc.rustykey.htb` instead of just `rustykey.htb`. This is because SMB does name resolution using a different mechanism than LDAP. And since we’re using kerberos, wherever possible we must use the DC’s FQDN. Ensure that your `/etc/hosts` file is configured to resolve `dc.rustykey.htb` to the machine IP.

Next, I ran bloodhound-ce-python to collect LDAP information about the environment and then ingested that into bloodhound-ce. Unfortunately, our current user had no outbound controls. But, there were some interesting observations.

There were a bunch of computers present (16 including the DC):

<figure><img src="/files/77UOHAUeXwndixHdkuZV" alt=""><figcaption></figcaption></figure>

This was a new scenario for me. Most of these computers didn’t have any privileges. At this point I was stuck trying to find a way forward.

I was glad to be directed by a member of the HTB Community towards **timeroasting**.

> The mechanism of NTP allows anyone in the network to request **unauthenticated** time synchronisation with the DC. This request includes the RID of the entity for which synchronisation is requested. The DC’s response to such a request is signed with the NTLM hash of the password of the entity (signed NTP response). If the password of that computer account is weak, then the SNTP hash can be cracked. This process is called timeroasting.

Read more about it [here](https://cybersecurity.bureauveritas.com/uploads/whitepapers/Secura-WP-Timeroasting-v3.pdf).

This attack is effective only if computer accounts are manually configured because by default, modern AD environments’ computers have long, unpredictable passwords that are automatically rotated.

This attack can be performed using various tools, but I used nxc since it has a module for it:

<figure><img src="/files/ZUXrmYbHIm5fBsUA5hDK" alt=""><figcaption><p>Listing SMB modules in nxc</p></figcaption></figure>

<figure><img src="/files/zpP98LEtwSbmUMWC3ftV" alt=""><figcaption><p>Performing unauthenticated timeroasting</p></figcaption></figure>

This output makes it clear how we’re supposed to use the account we’ve been given. We can use it to map the RIDs to devices in the network.

Storing these hashes in a file, the next thing to attempt is cracking. From [Secura’s Github](https://github.com/SecuraBV/Timeroast?tab=readme-ov-file) for their timeroast scripts, I came to know that the beta version of hashcat supports SNTP hashes. After downloading it and running it with rockyou.txt, one of the hashes cracked successfully:

<figure><img src="/files/aEc1CU2HQMVzk4DnO0HL" alt=""><figcaption></figcaption></figure>

The RID for this hash was `1125`, which belongs to `IT-Computer3`.

So, now we have a new set of credentials —

`IT-Computer3$ / Rusty88!`

The Bloodhound data for this computer account shows:

<figure><img src="/files/siQ8sq6PPSRxLRQEbixL" alt=""><figcaption></figcaption></figure>

Which means we inherit the controls the HelpDesk group has:

<figure><img src="/files/zE4r4MZhp8YSOhMDJMZO" alt=""><figcaption><p>Outbound Controls of the HelpDesk group</p></figcaption></figure>

When I saw this initially, I got really happy seeing the numerous privileges. It was when I started trying all the possibilities that I realised what a pain it is to have multiple options!

The first thing I looked for was which of these users have Remote Management rights.

<figure><img src="/files/erxTwWmStT4Vol4llbTz" alt=""><figcaption></figcaption></figure>

Great, so we can change passwords for all of them.

Since we’ll be using kerberos auth, a krb5.conf file is needed to define some configurations that are referred while generating tickets. After dealing with all the encryption and realm related issues, the final working file was:

{% code overflow="wrap" fullWidth="false" %}

```
[libdefaults]
    default_realm = RUSTYKEY.HTB
    dns_lookup_realm = false
    dns_lookup_kdc = false
    rdns = false
    default_tkt_enctypes = rc4-hmac
    default_tgs_enctypes = rc4-hmac
    permitted_enctypes = rc4-hmac

[realms]
    RUSTYKEY.HTB = {
        kdc = dc.rustykey.htb
        admin_server = dc.rustykey.htb
        default_domain = rustykey.htb
    }

[domain_realm]
    .rustykey.htb = RUSTYKEY.HTB
    rustykey.htb = RUSTYKEY.HTB
```

{% endcode %}

In order to use this config, the `KRB5_CONFIG` environment variable needs to be set to its absolute path. For instance, in my case:

`export KRB5_CONFIG='/home/rr/Downloads/htb/rustykey/krb5.conf'`

A ticket can now be requested for IT-Computer3. I used impacket’s GetTGT.py:

`getTGT.py rustykey.htb/IT-Computer3$:'Rusty88!' -k -dc-ip dc.rustykey.htb`

Once this command executes successfully, the `KRB5CCNAME` environment variable needs to be set to the absolute location of the ticket. In my case:

`export KRB5CCNAME='/home/rr/Downloads/htb/rustykey/IT-Computer3$.ccache'`

Now we can use this ticket for operations. I used [bloodyAD](https://github.com/CravateRouge/bloodyAD) for most of it.

First, add IT-Computer3 to the HelpDesk group:

`bloodyAD — host dc.rustykey.htb -d 'rustykey.htb' -u 'IT-Computer3$' -p 'Rusty88!' -k add groupMember 'HelpDesk' 'IT-Computer3$'`

We have 3 users to work on now — `ee.reed`, `gg.anderson` and `bb.morgan`.

After changing each of their passwords, when I tried to obtain a kerberos ticket for them, I kept running into unsupported encryption type errors. I tried tinkering with the `enctypes` entries in my kerberos config file, adding entries for AES algorithms, but the errors persisted.

I went back to my privileges as a member of HelpDesk, and focused on the ability to add members to the Protected Objects group. I learnt that Protected Objects is a member of the Protected Users group, and that both Support and IT groups are members of the Protected Objects group. This can be better understood with the following graph:

<figure><img src="/files/J2he0SgBK3dvZ4SrBAeF" alt=""><figcaption></figcaption></figure>

> Protected Users is a global security group for Active Directory (AD) designed to protect against credential theft attacks. The group triggers nonconfigurable protection on devices and host computers to prevent credentials from being cached when group members sign-in.

<figure><img src="/files/rtDZozvfiMjhO7diNB9j" alt=""><figcaption><p><a href="https://learn.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/protected-users-security-group">Source</a></p></figcaption></figure>

To put it all together, all 3 users with WinRM rights are Protected Users. And although we can change their passwords, we cannot perform kerberos authentication for any of them since the DC only supports RC4 encryption which is explicitly denied for Protected Users.

To overcome this, HelpDesk’s AddMember permission can be used. We can remove our users from the Protected Objects groups, which ultimately removes them from Protected Users.

I decided to work on ee.reed first.

Removing his parent group (Support) from Protected Objects:

`bloodyAD — host dc.rustykey.htb -d 'rustykey.htb' -u 'IT-Computer3$' -p 'Rusty88!' -k remove groupMember 'Protected Objects' 'Support'`

Change his password:

`bloodyAD — host dc.rustykey.htb -d ‘rustykey.htb’ -u ‘IT-Computer3$’ -p ‘Rusty88!’ -k set password “ee.reed” ‘Rusty88!’`

And then I was able to successfully request a ticket for him.

However, when I tried to authenticate to `evil-winrm` with his ticket I kept getting this error:

<figure><img src="/files/dLnKxacugmgjceewxtAW" alt=""><figcaption></figcaption></figure>

On searching about it I came across another [HTB writeup](https://0xdf.gitlab.io/2025/04/26/htb-vintage.html) for an AD machine. The author received the same error while logging in as a certain user. It means that this user is denied from logging in by this manner.

Moving on, next I focused on `gg.anderson`. After performing the same steps as above (only difference being that in this case we must remove the IT group from Protected Objects), when I got to requesting a ticket for him, I received the following error:

<figure><img src="/files/0AHizPtGUIRuMLe7AAJb" alt=""><figcaption></figcaption></figure>

It seems that this account is disabled. To confirm, I used `ldapsearch` as IT-Computer3 and checked the `userAccountControl` attribute for him.

> The `userAccountControl` attribute is the sum of all active property flags set for a user. Read about it [here](https://learn.microsoft.com/en-us/troubleshoot/windows-server/active-directory/useraccountcontrol-manipulate-account-properties?utm_source=chatgpt.com#property-flag-descriptions).

<figure><img src="/files/kezDWXmaiSrSUy8ejFz3" alt=""><figcaption></figcaption></figure>

The value 66050 implies that this is a normal account (512) whose password never expires (65536) but it is disabled (2).

I tried to modify this value using `ldapmodify` but IT-Computer3 does not have the rights to do so.

That just leaves `bb.morgan`.

The steps to obtain his ticket are the same as `gg.anderson`. Authenticated as IT-Computer3, first remove the IT group from the Protected Objects group, and then reset bb.morgan’s password.

On another terminal, Use `GetTGT.py` to obtain a kerberos ticket for him. Then set the `KRB5CCNAME` environment variable to bb.morgan’s ticket’s path. And finally authenticate to `evil-winrm` with it.

<figure><img src="/files/QAFJQcj8jX4YJk10nIFP" alt=""><figcaption><p>User flag captured!</p></figcaption></figure>

Finally we have shell access to the machine.

On the desktop there is a PDF file containing a memo from bb.morgan to the members of the Support group. It informs that the Support group has been temporarily given elevated permissions to troubleshoot the file archiving tool on shared systems. It also highlights that they might need to make registry modifications due to differences in handling right-click context menus on newer systems.

The archiving tool can be found by viewing installed packages:

<figure><img src="/files/NoW4pzrUHHuYHiJZQYeK" alt=""><figcaption></figcaption></figure>

Searching about 7-Zip related info specific to registries, I came across the term Component Object Model (COM) Registration which involves the 7-Zip Shell Extension DLL.

> 7-Zip uses a Shell Extension to add items to the Windows right-click menu. This is what allows us to use features like Extract and Archive when we right-click on a file. To make this work, 7-Zip uses a **DLL file**, and registers it as a **COM object**.

This Shell Extension COM object is configured in the `HKEY_CLASSES_ROOT\CLSID\{23170F69–40C1–278A-1000–000100020000}` registry under the `InprocServer32` key. Let’s view its permissions so we can confirm what’s written in the PDF.

<figure><img src="/files/q8F5x1dsmMq8mSbrlqub" alt=""><figcaption></figcaption></figure>

This means a user of the Support group can hijack the DLL in this COM Object, replacing it with a malicious DLL that sends a reverse shell, for instance. This technique is called COM Hijacking and you can read more about it [here](https://www.mdsec.co.uk/2019/05/persistence-the-continued-or-prolonged-existence-of-something-part-2-com-hijacking/).

So now we need shell access as ee.reed since he’s the only member of the Support group. [RunasCs](https://github.com/antonioCoco/RunasCs/releases/download/v1.4/RunasCs.zip) can be used to do this.

We will need ee.reed’s password first. For this, follow the same process as before to reset his password with our IT-Computer3 account. Once his password is reset successfully, the -r option can be used to obtain a powershell connection on an nc listener on our machine:

<figure><img src="/files/2EGc66KgISijXNHsx9t6" alt=""><figcaption></figcaption></figure>

I used msfvenom to generate a malicious DLL which will provide a powershell reverse connection to my machine.

<figure><img src="/files/IMGrOsVq8yr1gYZmTKYj" alt=""><figcaption></figcaption></figure>

Uploading this on the machine, I went ahead and edited the registry value to point to my DLL:

<figure><img src="/files/jRIev2m6PQGJ0tCoWSTc" alt=""><figcaption></figcaption></figure>

Once the change was successful, I got a reverse shell as mm.turner user on my listener within a few minutes:

<figure><img src="/files/1JsuhyXFIP2Gg2KRm2sG" alt=""><figcaption></figcaption></figure>

Examining Bloodhound for this user:

<figure><img src="/files/nG8L11I0y72U18pMto3j" alt=""><figcaption></figcaption></figure>

As a member of the Delegation Managers group, mm.turner has the ability to write to the DC’s `msDS-Allowed-To-Act-On-Behalf-Of-Other-Identity` attribute, which is used for [Resource-Based Constrained Delegation](https://www.thehacker.recipes/ad/movement/kerberos/delegations/rbcd) attacks. To put it simply, with this ability we can pretend to be any domain user to the particular computer object (DC).

> Resource-Based constrained delegation means that the resource (DC here) decides who can impersonate users on it. This setting is controlled via the `msDS‑AllowedToActOnBehalfOfOtherIdentity` attribute on the **resource’s account**. Since we have the ability to change this attribute, we can set either a user with an SPN or a computer account to impersonate users on the DC.

Bloodhound provides the exact steps that are needed to perform this attack. It usually requires the creation of a computer account but we can use IT-Computer3. Overall, the following commands add the SID of IT-Computer3 to the `msDS‑AllowedToActOnBehalfOfOtherIdentity` attribute of the DC. This will require the [PowerView](https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1) script to be imported to the PowerShell session.

<figure><img src="/files/8BUiVoOBckRZwovpe1Ia" alt=""><figcaption></figcaption></figure>

After this, [Rubeus](https://github.com/r3motecontrol/Ghostpack-CompiledBinaries/blob/master/Rubeus.exe) can be used to exploit this ability in order to obtain a service ticket for any user we want. I tried impersonating the administrator but kept getting `KDC_ERR_BADOPTION` error. Then I remembered from Bloodhound that there’s another admin we can impersonate — backupadmin.

This worked, and I successfully obtained a service ticket as backupadmin. I dumped it with Rubeus to use it on my attacking machine.The following is a summary of the list of commands to be run as mm.turner:

{% code overflow="wrap" %}

```
# After importing powerview
$ComputerSid = Get-DomainComputer 'IT-Computer3' -Properties objectsid | Select -Expand objectsid

#We now need to build a generic ACE with the attacker-added computer SID as the principal, and get the binary bytes for the new DACL/ACE:
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($ComputerSid))"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)

#Next, we need to set this newly created security descriptor in the msDS-AllowedToActOnBehalfOfOtherIdentity field of the computer account we're taking over, again using PowerView in this case:
Get-DomainComputer 'DC' | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}

Rubeus.exe hash /password:Rusty88!

#And finally we can use Rubeus' *s4u* module to get a service ticket for the service name (sname) we want to "pretend" to be "admin" for. This ticket is injected (thanks to /ptt)
Rubeus.exe s4u /user:IT-Computer3$ /rc4:<output from previous command> /impersonateuser:backupadmin /msdsspn:cifs/DC.rustykey.htb /ptt

./Rubeus.exe dump /nowrap
```

{% endcode %}

I took the base64-encoded ticket dumped by Rubeus and base64-decoded it to obtain the service ticket in `kirbi` format which is default for Rubeus. Then, I used Impacket’s `ticketConverter.py` to convert it to the `ccache` format that Impacket tools accept.

<figure><img src="/files/zIQoBdVlBxIOETR6J7Ui" alt=""><figcaption></figcaption></figure>

Now we can use this to spawn an admin shell with Impacket’s `psexec.py`!

<figure><img src="/files/FmX5nWIFQoLLjjGnCXWv" alt=""><figcaption></figcaption></figure>

Rooted!

***

This machine was quite a fun and adventurous one. So many concepts to learn and abuse, and a great deal of exploration.

If you liked my explanation, don’t forget to drop a respect on my [HTB Profile](https://app.hackthebox.com/profile/1544251) :)

<mark style="color:$info;">\[Originally Published on Jan 24, 2026]</mark>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://cl4nd3st1ne.gitbook.io/write-ups/hack-the-box/machines/htb-season-8-rustykey-walk-through.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
