fix image crash

This commit is contained in:
yincong
2026-03-12 09:28:13 +08:00
parent 405133b8dc
commit bcac8ae75d
6 changed files with 299 additions and 101 deletions
+3 -3
View File
@@ -667,13 +667,13 @@ function attachUploadMedia() {
Interceptor.attach(uploadImageAddr.add(0x10), {
onEnter: function (args) {
uploadGlobalX0 = this.context.x0;
const selfId = uploadImageX1.add(0x68).readUtf8String();
const imagePath = uploadImageX1.add(0xe0).readPointer().readUtf8String();
const selfId = this.context.x1.add(0x68).readUtf8String();
const imagePath = this.context.x1.add(0xe0).readPointer().readUtf8String();
send({
type: "upload",
self_id: selfId,
})
console.log("UploadMedia x0: " + uploadGlobalX0 + " x1: " + uploadImageX1 + " imagePath: " + imagePath + " selfId: " + selfId);
console.log("UploadMedia x0: " + uploadGlobalX0 + " imagePath: " + imagePath + " selfId: " + selfId);
}
})
}
+198 -49
View File
@@ -5,9 +5,29 @@ if (!baseAddr) {
var buf2RespAddr = baseAddr.add(0x3721FA0)
var downloadImagAddr = baseAddr.add(0x4A6975C)
var hdPicDownloadAddr = baseAddr.add(0x494652C)
var startDownloadMedia = baseAddr.add(0x494663C)
var downloadGlobalX0;
var downloadFileX1 = ptr(0)
var fileIdAddr = ptr(0)
var fileMd5Addr = ptr(0)
var downloadAesKeyAddr = ptr(0)
var filePathAddr = ptr(0)
var fileCdnUrlAddr = ptr(0)
// -------------------------接收消息分区-------------------------
function setupDownloadFileDynamic() {
downloadFileX1 = Memory.alloc(1624)
fileIdAddr = Memory.alloc(128)
fileMd5Addr = Memory.alloc(128)
downloadAesKeyAddr = Memory.alloc(128)
filePathAddr = Memory.alloc(256)
fileCdnUrlAddr = Memory.alloc(256)
}
setImmediate(setupDownloadFileDynamic)
function setReceiver() {
Interceptor.attach(buf2RespAddr, {
onEnter: function (args) {
@@ -118,21 +138,17 @@ function setReceiver() {
},
});
Interceptor.attach(hdPicDownloadAddr, {
Interceptor.attach(startDownloadMedia, {
onEnter: function (args) {
var fileIDAddr = this.context.x1.add(0x40).readPointer();
var fileId = fileIDAddr?.readUtf8String();
if (!fileId.endsWith("_1")) {
if (downloadGlobalX0) {
return
}
console.log(" [+] download file: ", fileId);
this.context.x1.add(0x148).writeByteArray([0xa0, 0x86, 0x01, 0x00]);
this.context.x1.add(0xA0).writeU32(0x02);
downloadGlobalX0 = this.context.x0;
console.log("downloadGlobalX0: " + downloadGlobalX0)
}
});
})
Interceptor.attach(downloadImagAddr, { // 建议使用函数起始地址或你计算出的偏移地址
Interceptor.attach(downloadImagAddr, {
onEnter: function (args) {
var dataPtr = this.context.x1;
var dataLen = this.context.x2.toInt32();
@@ -352,48 +368,181 @@ function protobufVarintToNumberString(uint8Array) {
return result.toString();
}
function patchString(addr, plainStr) {
const bytes = [];
for (let i = 0; i < plainStr.length; i++) {
bytes.push(plainStr.charCodeAt(i));
}
addr.writeByteArray(bytes);
addr.add(bytes.length).writeU8(0);
}
// -----------------------辅助函数-----------------------
// fileType: HdImage => 1,Image => 2, humbImage => 3, Video => 4, File => 5,
function triggerDownload(receiver, cdnUrl, aesKey, filePath, fileType) {
const downloadMediaPayload = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x30
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xF0, 0xB6, 0x4C, 0xFC, 0x0A, 0x00, 0x00, 0x00, // 0x40
0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x80, 0x10, 0x4B, 0xFA, 0x0A, 0x00, 0x00, 0x00, // 0x58
0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0xF0, 0xB3, 0x4C, 0xFC, 0x0A, 0x00, 0x00, 0x00, // 0x70
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x60, 0xC4, 0x2D, 0xFE, 0x0A, 0x00, 0x00, 0x00, // 0x88
0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90
0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, // 0x98
0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, // 0xa0
0x00, 0x00, 0x00, 0x00, 0x01, 0xAA, 0xAA, 0xAA, // 0xa8
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xb0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xc0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xd0
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xd8
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xe0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xf0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x100
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x110
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, // 0x128
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x11, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x148
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x00, 0x00, 0xAA, 0xAA, 0xAA, // 0x170
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, // 0x180
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, // 0x1a0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x22, 0x1A, 0xFE, 0x0A, 0x00, 0x00, 0x00, // 0x1d0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x1f0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x200
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x288
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x298
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2a0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x4F, 0x56, 0xFC, 0x0A, 0x00, 0x00, 0x00, // 0x2c0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x300
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, // 0x318
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x340
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, // 0x378
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, // 0x3e0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
patchString(fileIdAddr, receiver + "_" + String(Math.floor(Date.now() / 1000)) + "_" + Math.floor(Math.random() * 1001) + "_1");
patchString(fileCdnUrlAddr, cdnUrl)
patchString(downloadAesKeyAddr, aesKey)
patchString(filePathAddr, filePath);
downloadFileX1.writeByteArray(downloadMediaPayload);
downloadFileX1.add(0x40).writePointer(fileIdAddr);
downloadFileX1.add(0x58).writePointer(fileCdnUrlAddr);
downloadFileX1.add(0x70).writePointer(downloadAesKeyAddr);
downloadFileX1.add(0x88).writePointer(filePathAddr);
downloadFileX1.add(0xa0).writeU32(fileType);
const startDwMedia = new NativeFunction(startDownloadMedia, 'int64', ['pointer', 'pointer']);
const result = startDwMedia(downloadGlobalX0, downloadFileX1);
console.log("下载调用结果: " + result);
return result;
}
rpc.exports = {
triggerDownload: triggerDownload,
};
// -----------------------测试函数-------------------------
function testGetProtobufRawBytes() {
const rawMemoryData = [
0x08, 0x00, 0x12, 0xdc, 0x0f, 0x08, 0x01, 0x12, 0xd7, 0x0f, 0x08, 0x05, 0x12, 0xd2, 0x0f, 0x08,
0xcc, 0x0f, 0x12, 0xcc, 0x0f, 0x08, 0x85, 0xa0, 0xd5, 0xe8, 0x04, 0x12, 0x15, 0x0a, 0x13, 0x77,
0x78, 0x69, 0x64, 0x5f, 0x37, 0x77, 0x64, 0x31, 0x65, 0x63, 0x65, 0x39, 0x39, 0x66, 0x37, 0x69,
0x32, 0x31, 0x1a, 0x15, 0x0a, 0x13, 0x77, 0x78, 0x69, 0x64, 0x5f, 0x6c, 0x64, 0x66, 0x74, 0x75,
0x68, 0x65, 0x33, 0x36, 0x69, 0x7a, 0x67, 0x31, 0x39, 0x20, 0x22, 0x2a, 0xe6, 0x03, 0x0a, 0xe3,
0x03, 0x3c, 0x6d, 0x73, 0x67, 0x3e, 0x3c, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x6d, 0x73, 0x67, 0x20,
0x65, 0x6e, 0x64, 0x66, 0x6c, 0x61, 0x67, 0x3d, 0x22, 0x31, 0x22, 0x20, 0x63, 0x61, 0x6e, 0x63,
0x65, 0x6c, 0x66, 0x6c, 0x61, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x66, 0x6f, 0x72, 0x77, 0x61,
0x72, 0x64, 0x66, 0x6c, 0x61, 0x67, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65,
0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x3d, 0x22, 0x34, 0x22, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65,
0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3d, 0x22, 0x31, 0x31, 0x30, 0x30, 0x22, 0x20, 0x6c, 0x65,
0x6e, 0x67, 0x74, 0x68, 0x3d, 0x22, 0x31, 0x32, 0x35, 0x32, 0x22, 0x20, 0x62, 0x75, 0x66, 0x69,
0x64, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x61, 0x65, 0x73, 0x6b, 0x65, 0x79, 0x3d, 0x22, 0x37, 0x30,
0x66, 0x34, 0x31, 0x36, 0x37, 0x36, 0x63, 0x38, 0x31, 0x31, 0x34, 0x33, 0x62, 0x66, 0x33, 0x61,
0x38, 0x38, 0x36, 0x62, 0x33, 0x33, 0x38, 0x32, 0x33, 0x30, 0x62, 0x37, 0x38, 0x37, 0x22, 0x20,
0x76, 0x6f, 0x69, 0x63, 0x65, 0x75, 0x72, 0x6c, 0x3d, 0x22, 0x33, 0x30, 0x35, 0x32, 0x30, 0x32,
0x30, 0x31, 0x30, 0x30, 0x30, 0x34, 0x34, 0x62, 0x33, 0x30, 0x34, 0x39, 0x30, 0x32, 0x30, 0x31,
0x30, 0x30, 0x30, 0x32, 0x30, 0x34, 0x66, 0x36, 0x35, 0x63, 0x39, 0x63, 0x65, 0x30, 0x30, 0x32,
0x30, 0x33, 0x32, 0x66, 0x38, 0x30, 0x32, 0x39, 0x30, 0x32, 0x30, 0x34, 0x32, 0x35, 0x66, 0x38,
0x33, 0x64, 0x62, 0x37, 0x30, 0x32, 0x30, 0x34, 0x36, 0x39, 0x61, 0x31, 0x33, 0x38, 0x65, 0x30,
0x30, 0x34, 0x32, 0x34, 0x33, 0x38, 0x36, 0x31, 0x36, 0x34, 0x36, 0x33, 0x33, 0x35, 0x33, 0x36,
0x36, 0x36, 0x33, 0x33, 0x32, 0x64, 0x33, 0x37, 0x33, 0x30, 0x33, 0x33, 0x36, 0x36, 0x32, 0x64,
0x33, 0x34, 0x36, 0x36, 0x36, 0x36, 0x33, 0x30, 0x32, 0x64, 0x33, 0x39, 0x33, 0x38, 0x33, 0x36,
0x36, 0x34, 0x32, 0x64, 0x33, 0x30, 0x36, 0x32, 0x33, 0x33, 0x36, 0x32, 0x36, 0x32, 0x36, 0x32,
0x36, 0x32, 0x33, 0x31, 0x33, 0x32, 0x33, 0x38, 0x33, 0x38, 0x33, 0x37, 0x30, 0x32, 0x30, 0x34,
0x30, 0x31, 0x31, 0x38, 0x30, 0x30, 0x30, 0x66, 0x30, 0x32, 0x30, 0x31, 0x30, 0x30, 0x30, 0x34,
0x30, 0x30, 0x39, 0x61, 0x38, 0x35, 0x33, 0x65, 0x64, 0x61, 0x22, 0x20, 0x76, 0x6f, 0x69, 0x63,
0x65, 0x6d, 0x64, 0x35, 0x3d, 0x22, 0x22, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x6d, 0x73,
0x67, 0x69, 0x64, 0x3d, 0x22, 0x34, 0x39, 0x37, 0x35, 0x30, 0x66, 0x31, 0x61, 0x35, 0x31, 0x35,
0x61, 0x37, 0x64, 0x30, 0x35, 0x35, 0x63, 0x35, 0x66, 0x31, 0x38, 0x34, 0x32, 0x64, 0x32, 0x66,
0x66, 0x39, 0x37, 0x34, 0x30, 0x77, 0x78, 0x69, 0x64, 0x5f, 0x6c, 0x64, 0x66, 0x74, 0x75, 0x68,
0x65, 0x33, 0x36, 0x69, 0x7a, 0x67, 0x31, 0x39, 0x5f, 0x32, 0x33, 0x36, 0x5f, 0x31, 0x37, 0x37,
0x32, 0x31, 0x37, 0x33, 0x35, 0x33, 0x35, 0x22, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x75, 0x73, 0x65,
0x72, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x78, 0x69, 0x64, 0x5f, 0x37, 0x77, 0x64, 0x31,
0x65, 0x63, 0x65, 0x39, 0x39, 0x66, 0x37, 0x69, 0x32, 0x31, 0x22, 0x20, 0x2f, 0x3e, 0x3c, 0x2f,
0x6d, 0x73, 0x67, 0x3e, 0x30, 0x03, 0x38, 0x01, 0x42, 0xea, 0x09, 0x08, 0xe4, 0x09, 0x12, 0xe4
];
const rawMemoryData = [];
const pBuffer = {
// 模拟指针读取内存返回 ArrayBuffer
+1 -1
View File
@@ -13,7 +13,7 @@ func Download(rawMsg []byte) error {
return err
}
Info("下载文件", "file_id", downloadReq.FileID, "media_len", len(downloadReq.Media), "cdn_url", downloadReq.CDNURL[:20])
Info("下载文件", "file_id", downloadReq.FileID, "media_len", len(downloadReq.Media), "cdn_url", downloadReq.CDNURL[:30])
if downloadReqInter, ok := userID2FileMsgMap.Load(downloadReq.CDNURL); ok {
beforeDownloadReq := downloadReqInter.(*DownloadRequest)
beforeDownloadReq.Media = append(beforeDownloadReq.Media, downloadReq.Media...)
+1 -1
View File
@@ -3,7 +3,7 @@
### 使用方式和脚本基本一致:
1. 编译main.go或者直接下载编译好的onebot二进制文件
2. 如果不想关闭SIP直接使用,需要按gadget文档操作wechat的二进制,[文档](https://github.com/yincongcyincong/weixin-macos/tree/main/frida-gadget),需要找到自己的图片位置:./onebot -type=gadget -image_path='/Users/xx/Library/Containers/com.tencent.xinWeChat/Data/Documents/xwechat_files/wxid_xxx/temp/xxx/2026-01/Img/'
3. 如果关闭了SIP 直接使用pid即可,./onebot -wechat_pid=18835 -image_path='/Users/xxx/Library/Containers/com.tencent.xinWeChat/Data/Documents/xwechat_files/wxid_xxx/temp/xxx/2026-01/Img/'
3. 如果关闭了SIP 直接使用pid即可,./onebot -image_path='/Users/xxx/Library/Containers/com.tencent.xinWeChat/Data/Documents/xwechat_files/wxid_xxx/temp/xxx/2026-01/Img/'
4. 发送一张图片,如果失败证明已经patch成功,可以正常使用。
5. 启动onebot服务,默认监听127.0.0.1:58080,可以通过http接口发送消息。
6. 会把收到的消息通过 http://127.0.0.1:36060/onebot 其他参数可用./onebot -h查看
+95 -43
View File
@@ -108,17 +108,23 @@ function getProtobufRawBytes(pBuffer, scanSize) {
let bytesReadForLen = 0;
i = i + 1;
let lenNum = 0;
while (i < uint8Array.length) {
let b = uint8Array[i];
length |= (b & 0x7F) << shift;
bytesReadForLen++;
i++;
lenNum++;
if (!(b & 0x80)) break;
shift += 7;
}
// 2. 截取原始 Byte 数据
if (i + length <= uint8Array.length) {
let addNum = 0
if (targetTag === 0x12 || targetTag === 0x1A || targetTag === 0x2A) {
addNum = lenNum + 1;
}
let rawData = uint8Array.slice(i, i + length);
if (targetTag === 0x42) {
finalResults.push(rawData);
@@ -216,7 +222,7 @@ function protobufVarintToNumberString(uint8Array) {
let result = BigInt(0);
let shift = BigInt(0);
for (let i = 0; i < uint8Array.length; i++) {
for (let i = 0; i < uint8Array?.length; i++) {
const byte = uint8Array[i];
// 1. 取出低 7 位并累加到结果中
@@ -276,11 +282,16 @@ var sendMsgType = "";
var buf2RespAddr = baseAddr.add({{.buf2RespAddr}});
// 图片消息全局变量
var imageCallbackFuncAddr = baseAddr.add({{.imageCallbackFuncAddr}});
var imgProtobufAddr = imageCallbackFuncAddr.add(0x54);
var patchImgProtobufFunc1 = imageCallbackFuncAddr.add(0x10);
var patchImgProtobufFunc1Byte;
var patchImgProtobufFunc2 = imageCallbackFuncAddr.add(0x30);
var patchImgProtobufFunc2Byte;
var imgProtobufDeleteAddr = imageCallbackFuncAddr.add(0x6c);
var imgProtobufDeleteAddrByte;
var uploadImageAddr = baseAddr.add({{.uploadImageAddr}});
var imgProtobufAddr = baseAddr.add({{.imgProtobufAddr}});
var patchImgProtobufFunc1 = baseAddr.add({{.patchImgProtobufFunc1}})
var patchImgProtobufFunc2 = baseAddr.add({{.patchImgProtobufFunc2}});
var imgProtobufDeleteAddr = baseAddr.add({{.imgProtobufDeleteAddr}});
var CndOnCompleteAddr = baseAddr.add({{.CndOnCompleteAddr}});
var imgMessageCallbackFunc1 = baseAddr.add({{.imgMessageCallbackFunc1}});
var uploadGetCallbackWrapperAddr = baseAddr.add({{.uploadGetCallbackWrapperAddr}});
@@ -290,7 +301,7 @@ var uploadOnCompleteFuncAddr = baseAddr.add({{.uploadOnCompleteFuncAddr}});
var downloadImagAddr = baseAddr.add({{.downloadImagAddr}});
var hdPicDownloadAddr = baseAddr.add({{.hdPicDownloadAddr}})
var uploadImageX1;
var uploadImageX1 = ptr(0);
var imgCgiAddr = ptr(0);
var sendImgMessageAddr = ptr(0);
var imgMessageAddr = ptr(0);
@@ -414,7 +425,7 @@ function patchTextProtoBuf() {
setImmediate(patchTextProtoBuf);
function triggerSendTextMessage(taskId, receiver, content, atUser) {
console.log("[+] Manual Trigger Started...");
// console.log("[+] Manual Trigger Started...");
if (!taskId || !receiver || !content) {
console.error("[!] taskId or Receiver or Content is empty!");
return "fail";
@@ -494,7 +505,7 @@ function triggerSendTextMessage(taskId, receiver, content, atUser) {
triggerX1Payload.add(0x190).writePointer(triggerX1Payload.add(0x198));
sendMsgType = "text"
console.log("finished init payload")
// console.log("finished init payload")
const MMStartTask = new NativeFunction(sendFuncAddr, 'int64', ['pointer', 'pointer']);
// 5. 调用函数
@@ -666,6 +677,7 @@ function setupSendImgMessageDynamic() {
md5Addr = Memory.alloc(256);
uploadAesKeyAddr = Memory.alloc(256);
ImagePathAddr1 = Memory.alloc(256);
uploadImageX1 = Memory.alloc(1024);
// A. 写入字符串内容
patchString(imgCgiAddr, "/cgi-bin/micromsg-bin/uploadmsgimg");
@@ -696,39 +708,63 @@ function setupSendImgMessageDynamic() {
imgMessageAddr.add(0x30).writeU64(uint64("0x0000000001010100"));
console.log(" [+] Dynamic Memory Setup Complete. - Message Object: " + imgMessageAddr);
patchImgProtobufFunc1Byte = patchImgProtobufFunc1.readByteArray(4);
patchImgProtobufFunc2Byte = patchImgProtobufFunc2.readByteArray(4);
imgProtobufDeleteAddrByte = imgProtobufDeleteAddr.readByteArray(4);
}
setImmediate(setupSendImgMessageDynamic);
function patchImgProtoBuf() {
Memory.patchCode(patchImgProtobufFunc1, 4, code => {
const cw = new Arm64Writer(code, {pc: patchImgProtobufFunc1});
cw.putNop();
cw.flush();
});
Interceptor.attach(imageCallbackFuncAddr, {
onEnter: function (args) {
var firstValue = this.context.sp.add(0x10).readU32();
console.log("[+] 捕获到 ImageCallbackFunc 调用,firstValue", firstValue, "X1地址:", taskIdGlobal);
if (firstValue === taskIdGlobal) {
if (patchImgProtobufFunc1.readU32() !== 3573751839) {
Memory.patchCode(patchImgProtobufFunc1, 4, code => {
const cw = new Arm64Writer(code, {pc: patchImgProtobufFunc1});
cw.putNop();
cw.flush();
});
Memory.patchCode(patchImgProtobufFunc2, 4, code => {
const cw = new Arm64Writer(code, {pc: patchImgProtobufFunc2});
cw.putNop();
cw.flush();
});
Memory.patchCode(imgProtobufDeleteAddr, 4, code => {
const cw = new Arm64Writer(code, {pc: imgProtobufDeleteAddr});
cw.putNop();
cw.flush();
});
}
} else {
if (patchImgProtobufFunc1.readU32() === 3573751839) {
Memory.patchCode(patchImgProtobufFunc1, 4, code => {
const cw = new Arm64Writer(code, {pc: patchImgProtobufFunc1});
cw.putBytes(new Uint8Array(patchImgProtobufFunc1Byte));
cw.flush();
});
Memory.patchCode(patchImgProtobufFunc2, 4, code => {
const cw = new Arm64Writer(code, {pc: patchImgProtobufFunc2});
cw.putBytes(new Uint8Array(patchImgProtobufFunc2Byte));
cw.flush();
});
Memory.patchCode(imgProtobufDeleteAddr, 4, code => {
const cw = new Arm64Writer(code, {pc: imgProtobufDeleteAddr});
cw.putBytes(new Uint8Array(imgProtobufDeleteAddrByte));
cw.flush();
});
}
Memory.patchCode(patchImgProtobufFunc2, 4, code => {
const cw = new Arm64Writer(code, {pc: patchImgProtobufFunc2});
cw.putNop();
cw.flush();
});
Memory.patchCode(imgProtobufDeleteAddr, 4, code => {
const cw = new Arm64Writer(code, {pc: imgProtobufDeleteAddr});
cw.putNop();
cw.flush();
});
console.log("[+] Patching patchImgProtobufFunc1 " + patchImgProtobufFunc1 + " 成功." + "[+] Patching patchImgProtobufFunc2 " + patchImgProtobufFunc2 + " 成功."
+ " Patching imgProtobufDeleteAddr " + imgProtobufDeleteAddr + " 成功.");
}
}
})
}
setTimeout(function () {
console.log("[+] 2秒等待结束,准备执行 Patch...");
patchImgProtoBuf();
}, 2000);
setImmediate(patchImgProtoBuf);
function triggerSendImgMessage(taskId, sender, receiver) {
console.log("[+] Manual Trigger Started...");
@@ -747,7 +783,7 @@ function triggerSendImgMessage(taskId, sender, receiver) {
imgMessageAddr.add(0x08).writeU32(taskIdGlobal);
sendImgMessageAddr.add(0x20).writeU32(taskIdGlobal);
console.log("start init payload")
// console.log("start init payload")
const payloadData = [
0x6e, 0x00, 0x00, 0x00, // 0x00
@@ -832,6 +868,12 @@ function attachProto() {
Interceptor.attach(imgProtobufAddr, {
onEnter: function (args) {
var currTaskId = this.context.sp.add(0x30).readU32();
if (currTaskId !== taskIdGlobal) {
console.log(`[+] 拦截到非目标 currTaskId: ${currTaskId} taskIdGlobal: ${taskIdGlobal}`);
return
}
const type = [0x0A, 0x40, 0x0A, 0x01, 0x00]
const msgId = [0x10].concat(generateRandom5ByteVarint())
const cpHeader = [0x1A, 0x10]
@@ -914,12 +956,12 @@ function attachProto() {
this.context.x1 = imgProtoX1PayloadAddr;
this.context.x2 = ptr(finalPayload.length);
console.log("[+] 寄存器修改完成: X1=" + this.context.x1 + ", X2=" + this.context.x2, hexdump(imgProtoX1PayloadAddr, {
offset: 0,
length: 256,
header: true,
ansi: true
}));
// console.log("[+] 寄存器修改完成: X1=" + this.context.x1 + ", X2=" + this.context.x2, hexdump(imgProtoX1PayloadAddr, {
// offset: 0,
// length: 256,
// header: true,
// ansi: true
// }));
},
});
}
@@ -1040,14 +1082,13 @@ function attachUploadMedia() {
Interceptor.attach(uploadImageAddr.add(0x10), {
onEnter: function (args) {
uploadGlobalX0 = this.context.x0;
uploadImageX1 = this.context.x1;
const selfId = uploadImageX1.add(0x68).readUtf8String();
const imagePath = uploadImageX1.add(0xe0).readPointer().readUtf8String();
const selfId = this.context.x1.add(0x68).readUtf8String();
const imagePath = this.context.x1.add(0xe0).readPointer().readUtf8String();
send({
type: "upload",
self_id: selfId,
})
console.log("UploadMedia x0: " + uploadGlobalX0 + " x1: " + uploadImageX1 + " imagePath: " + imagePath + " selfId: " + selfId);
console.log("UploadMedia x0: " + uploadGlobalX0 + " imagePath: " + imagePath + " selfId: " + selfId);
}
})
}
@@ -1060,6 +1101,13 @@ function patchCdnOnComplete() {
try {
const x2 = this.context.x2;
const currentFileId = x2.add(0x20).readPointer().readUtf8String();
const fileId = imageIdAddr.readUtf8String();
if (currentFileId !== fileId) {
console.log("[-] CndOnComplete x2: " + x2 + " currentFileId: " + currentFileId + " fileId: " + fileId);
return
}
globalImageCdnKey = x2.add(0x60).readPointer().readUtf8String();
globalAesKey1 = x2.add(0x78).readPointer().readUtf8String();
globalMd5Key = x2.add(0x90).readPointer().readUtf8String();
@@ -1133,6 +1181,10 @@ function setReceiver() {
Interceptor.attach(buf2RespAddr, {
onEnter: function (args) {
const currentPtr = this.context.x1;
if (currentPtr.add(0).readU8() !== 0x08) {
return
}
let start = 0x1e;
let senderLen = currentPtr.add(start).readU8();
if (senderLen !== 0x14 && senderLen !== 0x13) {
+1 -4
View File
@@ -4,10 +4,7 @@
"sendFuncAddr": "0x47FE448",
"req2bufEnterAddr": "0x36FC204",
"req2bufExitAddr": "0x36FD3DC",
"imgProtobufAddr": "0x245D164",
"patchImgProtobufFunc1": "0x245D120",
"patchImgProtobufFunc2": "0x245D140",
"imgProtobufDeleteAddr": "0x245D17C",
"imageCallbackFuncAddr": "0x245D110",
"imgMessageCallbackFunc1": "0x8790DD8",
"uploadImageAddr": "0x49459C8",
"CndOnCompleteAddr": "0x36BAFC0",