CHAPTER 5 · THE TWIST
THE INVISIBLE DIALOG
Chapter 4 ended with a machine that was provably waiting and demonstrably not asleep. The resolution was not another fix. It was a single injected Enter key, a one-bit X-ray of video memory, and a confession: the world's most heavily instrumented Windows install had been running without the install CD.
Where things stood
By the small hours of 16 July the census (chapter 4) had said everything it could say: eight processes, seventy-one threads, every one of them Waiting, zero runnable, kernel stacks paged out, the CPU parked in mddosem's emulation of the idle loop — while the guest went on making protected-mode stack transitions at about eighteen a second, so the machine was demonstrably not asleep. Three real emulation fixes had landed in a single night — the interrupt shadow, the parked timer (both chapter 6), and the PIIX3 status latch (chapter 3) — and capture 11 proved the wall had survived all three. The screen showed what every capture since the campaign began had recorded: the same byte-identical 5,757-byte black PNG — a frame that would go on recurring for four days. Nothing was crashing. Nothing was lost. Everything, everywhere, was waiting.
One keystroke
Capture 15 was the experiment nobody had thought to run. Wait for setup to reach the fully out-swapped terminal state — threads parked, kernel stacks paged out, the census signature stable — then inject a single Enter key through the emulator's control pipe. Setup immediately became active. The journal draws the conclusion in one line: the wait was a modal dialog, not a lost kernel wakeup.
A modal dialog is Windows at its most patient. The thread that owns it stops doing work and sits in a message loop, blocked until input arrives; from the kernel's side that is an ordinary event wait, indistinguishable from a deadlock — because the producer that will eventually signal it is a human being with a keyboard. The census had been perfectly correct: everyone really was waiting, and nothing really was going to wake them. It had misread only one thing — who they were waiting for. Three weeks of kernel-level forensics, ended by a keystroke.
The X-ray
But a dialog for whom? The screen was black — had been black in every capture that reached the wall. The way past that contradiction was to stop trusting the screen. In the VGA's 16-colour graphics modes the picture does not live in a tidy byte-per-pixel framebuffer: it lives in four parallel bit-planes, overlaid at the same guest addresses starting at A000:0000, one bit of each pixel in each plane. Whatever the emulator's renderer was putting on the visible display, the plane memory underneath could still be read directly — and reconstructed at one bit per pixel into a crude black-and-white image of whatever had been drawn, whether or not it was being shown.
The decode was startling. Behind the darkness, GUI Setup was alive and mid-conversation:
a wizard page titled Your Product Key, the CD-case illustration with
Microsoft's generic placeholder sticker art, the instruction about the 25-character key on
the yellow sticker, < Back and Next > buttons — and, overlapping
it, an error box reading “The CD Key you entered is not valid.” The frame
recreated below dates from the following evening, after the campaign had learned where to
look, and it portrays the second of the two prompts this chapter uncovers — but it
is the definitive portrait of the wall: Setup politely asking questions into a void.
Naming the dialog
A keystroke proves a dialog; forensics demands to know which. Two
instrument repairs made that possible. mddosem's time-travel debugger can arm instruction
triggers — watchpoints that fire when execution reaches a chosen
CS:EIP — but one interpreter path compared only the low sixteen bits of the
instruction pointer, so a trigger set on an NT kernel-mode address like
0x804xxxxx could never match. The fix,
Cpu::instruction_offset(), selects the full 32-bit EIP whenever the code segment
is 32-bit and the truncated IP only for genuine 16-bit segments. And trigger logging was made
side-effect-free: on firing, it records the registers and the stack frame, and where a frame
slot points at readable UTF-16 it logs an escaped preview of the string — all through a debug
translation path that sets no Accessed bits and pollutes no TLB. A debugger should read guest
memory the way a bus analyser would: without leaving fingerprints.
Static cross-references in the exact SP4 build of setupapi.dll suggested
three code paths that could raise a blocking dialog — a failed-verification prompt, a
copy-error dialog, and a missing-media prompt. Triggers went on all three; capture 18 ran to
the wall. Exactly one fired: 001B:778CF4FB, the internal
implementation of the exported SetupPromptForDiskW. The other two never executed.
Capture 19 then logged the live call frame — the decisive evidence of the whole campaign:
capture 19 · time-machine log trigger @ 001B:778CF4FB · setupapi!SetupPromptForDiskW (internal) DiskName "Service Pack 4 CD" PathToSource "D:\I386" FileSought "NT5INF.CAT" TagFile NULL DiskPromptStyle 0x105
Field values as recorded in the capture-19 trigger log; layout stylised. The journal's reading of the frame: a normal request for missing installation media — not a signature failure, not a copy error. Windows was not crashing, not corrupting, not deadlocked. It wanted its CD back, and it had asked in the politest way it knew: a dialog box, on a screen nobody could see.
The confession
Why was there no CD? Because the harness had removed it. The original install driver,
drive-install.sh, always attached the SP4 ISO to the emulated CD-ROM drive. The
capture harness — rebuilt for the forensic campaign, with its hash-verified fresh disk copies
and its census watchers — did not: captures 03 through 19 omitted
--cdrom. The guest was never stuck. It was waiting, politely and
invisibly, for a disc that nobody had inserted, on hardware that faithfully reported an empty
drive.
The sting in the tail: both post-PIIX3 “verdict” runs were among the CD-less captures. The journal is unsparing — those runs “cannot decide whether the CPU/PIT/IDE fixes complete setup; Windows correctly prompted for the absent source.” Every retest since capture 03 had been answering a different question from the one being asked.
- 16 JUL · CAPTURE 11The wall survives fix three With the reviewed PIIX3 latch landed, setup still parks: black screen, three threads Waiting, kernel stacks out-swapped.
- 16 JUL · CAPTURE 15One Enter key Injected at the fully out-swapped state — setup wakes instantly. A modal dialog, not a lost kernel wakeup.
- 16 JUL · INSTRUMENTSThe triggers learn 32-bit addresses
Full-EIP trigger matching (
Cpu::instruction_offset()) and side-effect-free frame logging with escaped UTF-16 previews. - 16 JUL · CAPTURE 18One trigger fires Of three candidate dialog paths in setupapi.dll, only 001B:778CF4FB executes — SetupPromptForDiskW's internal implementation.
- 16 JUL · CAPTURE 19The frame decoded DiskName “Service Pack 4 CD” · PathToSource D:\I386 · FileSought NT5INF.CAT · DiskPromptStyle 0x105 — routine missing media.
- 16 JUL · THE AUDITThe confession drive-install.sh had always attached the ISO; captures 03–19 omitted --cdrom. Windows was right all along.
- 16 JUL · CAPTURE 20The CD returns Straight past the three-thread wall; setup grows from four threads to eight; real progress — until a second invisible page.
The second invisible page
Capture 20 restored the ISO as drive D:. Setup went straight past the old three-thread
wall, grew from four threads to eight, and alternated between installer work and
service-control traffic — the first real forward progress at this phase in weeks. Then it
parked again, black again: nine processes now, eighty-four threads, setup holding six Waiting
threads with their stacks paged out. Capture 21 repeated the keystroke experiment, and once
again a single Enter made setup runnable. Another invisible modal — but this time the media
prompt stayed silent: SetupPromptForDiskW's fire count was zero.
So the probes went generic: triggers on USER32's own dialog machinery, the functions any
Windows program must call to put a box on screen. MessageBoxW at
0x77E36AB3 fired, called from a return address inside
syssetup.dll at 0x67015998; static disassembly just
above the call site showed it raising message resource 0xEA76 with
the error icon, and the SP4 message table decodes 0xEA76 to “The CD Key you entered is
not valid.” EndDialog fired once as the injected Enter dismissed the error.
The guest was sitting at an invisible Product Key wizard page — the page the X-ray above
portrays — rejecting what it had been given and asking, unseen, for another try.
Entering a secret politely
The next problem was not emulation at all. Someone had to type a product key into a
machine that could not display its own key page — through tooling that logs everything it
touches. The existing remote-keystroke command, ctl key TEXT, put its payload in
the client's process command line and shell history: unusable for a secret. So the emulator
gained ctl key --stdin, which reads the keystroke text from standard input and
feeds the unchanged keyboard-injection path. Arthur typed the key into a hidden PowerShell
secure prompt (Read-Host -AsSecureString) that piped it through stdin and zeroed
the temporary buffer. The journal states the boundary plainly: the agent “must not read,
print, log, or transmit the key.” No key value entered a command line, a log file, a
journal, or a chat transcript — and none enters this site.
The correction of 18 July
The first key-entry experiment was recorded as a success — setup, the journal initially
said, rejected one candidate key and accepted another. Two days later that claim was formally
withdrawn, and the withdrawal is worth telling with the same respect as the fixes. Three
faults were found in the procedure, none in the emulator. The ctl scancodes
command parsed digit-only tokens as decimal, so chord sequences written as hex had never sent
the intended keystrokes — explicit 0x prefixes were required. The SP4 Product
Key dialog turned out to own five edit controls, each limited to five characters and
auto-advancing to the next — so the procedure's deliberate Tab between groups had silently
skipped every other field. And the key the successful QEMU reference install had actually
used matched neither key that had been tried. An experiment whose input procedure is broken
proves nothing, and the journal says so in plain terms: claim withdrawn.
Capture 26 redid the entry properly — a cold boot of a hash-verified copy of the capture-24 disk, the QEMU-proven key, explicit-hex chords, five clean five-character groups, no hyphens, no Tabs, Enter. Instrument honesty is a running theme of this story: the same campaign that retracted its own census (chapter 4) also retracted its own success.
With the CD in the drive and the key entered by a procedure proven against the oracle, native setup ran its full course for the first time — chapter 7 tells that night minute by minute. But none of this motion was free. For the machine to reach these dialogs at all — and to survive what came after them — four instruction-level truths had to hold, and chapter 6 is about those.
Sources for this chapter — the 15 July master journal for the boot-to-desktop
goal (section: “the terminal wait was an invisible media prompt”) and the 16–18 July entries,
bug ledger MDD-BUG-KILN-00004; the capture archive (captures 11–26), including
capture-24/a000-1bpp.png and the byte-identical 5,757-byte wall frame; the commit record for
the time-machine trigger fixes and ctl key --stdin. Full evidence table:
how we know, under mddosem.