首页
社区
课程
招聘
[原创] 破解小米手表S3实现原神启动
发表于: 2024-6-1 12:59 24633

[原创] 破解小米手表S3实现原神启动

2024-6-1 12:59
24633

S3是小米最新发布的智能手表,搭载小米基于NUTTX系统二次开发的Vela系统。Vela是RTOS系统,与传统的安卓系统穿戴设备有一定区别。本文通过Hack小米S3手表,成功实现原神启动。

引言

小米手表S3搭载了小米基于NUTTX系统二次开发的Vela系统,这是一款实时操作系统,与传统的安卓穿戴设备有一定区别。S3的应用自然也不是安卓APK应用,而是快应用(QuickAPP),一个由国内几家手机厂商联合推动的一个类似微信小程序的应用标准,这种应用使用JS开发,使用了与安卓APK类似的签名机制。本文的研究目标就是破解S3手表,让它安装我们修改后的应用,实现原神启动。

要实现这一目标,我们需要解决以下两个挑战:

  • 推送任意快应用进入S3手表安装 很显然,我们需要把修改后的快应用推送到S3手表内安装。S3手表不具备网络通信功能,它与外界通信都是通过蓝牙实现的,协议分析有一定挑战性,但我们会介绍一个TRICK绕过这一难题
  • 具备快应用的签名能力 修改快应用后不进行二次签名会无法通过完整性校验,导致安装失败

方法

任意快应用安装

前文提到过,S3手表不具备网络连接能力,那么它是如何完成应用安装功能的呢?小米提供了一个小米运动健康APP,通过这个APP与手表配对后,在APP中的设备页面,有应用商店选项,点击进入后可以安装手表应用。在安卓手机上,这个过程是通过蓝牙串口通信协议完成的,用户先在小米健康APP上下载要安装的手表应用,然后通过蓝牙串口通信协议把下载的应用传输进入手表安装。

要实现任意应用安装,传统的方法是分析蓝牙通信协议,蓝牙通信协议相关代码在com.xiaomi.wearable.wear.api.SppConnection,com.xiaomi.wearable.wear.queue.BleTaskQueueV2中。但是其实可以使用一个TRICK绕过协议分析的问题,手表应用安装的过程首先需要下载应用到安卓本机,那么只需要在下载完成后替换下载的应用为我们修改的应用,就可以实现任意应用安装。

要实现替换应用,需要访问本机文件,Frida JS API没有文件访问API。我将演示如何使用我开发的pyfrida框架非常自然地完成替换过程。pyfrida框架支持直接使用Python编写Frida HOOK脚本,详细可以见文章末尾往期推送。

快应用下载相关代码在com.xiaomi.xms.wearable.ui.appshop.manager.AppDownloadManager类中,该类的getAppFilePath方法是我们需要HOOK的方法。因为在下载快应用后,会调用这个方法获取快应用在安卓本机上的路径,参数就是快应用包名。

接下来,我演示如何通过HOOK这个方法,把下载的快应用拉取到电脑。首先使用pyfrida编写HOOK脚本,然后在安卓手机上安装一个手表应用。如下图所示,get_filepath方法是我们的替换方法,在其中通过调用adb pull拉取下载的快应用到电脑。getAppFilePath方法被调用了两次,第一次调用是下载前被调用,作为下载目标路径,第二次调用是下载后调用,因为要把下载的快应用推送到S3手表。使用pyfrida框架可以很流畅地完成这个过程,因为可以直接使用Python编写Frida HOOK脚本,而如果使用传统的Frida HOOK脚本工作流程,则需要使用Socket通信实现类似功能,较为繁琐。

HOOK结果打印

安装手表应用

完整代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from pyfrida import pyfrida
from pyfrida.pyfrida import JSObject, JSContext
import frida
import os
 
def setup_hook(ctx: JSContext):
    clz = ctx.Java.use("com.xiaomi.xms.wearable.ui.appshop.manager.AppDownloadManager")
    clz.getAppFilePath.implementation = js_getfilepath
 
def get_filepath(ctx: JSContext, a1: JSObject):
    r = ctx.this.getAppFilePath(a1)
    print("参数: ", a1.get_val(), "返回值: ", r.get_val())
    os.system("adb pull %s 1.rpk" % (r.get_val(), ))
    return r
 
device = frida.get_usb_device()
 
fs = pyfrida.FridaScript()
js_setup_hook = fs.add_js_function(setup_hook)
js_getfilepath = fs.add_js_function(get_filepath)
 
ps = device.get_process("小米运动健康")
fs.attach(device, ps.pid)
 
fs.exec_func_in_java(js_setup_hook)
 
input()

基于pyfrida框架,如果要实现替换应用也很简单,只需要在触发HOOK时,执行adb push上传应用即可。

快应用签名

刚刚下载到的RPK文件是一个ZIP包,与安卓APK类似,它也有两处签名。一处是简单的完整性校验,有一个文件记录了ZIP包内其它条目的SHA256摘要,类似安卓V1签名,一处是修改校验,它在ZIP包中添加了签名快,类似安卓V2签名。接下来依次介绍这些签名。

V1签名


[注意]看雪招聘,专注安全领域的专业人才平台!

收藏
免费 4
支持
分享
最新回复 (5)
雪    币: 4196
活跃值: (4552)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
厉害了。
2024-6-1 15:58
0
雪    币: 309
活跃值: (2417)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
我还以为真原生跑元神呢
2024-6-1 17:33
2
雪    币: 3098
活跃值: (5758)
能力值: ( LV9,RANK:225 )
在线值:
发帖
回帖
粉丝
4
轻装前行 我还以为真原生跑元神呢
标题玩个烂梗罢了
2024-6-1 19:11
0
雪    币: 686
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
y3c能用吗
2024-6-1 20:50
0
雪    币: 712
活跃值: (1273)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
大佬,我看到你的github上有romfs的rom解包的代码,但是没有对应的打包代码,想求一份可以打包romfs的代码
2024-7-10 18:19
0
游客
登录 | 注册 方可回帖
返回