AfterHours
Long after the front desk closes and the pool lights dim, the resort's back-office machines keep humming. A forensics writeup covering WMI repository artifact analysis, hidden custom class discovery, and embedded .NET payload extraction.
Challenge Brief
Someone — or something — has been logging in during the small hours, well after the night-shift technician has gone home. Nothing obvious shows up in Startup, Scheduled Tasks, or the registry Run keys. Whatever's keeping itself alive is hiding somewhere quieter, tucked away in a corner of the system most tools don't think to check.
The challenge provides five system artifacts with a passphrase (Aft3rH0ursAtt4chm3ntP4ss) for the attachment archive. The goal: parse the artifacts for hidden custom configuration data, locate the malicious class, extract its embedded payload, decode it, and recover the flag.
System Artifacts
The provided files and their roles once identified:
| File | Size | Role |
|---|---|---|
| INDEX.BTR | 4.8 MB | WMI repository B-tree index |
| MAPPING1.MAP | 77 KB | WMI repository mapping file (namespace 1) |
| MAPPING2.MAP | 77 KB | WMI repository mapping file (namespace 2) |
| MAPPING3.MAP | 77 KB | WMI repository mapping file (namespace 3) |
| OBJECTS.DATA | 23 MB | WMI repository — class definitions & instances |
%windir%\System32\wbem\Repository\ on a live Windows system. This is the on-disk store that holds all WMI class definitions, instances, and provider registrations. It's exactly the kind of location that autoruns tools don't scan by default.Initial Reconnaissance
Starting with file and xxd on each artifact, the magic bytes tell the story:
hexdump — INDEX.BTR
00000000: ccac 0000 4d00 0000 0000 0000 0000 0000 ....M...........
00000010: 2600 0000 0000 0000 0000 0000 0000 0000 &...............hexdump — MAPPING1.MAP
00000000: cdab 0000 5754 0000 7c01 0000 7b01 0000 ....WT..|...{...hexdump — OBJECTS.DATA
00000000: 2018 0b6f 7001 0000 5900 0000 0000 0000 ..op...Y.......
000001a0: 1900 0080 005f 5f53 7973 7465 6d43 6c61 .....__SystemCla
000001b0: 7373 0000 6162 7374 7261 6374 000c 0000 ss..abstract....The 0xCCAC magic on INDEX.BTR and 0xCDAB on the MAP files are the known signatures of the WMI repository format. OBJECTS.DATA immediately reveals .NET/WMI metadata: __SystemClass, abstract, and references to __Win32Provider, __EventFilter, __EventConsumer, and __FilterToConsumerBinding.
Why WMI persistence evades autoruns
WMI (Windows Management Instrumentation) persistence is a well-known but under-detected technique. While some autoruns tools now check for WMI event subscriptions (the __EventFilter + __EventConsumer + __FilterToConsumerBinding triad), they rarely scan the raw repository binary for custom class definitions with embedded data. That's exactly what this challenge exploits.
Finding the Malicious Class
With 366,000+ strings in OBJECTS.DATA, the search needs to be targeted. The standard approach: look for non-standard class names that don't match known Windows WMI prefixes (Win32_, MSFT_, CIM_, __, etc.) and search for encoded payloads (long base64 or hex strings).
strings + grep — searching for base64 payloads
# Extract all base64-like strings (30+ chars, not hex)
python3 -c "
import re
data = open('OBJECTS.DATA','rb').read()
# ... extract ASCII strings, filter for base64 pattern
b64 = re.compile(r'^[A-Za-z0-9+/=]{30,}$')
# Found at offset 0x8d576:
# 7VZPbFRFGP/edillgUrBAJWAjy0l5d/r0hYDpIWW7gLF/...
"
# Examine context around the hit
python3 -c "
data = open('OBJECTS.DATA','rb').read()
ctx = data[0x8d576-300:0x8d576]
# Found: Win32_HardwareTelemetry ... ConfigData
"The context immediately before the base64 string reveals a custom WMI class:
raw context — bytes before 0x8d576
...WDMClassesOfDriver
...MS_SystemInformation
...C:\Windows\System32\drivers\en-US\mssmbios.sys.mui[MofResource]
...
Win32_HardwareTelemetry
ConfigData
[08 00 00 00] [00 00 00 00] [00 00 00 00] [00 00 11 00]
7VZPbFRFGP/edillgUrBAJWAjy0l5d/r0hYDpIWW7gLF/oMtxRAT...ConfigData property. This is the "hidden custom configuration data" the challenge refers to — invisible to autoruns because it's not a standard persistence vector.Extracting & Decoding the Payload
The ConfigData property contains a 2,212-character base64 string. Decoding it produces 1,658 bytes of raw binary — but the result doesn't match any known file magic, ruling out a direct PE or ZIP.
payload decoding pipeline
import base64, zlib
b64_str = "7VZPbFRFGP/edillgUrBAJWAjy0l5d/r0hYDpIWW7gLF/oMt..."
decoded = base64.b64decode(b64_str)
# Standard zlib fails — header check error
zlib.decompress(decoded)
# → Error -3: incorrect header check
# Raw DEFLATE (no zlib header) succeeds!
pe = zlib.decompress(decoded, -15)
# → 4096 bytes, starts with MZ
print(pe[:4])
# → b'MZ\x90\x00'The data is compressed with raw DEFLATE (no zlib wrapper). Decompressing yields a 4 KB Windows PE executable — a .NET assembly.
Assembly analysis
Running strings on the decompressed binary reveals its structure:
strings — decompressed PE (updates.exe)
# .NET metadata
*BSJB
v4.0.30319
<Module>
updates.exe
AfterHours # ← the malicious class name
# Referenced types
mscorlib
System
System.Diagnostics
ProcessStartInfo
Process
Console
# Embedded command (UTF-16LE)
cmd.exe
/c net user patch VEhNe1A0dGNoX29wM25lZF90aDNfQmFjS2QwMHJ9 /add
# Guard clause
Execution halted: Environment mismatch.updates.exe, class AfterHours) spawns cmd.exe to create a hidden user account named patch with a password that is actually a base64-encoded string. This is the "after hours" backdoor — a rogue user account being silently provisioned.Flag Recovery
The final step: base64-decode the password value from the net user command.
base64 decode — final step
import base64
encoded = "VEhNe1A0dGNoX29wM25lZF90aDNfQmFjS2QwMHJ9"
flag = base64.b64decode(encoded).decode()
print(flag)
# → THM{P4tch_op3ned_th3_BacKd00r}Attack Chain Summary
WMI Repository Infiltration
Attacker writes a custom class Win32_HardwareTelemetry directly into the WMI repository binary (OBJECTS.DATA), masquerading as a legitimate hardware telemetry class.
Payload Embedding
A .NET assembly is raw-DEFLATE-compressed and base64-encoded, then stored in the class's ConfigData property — invisible to standard autoruns scanners.
After-Hours Execution
The embedded assembly (updates.exe / class AfterHours) runs net user patch <base64> /add, silently creating a backdoor account during off-hours.
Flag Concealment
The account password VEhNe1A0dGNoX29wM25lZF90aDNfQmFjS2QwMHJ9 is itself a base64-encoded flag, adding one more layer of obfuscation.
Key takeaways
WMI repository tampering is a powerful persistence technique because the repository is a binary blob that most forensic tools don't parse line-by-line. Custom classes with embedded payloads are essentially invisible to standard autoruns scans. Defenders should:
Monitor the WMI repository for unauthorized class creation, diff repository snapshots against known-good baselines, and use specialized tools like SharpWMI or manual binary analysis when investigating suspicious persistence. The Win32_HardwareTelemetry class name is designed to blend in with legitimate hardware-related WMI classes — always verify class provenance against Microsoft's documentation.