debug_wechat_send9.js
4.89 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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/**
* 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.");
});