Dismay
Challenge Lab (Hard) - by D1n0Gm01d
The following post by 0xb0b is licensed under CC BY 4.0
Scenario
Objective
You have been assigned a penetration test of a client's internal network. There are three different servers in-scope. Your task is to identify all vulnerabilities and demonstrate impact to the client by elevating your access to Domain Admin. The client has provided you VPN access and Active Directory credentials (below) for the engagement.
Please note - there are 2 intended paths to compromise this machine. Once you solve it one way, we encourage you to try and solve it a second way.
Initial Access
The client has provided you with Active Directory credentials and VPN access. xiao.ge:AmBZATVjnH4qo8H4
Summary
Summary
In Dismay, we begin with assumed breach credentials to gain an initial foothold via SMB and RDP on the Nexus WSUS server, quickly identifying a Windows enterprise environment with exposed AD, WSUS, and certificate services across multiple domain controllers. Early access reveals sensitive artifacts in the Recycle Bin, including an encrypted archive and a penetration testing report, which we decrypt by combining reused passwords and wordlist generation to recover credentials, decrypting the archive to gain access to a penetration test report revealing credentials for user guy.rookie.
In parallel, exploitation of a vulnerable WSUS deployment CVE-2025-59287 allows SYSTEM-level compromise on Nexus via unsafe deserialization, which is further leveraged to deploy a Sliver-based stager chain using a Potato exploit and achieve full control of the host, also leading to the penetration test report on the Administrators Desktop.
With expanded access as guy.rookie, we enumerate the domain and uncover multiple privilege escalation paths, including misconfigured AD permissions. From there, BloodHound analysis reveals a chained delegation path through password resets and group membership manipulation, enabling progression from jena.yamazaki to mike.silver, granting access to the Tools share on DC1. A DLL hijack weakness in a broken enterprise binary is then abused to execute a malicious payload, providing execution as wang.kali on DC1.
Finally, privilege escalation continues through AD group delegation, RDP access, and ESC8 exploitation against AD CS on DC2 using NTLM relay and PetitPotam coercion. By obtaining a valid machine certificate and performing DCSync, we extract domain secrets and escalate to Domain Admin, culminating in full compromise of DC2 as Administrator and retrieval of the final flag.
Changelog
Beyond Root - Attack Path prior Changes
Before the change, the web enrollment endpoint was not accessible externally, but it was enabled and accessible locally on DC2. But having the web enrollment enabled but not accessible lacks realism. This required the following attack path. The attack path still available!
The port forwarding is no longer necessary. In my opinion the steps involved are still interesting and I recommend to give it a try.
The old path is covered in Beyond Root - Attack Path prior Changes section.
Recon
Nexus
We use rustscan -b 500 -a 10.0.29.100 --top -- -sC -sV -Pn to enumerate all TCP ports on the target machine, piping the discovered results into Nmap which runs default NSE scripts -sC, service and version detection -sV, and treats the host as online without ICMP echo -Pn.
A batch size of 500 trades speed for stability, the default 1500 balances both, while much larger sizes increase throughput but risk missed responses and instability.

The target 10.1.83.105 is a Windows-based host. It hosts a Microsoft IIS 10.0 web server on port 80, as well as additional web services on ports 8530 (IIS) and 8531. The host has SMB services exposed via ports 139 and 445 with message signing enabled but not required. Remote management and access are available through RDP 3389. Furthermore, the system exposes several MSRPC endpoints on ports 135, 49667, and 49668.

Ports 8530 and 8531 are the defaults for Windows Server Update Services (WSUS), used by client machines to check for, download, and report the status of software updates from the central update server.

SMB
We are now attempting to authenticate via SMB using xiao.ge and list the available shares.
The output confirms that your target is a WSUS server with several associated shares accessible for reading.
The most critical threat in 2026 is CVE-2025-59287, a critical unauthenticated Remote Code Execution (RCE) vulnerability caused by unsafe deserialization in the WSUS authorization cookie. This might be a lead forfurhter escalation.

