Frida-based hook toolkit for WeChat Android mini program cloud function traffic.
Project description
AndroidWXCloudFuncHook
android_wx_cloud_func_hook 是一个面向微信 Android 小程序云请求分析的 Frida Hook 库,重点覆盖 operateWXData、qbase_commapi、tcbapi_call_gateway 等链路,并支持请求/响应回调改写。
通过 frida-legacy-compat 实现 Frida 17 新版 API 兼容。
Star History
一、微信云函数 / 云网关简介与当前研究结论
这里说的“微信云函数”并不只指单独的云函数能力,而是把以下几类能力统称为云函数体系:
- 云网关
- 云托管
- 云函数
很多小程序请求并不是普通 HTTP 请求,而是基于微信云网关 / 云函数 / 云托管完成。此类请求直接用常规抓包软件通常抓不到,因为底层往往通过微信自己的 Mmtls 链路发包。根据当前研究,常见云请求大致有以下几种:
- 基于微信
Mmtls协议,通过OperateWxData接口发包- 在 PC 小程序逆向中也能看到该函数
- 该链路通过小程序进程与微信进程通信,最终走微信私有链路发包
- 基于
HTTP/2的鉴权模式- 常见于部分微信小程序
- 一般流程如下:
- 通过
OperateWxData的qbase_commit中的tcbapi_get_service_info获取加密参数与鉴权 Token - 使用获取到的 key 和 token 对请求体进行加密并压缩
- 当前观察到压缩常见为
snappy,数据格式一般为ProtoBuf或JSON - 服务端收到后再用 key 解密,当前常见解密算法为
AES-CBC
- 通过
- 不鉴权的
HTTP/2模式- 通常见于使用了微信云托管 / 云网关,但不在小程序内、而是独立网站的场景
- key 和 token 仍通过微信链路获取,后续请求的编解码流程与上面的鉴权模式类似
- 基于 HTTP 明文的请求
- 常见于部分其他 App 的微信云网关接入
- 这类请求往往需要带
Socks的抓包软件才能看到 - 请求头中通常会带上
x-wx-auth-code和x-wx-call-id - 这两个值由 URL 和 Body 共同计算,用于合法性校验
- 2025 年 8 月以后,腾讯云网关 SDK 更新后,明文请求已经越来越少
- 趋势逐渐转向 V3 加密版纯二进制实现
- V3 算法通常通过
tcbapi_get_service_info返回的key/kx/token完成请求编解码- 具体实现当前暂不开源
二、这个项目可以做什么
- 提供可直接调用的 PyPI 库,对小程序 Native 层主要链路进行 Frida Hook,抓取大部分 API 的请求和响应
- 通过修改
operateWXData接口,实现对云网关 V3 的降级,让其改走Mmtls层面的云网关,方便抓包 - 当
operateWXData中的get_service_info触发特定异常时,可自动降级为第一种Mmtls模式,便于进一步定位和抓包 - 相关辅助逻辑可直接参考 plugin.py
Features
- 自动枚举并附加微信主进程和
appbrand相关进程 - 自动补挂新出现的
com.tencent.mm:appbrandX进程 - 提供
RequestEvent/ResponseEvent事件模型 - 支持在 Python 回调中重写请求体和响应体
- 将
js/native.js作为包资源一起分发 - 内置
example.run(),安装后可直接导入运行示例
Installation
从 PyPI 安装:
pip install android-wx-cloud-func-hook
如果你使用 uv:
uv add android-wx-cloud-func-hook
Quick Start
安装后可以直接运行包内示例:
from android_wx_cloud_func_hook import example
example.run()
example代码的原理如下
def lower_gateway_and_match_v3_config(response: ResponseEvent) -> dict[str, Any] | None:
"""提取网关 V3 配置并将响应体置空,以便触发 JS 侧降级。"""
request = response.request
if response.api != "operateWXData" or request is None or "tcbapi_get_service_info" not in request.body:
return None
try:
response_dict = json.loads(response.body)
response_data = json.loads(response_dict["data"])
cloud_v3_response_config = json.loads(response_data["data"])
request_dict = json.loads(request.body)
cloud_v3_request_config = json.loads(request_dict["data"]["data"]["qbase_req"])
logger.info(cloud_v3_response_config)
logger.info(cloud_v3_request_config)
full_config = {**cloud_v3_response_config, **cloud_v3_request_config}
response.body = ""
return full_config
except Exception:
return None
def parse_gateway_http_request(request: RequestEvent | None) -> dict[str, Any] | None:
"""解析 `tcbapi_call_gateway` 对应的 qbase 请求体。"""
if request is None or request.api != "operateWXData":
return None
try:
body_dict = json.loads(request.body)
qbase_api_name = body_dict["data"]["data"].get("qbase_api_name")
if qbase_api_name != "tcbapi_call_gateway":
return None
qbase_request = body_dict["data"]["data"]["qbase_req"]
return json.loads(qbase_request)
except Exception:
return None
def parse_gateway_http_response(response: ResponseEvent) -> dict[str, dict[str, Any]] | None:
"""解析网关 HTTP 请求和响应,便于调试打印。"""
parsed_request = parse_gateway_http_request(response.request)
if parsed_request is None:
return None
try:
response_dict = json.loads(response.body)
response_data = json.loads(response_dict["data"])
return {
"request": parsed_request,
"response": response_data,
}
except Exception:
return None
如果你想自定义回调,并重写请求和响应,可以直接使用核心类:
from android_wx_cloud_func_hook import AndroidWXCloudFuncHook, RequestEvent, ResponseEvent
def on_request(request: RequestEvent) -> None:
if "tcbapi_call_gateway" in request.body:
print("matched request", request.id)
request.body = "重写请求体"
def on_response(response: ResponseEvent) -> None:
if response.request is not None:
print("matched response", response.id, response.request.api)
response.body = "重写响应体,可以实现重写降级后的网关 HTTP 响应以及 WxJS 中的其他 API 响应"
with AndroidWXCloudFuncHook() as hook:
processes = hook.get_wechat_processes()
if not processes:
raise SystemExit("没有找到微信相关进程")
hook.start_hook(
processes,
on_request=on_request,
on_response=on_response,
auto_attach_new_processes=True,
)
input("Hook 已启动,按回车退出...")
Package API
AndroidWXCloudFuncHook
- 负责枚举进程、附加 Frida、自动补挂新进程、接收消息并回传补丁
RequestEvent
id: 请求唯一 IDapi: JSAPI 名称,可改写body: 当前请求体,可改写meta_body: 原始请求体快照,只读语义
ResponseEvent
id: 响应唯一 IDbody: 当前响应体,可改写meta_body: 原始响应体快照,只读语义request: 匹配到的请求对象,没有命中时为None
example.run()
- 包内自带的最小可运行示例
- 适合快速验证设备、Frida 环境和微信小程序链路是否已命中
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file android_wx_cloud_func_hook-1.0.0.tar.gz.
File metadata
- Download URL: android_wx_cloud_func_hook-1.0.0.tar.gz
- Upload date:
- Size: 17.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a43dc0a987705b7d849fc998e64e7d6dd03fe3ac3aa0804d699b7ead34f8940c
|
|
| MD5 |
9bba66c360489695f758834ab9c61ca1
|
|
| BLAKE2b-256 |
44fac2eca517ffba22a459530b1182270ef755261ef71042c1456bd11f325ead
|
Provenance
The following attestation bundles were made for android_wx_cloud_func_hook-1.0.0.tar.gz:
Publisher:
release.yml on RYF5584/AndroidWXCloudFuncHook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
android_wx_cloud_func_hook-1.0.0.tar.gz -
Subject digest:
a43dc0a987705b7d849fc998e64e7d6dd03fe3ac3aa0804d699b7ead34f8940c - Sigstore transparency entry: 1642584622
- Sigstore integration time:
-
Permalink:
RYF5584/AndroidWXCloudFuncHook@153bbe7785673f1149f2c42e31380b2d2d107b1f -
Branch / Tag:
refs/tags/V1.0.0 - Owner: https://github.com/RYF5584
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@153bbe7785673f1149f2c42e31380b2d2d107b1f -
Trigger Event:
push
-
Statement type:
File details
Details for the file android_wx_cloud_func_hook-1.0.0-py3-none-any.whl.
File metadata
- Download URL: android_wx_cloud_func_hook-1.0.0-py3-none-any.whl
- Upload date:
- Size: 15.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
45706a13565c3e99ffc259187c41eff525fdda1ef34160dc58bfdd3f88916189
|
|
| MD5 |
2923a74450d63d8944c5b7d57265ccf5
|
|
| BLAKE2b-256 |
ef56654ecc4f10fc7989e581ac50f7ae2d42fb9f9866df741fcd75851d44ae3e
|
Provenance
The following attestation bundles were made for android_wx_cloud_func_hook-1.0.0-py3-none-any.whl:
Publisher:
release.yml on RYF5584/AndroidWXCloudFuncHook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
android_wx_cloud_func_hook-1.0.0-py3-none-any.whl -
Subject digest:
45706a13565c3e99ffc259187c41eff525fdda1ef34160dc58bfdd3f88916189 - Sigstore transparency entry: 1642584783
- Sigstore integration time:
-
Permalink:
RYF5584/AndroidWXCloudFuncHook@153bbe7785673f1149f2c42e31380b2d2d107b1f -
Branch / Tag:
refs/tags/V1.0.0 - Owner: https://github.com/RYF5584
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@153bbe7785673f1149f2c42e31380b2d2d107b1f -
Trigger Event:
push
-
Statement type: