首先我使用了一个叫objection的东西。
列出了他所有的活动界面,列出来之后在慢慢筛选。
然后用了一个命令,就是可以跳到这个活动界面的命令。
我就确定了这个活动界面的位置,然后我就采取了objection的另一种栈追踪。
追踪到了这个地方。
先打印出具有特征参数的值,在从里面筛选。
Java.perform(function() {
// 获取 MsgUIData 类的引用
var MsgUIData = Java.use('com.xingin.chatbase.bean.MsgUIData');
// 获取该类所有的方法
var methods = MsgUIData.class.getDeclaredMethods();
methods.forEach(function(method) {
var methodName = method.getName();
console.log('Found method: ' + methodName);
// 钩取每个方法并打印日志
try {
var overloads = MsgUIData[methodName].overloads;
overloads.forEach(function(overload) {
overload.implementation = function() {
// 打印方法名及参数
console.log('Method called: ' + methodName + ' with args: ' + JSON.stringify(arguments));
// 调用原始方法
return overload.apply(this, arguments);
};
});
} catch (e) {
console.log('Error hooking ' + methodName + ': ' + e.message);
}
});
});
com.xingin.chatbase.bean.MsgUIData进行hook一下这些
//Method called: setStrMsg with args: {"0":"VCG范丞丞"}
//Method called: setMsgUUID with args: {"0":"51df9f21-fbb2-4714-8488-12ad58c1b1da"}
//Method called: setMsgId with args: {"0":"612368ee000000000101cd0c.62e7a0e6000000001f0077b5.1e79083a71bc144"}
//Method called: setStoreId with args: {"0":241}
//Method called: setCreatTime with args: {"0":"1737524135432"}
//Method called: setShowTime with args: {"0":"刚刚"}
//Method called: setMsgType with args: {"0":1}
//Method called: setSenderId with args: {"0":"612368ee000000000101cd0c"}
//Method called: setReceiverId with args: {"0":"62e7a0e6000000001f0077b5"}
//Method called: setChatId with args: {"0":"612368ee000000000101cd0c"}
//Method called: setLocalChatId with args: {"0":"612368ee000000000101cd0c@62e7a0e6000000001f0077b5"}
Java.perform(function() {
// 获取 MsgUIData 类的引用
var MsgUIData = Java.use('com.xingin.chatbase.bean.MsgUIData');
// 钩取 setStrMsg 方法
MsgUIData.setStrMsg.implementation = function(arg0) {
console.log('方法调用: setStrMsg 参数: ' + arg0);
return this.setStrMsg(arg0); // 调用原方法
};
// 钩取 setMsgUUID 方法
MsgUIData.setMsgUUID.implementation = function(arg0) {
console.log('方法调用: setMsgUUID 参数: ' + arg0);
return this.setMsgUUID(arg0); // 调用原方法
};
// 钩取 setMsgId 方法
MsgUIData.setMsgId.implementation = function(arg0) {
console.log('方法调用: setMsgId 参数: ' + arg0);
return this.setMsgId(arg0); // 调用原方法
};
// 钩取 setStoreId 方法
MsgUIData.setStoreId.implementation = function(arg0) {
console.log('方法调用: setStoreId 参数: ' + arg0);
return this.setStoreId(arg0); // 调用原方法
};
// 钩取 setCreatTime 方法
MsgUIData.setCreatTime.implementation = function(arg0) {
console.log('方法调用: setCreatTime 参数: ' + arg0);
return this.setCreatTime(arg0); // 调用原方法
};
// 钩取 setShowTime 方法
MsgUIData.setShowTime.implementation = function(arg0) {
console.log('方法调用: setShowTime 参数: ' + arg0);
return this.setShowTime(arg0); // 调用原方法
};
// 钩取 setMsgType 方法
MsgUIData.setMsgType.implementation = function(arg0) {
console.log('方法调用: setMsgType 参数: ' + arg0);
return this.setMsgType(arg0); // 调用原方法
};
// 钩取 setSenderId 方法
MsgUIData.setSenderId.implementation = function(arg0) {
console.log('方法调用: setSenderId 参数: ' + arg0);
return this.setSenderId(arg0); // 调用原方法
};
// 钩取 setReceiverId 方法
MsgUIData.setReceiverId.implementation = function(arg0) {
console.log('方法调用: setReceiverId 参数: ' + arg0);
return this.setReceiverId(arg0); // 调用原方法
};
// 钩取 setChatId 方法
MsgUIData.setChatId.implementation = function(arg0) {
console.log('方法调用: setChatId 参数: ' + arg0);
return this.setChatId(arg0); // 调用原方法
};
// 钩取 setLocalChatId 方法
MsgUIData.setLocalChatId.implementation = function(arg0) {
console.log('方法调用: setLocalChatId 参数: ' + arg0);
return this.setLocalChatId(arg0); // 调用原方法
};
});
这个代码是接收到消息的代码
Java.perform(function() {
var MsgUIData = Java.use('com.xingin.chatbase.bean.MsgUIData');
// 钩取 setStrMsg 方法的指定重载
MsgUIData.setStrMsg.overload('java.lang.String').implementation = function(arg0) {
console.log('方法调用: setStrMsg 参数: ' + arg0);
return this.setStrMsg(arg0);
};
});
追逐这个发送消息的栈
Java.perform(function() {
var MsgUIData = Java.use('com.xingin.chatbase.bean.MsgUIData');
MsgUIData.setStrMsg.implementation = function(str) {
console.log('调用栈: ' + Java.use('android.util.Log').getStackTraceString(Java.use('java.lang.Exception').$new()));
console.log('原始消息值: ' + str);
return this.setStrMsg(str);
};
});
我从那个MsgUIData写了一个栈 就是上面的那个代码 我在想,这个消息只能在UI那个界面停留才会收到,原数据会把这个消息传进UI里面,所以我就写了一个栈,然后一路找到了这个位置。
我阅读了一下代码,然后发现这个地方最可疑。
于是我点击了这个getContent()然后进去了,跳转到了另一个页面。
就是这个页面。
然后我就写了一个遍历这个地方的一个方法。
Java.perform(function () {
// 获取 MsgContentBean 类
var MsgContentBean = Java.use('com.xingin.chatbase.bean.MsgContentBean');
// 获取 MsgContentBean 类中的所有方法
var methods = MsgContentBean.class.getDeclaredMethods();
methods.forEach(function (method) {
var methodName = method.getName();
console.log("Hooking method: " + methodName);
// hook 每个方法
MsgContentBean[methodName].overload().implementation = function () {
// 打印方法名
console.log('Called ' + methodName);
// 打印方法参数
var args = arguments;
for (var i = 0; i < args.length; i++) {
console.log('Arg ' + i + ': ' + args[i]);
}
// 调用原始方法并获取返回值
var result = this[methodName].apply(this, arguments);
// 打印返回值
console.log('Return value from ' + methodName + ': ' + result);
return result; // 返回原始的结果
};
});
});
运行结果是这样的。
然后我这个部分就获取成功了。 上面的部分是解决了我的收到消息的模块。
接下来我要弄得是我自己发送消息的模块。
我通过这个代码,找到我自己发送的消息。
Java.perform(function() {
// 获取 MsgUIData 类的引用
var MsgUIData = Java.use('com.xingin.chatbase.bean.MsgUIData');
// 获取该类所有的方法
var methods = MsgUIData.class.getDeclaredMethods();
methods.forEach(function(method) {
var methodName = method.getName();
console.log('Found method: ' + methodName);
// 钩取每个方法并打印日志
try {
var overloads = MsgUIData[methodName].overloads;
overloads.forEach(function(overload) {
overload.implementation = function() {
// 打印方法名及参数
console.log('Method called: ' + methodName + ' with args: ' + JSON.stringify(arguments));
// 调用原始方法
return overload.apply(this, arguments);
};
});
} catch (e) {
console.log('Error hooking ' + methodName + ': ' + e.message);
}
});
});
找到了这个方法的名字。但是这个显示的是UI界面的一个方法的名字,和传输出去信息的方法无关。
所以我只能靠追踪栈来找了。
Java.perform(function() {
var MsgUIData = Java.use('com.xingin.chatbase.bean.MsgUIData');
MsgUIData.setStrMsg.implementation = function(str) {
console.log('调用栈: ' + Java.use('android.util.Log').getStackTraceString(Java.use('java.lang.Exception').$new()));
console.log('原始消息值: ' + str);
return this.setStrMsg(str);
};
});
追踪好之后,就会出来这些参数。
然后我把这些栈发给AI进行分析一下。
我分析了一下,这个onclick肯定是发送的按钮。
它那个17,代表17行进行了一个调试。
还有就是那个ChatPresenter。
- 你在聊天界面输入消息 →
ChatPresenter
接收到这个消息。 ChatPresenter
负责发送消息(比如通过网络请求)。- 消息发送成功后,
ChatPresenter
通知界面更新,把新消息展示给你。
我想了一下
at ny1.y1.O0(ChatPresenter.kt:6)
at ny1.y1.x1(ChatPresenter.kt:5)
为什么没有在jadx发现这些参数,因为我没用MT管理器找。
在classes2.dex里面。
public void O0(String content, int type, ec.h model, String quoteId, MessageBean quoteContent, int fromType) {
if (PatchProxy.proxy(new Object[]{content, new Integer(type), model, quoteId, quoteContent, new Integer(fromType)}, this, changeQuickRedirect, false, 126994, Void.TYPE).isSupported) {
return;
}
Intrinsics.checkNotNullParameter(content, "content");
Intrinsics.checkNotNullParameter(quoteId, "quoteId");
Nb().O0(content, type, model, quoteId, quoteContent, fromType);
}
然后我写了一个监视发送。
Java.perform(function () {
// 获取类 y1
var y1Class = Java.use("ny1.y1");
// Hook O0 方法
y1Class.O0.overload('java.lang.String', 'int', 'ec.h', 'java.lang.String', 'com.xingin.chatbase.bean.MessageBean', 'int').implementation = function (content, type, model, quoteId, quoteContent, fromType) {
// 打印传入参数
console.log("O0 called with parameters:");
console.log("content: " + content);
console.log("type: " + type);
console.log("model: " + model);
console.log("quoteId: " + quoteId);
console.log("quoteContent: " + quoteContent);
console.log("fromType: " + fromType);
// 调用原方法
return this.O0(content, type, model, quoteId, quoteContent, fromType);
};
});
拦截并且修改发送的消息。
Java.perform(function () {
// 获取类 y1
var y1Class = Java.use("ny1.y1");
// Hook O0 方法
y1Class.O0.overload('java.lang.String', 'int', 'ec.h', 'java.lang.String', 'com.xingin.chatbase.bean.MessageBean', 'int').implementation = function (content, type, model, quoteId, quoteContent, fromType) {
// 打印原始参数
console.log("Original O0 parameters:");
console.log("content: " + content);
console.log("type: " + type);
console.log("model: " + model);
console.log("quoteId: " + quoteId);
console.log("quoteContent: " + quoteContent);
console.log("fromType: " + fromType);
// 修改参数为固定值
var newContent = "666666"; // 固定的内容
var newType = 1; // 固定的类型
var newQuoteId = quoteId; // 固定的引用ID
var newFromType = 0; // 固定的来源类型
var newModel = model; // 保持 model 不变
var newQuoteContent = quoteContent; // 保持 quoteContent 不变
// 调用原方法,使用修改后的参数
this.O0(newContent, newType, newModel, newQuoteId, newQuoteContent, newFromType);
};
});
把这所有的栈复制下来放给AI,让他给我追踪所有的方法,还有打印出来的值。
Java.perform(function () {
// Hook ChatActivity.onClick 方法
var ChatActivity = Java.use("com.xingin.im.ui.activity.ChatActivity");
ChatActivity.onClick.overload('android.view.View').implementation = function (view) {
console.log("=== Hooked ChatActivity.onClick ===");
console.log("Parameter: View = " + view);
// 调用原始方法
var result = this.onClick(view);
console.log("=== Exiting ChatActivity.onClick ===");
return result;
};
// Hook ChatActivity.Hc 方法
ChatActivity.Hc.implementation = function () {
console.log("=== Hooked ChatActivity.Hc ===");
// 打印所有参数
for (var i = 0; i < arguments.length; i++) {
console.log("Parameter " + i + ": " + arguments[i]);
}
// 调用原始方法
var result = this.Hc();
console.log("=== Exiting ChatActivity.Hc ===");
return result;
};
// Hook ny1.y1.x1 方法
var y1Class = Java.use("ny1.y1");
y1Class.x1.overload('jh4.a').implementation = function (action) {
console.log("=== Hooked ny1.y1.x1 ===");
console.log("Parameter: Action = " + action);
// 打印参数详细信息(如果是对象)
try {
console.log("Action type: " + action.getClass().getName());
console.log("Action toString: " + action.toString());
} catch (e) {
console.log("Error retrieving action details: " + e.message);
}
// 调用原始方法
var result = this.x1(action);
console.log("=== Exiting ny1.y1.x1 ===");
return result;
};
// Hook ny1.y1.O0 方法
y1Class.O0.overload('java.lang.String', 'int', 'ec.h', 'java.lang.String', 'com.xingin.chatbase.bean.MessageBean', 'int').implementation = function (content, type, model, quoteId, quoteContent, fromType) {
console.log("=== Hooked ny1.y1.O0 ===");
console.log("Content: " + content);
console.log("Type: " + type);
console.log("Model: " + model);
console.log("Quote ID: " + quoteId);
console.log("Quote Content: " + quoteContent);
console.log("From Type: " + fromType);
// 调用原始方法
var result = this.O0(content, type, model, quoteId, quoteContent, fromType);
console.log("=== Exiting ny1.y1.O0 ===");
return result;
};
// Hook MsgConvertUtils.messageToMsgUIData 方法
var MsgConvertUtils = Java.use("com.xingin.chatbase.bean.convert.MsgConvertUtils");
MsgConvertUtils.messageToMsgUIData.overload('com.xingin.chatbase.db.entity.Message').implementation = function (message) {
console.log("=== Hooked MsgConvertUtils.messageToMsgUIData ===");
console.log("Message: " + message);
// 调用原始方法
var result = this.messageToMsgUIData(message);
console.log("Result: " + result);
console.log("=== Exiting MsgConvertUtils.messageToMsgUIData ===");
return result;
};
// Hook MsgUIData.setStrMsg 方法
var MsgUIData = Java.use("com.xingin.chatbase.bean.MsgUIData");
MsgUIData.setStrMsg.overload('java.lang.String').implementation = function (str) {
console.log("=== Hooked MsgUIData.setStrMsg ===");
console.log("Message: " + str);
// 调用原始方法
var result = this.setStrMsg(str);
console.log("=== Exiting MsgUIData.setStrMsg ===");
return result;
};
});
然后我找到了了这个。
然后我叫AI又重新精准定位这个地方。
Java.perform(function () {
// Hook MsgConvertUtils.messageToMsgUIData 方法
var MsgConvertUtils = Java.use("com.xingin.chatbase.bean.convert.MsgConvertUtils");
MsgConvertUtils.messageToMsgUIData.overload('com.xingin.chatbase.db.entity.Message').implementation = function (message) {
console.log("=== Hooked MsgConvertUtils.messageToMsgUIData ===");
// 提取 Message 的关键字段
try {
console.log("UUID: " + message.uuid);
console.log("MsgID: " + message.msgId);
console.log("StoreID: " + message.storeId);
console.log("CreateTime: " + message.createTime);
console.log("Content: " + message.content);
console.log("SenderID: " + message.senderId);
console.log("ReceiverID: " + message.receiverId);
} catch (e) {
console.log("Error extracting Message fields: " + e.message);
}
// 调用原始方法
var result = this.messageToMsgUIData(message);
console.log("Result: " + result);
return result;
};
});
我找到了一个发送的一个函数了。
我通过延时的方法来检测是不是发送的函数,结果是发送的函数。
Java.perform(function () {
// 获取 y1 类
var y1Class = Java.use("ny1.y1");
// Hook l6 方法,假设签名为 l6(com.xingin.chatbase.db.entity.Message)
y1Class.l6.overload('com.xingin.chatbase.db.entity.Message').implementation = function (message) {
console.log("=== Hooked y1.l6 ===");
console.log("Intercepted Message: " + message);
// 打印消息的部分字段(如果需要)
// console.log("Message content: " + message.content);
// 延时 5 秒
console.log("Delaying 5 seconds before sending...");
var Thread = Java.use("java.lang.Thread");
Thread.sleep(5000); // 让当前线程暂停 5 秒
console.log("Now calling original l6 method.");
// 调用原始 l6 方法
var result = this.l6(message);
console.log("Message sent (after delay).");
return result;
};
console.log("Hook setup complete. Waiting for y1.l6 calls...");
});
搞定了,这个能发送了。
因为我是一路往上找,才找到的。
/*// Hook r.a.b(this.b) 方法
Java.perform(function () {
// 获取 r.a 类的引用
var rAClass = Java.use('uy1.r$a');
// Hook b 方法
rAClass.b.overload('java.lang.String').implementation = function (str) {
// 输出传入的参数值 (this.b)
console.log('Hooked r.a.b() method');
console.log('Original argument (this.b): ' + str);
// 调用原始的 b 方法并获取返回值
var result = this.b(str);
// 输出返回值
console.log('Original return value: ' + result);
// 你可以修改返回值,例如:
// var modifiedResult = 'modified value';
// return modifiedResult;
// 返回原始的结果
return result;
};
});
*/
/*
Original argument (this.b): 哥哥刚刚吃饭
Original return value: 哥哥刚刚吃饭
Hooked r.a.b() method
Original argument (this.b):
Original return value:
Hooked r.a.b() method
Original argument (this.b):
Original return value:
Hooked r.a.b() method
Original argument (this.b): 吃吃吃vv好
Original return value: 吃吃吃vv好
Hooked r.a.b() method
Original argument (this.b): 吃吃吃vv好
Original return value: 吃吃吃vv好
Hooked r.a.b() method
Original argument (this.b):
Original return value:
Hooked r.a.b() method
Original argument (this.b):
Original return value:
*/
/*
Java.perform(function () {
// Hook y1$m0 类
var y1_m0_class = Java.use('ny1.y1$m0');
// Hook 构造函数
y1_m0_class.$init.overload('java.lang.String', 'com.xingin.chatbase.bean.MessageBean', 'ny1.y1', 'int', 'ec.h', 'java.lang.String', 'int').implementation = function (p0, p1, p2, p3, p4, p5, p6) {
// 输出 p1(即 MessageBean 对象)
if (p1 != null) {
console.log('this.c (MessageBean) = ' + p1.toString());
} else {
console.log('this.c (MessageBean) = null');
}
// 调用原始构造函数
this.$init(p0, p1, p2, p3, p4, p5, p6);
};
});
*/
/*
this.c (MessageBean) = null
this.c (MessageBean) = null
this.c (MessageBean) = null
*/
/*
Java.perform(function () {
// 获取 y1 类
var y1_class = Java.use('ny1.y1');
// Hook D6 方法
y1_class.D6.overload('ny1.y1', 'java.lang.String', 'int', 'ec.h', 'java.lang.String', 'com.xingin.chatbase.bean.MessageBean', 'boolean', 'int', 'java.lang.Object').implementation = function (p0, p1, p2, p3, p4, p5, p6, p7, p8) {
console.log("Hooked y1.D6()");
// 打印出输入参数
console.log("p0 (this.d) = " + p0); // this.d
console.log("p1 (str) = " + p1); // str
console.log("p2 (this.e) = " + p2); // this.e
console.log("p3 (this.f) = " + p3); // this.f
console.log("p4 (this.g) = " + p4); // this.g
console.log("p5 (tc) = " + p5); // tc (MessageBean)
console.log("p6 (boolean) = " + p6); // false
console.log("p7 (int) = " + p7); // 32
console.log("p8 (java.lang.Object) = " + p8); // java.lang.Object (null)
// 调用原始的 D6 方法
var result = this.D6(p0, p1, p2, p3, p4, p5, p6, p7, p8);
// 打印返回的 message 对象
console.log("Returned message = " + result);
// 返回原始结果
return result;
};
});
*/
/*
[MI 8 SE::小红书 ]-> Hooked y1.D6()
p0 (this.d) = ny1.y1@cb5ddfe
p1 (str) = 郭发发发
p2 (this.e) = 1
p3 (this.f) = null
p4 (this.g) = null
p5 (tc) = null
p6 (boolean) = false
p7 (int) = 56
p8 (java.lang.Object) = null
Returned message = Message(uuid='17376898235967000062e7a0e6000000001f0077b5', msgId='', storeId='0', createTime=1737689827038, contentType=1, msgType=1, subType='', senderId='62e7a0e6000000001f0077b5', receiverId='612368ee000000000101cd0c', chatId='612368ee000000000101cd0c', content='{"content":"郭发发发","content_type":1,"nickname":"123","not_front_chain":false,"not_unread_count":false}', hasRead=true, localChatUserId='612368ee000000000101cd0c@62e7a0e6000000001f0077b5', localMsgId='17376898235967000062e7a0e6000000001f0077b5@62e7a0e6000000001f0077b5', pushStatus=-1, msg='', hasImpression=false, isGroupChat=false, groupId=, localGroupChatId=)
*/
/*
Java.perform(function () {
// 获取 y1 类
var y1_class = Java.use('ny1.y1');
// Hook D6 方法,重载方法签名
y1_class.D6.overload('ny1.y1', 'java.lang.String', 'int', 'ec.h', 'java.lang.String', 'com.xingin.chatbase.bean.MessageBean', 'boolean', 'int', 'java.lang.Object').implementation = function (p0, p1, p2, p3, p4, p5, p6, p7, p8) {
console.log("Hooked y1.D6()");
// 打印所有参数
console.log("p0 (y1 instance) = " + p0); // y1 instance
console.log("p1 (String p1) = " + p1); // String p1
console.log("p2 (int p2) = " + p2); // int p2
console.log("p3 (h p3) = " + p3); // h p3
console.log("p4 (String p4) = " + p4); // String p4
console.log("p5 (MessageBean p5) = " + p5); // MessageBean p5
console.log("p6 (boolean p6) = " + p6); // boolean p6
console.log("p7 (int p7) = " + p7); // int p7
console.log("p8 (Object p8) = " + p8); // Object p8
// 计算和打印经过位运算后的参数值
var oh = (p7 & 0x04) ? null : p3;
var str = (p7 & 0x08) ? "" : p4;
var messageBean = (p7 & 0x10) ? null : p5;
var b = (p7 & 0x20) ? false : p6;
console.log("Processed oh = " + oh); // processed h oh
console.log("Processed str = " + str); // processed str
console.log("Processed messageBean = " + messageBean); // processed MessageBean
console.log("Processed b = " + b); // processed boolean b
// 调用原始的 C6 方法
var result = this.D6(p0, p1, p2, p3, p4, p5, p6, p7, p8);
// 打印返回的 Message 对象
console.log("Returned Message = " + result);
// 返回原始结果
return result;
};
});
*/
/*
Hooked y1.D6()
p0 (y1 instance) = ny1.y1@cb5ddfe
p1 (String p1) = vv好尴尬
p2 (int p2) = 1
p3 (h p3) = null
p4 (String p4) = null
p5 (MessageBean p5) = null
p6 (boolean p6) = false
p7 (int p7) = 56
p8 (Object p8) = null
Processed oh = null
Processed str =
Processed messageBean = null
Processed b = false
Returned Message = Message(uuid='17376902126862000062e7a0e6000000001f0077b5', msgId='', storeId='0', createTime=1737690216127, contentType=1, msgType=1, subType='', senderId='62e7a0e6000000001f0077b5', receiverId='612368ee000000000101cd0c', chatId='612368ee000000000101cd0c', content='{"content":"vv好尴尬","content_type":1,"nickname":"123","not_front_chain":false,"not_unread_count":false}', hasRead=true, localChatUserId='612368ee000000000101cd0c@62e7a0e6000000001f0077b5', localMsgId='17376902126862000062e7a0e6000000001f0077b5@62e7a0e6000000001f0077b5', pushStatus=-1, msg='', hasImpression=false, isGroupChat=false, groupId=, localGroupChatId=)
*/
/*
Java.perform(function () {
// 获取 y1 类
var y1_class = Java.use('ny1.y1');
// Hook C6 方法
y1_class.C6.overload('java.lang.String', 'int', 'ec.h', 'java.lang.String', 'com.xingin.chatbase.bean.MessageBean', 'boolean').implementation = function (p0, p1, p2, p3, p4, p5) {
console.log("Hooked y1.C6()");
// 打印所有参数
console.log("p0 (String p0) = " + p0); // String p0
console.log("p1 (int p1) = " + p1); // int p1
console.log("p2 (h p2) = " + p2); // h p2
console.log("p3 (String p3) = " + p3); // String p3
console.log("p4 (MessageBean p4) =