Multiplayer: two clients on one guest, joined by typed IP and by LAN browse, launched a 2-player game and played two turns in lockstep. 44,319 packets captured outside the guest, ZERO to any GameSpy port. Availability check fails open exactly as lane G2 read it; Join Manually is enabled with every gamespy.com name dead, falsifying G2's own caveat (a). The shipped MOTD is fetched live from kerberos-productions.com and tells players to host in LAN mode -- the developer's own statement of the same finding. Watchpoints: a new shim module arms DR0-DR3 from StrategyServer::ApplyAllTurnCommands. ModCount takes exactly 12 writes per End Turn (lane A2's prediction, confirmed twice, both predicted addresses exact); Frame takes exactly one, from BeginProcessTurn+0x2a, settling the ModCount-vs-Frame naming in A2's favour. The Player.Status writer between tail phase 31 and the autosave EXISTS and is StrategyNetworkClient::OnMessage+0xa15 -- correcting lane T2. Rule 19 control: the armed run reproduced the determinism oracle byte for byte. rcex: closed from the corpus alone. It is sixteen 4-bit per-player counters; nibble p is set to 1 on the turn the system enters player p's AFlags and ticked to 0 the next turn. 7/7 across two different games.
84 lines
7.4 KiB
JSON
84 lines
7.4 KiB
JSON
{
|
|
"entries": [
|
|
{
|
|
"name": "StrategyServer_ProcessTurn_ModCountBump",
|
|
"addr": "0x007dc6f0",
|
|
"convention": "site",
|
|
"prototype": "`inc [esi+0x8]` with esi = S -- the FIRST instruction of StrategyServer::ProcessTurn's body bumps ModCount. OBSERVED LIVE by a DR0 4-byte write watchpoint on S+0x8 (lane W2): the trap reports EIP 0x007dc6f3, i.e. the instruction after a 3-byte `inc`, on both measured End Turns. This is the ordering marker for the whole ModCount question -- every command-application bump precedes it and the OnAllCombatDone_Tail bump follows it",
|
|
"status": "verified",
|
|
"source": "findings/control-flow/watchpoints-modcount-status.md §2 (lane W2 2026-09-08, hardware watchpoint, 2 End Turns from ref-turn2.sav); address predicted by lane A2 alliance-mask-and-modcount.md §3 and by lane T turn-driver.md §0.1"
|
|
},
|
|
{
|
|
"name": "StrategyServer_OnAllCombatDone_Tail_ModCountBump",
|
|
"addr": "0x007d92ca",
|
|
"convention": "site",
|
|
"prototype": "ModCount bump at OnAllCombatDone_Tail + 0x2a (trap EIP 0x007d92cd). CORRECTS lane A2's prose, which called it 'OnAllCombatDone_Tail's first instruction': the address A2 predicted is exactly right, the offset is +0x2a and not +0. It is the LAST ModCount write of the turn and it lands AFTER StrategyServer::ProcessTurn has been entered, which refines A2's falsifier (c) -- 'hits after ProcessTurn is entered' is expected for this one site and only this one",
|
|
"status": "verified",
|
|
"source": "findings/control-flow/watchpoints-modcount-status.md §2 (lane W2 2026-09-08, hardware watchpoint)"
|
|
},
|
|
{
|
|
"name": "StrategyServer_BeginProcessTurn_FrameBump",
|
|
"addr": "0x007d990a",
|
|
"convention": "site",
|
|
"prototype": "The turn-number increment: `inc [reg+0xc]` with reg = S, at BeginProcessTurn + 0x2a (trap EIP 0x007d990d). OBSERVED LIVE on DR1 watching S+0xc: EXACTLY ONE write per End Turn, value 3 -> 4 on the second measured turn, against TWELVE writes to S+0x8 in the same window. THIS SETTLES THE NAMING DISPUTE: S+0x8 is a modification counter (lane A2's `StrategySim_off_ModCount`) and S+0xc is the frame/turn number (lane A2's `StrategySim_off_Frame`). addresses.json's `StrategyServer_off_ModCount` (0x8 in the raw frame == S+0xc) carries the name on the wrong word, and lane T's `StrategyServer_off_PhaseCounter` (S+0x8) is ModCount",
|
|
"status": "verified",
|
|
"source": "findings/control-flow/watchpoints-modcount-status.md §3 (lane W2 2026-09-08, hardware watchpoint)"
|
|
},
|
|
{
|
|
"name": "StrategyServer_ProcessTurnTail_PlayerStatusOne",
|
|
"addr": "0x007dcc8a",
|
|
"convention": "site",
|
|
"prototype": "Writes Player.Status(+0x164) = 1 for the LOCAL player only (not for every player), at StrategyServer::ProcessTurn + 0x5ca. Trap EIP 0x007dcc94, so the store is a 10-byte `mov dword ptr [reg+0x164], 1`. Confirms lane T2's static reading of the site AND narrows it: on a two-human-player save only player[0]'s Status moved; player[1]'s did not",
|
|
"status": "verified",
|
|
"source": "findings/control-flow/watchpoints-modcount-status.md §4 (lane W2 2026-09-08, DR2/DR3 on players[0]/[1] +0x164)"
|
|
},
|
|
{
|
|
"name": "StrategyNetworkClient_OnMessage_PlayerStatusFour",
|
|
"addr": "0x00785055",
|
|
"convention": "site",
|
|
"prototype": "THE MISSING WRITER OF Player.Status = 4 between tail phase 31 and the post-turn autosave. This address is the instruction AFTER the store (the trap address); the store itself ends here. It lives in StrategyNetworkClient::OnMessage at +0xa15 -- the End-Turn dispatcher -- and it fires AFTER StrategyServer::ProcessTurn has returned and BEFORE the autosave, writing 4 to the local player's Status over the 1 the ProcessTurn tail had just written. CORRECTS lane T2's treaty-turn-stamp.md §3, which read StrategyServer::MarkPlayerTurnEnded 0x00821a40 as 'THE ONLY WRITER OF Player.Status = 4 IN THE IMAGE' and concluded 'there is NO writer between tail phase 31 and the autosave'. There is, and it was watched happening twice on two consecutive End Turns",
|
|
"status": "verified",
|
|
"source": "findings/control-flow/watchpoints-modcount-status.md §4 (lane W2 2026-09-08, hardware watchpoint on ServerPlayer+0x164)"
|
|
},
|
|
{
|
|
"name": "StrategyServer_MarkPlayerTurnEnded_StatusStore",
|
|
"addr": "0x00821a75",
|
|
"convention": "site",
|
|
"prototype": "The `p->Status(+0x164) = 4` store inside StrategyServer::MarkPlayerTurnEnded, at +0x35 (trap EIP 0x00821a75, so the store ends here). Called ONCE PER PLAYER at the START of an End Turn, from OnPlayerEndTurn 0x007d9af0 (return address 0x007d9b2a, i.e. the call is at +0x35) -- confirming lane T2's caller list live. It runs BEFORE the pre-turn autosave's successor and before ApplyAllTurnCommands, which is why the `(Autosave EndTurn)` file still carries Status 0",
|
|
"status": "verified",
|
|
"source": "findings/control-flow/watchpoints-modcount-status.md §4 (lane W2 2026-09-08, hardware watchpoint)"
|
|
},
|
|
{
|
|
"name": "StrategySim_ModCountBump_unresolved_0086c3e6",
|
|
"addr": "0x0086c3e6",
|
|
"convention": "site",
|
|
"prototype": "A ModCount bump observed live but NOT attributable to a named function: the trap EIP is 0x0086c3e9 and the nearest preceding known symbol is ServerTradeManager_ProcessTurn 0x0086b300, +0x10e9 away -- far too far to claim containment. Its return address is 0x0088fce2 (inside StrategySim::ApplyTurnCommandBatch 0x0088f9b0), so it IS one of lane A2's twenty command handlers; only the handler's identity is open. Recorded as an address to disassemble rather than dropped",
|
|
"status": "mapped",
|
|
"source": "findings/control-flow/watchpoints-modcount-status.md §2 (lane W2 2026-09-08)"
|
|
},
|
|
{
|
|
"name": "StrategySim_ModCountBump_unresolved_00821a84",
|
|
"addr": "0x00821a84",
|
|
"convention": "site",
|
|
"prototype": "A ModCount bump observed live FOUR times per turn -- the single most frequent command handler on this save. Trap EIP 0x00821a87; nearest known symbol is StrategyServer_MarkPlayerTurnEnded 0x00821a40, but lane T2 measured that function at 60 bytes (ending 0x00821a7c), so this is the NEXT function and MarkPlayerTurnEnded's neighbour, not MarkPlayerTurnEnded. Return address 0x0088ffcb (StrategySim::ApplyTurnCommandBatch)",
|
|
"status": "mapped",
|
|
"source": "findings/control-flow/watchpoints-modcount-status.md §2 (lane W2 2026-09-08)"
|
|
},
|
|
{
|
|
"name": "StrategySim_ModCountBump_unresolved_0084946b",
|
|
"addr": "0x0084946b",
|
|
"convention": "site",
|
|
"prototype": "A ModCount bump observed live once per turn; trap EIP 0x0084946e, nearest known symbol ServerTradeManagerImpl_vslot11 0x00848570 at +0xefe (not containment). Return address 0x008900a4 (StrategySim::ApplyTurnCommandBatch)",
|
|
"status": "mapped",
|
|
"source": "findings/control-flow/watchpoints-modcount-status.md §2 (lane W2 2026-09-08)"
|
|
},
|
|
{
|
|
"name": "StrategySim_ModCountBump_unresolved_0088befe",
|
|
"addr": "0x0088befe",
|
|
"convention": "site",
|
|
"prototype": "A ModCount bump observed live once per turn; trap EIP 0x0088bf01, nearest known symbol StrategyServer_DestroyFleet 0x0088b980 at +0x581 -- plausibly inside it, but unproven. Return address 0x008902b4 (StrategySim::ApplyTurnCommandBatch), so it is a command handler called from the batch applier rather than an inlined site",
|
|
"status": "mapped",
|
|
"source": "findings/control-flow/watchpoints-modcount-status.md §2 (lane W2 2026-09-08)"
|
|
}
|
|
]
|
|
}
|