本文同步更新于旺仔的个人博客,访问可能有点慢,多刷新几次。
缘由
不知道大家有没有用过QQ/TIM登录的时候使用扫描二维码登录的功能呢?
也就是登录界面的右下角那里有个二维码的按钮
点击之后就会出现二维码
然后用手机QQ/TIM打开扫一扫界面,扫了之后,会弹出允许登录的界面
然后我们需要点击允许登录TIM/QQ,电脑端就登录成功了。
但是每次登录都要点击允许登录,我觉得好麻烦,所以就实现了自动点击功能,这篇文章就是来介绍如何使用Xposed来实现自动点击。
实践
首先我们先整理一下思路,先要获取确认登录界面的Class,然后获取允许登录这个控件的Field,然后通过调用performClick
这个方法来实现点击。
查找确认登录Activity
接下来,我们需要获取确认登录界面的Activity是哪一个,在这里我们先下载一个软件当前界面,可以获取到当前界面的Activity
在这里我们找到了确认界面的Activity的类名是com.tencent.biz.qrcode.activity.QRLoginActivity
,然后我们进行下一步
反编译classes.dex
当前使用的apk版本是2.0.0,然后改后缀,打开压缩包,复制里面的dex
文件
然后通过dex2jar
将dex
转换成jar
文件,然后用jd-gui
打开jar
包,最后在classes6-dex2jar.jar
里面找到QRLoginActivity
类
使用AndroidKiller
由于我们需要获取控件相关的内容,就需要获取控件的id、text之类的东西,那么仅仅靠dex2jar
和jd-gui
两个东西是完成不了的,所以这里我们需要用到AndroidKiller
,AndroidKiller是一款可视化的安卓应用逆向工具,具体使用,大家自行上网搜索,这里不介绍。
获取text引用
将我们的TIM的apk打开,然后搜索允许登录
内容,找到对应的16进制内容
找到之后,发现有两个16进制的值,一个是7f0a0872
,一个是7f0a0ba9
,既然有两个,那么就有分别去搜索这两个值的调用,我这里有搜索过,第二个才是我们需要的,我们来看搜索结果
可以看出,这个值的引用是在hxq
类上面调用的,点开jd-gui
,找到这个类,同样是在classes6-dex2jar.jar
里面
可以看出这个类是个Handler
类,那么我们就可以这样理解,当扫描二维码后,会调用sendMessage
之类的方法,然后在handleMessage
里面进行修改控件的Text值。
Hook方法
通过上面的说明,我们可以很明确的知道该hook的地方在哪里了:
- 首先我们需要将Hook控件初始化的方法,然后再Hook我们的
hxq
类里面的handleMessage
方法 - 之后进行判断控件的值是不是包含
允许登录
的内容(因为二维码过期我们不需要进行处理,只有登录的时候才进行处理),如果包含的话就调用performClick
这个方法实现点击。
找到初始化方法
如何找到初始化方法呢,通过搜索findviewbyid
,找到了doOnCreate
方法
然后我们Hook这个方法
// 获取Class
final Class<?> aClass = XposedHelpers.findClassIfExists("com.tencent.biz.qrcode.activity.QRLoginActivity", lpparam.classLoader);
if (aClass == null) {
return;
}
// Hook指定方法
XposedHelpers.findAndHookMethod(aClass, "doOnCreate", Bundle.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
// 操作
}
});
反射获取控件
通过获取QRLoginActivity
的Class之后,我们通过反射获取里面的所有变量,然后通过判断变量的类型,然后判断控件的Text值是否包含允许登录
内容,然后实现点击。
for (Field declaredField : declaredFields) {
// 设置true
declaredField.setAccessible(true);
// 判断类型是否是Button
if (declaredField.getGenericType().toString().contains("android.widget.Button")) {
// 获取值
final Button loginButton = (Button) declaredField.get(param.thisObject);
if (loginButton == null) {
return;
}
// 默认的Button的Text为空,需要在Handler这个类里面的方法后面加上判断
Class<?> handlerClass = XposedHelpers.findClassIfExists(resultStr, lpparam.classLoader);
if (handlerClass == null) {
return;
}
try {
// Hook方法,对handleMessage方法调用后,进行判断Button的Text进行判断,并且自动调用点击方法
XposedHelpers.findAndHookMethod(handlerClass, "handleMessage", Message.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
// 当Button的Text为允许登录TIM/允许登录QQ的时候才实现点击
if (loginButton.getText().toString().contains("允许登录")) {
loginButton.performClick();
}
}
});
} catch (Throwable t) {
XposedBridge.log("Hook 出错 " + t);
}
}
}
最后打包,安装,激活重启
结果:
结语
文章说的简单一点,实际上自己反编译并且查找内容,是一个比较繁琐的事情,明确的方向会减轻需要操作的步骤。
微信自动确认登录
同样我们可以实现自动确认电脑端登录,这里就不再介绍了,大家可以自己试一试:
GitHub
Github地址在此奉上:ScanLogin,欢迎star