“ 以为只要努力就一定能成功,其实是一种傲慢。——《强风吹拂》E22 ”
01
—
环境版本
环境:
电脑,Windows 11 专业版 23H2
软件:
Yakit,v1.4.1-0606
微信,Windows 3.9.10.19
微信开发者工具,1.06.2503290
WeChatOpenDevTools-Python,0.3.2
02
—
操作步骤
1、Yakit抓包,请求响应加密
5beK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6&6j5h3E0D9j5h3&6Y4i4K6u0W2j5$3!0E0i4K6u0r3

2、WechatOpenDevTools-Python.exe开启控制台
394K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6v1j5i4k6W2L8r3g2&6f1f1q4c8i4K6u0r3g2$3g2o6K9r3q4@1e0%4m8W2L8V1c8W2N6W2c8G2L8$3I4K6i4K6u0V1f1s2W2@1K9r3!0F1

3、调试模式已禁用

4、unveilr.exe反编译__APP__.wxapkg

03
—
请求分析
5、微信开发者工具导入,控制台跟调试语句

6、a是解密函数,f是随机16位动态密钥,o.data.data是密文,a(o.data.data, f)获取明文

7、搜索f=,定位到t.getKey(16),获取动态密钥的地方
8、进入函数,在对应的源码中,将返回值r写死,将密钥固定为0000000000000000

9、回到第五步,f始终为0000000000000000,也能正常解密

04
—
配置JsRpc
10、导出a解密函数,f密钥到全局
globalThis.a = a;
globalThis.f = f;

11、取消所有断点,注入JsRpc环境
65dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6B7P5r3S2U0P5X3S2D9i4K6u0r3d9Y4y4d9M7r3y4Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4u0W2M7$3!0#2j5$3g2K6i4K6u0r3g2$3g2o6K9r3q4@1i4K6g2X3c8r3g2$3i4K6u0W2K9Y4x3`.

12、连接通信
var demo = new Hlclient("ws://192.168.14.159:12080/ws?group=zzz");

13、注册解密函数
demo.regAction("decrypt", function (resolve,param) {
console.log("param值是" + param);
f = "0000000000000000";
var data = a(param, f);
resolve(data);
})

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

15、开启热加载功能,显示明文流量
hijackSaveHTTPFlow = func(flow /* *yakit.HTTPFlow */, modify /* func(modified *yakit.HTTPFlow) */, drop/* func() */) {
req = str.Unquote(flow.Request)~
rsp = str.Unquote(flow.Response)~
// ================================
// 解密 data
// ================================
if str.Contains(req, "\"data\":\"") {
parts := str.Split(req, "\"data\":\"")
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.159: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)
}
}
}
// ================================
// 解密 data
// ================================
if str.Contains(rsp, "\"data\":\"") {
parts := str.Split(rsp, "\"data\":\"")
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.159: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)
}

[培训]科锐逆向工程师培训第53期2025年7月8日开班!