对 M6 智能健身手环进行逆向工程(上)
2021-08-02 11:30:00 Author: www.4hou.com(查看原文) 阅读量:78 收藏

概述

1、了解它的硬件

2、弄清楚如何与它交谈

3、转储其库存固件

4、让它运行自定义代码,最好利用它:

  ▪GPIO 引脚(用于输入和输出)

  ▪彩色显示

  ▪蓝牙低功耗 (BLE) 功能

硬件介绍

拆开塑料外壳,我们看到了一些有趣的东西:

▪Telink TLSR8232芯片系统(SoC)

▪0.96 英寸(160x80 像素)彩色显示屏

▪一个约 100 mAh 的微型锂电池和 USB 充电电路

▪振动电机

▪一个(最有可能的)假心率传感器

核心组件

3.jpeg

印刷电路板全图

M6中的SoC是Telink TLSR8232(数据表),规格如下:

▪32位中央处理器:封闭式架构(通常称为tc32,类似于ARM9,关于它的介绍并不多)和24 MHz 时钟速度;

▪16kB 的 SRAM;

▪512kB 内部闪存;

▪用于低功耗模式的 32kHz 板载振荡器;

▪用于调试和编程的 SWS(Single Wire Slave)接口;

▪集成蓝牙低功耗 (BLE) 收发器;

▪低功耗运行(据称在深度睡眠中约为 2 uA);

幸运的是,就在几个月前,研究人员在其破解的小米温度计中看到了Telink芯片。此时,我用@atc1441 的替代固件重新刷了它。尽管它是不同的 SoC 模型,但这给了我一点希望和一个有价值的起点。

焊盘

焊盘 (Exposed-Pad),有些封装具有裸露焊盘,用来改善器件散热的焊盘。通常为非电气绝缘,可根据电连接要求将其接地或电源。

4.jpeg

印刷电路板底部

5.jpeg

印刷电路板底部

除了万用表、数据表,我什么也没有,我试图找到这些焊盘的连接位置。这就是我想出的:

6.png

单线(又名 SWire 或 SWS)接口

现在我们确定了手环的核心部件,如果你之前对 ESP32 进行过编程,你可能会依赖其引导加载程序并通过 UART 与它通信。如果你之前编程或调试过 ARM 微控制器,你可能使用了 SWD(串行线调试)协议。

在Telink-land 中,类似的接口称为Single Wire 或SWire。这就是应用程序如何加载到其闪存中、如何读取和写入内存以及如何在运行时调试的方式。

然而,当我们尝试了解有关此界面的更多信息时,真正的挑战才刚刚开始。在现实世界中,这些芯片是使用Telink官方的调试工具进行调试的。

研究人员在找到存储库 TlsrTools 时,其中有对 SWire 协议的两页描述。这似乎是一个旧版本的Telink数据表的一部分,已经被删除。

从 Pascal 到 Python

在编程/调试芯片时,通常有三个活动部分:

▪我们要编程的目标板

▪程序员硬件

▪与程序员通信的计算机软件

计算机软件的作用是向程序员硬件发送命令,并使其从目标板读写数据。由于研究人员手边没有Windows设备,所以我实现了一个基本的Python脚本,即 tlsr82-debugger-client.py,它作为计算机软件组件工作。

我们现在可以使用这个 Python 脚本和 STM32 来解密 M6 手环中隐藏的信息。设置如下:

7.png

基于 STM32 的替代编程设置

SWire 规范

顾名思义,单线用于在两个设备之间来回传输数据。在我们的例子中,STM32 编程器(主)和目标板(附属)。没有像 SPI 或 I2C 那样单独的时钟线。单线拓扑允许两个设备通信,但它们不能同时通信。换句话说,我们可以将 SWire 称为异步、半双工接口。

这意味着:

▪异步:由于没有共享时钟,两个设备必须以某种方式采用兼容的读写速度;

▪半双工:每个设备必须知道什么时候应该监听消息,什么时候允许传输消息。

为了实现协调,SWire 协议将责任归属于主盘和附属设备。主盘负责发起通信并管理数据传输之间的总线逻辑层。从盘负责在预期的时间发送数据。下面我将一些真实世界的例子放在一起,以便更清楚地说明这一点。

发送单个位

首先要注意的是位是如何在线路中编码的。每个位以五个时间单位传输:

▪要发送 0,请保持 1 个单元的低电压和 4 个单元的高电压;

▪要发送 1,保持低电压 4 个单位时间和高电压 1 个单位;

具体来说,这是我用逻辑分析仪捕获的真实 SWire 传输:

8.png

SWire 中 0 和 1 的示例

在上面的截图中,标记为 25 和 26 的标志之间有 8 位正在传输,但是很难解码。

发送单个字节

我们现在知道为了传输一个完整的字节,SWire 协议规定需要 9 位:

▪位 1:cmd 位。 0 指定消息包含数据,1 指定消息是命令;

▪位 2-8:消息内容(8 位);

▪低级别的一个时间单位表示消息结束;

另外,让我们看一下 0xb0 字节的真实示例传输:

9.png

在 SWire 中发送一个字节的示例

发送最后一个低级别后,总线被释放并恢复到其自然高电压。换句话说,SWire 数据总线被拉高。

写入请求

如上所述,单个位和字节是如何在线路中编码的。接下来,我们来看看SWire协议是如何指定要写入特定地址的字节的。在该示例中,主盘希望将一个字节b写入从盘内存中的地址addr。

为此,主盘必须发送一个字节序列,每个字节都按照上一节所述进行编码:

▪START字节,这个值总是 0x5a;

▪目标addr的最高有效8位;

▪目标addr的最低有效8位;

▪RW_ID字节,最重要的位应该设置为0,用于写入操作;

▪字节值 b;

▪END字节,它的值始终为 0xff;

让我们看看下面的例子:

10.png

在 SWire 中写入数据的示例

在这个例子中,我们可以看到字节 0x05 被写入从盘的内存地址 0x0602。

SWire 协议的变体

值得注意的是,至少存在一个SWire协议的变体。在另一种变体中,主盘在 START 字节之后发送 3 个字节的 addr,而不是在我们的 SWire 协议中仅发送两个字节。例如,Telink 的 TLSR8251 SoC 中采用了 3 字节变体,用于我们上面提到的小米温度计。在 ATC_MiThermometer 存储库中基于 Python 的闪光器中,我们可以看到在从主盘到从盘的读/写请求中指定了 3 个字节的 addr。

写入多个字节

这是写入单个字节要花费的能力,幸运的是,该协议让我们一次写入多个数据字节。为此,主盘只需发送一个字节序列,而不是像上面示例中的单个字节。

本文翻译自:https://rbaron.net/blog/2021/07/06/Reverse-engineering-the-M6-smart-fitness-band.html如若转载,请注明原文地址


文章来源: https://www.4hou.com/posts/L04g
如有侵权请联系:admin#unsafe.sh