136 lines
4.8 KiB
JavaScript
136 lines
4.8 KiB
JavaScript
// 微信8.0.56 消息真实发送Hook脚本
|
||
// 策略:Hook OkHttp网络层,捕获微信发送消息的真实HTTP请求,然后重放
|
||
|
||
'use strict';
|
||
|
||
var capturedSendRequests = [];
|
||
var sendClassFound = null;
|
||
var sendMethodFound = null;
|
||
var isReady = false;
|
||
|
||
// 等待微信完全初始化
|
||
Java.perform(function() {
|
||
|
||
// 1. Hook OkHttp3 - 捕获所有网络请求
|
||
try {
|
||
var OkHttpClient = Java.use('okhttp3.OkHttpClient');
|
||
var Request = Java.use('okhttp3.Request');
|
||
var RequestBody = Java.use('okhttp3.RequestBody');
|
||
|
||
// Hook newCall
|
||
OkHttpClient.newCall.implementation = function(request) {
|
||
var url = request.url().toString();
|
||
if (url.indexOf('weixin') > -1 || url.indexOf('tencent') > -1 || url.indexOf('wx') > -1) {
|
||
var method = request.method();
|
||
var body = '';
|
||
try {
|
||
var rb = request.body();
|
||
if (rb != null) {
|
||
var buf = Java.use('okio.Buffer').$new();
|
||
rb.writeTo(buf);
|
||
body = buf.readUtf8();
|
||
}
|
||
} catch(e) {}
|
||
|
||
capturedSendRequests.push({
|
||
url: url,
|
||
method: method,
|
||
body: body.substring(0, 500),
|
||
time: Date.now()
|
||
});
|
||
|
||
if (capturedSendRequests.length > 50) {
|
||
capturedSendRequests.shift();
|
||
}
|
||
}
|
||
return this.newCall(request);
|
||
};
|
||
send({type: 'log', data: '[OK] OkHttp3 hooked'});
|
||
} catch(e) {
|
||
send({type: 'log', data: '[SKIP] OkHttp3: ' + e.message});
|
||
}
|
||
|
||
// 2. Hook 微信MMServiceManager - 找到消息发送服务
|
||
try {
|
||
var MMServiceManager = Java.use('com.tencent.mm.sdk.platformtools.MMServiceManager');
|
||
send({type: 'log', data: '[OK] MMServiceManager found'});
|
||
} catch(e) {
|
||
send({type: 'log', data: '[SKIP] MMServiceManager: ' + e.message});
|
||
}
|
||
|
||
// 3. Hook XMPP/MMProtocol - 微信自定义协议
|
||
var xmppClasses = [
|
||
'com.tencent.mm.protocal.MMProtocal',
|
||
'com.tencent.mm.protocal.b',
|
||
'com.tencent.mm.network.MMNetworkService',
|
||
'com.tencent.mm.network.b',
|
||
'com.tencent.mm.xmpp.XMPPService',
|
||
];
|
||
|
||
xmppClasses.forEach(function(cls) {
|
||
try {
|
||
Java.use(cls);
|
||
send({type: 'log', data: '[FOUND] ' + cls});
|
||
} catch(e) {}
|
||
});
|
||
|
||
// 4. 扫描所有已加载的类,找到包含"sendMsg"或"sendMessage"的类
|
||
// 使用精准枚举而不是全量扫描
|
||
var targetPatterns = [
|
||
'com.tencent.mm.model',
|
||
'com.tencent.mm.messenger',
|
||
'com.tencent.mm.modelmulti',
|
||
];
|
||
|
||
// 5. Hook SQLiteDatabase.execSQL - 捕获消息写入时的调用栈
|
||
try {
|
||
var WCDB = Java.use('com.tencent.wcdb.database.SQLiteDatabase');
|
||
|
||
WCDB.execSQL.overload('java.lang.String').implementation = function(sql) {
|
||
if (sql && sql.indexOf('message') > -1 && sql.indexOf('INSERT') > -1) {
|
||
var stack = Java.use('android.util.Log').getStackTraceString(
|
||
Java.use('java.lang.Exception').$new('STACK')
|
||
);
|
||
send({type: 'msg_insert_stack', data: {sql: sql.substring(0, 200), stack: stack.substring(0, 2000)}});
|
||
}
|
||
return this.execSQL(sql);
|
||
};
|
||
send({type: 'log', data: '[OK] WCDB.execSQL hooked'});
|
||
} catch(e) {
|
||
send({type: 'log', data: '[SKIP] WCDB.execSQL: ' + e.message});
|
||
}
|
||
|
||
// 6. Hook insert方法
|
||
try {
|
||
var WCDB2 = Java.use('com.tencent.wcdb.database.SQLiteDatabase');
|
||
WCDB2.insert.overload('java.lang.String', 'java.lang.String', 'android.content.ContentValues').implementation = function(table, nullColumnHack, values) {
|
||
if (table && table.indexOf('message') > -1) {
|
||
var stack = Java.use('android.util.Log').getStackTraceString(
|
||
Java.use('java.lang.Exception').$new('STACK')
|
||
);
|
||
send({type: 'msg_insert_stack', data: {table: table, stack: stack.substring(0, 3000)}});
|
||
}
|
||
return this.insert(table, nullColumnHack, values);
|
||
};
|
||
send({type: 'log', data: '[OK] WCDB.insert hooked'});
|
||
} catch(e) {
|
||
send({type: 'log', data: '[SKIP] WCDB.insert: ' + e.message});
|
||
}
|
||
|
||
isReady = true;
|
||
send({type: 'ready', data: 'Hook脚本已就绪,请在手机上发送一条微信消息'});
|
||
});
|
||
|
||
rpc.exports = {
|
||
getCapturedRequests: function() {
|
||
return capturedSendRequests;
|
||
},
|
||
isReady: function() {
|
||
return isReady;
|
||
},
|
||
clearRequests: function() {
|
||
capturedSendRequests = [];
|
||
return true;
|
||
}
|
||
};
|