New Version Adaptation
Please follow the guidelines to find the offset values if you wish to support a new WMPF version on your own.
Also, PR welcome!
Prerequisites
Windows
You need to locate the folder which contains WeChatAppEx.exe, for newer versions, it will be something like
%appdata%\Tencent\xwechat\xplugin\Plugins\RadiumWMPF\19339\extracted\runtime
where the 19339 indicates the version number.
Use IDA to open flue.dll inside this folder (for much older versions, open WeChatAppEx.exe)
Linux
Depending on your distribution's packaging policy, the path may vary.
readlink /proc/$(pidof WeChatAppEx | awk '{print $1}')/exe
Analyze WeChatAppEx using IDA.
Warning
Do not continue with any actions until the indicator in the lower-left corner of IDA displays AU: idle.
LoadStartHookOffset
Linux (>=25665), Windows (>=18891)
Please search OnLoadStart (camel-case) and find the x-ref function that references a string contains applet_index_container.cc. Possibly sub_18xxxxxxx+E6

If you cannot find something similar to the picture below, and you can only see something like .rdata:000000018AB7A3E4 db 4Fh ; O , this means the loading is not complete, please wait.

To show the Pseudocode like below, press F5

If you found sub_1825B50C0 (as shown in the above example) matches the pattern in the picture above, then you can fill in
{
"Version": xxx,
"LoadStartHookOffset": "0x25B50C0",
}
Scroll down to the bottom of the pseudocode of this function and you will find something like
(version 19339 example)
if ( (_BYTE)a2 )
result = sub_182B02350(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 1376LL), *(_QWORD *)(*(_QWORD *)(a1 + 80) + 56LL));
if ( ((unsigned __int64)v19 ^ v27) != _security_cookie )
{
((void (*)(void))unk_184AD7B40)();
__debugbreak();
}
return result;
We are interested in functions that are executed only when a2 is true, so please go to sub_182B02350.
You will find something like
result = *(_QWORD *)(a1 + 8);
if ( *(_DWORD *)(*(_QWORD *)(*(_QWORD *)(result + 1312) + 16LL) + 456LL) != 1101 && *(_BYTE *)(a1 + 41) != 1 )
goto LABEL_32;
v34 = 0xAAAAAAAAAAAAAAAAuLL;
ws:__localhost:9421_1 = 0;
v30 = 0;
v31 = 0;
memset(v33, 0, sizeof(v33));
v32 = v33;
ws:__localhost:9421 = (char *)&ws:__localhost:9421_1;
The magic number 1101 is what we need. We need to tell the script how to access 1101 through multiple layers of pointer offsets and dereferencing. Please refer to the code in hook.js:
const miniappConfigPtr = a1
.add(sceneOffsets[0])
.readPointer()
.add(sceneOffsets[1])
.readPointer();
const miniappScenePtr = miniappConfigPtr
.add(sceneOffsets[2])
.readPointer()
.add(sceneOffsets[3])
.readPointer()
.add(sceneOffsets[4])
.readPointer()
.add(sceneOffsets[5]);
Based on the pattern of the first argument passed to sub_182B02350, the result, and the if statement block, overall (*(_QWORD *)(a1 + 56) + 1376LL) -> result = *(_QWORD *)(a1 + 8); -> (*(_QWORD *)(*(_QWORD *)(result + 1312) + 16LL) + 456LL), the answer is:
"SceneOffsets": [56, 1376, 8, 1312, 16, 456]
Linux (>=14910), Windows (>=14199) [Old Version]
Locate the AppletIndexContainer::OnLoadStart function by searching [Perf] AppletIndexContainer::OnLoadStart
in strings.

Hit x, the only x-ref function address is the offset.

How to find SceneOffsets? Please refer to the section above.
Note
Also, check the struct offset in these two marked functions.
These offsets are being used in the onLoadStartHook function in frida/hook.js

CDPFilterHookOffset
Locate the filter by searching SendToClientFilter in
strings.

Hit x, go to the only function that references this string.

The hook target function sub_1824839E0 is the very first
function called in the x-refed function sub_181DB82D0.

"CDPFilterHookOffset": "0x24839E0",
Save the config
Save addresses.xxxxx.json in frida/config with the params you found above where xxxxx is the new version
{
"Version": xxxxx,
"LoadStartHookOffset": "0x25B5DD0",
"CDPFilterHookOffset": "0x301B3C0",
"SceneOffsets": [1376, 1312, 456]
}
(Legacy) ResourceCachePolicyHookOffset
We don't need this in the latest version
Not sure if this function affects the sources shown in the devtools, keep hooking this just in case.
Locate the resource cache policy function by searching
WAPCAdapterAppIndex.js in strings, select the second
search result.

Hit x, the only function that references this string
is the target function.