We connect to the WsusContent share using impackets smbclient.py but do not find anything useful.

RDP
Next, we try to connect to the Nexus host via RDP using the provided credentials, and we succeed. At first glance, we see that there is still something in the Recycle Bin.

There is a confidential 7zip ZIP file in the Recycle Bin. As it turns out, it is encrypted. The Recycle Bin furthermore contains an invoice, meeting notes, and an audit log. We'll take a closer look at the contents later. But this could present an opportunity to elevate our privileges or move laterally.

In C:\Tools, we find WSUS-related scripts. We'll take a closer look at these in the next steps as a way to potentially elevate our privileges. As mentioned earlier, we might be able to exploit CVE-2025-59287 and these scripts could help us with that, or provide us with insights.

DC1
Before we continue with our first findings on the Nexus machine, we continue with an initial enumeration of DC1 and DC2.
We use rustscan -b 500 -a 10.0.31.114 --top -- -sC -sV -Pn to enumerate all TCP ports on the target machine, piping the discovered results into Nmap which runs default NSE scripts -sC, service and version detection -sV, and treats the host as online without ICMP echo -Pn.
A batch size of 500 trades speed for stability, the default 1500 balances both, while much larger sizes increase throughput but risk missed responses and instability.
The target DC1.dismay.hsm is a Windows-based host acting as a Domain Controller for the dismay.hsm domain.
It runs Active Directory services with LDAP exposed on ports 389/636 and Global Catalog on 3268/3269, alongside Kerberos on port 88 and DNS on port 53. SMB services 139/445 are open with message signing enabled. The host also exposes MSRPC endpoints 135, 593, 49664, etc. and the Active Directory Web Services on port 9389. Remote management is available via RDP on port 3389 and WinRM on port 5985.

SMB
We are trying to authenticate via SMB using the provided credentials through NetExec, but we are unable to do so.

Even though authentication is missing, we use NetExec to generate a host file entry for the DC.

We add the following entry to our /etc/hosts file if we haven't passed it directly to NetExec:
DC2
We use rustscan -b 500 -a 10.0.18.82 --top -- -sC -sV -Pn to enumerate all TCP ports on the target machine, piping the discovered results into Nmap which runs default NSE scripts -sC, service and version detection -sV, and treats the host as online without ICMP echo -Pn.
A batch size of 500 trades speed for stability, the default 1500 balances both, while much larger sizes increase throughput but risk missed responses and instability.
The target DC2.dismay.hsm is a Windows-based host serving as a secondary Domain Controller and the Enterprise Certificate Authority for the dismay.hsm domain.
It runs Active Directory services with LDAP exposed on ports 389/636 and Global Catalog on 3268/3269, alongside Kerberos on port 88 and DNS on port 53. SMB services 139/445 are open with message signing enabled. Notably, the host exposes web services on ports 80 and 443, and its SSL certificate identifies it as the issuer commonName=dismay-DC2-CA. Multiple MSRPC endpoints are open 135, 593, 49664, etc., and remote access is provided via RDP 3389 and WinRM 5985.

SMB
We are trying to authenticate via SMB using the provided credentials through NetExec, but we are unable to do so.

Even though authentication is missing, we use NetExec to generate a host file entry for the DC.

We add the following entry to our /etc/hosts file if we haven't passed it directly to NetExec:
Access as guy.rookie
We'll continue with the results of our enumeration on the Nexus host and see that we have two paths to escalte our privileges. First, we'll look at the items in the Recycle Bin. Alternatively, we can also expand our privileges using the exposed WSUS service.
via sensitive file disclosure
As we recall, we found the four files in the Recycle Bin. We will now transfer them to our system via a shared folder and examine them. The 7zip file is encrypted.

The invoice contains two passwords.

We will generate a list of words containing the keywords and passwords from the invoice, as well as the password we know for the user xiao.ge.
Next, we generate the a hash from the file using 7z2john.pl...
... and attempt to crack it. We see that passwords had been reused; we were able to crack the hash and open the ZIP file.


