The podium rig stops rather than lie about its heap

The no-elevation page-heap trick the rig was built on is dead on Windows
26200, and it fails silently - which is the dangerous half. Measured at the
create-process event: the write lands (dd $peb+68 reads back 02001000), then
one g later ntdll has zeroed NtGlobalFlag again, so no verifier.dll, no page
heap, and a run that looks exactly like an instrumented one right down to the
clean exits. It was verified working on 26100; the machine has moved on.

A six-pod driven run this morning went the whole way - all six placed on the
stand, full teardown, six clean exits - before the cdb logs turned out to
carry no page-heap line at all. That result proves nothing and is recorded as
such.

So feeder.ps1 now aborts when it cannot confirm page heap on every pod, and
prints the elevated gflags recipe instead. -AllowNoPageHeap runs anyway and
says in the log that a clean result is not evidence of absence, because the
one thing this rig must never do is bank a negative it did not earn.

This makes gflags the only route to a heap instrument on this machine, which
costs nothing that was not already true: full page heap was already the
discriminating test for the overrun reading of the dumps, and light page heap
could never have caught an overrun anyway.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-08-14 10:06:06 -05:00
co-authored by Claude Opus 5
parent 3b5eb992f1
commit 021ad36951
2 changed files with 71 additions and 1 deletions
+37
View File
@@ -96,6 +96,34 @@ anything before it could. The feeder is a close copy of the proven
two-pod-test, but treat its first run as a shakedown: if the pods never reach
`WaitingForLaunch`, the mesh/egg path is the thing to debug, not the crash.
## The PEB page-heap trick is DEAD on Windows 26200 (2026-08-14)
The no-elevation trick this rig was built on no longer works, and it fails
**silently** — which is the dangerous part, because an uninstrumented run
looks exactly like an instrumented one right down to the clean exits.
Measured at the create-process event on build 26200:
dd $peb+68 L1 -> 00000000 (before)
ed $peb+68 02001000
dd $peb+68 L1 -> 02001000 (the write lands)
g
dd $peb+68 L1 -> 00000000 (ntdll zeroed it during init)
So `NtGlobalFlag` is re-initialised after `-xe cpr` and page heap never
turns on: no `verifier.dll`, no `Page heap: pid ...` line. It was verified
working on 26100; the machine has since moved to 26200.
`feeder.ps1` now ABORTS when it cannot confirm page heap on every pod,
rather than running an uninstrumented test and reporting a clean result.
`-AllowNoPageHeap` runs anyway and says loudly in the log that the result
is not evidence of absence.
**This makes gflags (and therefore an elevated shell) the only route to a
heap instrument on this machine** — see "Full page heap" below. That is no
loss: full page heap was already the discriminating test for the overrun
reading of the dumps, and light page heap could never have caught it.
## Gotchas this rig has already paid for
- **`dist\environ.ini` ships `RP412PODIUM=0`.** The podium is OFF by default,
@@ -186,6 +214,15 @@ cannot press buttons (only the four analog channels), so it cannot fire a
weapon or pop a chute; if deaths turn out to matter, they need a hazardous
map or a different mechanism, not a fiercer script.
**2026-08-14, six pods, driven, podium ON — NO PAGE HEAP, and that is the
finding.** All six raced (scores 741..1010, so they really drove), all six
placed (`WinnersCircle: 6 placed on 8 spots`), full teardown, six clean
exits, no exception. Then the cdb logs turned out to carry no
`Page heap: pid` line at all: the PEB trick had stopped working (see above).
**Do not record this as a negative** — it is an uninstrumented run, which is
weaker even than the earlier light-page-heap ones. Its only value is as one
more sample of the crash failing to happen on its own.
### What the two clean runs change
Light page heap traps a **double free** at the second free. It does NOT trap
+34 -1
View File
@@ -21,7 +21,11 @@ param(
# cdbrun.txt enables LIGHT page heap itself via the PEB.
# cdbrun-gflags.txt does not - use it when `gflags -i rpl4opt.exe +hpa`
# has already been set (full page heap), so only one mechanism is in play.
[string]$CdbScript = 'cdbrun.txt'
[string]$CdbScript = 'cdbrun.txt',
# Run even when page heap could not be confirmed. Off by default: an
# uninstrumented clean run looks exactly like an instrumented one in the
# summary, and banking it as a negative is how a rig starts lying.
[switch]$AllowNoPageHeap
)
$ErrorActionPreference = 'Stop'
Add-Type -Path $MungaNetDll
@@ -173,6 +177,35 @@ foreach ($k in $keys) {
}
}
#
# Stop rather than bank a negative that proves nothing.
#
# The PEB trick this rig was built on FAILS SILENTLY on Windows 26200: the
# write lands at the create-process event - read it back there and it is
# 0x02001000 - and ntdll zeroes NtGlobalFlag again during its own init, so
# every pod runs on an ordinary heap. It worked on 26100, which is what the
# README verified against. Nothing in the run's output would tell you: the
# races look identical and the pods exit clean either way.
#
$instrumented = @($keys | Where-Object { $podInfo[$_].pid }).Count
if ($instrumented -lt $PodCount) {
Log "PAGE HEAP NOT CONFIRMED on $($PodCount - $instrumented) of $PodCount pods"
if (-not $AllowNoPageHeap) {
Log 'ABORTING - a clean result without the heap instrument proves nothing.'
Log 'Full page heap needs an ELEVATED shell:'
Log " & 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\gflags.exe' -i rpl4opt.exe +hpa"
Log " ...feeder.ps1 -PodCount 4 -CdbScript cdbrun-gflags.txt"
Log " & '...\gflags.exe' -i rpl4opt.exe -hpa # always put it back"
Log 'Or pass -AllowNoPageHeap to run uninstrumented on purpose.'
Get-Process rpl4opt -ErrorAction SilentlyContinue | Stop-Process -Force -Confirm:$false -ErrorAction SilentlyContinue
Get-Process cdb -ErrorAction SilentlyContinue | Stop-Process -Force -Confirm:$false -ErrorAction SilentlyContinue
exit 1
}
Log 'CONTINUING UNINSTRUMENTED (-AllowNoPageHeap) - this run can only catch'
Log 'a crash that faults on its own, as the fatal night did. A clean result'
Log 'is NOT evidence of absence and must not be recorded as one.'
}
#-----------------------------------------------------------------
# Break detection: cdb writes the marker the instant it traps, well
# before a race would time out.