“ 不自量力地还手,直至死方休。——《山丘》 ”
01
—
环境版本
环境:
电脑,Windows 10 专业版 23H2
软件:
Yakit,v1.4.1-0606
微信,Windows 3.9.10.19
WeChatOpenDevTools-Python,0.3.2
02
—
操作步骤
1、Yakit抓包请求响应加密
363K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2&6j5h3E0D9j5h3&6Y4i4K6u0W2j5$3!0E0i4K6u0r3

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

03
—
解密函数
3、控制台输出调试语句日志,跟进secretRequestData

4、跟调用堆栈

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

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

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

04
—
配置JsRpc
8、取消断点,注入JsRpc环境,注意用WeChat小程序版本
183K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6B7P5r3S2U0P5X3S2D9i4K6u0r3d9Y4y4d9M7r3y4Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4u0W2M7$3!0#2j5$3g2K6i4K6u0r3g2$3g2o6K9r3q4@1i4K6g2X3c8r3g2$3i4K6u0W2K9Y4x3`.

9、开启JsRpc,连接通信
var demo = new Hlclient("ws://192.168.14.158:12080/ws?group=zzz");

10、注册解密方法,param参数即传入的密文,调用h(param, t, 0, n)返回明文即可
demo.regAction("decrypt", function (resolve,param) {
console.log("param值是" + param)
var data = h(param, t, 0, n)
resolve(data);
})

11、测试JsRpc正常,得到明文
486K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8U0p5&6x3W2)9J5k6e0p5$3z5q4)9J5k6e0p5@1i4K6u0W2x3e0f1^5i4K6y4m8x3e0t1H3z5o6m8Q4x3V1k6Y4L8#2)9K6c8X3N6J5L8%4g2H3i4K6y4p5P5Y4A6*7i4K6t1$3j5h3#2H3i4K6y4n7j5h3y4@1K9h3!0F1i4K6y4p5k6r3g2U0M7Y4W2H3N6q4)9J5y4X3q4E0M7q4)9K6b7Y4m8S2M7X3q4E0i4K6y4p5x3h3k6S2P5s2S2^5

05
—
Yakit 热加载
12、以/api/v1/datasheet/get_configs为例,请求的requestData和响应的responseData是密文

13、目前需求是查看明文数据包不做修改,所以使用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¶m={{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¶m={{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)
}

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