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:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user