/**
 * 工作手机SDK - Frida Hook监听器
 * 目标：捕获微信8.0.56真实消息发送类名
 * 方法：Hook SQLite insert + Android.os.Handler + 调用栈分析
 */
'use strict';

var _foundSendClasses = [];
var _foundSnsClasses = [];
var _messageLog = [];
var _hookReady = false;

// ============================================================
// 工具函数
// ============================================================
function getStack() {
    try {
        var Exception = Java.use('java.lang.Exception');
        var e = Exception.$new();
        var stack = e.getStackTrace();
        var result = [];
        for (var i = 0; i < Math.min(stack.length, 20); i++) {
            var frame = stack[i];
            var cls = frame.getClassName();
            var method = frame.getMethodName();
            if (cls.indexOf('com.tencent.mm') !== -1) {
                result.push(cls + '.' + method);
            }
        }
        return result;
    } catch(e) {
        return ['stack_error: ' + e];
    }
}

// ============================================================
// Hook 1: SQLite insert - 捕获消息写入调用栈
// ============================================================
function hookSQLiteInsert() {
    var hooked = false;
    
    // 尝试多个SQLite类
    var sqliteClasses = [
        'com.tencent.wcdb.database.SQLiteDatabase',
        'net.sqlcipher.database.SQLiteDatabase',
        'android.database.sqlite.SQLiteDatabase'
    ];
    
    for (var i = 0; i < sqliteClasses.length; i++) {
        try {
            var SQLiteDB = Java.use(sqliteClasses[i]);
            var clsName = sqliteClasses[i];
            
            // Hook insert方法
            try {
                SQLiteDB.insert.overload('java.lang.String', 'java.lang.String', 'android.content.ContentValues').implementation = function(table, nullCol, values) {
                    var result = this.insert(table, nullCol, values);
                    if (table === 'message') {
                        try {
                            var isSend = values.getAsInteger('isSend');
                            if (isSend && parseInt(isSend.toString()) === 1) {
                                var content = values.getAsString('content');
                                var talker = values.getAsString('talker');
                                var stack = getStack();
                                _messageLog.push({
                                    type: 'message_insert',
                                    table: table,
                                    talker: talker,
                                    content: content ? content.substring(0, 100) : '',
                                    stack: stack,
                                    time: Date.now()
                                });
                                send({ type: 'message_insert', talker: talker, content: content ? content.substring(0, 50) : '', stack: stack.slice(0, 5) });
                            }
                        } catch(e2) {}
                    }
                    if (table === 'SnsInfo' || table === 'SnsComment') {
                        var stack = getStack();
                        _foundSnsClasses = stack;
                        send({ type: 'sns_insert', table: table, stack: stack.slice(0, 5) });
                    }
                    return result;
                };
                send({ type: 'hook_ok', msg: 'SQLite.insert hooked: ' + clsName });
                hooked = true;
            } catch(e) {
                send({ type: 'hook_fail', msg: clsName + '.insert: ' + e });
            }
            
            // Hook execSQL
            try {
                SQLiteDB.execSQL.overload('java.lang.String').implementation = function(sql) {
                    if (sql && sql.toLowerCase().indexOf('insert') !== -1 && sql.toLowerCase().indexOf('message') !== -1) {
                        var stack = getStack();
                        send({ type: 'execsql_message', sql: sql.substring(0, 100), stack: stack.slice(0, 5) });
                    }
                    return this.execSQL(sql);
                };
            } catch(e) {}
            
            break;
        } catch(e) {
            send({ type: 'hook_fail', msg: sqliteClasses[i] + ': ' + e.toString().substring(0, 100) });
        }
    }
    return hooked;
}