The archive contains Confidential.pdf, a penetration test report. This file contains the credentials for the user guy.rookie. We make a note of them.

We test the credentials of guy.rookie that we just found and attempting to authenticate ourselves against DC1 via SMB using Netexec. We succeed in doing so and, at the same time, discover a Tools share to which we currently have neither read nor write permissions. Next, we can try to enumerate the domain using the credentials we've obtained.

via WSUS exploit
The following path is an alternative approach that exploits a vulnerability in WSUS to elevate privileges on the Nexus machine to get access to the penetration test report. It is optional and can be skipped, but is still worth exploring.
Additionally, this path demonstrates how to create a stager, which will be reused later in the scenario.
Shell as NT AUTHORITY\NETWORK SERVICE on Nexus
During our initial assessment of the Nexus machine, we determined that the WSUS server was running on it. After a brief investigation, we came across CVE-2025-59287.
This is the most recent and critical threat in 2026 with a a critical unauthenticated Remote Code Execution vulnerability caused by unsafe deserialization in the WSUS authorization cookie. This might be a lead forfurhter escalation.
Offsec provides an in-depth analysis of the vulnerability, including a link to a proof-of-concept. I recommend reading this blog
We will try to use the exploit showcased in the blog. All we need is the poc and ysoserial.
We just need to make slight adjustments in the wsus-rce.ps1 by adapting the host, port and target URL. We chose the target URL to be 127.0.0.1, since we will run it on the target machine.

We provide the PoC via a web server, alternatively we could also mount a share.

We download both on the system and extract the ysoserial zip file. PoC and the ysoserial folder need to be in the same location.

Next, we run the poc,...

... and set up a listener. The reverse-shell payload will be triggered when an administrator opens the WSUS management console

After 10 minutes we receive a connection back. We are NT AUTHORITY\NETWORK.

The process can be speed up by the scripts in C:\Test.
The script Apply-WsusSecurityPolicy.ps1 is used by an Administrator to grant the user xiao.ge permission to access and execute the scheduled task named WSUS. It reads the task's current SDDL permissions, adds an ACE giving GRGX (Generic Read + Execute) rights to xiao.ge, and applies the updated permissions to both the task and the root task folder.
Impact: This allows a low-privileged user to manually view and run the high-privilege WSUS scheduled task without needing administrator credentials, password prompts, or UAC elevation.
This script Invoke-WSUSMaintenance.ps1 acts as the actual WSUS trigger by first sending a request to the local WSUS IIS endpoint to wake up the WsusPool application pool, ensuring the service is active. It then connects to the WSUS server using AdminProxy, searches for a specific security update (KB5031354), and runs PerformCleanup() with a cleanup scope that declines expired updates.
Impact: Triggering these WSUS operations can force service-side processing under elevated privileges, making it useful for abusing a privileged scheduled task or backend WSUS execution path from a lower-privileged shell.
So technically if we start the task we should immediatly get a callback.
Shell as NT AUTHORITY/SYSTEM on Nexus
We see that we, as this user, have the SeImpersonatePivilige permission active.

Since the SeImpersonatePrivilege is enabled we can make use of one of the infamous potato exploits. One of my favorite Potato exploits is the EfsPotato exploit. We can compile this on the machine if the C# compiler is available, and it should also go undetected.
We check for a compiler at C:\Windows\Microsoft.Net\Framework\ and see a v4.0 version is persent. Nice.

The csc.exe to compile the exploit is present.
Next, we download the source file from our attacker machine, compile with the compiler found at C:\Windows\Microsoft.Net\Framework\v4... and execute it with the whoami command.
We download the file:
And compile the potato exploit:

