本帖最后由 hjw45611 于 2019-10-17 14:40 编辑
严重声明
本文的意图只有一个就是通过分析app学习更多的逆向技术,如果有人利用本文知识和技术进行非法操作进行牟利,带来的任何法律责任都将由操作者本人承担,和本文作者无任何关系,最终还是希望大家能够秉着学习的心态阅读此文。
上篇是在信息展示页自动点击添加好友按钮并跳转到验证申请页面,本篇功能自动发送验证信息。
前两篇链接:
https://www.52pojie.cn/thread-872046-1-1.html
https://www.52pojie.cn/thread-886190-1-1.html
在此说明一下
不是我不放出成品,而是成品很简陋,只是用来让我的测试微信号自动通过我的手机号来添加微信大号的一个功能,真正要做成成品,要思考如何动态把要添加好友的手机号存放在手机里,如何触发自动添加,添加后如何移除,这都是一个完整成品所要考虑的,而不同的产品有不同的实现方式,我只是把核心功能做了一下,希望大家从中学习思想,而不是仅仅是体验一下这个简陋的成品就完事了。
同样以微信7.0.3为例
查看页面并分析
发送验证信息页是com.tencent.mm.plugin.profile.ui.SayHiWithSnsPermissionUI,jadx打开并查找类SayHiWithSnsPermissionUI,分析代码
一眼看到有两个EditText,对比页面,可以肯定这两个EditText就是页面中的输入框,直接hook一下:
[Java] 纯文本查看 复制代码 findAndHookMethod(SayHiWithSnsPermissionUIClass,
"onCreate", Bundle.class,
new XC_MethodHook() {
@Override
protected void afterHookedMethod(final MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
log("SayHiWithSnsPermissionUI-bundle=" + logBundle(((Activity) param.thisObject).getIntent().getExtras()));
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
try {
EditText editText= (EditText) XposedHelpers.findField(SayHiWithSnsPermissionUIClass,"oLC").get(param.thisObject);
editText.setText("测试用,勿加");
EditText editText1= (EditText) XposedHelpers.findField(SayHiWithSnsPermissionUIClass,"oLD").get(param.thisObject);
editText1.setText("测试好友");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
},100);
}
});
结果就如我们所猜测的那样
继续分析代码,我们要找的是实现了OnMenuItemClickListener的内部类,因为在 我的微信数据监控研究发展过程 这个帖子中微信页面的顶部点击事件是实现了OnMenuItemClickListener的内部类,能直接找到有两个内部类实现了OnMenuItemClickListener
它们在initView方法中被使用到
可以确定一个是发送按钮,一个是返回按钮,那就重点分析mo9514a方法吧
直接搜索mo9514a方法,发现是父类MMActivity中的方法,只有addTextOptionMenu这个方法
mController对象
查找mController对象的类:
可以看到这个类继承自一个抽象类,只有实现几个抽象方法,我们需要查看这个抽象类
在这个类中查找addTextOptionMenu这个方法,
可以看到方法中构造了一个内部类的对象,然后加到这个xrG变量的list集合里,然后直接在类中搜索gkj.onMenuItemClick,能看到是这个a方法调用的点击事件:
查看m4207a方法的调用,调用有多处,但确定是onCreateOptionsMenu方法中调用,因为在MMActivity中也有它的的调用
所以先分析onCreateOptionsMenu方法
可以看到,代码大致就是直接遍历集合后通过menu.add添加item按钮,并通过findview得到发送按钮,设置好点击监听。
直接hook
可以直接hook这个方法,并在方法执行完成后直接执行点击事件
[Java] 纯文本查看 复制代码 findAndHookMethod(ControllerClass,
"onCreateOptionsMenu", Menu.class,
new XC_MethodHook() {
@Override
protected void afterHookedMethod(final MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
if (TextUtils.equals(XposedHelpers.findField(ControllerClass, "xyi").get(param.thisObject).getClass().getSimpleName(),
"SayHiWithSnsPermissionUI")) {
log("onCreateOptionsMenu--" +
"list(0).xrP=" + XposedHelpers.findField(XposedHelpers.findClass("com.tencent.mm.ui.q$a", mlpparam.classLoader), "xrP").get(((LinkedList) findField(ControllerClass, "xrG").get(param.thisObject)).get(0)) + "===" +
"list(0).xyM==null=" + (XposedHelpers.findField(XposedHelpers.findClass("com.tencent.mm.ui.q$a", mlpparam.classLoader), "xyM").get(((LinkedList) findField(ControllerClass, "xrG").get(param.thisObject)).get(0)) == null) + "===" +
"textview=" + ((TextView) findField(ControllerClass, "xrx").get(param.thisObject)).getText() + "==" +
"Button=" + ((Button) findField(ControllerClass, "lvg").get(param.thisObject)).getText() + "=="
);
final Object menuItem = ((Menu) param.args[0]).getItem(0);
try {
XposedHelpers.callMethod(param.thisObject, "a", menuItem,
((LinkedList) findField(ControllerClass, "xrG").get(param.thisObject)).get(0));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
});
因为我们hook的是一个抽象父类,所以先确定调用者是不是我们要用的SayHiWithSnsPermissionUI,使用了类中的Activity变量xyi来对比,然后打印了一些方法内的参数,通过这几个参数确定集合中只有一个数据,menu.add也就只add了一个发送按钮,然后通过方法的Menu参数获取到这个按钮的MenuItem对象后,直接执行a方法。
在这里运行后直接报错
可以看到是没有找到这个方法报错了,原因是com.tencent.mm.ui.MMActivity$1这个类中没有a方法,而这个类是mController对象的类,而我们Hook的是它继承的那个抽象父类,所以hook时param.thisObject这个实例对象并不是父类,所以无法调用它里面的private方法。
既然无法使用a方法,那我们就执行a方法里的代码吧, c2171a.gkj.onMenuItemClick(menuItem);
[Java] 纯文本查看 复制代码 findAndHookMethod(ControllerClass,
"onCreateOptionsMenu", Menu.class,
new XC_MethodHook() {
@Override
protected void afterHookedMethod(final MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
if (TextUtils.equals(XposedHelpers.findField(ControllerClass, "xyi").get(param.thisObject).getClass().getSimpleName(),
"SayHiWithSnsPermissionUI")) {
final Object menuItem = ((Menu) param.args[0]).getItem(0);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
try {
Object c2171a = ((LinkedList) findField(ControllerClass, "xrG").get(param.thisObject)).get(0);
Object menuItemClickListener = findField(XposedHelpers.findClass("com.tencent.mm.ui.q$a", mlpparam.classLoader), "gkj").get(c2171a);
XposedHelpers.callMethod(menuItemClickListener, "onMenuItemClick", menuItem);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}, 300);
}
}
});
效果图
至此本文完成,自动加好友的功能也完整走完,可能本文较上文更细致一些,把全部思路都有截图说明,希望喜欢Xposed的朋友能从中获益。
同样在GitHub给出完整代码
https://github.com/hjw45611/WechatPlugin/
|