模拟 USB HID 修好了无限重启的 Android 手机 —— 如何在 2s 时间内快速打开 ADB

Table of Contents

背景

m1luf0 在她的 OnePlus 12 上安装了 Island 创建隔离的 Work Profile,然后进行了一些 App 的 Clone 后 Destroy 再次重新创建,在创建过程中手机就自动重启,接着开机后,每次输入密码大概 2-4s 左右的时间又会自动重启(前3次只重启 Android Userspace,不重启内核,最后一次硬件重启)。此时,桌面上也并没有出现任何 Island Clone 出的任何 App。同时,安全模式也并未解决重启问题。而没有输入密码之前,手机可以保持一个稳定开机的状态。

与此同时,由于 ADB 并没有打开无法进行高级 Debug,而自动重启也很难直接在手机上进行任何操作。纯用触摸屏操作大概就是:解锁后滑动下屏幕,点不开任何 App,就自动重启了。而她找遍了北京几家 OPPO 售后,也只得到了刷机的回复。加上她清明假期刚旅游回来,一定有很多难忘的回忆而且还没有任何备份,又是自己认识了11年的朋友+高中同学+同事,决定好好帮帮她。

分析

Island 创建 Work Profile 中途会进行什么操作

刚好最近我为了随时随地 Vibe Coding 需求买了台二手小米 Mix Fold 3,就在自己的第二手机上看了下 Work Profile 的创建过程:

发现,在创建刚点击下去后,迅速观测 adb shell pm list users,就可以看到 Island 创建出了 Work Profile。

那么大胆猜想:是否 adb shell pm remove user 14 即可解决问题?

随后我在自己手机进行了测试,确实这样就可以删除 Island 创建的 User,Work Profile 以及 Clone 的 App 也随之消失。那么大胆猜想:也许我们只要在 shell 执行 pm remove user ${WORK_PROFILE_ID} ,问题就可以解决!即使不能解决,只要有了 ADB,我们大概也有 114514 种方法救出手机里的资料。

如何打开 ADB

既然我们已经知道有了 ADB 的情况下如何解决问题了,那么如何获得 ADB 呢?

我想到了自己有 CH9329 ,这个芯片可以用串口模拟 USB HID,淘宝上也有成品 CH9329 + CH340 数据线,一头连接 Host 作为控制端,一头连接 OTG 模拟 USB 键盘鼠标。我们用这个东西可以远快于触摸屏操作的速度,因为键盘方向键可以精准点击菜单。Host端软件我采用了 pych9329-hid,并且自己 Vibe Coding 了 relative mouse mode 的支持,使得可以在 Android 上模拟鼠标。

我也拿自己手机试了一下,1.2s 左右就能打开开发者模式,打开 ADB 的时间也类似,只可惜小米的 ADB 还需要额外时间确认,好在 AOSP 以及 ColorOS 都没有这个问题。

如何获取更多的时间

经过研究和尝试发现,ColorOS 虽然在锁屏页面不能下拉通知栏点击设置图标,但可以点击紧急呼叫后输入 *#899# 进入工程模式,此时就可以下拉通知栏点击设置,这就避免了我们解锁后再去下拉通知栏或者去启动器上找设置可能还要花费至少1秒钟的时间,这对于后续的键盘操作就十分友好。

与此同时,我还把整个过程写成了脚本操作:

def enter_aftersale_page(controller):
    controller.press("space")
    time.sleep(0.5)
    # now at lock screen
    controller.press("tab")
    controller.press("tab")
    controller.press("space")
    time.sleep(0.5)
    # now at emergency call screen, input 1 to select the input box
    controller.press("tab")
    controller.press("tab")
    controller.press("tab")
    controller.press("space")
    time.sleep(0.5)
    controller.press("backspace")
    controller.press("backspace")
    time.sleep(0.5)
    controller.write("*#899#")
    time.sleep(1)