Next we want to execute with elevated privileges to get a reverse shell. We will continue this challenge using Sliver-C2. For this we will prepare a stager we want to execute and setup Sliver.
Prepare a custom stager
First we need to prepare the stager.
The stager fetches raw shellcode from a chosen URL and loads it directly into memory as bytes. The payload is not embedded in the binary, allowing it to be changed without recompiling.
It calls VirtualAlloc to reserve and commit memory with execute, read, and write permissions, then copies the downloaded shellcode into that memory using unsafe pointer operations.
The execution is transferred to the allocated memory address using syscall.Syscall, handing control to the shellcode.
We compile the stager as follows on our exegol instance:
The addition of -ldflags="-H windowsgui" ensures that we compile it as an application and not a console app, so it wont spawn a terminal.
Since the stager got caught due to sample submission, but want to reuse it, we use a simple trick and use the -s -w ldflags for compilation.
Using -s -w strips debug symbols and DWARF metadata from the Go binary, changing its hash and reducing recognizable signatures, which can help avoid detection because antivirus engines that previously flagged the original sample submission may no longer match the modified compiled file exactly. We might see this neat trick later again.

Generate shell code
During generation without the -G tag, which disables the encoder, no shellcode could be successfully generated. The resulting shellcode was always empty. This may be related to the underlying architecture on which I am operating, namely ARM:
Next, we need to generate the shell code insed our sliver instance. We do this as follows:

We run a web server from which the stager and the shellcode can be fetched.
Setup listener
We set up the listener in sliver as follows:

Next, we download and run our stager with the EfsPotato exploit


We get a connection back to our listener in Sliver.
To interacte with the session received we issue sessions -i <id>.
We are NT AUTHORITY SYSTEM.
At C:/Users/Administrator/Desktop/Confidential.pdf we find a penetration test report...

... which contains the credentials of guy.rookie.

We test the credentials of guy.rookie that we just found and attempting to authenticate ourselves against DC1 via SMB using Netexec. We succeed in doing so and, at the same time, discover a Tools share to which we currently have neither read nor write permissions. Next, we can try to enumerate the domain using the credentials we've obtained.

Bloodhound Enumeration
With the credentials, we can now also enumerate the AD using BloodHound.

We first look at our compromised user and initially, we are can change the password of jena.yamazaki via ForceChangePassword.

From there we have GenericAll from yena.yamazaki to mike.silver. Allowing us to change the password of that user. This user is allowed to add members to the shares_operators group. This might enable us to get access to the Tools share we identified earlier.

Besides the path identified we check for Domain Admins and only find the Administrator user as one of those.

AD CS Enumeration
We are also trying to identify certificate misconfigurations using Certipy and have a possible ESC8 misconfiguration infront of us..


Next, we check for certificates to use for enrollment.

The User template allows any authenticated domain user to enroll for a client authentication certificatee, which can be abused during ESC8 to obtain a valid certificate for authentication if NTLM relay to Web Enrollment is successful.
Shell as Administrator on DC2
So the steps for ESC8 are as follows:
Force or capture NTLM auth from a machine/user
Relay it to:
Request certificate on behalf of that relayed identity
Use cert for authentication (LDAP/Kerberos)
A cheat sheet can be found here:
A detailed explanation for ESC8 can be found here:
First, we start ntlmrelayx.py to relay captured NTLM authentication to the AD CS Web Enrollment endpoint at certfnsh.asp, requesting a certificate using the User template. If successful, it issues a certificate for the relayed identity, enabling authentication to the Active Directory services.

Next, we use PetitPotam to coerce DC1 into authenticating to the attacker-controlled host 10.200.38.246 by abusing MS-EFSRPC calls. The provided credentials of guy.rookie are used to trigger the authentication attempt, which can then be captured and relayed. We use our machine IP 10.200.38.246 since we run the relay.

After a while, we receive a certificate file.

Next we authenticate via certipy using the DC1.pfx certificate obtained giving us a ccache file and the NTLM hash of the DC1$ machine.

Since we now have access as the DC1 we are able to perform a DCSync.

DCSync is a technique that uses Windows Domain Controller's API to simulate the replication process from a remote domain controller allowing to request password data from a domain controller as if they were another DC. We can do it either using the gathered hash or the ccache file via impackets secretsdump.py.
We retrieve the NTLM hash of the Administrator account.

We connect to DC2 as Administrator using the hash...

... and find the final flag at C:\Users\Administrator\Desktop\root.txt.