// ============================================================
// Hook 2: 尝试Hook已知的消息发送相关类
// ============================================================
function hookKnownClasses() {
    // 微信8.0.x常见的消息发送类（通过逆向分析得到的候选）
    var candidates = [
        // 8.0.50+ 版本
        { cls: 'com.tencent.mm.model.chat.ChatManager', method: 'sendTextMessage' },
        { cls: 'com.tencent.mm.model.chat.ChatManager', method: 'a' },
        { cls: 'com.tencent.mm.sdk.platformtools.Util', method: 'sendMessage' },
        // 通用模式
        { cls: 'com.tencent.mm.ui.chatting.ChattingUIFragment', method: 'sendTextMessage' },
        { cls: 'com.tencent.mm.ui.chatting.ChattingUIFragment', method: 'a' },
        // 消息服务
        { cls: 'com.tencent.mm.plugin.messenger.service.MessageService', method: 'sendMessage' },
        { cls: 'com.tencent.mm.plugin.messenger.service.MessageService', method: 'a' },
    ];
    
    var found = [];
    for (var i = 0; i < candidates.length; i++) {
        try {
            var cls = Java.use(candidates[i].cls);
            found.push(candidates[i].cls);
            send({ type: 'class_found', cls: candidates[i].cls });
        } catch(e) {
            // 不存在，跳过
        }
    }
    return found;
}

// ============================================================
// Hook 3: Hook Handler.dispatchMessage 捕获消息处理
// ============================================================
function hookHandlerDispatch() {
    try {
        var Handler = Java.use('android.os.Handler');
        Handler.dispatchMessage.implementation = function(msg) {
            this.dispatchMessage(msg);
        };
        // 不hook这个，太频繁
    } catch(e) {}
}

