# 果加智能门锁的全面分析（中）

## 前言

在本专题的上一篇中，完成了用IDA加载解析家庭版果加智能门锁的固件。用IDA加载解析只是准备工作，理解这些代码才是最终目的。本篇就开始尝试分析这些代码。

仔细看一下IDA解析出的代码，内容多，没有调试信息，也没有可参考的字符串，这就导致很难弄清楚这些代码的作用，更遑论分析代码。所以，在本篇中尝试以BLE通信为突破口，以此来研究一下这大片代码的含义。根据BLE通信的特征，有2个方法找到固件中的关键代码。如下：

A.  通过果加BLE通信的帧格式，直接在代码中定位帧格式中的常量，可以快速找到BLE通信数据的解析函数。

B.  通过硬件电路，找到MCU与BLE芯片的通信引脚。然后查看文档确定该引脚映射的内存地址，最后定位到代码中BLE发送和接收函数。

这里采用A方法，B方法会在接下来的文章中介绍。家庭版果加智能门锁与配套的果加app进行BLE通信，所以通过逆向果加app可以确定BLE通信数据包的格式，并在格式中找到帮助我们定位固件代码的常量。所以我们先开始app的逆向分析。

## app分析

### 2.1 Java层分析

在本专题的前几篇文章中，我们已经分析过几个app了，这里也采用类似的方法。首先来观察果加app输出的日志，幸运的是笔者在2018年分析的果加家庭版智能门锁app并没有隐藏日志内容，而是大大方方的打印了出来。通过搜索日志内容中的关键字符串，我们很容易定位到发送BLE开锁指令的关键代码在cn.igoplus.locker.ble包中，截图如下：

![图2-1 BLE开锁时的关键代码](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdFJ10CuD2SzdsVLTPD%2F-MdFLw4sGBTEbKkztFin%2Fimage.png?alt=media\&token=ddd7aecc-ece2-4c24-beea-00b1221e56b6)

上图为通过JEB反编译工具分析该apk的截图。进一步追踪BLE通信数据的生成过程，可以发现所有BLE通信指令的生成全部都在native函数中，这些native函数的声明在cn.igoplus.locker.ble.cmd包中，如下图所示：

![图2-2 BLE指令的生成函数](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdFJ10CuD2SzdsVLTPD%2F-MdFM-IhvmXsk7GyaQIn%2Fimage.png?alt=media\&token=bec44e1c-03fe-4b18-a8ea-4b590d446e39)

这些函数的定义在都在libBleCmd.so中，翻阅代码就可以找到该so的名称和加载位置，如下图所示：

![图2-3 BLE通信数据由libBleCmd.so生成](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdFJ10CuD2SzdsVLTPD%2F-MdFM3ssX1xc1UD-zT8w%2Fimage.png?alt=media\&token=a5531f15-c8ef-4244-852e-68f1d6c55d78)

那么，就开始分析该so的代码吧。&#x20;

### 2.2 Native层分析&#x20;

通过zip工具解压缩apk程序包，在lib\armeabi-v7a文件夹中即可找到libBleCmd.so库文件，如下图所示：

![图2-4 libBleCmd.so文件位置](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdFJ10CuD2SzdsVLTPD%2F-MdFM8euNftx4QZ7P8av%2Fimage.png?alt=media\&token=030aba11-627a-4dfd-9c71-ce113ce26cdb)

该文件可以被IDA自动解析，并不需要像上一篇解析固件那样进行一系列的配置工作，如下图所示：

![图2-5 IDA自动解析liBleCmd.so文件](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdFJ10CuD2SzdsVLTPD%2F-MdFMCEOoPSK8v5zkLJK%2Fimage.png?alt=media\&token=fc9a5716-c848-4cb1-a2c0-a073cb282386)

待解析完毕之后，我们可以打开Exports选项卡，查看这个so文件的所有导出函数，如下图：

![图2-6 libBleCmd.so的导出函数](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdFJ10CuD2SzdsVLTPD%2F-MdFMFKWtZsLY4-1JVoj%2Fimage.png?alt=media\&token=871ab99e-ee0c-4770-baa7-b35154208423)

在导出函数中可以找到所有BLE指令的生成函数，以及Decrypt和Encrypt用于加密或者解密BLE通信数据的函数，看函数命名应该是和Tea算法有点关系。在Tea算法中，存在几个常量用于加密或解密运算，而这几个常量就可以帮助我们定位关键代码。所以，我们跟进Decrypt函数看一下，得益于强大的Hex-Rays Decompiler插件，我们可以按F5快捷键，直接查看关键位置的伪代码：

![图2-7 Decrypt函数的实现](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdFJ10CuD2SzdsVLTPD%2F-MdFMJmayHyhvlA03CPH%2Fimage.png?alt=media\&token=b6dcd7a7-c236-4604-9cc4-f692f7a51796)

上图中，我们用红框标识出了2个常量，接下来就通过这些常量分析一下固件代码。

## 固件分析

