前言
由于Vivo的骚操作,我们无法直接使用[fastboot oem unlock]命令来解锁。Vivo的解锁命令为[fastboot vivo_bsp unlock_vivo],但是安卓官方的fastboot并不会识别这个命令,而是直接当作unknown command:
fastboot_unknown_command.png (28.85 KB, 下载次数: 0)
下载附件
2022-9-28 17:16 上传
因此需要在fastboot的代码中添加一条else if条件并调用do_oem_command函数:
fastboot_vivo_bsp.png (41.77 KB, 下载次数: 0)
下载附件
2022-9-28 17:17 上传
XDA上也有大神编译了修改版(例如https://forum.xda-developers.com/t/how-to-unlock-bootloader-of-vivo-phones.3686690/)。然而网上似乎并没有找到适用于MacOS的修改版fastboot的可执行文件,由于硬盘容量有限,本人也未能自行编译fastboot。受限于此,本人通过对fastboot进行usb抓包分析,并使用pyusb模拟fastboot对手机发包,来实现同等效果。我的型号是Vivo Y31S高通版,其他型号也可以作为参考。该方案并非官方方案,解锁有风险,操作前记得先备份好数据。
USB抓包
在抓包之前,首先需要重启进入恢复模式,在终端输入[csrutil disable]关闭SIP。重启之后,在终端输入[tcpdump -D]查看接口列表:
list_interfaces.png (418.24 KB, 下载次数: 0)
下载附件
2022-9-28 17:18 上传
这里我连接手机使用的usb接口对应的是XHC1,所以接着在终端输入[sudo ifconfig XHC1 up]来开启接口。手机关机后长按电源键+音量+键进入fastboot模式。
接着打开Wireshark,选择XHC1开始抓包。如果是通过hub来连接手机的,需要在系统报告中找到对应的接口的位置ID,然后在filter中用[usb.darwin.location_id == 位置ID]来过滤出手机的包,例如[usb.darwin.location_id == 0x01130000]。
usb_info.png (168.24 KB, 下载次数: 0)
下载附件
2022-9-28 17:19 上传
例如,打开fastboot对手机发一个[fastboot oem unlock],可以得到如下几个包:
fastboot_captured.png (132.42 KB, 下载次数: 0)
下载附件
2022-9-28 17:20 上传
可以观察到,当发送一个命令的时候,首先会给in和out两个端点分别发送一个clear halt的请求,再通过out端点向手机发一个bulk包,最后从in端点从手机接收一个bulk包。
clear_halt.png (60.6 KB, 下载次数: 0)
下载附件
2022-9-28 17:21 上传
bulk_info.png (257.73 KB, 下载次数: 0)
下载附件
2022-9-28 17:20 上传
bulk_out_content.png (98.51 KB, 下载次数: 0)
下载附件
2022-9-28 17:21 上传
bulk_in_content.png (106.05 KB, 下载次数: 0)
下载附件
2022-9-28 17:20 上传
这里仅以发送命令为例,别的操作就不一一展示了。总之,抓取了这些usb包之后,就可以根据它们来写代码复现。
Python复现
首先安装libusb和pyusb:
[Shell] 纯文本查看 复制代码brew install libusb
brew install libusb-compat
pip3 install pyusb
完整代码放在了https://github.com/h4ckm310n/Unlock-Vivo,这里主要说说几个步骤。
首先是初始化,根据厂商和产品ID找到对应的设备,并且对接口进行claim操作。网上看到的代码好像都没写claim这一步,但是我如果不写这一步的话,在发包的时候就会找不到端点,不知道这是不是Mac的问题,我在这里纠结了很久,最后慢慢摸索出来的。同样,在结束运行之后,也需要对接口调用release操作。
func_init_phone.png (64.59 KB, 下载次数: 0)
下载附件
2022-9-28 17:22 上传
在发包之前,还要先对两个端点进行clear halt操作:
func_clear_halt.png (30.96 KB, 下载次数: 0)
下载附件
2022-9-28 17:25 上传
后面的刷vendor和解锁操作都是通过这个函数发送bulk包:
func_send_bulk.png (49.79 KB, 下载次数: 0)
下载附件
2022-9-28 17:25 上传
我之前也没搞懂vendor.img是哪来的,后来我发现这个文件的内容就只是一堆0而已,所以可以自己生成。3个getvar命令似乎没啥必要,不过我还是一并复现了,没试过去掉有没有影响。在发送vendor数据本身之前,需要先发一个download命令,后面接的是vendor的数据大小。
func_flash_vendor.png (171.58 KB, 下载次数: 0)
下载附件
2022-9-28 17:25 上传
至于刷vendor有什么用,我也没搞懂,虽然刷不进去,但在这之后再解锁就不会出现签名错误的问题了。解锁和锁定差不多,都是发送一个命令,只不过在解锁之前要先刷一遍vendor。
func_unlock_lock.png (55.23 KB, 下载次数: 0)
下载附件
2022-9-28 17:25 上传
运行的输出结果如下:
unlock_output.png (134.67 KB, 下载次数: 0)
下载附件
2022-9-28 17:25 上传
重启手机,可以看到解锁后的提示,以及清除数据的要求。
IMG_20220905_154556_edit_758404242166046-scaled.jpg (323.16 KB, 下载次数: 0)
下载附件
2022-9-28 17:27 上传