最近忙于工作,我的“咸鱼”时间终于脱颖而出,期间也走了很多弯路,现在也在做笔记,供想学习的朋友们参考。
收到的图片
发送的图片
老规矩,我们来分析一下海浪!
一开始看这个布局,可以看到微信聊天列表和这个聊天界面处于同一水平,我后面的hook listview总是跑到主页的列表上。
关键点-看到com了。在我上一篇文章提到的ChattingUI$a类中,这就是郑州。
接下来我们来看看撤回消息时到底发生了什么。消息已保存在本地数据中。继续看为什么这么说。
Com。
前面提到的类ChattingUI$a如果不知道我为什么找到后面几个相关类,看前面的帖子都可以连接。、、、
而且这门课没有什么实质性的东西,所以我点击了他的父亲类。
Com。
发现
Com。
我不说别人看到这个会怎么想。我平时自己写聊天应用程序的时候也会把聊天数据存储在数据库里。所以我开始hook。
/* * *
直接hook SQL实现了获取撤回消息id的目的* * @ param application context * @ param
class loader */private void hook db(final context application context,final)
ClassLoader classLoader) {
final class SQLite database=x(' com . '),class loader);
final class cancellation signal=x(' com .class loader);
if(SQLite database==null)return;
X ('com .而且,
ClassLoader、
Sqlite数据库,
s,
Object[]。class,
CancellationSignal、
New XC_MethodReplacement() {
@Override
protected object replacehookedmethod(methodhookparam param)throws throwable {
Object[]objArr=(Object[])[2];
字串originalSql=[1]。toString();
//打印调用SQLiteProgram的所有SQL
(' hookdb '' SQL-'[1],' objarr3360 '
JSON . toj sonstring(ob jarr));If (objArr!=空
Original sql.touppercase()。startswith ('updat
E MESSAGE")) {for (Object obj : objArr) {
String sqlParam = obj.toString();//自己撤回10002 别人撤回10000 if ("10000")) {//别人撤回 Object[] newObjArr = new Object[2];
//[1] = "UPDATE message SET type=? WHERE msgId=?"; [1] = "select * from message where type=? and msgId=?";
[2] = newObjArr;
newObjArr[0] = 1;
newObjArr[1] = objArr[objArr.length - 1];
//[1] = "UPDATE message SET content=(select (select content from message where msgId = ?)||X'0D'||X'0A'||X'0D'||X'0A'||(\"wxInvoke卧槽,TA竟然要撤回上面的信息wxInvoke\")),msgId=?,type=? WHERE msgId=?"; LogU("hookDB", "originalSql->" + originalSql, "newSql->" + [1], "sqlParam->" + JSON.toJSONString(newObjArr));
WxChatInvokeMsg msg = new WxChatInvokeMsg();
m(newObjArr[1].toString());
WxC(applicationContext, msg);
}
}
}
return X, , );
}
});
}
看到上面我hook的是SQLiteProgram 会有朋友问为啥?
因为我SQLiteDatabase在里面找insert和update的方法发现里面最后走进入了SQLiteProgram 哈哈! 偷个懒我就不具体截图找给大家看了,然后把撤回的消息id记录在本地,作为后面标记的依据。
接下来开始处理撤回效果了
/** * 微信聊天界面 * * @param applicationContext * @param classLoader */ private void hookWxChatUIMM(final Context applicationContext, final ClassLoader classLoader) {
X("com.",
classLoader,
"onLayout",
boolean.class,
int.class,
int.class,
int.class,
int.class,
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
(param);
ViewGroup mMPullDownView = (ViewGroup) ;// if () == View.GONE) return; for (int i = 0; i < mMPullDownView.getChildCount(); i++) {
View childAt = mMPullDownView.getChildAt(i);
if (childAt instanceof ListView) {
final ListView listView = (ListView) childAt;
final Listadapter adapter = li();
X(),
"getView",
int.class,
View.class,
ViewGroup.class,
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
(param);
int position = (int) [0];
View view = (View) [1];
JSONObject itemData = null;// LogU(position, view.toString()); if (position < ada()) {
itemData = JSON.parseObjec(position)), JSONObject.class);
int itemViewType = ada(position);// LogU(itemViewType); //经过以上代码可以知道 itemViewType == 1的时候打印的值是正常对话列表的值 if (itemData != null && (view != null && view.toString().contains("com.;))) {// if (itemData != null && itemViewType == 1 && (view != null && view.toString().contains("com.;))) { String field_msgId = i("field_msgId");
WxChatInvokeMsg wxChatInvokeMsg = WxC(applicationContext, field_msgId);
ViewGroup itemView = (ViewGroup) view;
View itemViewChild = i(0);
Object tag = i);
TextView textView;
if (tag == null) {
textView = new TextView(applicationContext);
);
(new LinearLayout.LayoutParam, ViewGroup.Layou));
i, textView);
);
i(textView);
} else {
textView = (TextView) i);
}
("");
);
if (wxChatInvokeMsg != null) {
(10, 5, 10, 5);
());
Color("#666666"));
View msgView = i(3);
Rela lp = (Rela) ();
lp.addRule);
lp.addRule, m());
lp.bottomMargin = 50;
("这小子想撤回这个消息");
);
LogU(position, view, itemViewType, i());
}
}
}// }
});
break;
}
}
}
});
}
记住hook 这个listview的时候会遇到我文章片头说的问题,导致每个item的view 对应错误,所以我加了过滤标识。
以上内容仅仅作为学习交流。代码很简单,乐趣在于找到这些代码位置的过程。
原文链接:[原创]Xposed第三课(微信篇) 防止好友消息撤回
本文由看雪论坛 KingZd 原创
转载请注明来自看雪社区