Crash Dump Analysis
Ett till pajat fönster
This challenge is about reversing a Windows kernel crash dump instead of a normal binary. The goal is not just to scrape strings, but to understand why the machine crashed, what the custom driver was doing right before the bugcheck, and where the real flag survived in the saved execution state.
undut{w0w_7h15_w45_4nn0y1n6}
What The Challenge Is About
Ett till pajat fönster gives us a small Windows crash dump and expects us to
recover the flag from the wreckage. The interesting part is that the challenge is built
around a fake-looking trail of readable strings and a real solution hidden in the crash-time
CPU context.
In practice, that means the task sits between forensics and
reversing: we inspect dump metadata, recover driver-related strings, identify
the custom code path, and then reason about the saved registers to reconstruct the secret.
another, year, and pajat fönster, but those are
just arguments passed into the crash path. The actual flag is stored in transformed form.
What We Started With
The challenge file was a Windows crash dump named 030426-4281-01.dmp.
The first useful check was simply identifying the file type:
file 030426-4281-01.dmp
030426-4281-01.dmp: MS Windows 64bit crash dump, version 15.19041, 4 processors, small dump
That tells us this is not an application log or a memory snapshot in a custom format. It is a real Windows minidump / kernel crash dump artifact.
Even before deeper analysis, the dump already gives us some useful constraints:
- It is a 64-bit Windows crash dump.
- The OS build is
15.19041. - The crash happened on a system with
4 processors. - The dump is small, so we should expect selective state instead of full RAM.
High-Level Plan
- Extract obvious strings from the dump and look for challenge-specific artifacts.
- Identify whether the crash involved a custom driver or ordinary Windows code.
- Find any hardcoded strings, registry paths, or suspicious bugcheck arguments.
- Disassemble the relevant driver code path to understand what happens before the crash.
- Recover the saved CPU context from the dump and inspect registers at crash time.
- Decode the transformed bytes into the real flag.
Step 1: Pull Strings from the Dump
The fastest first move is always broad string extraction:
strings -el 030426-4281-01.dmp | head -n 200
strings -a 030426-4281-01.dmp | rg -i "flag|Driver1|fonster"
This immediately revealed several important artifacts:
\??\C:\Users\Administrator\Desktop\Driver1.sys\Device\HarddiskVolume2\Users\Administrator\Desktop\Driver1.sys\Registry\Machine\Software\fonsterflag\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services\Driver1\Driver\Driver1
That is already enough to say the crash involves a custom kernel driver named
Driver1.sys, and that the driver is connected to a registry key
HKLM\Software\fonster with a value named flag.
The combination of a desktop-loaded driver path, a service entry under
ControlSet001\Services, and a dedicated driver object name is strong evidence
that this challenge was intentionally staged around a custom kernel component rather than a
random Windows crash.
Step 2: Check the Obvious Strings Near the Registry Key
Near that registry string block, the dump also contained these plain ASCII fragments:
another
year
pajat fönster
In the raw dump, the last string is not even stored as one nice clean token. It appears as
split fragments like pajat f and nster, which is a good reminder
that string output alone can be misleading when it crosses memory boundaries.
These looked promising at first, but they turned out to be bait. That is a common CTF pattern: put readable words near the real logic so people stop at the first plausible guess.
Step 3: Read the Crash Header
We parsed the dump header directly to recover the bugcheck code:
BugCheckCode = 0x29
0x29 is SECURITY_SYSTEM. That matters because the suspicious
strings were not just passive leftovers in memory. The custom driver was deliberately
causing a system bugcheck and passing controlled arguments into it.
Step 4: Find the Driver Strings and Code References
The key move was locating the actual code references to the suspicious strings instead of just reading them as raw text.
Searching for RIP-relative references showed this:
0x4b0da -> 0x4bacc (\Registry\Machine\Software\fonster)
0x4b0ec -> 0x4bb1c (flag)
0x4b188 -> 0x4bb2c (another)
0x4b194 -> 0x4bb3c (year)
0x4b1a0 -> 0x4bb4c (pajat fönster)
That told us one function was actively using all five strings together. So the next step was to disassemble that function.
Step 5: Disassemble the Critical Function
The important part of the function looked like this:
lea rdx, [rip+0x9eb] ; "\Registry\Machine\Software\fonster"
lea rcx, [rsp+0x60]
call ...
lea rdx, [rip+0xa29] ; "flag"
lea rcx, [rsp+0x70]
call ...
...
lea r8, [rip+0x99d] ; "another"
mov ecx, 0x29
lea r9, [rip+0x9a1] ; "year"
mov [rsp+0x20], r8
lea rdx, [rip+0x9a5] ; "pajat fönster"
call ...
The structure is important:
- First it resolves the registry path and the value name
flag. - Then it reads registry data into a stack buffer.
- After that it loads
another,year, andpajat fönster. - Finally it calls into the bugcheck path using those strings as arguments.
This means the readable words were bugcheck arguments, not the flag itself.
Step 6: Recover the Saved Crash Context
A minidump often stores a Windows CONTEXT record. We searched for a valid x64
context block and found one whose stack pointer matched the active crash frame.
Important recovered registers:
ContextFlags = 0x10000f
Rcx = 0x29
Rdx = 0xfffff80219131ab0
R8 = 0xfffff80219131a90
R9 = 0xfffff80219131aa0
Rsp = 0xffffb183ccd34758
Rbp = 0xffffb183ccd34860
Rip = 0xfffff802154071b0
The values in RCX, RDX, R8, and R9
align with the bugcheck call arguments we had already identified. That confirmed we were
looking at the real crash-time register state.
Step 7: Inspect the Saved XMM Registers
The driver contained vector instructions just before the string table. That suggested the flag data might not stay in ordinary general-purpose registers.
From the saved context we extracted:
XMM14 = 8a91043d8b84177888a05720ceca3f3f
XMM15 = cbca3f7c91915031ce915635ffff6048
Concatenated together, that gives a 32-byte blob:
8a91043d8b84177888a05720ceca3f3fcbca3f7c91915031ce915635ffff6048
That is exactly the right size for a short transformed flag string.
Step 8: Infer the Decode Method
Since the known flag format starts with undut{, we can use that as a crib.
XOR the first six bytes of the blob with undut{:
cipher: 8a 91 04 3d 8b 84
plain : 75 6e 64 75 74 7b
key : ff ff 60 48 ff ff
That partial key immediately suggests a repeating XOR key. Testing the repeating 8-byte key
pattern ff ff 60 48 ff ff 60 48 produces a coherent plaintext.
Step 9: Decode the Blob
Applying the repeating XOR key gives:
undut{w0w_7h15_w45_4nn0y1n6}
This is the real flag. It also explains why the plain strings were wrong: the challenge was designed so that a shallow strings-only analysis would produce believable but incorrect answers.
Why the Earlier Guesses Failed
What looked tempting
anotheryearpajat fönster
Those are human-readable and close to flag in memory.
Why they were wrong
- They were passed into the bugcheck path as arguments.
- They were not read back as one contiguous flag string.
- The actual secret survived in vector register state, not as plain text.
Takeaways for Learners
- Start with strings, but do not stop there.
- Always ask: which code references this string?
- If a dump involves a custom driver, inspect crash-time register state.
- Saved
CONTEXTstructures can be more valuable than heap or stack strings. - Vector registers matter. Modern code may keep transformed secrets in
XMM/YMM. - Known flag prefixes are powerful when testing XOR or simple substitution schemes.
Minimal Reproduction Workflow
1. file 030426-4281-01.dmp
2. strings -el 030426-4281-01.dmp | rg "Driver1|fonster|flag"
3. locate code references to those strings
4. disassemble the referencing function
5. recover the saved x64 CONTEXT from the dump
6. extract XMM14 and XMM15
7. concatenate the 32-byte blob
8. derive repeating XOR key from "undut{"
9. decode -> undut{w0w_7h15_w45_4nn0y1n6}