diff --git a/frida/auto.js b/frida/auto.js index a4eb84a..5c6734f 100644 --- a/frida/auto.js +++ b/frida/auto.js @@ -1,19 +1,19 @@ -let module; -Process.enumerateModules().forEach(function (m) { - if (m.name.toLowerCase().includes("wechat.dylib")) { - module = m; - } -}); -console.log("module:", module.name, module.base, module.size); +var moduleName = "wechat.dylib"; +var module = Process.findModuleByName(moduleName); +var baseAddr = module.base; +if (!baseAddr) { + console.error("[!] 找不到 WeChat 模块基址,请检查进程名。"); +} +console.log("[+] WeChat base address: " + baseAddr); function scanPatterns() { myPatterns.forEach((item, index) => { const { name, pattern } = item; - Memory.scan(module.base, module.size, pattern, { + Memory.scan(baseAddr, module.size, pattern, { onMatch: function(address, size) { // 计算相对偏移 (RVA) - const offset = address.sub(module.base); + const offset = address.sub(baseAddr); console.log(`"${name}": "${offset}", 绝对地址: ${address}`); }, onError: function(reason) { diff --git a/frida/file.js b/frida/file.js index 98bfb23..7efafa4 100644 --- a/frida/file.js +++ b/frida/file.js @@ -1,16 +1,11 @@ // 1. 获取微信主模块的基地址 -var baseAddr = ptr(0); -Process.enumerateModules().forEach(function (m) { - if (m.name.toLowerCase().includes("wechat.dylib")) { - baseAddr = m.base; - } -}); - -if (baseAddr === 0x0) { - console.log("wechat.dylib not found"); +var moduleName = "wechat.dylib"; +var baseAddr = Process.findModuleByName(moduleName).base; +if (!baseAddr) { + console.error("[!] 找不到 WeChat 模块基址,请检查进程名。"); } +console.log("[+] WeChat base address: " + baseAddr); -console.log("baseAddr: " + baseAddr); // -------------------------基础函数分区------------------------- function toVarint(n) { @@ -108,15 +103,15 @@ function generateBytes(n) { // 双方公共使用的地址 var triggerX1Payload; var triggerX0; -var req2bufEnterAddr = baseAddr.add(0x3806b30); -var req2bufExitAddr = baseAddr.add(0x3807C48); +var req2bufEnterAddr = baseAddr.add(`0x3806b30`); +var req2bufExitAddr = baseAddr.add(0x3807C44); var sendFuncAddr = baseAddr.add(0x498D2E0); var insertMsgAddr = ptr(0); var sendMsgType = ""; // 图片消息全局变量 var imageCallbackFuncAddr = baseAddr.add(0x251AD40); -var imgProtobufAddr = imageCallbackFuncAddr.add(0x54); +var imgProtobufAddr = imageCallbackFuncAddr.add(0x50); var patchImgProtobufFunc1 = imageCallbackFuncAddr.add(0x10); var patchImgProtobufFunc1Byte; var patchImgProtobufFunc2 = imageCallbackFuncAddr.add(0x30); @@ -126,7 +121,7 @@ var imgProtobufDeleteAddrByte; // 视频消息全局变量 var videoCallbackFuncAddr = baseAddr.add(0x2587FD0); -var videoProtobufAddr = videoCallbackFuncAddr.add(0x54); +var videoProtobufAddr = videoCallbackFuncAddr.add(0x50); var patchVideoProtobufFunc1 = videoCallbackFuncAddr.add(0x10); var patchVideoProtobufFunc1Byte; var patchVideoProtobufFunc2 = videoCallbackFuncAddr.add(0x30); @@ -139,6 +134,11 @@ var cndOnCompleteAddr = baseAddr.add(0x37C40E0); var imgMessageCallbackFunc1 = baseAddr.add(0x89159F0); var videoMessageCallbackFunc1 = baseAddr.add(0x8918790); +var uploadGetCallbackWrapperAddr = baseAddr.add(0x4aa2324); +var uploadGetCallbackWrapperFuncAddr = baseAddr.add(0x37C392C); +var uploadOnCompleteAddr = baseAddr.add(0x4AA2920); +var uploadOnCompleteFuncAddr = baseAddr.add(0x37C4B10); + var uploadImageX1 = ptr(0); var imgCgiAddr = ptr(0); var sendImgMessageAddr = ptr(0); @@ -767,7 +767,11 @@ function attachProto() { })); }, }); +} +setImmediate(attachProto); + +function attachVideoProto() { Interceptor.attach(videoProtobufAddr, { onEnter: function (args) { @@ -899,7 +903,7 @@ function attachProto() { }); } -setImmediate(attachProto); +setImmediate(attachVideoProto()); function triggerUploadImg(receiver, md5, imagePath) { @@ -1242,7 +1246,7 @@ function patchCdnOnComplete() { setImmediate(patchCdnOnComplete) function attachGetCallbackFromWrapper() { - Interceptor.attach(baseAddr.add(0x4aa2324), { + Interceptor.attach(uploadGetCallbackWrapperAddr, { onEnter: function (args) { const tmpFileId = this.context.x1.readPointer().readUtf8String(); const imageFileId = imageIdAddr.readUtf8String(); @@ -1252,13 +1256,13 @@ function attachGetCallbackFromWrapper() { return } - uploadCallback.add(0x10).writePointer(baseAddr.add(0x37C392C)); + uploadCallback.add(0x10).writePointer(uploadGetCallbackWrapperFuncAddr); this.context.x8 = uploadCallback; console.log("[+] GetCallbackFromWrapper x8: " + this.context.x8); } }) - Interceptor.attach(baseAddr.add(0x4AA2920), { + Interceptor.attach(uploadOnCompleteAddr, { onEnter: function (args) { const tmpFileId = this.context.x1.readPointer().readUtf8String(); const imageFileId = imageIdAddr.readUtf8String(); @@ -1268,7 +1272,7 @@ function attachGetCallbackFromWrapper() { return } - uploadCallback.add(0x30).writePointer(baseAddr.add(0x37C4B10)); + uploadCallback.add(0x30).writePointer(uploadOnCompleteFuncAddr); this.context.x8 = uploadCallback; console.log("[+] OnComplete x8: " + this.context.x8); } diff --git a/frida/init.js b/frida/init.js index bca1eab..024f8f8 100644 --- a/frida/init.js +++ b/frida/init.js @@ -1,7 +1,7 @@ -var baseAddr = ptr(0); -Process.enumerateModules().forEach(function (m) { - if (m.name.toLowerCase().includes("wechat.dylib")) { - baseAddr = m.base; - } -}); -console.log("Base address of wechat.dylib: " + baseAddr); \ No newline at end of file +// 1. 获取微信主模块的基地址 +var moduleName = "wechat.dylib"; +var baseAddr = Process.findModuleByName(moduleName).base; +if (!baseAddr) { + console.error("[!] 找不到 WeChat 模块基址,请检查进程名。"); +} +console.log("[+] WeChat base address: " + baseAddr); diff --git a/frida/receiver.js b/frida/receiver.js index e074258..2dd848c 100644 --- a/frida/receiver.js +++ b/frida/receiver.js @@ -1,19 +1,14 @@ -var baseAddr = ptr(0); -Process.enumerateModules().forEach(function (m) { - if (m.name.toLowerCase().includes("wechat.dylib")) { - baseAddr = m.base; - } -}); - -if (baseAddr === 0x0) { - console.log("wechat.dylib not found"); +var moduleName = "wechat.dylib"; +var baseAddr = Process.findModuleByName(moduleName).base; +if (!baseAddr) { + console.error("[!] 找不到 WeChat 模块基址,请检查进程名。"); } -console.log("baseAddr: " + baseAddr); +console.log("[+] WeChat base address: " + baseAddr); -var buf2RespAddr = baseAddr.add(0x382c1b4) -var downloadImagAddr = baseAddr.add(0x4bf8608) // image_download -var downloadFileAddr = baseAddr.add(0x4B97384) // c2c_download -var downloadVideoAddr = baseAddr.add(0x4bb9100) // hdvideo_streaming +var buf2RespAddr = baseAddr.add(0x382C1A8) +var downloadImagAddr = baseAddr.add(0x4BF85F0) // image_download +var downloadFileAddr = baseAddr.add(0x4B97378) // c2c_download +var downloadVideoAddr = baseAddr.add(0x4bb90fc) // hdvideo_streaming var startDownloadMedia = baseAddr.add(0x4AD54D4) var downloadGlobalX0; @@ -40,12 +35,12 @@ setImmediate(setupDownloadFileDynamic) function setReceiver() { Interceptor.attach(buf2RespAddr, { onEnter: function (args) { - const currentPtr = this.context.x1; + const currentPtr = this.context.x20; if (currentPtr.add(0).readU8() !== 0x08) { return } - const x2 = this.context.x2.toInt32(); + const x2 = this.context.x0.toInt32(); const fields = getProtobufRawBytes(currentPtr, x2) const sender = fields[0] @@ -154,8 +149,8 @@ function setReceiver() { Interceptor.attach(downloadFileAddr, { onEnter: function (args) { - var dataPtr = this.context.x1; - var dataLen = this.context.x2.toInt32(); + var dataPtr = this.context.x22; + var dataLen = this.context.x0.toInt32(); var fileId = this.context.sp.add(0x30).readPointer().readUtf8String(); var cdnUrl = this.context.x19.add(0x2F8).readPointer().readUtf8String(); @@ -170,7 +165,7 @@ function setReceiver() { Interceptor.attach(downloadImagAddr, { onEnter: function (args) { - var dataPtr = this.context.x1; + var dataPtr = this.context.x22; var dataLen = this.context.x2.toInt32(); var fileId = this.context.x19.add(0x2E0).readPointer().readUtf8String(); var cdnUrl = this.context.x19.add(0x2F8).readPointer().readUtf8String(); @@ -187,7 +182,7 @@ function setReceiver() { Interceptor.attach(downloadVideoAddr, { onEnter: function (args) { var dataPtr = this.context.x1; - var dataLen = this.context.x2.toInt32(); + var dataLen = this.context.x24.toInt32(); var fileId = this.context.x22.add(0x40).readPointer().readUtf8String(); var cdnUrl = this.context.x22.add(0x58).readPointer().readUtf8String(); diff --git a/frida/text.js b/frida/text.js index d203e0b..498a5d8 100644 --- a/frida/text.js +++ b/frida/text.js @@ -1,15 +1,9 @@ -var baseAddr = ptr(0); -Process.enumerateModules().forEach(function (m) { - if (m.name.toLowerCase().includes("wechat.dylib")) { - baseAddr = m.base; - } -}); - -if (baseAddr === 0x0) { - console.log("wechat.dylib not found"); +var moduleName = "wechat.dylib"; +var baseAddr = Process.findModuleByName(moduleName).base; +if (!baseAddr) { + console.error("[!] 找不到 WeChat 模块基址,请检查进程名。"); } -console.log("baseAddr: " + baseAddr); - +console.log("[+] WeChat base address: " + baseAddr); // -------------------------基础函数分区------------------------- function toVarint(n) { @@ -95,15 +89,15 @@ var textCgiAddr = ptr(0); var sendTextMessageAddr = ptr(0); var textMessageAddr = ptr(0); var textProtoX1PayloadAddr = ptr(0); -var sendMessageCallbackFunc = ptr(0); -var messageCallbackFunc1 = baseAddr.add(0x8915F28); + +var sendMessageCallbackFunc = baseAddr.add(0x8915F28); // 双方公共使用的地址 var triggerX1Payload; var triggerX0; var req2bufEnterAddr = baseAddr.add(0x3806b30); -var req2bufExitAddr = baseAddr.add(0x3807C48); +var req2bufExitAddr = baseAddr.add(0x3807C44); var sendFuncAddr = baseAddr.add(0x498D2E0); var insertMsgAddr = ptr(0); var sendMsgType = ""; @@ -137,7 +131,7 @@ function setupSendTextMessageDynamic() { // B. 构建 sendTextMessageAddr 结构体 (X24 基址位置) sendTextMessageAddr.add(0x00).writeU64(0); sendTextMessageAddr.add(0x08).writeU64(0); - sendTextMessageAddr.add(0x10).writePointer(sendMessageCallbackFunc); + sendTextMessageAddr.add(0x10).writeU64(0); sendTextMessageAddr.add(0x18).writeU64(1); sendTextMessageAddr.add(0x20).writeU32(taskIdGlobal); sendTextMessageAddr.add(0x28).writePointer(textMessageAddr); // 指向动态分配的 Message @@ -150,7 +144,7 @@ function setupSendTextMessageDynamic() { })); // C. 构建 Message 结构体 - textMessageAddr.add(0x00).writePointer(messageCallbackFunc1); + textMessageAddr.add(0x00).writePointer(sendMessageCallbackFunc); textMessageAddr.add(0x08).writeU32(taskIdGlobal); textMessageAddr.add(0x0c).writeU32(0x20a); textMessageAddr.add(0x10).writeU64(0x3); @@ -309,7 +303,7 @@ function triggerSendTextMessage(taskId, receiver, content, atUser) { } function AttachSendTextProto() { - Interceptor.attach(sendFuncAddr, { + Interceptor.attach(sendFuncAddr.add(0x10), { onEnter: function (args) { if (triggerX1Payload) { return @@ -448,4 +442,4 @@ function attachReq2buf() { setImmediate(attachReq2buf); -// -------------------------Req2Buf公共部分分区------------------------- \ No newline at end of file +// -------------------------Req2Buf公共部分分区------------------------- diff --git a/hook/hook.js b/hook/hook.js deleted file mode 100644 index 46f123e..0000000 --- a/hook/hook.js +++ /dev/null @@ -1,143 +0,0 @@ -const FUNCTION_RVA = 0x10250D878; // 目标函数 sendMsg_10250D878 的 RVA - -const STRUCT_SIZE = 0x50; - -const module = Process.getModuleByName("WeChat"); -const baseAddress = module.base; -console.log(`Base: ${baseAddress}, size: ${module.base.add(module.size)}`) - -const targetAddress = baseAddress.add(FUNCTION_RVA - 0x100000000); -console.log(`Target Address: ${targetAddress}`) - -let resent = true; -let arg0; - -function sendMessageWechat() { - const funcAddr_1 = baseAddress.add(0x10817DF48 - 0x100000000); // 示例计算 - const funcAddr_2 = baseAddress.add(0x108177ED0 - 0x100000000); // 示例计算 - const funcAddr_3 = baseAddress.add(0x10816AFD8 - 0x100000000); // 示例计算 - const funcAddr_4 = baseAddress.add(0x10817C298 - 0x100000000); // 示例计算 - - - // --- 2. 构造数据结构体的内存 --- - const structPointer = Memory.alloc(STRUCT_SIZE); - - // --- 3. 构造 wxid 字符串 (参数 5) --- - const WXID_STRING = "wxid_7wd1ece99f7i21"; - - structPointer.writePointer(funcAddr_1); - console.log(`Function 1 Address: ${funcAddr_1}`); - - // 结构体偏移 0x08: 参数 2 的第一级指针 (0x60000151F948) - // 这里需要构造二级指针。由于无法分配静态地址 0x6000...,我们只能构造一个新链。 - - // 构造二级指针的目标函数 sub_1023D8204 - const funcPtr_2_tmp1 = Memory.alloc(Process.pointerSize); - const funcPtr_2_tmp2 = Memory.alloc(Process.pointerSize); - funcPtr_2_tmp1.writePointer(funcPtr_2_tmp2); - funcPtr_2_tmp2.writePointer(funcAddr_2); - structPointer.add(0x08).writePointer(funcPtr_2_tmp1); - console.log(`Function 2 Address: ${funcAddr_2}, tmp1: ${funcPtr_2_tmp1}, tmp2: ${funcPtr_2_tmp2}`); - - // 结构体偏移 0x10: 参数 3 的第一级指针 (0x600003F41C20 -> sub_1021D5E48) - const funcPtr_3 = Memory.alloc(Process.pointerSize); - funcPtr_3.writePointer(funcAddr_3); - structPointer.add(0x10).writePointer(funcPtr_3); - console.log(`Function 3 Address: ${funcAddr_3}, tmp: ${funcPtr_3}`); - - const funcPtr_4 = Memory.alloc(Process.pointerSize); - funcPtr_4.writePointer(funcAddr_4); - structPointer.add(0x18).writePointer(funcPtr_4); - console.log(`Function 4 Address: ${funcAddr_3}, tmp: ${funcPtr_4}`); - - // 结构体偏移 0x20: 参数 5 (wxid_7wd1ece99f7i21) - structPointer.add(0x20).writeUtf8String(WXID_STRING); - console.log(`WXID String Address: ${WXID_STRING}`); - - // 填充剩余部分(假设为 NULL 或 0) - structPointer.add(0x28).writePointer(NULL); - structPointer.add(0x30).writePointer(NULL); - - console.log(`Structure constructed at: ${structPointer}`); - - - // --- 5. 定义函数签名并调用 --- - try { - - const sendMsgFunc = new NativeFunction( - targetAddress, - 'void', - ['pointer'] // 参数类型为 'pointer' - ); - - console.log(`Attempting to call the function with constructed structure...: ${targetAddress}`); - - // 调用函数,传入主结构体的地址 - sendMsgFunc(structPointer); - - console.log(`Function called successfully!`); - - } catch (e) { - console.error(`Error calling function: ${e.message}`); - console.error(`Error details: ${e.stack}`); - } -} - -Interceptor.attach(targetAddress, { - onEnter: function (args) { - console.log(`[ENTER] sendMsg called with a1 = ${args[0]}`); - // 检查传入的结构 - const a1 = args[0] - console.log(` a1: ${a1.readPointer()}`); - console.log(` a1+8: ${a1.add(0x08).readPointer()}`); - console.log(` a1+16: ${a1.add(0x10).readPointer()}`); - console.log(` a1+24: ${a1.add(0x18).readPointer()}`); - console.log(` a1+32: ${a1.add(0x20).readPointer()}`); - - }, - onLeave: function (retval) { - console.log(`[LEAVE] sendMsg returned`); - } -}); - -function resend() { - console.log(`Resending structure...`); - console.log(` resend a1: ${arg0.readPointer()}`); - console.log(` resend a1+8: ${arg0.add(0x08).readPointer()}`); - console.log(` resend a1+16: ${arg0.add(0x10).readPointer()}`); - console.log(` resend a1+24: ${arg0.add(0x18).readPointer()}`); - console.log(` resend a1+32: ${arg0.add(0x20).readPointer()}`); - const structPointer = Memory.alloc(STRUCT_SIZE); - - // --- 3. 构造 wxid 字符串 (参数 5) --- - const WXID_STRING = "wxid_7wd1ece99f7i21"; - - structPointer.writePointer(arg0.readPointer()); - structPointer.add(0x08).writePointer(arg0.add(0x08).readPointer()); - structPointer.add(0x10).writePointer(arg0.add(0x10).readPointer()); - structPointer.add(0x18).writePointer(arg0.add(0x18).readPointer()); - structPointer.add(0x20).writeUtf8String(WXID_STRING); - structPointer.add(0x28).writePointer(NULL); - structPointer.add(0x30).writePointer(NULL); - console.log(`Resent structure constructed at: ${structPointer}`); - - try { - - const sendMsgFunc = new NativeFunction( - targetAddress, - 'void', - ['pointer'] // 参数类型为 'pointer' - ); - - console.log(`Attempting to call the function with constructed structure...: ${targetAddress}`); - - // 调用函数,传入主结构体的地址 - sendMsgFunc(structPointer); - - console.log(`Function called successfully!`); - - } catch (e) { - console.error(`Error calling function: ${e.message}`); - console.error(`Error details: ${e.stack}`); - } -} \ No newline at end of file diff --git a/hook/log_decrypt.js b/hook/log_decrypt.js deleted file mode 100644 index e69de29..0000000 diff --git a/hook/readme.md b/hook/readme.md deleted file mode 100644 index 60198cb..0000000 --- a/hook/readme.md +++ /dev/null @@ -1,8 +0,0 @@ -### 问题 -解决不存在frida-core.h: https://github.com/frida/frida-go/issues/4 - -1 参数 10817DF48 是一个函数 sub_10250D544 -2 参数 60000151F948->600003F41C38 -> 108177ED0 是一个函数 sub_1023D8204 -3 参数 600003F41C20 -> 10816AFD8 是一个函数 sub_1021D5E48 -4 参数 1371FD018-> 10817C298 是一个函数 sub_10247C008 -5 参数 wxid_7wd1ece99f7i21 \ No newline at end of file diff --git a/onebot/main.go b/onebot/main.go index 1922882..7c0a73b 100644 --- a/onebot/main.go +++ b/onebot/main.go @@ -26,16 +26,16 @@ func main() { initFrida() } go SendWorker() - + http.HandleFunc("/send_private_msg", sendHandler) http.HandleFunc("/send_group_msg", sendHandler) - + http.HandleFunc("/ws", handleWebSocket) http.HandleFunc("/test_ws", testWebSocket) - + stop := make(chan os.Signal, 1) signal.Notify(stop, os.Interrupt, syscall.SIGTERM) - + go func() { <-stop fridaScript.Clean() @@ -43,13 +43,13 @@ func main() { device.Clean() Fatal("正在释放 Frida 资源并退出...") }() - + // 3. 启动服务 Info("HTTP 服务启动在", "host", config.ReceiveHost) if err := http.ListenAndServe(config.ReceiveHost, nil); err != nil { Error("服务启动失败", "err", err) } - + } func initFlag() { @@ -59,13 +59,13 @@ func initFlag() { flag.StringVar(&config.FridaGadgetAddr, "gadget_addr", "127.0.0.1:27042", "Gadget 地址: 127.0.0.1:27042 仅当 type 为 gadget 时有效") flag.StringVar(&config.OnebotToken, "token", "MuseBot", "OneBot Token: MuseBot") flag.StringVar(&config.ImagePath, "image_path", "", "图片路径: /Users/xxx/Library/Containers/com.tencent.xinWeChat/Data/Documents/xwechat_files/xxx/temp/xxx/2026-01/Img/") - flag.StringVar(&config.WechatConf, "wechat_conf", "../wechat_version/4_1_7_57_mac.json", "微信配置文件路径: ../wechat_version/4_1_6_12_mac.json") + flag.StringVar(&config.WechatConf, "wechat_conf", "../wechat_version/4_1_8_28_mac.json", "微信配置文件路径: ../wechat_version/4_1_6_12_mac.json") flag.StringVar(&config.ConnType, "conn_type", "http", "连接类型: http | websocket") flag.IntVar(&config.SendInterval, "send_interval", 1000, "发送间隔: ms") flag.StringVar(&logLevel, "log_level", "info", "log level") - + flag.Parse() - + fmt.Println("FridaType", config.FridaType) fmt.Println("SendURL", config.SendURL) fmt.Println("ReceiveHost", config.ReceiveHost) @@ -86,39 +86,39 @@ func initFridaGadget() { if err != nil { Fatal("❌ 无法连接 Gadget", err) } - + session, err = device.Attach("Gadget", nil) if err != nil { Fatal("❌ 附加失败", err) } - + loadJs() - + } func initFrida() { var err error // 1. 获取本地设备管理器 mgr := frida.NewDeviceManager() - + // 2. 枚举并获取本地设备 (TypeLocal) device, err = mgr.DeviceByType(frida.DeviceTypeLocal) if err != nil { Fatal("无法获取本地设备", "err", err) } - + pid, err := GetWeChatPID() if err != nil { Fatal("未发现正在运行的微信进程") } Info("微信进程 PID", "PID", pid) MonitorProcessExit(pid) - + session, err = device.Attach(pid, nil) if err != nil { Fatal("Attach 失败 (请检查 SIP 状态或权限)", "err", err) } - + loadJs() } @@ -127,35 +127,35 @@ func loadJs() { if err != nil { Fatal("读取文件失败", "err", err) } - + // 2. 将 JSON 解析为 Map var wechatHookConf map[string]interface{} if err = json.Unmarshal(jsonData, &wechatHookConf); err != nil { Fatal("解析 JSON 失败", "err", err) } - + codeTemplate, err := os.ReadFile("./script.js") if err != nil { Fatal("读取脚本失败", "err", err) } - + tmpl, err := template.New("fridaScript").Parse(string(codeTemplate)) if err != nil { Fatal("解析模板失败", "err", err) return } - + var buf bytes.Buffer err = tmpl.Execute(&buf, wechatHookConf) if err != nil { Fatal("执行模板失败", "err", err) } - + script, err := session.CreateScript(buf.String()) if err != nil { Fatal("创建脚本失败", "err", err) } - + // 打印 JS 里的 console.log script.On("message", func(rawMsg string) { defer func() { @@ -163,16 +163,16 @@ func loadJs() { Error("message panic", "err", r, "stack", string(debug.Stack())) } }() - + var msg map[string]interface{} err = json.Unmarshal([]byte(rawMsg), &msg) if err != nil { Error("JSON解析失败", "err", err) return } - + msgType := msg["type"].(string) - + switch msgType { case "send": if p, ok := msg["payload"]; ok { @@ -224,7 +224,7 @@ func loadJs() { Error("下载失败", "err", err) } } - + } } } @@ -234,11 +234,11 @@ func loadJs() { Error("[JS日志报错]", "err", msg["description"], "stack", msg["stack"]) } }) - + if err := script.Load(); err != nil { Fatal("❌ 加载脚本失败", err) } - + fridaScript = script Info("✅ Frida 已就绪,微信控制通道已打通") } diff --git a/onebot/script.js b/onebot/script.js index ec4832c..a102def 100644 --- a/onebot/script.js +++ b/onebot/script.js @@ -1,5 +1,5 @@ -// 1. 获取微信主模块的基地址 -var baseAddr = Process.getModuleByName("WeChat").base; +var moduleName = "wechat.dylib"; +var baseAddr = Process.findModuleByName(moduleName).base; if (!baseAddr) { console.error("[!] 找不到 WeChat 模块基址,请检查进程名。"); } @@ -260,7 +260,7 @@ function generateBytes(n) { // 文本消息全局变量 // 文本消息全局变量 var textCallbackFuncAddr = baseAddr.add({{.textCallbackFuncAddr}}); -var protobufAddr = textCallbackFuncAddr.add(0x44); +var protobufAddr = textCallbackFuncAddr.add(0x40); var patchTextProtobufAddr = textCallbackFuncAddr.add(0x20); var patchTextProtobufByte var patchTextProtobufDeleteAddr = textCallbackFuncAddr.add(0x5C); @@ -284,7 +284,7 @@ var buf2RespAddr = baseAddr.add({{.buf2RespAddr}}); // 图片消息全局变量 var imageCallbackFuncAddr = baseAddr.add({{.imageCallbackFuncAddr}}); -var imgProtobufAddr = imageCallbackFuncAddr.add(0x54); +var imgProtobufAddr = imageCallbackFuncAddr.add(0x50); var patchImgProtobufFunc1 = imageCallbackFuncAddr.add(0x10); var patchImgProtobufFunc1Byte; var patchImgProtobufFunc2 = imageCallbackFuncAddr.add(0x30); @@ -294,7 +294,7 @@ var imgProtobufDeleteAddrByte; // 视频消息全局变量 var videoCallbackFuncAddr = baseAddr.add({{.videoCallbackFuncAddr}}); -var videoProtobufAddr = videoCallbackFuncAddr.add(0x54); +var videoProtobufAddr = videoCallbackFuncAddr.add(0x50); var patchVideoProtobufFunc1 = videoCallbackFuncAddr.add(0x10); var patchVideoProtobufFunc1Byte; var patchVideoProtobufFunc2 = videoCallbackFuncAddr.add(0x30); @@ -577,8 +577,8 @@ function triggerSendTextMessage(taskId, receiver, content, atUser) { } } -function AttachSendTextProto() { - Interceptor.attach(sendFuncAddr, { +function AttachSendFunc() { + Interceptor.attach(sendFuncAddr.add(0x10), { onEnter: function (args) { if (triggerX1Payload) { @@ -592,7 +592,7 @@ function AttachSendTextProto() { }) } -setImmediate(AttachSendTextProto); +setImmediate(AttachSendFunc); // 拦截 SendTextProto 编码逻辑,注入自定义 Payload function attachSendTextProto() { @@ -1707,12 +1707,12 @@ setImmediate(setupDownloadFileDynamic) function setReceiver() { Interceptor.attach(buf2RespAddr, { onEnter: function (args) { - const currentPtr = this.context.x1; + const currentPtr = this.context.x20; if (currentPtr.add(0).readU8() !== 0x08) { return } - const x2 = this.context.x2.toInt32(); + const x2 = this.context.x0.toInt32(); // console.log(" [+] currentPtr: ", hexdump(currentPtr, { // offset: 0, // length: x2, @@ -1820,8 +1820,8 @@ function setReceiver() { Interceptor.attach(downloadFileAddr, { onEnter: function (args) { - var dataPtr = this.context.x1; - var dataLen = this.context.x2.toInt32(); + var dataPtr = this.context.x22; + var dataLen = this.context.x20.toInt32(); var fileId = this.context.sp.add(0x30).readPointer().readUtf8String(); var cdnUrl = this.context.x19.add(0x2F8).readPointer().readUtf8String(); @@ -1841,7 +1841,7 @@ function setReceiver() { Interceptor.attach(downloadImagAddr, { onEnter: function (args) { - var dataPtr = this.context.x1; + var dataPtr = this.context.x22; var dataLen = this.context.x2.toInt32(); var fileId = this.context.x19.add(0x2E0).readPointer().readUtf8String(); var cdnUrl = this.context.x19.add(0x2F8).readPointer().readUtf8String(); @@ -1863,7 +1863,7 @@ function setReceiver() { Interceptor.attach(downloadVideoAddr, { onEnter: function (args) { var dataPtr = this.context.x1; - var dataLen = this.context.x2.toInt32(); + var dataLen = this.context.x24.toInt32(); var fileId = this.context.x22.add(0x40).readPointer().readUtf8String(); var cdnUrl = this.context.x22.add(0x58).readPointer().readUtf8String(); @@ -2107,4 +2107,4 @@ function getMessages(content, sender, mediaContent) { return messages; } -// -------------------------接收消息分区------------------------- \ No newline at end of file +// -------------------------接收消息分区------------------------- diff --git a/wechat_version/4_1_8_28_mac.json b/wechat_version/4_1_8_28_mac.json index 68f6646..a2e3d4a 100644 --- a/wechat_version/4_1_8_28_mac.json +++ b/wechat_version/4_1_8_28_mac.json @@ -1,22 +1,22 @@ { - "textCallbackFuncAddr": "", - "sendMessageCallbackFunc": "", - "sendFuncAddr": "", - "req2bufEnterAddr": "", - "req2bufExitAddr": "", - "imageCallbackFuncAddr": "", - "imgMessageCallbackFunc": "", - "uploadImageAddr": "", - "cndOnCompleteAddr": "", - "buf2RespAddr": "", - "uploadGetCallbackWrapperAddr": "", - "uploadGetCallbackWrapperFuncAddr": "", - "uploadOnCompleteAddr": "", - "uploadOnCompleteFuncAddr": "", - "downloadImagAddr": "", - "startDownloadMedia": "", - "downloadFileAddr": "", - "downloadVideoAddr": "", - "videoCallbackFuncAddr": "", - "videoMessageCallbackFunc": "" -} \ No newline at end of file + "textCallbackFuncAddr": "0x2524140", + "sendMessageCallbackFunc": "0x8915F28", + "sendFuncAddr": "0x498D2E0", + "req2bufEnterAddr": "0x3806b30", + "req2bufExitAddr": "0x3807C44", + "imageCallbackFuncAddr": "0x251AD40", + "imgMessageCallbackFunc": "0x89159F0", + "uploadImageAddr": "0x4ad4860", + "cndOnCompleteAddr": "0x37C40E0", + "buf2RespAddr": "0x382C1A8", + "uploadGetCallbackWrapperAddr": "0x4aa2324", + "uploadGetCallbackWrapperFuncAddr": "0x37C392C", + "uploadOnCompleteAddr": "0x4AA2920", + "uploadOnCompleteFuncAddr": "0x37C4B10", + "downloadImagAddr": "0x4BF85F0", + "startDownloadMedia": "0x4AD54D4", + "downloadFileAddr": "0x4B97378", + "downloadVideoAddr": "0x4bb90fc", + "videoCallbackFuncAddr": "0x2587FD0", + "videoMessageCallbackFunc": "0x8918790" +}