Conversation
The 25715 refactor (2970a6c) reworked handleOnLoadStart for the new flue layout and broke the config.SceneOffsets branch: 1. The final hop referenced an undeclared variable (remoteDebugParametersPtr), throwing "ReferenceError: 'remoteDebugParametersPtr' is not defined" on every AppletIndexContainer::OnLoadStart call. 2. The chain was split after an extra dereference of offset[2], so the legacy six-hop chain was walked incorrectly and landed on the wrong struct even once the name was fixed. Because the exception aborts onEnter, miniappScenePtr was never computed, writeInt(1101) never ran, and mini-programs never entered remote-debug mode. The debug server still started and reported the correct WMPF version, so the breakage only became visible when a mini-program was launched. Restore the legacy branch to a single six-hop pass, matching the pre-refactor implementation, and keep remoteDebugConfigPtr assigned so the code below works for both branches. The modern branch (MiniAppConfigStructOffsets) is unchanged. Verified on Windows x64 with WMPF 25510: previously every mini-program load threw the ReferenceError; now the hook reports "[hook] scene: 1256" and rewrites it to 1101.
recoverRemoteGuard assumed the scene and mode comparisons always share a base expression (baseKey === scene.baseKey). Legacy builds such as 25510 do not: the scene value sits behind a deep pointer chain while the remote-debug flag is read straight off the function's first argument. On 25510 the detected helper looks like: mov rsi, rcx mov rax, [rcx + 8] mov rcx, [rax + 0x5c0] mov rcx, [rcx + 0x10] cmp dword ptr [rcx + 0x1c8], 0x44d cmp byte ptr [rsi + 0x29], 1 so the scene comparison resolves to argumentIndex 0 with offsets [8, 1472, 16] while the mode comparison resolves to a different base with an empty chain. baseKey can never match, no candidate is produced, and detectLegacy fails with "expected one candidate, found 0". The former frida/version-detect.js had no such constraint: it located the scene by scanning opcode patterns, which is why auto-detect used to work on these builds. Legacy detection only needs the scene side (SceneOffsets is assembled from rootOffsets + sceneOffset), so fall back to an unpaired scene candidate instead of rejecting the build. A paired mode field is still preferred when present, so modern builds are unaffected, and the modern path now rejects a null mode offset so the fallback cannot emit a partial config. Recovered offsets on 25510 now match the hand-verified addresses.25510.json exactly.
|
Thank you for your contribution. However, the bug was already fixed in PR #286. Additionally, the auto-detect was already updated and tested, and I cannot see breaking changes in this PR regarding auto-detection methods. Technically, the auto-detect feature is for the later version that the repo does not have a corresponding config, that is, the previous builds are not take into the consideration of the scope that auto-detect feature would concern. Still, I really appreciate your time and contribution, thank you! |
|
Thanks for the explanation — you're right on both counts.
Closing this. Thanks for the quick review. |
Fix legacy WMPF support broken by the 25715 refactor
Summary
Two independent defects break legacy WMPF builds (anything configured with
SceneOffsets, e.g. 25510 / 25558 / 25560) on currentmain:frida/hook.js— everyAppletIndexContainer::OnLoadStartcall throwsReferenceError: 'remoteDebugParametersPtr' is not defined, so mini-programsnever enter remote-debug mode.
frida/autodetect/win32.js—--auto-detectrejects these builds withlegacy scene path: expected one candidate, found 0.Both were introduced by 2970a6c ("[version] new version 25715") and its
companion 9be09da ("[auto-detect] update auto-detect scripts"). That commit
also carries the note
TODO: auto-detect should be updated, and the latere73175d ("fix legacy wmpf version detection") addressed only
src/platform/win32.ts, which handles version detection rather than hookexecution or offset recovery.
Fix 1 —
frida/hook.js(handleOnLoadStart)The refactor split the previously single-pass legacy chain into two halves and
introduced two defects in the
config.SceneOffsetsbranch:Wrong variable name. The final hop read
remoteDebugParametersPtr, whichis never declared (only
miniappLaunchConfigPtr,remoteDebugConfigPtrandminiappScenePtrexist).Chain split at the wrong point. The pre-refactor implementation walked
all six offsets in one go:
The refactored version instead terminated
miniappLaunchConfigPtrafter anextra dereference of
offset[2]and continued fromoffset[3]. Thatinserts one dereference too many and lands on the wrong struct, so even
after fixing the variable name the scene read would still be wrong.
Restore the legacy branch to a single six-hop pass, keep
remoteDebugConfigPtrassigned so the code below stays defined for both branches, and document why
the legacy branch returns early (on these builds remote-debug mode is enabled
by the
args[1] |= 0x1write inpatchOnLoadStart, and there is noWebSocketURLStringOffset/RemoteDebugModeOffsetfield to patch).The modern branch (
MiniAppConfigStructOffsets, 25715+) is untouched.Fix 2 —
frida/autodetect/win32.js(recoverRemoteGuard)recoverRemoteGuardassumed the scene and mode comparisons always share a baseexpression (
item.baseKey === scene.baseKey). On these builds they do not: thescene value lives behind a deep pointer chain, while the remote-debug flag is
read straight off the function's first argument.
Disassembly of the detected helper on 25510 shows the mismatch directly:
The scene comparison resolves to
argumentIndex 0with offsets[8, 1472, 16], while the mode comparison resolves to a different base withan empty chain, so
baseKeycan never match and no candidate is produced.The former
frida/version-detect.jsdid not have this constraint: it locatedthe scene by scanning opcode patterns (
81 b9 ?? ?? ?? ?? 4d 04 00 00), whichis why auto-detect used to work on these builds. 9be09da replaced that with
structural recovery and lost the coverage.
Legacy detection only needs the scene side —
SceneOffsetsis assembled fromrootOffsets+sceneOffset— so fall back to an unpaired scene candidateinstead of rejecting the build. A matching mode field is still preferred when
one exists, so 25715 and other modern builds behave exactly as before. The
modern path additionally refuses a
nullmode offset so the fallback can neverproduce a partial modern config.
Why both paths can coexist
Both layouts describe the same pointer progression; they only differ in how
it is sliced:
Dispatching on
config.SceneOffsets(as the existing code already does) issufficient to support both.
Testing
Environment: Windows 11 x64, WeChat with WMPF 25510 (
flue.dllunder%appdata%\Tencent\xwechat\XPlugin\Plugins\RadiumWMPF\25510\extracted\runtime).Fix 1 —
npx ts-node src/index.ts --debug-fridaBefore:
After:
Zero
ReferenceError/TypeError/type: 'error'entries in the run.Fix 2 —
npx ts-node src/index.ts --auto-detect --debug-fridaBefore:
After:
The recovered offsets match the hand-verified
frida/config/win32/addresses.25510.jsonexactly:addresses.25510.jsonLoadStartHookOffset0x2ce46400x2ce4640CDPFilterHookOffset0x3974ff00x3974ff0SceneOffsets[64, 1536, 8, 1472, 16, 456][64, 1536, 8, 1472, 16, 456]Also confirmed on the same build that the change does not regress concurrency:
three mini-programs opened simultaneously hold three established connections to
the debug server on port 9421, and all three platforms' credentials are
captured in the same probe round.
Notes for the reviewer
frida/config/win32/addresses.25510.jsonwas alreadycorrect and is unchanged.
preferred; they are combined here because both are required for the same
build to work end to end.
--auto-detectnow works on this build, so theTODO: auto-detect should be updateditem from 2970a6c is at least partially addressed. Whether otherlegacy versions need further heuristic adjustments is unknown, as only 25510
was available for testing.