Overview
| Field | Value |
|---|---|
| Category | Easy |
| Points | 846 |
| Author | Moritz |
| Binary | PE32+ x64 Windows GUI (.SCR screensaver) |
| Zip Password | flare |
| Flag | CMO{frogt4s7ic_r3vers1ng} |
Recon
The binary is a Windows screensaver (.SCR). Running file on it:
PE32+ executable (GUI) x86-64, for MS Windows, 6 sections
PDB path leaked in the binary hints at the author’s environment:
C:\Users\flare\wow\a\crackmesone\screensaver\i\love\it\thank\you\xoxoxox.pdb
Key imports that shape our analysis direction:
- ADVAPI32:
RegCreateKeyExW,RegSetValueExW,RegOpenKeyExW,RegQueryValueExW- registry I/O - USER32:
DialogBoxParamW,GetDlgItemTextW,SetDlgItemTextW- dialog with text input - KERNEL32:
GetComputerNameW,GetWindowsDirectoryW,FindFirstFileW,GetTickCount,IsDebuggerPresent- system info + anti-analysis - CRT:
rand,srand,wcschr,wcsncmp,wcstoul- string manipulation + RNG
Junk Code
The binary is heavily padded with dead code that does nothing meaningful. Nearly every function contains repeated sequences of:
GetDC(0)/CreateCompatibleDC/CreateCompatibleBitmap/DeleteObject/DeleteDC/ReleaseDC- creates and immediately destroys GDI objectsGetTickCount() % 100 + 5/SetLastError(...)- sets error codes to random-ish valuesGetDesktopWindow()/IsWindow(...)- checks the desktop existsGetWindowsDirectoryW/FindFirstFileW("*.dll")/FindClose- enumerates DLLs for no reasonGetComputerNameW/GetSystemMetrics- reads system info into unused variables- Counting loops:
do { ++counter; --n; } while (n);with result discarded
All of this is noise. The actual logic is a small fraction of each function.
Program Flow
WinMain (0x140002360)
Parses command-line arguments following standard screensaver conventions:
| Flag | Mode | Behavior |
|---|---|---|
/c or -c |
Configure | Shows a dialog box via DialogBoxParamW with DialogFunc |
/p or -p |
Preview | Minimal GDI setup, does nothing interesting |
/s or -s |
Screensaver | Full-screen screensaver with bouncing bitmap animation |
The configure mode (/c) is where the flag check lives.
DialogFunc (0x140001f30)
Handles the configuration dialog:
- WM_INITDIALOG: Calls
sub_140001AE0(String)to load existing text, then populates dialog item 1001 with the result. - WM_COMMAND (OK button): Reads user input from the dialog, writes it to registry key
HKCU\Software\FLRSCRNSVR\Text, and writes a hardcoded encrypted blob toHKCU\Software\FLRSCRNSVR\Quak.
sub_140001AE0 - Validation Logic (0x140001AE0)
This is the core check, called on dialog init and during screensaver rendering:
- Opens
HKCU\Software\FLRSCRNSVRand reads theTextvalue (user’s previous input). - If the registry key doesn’t exist, defaults to
"Crackmes.one". - Length gate: If
strlen(input) != 25, skip validation entirely. - Copies input to a working buffer, calls
sub_140001300to transform it. - Calls
sub_140001890to load the target (from registryQuakvalue, or hardcoded fallbackaQjat0x1400064d0). - Compares transformed input against target character by character.
- If match: sets global
byte_140008898 = 1(success flag, changes screensaver rendering).
The Transform - sub_140001300 (0x140001300)
Three operations applied sequentially to the 25-character input (wchar_t):
Step 1: Substitution Cipher
Two 66-character alphabets define a monoalphabetic substitution:
Source: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789}_{=-
Dest: -={_}9876543210ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba
Each character is looked up in Source and replaced with the character at the same index in Dest. Characters not in the alphabet are left unchanged.
Step 2: XOR with Key + Index
A repeating key derived from embedded DWORD constants:
|
|
This spells FLARERALF (9 characters, a palindrome of “FLARE”). The XOR operation is:
input[j] ^= key[j % 9] + j
Step 3: String Reversal
The transformed string is reversed in place by swapping characters from both ends toward the middle.
The Target
The hardcoded target blob aQj at 0x1400064d0 (also written to registry as Quak):
3c 00 51 00 6a 00 09 00 02 00 07 00 25 00 03 00
30 00 08 00 04 00 29 00 68 00 24 00 01 00 24 00
18 00 6b 00 77 00 0f 00 70 00 36 00 02 00 0e 00
0b 00 00 00
As 25 wchar_t values:
[0x3c, 0x51, 0x6a, 0x09, 0x02, 0x07, 0x25, 0x03, 0x30, 0x08,
0x04, 0x29, 0x68, 0x24, 0x01, 0x24, 0x18, 0x6b, 0x77, 0x0f,
0x70, 0x36, 0x02, 0x0e, 0x0b]
Solve
Invert the three transform steps in reverse order:
|
|
Flag
CMO{frogt4s7ic_r3vers1ng}