Beyond Root - Attack Path prior Changes
Before the change, the web enrollment endpoint was not accessible externally, but it was enabled and accessible locally on DC2. But having the web enrollment enabled but not accessible lacks realism. This required the following attack path. The attack path still available!
The port forwarding is no longer necessary. In my opinion the steps involved are still interesting and I recommend to give it a try.
AD CS Enumeration
We are also trying to identify certificate misconfigurations using Certipy, but we don't find any.

Since DC2 is the Certificate Authority, we check whether the web server is running and providing Web Enrollment at http://dc2.dismay.hsm/certsrv. In this case, it is not available. If it were accessible, it could potentially allow exploitation through ESC8, but we keep this in mind as a possible attack path.

Access as jena.yamazaki
Next, we follow the path identified and try to get access as jena.yamazaki.
To change the password we use bloodyAD:

After we have changed the password we try to authenticate as jena.yamazaki via SMB using NetExec and are successful.

Access as mike.silver
Next, we try to gain access as mike.silver by changing its password using the GenericAll permission that jena.yamazaki has over mike.silver.

After we have changed the password we try to authenticate as mike.silver via SMB using NetExec and are successful.

Shell as wang.kali on DC1
Next, we add mike.silver to the shares_operators group via bloodyAD.

Now we are able to read and write to the Tools share.

We connect to the share using impacktes smbclient.py and find several executables, we download them all to our attacker machine.

In the note we can see that Adrian is giving Kali a final warning to urgently fix a broken executable that was deployed last Thursday, as it is causing major issues for users and auditors. He demands a working replacement by 17:00 tomorrow and warns that failure to do so could result in termination.
We transfer the executables to our Windows exploit development environment to analyze them further. We run them and notice that the Dism.exe has trouble locating the dismcore.dll. This sounds familiar from the past scenario Sideload. If you missed it I highly recommend checking it out:
We may have the opportunity to use search order hijacking to place a malicious DLL that gets loaded upon execution, thereby providing us with a reverse shell or a stager to execute. If successful, we could potentially gain access to DC1.

Before diving into DLL sideloading and proxying, let's start with a basic DLL hijacking payload. This DLL uses the DllMain function, which is automatically executed when the DLL is loaded by a process, and triggers WinExec("calc.exe", SW_SHOW) during the DLL_PROCESS_ATTACH event to launch Calculator. In a DLL hijacking scenario, placing this malicious DLL where a vulnerable application loads it instead of the legitimate one allows arbitrary code execution as soon as the target application starts.
We can compile the DLL on our attacker machine and transfer it to our test environment. When we launch Dism.exe with the malicious DLL placed in the same folder, we notice that although another error appears, the calculator is launched. We can then replace this simple payload with one that downloads and executes the stager we created earlier, allowing us to establish a session in Sliver C2.

The creation of the stager is covered in th WSUS exploit section
Now we replace the calculator proof-of-concept with a payload for command and control access. When the DLL is loaded, it silently launches PowerShell, downloads stager.exe from our web server into the victim's %APPDATA% directory, and then executes it.
We compile the DLL...

... and place it into the share.

After around a minute we receive a session. We interact with it and see we are the user wang.kali.

We find the users flag at C:/user/wang.kali/Desktop/user.txt.

Shell as mike.silver on DC2
Since we now have access to a user we haven't yet identified in our attack path, let's take a look at what specific permissions and group memberships they have. The user is allowed to add members to the dc2-winrm-users group. Sounds like we can get access to the DC2 with that permission.

We chose to add our compromised user mike.silver to the group using powershell.
We use Sliver's execute to run the command directly on the target. It is cleaner and more reliable than spawning an interactive shell with shell, since execute runs the command non-interactively through the implant, avoiding unstable shell sessions, output issues, and additional detection opportunities caused by launching cmd.exe or powershell.exe manually.

After adding the user mike.silver we can connect to DC2 via evil-winrm.