def enter_settings_password(controller):
    # scroll down the notification bar
    controller.dragRel(0, 100)
    time.sleep(0.5)
    # move to settings icon and click
    controller.moveRel(209, 0)
    time.sleep(0.5)
    controller.moveRel(0, -40)
    time.sleep(0.1)
    controller.click()
    time.sleep(1)

如何获得键盘操作序列

找了另一位同事同样是一加 ColorOS 的手机,用 USB 键盘做了个点击尝试,最终写出了打开设置后的操作序列:

def oneplus_devmode(controller):
    # press arrow down to about phone
    for i in range(11):
        controller.press("down")
    controller.press("enter")
    time.sleep(0.05)
    for i in range(8):
        controller.press("down")
    controller.press("enter")
    time.sleep(0.05)
    for i in range(8):
        controller.press("enter")
    controller.write(PASSWORD) # password
    # assume in the devmode menu, you should restart to return to settings menu then run oneplus_adb

def oneplus_adb(controller):
    # press arrow down to developer options
    for i in range(10):
        controller.press("down")
    controller.press("enter")
    time.sleep(0.05)
    for i in range(8):
        controller.press("down")
    controller.press("enter")
    time.sleep(0.05)
    for i in range(14):
        controller.press("down")
    controller.press("enter")
    time.sleep(0.05)
    for i in range(2):
        controller.press("right")
    controller.press("enter")

最终效果

成功打开开发者模式以及 ADB ,附上一个差一点成功的开发者模式视频(成功的那一次是多次自动化尝试的,没录下来):

在打开了 ADB 之后,直接进行了删除,问题完美解决,手机不再自动重启:

同时,完整代码也放在了我的 gist 上。

一些经验

  1. CH9329 + CH340 + Python 做超低延迟的控制,macOS 的多次重复操作时间精度远高于 Linux。
  2. ColorOS 的设置第一页用键盘方向键没有光标,按相同的次数也可能因为按键间隔存在误差。
  3. 关注手机温度,多次尝试中建议增加散热器,防止过热后导致设置的点击无法快速操作。

一些思考

我朋友和我也与 AI 聊了这个问题,寻求解决方案,但是 AI 也同样给出了判死刑的回答,认为不太可能在几秒钟的时间内操作手机打开 ADB,如果售后没有后门几乎无解。我一开始也认为就算有 OTG 模拟 HID 希望也不大,直到我在自己手机上测试发现 只需要 1s 左右时间即可打开 ADB ,才重新燃起了巨大的希望。

从我朋友跟我说这个事情到最后解决其实也经历了很多波折,比如因为经验 [2] 导致其实设置第一页的点击并不精确,需要多次尝试才能打开,而一开始并没有去增加鼠标点击屏幕的方案,导致每次重试都是朋友自己手动点开的设置,再运行脚本。直到后来她在我面前演示了一下我才发现,原来解锁后有 3s 时间操作都是一个小概率情况,遂继续编写了鼠标点击代码,使得整个尝试过程可以全程自动化,最后才在尝试了 2h 后成功打开了开发者模式,又过了 2h 进行了各种微调才打开了 adb 。不过,每次都能逢山开路,遇水架桥,一步一步攻难关。

而我想,大多数手机维修行业不一定会知道有模拟 USB HID 这样的 Hack 技术存在。我朋友也找了第三方维修询问,不过某个第三方维修上来就是“CPU虚焊”,我们显然是不相信这个结论的,因为前三次重启只是重启 Android 的 Userspace ,甚至没重启 Linux 内核,这种情况实在无法相信是 CPU 有问题。我自己能快速想到能用 USB HID 这一点,也是因为我用过同样的技术做类似的事情——用 Arduino 模拟键盘给家里挂着 iMessage 短信转发的旧 iPhone 每几个小时输入密码,来绕过现在 iOS 的 2 天不解锁自动重启的安全保护。而我们在有了 AI 的当下,如果这样的 Hack 知识能被 AI 学习并传播给每一个需要的人,也许更多的数字回忆就能在这样的软件 Bug 中被保留下来,而不是原厂售后只能放弃资料的解决方案。

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to Top