mirror of
https://github.com/yincongcyincong/wechat_chatter.git
synced 2026-07-15 10:26:52 +08:00
format
This commit is contained in:
+5
-1
@@ -25,7 +25,7 @@ function scanPatterns() {
|
||||
// 特征码数组:? 代表通配符,空格可选
|
||||
const myPatterns = [
|
||||
{
|
||||
name: "CndOnCompleteAddr",
|
||||
name: "cndOnCompleteAddr",
|
||||
pattern: "08 19 40 F9 E1 03 14 AA E2 03 15 AA 00 01 3F D6"
|
||||
},
|
||||
{
|
||||
@@ -59,6 +59,10 @@ const myPatterns = [
|
||||
{
|
||||
name: "startDownloadMedia",
|
||||
pattern: "B6 E3 02 D1 68 E1 01 D0 08 71 44 F9 08 01 40 F9 A8 83 1C F8 28 7C 42 39 09 1D 00 13 2A 48 40 F9 3F 01 00 71 48 B1 88 9A"
|
||||
},
|
||||
{
|
||||
name: "downloadVideoAddr",
|
||||
pattern: "E0 03 07 91 01 00 80 52 45 C1 80 52 06 00 80 52 07 00 80 D2"
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
+138
-42
@@ -154,10 +154,38 @@ var uploadVideoX1 = ptr(0);
|
||||
var videoIdAddr = ptr(0);
|
||||
var videoPathAddr1 = ptr(0)
|
||||
|
||||
var globalCdnKey = "";
|
||||
var globalAesKey = "";
|
||||
var globalMd5Key = "";
|
||||
var videoIdentity = ""
|
||||
// -------------------------上传队列 (解决并发问题)-------------------------
|
||||
// 图片上传完成队列 - 存储 {cdnKey, aesKey, md5Key, targetId}
|
||||
var imageUploadQueue = [];
|
||||
// 视频上传完成队列 - 存储 {cdnKey, aesKey, md5Key, videoIdentity, targetId}
|
||||
var videoUploadQueue = [];
|
||||
|
||||
// 从队列中获取最早的可用上传信息
|
||||
function getImageUploadInfo() {
|
||||
if (imageUploadQueue.length > 0) {
|
||||
return imageUploadQueue.shift();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getVideoUploadInfo() {
|
||||
if (videoUploadQueue.length > 0) {
|
||||
return videoUploadQueue.shift();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function pushImageUploadInfo(info) {
|
||||
imageUploadQueue.push(info);
|
||||
console.log("[+] 图片上传信息已入队,当前队列长度:", imageUploadQueue.length);
|
||||
}
|
||||
|
||||
function pushVideoUploadInfo(info) {
|
||||
videoUploadQueue.push(info);
|
||||
console.log("[+] 视频上传信息已入队,当前队列长度:", videoUploadQueue.length);
|
||||
}
|
||||
|
||||
// -------------------------上传队列 end-------------------------
|
||||
|
||||
// 发送消息的全局变量
|
||||
var taskIdGlobal = 0x0 // 最好比较大,不和原始的微信消息重复
|
||||
@@ -622,7 +650,24 @@ function attachProto() {
|
||||
var currTaskId = this.context.sp.add(0x30).readU32();
|
||||
if (currTaskId !== taskIdGlobal) {
|
||||
console.log(`[+] 拦截到非目标 currTaskId: ${currTaskId} taskIdGlobal: ${taskIdGlobal}`);
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
// 从图片队列获取上传信息
|
||||
const imgUploadInfo = getImageUploadInfo();
|
||||
let cdnKey = "";
|
||||
let aesKey = "";
|
||||
let md5Key = "";
|
||||
let targetId = "";
|
||||
|
||||
if (imgUploadInfo) {
|
||||
cdnKey = imgUploadInfo.cdnKey;
|
||||
aesKey = imgUploadInfo.aesKey;
|
||||
md5Key = imgUploadInfo.md5Key;
|
||||
targetId = imgUploadInfo.targetId;
|
||||
} else {
|
||||
console.error("[!] 无法获取图片上传信息");
|
||||
return;
|
||||
}
|
||||
|
||||
const type = [0x0A, 0x40, 0x0A, 0x01, 0x00]
|
||||
@@ -635,7 +680,7 @@ function attachProto() {
|
||||
const sys = [0x55, 0x6E, 0x69, 0x66, 0x69, 0x65, 0x64, 0x50, 0x43, 0x4D, 0x61, 0x63, 0x20, 0x32, 0x36, 0x20, 0x61, 0x72, 0x6D, 0x36, 0x34, 0x30]
|
||||
|
||||
// 45872025384@chatroom_176787000_60_xwechat_1 只需要改这个时间戳就能重复发送
|
||||
const receiverMsgId = stringToHexArray(receiverGlobal).concat([0x5F])
|
||||
const receiverMsgId = stringToHexArray(targetId).concat([0x5F])
|
||||
.concat(stringToHexArray(Math.floor(Date.now() / 1000).toString()))
|
||||
.concat([0x5F, 0x31, 0x36, 0x30, 0x5F, 0x78, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x5F, 0x33]);
|
||||
|
||||
@@ -645,9 +690,9 @@ function attachProto() {
|
||||
const senderHeader = [0x1A, senderGlobal.length + 2, 0x0A, senderGlobal.length];
|
||||
// wxid_xxxx 或者 chatroom
|
||||
const sender = stringToHexArray(senderGlobal);
|
||||
const receiverHeader = [0x22, receiverGlobal.length + 2, 0x0A, receiverGlobal.length]
|
||||
const receiverHeader = [0x22, targetId.length + 2, 0x0A, targetId.length]
|
||||
// wxid_xxxx
|
||||
const receiver = stringToHexArray(receiverGlobal)
|
||||
const receiver = stringToHexArray(targetId)
|
||||
const randomId1 = [0x28, 0xF4, 0x0B]
|
||||
const type1 = [0x30, 0x00]
|
||||
const randomId2 = [0x38, 0xF4, 0x0B]
|
||||
@@ -667,27 +712,27 @@ function attachProto() {
|
||||
|
||||
const cdnHeader = [0x58, 0x01, 0x60, 0x02, 0x68, 0x00, 0x7A, 0xB2, 0x01]
|
||||
// 3057 开头的cdn key
|
||||
const cdn = stringToHexArray(globalCdnKey);
|
||||
const cdn = stringToHexArray(cdnKey);
|
||||
|
||||
const cdn2Header = [0x82, 0x01, 0xB2, 0x01]
|
||||
const cdn2 = stringToHexArray(globalCdnKey)
|
||||
const cdn2 = stringToHexArray(cdnKey)
|
||||
|
||||
const aesKeyHeader = [0x8A, 0x01, 0x20]
|
||||
const aesKey = stringToHexArray(globalAesKey)
|
||||
const aesKeyBytes = stringToHexArray(aesKey)
|
||||
|
||||
const randomId5 = [0x90, 0x01, 0x01, 0x98, 0x01, 0xFF, // 0x2C8
|
||||
0x13, 0xA0, 0x01, 0xFF, 0x13]
|
||||
|
||||
const cdn3Header = [0xAA, 0x01, 0xB2, 0x01]
|
||||
const cdn3 = stringToHexArray(globalCdnKey)
|
||||
const cdn3 = stringToHexArray(cdnKey)
|
||||
|
||||
const randomId6 = [0xB0, 0x01, 0xF4, 0x0B]
|
||||
const randomId7 = [0xB8, 0x01, 0x68]
|
||||
const randomId8 = [0xC0, 0x01, 0x3A]
|
||||
const aesKey1Header = [0xCA, 0x01, 0x20]
|
||||
const aesKey1 = stringToHexArray(globalAesKey)
|
||||
const aesKey1 = stringToHexArray(aesKey)
|
||||
const md5Header = [0xDA, 0x01, 0x20]
|
||||
const me5Key = stringToHexArray(globalMd5Key)
|
||||
const me5Key = stringToHexArray(md5Key)
|
||||
|
||||
const randomId9 = [0xE0, 0x01, 0xd9, 0xe7, 0xc7, 0xF3, 0x02]
|
||||
|
||||
@@ -698,7 +743,7 @@ function attachProto() {
|
||||
|
||||
const finalPayload = type.concat(msgId, cpHeader, fileCp, randomId, sysHeader, sys, msgIdHeader, receiverMsgId,
|
||||
senderHeader, sender, receiverHeader, receiver, randomId1, type1, randomId2, randomId3, randomId4, htmlHeader, html,
|
||||
cdnHeader, cdn, cdn2Header, cdn2, aesKeyHeader, aesKey, randomId5, cdn3Header, cdn3, randomId6, randomId7, randomId8,
|
||||
cdnHeader, cdn, cdn2Header, cdn2, aesKeyHeader, aesKeyBytes, randomId5, cdn3Header, cdn3, randomId6, randomId7, randomId8,
|
||||
aesKey1Header, aesKey1, md5Header, me5Key, randomId9, left0)
|
||||
|
||||
imgProtoX1PayloadAddr.writeByteArray(finalPayload);
|
||||
@@ -728,7 +773,26 @@ function attachProto() {
|
||||
header: true,
|
||||
ansi: true
|
||||
}));
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
// 从视频队列获取上传信息
|
||||
const videoUploadInfo = getVideoUploadInfo();
|
||||
let cdnKey = "";
|
||||
let aesKey = "";
|
||||
let md5Key = "";
|
||||
let videoId = "";
|
||||
let targetId = "";
|
||||
|
||||
if (videoUploadInfo) {
|
||||
cdnKey = videoUploadInfo.cdnKey;
|
||||
aesKey = videoUploadInfo.aesKey;
|
||||
md5Key = videoUploadInfo.md5Key;
|
||||
videoId = videoUploadInfo.videoIdentity;
|
||||
targetId = videoUploadInfo.targetId;
|
||||
} else {
|
||||
console.error("[!] 无法获取视频上传信息");
|
||||
return;
|
||||
}
|
||||
|
||||
const type = [0x0A, 0x3f, 0x0A, 0x01, 0x00]
|
||||
@@ -741,7 +805,7 @@ function attachProto() {
|
||||
const sys = [0x55, 0x6E, 0x69, 0x66, 0x69, 0x65, 0x64, 0x50, 0x43, 0x4D, 0x61, 0x63, 0x20, 0x32, 0x36, 0x20, 0x61, 0x72, 0x6D, 0x36, 0x34]
|
||||
|
||||
// 注意:这里 sender 和 receiver 互换了
|
||||
const receiverMsgId = stringToHexArray(receiverGlobal).concat([0x5F])
|
||||
const receiverMsgId = stringToHexArray(targetId).concat([0x5F])
|
||||
.concat(stringToHexArray(Math.floor(Date.now() / 1000).toString()))
|
||||
.concat([0x5F, 0x31, 0x36, 0x30, 0x5F, 0x78, 0x77, 0x65, 0x63, 0x68, 0x61, 0x74, 0x5F, 0x31]);
|
||||
|
||||
@@ -751,9 +815,9 @@ function attachProto() {
|
||||
const senderHeader = [0x1A, senderGlobal.length];
|
||||
// sender 和 receiver 互换了,sender 是 wxid_ldftuhe36izg19
|
||||
const sender = stringToHexArray(senderGlobal);
|
||||
const receiverHeader = [0x22, receiverGlobal.length]
|
||||
const receiverHeader = [0x22, targetId.length]
|
||||
// receiver 是 wxid_7wd1ece99f7i21
|
||||
const receiver = stringToHexArray(receiverGlobal)
|
||||
const receiver = stringToHexArray(targetId)
|
||||
|
||||
const randomId1 = [0x28, 0xac, 0x73, 0x30, 0xac, 0x73, 0x3a, 0x04, 0x08, 0x00, 0x12, 0x00]
|
||||
const type1 = [0x40, 0xe8, 0xf2, 0x6f]
|
||||
@@ -771,37 +835,37 @@ function attachProto() {
|
||||
|
||||
const cdnHeader = [0x82, 0x01, 0xb2, 0x01]
|
||||
// 3057 开头的cdn key
|
||||
const cdn = stringToHexArray(globalCdnKey);
|
||||
const cdn = stringToHexArray(cdnKey);
|
||||
|
||||
const aesKeyHeader = [0x8A, 0x01, 0x20]
|
||||
const aesKey = stringToHexArray(globalAesKey)
|
||||
const aesKeyBytes = stringToHexArray(aesKey)
|
||||
|
||||
const randomId5 = [0x90, 0x01, 0x01, 0x9A, 0x01, 0xB2, 0x01]
|
||||
|
||||
const cdn2 = stringToHexArray(globalCdnKey)
|
||||
const cdn2 = stringToHexArray(cdnKey)
|
||||
|
||||
const randomId6 = [0xA0, 0x01, 0xAC, 0x73, 0xA8, 0x01, 0xE8, 0x02, 0xB0, 0x01, 0xCB, 0x01]
|
||||
|
||||
const aesKey1Header = [0xBA, 0x01, 0x20]
|
||||
const aesKey1 = stringToHexArray(globalAesKey)
|
||||
const aesKey1 = stringToHexArray(aesKey)
|
||||
|
||||
const md5Header = [0xd2, 0x01, 0x20]
|
||||
const md5Key = stringToHexArray(globalMd5Key)
|
||||
const md5KeyBytes = stringToHexArray(md5Key)
|
||||
|
||||
const md5Header1 = [0xAA, 0x02, 0x20]
|
||||
const md5Key1 = stringToHexArray(videoIdentity)
|
||||
const md5Key1 = stringToHexArray(videoId)
|
||||
|
||||
const randomId7 = [0xB0, 0x02, 0x00]
|
||||
|
||||
const md5Key2Header = [0x82, 0x03, 0x20]
|
||||
const md5Key2 = stringToHexArray(globalMd5Key)
|
||||
const md5Key2 = stringToHexArray(md5Key)
|
||||
|
||||
const cdn3Header = [0x8A, 0x03, 0xB2, 0x01]
|
||||
const cdn3 = stringToHexArray(globalCdnKey)
|
||||
const cdn3 = stringToHexArray(cdnKey)
|
||||
|
||||
const randomId8 = [0x92, 0x03, 0x20]
|
||||
|
||||
const md5Key3 = stringToHexArray(globalAesKey)
|
||||
const md5Key3 = stringToHexArray(aesKey)
|
||||
|
||||
var left0 = [
|
||||
0x98, 0x03, 0xe8, 0xf2, 0x6f
|
||||
@@ -809,7 +873,7 @@ function attachProto() {
|
||||
|
||||
const finalPayload = type.concat(msgId, cpHeader, fileCp, randomId, sysHeader, sys, msgIdHeader, receiverMsgId,
|
||||
senderHeader, sender, receiverHeader, receiver, randomId1, type1, randomId2, randomId3, randomId4, htmlHeader, html,
|
||||
cdnHeader, cdn, aesKeyHeader, aesKey, randomId5, cdn2, randomId6, aesKey1Header, aesKey1, md5Header, md5Key, md5Header1,
|
||||
cdnHeader, cdn, aesKeyHeader, aesKeyBytes, randomId5, cdn2, randomId6, aesKey1Header, aesKey1, md5Header, md5KeyBytes, md5Header1,
|
||||
md5Key1, randomId7, md5Key2Header, md5Key2, cdn3Header, cdn3, randomId8, md5Key3, left0)
|
||||
|
||||
videoProtoX1PayloadAddr.writeByteArray(finalPayload);
|
||||
@@ -1109,23 +1173,55 @@ function patchCdnOnComplete() {
|
||||
return
|
||||
}
|
||||
|
||||
globalCdnKey = x2.add(0x60).readPointer().readUtf8String();
|
||||
globalAesKey = x2.add(0x78).readPointer().readUtf8String();
|
||||
globalMd5Key = x2.add(0x90).readPointer().readUtf8String();
|
||||
videoIdentity = x2.add(0xf0).readPointer().readUtf8String();
|
||||
const cdnKey = x2.add(0x60).readPointer().readUtf8String();
|
||||
const aesKey = x2.add(0x78).readPointer().readUtf8String();
|
||||
const md5Key = x2.add(0x90).readPointer().readUtf8String();
|
||||
const videoId = x2.add(0xf0).readPointer().readUtf8String();
|
||||
const targetId = x2.add(0x40).readUtf8String();
|
||||
console.log("X2: " + x2 + "[+] globalCdnKey: " + globalCdnKey + " globalAesKey: " + globalAesKey +
|
||||
" globalMd5Key: " + globalMd5Key + " videoIdentity:" + videoIdentity);
|
||||
|
||||
console.log("X2: " + x2 + "[+] cdnKey: " + cdnKey + " aesKey: " + aesKey +
|
||||
" md5Key: " + md5Key + " videoId:" + videoId);
|
||||
|
||||
send({
|
||||
type: "finish",
|
||||
})
|
||||
});
|
||||
|
||||
if (globalCdnKey !== "" && globalCdnKey != null && globalAesKey !== "" && globalAesKey != null &&
|
||||
globalMd5Key !== "" && globalMd5Key != null) {
|
||||
send({
|
||||
type: "upload_finish",
|
||||
target_id: targetId,
|
||||
})
|
||||
if (cdnKey !== "" && cdnKey != null && aesKey !== "" && aesKey != null &&
|
||||
md5Key !== "" && md5Key != null) {
|
||||
|
||||
// 判断是图片还是视频,存入对应队列
|
||||
if (videoId !== null && videoId !== "") {
|
||||
// 视频
|
||||
pushVideoUploadInfo({
|
||||
cdnKey: cdnKey,
|
||||
aesKey: aesKey,
|
||||
md5Key: md5Key,
|
||||
videoIdentity: videoId,
|
||||
targetId: targetId
|
||||
});
|
||||
send({
|
||||
type: "upload_video_finish",
|
||||
target_id: targetId,
|
||||
cdn_key: cdnKey,
|
||||
aes_key: aesKey,
|
||||
md5_key: md5Key
|
||||
});
|
||||
} else {
|
||||
// 图片
|
||||
pushImageUploadInfo({
|
||||
cdnKey: cdnKey,
|
||||
aesKey: aesKey,
|
||||
md5Key: md5Key,
|
||||
targetId: targetId
|
||||
});
|
||||
send({
|
||||
type: "upload_image_finish",
|
||||
target_id: targetId,
|
||||
cdn_key: cdnKey,
|
||||
aes_key: aesKey,
|
||||
md5_key: md5Key
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.error("cdnKey or aesKey or md5key 为空")
|
||||
}
|
||||
|
||||
+18
-18
@@ -39,12 +39,6 @@ function setReceiver() {
|
||||
}
|
||||
|
||||
const x2 = this.context.x2.toInt32();
|
||||
console.log(" [+] currentPtr: ", hexdump(currentPtr, {
|
||||
offset: 0,
|
||||
length: x2,
|
||||
header: true,
|
||||
ansi: true
|
||||
}));
|
||||
const fields = getProtobufRawBytes(currentPtr, x2)
|
||||
|
||||
const sender = fields[0]
|
||||
@@ -57,14 +51,16 @@ function setReceiver() {
|
||||
|
||||
if (typeof sender !== "string" || sender === "" || typeof receiver !== "string" || receiver === "" ||
|
||||
typeof content !== "string" || content === "" || typeof msgId !== "string" || msgId === "") {
|
||||
console.log("字段缺失,无法解析 sender:" + sender + " receiver:" + receiver + hexdump(currentPtr, {
|
||||
length: x2,
|
||||
header: true,
|
||||
ansi: true,
|
||||
}))
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(" [+] currentPtr: ", hexdump(currentPtr, {
|
||||
offset: 0,
|
||||
length: x2,
|
||||
header: true,
|
||||
ansi: true
|
||||
}));
|
||||
|
||||
var selfId = receiver
|
||||
var msgType = "private"
|
||||
var groupId = ""
|
||||
@@ -202,12 +198,12 @@ function setReceiver() {
|
||||
var buffer = dataPtr.readByteArray(dataLen);
|
||||
var uint8Array = new Uint8Array(buffer);
|
||||
|
||||
send({
|
||||
type: "download",
|
||||
media: Array.from(uint8Array),
|
||||
file_id: fileId,
|
||||
cdn_url: cdnUrl,
|
||||
})
|
||||
// send({
|
||||
// type: "download",
|
||||
// media: Array.from(uint8Array),
|
||||
// file_id: fileId,
|
||||
// cdn_url: cdnUrl,
|
||||
// })
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -246,7 +242,9 @@ function getMessages(content, sender, mediaContent) {
|
||||
messages.push({type: "face", data: {text: part}});
|
||||
} else if (part.startsWith("<?xml version=\"1.0\"?><msg><videomsg")) {
|
||||
messages.push({type: "video", data: {text: part}});
|
||||
} else {
|
||||
} else if (part.startsWith("<sysmsg") || part.startsWith("<?xml version=\"1.0\"?><sysmsg")) {
|
||||
messages.push({type: "sys", data: {text: part}});
|
||||
} else {
|
||||
messages.push({type: "text", data: {text: part}});
|
||||
}
|
||||
}
|
||||
@@ -276,6 +274,8 @@ function getMessages(content, sender, mediaContent) {
|
||||
messages.push({type: "face", data: {text: content}});
|
||||
} else if (content.startsWith("<?xml version=\"1.0\"?><msg><videomsg")) {
|
||||
messages.push({type: "video", data: {text: content}});
|
||||
} else if (content.startsWith("<sysmsg") || content.startsWith("<?xml version=\"1.0\"?><sysmsg")) {
|
||||
messages.push({type: "sys", data: {text: content}});
|
||||
} else {
|
||||
messages.push({type: "text", data: {text: content}});
|
||||
}
|
||||
|
||||
+8
-5
@@ -37,6 +37,9 @@ func main() {
|
||||
|
||||
go func() {
|
||||
<-stop
|
||||
fridaScript.Clean()
|
||||
session.Clean()
|
||||
device.Clean()
|
||||
Fatal("正在释放 Frida 资源并退出...")
|
||||
}()
|
||||
|
||||
@@ -75,9 +78,10 @@ func initFlag() {
|
||||
}
|
||||
|
||||
func initFridaGadget() {
|
||||
var err error
|
||||
mgr := frida.NewDeviceManager()
|
||||
// 连接到 Gadget 默认端口
|
||||
device, err := mgr.AddRemoteDevice(config.FridaGadgetAddr, frida.NewRemoteDeviceOptions())
|
||||
device, err = mgr.AddRemoteDevice(config.FridaGadgetAddr, frida.NewRemoteDeviceOptions())
|
||||
if err != nil {
|
||||
Fatal("❌ 无法连接 Gadget", err)
|
||||
}
|
||||
@@ -92,11 +96,12 @@ func initFridaGadget() {
|
||||
}
|
||||
|
||||
func initFrida() {
|
||||
var err error
|
||||
// 1. 获取本地设备管理器
|
||||
mgr := frida.NewDeviceManager()
|
||||
|
||||
// 2. 枚举并获取本地设备 (TypeLocal)
|
||||
device, err := mgr.DeviceByType(frida.DeviceTypeLocal)
|
||||
device, err = mgr.DeviceByType(frida.DeviceTypeLocal)
|
||||
if err != nil {
|
||||
Fatal("无法获取本地设备", "err", err)
|
||||
}
|
||||
@@ -222,11 +227,9 @@ func loadJs() {
|
||||
}
|
||||
}
|
||||
case "log":
|
||||
// 这里处理 console.log
|
||||
Info("[JS日志]", "payload", msg["payload"])
|
||||
case "error":
|
||||
// 这里处理 JS 脚本报错
|
||||
Error("[JS日志报错]", "err", msg["description"])
|
||||
Error("[JS日志报错]", "err", msg["description"], "stack", msg["stack"])
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
var (
|
||||
fridaScript *frida.Script
|
||||
session *frida.Session
|
||||
device frida.DeviceInt
|
||||
taskId = int64(0x20000000)
|
||||
myWechatId = ""
|
||||
|
||||
|
||||
+16
-23
@@ -303,9 +303,9 @@ var videoProtobufDeleteAddr = videoCallbackFuncAddr.add(0x6c);
|
||||
var videoProtobufDeleteAddrByte;
|
||||
|
||||
var uploadImageAddr = baseAddr.add({{.uploadImageAddr}});
|
||||
var CndOnCompleteAddr = baseAddr.add({{.CndOnCompleteAddr}});
|
||||
var imgMessageCallbackFunc1 = baseAddr.add({{.imgMessageCallbackFunc1}});
|
||||
var videoMessageCallbackFunc1 = baseAddr.add({{.videoMessageCallbackFunc1}});
|
||||
var cndOnCompleteAddr = baseAddr.add({{.cndOnCompleteAddr}});
|
||||
var imgMessageCallbackFunc = baseAddr.add({{.imgMessageCallbackFunc}});
|
||||
var videoMessageCallbackFunc = baseAddr.add({{.videoMessageCallbackFunc}});
|
||||
|
||||
var uploadGetCallbackWrapperAddr = baseAddr.add({{.uploadGetCallbackWrapperAddr}});
|
||||
var uploadGetCallbackWrapperFuncAddr = baseAddr.add({{.uploadGetCallbackWrapperFuncAddr}});
|
||||
@@ -570,9 +570,7 @@ function triggerSendTextMessage(taskId, receiver, content, atUser) {
|
||||
|
||||
// 5. 调用函数
|
||||
try {
|
||||
const result = MMStartTask(triggerX0, triggerX1Payload);
|
||||
console.log(`[+] Execution MMStartTask ${sendFuncAddr} with args: (${triggerX0}) (${triggerX1Payload}) Success. Return value: ` + result);
|
||||
return "ok";
|
||||
return MMStartTask(triggerX0, triggerX1Payload);
|
||||
} catch (e) {
|
||||
console.error(`[!] Error trigger MMStartTask ${sendFuncAddr} with args: (${triggerX0}) (${triggerX1Payload}), during execution: ` + e);
|
||||
return "fail";
|
||||
@@ -753,7 +751,7 @@ function setupSendImgMessageDynamic() {
|
||||
sendImgMessageAddr.add(0x20).writeU32(taskIdGlobal);
|
||||
sendImgMessageAddr.add(0x28).writePointer(imgMessageAddr);
|
||||
|
||||
imgMessageAddr.add(0x00).writePointer(imgMessageCallbackFunc1);
|
||||
imgMessageAddr.add(0x00).writePointer(imgMessageCallbackFunc);
|
||||
imgMessageAddr.add(0x08).writeU32(taskIdGlobal);
|
||||
imgMessageAddr.add(0x0c).writeU32(0x6e);
|
||||
imgMessageAddr.add(0x10).writeU64(0x3);
|
||||
@@ -784,7 +782,7 @@ function setupSendImgMessageDynamic() {
|
||||
sendVideoMessageAddr.add(0x20).writeU32(taskIdGlobal);
|
||||
sendVideoMessageAddr.add(0x28).writePointer(videoMessageAddr);
|
||||
|
||||
videoMessageAddr.add(0x00).writePointer(videoMessageCallbackFunc1);
|
||||
videoMessageAddr.add(0x00).writePointer(videoMessageCallbackFunc);
|
||||
videoMessageAddr.add(0x08).writeU32(taskIdGlobal);
|
||||
videoMessageAddr.add(0x0c).writeU32(0x6e);
|
||||
videoMessageAddr.add(0x10).writeU64(0x3);
|
||||
@@ -982,9 +980,7 @@ function triggerSendImgMessage(taskId, sender, receiver) {
|
||||
|
||||
// 5. 调用函数
|
||||
try {
|
||||
const result = MMStartTask(triggerX0, triggerX1Payload);
|
||||
console.log(`[+] Execution StartTask ${sendFuncAddr} with args: (${triggerX0}) (${triggerX1Payload}) Success. Return value: ` + result);
|
||||
return "ok";
|
||||
return MMStartTask(triggerX0, triggerX1Payload);
|
||||
} catch (e) {
|
||||
console.error(`[!] Error trigger StartTask ${sendFuncAddr} with args: (${triggerX0}) (${triggerX1Payload}), during execution: ` + e);
|
||||
return "fail";
|
||||
@@ -1074,9 +1070,7 @@ function triggerSendVideoMessage(taskId, sender, receiver) {
|
||||
|
||||
// 5. 调用函数
|
||||
try {
|
||||
const result = MMStartTask(triggerX0, triggerX1Payload);
|
||||
console.log(`[+] Execution StartTask ${sendFuncAddr} with args: (${triggerX0}) (${triggerX1Payload}) Success. Return value: ` + result);
|
||||
return "ok";
|
||||
return MMStartTask(triggerX0, triggerX1Payload);
|
||||
} catch (e) {
|
||||
console.error(`[!] Error trigger StartTask ${sendFuncAddr} with args: (${triggerX0}) (${triggerX1Payload}), during execution: ` + e);
|
||||
return "fail";
|
||||
@@ -1434,8 +1428,7 @@ function triggerUploadImg(receiver, md5, imagePath) {
|
||||
const startUploadMedia = new NativeFunction(uploadImageAddr, 'int64', ['pointer', 'pointer']);
|
||||
|
||||
console.log(`开始手动触发 C2C 上传 X0 ${uploadGlobalX0}, X1: ${uploadImageX1}`);
|
||||
const result = startUploadMedia(uploadGlobalX0, uploadImageX1);
|
||||
console.log("调用结果: " + result);
|
||||
return startUploadMedia(uploadGlobalX0, uploadImageX1);
|
||||
}
|
||||
|
||||
function triggerUploadVideo(receiver, md5, videoPath) {
|
||||
@@ -1554,8 +1547,7 @@ function triggerUploadVideo(receiver, md5, videoPath) {
|
||||
|
||||
const startUploadMedia = new NativeFunction(uploadImageAddr, 'int64', ['pointer', 'pointer']);
|
||||
|
||||
const result = startUploadMedia(uploadGlobalX0, uploadVideoX1);
|
||||
console.log("调用结果: " + result);
|
||||
return startUploadMedia(uploadGlobalX0, uploadVideoX1);
|
||||
}
|
||||
|
||||
function attachUploadMedia() {
|
||||
@@ -1577,7 +1569,7 @@ setImmediate(attachUploadMedia);
|
||||
|
||||
|
||||
function patchCdnOnComplete() {
|
||||
Interceptor.attach(CndOnCompleteAddr, {
|
||||
Interceptor.attach(cndOnCompleteAddr, {
|
||||
onEnter: function (args) {
|
||||
|
||||
try {
|
||||
@@ -2041,10 +2033,7 @@ function triggerDownload(receiver, cdnUrl, aesKey, filePath, fileType) {
|
||||
downloadFileX1.add(0xa0).writeU32(fileType);
|
||||
|
||||
const startDwMedia = new NativeFunction(startDownloadMedia, 'int64', ['pointer', 'pointer']);
|
||||
const result = startDwMedia(downloadGlobalX0, downloadFileX1);
|
||||
|
||||
console.log("下载调用结果: " + result);
|
||||
return result;
|
||||
return startDwMedia(downloadGlobalX0, downloadFileX1);
|
||||
}
|
||||
|
||||
function getMessages(content, sender, mediaContent) {
|
||||
@@ -2076,6 +2065,8 @@ function getMessages(content, sender, mediaContent) {
|
||||
messages.push({type: "face", data: {text: part}});
|
||||
} else if (part.startsWith("<?xml version=\"1.0\"?><msg><videomsg")) {
|
||||
messages.push({type: "video", data: {text: part}});
|
||||
} else if (part.startsWith("<sysmsg") || part.startsWith("<?xml version=\"1.0\"?><sysmsg")) {
|
||||
messages.push({type: "sys", data: {text: part}});
|
||||
} else {
|
||||
messages.push({type: "text", data: {text: part}});
|
||||
}
|
||||
@@ -2106,6 +2097,8 @@ function getMessages(content, sender, mediaContent) {
|
||||
messages.push({type: "face", data: {text: content}});
|
||||
} else if (content.startsWith("<?xml version=\"1.0\"?><msg><videomsg")) {
|
||||
messages.push({type: "video", data: {text: content}});
|
||||
} else if (content.startsWith("<sysmsg") || content.startsWith("<?xml version=\"1.0\"?><sysmsg")) {
|
||||
messages.push({type: "sys", data: {text: content}});
|
||||
} else {
|
||||
messages.push({type: "text", data: {text: content}});
|
||||
}
|
||||
|
||||
+22
-1
@@ -25,6 +25,7 @@ func SendWorker() {
|
||||
Info("收到完成信号")
|
||||
case m, ok := <-msgChan:
|
||||
if !ok {
|
||||
Fatal("发送通道关闭")
|
||||
return
|
||||
}
|
||||
SendWechatMsg(m)
|
||||
@@ -35,7 +36,7 @@ func SendWorker() {
|
||||
func SendWechatMsg(m *SendMsg) {
|
||||
time.Sleep(time.Duration(config.SendInterval) * time.Millisecond)
|
||||
currTaskId := atomic.AddInt64(&taskId, 1)
|
||||
Info("📩 收到任务", "task_id", currTaskId)
|
||||
Info("📩 收到任务", "task_id", currTaskId, "", m.)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
@@ -54,6 +55,10 @@ func SendWechatMsg(m *SendMsg) {
|
||||
case "text":
|
||||
result := fridaScript.ExportsCall("triggerSendTextMessage", currTaskId, targetId, m.Content, m.AtUser)
|
||||
Info("📩 发送文本任务执行结果", "result", result, "task_id", currTaskId, "target_id", targetId, "at_user", m.AtUser)
|
||||
if result != "1" {
|
||||
Error("发送文本失败", "task_id", currTaskId, "target_id", targetId, "result", result)
|
||||
return
|
||||
}
|
||||
case "image":
|
||||
targetPath, md5Str, err := SaveBase64Image(m.Content)
|
||||
if err != nil {
|
||||
@@ -63,9 +68,17 @@ func SendWechatMsg(m *SendMsg) {
|
||||
|
||||
result := fridaScript.ExportsCall("triggerUploadImg", targetId, md5Str, targetPath)
|
||||
Info("📩 上传图片任务执行结果", "result", result, "target_id", targetId, "md5", md5Str, "path", targetPath)
|
||||
if result != "0" {
|
||||
Error("上传图片失败", "target_id", targetId, "md5", md5Str, "result", result)
|
||||
return
|
||||
}
|
||||
case "send_image":
|
||||
result := fridaScript.ExportsCall("triggerSendImgMessage", currTaskId, myWechatId, targetId)
|
||||
Info("📩 发送图片任务执行结果", "result", result, "task_id", currTaskId, "wechat_id", myWechatId, "target_id", targetId)
|
||||
if result != "1" {
|
||||
Error("上传图片失败", "task_id", currTaskId, "target_id", targetId, "result", result)
|
||||
return
|
||||
}
|
||||
case "video":
|
||||
targetPath, md5Str, err := SaveBase64Image(m.Content)
|
||||
if err != nil {
|
||||
@@ -75,9 +88,17 @@ func SendWechatMsg(m *SendMsg) {
|
||||
|
||||
result := fridaScript.ExportsCall("triggerUploadVideo", targetId, md5Str, targetPath)
|
||||
Info("📩 上传视频任务执行结果", "result", result, "target_id", targetId, "md5", md5Str, "path", targetPath)
|
||||
if result != "0" {
|
||||
Error("上传视频失败", "target_id", targetId, "md5", md5Str, "result", result)
|
||||
return
|
||||
}
|
||||
case "send_video":
|
||||
result := fridaScript.ExportsCall("triggerSendVideoMessage", currTaskId, myWechatId, targetId)
|
||||
Info("📩 发送视频任务执行结果", "result", result, "task_id", currTaskId, "wechat_id", myWechatId, "target_id", targetId)
|
||||
if result != "1" {
|
||||
Error("上传图片失败", "task_id", currTaskId, "target_id", targetId, "result", result)
|
||||
return
|
||||
}
|
||||
case "download":
|
||||
result := fridaScript.ExportsCall("triggerDownload", targetId, m.FIleCdnUrl, m.AesKey, m.FilePath, m.FileType)
|
||||
Info("📩 下载任务执行结果", "result", result, "task_id", currTaskId, "wechat_id", myWechatId, "target_id", targetId)
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
"req2bufEnterAddr": "0x36FC204",
|
||||
"req2bufExitAddr": "0x36FD3DC",
|
||||
"imageCallbackFuncAddr": "0x245D110",
|
||||
"imgMessageCallbackFunc1": "0x8790DD8",
|
||||
"imgMessageCallbackFunc": "0x8790DD8",
|
||||
"uploadImageAddr": "0x49459C8",
|
||||
"CndOnCompleteAddr": "0x36BAFC0",
|
||||
"cndOnCompleteAddr": "0x36BAFC0",
|
||||
"buf2RespAddr": "0x3721FA0",
|
||||
"uploadGetCallbackWrapperAddr": "0x491348C",
|
||||
"uploadGetCallbackWrapperFuncAddr": "0x36BA7DC",
|
||||
@@ -18,5 +18,5 @@
|
||||
"downloadFileAddr": "0x4A084EC",
|
||||
"downloadVideoAddr": "0x4A2A268",
|
||||
"videoCallbackFuncAddr": "0x24C76C8",
|
||||
"videoMessageCallbackFunc1": "0x8793B78"
|
||||
"videoMessageCallbackFunc": "0x8793B78"
|
||||
}
|
||||
Reference in New Issue
Block a user