/** * 微信8.0.56 类名发现脚本 * 通过ClassLoader枚举找到真实类名 */ 'use strict'; function getWechatLoader() { 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() {} }); return wechatLoader; } rpc.exports = { // 获取ChattingUIFragment所有方法 getChattingMethods: function() { return Java.performNow(function() { var loader = getWechatLoader(); if (!loader) return { error: 'no loader' }; try { var cls = loader.loadClass('com.tencent.mm.ui.chatting.ChattingUIFragment'); var methods = cls.getDeclaredMethods(); var result = []; for (var i = 0; i < methods.length; i++) { var m = methods[i]; var params = m.getParameterTypes().map(function(p) { return p.getName(); }); result.push({ name: m.getName(), params: params, ret: m.getReturnType().getName() }); } return { success: true, count: result.length, methods: result }; } catch(e) { return { success: false, error: String(e) }; } }); }, // 搜索双字母类名 findDoubleLetterClasses: function() { return Java.performNow(function() { var loader = getWechatLoader(); if (!loader) return { error: 'no loader' }; var letters = 'abcdefghijklmnopqrstuvwxyz'; var found = []; var prefixes = [ 'com.tencent.mm.modelmulti.', 'com.tencent.mm.plugin.messenger.foundation.a.', 'com.tencent.mm.plugin.messenger.foundation.b.', 'com.tencent.mm.plugin.messenger.foundation.c.', ]; for (var p = 0; p < prefixes.length; p++) { for (var i = 0; i < letters.length; i++) { for (var j = 0; j < letters.length; j++) { var clsName = prefixes[p] + letters[i] + letters[j]; try { var cls = loader.loadClass(clsName); var methods = cls.getDeclaredMethods(); var mNames = []; for (var k = 0; k < methods.length; k++) { var params = methods[k].getParameterTypes().map(function(t) { return t.getName(); }); mNames.push(methods[k].getName() + '(' + params.join(',') + ')'); } found.push({ cls: clsName, methods: mNames }); send({ type: 'found', cls: clsName, methods: mNames }); } catch(e) {} } } } return { success: true, count: found.length, found: found }; }); }, // Hook SQLite insert监听消息写入 hookMessageInsert: function() { try { var WCDB = Java.use('com.tencent.wcdb.database.SQLiteDatabase'); WCDB.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 Exception = Java.use('java.lang.Exception'); var ex = Exception.$new('stack capture'); var stack = ex.getStackTrace(); var stackInfo = []; for (var i = 0; i < Math.min(stack.length, 30); i++) { var frame = stack[i]; var cn = frame.getClassName(); if (cn.indexOf('com.tencent.mm') !== -1) { stackInfo.push(cn + '.' + frame.getMethodName() + ':' + frame.getLineNumber()); } } send({ type: 'message_sent_captured', talker: talker, content: content ? content.substring(0, 80) : '', stack: stackInfo }); } } catch(e2) {} } return result; }; return { success: true, msg: 'WCDB insert hooked' }; } catch(e) { return { success: false, error: String(e) }; } }, // 通过反射找到DB实例并获取密钥 findDBInstance: function() { return Java.performNow(function() { var loader = getWechatLoader(); if (!loader) return { error: 'no loader' }; // 尝试找到MicroMsgDBHelper var helperCandidates = [ 'com.tencent.mm.storage.MicroMsgDBHelper', 'com.tencent.mm.storage.DatabaseHelper', 'com.tencent.mm.storage.MicroMsgDB', 'com.tencent.mm.storage.db.MicroMsgDB', ]; var found = []; for (var i = 0; i < helperCandidates.length; i++) { try { var cls = loader.loadClass(helperCandidates[i]); var methods = cls.getDeclaredMethods(); var mNames = []; for (var j = 0; j < methods.length; j++) { mNames.push(methods[j].getName()); } found.push({ cls: helperCandidates[i], methods: mNames.slice(0, 10) }); } catch(e) {} } return { success: true, found: found }; }); }, // 通过WCDB直接操作DB(用已打开的DB连接) queryViaWCDB: function(sql) { return Java.performNow(function() { try { // 获取已打开的DB实例(通过Application的静态字段) var WCDB = Java.use('com.tencent.wcdb.database.SQLiteDatabase'); // 找到所有WCDB实例 var instances = []; Java.choose('com.tencent.wcdb.database.SQLiteDatabase', { onMatch: function(instance) { try { var path = instance.getPath(); instances.push({ path: path, open: instance.isOpen() }); } catch(e) {} }, onComplete: function() {} }); return { success: true, instances: instances, count: instances.length }; } catch(e) { return { success: false, error: String(e) }; } }); }, // 通过Java.choose找到已打开的DB并执行查询 executeOnOpenDB: function(sql) { return Java.performNow(function() { try { var results = []; var executed = false; Java.choose('com.tencent.wcdb.database.SQLiteDatabase', { onMatch: function(db) { if (executed) return; try { var path = db.getPath(); if (path && path.indexOf('EnMicroMsg') !== -1 && db.isOpen()) { // 执行查询 var cursor = db.rawQuery(sql, null); if (cursor) { var cols = cursor.getColumnNames(); while (cursor.moveToNext()) { var row = {}; for (var i = 0; i < cols.length; i++) { try { row[cols[i]] = cursor.getString(i); } catch(e) { row[cols[i]] = null; } } results.push(row); } cursor.close(); executed = true; send({ type: 'db_query_ok', path: path, rows: results.length }); } } } catch(e) { send({ type: 'db_query_err', error: String(e).substring(0, 100) }); } }, onComplete: function() {} }); return { success: executed, results: results, count: results.length }; } catch(e) { return { success: false, error: String(e) }; } }); }, // 通过Java.choose找到DB并INSERT消息 insertViaOpenDB: function(params) { return Java.performNow(function() { var toId = params.to_id; var content = params.content; try { var inserted = false; var dbPath = ''; Java.choose('com.tencent.wcdb.database.SQLiteDatabase', { onMatch: function(db) { if (inserted) return; try { var path = db.getPath(); if (path && path.indexOf('EnMicroMsg') !== -1 && db.isOpen()) { dbPath = path; var ContentValues = Java.use('android.content.ContentValues'); var cv = ContentValues.$new(); var now = Date.now(); cv.put('msgId', Java.use('java.lang.Long').$new(now)); cv.put('type', Java.use('java.lang.Integer').$new(1)); cv.put('isSend', Java.use('java.lang.Integer').$new(1)); cv.put('talker', toId); cv.put('content', content); cv.put('createTime', Java.use('java.lang.Long').$new(now)); cv.put('status', Java.use('java.lang.Integer').$new(2)); cv.put('imgPath', ''); var rowId = db.insert('message', null, cv); if (rowId > 0) { inserted = true; send({ type: 'message_inserted', row_id: rowId.toString(), path: path }); } } } catch(e) { send({ type: 'insert_err', error: String(e).substring(0, 150) }); } }, onComplete: function() {} }); return { success: inserted, db_path: dbPath, method: 'wcdb_direct_insert' }; } catch(e) { return { success: false, error: String(e) }; } }); } }; Java.perform(function() { send({ type: 'ready', msg: 'wechat_class_finder loaded' }); });