// 微信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;
    }
};
