Players will investigate a ransomware attack originating from an insider threat. They’ll reconstruct the event timeline using Windows artifacts, retrieve a sample of the malware, reverse-engineer it, and successfully decrypt the affected files.
An insider operating as Krampus pivoted by network logon from another workstation onto Santa’s machine and browsed the file server, opening folders about Christmas Eve plans and a departmental complaints file. Defender blocked a first certutil download of a collection package, so the actor switched off real-time protection and pulled a 7-Zip installer and a renamed FileZilla installer instead. Files from the share and from Santa’s desktop archive were staged with 7-Zip, the resulting zip was renamed and pushed to the actor’s own Linux server over a saved FileZilla session. Krampus then fetched a ransomware bundle from a second host, ran it, and logged off. The ransomware is compiled V8 bytecode; disassembling it exposed the XOR-wrapped key and IV, which decrypted the affected documents.
Windows/System32/winevt/logs → parse with EvtxECmd. Security (4624/4634), TerminalServices, and Windows Defender Operationalsanta/Recent → LECmd. Target paths and share namessanta NTUSER and UsrClass → SBECmd. First and last interaction times per folderHKCU\Software\7-Zip → regipy. FM panel paths, folder history, copy history and archive history are stored as UTF-16 stringsrecentservers.xml, filezilla.xml, queue.sqlite3 → text editor and sqlite3MetaData and Content → strings -el for the URL, and the cached file itself for the payloadWindows/Prefetch → PECmdTimestamp note: Most questions take
YYYY-MM-DD HH:MM:SS. The shellbag first-interaction time and the Security event time are different clocks for the same action; Q4 wants the shellbag one.
Parse the Security log and list 4624 network logons (type 3) on Santa’s machine around the start of the intrusion. The first NTLM logon arrives with the source workstation name in the event, which is the hop-off host. The hostname is case-mixed in the event, so copy it as logged.
EvtxECmd -d C/Windows/System32/winevt/logs --csv work/evtx
grep ',4624,' work/evtx/*.csv | grep -i ntlm
Tip: Filter on logon type 3 and NTLM; the workstation name field is the answer, not the IP.
From Q1 we have the source host and the logon attempt. The 4624 for the interactive session carries a LogonId (0x312175), and the Terminal Services 1149 RDP event lines up with it a few seconds after the network logon at 10:38:49. The same LogonId is later used to find the logoff in Q24.
grep -E ',(4624|1149),' work/evtx/*.csv
Parse Santa’s Recent folder with LECmd and look for LNK files pointing at the file server. One is named after a Christmas Eve folder under kitchen-prep, and its target path gives the full UNC path.
LECmd -d santa/Recent --csv work/lnk
Gotcha: The LNK stores the share name in upper case, but the accepted path uses
filesharein lower case and keeps the misspelledcristmasin the folder name.
Run SBECmd over Santa’s hive and filter to the folder from Q3. The shellbag entry for cristmas-eve-PRIORITY records when the folder was first interacted with, which is the moment the attacker browsed to it. This was reasoned from the artifact semantics rather than read from a field labelled “visited”.
SBECmd -d santa --csv work/sb
Gotcha: The LNK target access time, other Security log times are all close to this value but are not it. Shellbag first-interaction is the one that matches the question.
A second LNK in Recent, toys-dept.lnk, resolves to the Complaints folder on the same share and points at a text file. That same filename shows up again in the archive the attacker built for exfiltration.
LECmd -d santa/Recent --csv work/lnk
Defender logged a threat detection (1116) and remediation (1117) for a certutil download. The full command line sits in the event’s Path field, with the -urlcache -f flags and the staging URL on port 8175 under OpXmasDestroy/Collection.
grep -E ',(1116|1117),' work/evtx/*.csv
Tip: The
Pathfield holds the full command line, not just the binary path. Read it in full before trimming.
Download URLs for tools fetched through the Windows crypto stack are cached under CryptnetUrlCache\MetaData. Reading the metadata files as UTF-16 shows two URLs on the same host and port: the collection package.exe (the one Defender stopped) and exfil/Godzilla.exe. The exfiltration tool is the second.
strings -el CryptnetUrlCache/MetaData/*
The cached Godzilla.exe is a PE file that turns out to be a FileZilla installer under a different name. The FileZilla profile on the box (saved server, queue database) confirms the same software was used for the upload.
strings -el CryptnetUrlCache/MetaData/* | grep -i godzilla
Gotcha: The download filename is not the software name. Check the installer metadata or the profile it creates.
After the blocked certutil attempt, Defender logged event 5001, which is real-time protection being disabled. The timestamp on that event is the answer,.
grep ',5001,' work/evtx/*.csv
7-Zip File Manager stores its history in NTUSER.DAT under HKCU\Software\7-Zip\FM. Decode CopyHistory as UTF-16; the destination directory the file was copied to is the answer.
regipy dump of NTUSER.DAT \Software\7-Zip keys
regipy decode 7-Zip FM CopyHistory/FolderHistory (UTF-16)
The 7-Zip path history contains the zip on Santa’s desktop with its internal folder path, since 7-Zip FM treats archives as folders. Searching the hive for finance_christmas gives the nested Employees\performance_bonus_24 folder. This was found with strings over the hive rather than a registry parser.
strings -el NTUSER.DAT | grep -i finance_christmas
ArcHistory under the same 7-Zip key lists archives the user created or opened. The new archive the attacker made for staging is the entry that is not Santa’s own zip.
regipy decode 7-Zip FM CopyHistory/FolderHistory (UTF-16)
PanelPath0 and FolderHistory under the 7-Zip FM key record the last directory shown in the file manager panel. It points into a PowerShell configuration folder under Program Files (x86), an unusual location for file-manager activity.
regipy decode 7-Zip FM CopyHistory/FolderHistory (UTF-16)
Tip: The format asks for no trailing slash, unlike Q8.
The staging archive from Q10 was renamed before upload. Strings over the NTUSER hive and the jump lists surface the new zip name, and the FileZilla queue data is consistent with it.
strings -el NTUSER.DAT | grep -i '\.zip'
sqlite3 queue.sqlite3 'select * from files'
FileZilla’s recentservers.xml stores the host, user and a base64-encoded password for the saved server. Decode the Pass element to get the credential pair for the actor’s server.
grep -iE '<(Host|User|Pass)' recentservers.xml
The FileZilla RemotePath entry in the profile and the queue database show the directory on the Linux server where the upload landed. Copy the path exactly as stored.
sqlite3 queue.sqlite3 'select * from servers'
Gotcha: Linux paths are case-sensitive, so keep the capitalisation of every path element as stored.
The same CryptnetUrlCache\MetaData strings pass reveals a second host with no port and a final_operation folder, serving destroyer.zip. That is the ransomware bundle.
strings -el CryptnetUrlCache/MetaData/*
The cached download is the zip itself, in CryptnetUrlCache\Content. Unzip it (statically, nothing is run) and hash the executable it contains.
unzip CryptnetUrlCache/Content/5A76... -d work/destroyer
sha256sum work/destroyer/destroyer/krampus.exe
PECmd over the prefetch directory gives the run times for KRAMPUS.EXE. The last-run time is the execution, and it is minutes after the exfiltration finished.
PECmd -d prefetch --csv work/pf
The ransomware is compiled V8 bytecode (krampus.jsc), so no decompiler worked and the bytecode had to be disassembled by hand with a small Python disassembler built from the matching V8 bytecode table. The encryption constants are stored base64-encoded and XORed with the string C:/Users/Public/file.txt. The XOR routine has an off-by-one key wrap, so the key index runs one past the end of the string, which means a zero byte is inserted each cycle. A plain repeating-key XOR gives wrong output. The IV is the decoded and de-XORed first constant.
python3 -I work/dis/<disassembler>.py krampus.jsc
Gotcha: If the recovered IV or key looks mostly right but has garbled characters, check the key wrap in the XOR routine.
The key comes from the second base64 constant, using the same XOR with the same off-by-one wrap as Q20. It is 32 characters long.
python3 -I work/dis/<disassembler>.py krampus.jsc
With the key and IV, decrypt the encrypted files in the user’s directory and open the Naughty list. One entry is tagged [Extra naughty kid].
python3 -I <decryptor>.py <encrypted-file>
The decrypted spreadsheet has a row marked Confirmed with a 13699$ amount. The name on that row is the promotion and raise.
python3 -I <decryptor>.py <encrypted-xlsx>
Gotcha: The cell holds a single token with no space, and the format example suggests a normal name. Copy it exactly as the cell has it.
The 4634 logoff event carries the same LogonId (0x312175) as the logon in Q2, which ties the session start and end together.
grep ',4634,' work/evtx/*.csv | grep 0x312175
| Phase | Action |
|---|---|
| Lateral Movement | Network logon and RDP session onto Santa’s workstation from another host |
| Discovery | Browses the file server, opening the Christmas Eve folder and the departmental complaints file |
| Command and Control | certutil download of a collection package is blocked by Defender |
| Defense Evasion | Real-time protection disabled |
| Collection | 7-Zip and FileZilla installers fetched; files copied and archived with 7-Zip, including contents of Santa’s finance zip |
| Exfiltration | Archive renamed and uploaded to Krampus’s Linux server over a saved FileZilla session |
| Impact | Ransomware bundle downloaded from a second host and executed |
| Impact | Session ends with logoff |
| Timestamp | Event |
|---|---|
| 2024-12-10 10:38:49 | NTLM network logon from the source workstation |
| 2024-12-10 10:38:58 | Krampus session logs on (LogonId 0x312175) |
| 2024-12-10 10:41:40 | Christmas Eve share folder first browsed |
| 2024-12-10 10:44:10 | Defender real-time protection disabled |
| 2024-12-10 11:06:30 | KRAMPUS.EXE runs per prefetch |
| 2024-12-10 11:10:19 | Session logoff |
| Type | Value |
|---|---|
| URL (blocked package) | hxxp[://]3[.]110[.]162[.]216[:]8175/OpXmasDestroy/Collection/package.exe |
| URL (exfil tool) | hxxp[://]3[.]110[.]162[.]216[:]8175/OpXmasDestroy/exfil/Godzilla.exe |
| URL (ransomware) | hxxp[://]3[.]109[.]152[.]7/final_operation/destroyer.zip |
| SHA-256 (krampus.exe) | 808F098B303D6143E317DD8DAE9E67AC8D2BCB445427D221AA9AD838AA150DE3 |
| Archive | scan87x.zip, renamed to transfer_scanned.zip |
| Staging directory | C:\Users\Public\scan\ |
| Exfil path | /home/krampus/ChristmasOP/santaloot |
| Technique | ID | Description |
|---|---|---|
| Remote Services: Remote Desktop Protocol | T1021.001 | Network logon and RDP onto Santa’s workstation |
| Network Share Discovery | T1135 | Browsing the file server shares |
| Data from Network Shared Drive | T1039 | Complaints and Christmas Eve folder contents collected |
| Ingress Tool Transfer | T1105 | certutil and later installer and ransomware downloads |
| Impair Defenses: Disable or Modify Tools | T1562.001 | Defender real-time protection turned off |
| Archive Collected Data: Archive via Utility | T1560.001 | 7-Zip archive of collected files |
| Exfiltration Over Alternative Protocol | T1048 | FileZilla upload to the actor’s server |
| Data Encrypted for Impact | T1486 | Ransomware encrypting user documents |
Defender detections need a tamper-protection backstop. The first certutil attempt was blocked, and the actor simply turned real-time protection off minutes later. Enable Tamper Protection and alert on Defender event 5001 as a high-severity signal.
certutil -urlcache to an external IP should be an alert on its own. The command line was in the Defender event, and the same pattern would show in process creation logging. Block or alert on certutil network use.
Unapproved file transfer clients and archivers are visible in user hives. The 7-Zip and FileZilla histories were enough to rebuild what was collected, where it was staged, and where it went. Application control on workstations would have stopped both installs.
Cached downloads preserve what the attacker pulled. CryptnetUrlCache kept both the URLs and the payload bytes, which made the ransomware recoverable without the actor’s server. Keep it in triage collections.
Compiled script ransomware hides its constants, not its logic. The key and IV were recoverable because they sat in the bytecode, obfuscated only by a short XOR. Offline recovery is realistic for this class of sample.
An insider with a foothold on a colleague’s workstation collected, exfiltrated and then encrypted data in about half an hour, and every step left a user-hive or event-log trace. The ransomware was beatable because its key material was embedded in the sample.