probe: run-4 connect-state lifecycle spread (8 targets)

Expands to 8 entry probes across the connect-state lifecycle (ctor, controller
accessor, four vtable steps) to distinguish entered-but-stalled from never-entered.
Result: ctor fires x4, everything else 0 — subsystem created but dormant.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-07-02 18:03:50 -07:00
parent c1d1f03ec8
commit 493b9e0573
+17 -6
View File
@@ -186,13 +186,20 @@ struct Target {
/// - `OnlineStatus.deser` (+0x278a4d0): confirms our pushed OnlineStatusEvent still
/// arrives during the test (control signal).
const TARGETS: &[Target] = &[
Target { module: b"\0", rva: 0x2861910, label: "nucleusConnectREST", main_exe: true },
Target { module: b"\0", rva: 0x5078370, label: "nucleusConnectTrusted", main_exe: true },
Target { module: b"\0", rva: 0x507d660, label: "connectState.tick", main_exe: true },
Target { module: b"\0", rva: 0x278a4d0, label: "OnlineStatus.deser", main_exe: true },
// Run 4: settle "connect state entered-but-stalled" vs "never entered". If the ctor
// fires but nothing else, the connect states are created at init but never used; if
// GetByIdx / any vtable step fires, the online subsystem is iterating them.
Target { module: b"\0", rva: 0x5078d20, label: "connectState.ctor", main_exe: true },
Target { module: b"\0", rva: 0x4f46570, label: "ctrl.GetConnState", main_exe: true },
Target { module: b"\0", rva: 0x507cd60, label: "connState.m_a8", main_exe: true },
Target { module: b"\0", rva: 0x507cf90, label: "connState.m_b0", main_exe: true },
Target { module: b"\0", rva: 0x507d660, label: "connState.tick_b8", main_exe: true },
Target { module: b"\0", rva: 0x507d760, label: "connState.m_c0", main_exe: true },
Target { module: b"\0", rva: 0x2861910, label: "nucleusConnectREST", main_exe: true },
Target { module: b"\0", rva: 0x278a4d0, label: "OnlineStatus.deser", main_exe: true },
];
const N: usize = 4; // must equal TARGETS.len()
const N: usize = 8; // must equal TARGETS.len()
static ADDRS: [AtomicUsize; N] = [const { AtomicUsize::new(0) }; N];
static mut ORIG: [[u8; 14]; N] = [[0u8; 14]; N];
@@ -202,7 +209,7 @@ static CALLS: [AtomicUsize; N] = [const { AtomicUsize::new(0) }; N];
const LOG_CAP: usize = 24;
type ProbeFn = unsafe extern "system" fn(usize, usize, usize, usize) -> usize;
const PROBE_FNS: [ProbeFn; N] = [p0, p1, p2, p3];
const PROBE_FNS: [ProbeFn; N] = [p0, p1, p2, p3, p4, p5, p6, p7];
unsafe fn write_jmp(addr: *mut u8, dest: u64) {
let mut old: u32 = 0;
@@ -253,6 +260,10 @@ unsafe extern "system" fn p0(a: usize, b: usize, c: usize, d: usize) -> usize {
unsafe extern "system" fn p1(a: usize, b: usize, c: usize, d: usize) -> usize { generic(1, a, b, c, d) }
unsafe extern "system" fn p2(a: usize, b: usize, c: usize, d: usize) -> usize { generic(2, a, b, c, d) }
unsafe extern "system" fn p3(a: usize, b: usize, c: usize, d: usize) -> usize { generic(3, a, b, c, d) }
unsafe extern "system" fn p4(a: usize, b: usize, c: usize, d: usize) -> usize { generic(4, a, b, c, d) }
unsafe extern "system" fn p5(a: usize, b: usize, c: usize, d: usize) -> usize { generic(5, a, b, c, d) }
unsafe extern "system" fn p6(a: usize, b: usize, c: usize, d: usize) -> usize { generic(6, a, b, c, d) }
unsafe extern "system" fn p7(a: usize, b: usize, c: usize, d: usize) -> usize { generic(7, a, b, c, d) }
/// Spawn a background thread that waits for anadius64.dll to load, then installs
/// all probes. anadius may not be present when our DllMain runs, so we defer