debug_wechat_send9.js 4.89 KB
/**
 * Frida debug script v9 — trace u01.r1, u01.q1, u01.m1 during manual send
 * Also trace a2 methods and WCDB to confirm the real path
 */

function log(tag, msg) {
    console.log("[" + tag + "] " + msg);
}

function printStack(tag) {
    try {
        var Thread = Java.use("java.lang.Thread");
        var stack = Thread.currentThread().getStackTrace();
        var lines = [];
        for (var i = 0; i < stack.length; i++) {
            lines.push("  at " + stack[i].toString());
        }
        console.log("[" + tag + " STACK]\n" + lines.join("\n") + "\n[END STACK]");
    } catch (e) {
        console.log("[" + tag + " STACK] failed: " + e + "\n[END STACK]");
    }
}

Java.perform(function () {
    log("MAIN", "Tracing u01.r1/q1/m1 and a2 during manual send...");

    // Hook u01.r1.a(String)
    try {
        var r1 = Java.use("u01.r1");
        r1.a.overload("java.lang.String").implementation = function(toUser) {
            log("R1", "u01.r1.a(\"" + toUser + "\") called");
            printStack("R1");
            return this.a(toUser);
        };
        log("MAIN", "u01.r1.a(String) hooked");
    } catch (e) {
        log("MAIN", "u01.r1 hook failed: " + e);
    }

    // Hook u01.q1.e(String) content setter
    try {
        var q1 = Java.use("u01.q1");
        q1.e.overload("java.lang.String").implementation = function(content) {
            log("Q1", "u01.q1.e(\"" + content.substring(0, 30) + "\") called");
            printStack("Q1_E");
            return this.e(content);
        };
        log("MAIN", "u01.q1.e(String) hooked");
    } catch (e) {
        log("MAIN", "u01.q1.e hook failed: " + e);
    }

    // Hook u01.q1.a() build method
    try {
        var q1 = Java.use("u01.q1");
        q1.a.overload().implementation = function() {
            log("Q1", "u01.q1.a() build called");
            printStack("Q1_A");
            return this.a();
        };
        log("MAIN", "u01.q1.a() hooked");
    } catch (e) {
        log("MAIN", "u01.q1.a() hook failed: " + e);
    }

    // Hook u01.m1.a() submit method
    try {
        var m1 = Java.use("u01.m1");
        m1.a.overload().implementation = function() {
            log("M1", "u01.m1.a() called");
            printStack("M1");
            return this.a();
        };
        log("MAIN", "u01.m1.a() hooked");
    } catch (e) {
        log("MAIN", "u01.m1.a() hook failed: " + e);
    }

    // Hook a2.b() which was in the real send stack
    try {
        var a2 = Java.use("com.tencent.mm.plugin.messenger.foundation.a2");
        a2.b.overload("com.tencent.mm.modelbase.p0", "f35.pu4", "ef3.z4").implementation = function(p0, pu4, z4) {
            log("A2", "a2.b() called");
            printStack("A2_B");
            return this.b(p0, pu4, z4);
        };
        log("MAIN", "a2.b() hooked");
    } catch (e) {
        log("MAIN", "a2.b() hook failed: " + e);
    }

    // Hook a2.c()
    try {
        var a2 = Java.use("com.tencent.mm.plugin.messenger.foundation.a2");
        a2.c.overload("f35.i4", "java.lang.Object", "int", "f35.pu4", "ef3.z4").implementation = function(i4, obj, i, pu4, z4) {
            log("A2", "a2.c() called");
            printStack("A2_C");
            return this.c(i4, obj, i, pu4, z4);
        };
        log("MAIN", "a2.c() hooked");
    } catch (e) {
        log("MAIN", "a2.c() hook failed: " + e);
    }

    // Hook az0.l.l() which was in the real stack
    try {
        var l_cls = Java.use("az0.l");
        var methods = l_cls.class.getDeclaredMethods();
        for (var i = 0; i < methods.length; i++) {
            var m = methods[i];
            if (m.getName() === "l" && m.getModifiers() & 0x0001) {
                var params = m.getParameterTypes();
                var sig = "";
                for (var j = 0; j < params.length; j++) {
                    sig += params[j].getName() + ",";
                }
                log("MAIN", "az0.l.l() signature: (" + sig + ")");
                break;
            }
        }
    } catch (e) {
        log("MAIN", "az0.l inspect failed: " + e);
    }

    // Hook WCDB insert
    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.toLowerCase().indexOf("message") !== -1) {
                var isSend = values ? values.getAsInteger("isSend") : null;
                var talker = values ? values.getAsString("talker") : null;
                if (isSend && isSend == 1) {
                    log("WCDB", "INSERT SEND talker=" + talker);
                    printStack("WCDB_SEND");
                }
            }
            return this.insert(table, nullCol, values);
        };
        log("MAIN", "WCDB hooked");
    } catch (e) {
        log("MAIN", "WCDB hook failed: " + e);
    }

    log("MAIN", "All hooks installed. Send a message manually.");
});