From e9abe629dc26f5d0e86f595855f54a5e1cafc6f6 Mon Sep 17 00:00:00 2001 From: yincong Date: Wed, 25 Feb 2026 10:47:52 +0800 Subject: [PATCH] update 4.1.7.55 --- README.md | 2 +- frida-wechat.md | 4 +-- frida/image.js | 56 ++++++++++++++++---------------- frida/receiver.js | 3 +- frida/text.js | 14 ++++---- frida/trigger_send_msg.js | 47 --------------------------- onebot/script.js | 1 - wechat_version/4_1_7_55_mac.json | 21 ++++++------ 8 files changed, 49 insertions(+), 99 deletions(-) delete mode 100644 frida/trigger_send_msg.js diff --git a/README.md b/README.md index 1ccfa02..380cabe 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ hook2是对Req2Buf这个函数进行消息体注入,因为hook1触发的时候 hook4是在Req2Buf,清除掉消息体的内容,因为后序在OnTaskEnd会回收内存,如果我这边消息体还在整个的指针上就会被清除,但是这个线程不认识这块内存,整个程序就会crash。 -查看:./frida/succ.js +根据release中对应的微信版本使用 ## 图片消息 ``` diff --git a/frida-wechat.md b/frida-wechat.md index b339289..068a8e5 100644 --- a/frida-wechat.md +++ b/frida-wechat.md @@ -1,5 +1,5 @@ -触发 STNManager__MMStartTask -图片hook: startUploadMedia, OnUploadCompleted +触发 STNManager__MMStartTask (ida搜 MMStartTask) +图片hook: startUploadMedia (ida搜), OnUploadCompleted (ce查) startUploadMedia 上传图片,OnUploadCompleted 上传图片完成后的回调 WeChatExt中会有导致idapro出问题的代码 \ No newline at end of file diff --git a/frida/image.js b/frida/image.js index bbd2a08..e9ef0fb 100644 --- a/frida/image.js +++ b/frida/image.js @@ -160,20 +160,20 @@ function generateBytes(n) { // 双方公共使用的地址 var triggerX1Payload; var triggerX0; -var req2bufEnterAddr = baseAddr.add(0x35CEDBC); -var req2bufExitAddr = baseAddr.add(0x35CFF94); -var sendFuncAddr = baseAddr.add(0x4A49BC4); +var req2bufEnterAddr = baseAddr.add(0x36F1614); +var req2bufExitAddr = baseAddr.add(0x36F27EC); +var sendFuncAddr = baseAddr.add(0x47F1888); var insertMsgAddr = ptr(0); var sendMsgType = ""; // 图片消息全局变量 -var uploadImageAddr = baseAddr.add(0x47D5D64); -var imgProtobufAddr = baseAddr.add(0x237DFE0); -var patchImgProtobufFunc1 = baseAddr.add(0x237DF9C) -var patchImgProtobufFunc2 = baseAddr.add(0x237DFBC); -var imgProtobufDeleteAddr = baseAddr.add(0x237DFF8); -var CndOnCompleteAddr = baseAddr.add(0x358D98C); -var imgMessageCallbackFunc1 = baseAddr.add(0x865D680); +var uploadImageAddr = baseAddr.add(0x4938E08); +var imgProtobufAddr = baseAddr.add(0x2455574); +var patchImgProtobufFunc1 = baseAddr.add(0x2455530) +var patchImgProtobufFunc2 = baseAddr.add(0x2455550); +var imgProtobufDeleteAddr = baseAddr.add(0x245558C); +var CndOnCompleteAddr = baseAddr.add(0x36B03A0); +var imgMessageCallbackFunc1 = baseAddr.add(0x8781AF8); var uploadImageX1; var imgCgiAddr = ptr(0); @@ -182,9 +182,9 @@ var imgMessageAddr = ptr(0); var imgProtoX1PayloadAddr = ptr(0); var uploadGlobalX0 = ptr(0) var uploadFunc1Addr = ptr(0) -var uploadFunc1 = baseAddr.add(0x086EEB8C8) +var uploadFunc1 = ptr(0) var uploadFunc2Addr = ptr(0) -var uploadFunc2 = baseAddr.add(0x086E32AB0) +var uploadFunc2 = ptr(0) var imageIdAddr = ptr(0) var md5Addr = ptr(0) var uploadAesKeyAddr = ptr(0) @@ -732,7 +732,7 @@ function patchCdnOnComplete() { setImmediate(patchCdnOnComplete) function attachGetCallbackFromWrapper() { - Interceptor.attach(baseAddr.add(0x47A3828), { + Interceptor.attach(baseAddr.add(0x49068CC), { onEnter: function (args) { const tmpFileId = this.context.x1.readPointer().readUtf8String(); const fileId = imageIdAddr.readUtf8String(); @@ -742,25 +742,25 @@ function attachGetCallbackFromWrapper() { } console.log("[+] GetCallbackFromWrapper x8: " + this.context.x8); - uploadCallback.add(0x10).writePointer(baseAddr.add(0x358D1A8)); + uploadCallback.add(0x10).writePointer(baseAddr.add(0x36AFFEC)); this.context.x8 = uploadCallback; } }) - Interceptor.attach(baseAddr.add(0x47A3E24), { - onEnter: function (args) { - const tmpFileId = this.context.x1.readPointer().readUtf8String(); - const fileId = imageIdAddr.readUtf8String(); - if (tmpFileId !== fileId) { - console.log("[+] OnComplete tmpFileId: " + tmpFileId + " fileId: " + fileId); - return - } - - console.log("[+] OnComplete x8: " + this.context.x8); - uploadCallback.add(0x30).writePointer(baseAddr.add(0x358E398)); - this.context.x8 = uploadCallback; - } - }) + // Interceptor.attach(baseAddr.add(0x47A3E24), { + // onEnter: function (args) { + // const tmpFileId = this.context.x1.readPointer().readUtf8String(); + // const fileId = imageIdAddr.readUtf8String(); + // if (tmpFileId !== fileId) { + // console.log("[+] OnComplete tmpFileId: " + tmpFileId + " fileId: " + fileId); + // return + // } + // + // console.log("[+] OnComplete x8: " + this.context.x8); + // uploadCallback.add(0x30).writePointer(baseAddr.add(0x358E398)); + // this.context.x8 = uploadCallback; + // } + // }) } setImmediate(attachGetCallbackFromWrapper); diff --git a/frida/receiver.js b/frida/receiver.js index 5962b7e..90d6b71 100644 --- a/frida/receiver.js +++ b/frida/receiver.js @@ -3,7 +3,7 @@ if (!baseAddr) { console.error("[!] 找不到 WeChat 模块基址,请检查进程名。"); } -var buf2RespAddr = baseAddr.add(0x35F4B58) +var buf2RespAddr = baseAddr.add(0x37173B0) // -------------------------接收消息分区------------------------- function setReceiver() { @@ -11,7 +11,6 @@ function setReceiver() { // 3. 开始拦截 Interceptor.attach(buf2RespAddr, { onEnter: function (args) { - console.log("[*] 拦截到消息发送"); const currentPtr = this.context.x1; let start = 0x1e; let senderLen = currentPtr.add(start).readU8(); diff --git a/frida/text.js b/frida/text.js index 5fd59bc..0481a3e 100644 --- a/frida/text.js +++ b/frida/text.js @@ -78,23 +78,23 @@ function patchString(addr, plainStr) { // -------------------------全局变量分区------------------------- // 文本消息全局变量 -var protobufAddr = baseAddr.add(0x2387280); -var patchTextProtobufAddr = baseAddr.add(0x238725C); -var PatchTextProtobufDeleteAddr = baseAddr.add(0x2387298); +var protobufAddr = baseAddr.add(0x245E9B0); +var patchTextProtobufAddr = baseAddr.add(0x245E98C); +var PatchTextProtobufDeleteAddr = baseAddr.add(0x245E9C8); var textCgiAddr = ptr(0); var sendTextMessageAddr = ptr(0); var textMessageAddr = ptr(0); var textProtoX1PayloadAddr = ptr(0); var sendMessageCallbackFunc = ptr(0); -var messageCallbackFunc1 = baseAddr.add(0x865DBB8); +var messageCallbackFunc1 = baseAddr.add(0x8781010); // 双方公共使用的地址 var triggerX1Payload; var triggerX0; -var req2bufEnterAddr = baseAddr.add(0x35CEDBC); -var req2bufExitAddr = baseAddr.add(0x35CFF94); -var sendFuncAddr = baseAddr.add(0x4A49BC4); +var req2bufEnterAddr = baseAddr.add(0x36F1614); +var req2bufExitAddr = baseAddr.add(0x36F27EC); +var sendFuncAddr = baseAddr.add(0x47F1888); var insertMsgAddr = ptr(0); var sendMsgType = ""; diff --git a/frida/trigger_send_msg.js b/frida/trigger_send_msg.js deleted file mode 100644 index 93a8c26..0000000 --- a/frida/trigger_send_msg.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * 构造内存数据并调用 sub_10481C304 - */ -function callTargetFunction() { - // 1. 查找函数地址 (请确保模块名正确,这里假设是 WeChat) - const moduleName = "WeChat"; - const sub_10481C304_addr = Module.findBaseAddress(moduleName).add(0x481C304); - const sub_10481C304 = new NativeFunction(sub_10481C304_addr, 'void', ['pointer']); - - // 2. 准备原始字节数据 (Hex 形式) - // 注意:0x18 偏移处的 8 字节(原数据 60 E1 39 78 05 00 00 00)会被动态生成的指针覆盖 - const rawData = [ - 0x00, 0x00, 0x00, 0x00, 0x0A, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 指针位置 - 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x11, 0x01, 0x00, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0xAA, 0xAA, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0A, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ]; - - // 3. 申请结构体内存 - const structPtr = Memory.alloc(rawData.length); - structPtr.writeByteArray(rawData); - - // 4. 申请字符串内存并写入指针 (偏移 0x18) - const cgiPath = "/cgi-bin/micromsg-bin/newsendmsg"; - const pathPtr = Memory.allocUtf8String(cgiPath); - - // 将字符串地址写入结构体的 0x18 偏移处 (64位系统占8字节) - structPtr.add(0x18).writePointer(pathPtr); - - console.log("[+] 内存结构体已准备完毕: " + structPtr); - console.log("[+] 字符串地址: " + pathPtr + " 内容: " + cgiPath); - - // 5. 调用函数 - try { - sub_10481C304(structPtr); - console.log("[+] sub_10481C304 调用成功!"); - - console.log("[*] 结构体内存布局 (调用后):"); - console.log(hexdump(structPtr, { offset: 0, length: rawData.length, header: true, ansi: true })); - - } catch (e) { - console.log("[-] 调用出错: " + e); - } -} \ No newline at end of file diff --git a/onebot/script.js b/onebot/script.js index 9d46384..f0668c4 100644 --- a/onebot/script.js +++ b/onebot/script.js @@ -220,7 +220,6 @@ var sendTextMessageAddr = ptr(0); var textMessageAddr = ptr(0); var textProtoX1PayloadAddr = ptr(0); var sendMessageCallbackFunc = baseAddr.add({{.sendMessageCallbackFunc}}); -var messageCallbackFunc1 = ptr(0); // 双方公共使用的地址 diff --git a/wechat_version/4_1_7_55_mac.json b/wechat_version/4_1_7_55_mac.json index 1bbd5b9..3f0a39a 100644 --- a/wechat_version/4_1_7_55_mac.json +++ b/wechat_version/4_1_7_55_mac.json @@ -1,20 +1,19 @@ { - "protobufAddr": "", - "patchTextProtobufAddr": "", - "PatchTextProtobufDeleteAddr": "", - "sendMessageCallbackFunc": "", - "sendFuncAddr": "", - "req2bufEnterAddr": "", - "req2bufExitAddr": "", + "protobufAddr": "0x245E9B0", + "patchTextProtobufAddr": "0x245E98C", + "PatchTextProtobufDeleteAddr": "0x245E9C8", + "sendMessageCallbackFunc": "0x8781010", + "sendFuncAddr": "0x47F1888", + "req2bufEnterAddr": "0x36F1614", + "req2bufExitAddr": "0x36F27EC", "imgProtobufAddr": "", "patchImgProtobufFunc1": "", - "patchImgProtobufFunc2": " ", + "patchImgProtobufFunc2": "", "imgProtobufDeleteAddr": "", + "imgMessageCallbackFunc1": "", "uploadImageAddr": "", "CndOnCompleteAddr": "", - "sendImgMessageCallbackFunc": "", - "buf2RespAddr": "", - "imgMessageCallbackFunc1": "", + "buf2RespAddr": "0x37173B0", "uploadGetCallbackWrapperAddr": "", "uploadGetCallbackWrapperFuncAddr": "", "uploadOnCompleteAddr": "",