https://mp.weixin.qq.com/s/-oTirKKgNCJSRQa9U5QlHw

环境准备

环境:

  • 电脑,Windows 10 专业版 23H2

  • 软件:

​ Yakit,v1.4.1-0606

​ 微信,Windows 3.9.10.19

​ WeChatOpenDevTools-Python,0.3.2

操作步骤

1、yakit抓取请求数据包,发现全流量加密:

https://www.yaklang.com/

图片

2、注入WechatOpenDevTools-Python打开控制台

图片

解密函数

1、控制台输出调试语句日志,跟进secretRequestData

图片

2、继续跟踪调用堆栈

图片

3、搜索decrypt关键字定位到解密函数

图片

4、e是密文,t是密钥,n是undefined,不用n也可以,h(e, t, 0)得到明文

图片

5、小程序使用globalThis将h解密,t密钥,n导出到全局

globalThis.h = h;

globalThis.t = t;

globalThis.n = n;

图片

配置JSRpc

1、取消断点,注入JsRpc环境,注意用WeChat小程序版本

https://github.com/jxhczhl/JsRpc/blob/main/resouces/WeChat_Dev.js

图片

2、开启RPC,连接通信:

https://github.com/jxhczhl/JsRpc/blob/main/resouces/WeChat_Dev.js

图片

3、注册解密方法,param参数即传入的密文,调用h(param, t, 0, n)返回明文即可

图片

4、测试RPC,成功得到明文

http://192.168.14.158:12080/go?group=zzz&action=decrypt&param=1faxxx

图片

yakit热加载

1、以/api/v1/datasheet/get_configs为例,请求的requestData和响应的responseData是密文

图片

2、目前需求是查看明文数据包不做修改,所以使用hijackSaveHTTPFlow在发送请求之后,数据包存入数据库之前调用JsRpc获取明文替换requestData和responseData,这样所有数据包就显示为明文且不影响请求

hijackSaveHTTPFlow = func(flow /* *yakit.HTTPFlow */, modify /* func(modified *yakit.HTTPFlow) */, drop/* func() */) {
req = str.Unquote(flow.Request)~
rsp = str.Unquote(flow.Response)~
// ================================
// 解密 requestData
// ================================
if str.Contains(req, "\"requestData\":\"") {
parts := str.Split(req, "\"requestData\":\"")
if len(parts) >= 2 {
encPart := parts[1]
encValue := str.Split(encPart, "\"")[0]
// 发送解密请求
rsp2, req2 = poc.HTTP(`GET /go?group=zzz&action=decrypt&param={{params(paramStr)}} HTTP/1.1
Host: 192.168.14.158:12080
User-Agent: Mozilla/5.0
Accept: */*
Connection: close
`, poc.params({
"paramStr": encValue,
}))~
rspIns2 = poc.ParseBytesToHTTPResponse(rsp2)~
body2 = io.ReadAll(rspIns2.Body)~
// 提取明文
parts2 := str.Split(body2, "\"data\":\"")
if len(parts2) >= 2 {
dataPart2 := parts2[1]
dataEnd := str.Split(dataPart2, "\",\"group\"")[0]
plainData := str.ReplaceAll(dataEnd, "\\", "")
req = str.ReplaceAll(req, encValue, plainData)
}
}
}
// ================================
// 解密 responseData
// ================================
if str.Contains(rsp, "\"responseData\":\"") {
parts := str.Split(rsp, "\"responseData\":\"")
if len(parts) >= 2 {
encPart := parts[1]
encValue := str.Split(encPart, "\"")[0]
// 发送解密请求
rsp2, req2 = poc.HTTP(`GET /go?group=zzz&action=decrypt&param={{params(paramStr)}} HTTP/1.1
Host: 192.168.14.158:12080
User-Agent: Mozilla/5.0
Accept: */*
Connection: close
`, poc.params({
"paramStr": encValue,
}))~
rspIns2 = poc.ParseBytesToHTTPResponse(rsp2)~
body2 = io.ReadAll(rspIns2.Body)~
// 提取明文
parts2 := str.Split(body2, "\"data\":\"")
if len(parts2) >= 2 {
dataPart2 := parts2[1]
dataEnd := str.Split(dataPart2, "\",\"group\"")[0]
plainData := str.ReplaceAll(dataEnd, "\\", "")
rsp = str.ReplaceAll(rsp, encValue, plainData)
}
}
}
// 写回并保存入库
flow.Request = str.Quote(req)
flow.Response = str.Quote(rsp)
flow.AddTag("decrypted")
modify(flow)
}

图片

3、测试第一步发送验证码请求,得到明文请求响应

图片