/** * Debug script: verify builder class name when calling u01.r1.a("yibooo") * * Run on Mac: * frida -U -n com.tencent.mm -l debug_builder_class.js * * This script will: * 1. Call u01.r1.a("yibooo") and print builder.getClass().getName() * 2. Print builder class hierarchy * 3. Test method calls via both builder.getClass() and Java.use("u01.q1") * 4. Check if setIntField("f", 0) / ("i", 4) causes any issue */ function log(msg) { console.log("[DebugBuilder] " + msg); } Java.perform(function () { var toUser = "yibooo"; var content = "test msg from frida debug"; try { var r1 = Java.use("u01.r1"); var builder = r1.a(toUser); var builderClass = builder.getClass(); var className = builderClass.getName(); log("builder.getClass().getName() = " + className); // Print hierarchy var superClass = builderClass.getSuperclass(); while (superClass) { log(" extends: " + superClass.getName()); superClass = superClass.getSuperclass(); } // Check if it's exactly u01.q1 or a subclass var isExactQ1 = (className === "u01.q1"); log("Is exactly u01.q1? " + isExactQ1); // List all declared methods of the actual class var methods = builderClass.getDeclaredMethods(); log("Declared methods on " + className + ":"); for (var i = 0; i < methods.length; i++) { var m = methods[i]; if (m.getName() === "e" || m.getName() === "h" || m.getName() === "a") { log(" " + m.getName() + "(" + m.getParameterTypes().map(function(t){return t.getName();}).join(", ") + ") -> " + m.getReturnType().getName()); } } // Test 1: Call via builder.getClass().getMethod() (same as LSPosed) log("\n--- Test 1: builder.getClass().getMethod() ---"); try { var m_e = builderClass.getMethod("e", java.lang.String.class); var m_h = builderClass.getMethod("h", java.lang.Integer.TYPE); var m_a = builderClass.getMethod("a"); m_e.invoke(builder, content); log(" e() OK"); m_h.invoke(builder, 0); log(" h(0) OK"); // Try setIntField equivalent via reflection try { var f_field = builderClass.getDeclaredField("f"); f_field.setAccessible(true); f_field.setInt(builder, 0); log(" set f=0 OK"); } catch (f_err) { log(" set f=0 FAILED: " + f_err); } try { var i_field = builderClass.getDeclaredField("i"); i_field.setAccessible(true); i_field.setInt(builder, 4); log(" set i=4 OK"); } catch (i_err) { log(" set i=4 FAILED: " + i_err); } var result1 = m_a.invoke(builder); log(" a() result class: " + result1.getClass().getName()); var submit1 = result1.getClass().getMethod("a"); var ret1 = submit1.invoke(result1); log(" submit result: " + ret1); } catch (e) { log("Test 1 FAILED: " + e); if (e.getCause) log(" cause: " + e.getCause()); } // Test 2: Call via Java.use("u01.q1") (same as working frida code) log("\n--- Test 2: Java.use(\"u01.q1\") ---"); try { var builder2 = r1.a(toUser); var q1 = Java.use("u01.q1"); q1.e.call(builder2, content); log(" q1.e() OK"); q1.h.call(builder2, 0); log(" q1.h(0) OK"); var result2 = q1.a.call(builder2); log(" q1.a() result class: " + result2.getClass().getName()); var m1cls = Java.use("u01.m1"); var ret2 = m1cls.a.call(result2); log(" submit result: " + ret2); } catch (e) { log("Test 2 FAILED: " + e); } log("\n--- Done ---"); } catch (e) { log("Overall FAILED: " + e); } });