首先我使用了一个叫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);
}
//