开始固件分析之前，首先按照本专题上一篇中的相关内容，完成IDA对固件的加载工作。这里有一点要说明，从上一篇的截图中，可以看到Armv6-M是Armv7-M的子集，所有Armv6-M可运行的程序能够直接移植到Armv7-M架构上，将上一篇的截图复制过来如下：

![图3-1 Armv6-M与Armv7-M的关系](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdFJ10CuD2SzdsVLTPD%2F-MdFMWb2Yx5xQZFEHlf6%2Fimage.png?alt=media\&token=77897c1b-c608-49c2-990d-f86a8cf5f2a8)

在上一篇中，解析时设置架构为Armv6-M，但是发现有些指令无法在IDA中使用Armv6-M架构进行反汇编，当改为使用Armv7-M架构时，很顺利地解析了所有指令。在后文中，一律采用Armv7-M架构进行解析。

完成解析之后，就需要在固件文件中查找2-2节提到的常量，按alt + t快捷键，搜索我们找到的常量，如下图所示：

![图3-2 在IDA中搜索关键常量](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdFJ10CuD2SzdsVLTPD%2F-MdFMZqK_CsTF8X-1VDi%2Fimage.png?alt=media\&token=b2b928f1-8161-4b6f-83e1-ac41f75b779f)

搜索结果如下：

![图3-3 关键常量搜索结果](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdFJ10CuD2SzdsVLTPD%2F-MdFMc9gZbA244YVXxaT%2Fimage.png?alt=media\&token=ea275af6-8b9e-4403-9e96-da6a43f63dea)

经过反复对比libBleCmd.so的Decrypt函数和固件F0-S1\_1\_1-H1\_0-R.bin的代码之后，我可以确定固件中Encrypt和Decrypt函数的位置，如下图：

![图3-4 固件中的Encrypt和Decrypt函数](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdFJ10CuD2SzdsVLTPD%2F-MdFMfDRbpESH-cCNsqb%2Fimage.png?alt=media\&token=7c40b10f-8763-4ec7-b5a5-3e6cbeba7468)

上图中，其他位置的代码虽然也引用了常量‘0xCE6D’，但看代码内容不太像是Encrypt和Decrypt函数。

在此基础之上，我们查找Decrypt函数的交叉引用，可以定位到代码如下图所示：<br>

![图3-5 查找Decrypt函数的交叉引用](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdFJ10CuD2SzdsVLTPD%2F-MdFMiB_2_WubyKHE3Mx%2Fimage.png?alt=media\&token=455c78b7-a27c-47c1-b51c-29875ca88b74)

上图中，两处关键代码已经用绿框圈出。首先看第一处关键点，即0xBABEC0DE位置，如果有读者看过家庭版果加智能门锁app的日志，肯定会记得这个常量，部分日志内容截图如下：

![图3-6 家庭版果加门锁app的日志](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdFJ10CuD2SzdsVLTPD%2F-MdFMl_IgnsfJSTkveAi%2Fimage.png?alt=media\&token=c9019dfd-05d4-4c34-98a9-81c02d798c86)

可以看到，BLE消息就是以0xBABEC0DE字节开头。由此可以推断，图3-5中的固件代码应该是在处理接收到的BLE消息。进一步分析代码，可以确定Decrypt函数的三个参数分别为：消息密文，消息长度和解密密钥，并由此推断内存MEMORY\[0x20001848]开始的几个字节应该是存储解密密钥。通过搜索MEMORY\[0x20001848]的交叉引用，可以找到密钥的生成代码、使用代码等，并由此进一步扩大我们对固件代码的理解，但这里就不再深入分析了。

通过对上述代码的分析，我们可以猜测图3-5中的sub\_800B528函数具体功能应该是对接收到的消息进行预处理，检验消息头是否正确，crc校验是否正确，是否可以成功解密等。如果一切都顺利，那么该函数返回0。搜索sub\_800B528函数的交叉引用，可以定位到sub\_800EB20函数，如下图所示：

![图3-7 sub\_800EB20函数](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdFJ10CuD2SzdsVLTPD%2F-MdFMqp-xYdzPcDFfX2N%2Fimage.png?alt=media\&token=e1185598-f44c-4d21-b51b-735678b1f8b0)

通过分析上图中的代码，可以确定该函数其实是对sub\_800B528函数的封装，根据sub\_800B528的返回值，设置某些关键的内存。此外，还可以分析得出以内存0x20002D44开始的几个字节中，存储的是收到的BLE消息密文；内存MEMORY\[0x20000174]存储的是接收到的BLE数据长度。由此，我们对固件代码的理解逐步增加。

继续向上回溯调用sub\_800EB20函数的位置，我们可以找到sub\_80000C8函数。这个函数非常大，且非常复杂。具体的分析就留到下一篇中在进行讨论吧。

在本篇中，我们对家庭版果加智能门锁的配套app进行了简单的分析，着重研究了其BLE指令的构造过程以及so中的BLE指令加密和解密算法。然后根据BLE指令的特征，我们在门锁的固件中定位到了解析BLE指令的代码，并根据定位到的代码逐步理解认识整个果加门锁固件的逻辑。