Shell as Administrator on DC2
Check for web enrollment
Since Certipy did not initially reveal anything useful and we already know that DC2 is the Certificate Authority, the next step is to manually check whether Web Enrollment is available internally. Access to /certsrv could indicate a potential ESC8 attack path, even if it is not exposed externally. By querying it locally with curl http://127.0.0.1/certsrv. We can verify that web enrollment is enabled.
Receiving a 401 Unauthorized response from /certsrv/ is actually a good sign. It confirms that AD CS Web Enrollment is installed, IIS is actively serving the /certsrv endpoint, and authentication is required., typically through NTLM. This means the service is potentially vulnerable to ESC8 through NTLM relay attacks.
ESC8 is an Active Directory Certificate Services misconfiguration where NTLM authentication can be relayed to the Web Enrollment /certsrv endpoint to request a certificate on behalf of another user or machine. If successful, we can obtain a valid certificate for a privileged account, which can then be used for authentication and privilege escalation without needing the account's password.

Port forwarding
We want to make the internal web port of our attacker machine accessible via port forwarding. For this, we're using Ligolo-ng.
A comprehensive guide on pivoting with ligolo-ng can be found here, but is not required here:
First, we start our proxy.

Inside that proxy we create an interface called dc2-local.
And add the following route, which routes ligolo-ng's default IP address 240.0.0.0.1 to access to the local ports of the connected remote agent.

Next, we upload an agent and try to connect to our proxy. But it gets detected by Defender.

Fortunately, there's a workaround. This blog post takes a deep dive into the issue and uses the same trick we needed for our stager, which Windows ate up due to clumsy handling while having active sample submissions active. We simply re-compile ligolo-ng with the ldflags "-s -w".
Using -s -w strips debug symbols and DWARF metadata from the Go binary, changing its hash and reducing recognizable signatures, which can help avoid detection because antivirus engines that previously flagged the original sample submission may no longer match the modified compiled file exactly.

Next, we upload our new agent, and try to connect to our proxy. This time we are successful.

After the connection has been made we should see in our proxy that an agent has joined.
We can list and interact with the session by calling session and then chosing the session. The following screenshot illustrates the steps taken.
After chosing the session, we can start the tunnel.
To confirum our tunnel and routes we can issue the following commands:

Now we can request the certsrv endpoint. If we provide the credentials of one of our compromised user we see a welcome page.


Abusing ESC8
We recall our certipy output, without the vulnerable parameter to list all templates available.

The User template allows any authenticated domain user to enroll for a client authentication certificatee, which can be abused during ESC8 to obtain a valid certificate for authentication if NTLM relay to Web Enrollment is successful.
So the steps for ESC8 are as follows:
Force or capture NTLM auth from a machine/user
Relay it to:
Request certificate on behalf of that relayed identity
Use cert for authentication (LDAP/Kerberos)
A cheat sheet can be found here:
A detailed explanation for ESC8 can be found here:
First, we start ntlmrelayx.py to relay captured NTLM authentication to the AD CS Web Enrollment endpoint at certfnsh.asp, requesting a certificate using the vulnerable User template. If successful, it issues a certificate for the relayed identity, enabling authentication to the Active Directory services.

Next, we use PetitPotam to coerce DC1 into authenticating to the attacker-controlled host 10.200.38.246 by abusing MS-EFSRPC calls. The provided credentials mike.silver are used to trigger the authentication attempt, which can then be captured and relayed. We use our machine IP 10.200.38.246 since we run the relay.

After a while, we receive a certificate file; this may take a few relay attempts.

Next we authenticate via certipy using the DC1.pfx certificate obtained giving us a ccache file and the NTLM hash of the DC1$ machine.

Since we now have access as the DC1 we are able to perform a DCSync.

DCSync is a technique that uses Windows Domain Controller's API to simulate the replication process from a remote domain controller allowing to request password data from a domain controller as if they were another DC. We can do it either using the gathered hash or the ccache file via impackets secretsdump.py.
We retrieve the NTLM hash of the Administrator account.

We connect to DC2 as Administrator using the hash...

... and find the final flag at C:\Users\Administrator\Desktop\root.txt.


Last updated