// ============================================================
// RPC接口
// ============================================================
rpc.exports = {
    // 获取捕获的日志
    getLogs: function() {
        return { messages: _messageLog, sns: _foundSnsClasses, send_classes: _foundSendClasses };
    },
    
    // 触发一次消息发送（用于捕获调用栈）
    triggerSendCapture: function(toId, content) {
        try {
            return Java.performNow(function() {
                // 方式1: 通过WCDB
                try {
                    var WCDBSQLite = Java.use('com.tencent.wcdb.database.SQLiteDatabase');
                    send({ type: 'wcdb_found', msg: 'WCDB SQLiteDatabase exists' });
                } catch(e) {
                    send({ type: 'wcdb_not_found', msg: String(e).substring(0, 100) });
                }
                
                // 方式2: 枚举ClassLoader
                var loaders = [];
                Java.enumerateClassLoaders({
                    onMatch: function(loader) {
                        loaders.push(loader.toString().substring(0, 80));
                    },
                    onComplete: function() {}
                });
                send({ type: 'classloaders', loaders: loaders });
                
                return { success: true, loaders_count: loaders.length };
            });
        } catch(e) {
            return { success: false, error: String(e) };
        }
    },
    
    // 用正确ClassLoader查找类
    findClassWithLoader: function(className) {
        try {
            return Java.performNow(function() {
                var found = false;
                var loaderInfo = [];
                Java.enumerateClassLoaders({
                    onMatch: function(loader) {
                        try {
                            var cls = loader.loadClass(className);
                            found = true;
                            loaderInfo.push({ loader: loader.toString().substring(0, 60), found: true });
                            send({ type: 'class_loader_found', cls: className, loader: loader.toString().substring(0, 60) });
                        } catch(e) {
                            loaderInfo.push({ loader: loader.toString().substring(0, 40), found: false });
                        }
                    },
                    onComplete: function() {}
                });
                return { success: found, class: className, loaders: loaderInfo };
            });
        } catch(e) {
            return { success: false, error: String(e) };
        }
    },
    
    // 批量查找类（用正确ClassLoader）
    findClassesBatch: function(classNames) {
        try {
            return Java.performNow(function() {
                var results = {};
                // 先找到包含微信类的ClassLoader
                var wechatLoader = null;
                Java.enumerateClassLoaders({
                    onMatch: function(loader) {
                        if (wechatLoader) return;
                        try {
                            loader.loadClass('com.tencent.mm.app.Application');
                            wechatLoader = loader;
                        } catch(e) {}
                    },
                    onComplete: function() {}
                });
                
                if (!wechatLoader) {
                    return { success: false, error: 'WeChat ClassLoader not found' };
                }
                
                send({ type: 'wechat_loader', loader: wechatLoader.toString().substring(0, 80) });
                
                for (var i = 0; i < classNames.length; i++) {
                    try {
                        var cls = wechatLoader.loadClass(classNames[i]);
                        var methods = cls.getDeclaredMethods();
                        var methodList = [];
                        for (var j = 0; j < methods.length; j++) {
                            var m = methods[j];
                            var params = m.getParameterTypes().map(function(p) { return p.getName(); });
                            methodList.push(m.getName() + '(' + params.join(',') + ')');
                        }
                        results[classNames[i]] = { exists: true, methods: methodList };
                    } catch(e) {
                        results[classNames[i]] = { exists: false };
                    }
                }
                return { success: true, results: results };
            });
        } catch(e) {
            return { success: false, error: String(e) };
        }
    },
    
    // 用正确ClassLoader发送消息
    sendMessageWithLoader: function(params) {
        try {
            return Java.performNow(function() {
                var toId = params.to_id;
                var content = params.content;
                
                // 找微信ClassLoader
                var wechatLoader = null;
                Java.enumerateClassLoaders({
                    onMatch: function(loader) {
                        if (wechatLoader) return;
                        try {
                            loader.loadClass('com.tencent.mm.app.Application');
                            wechatLoader = loader;
                        } catch(e) {}
                    },
                    onComplete: function() {}
                });
                
                if (!wechatLoader) return { success: false, error: 'no wechat loader' };
                
                // 尝试候选类
                var sendCandidates = [
                    { cls: 'com.tencent.mm.modelmulti.h', method: 'b' },
                    { cls: 'com.tencent.mm.modelmulti.g', method: 'b' },
                    { cls: 'com.tencent.mm.modelmulti.f', method: 'b' },
                    { cls: 'com.tencent.mm.modelmulti.e', method: 'b' },
                    { cls: 'com.tencent.mm.modelmulti.d', method: 'b' },
                    { cls: 'com.tencent.mm.modelmulti.c', method: 'b' },
                    { cls: 'com.tencent.mm.modelmulti.b', method: 'b' },
                    { cls: 'com.tencent.mm.modelmulti.a', method: 'b' },
                    { cls: 'com.tencent.mm.plugin.messenger.foundation.a.k', method: 'a' },
                    { cls: 'com.tencent.mm.plugin.messenger.foundation.a.j', method: 'a' },
                    { cls: 'com.tencent.mm.plugin.messenger.foundation.a.i', method: 'a' },
                    { cls: 'com.tencent.mm.plugin.messenger.foundation.a.h', method: 'a' },
                ];
                
                for (var i = 0; i < sendCandidates.length; i++) {
                    try {
                        var cls = wechatLoader.loadClass(sendCandidates[i].cls);
                        send({ type: 'candidate_found', cls: sendCandidates[i].cls });
                        
                        // 获取方法
                        var methods = cls.getDeclaredMethods();
                        var methodNames = [];
                        for (var j = 0; j < methods.length; j++) {
                            methodNames.push(methods[j].getName() + '(' + methods[j].getParameterTypes().length + ')');
                        }
                        send({ type: 'candidate_methods', cls: sendCandidates[i].cls, methods: methodNames });
                        
                        return { success: true, found_class: sendCandidates[i].cls, methods: methodNames };
                    } catch(e) {}
                }
                
                return { success: false, error: 'no send class found with loader' };
            });
        } catch(e) {
            return { success: false, error: String(e) };
        }
    }
};

// 启动Hook
Java.perform(function() {
    var hooked = hookSQLiteInsert();
    var found = hookKnownClasses();
    _hookReady = true;
    send({ type: 'ready', sqlite_hooked: hooked, known_classes: found });
});
