From 0a329f3686ba1e22ef2306b9165edacd66558255 Mon Sep 17 00:00:00 2001 From: yincong Date: Sun, 18 Jan 2026 12:38:11 +0800 Subject: [PATCH] close finished --- onebot/main.go | 7 +- onebot/receiver.js | 250 +++++++++++++++++++++++++++++++++------------ onebot/script.js | 15 ++- 3 files changed, 199 insertions(+), 73 deletions(-) diff --git a/onebot/main.go b/onebot/main.go index 7bd55a0..1e2ebbc 100644 --- a/onebot/main.go +++ b/onebot/main.go @@ -32,7 +32,7 @@ var ( fridaScript *frida.Script session *frida.Session taskId = int64(0x20000000) - myWechatId = "wxid_ldftuhe36izg19" + myWechatId = "" msgChan = make(chan *SendMsg, 10) finishChan = make(chan struct{}) @@ -193,6 +193,11 @@ func loadJs() { go SendHttpReq(msg) } else if t.(string) == "finish" { finishChan <- struct{}{} + } else if t.(string) == "upload" { + if selfId, ok := pMap["self_id"]; ok && myWechatId == "" { + fmt.Printf("✅ 检测到微信登录,当前账号: %s\n", selfId.(string)) + myWechatId = selfId.(string) + } } } } diff --git a/onebot/receiver.js b/onebot/receiver.js index 35314f8..85f1412 100644 --- a/onebot/receiver.js +++ b/onebot/receiver.js @@ -23,75 +23,81 @@ function setReceiver() { } } - console.log("[+] Entered Receive Function: 0x1023B5348"); + const x2 = this.context.x2.toInt32(); + const fields = getProtobufRawBytes(currentPtr, x2) + console.log(JSON.stringify(fields)); - let senderPtr = currentPtr.add(start + 1); - let sender = senderPtr.readUtf8String(senderLen); - let receiverLenPtr = senderPtr.add(senderLen).add(3); - let receiverLen = receiverLenPtr.readU8(); - let receiverStrPtr = receiverLenPtr.add(1); - let receiver = receiverStrPtr.readUtf8String(receiverLen); - - let contentLenPtr = receiverStrPtr.add(receiverLen).add(6); - // 判断是否等于 0x77 ('w'), 如果是,则是短字段 - if (isPrintableOrChinese(contentLenPtr, 1)) { - contentLenPtr = contentLenPtr.add(-1); - } - const contentLenValue = readVarint(contentLenPtr) - let contentPtr = contentLenPtr.add(contentLenValue.byteLength); - var content = contentPtr.readUtf8String(contentLenValue.value); - - var selfId = receiver - var msgType = "private" - var groupId = "" - var senderUser = sender - var messages = []; - messages.push({type: "text", data: {text: content}}); - - if (sender.includes("@chatroom")) { - msgType = "group" - groupId = sender - let splitIndex = -1; - for (let i = 0; i < content.length; i++) { - if (content[i] === ':') { - splitIndex = i; - break; - } - } - - senderUser = content.substring(0, splitIndex).trim(); - content = content.substring(splitIndex + 2).trim(); - - messages = []; - const parts = content.split('\u2005'); - for (let part of parts) { - part = part.trim(); - if (!part.startsWith("@")) { - messages.push({type: "text", data: {text: part}}); - } - } - - const xmlPtr = contentPtr.add(contentLenValue.value).add(15); - const xmlLenValue = readVarint(xmlPtr) - const xml = xmlPtr.add(xmlLenValue.byteLength).readUtf8String(xmlLenValue.value); - const atUserMatch = xml.match(/([\s\S]*?)<\/atuserlist>/); - const atUser = atUserMatch ? atUserMatch[1] : null; - if (atUser) { - messages.push({type: "at", data: {qq: atUser}}); - } - } - - send({ - message_type: msgType, - user_id: senderUser, // 发送人的 ID - self_id: selfId, // 接收人的 ID - group_id: groupId, // 群 ID - message_id: generateAESKey(), - type: "send", - raw: {peerUid: generateAESKey()}, - message: messages - }) + // + // console.log("[+] Entered Receive Function: 0x1023B5348"); + // + // let senderPtr = currentPtr.add(start + 1); + // let sender = senderPtr.readUtf8String(senderLen); + // + // let receiverLenPtr = senderPtr.add(senderLen).add(3); + // let receiverLen = receiverLenPtr.readU8(); + // let receiverStrPtr = receiverLenPtr.add(1); + // let receiver = receiverStrPtr.readUtf8String(receiverLen); + // + // let contentLenPtr = receiverStrPtr.add(receiverLen).add(6); + // // 判断是否等于 0x77 ('w'), 如果是,则是短字段 + // if (isPrintableOrChinese(contentLenPtr, 1)) { + // contentLenPtr = contentLenPtr.add(-1); + // } + // const contentLenValue = readVarint(contentLenPtr) + // let contentPtr = contentLenPtr.add(contentLenValue.byteLength); + // var content = contentPtr.readUtf8String(contentLenValue.value); + // + // var selfId = receiver + // var msgType = "private" + // var groupId = "" + // var senderUser = sender + // var messages = []; + // messages.push({type: "text", data: {text: content}}); + // + // if (sender.includes("@chatroom")) { + // msgType = "group" + // groupId = sender + // let splitIndex = -1; + // for (let i = 0; i < content.length; i++) { + // if (content[i] === ':') { + // splitIndex = i; + // break; + // } + // } + // + // senderUser = content.substring(0, splitIndex).trim(); + // content = content.substring(splitIndex + 2).trim(); + // + // messages = []; + // const parts = content.split('\u2005'); + // for (let part of parts) { + // part = part.trim(); + // if (!part.startsWith("@")) { + // messages.push({type: "text", data: {text: part}}); + // } + // } + // + // const xmlPtr = contentPtr.add(contentLenValue.value).add(15); + // const xmlLenValue = readVarint(xmlPtr) + // const xml = xmlPtr.add(xmlLenValue.byteLength).readUtf8String(xmlLenValue.value); + // const atUserMatch = xml.match(/([\s\S]*?)<\/atuserlist>/); + // const atUser = atUserMatch ? atUserMatch[1] : null; + // if (atUser) { + // messages.push({type: "at", data: {qq: atUser}}); + // } + // } + // + // send({ + // message_type: msgType, + // user_id: senderUser, // 发送人的 ID + // self_id: selfId, // 接收人的 ID + // group_id: groupId, // 群 ID + // message_id: generateAESKey(), + // type: "send", + // raw: {peerUid: generateAESKey()}, + // message: messages + // }) }, }); } @@ -158,4 +164,114 @@ function generateAESKey() { key += chars.charAt(Math.floor(Math.random() * chars.length)); } return key; +} + + +function getProtobufRawBytes(pBuffer, scanSize) { + const tags = [0x12, 0x1A, 0x2A, 0x52]; + let uint8Array; + + try { + const mem = pBuffer.readByteArray(scanSize); + if (!mem) return []; + uint8Array = new Uint8Array(mem); + } catch (e) { + console.error("读取内存失败: " + e); + return []; + } + + let finalResults = []; + + let i = 0x1b; + tags.forEach(targetTag => { + let found = false; + for (; i < uint8Array.length; i++) { + if (uint8Array[i] === targetTag) { + // 1. 解析 Varint 长度 (支持 1-5 字节长度标识) + let length = 0; + let shift = 0; + let bytesReadForLen = 0; + i = i + 1; + + while (i < uint8Array.length) { + let b = uint8Array[i]; + length |= (b & 0x7F) << shift; + bytesReadForLen++; + i++; + if (!(b & 0x80)) break; + shift += 7; + } + + // 2. 截取原始 Byte 数据 + if (i + length <= uint8Array.length) { + let rawData = uint8Array.slice(i, i + length); + finalResults.push(getCleanString(rawData)); + i += length; + } else { + finalResults.push(null); // 长度越界 + } + + found = true; + break; // 找到第一个匹配的 Tag 就跳出 + } + } + if (!found) finalResults.push(null); // 未找到该 Tag + }); + + return finalResults; +} + +function getCleanString(uint8Array) { + var out = ""; + var i = 0; + var len = uint8Array.length; + + while (i < len) { + var c = uint8Array[i++]; + + // 1. 处理单字节 (ASCII: 0xxxxxxx) + if (c < 0x80) { + // 只保留可见字符 (Space 32 到 ~ 126) + if (c >= 32 && c <= 126) { + out += String.fromCharCode(c); + } + } + // 2. 处理双字节 (110xxxxx 10xxxxxx) + else if ((c & 0xE0) === 0xC0 && i < len) { + var c2 = uint8Array[i++]; + if ((c2 & 0xC0) === 0x80) { + // 这种通常是特殊拉丁字母等,按需保留 + var charCode = ((c & 0x1F) << 6) | (c2 & 0x3F); + out += String.fromCharCode(charCode); + } + } + // 3. 处理三字节 (1110xxxx 10xxxxxx 10xxxxxx) -> 绝大多数汉字在此 + else if ((c & 0xF0) === 0xE0 && i + 1 < len) { + var c2 = uint8Array[i++]; + var c3 = uint8Array[i++]; + if ((c2 & 0xC0) === 0x80 && (c3 & 0xC0) === 0x80) { + var charCode = ((c & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F); + // 判断是否在汉字区间 + if (charCode >= 0x4E00 && charCode <= 0x9FA5 || charCode === 0x2005) { + out += String.fromCharCode(charCode); + } + } + } + else if ((c & 0xF8) === 0xF0 && i + 2 < len) { + var c2 = uint8Array[i++]; + var c3 = uint8Array[i++]; + var c4 = uint8Array[i++]; + if ((c2 & 0xC0) === 0x80 && (c3 & 0xC0) === 0x80 && (c4 & 0xC0) === 0x80) { + // 计算 Unicode 码点 + var codePoint = ((c & 0x07) << 18) | ((c2 & 0x3F) << 12) | ((c3 & 0x3F) << 6) | (c4 & 0x3F); + + // Emoji 范围通常在 U+1F000 到 U+1F9FF 之间 + if (codePoint >= 0x1F000 && codePoint <= 0x1FADF) { + // 使用 fromCodePoint 处理 4 字节字符 + out += String.fromCodePoint(codePoint); + } + } + } + } + return out; } \ No newline at end of file diff --git a/onebot/script.js b/onebot/script.js index 6bf53fb..237ff2a 100644 --- a/onebot/script.js +++ b/onebot/script.js @@ -780,7 +780,7 @@ function attachProto() { console.log("[+] 寄存器修改完成: X1=" + this.context.x1 + ", X2=" + this.context.x2, hexdump(imgProtoX1PayloadAddr, { offset: 0, - length: 1024, + length: 256, header: true, ansi: true })); @@ -908,7 +908,14 @@ function attachUploadMedia() { onEnter: function (args) { console.log("[+] enter UploadMedia"); uploadGlobalX0 = this.context.x0; - console.log("UploadMedia x1: " + uploadGlobalX0); + const x1 = this.context.x1; + const selfId = x1.add(0x68).readUtf8String(); + const imagePath = x1.add(0xe0).readPointer().readUtf8String(); + send({ + type: "upload", + self_id: selfId, + }) + console.log("UploadMedia x1: " + uploadGlobalX0 + " imagePath: " + imagePath + " selfId: " + selfId); } }) } @@ -925,12 +932,10 @@ function patchCdnOnComplete() { globalImageCdnKey = x2.add(0x60).readPointer().readUtf8String(); globalAesKey1 = x2.add(0x78).readPointer().readUtf8String(); globalMd5Key = x2.add(0x90).readPointer().readUtf8String(); - const selfId = x2.add(0x40).readUtf8String(); console.log("[+] globalImageCdnKey: " + globalImageCdnKey + " globalAesKey1: " + globalAesKey1 + - " globalAesKey2: " + globalMd5Key + " selfId: " + selfId); + " globalAesKey2: " + globalMd5Key); send({ type: "finish", - self_id: selfId, }) } catch (e) { console.log("[-] Memory access error at onEnter: " + e);