USB调试授权自动化研究
关键词
- USB调试授权自动同意
- adb授权自动点击
- 网络调试自动授权
- 坏屏手机远程控制
环境
- 设备:屏幕碎了,直接拆掉屏幕,当云手机远程使用
- 系统:MIUI 12.5 Android 11,已关闭MIUI优化,已ROOT,有Xposed环境
- 其他:主设备都已授权USB调试,可通过scrcpy控制
方案
修改环境变量关闭验证
先用类似功能模块 Adb-root-enabler,思路是修改ro.adb.secure
属性,但是重启adbd后会自动重置该属性为1,参考文章小米10 adbd 可能要尝试改adbd为debug版本,感觉会有风险。故弃用此方案
无障碍点击授权
无障碍缺点是可能不稳定,但是配合root权限和轮询,理论上稳定性/效率应该可以。没有具体编码,采用后一种方案。
注入进程自动同意授权
既然adbd或环境变量都不行,尝试hook相关类,在弹出对话框的时候自动调用通过的回调,缺点是需要逆向相关代码。
花了点时间,具体做法是先找到对应的类,因为是个dialog,大概率有个activity或dialog相关的类。
-
先触发usb调试授权框,先看界面是哪个app哪个Activity,
adb shell dumpsys window | grep mCurrentFocus
,结果是mCurrentFocus=Window{6aabeb0 mode=0 rootTaskId=53712 u0 com.android.systemui/com.android.systemui.usb.UsbDebuggingActivity}
,可以看到就是systemui 下的 UsbDebuggingActivity -
逆向,看看这个类怎么写的,我是通过MT管理器导出这个apk看,逻辑很简单,这个Activity就是弹出个 AlertDialog
-
最后就是具体怎么hook了,思路有几个,一种是直接通过这个类拿到dialog实例,然后触发点击。另一种是hook所有dialog show的地方,然后判断title、message,判断是不是
允许 USB 调试吗?
,然后再去点击。 -
xposed代码直接注入
com.android.systemui
进程,第一种思路就能实现,相关代码如下:
1hookAllAfter(Activity::class.java, "onResume") {
2 LogUtil.log("currentActivity = ${it.thisObject}")
3 currentActivity = it.thisObject as Activity
4 if (currentActivity!!::class.java.name.contains("UsbDebuggingActivity")) {
5 for (field in currentActivity!!::class.java.fields + currentActivity!!::class.java.declaredFields) {
6 if (field.type.name.endsWith("Dialog")) {
7 field.isAccessible = true
8 val dialog = field.get(currentActivity)
9 LogUtil.log("field dialog = $field $dialog")
10 val bu = on(dialog).call("getButton",AlertDialog.BUTTON_POSITIVE).get<Button?>()
11 bu?.apply {
12 LogUtil.log("确认按钮 BUTTON_POSITIVE = $bu,自动点击确定")
13 performClick()
14 }
15 }
16 }
17}}
- 这样能达到目的,还是有些局限,1. activity类名混淆兼容问题,2. dialog类名混淆兼容问题,不过可能对于MIUI/澎湃OS不用考虑,这个系统好多代码都没混淆加密,我看了另一台澎湃OS,这个类代码也是差不多,跑起来估计问题也不大。
后记
- 最终采用的碎屏手机的远控方案,只适用MIUI/澎湃OS的ROOT后的手机,需要装好Xposed环境
- 其实主设备有授权了照理说就不需要这个方案了,但是这个授权实测不太稳定,隔段时间不知道为啥就不行了,而且不排除主设备ssh重新生成/覆盖/丢失的风险
- 安全问题,由于是自动授权,所以不要暴露到公网,避免被恶意利用