仅用Android手机拯救Linux主机,带你深入了解USB Gadget
0. 引
首先介绍一下本期主角,Chongxi之前购入过一台玩客云小主机,并给他刷了Ubuntu armv7,当作一个轻量的服务器来使用,在上面跑跑AdguardHome这种小玩意。在爆改的过程中,因为配置文件错误,导致主机的网卡死了,无法进行ssh连接,由于所处环境没有实体键盘以及HDMI显示器用,主机也没有reset按钮,使这台主机成了半残废的状态。
0.1 食材准备
首先介绍下救砖工具:
- 一台root过的Android手机
- USB数据线
所需软件: - USB Gadget Tool
- Android HID Keyword
所需文件均已给出其GitHub链接,您也可以通过Atlas快递站一键下载所需文件。
1. 原理讲解
其实非常简单,就是拿Android设备模拟成键盘,输入到主机中。至于无HDMI可视化是如何判断命令输出的?答案是,IO灯
对,你没听错,大多数人可能听说过靠主板IO灯来debug,很少听说过靠IO灯来判断输入输出并拯救ubuntu主机吧,当你输入操作和主机输出时,IO灯会闪烁,本文就是靠IO灯来诊断的
既然知道了原理,那么接下来救砖就一定很简单了…吧?
1.1 拦路虎
首先,绝对不是你想的「把数据线一接,然后打开Gboard就能输入」这么简单。
USB协议有严格的主从关系,你插上主机后,大概率是被主机作为要被调试的设备,而不是反过去调试主机。
再者就是BadUSB风险,这里简单过一下基本知识
BadUSB
BadUSB是最经典的攻击手段之一,USB协议有一个信任漏洞,主机会无条件信任设备对自己身份的声明,你说你是键盘他就会相信,没有额外的校验过程。一个简单的BadUSB攻击过程如下
- 将攻击设备插入主机
- 攻击设备向主机声明他是U盘,主机信任并加载
- 攻击设备主动断开连接,并以HID的声明重新连接,主机并不会校验他到底是不是键盘,会直接加载驱动,无任何防备接受一切来自此设备的输入
- 攻击设备开始向主机注入命令(如启动powershell下载木马),而在主机看来,这可能是一个打字飞快的人类,所以不会有任何阻拦
这和你的android手机又有什么关系?
如果你的android设备有完整的USB Gadget权限,他就能变成OURWORLD里最强大最隐蔽的BadUSB,谁会怀疑一个毫无威胁的正在充电的手机呢?
你可以使用Termux写攻击脚本来对目标设备注入,对方以为你在充电,实则模拟成键盘,甚至USB网卡劫持流量来发起中间人攻击,NetHunter就是一个专门为Android设备定制的渗透用rom,可以随意控制手机USB接口,伪装成各种设备
OEM厂商 Google Android社区都明白,对于这么巨大的安全隐患,做决策就非常简单了,直接砍掉
因为对于普通消费者来说,他们用USB传输顶多就是互传照片文件和网络共享,直接干掉Gadget无疑是OEM厂商的必然选择,风险实在过于严重
那么,我是如何让Android设备成功模拟成HID对Ubuntu进行输入的呢
2. 实现原理
Talk is cheap, show me the code.
我们直接来看 Linux 内核的官方configfs.txt来解释,为什么用户空间程序能够控制内核级别的硬件行为
2.1 内核提供蓝图 而不是成品
1 | Where sysfs is a filesystem-based view of kernel objects, configfs is a filesystem-based manager of kernel objects |
也就是说,sysfs 是让你看内核已经创建好的东西(比如你的 CPU 温度),而 configfs 是让你要求内核为你创建新的东西。
当 Android 内核被编译时,开启了 CONFIG_USB_GADGET 和 CONFIG_USB_HID 选项后,内核并不会立刻创建一个USB键盘设备。它只是在 /config/usb_gadget/ 目录下,准备好了基础工具,等着你来超级拼装
2.2 mkdir
1 | A configfs config_item is created via an explicit userspace operation: mkdir(2). |
你在 configfs 里每创建一个目录,就等于在调用一个内核函数
比如
1 | mkdir /config/usb_gadget/g1 |
- 这个命令执行时,
configfs会通知USB Gadget:用户想创建一个新的 Gadget 实例 g1 - 内核模块后在内存里分配了一块空间,用来描述这个即将被创建的USB设备
2.3 目录与文件
1 | The item's attributes will also appear at this time. |
mkdir 成功后,内核会立刻在这个新目录里,为你生成一堆配置文件,这些文件就是这个新对象的可配置属性
比如我们 mkdir g1 之后,ls /config/usb_gadget/g1 可能会看到类似这样的东西:
1 | idVendor # 厂商ID |
2.4 写入配置
1 | write(2) can store new values. |
也就是你用 echo 往这些属性文件里写东西,就等于在设置内核里那个对象的参数
比如让它模拟成键盘
1 | mkdir /config/usb_gadget/g1/functions/hid.usb0 |
2.5 激活
1 | [configfs handles] the filesystem representation... allowing the subsystem to ignore all but the basic show/store interaction. |
内核模块本身不关心你是怎么创建和配置的,它只在最后一步,等待激活
例
1 | # 找到你手机的 USB 控制器名称 (比如 a12345.dwc3),然后把它写入 UDC 文件 |
当 UDC 文件被写入时,内核的 USB Gadget 模块会收到一个Commit信号
它会读取你刚才在 g1 目录下做的所有配置,把它们组装成一个完整的 USB 设备描述符
然后,它会命令物理 USB 控制器断开当前的连接,并以键盘身份重新连接到主机
这样,就完成了 Android设备模拟成键盘输入设备的操作。
3. 我是如何救砖的
确保你的android手机已root,安装前文的两个开源工具,在Gadget Tool中授予su权限,并勾选启用HID Keyboard,便完成了Android设备模拟成键盘的操作
使用数据线将Android设备接入ubuntu主机,此时手机会被识别成输入设备,当你按下HID Keyboard提供的软键盘时,是能够看到IO灯闪烁的,接下来的诊断完全是靠IO灯判断的
尝试输入密码并等待十秒,建议直接使用root账号,可以省去sudo的麻烦,
这种情况在乎用户组安全没啥必要,随后执行ls观察IO灯是否剧烈闪烁,如果剧烈闪烁则说明ls成功提供了输出,为了稳妥起见,这里决定reboot一下,主机重启,说明我们登录操作没问题Chongxi这里是提前准备过一个恢复脚本,防止这种铸币情况,主要功能是恢复原来的网卡备份的内容。再次通过io灯判断输入,直接执行恢复命令,主机重启,打开openwrt,发现ubuntu对应的LAN口开始有正常流量通信,ssh可以正常连接,救砖成功
4. 结
本文确实已经超出了普通Linux桌面版使用的范畴,可以说是纯粹的炫技,需要你的设备内核支持且已root,可以说是天时地利人和都很考验的一种解决方案
对于Linux玩家来说,没有绝对的死局,只有你还未发现的后门,这就是卓越的开放性
- 标题: 仅用Android手机拯救Linux主机,带你深入了解USB Gadget
- 作者: Chongxi
- 创建于 : 2025-12-16 16:34:26
- 更新于 : 2026-01-03 03:01:44
- 链接: https://blog.chongxi.us/2025/12/16/aKeyboardHsf/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。