/** * Frida debug script v3 — trace WCDB insert to find real send API * Usage: frida -U -p PID -l debug_wechat_send3.js * Then manually send a message in WeChat UI, watch the stack trace */ var pendingStacks = []; function printStackTrace(tag) { var trace = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()); console.log("[" + tag + "] Stack trace:\n" + trace); } Java.perform(function () { console.log("[TRACE] Hooking WCDB insert..."); console.log("[TRACE] Now send a message manually in WeChat UI"); console.log("[TRACE] The stack trace will show the real send API path"); try { var SQLiteDatabase = Java.use("com.tencent.wcdb.database.SQLiteDatabase"); SQLiteDatabase.insert.overload('java.lang.String', 'java.lang.String', 'android.content.ContentValues').implementation = function(table, nullCol, values) { if (table && table.indexOf("message") !== -1) { var isSend = values.getAsInteger("isSend"); var talker = values.getAsString("talker"); var content = values.getAsString("content"); if (isSend && isSend == 1) { console.log("\n========== WCDB INSERT SEND =========="); console.log("talker=" + talker + " content=" + (content ? content.substring(0, 50) : "null")); printStackTrace("SEND"); console.log("=====================================\n"); } } return this.insert(table, nullCol, values); }; // Also hook execSQL for potential direct SQL execution SQLiteDatabase.execSQL.overload('java.lang.String').implementation = function(sql) { if (sql && sql.indexOf("message") !== -1 && sql.indexOf("INSERT") !== -1) { console.log("\n========== WCDB EXECSQL INSERT =========="); console.log("sql=" + sql.substring(0, 100)); printStackTrace("EXECSQL"); console.log("========================================\n"); } return this.execSQL(sql); }; // Hook NetScene related classes — search for any class with "dispatch" or "doScene" console.log("[TRACE] Hooks installed. Send a message manually now."); } catch (e) { console.log("[TRACE] Hook failed: " + e); } });