debug_builder_class.js
4.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/**
* 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);
}
});