# 海康萤石智能门锁的网关分析（4）

本篇是关于海康萤石智能网关分析的第4篇，在此前的3篇文章中，我们已经完成了固件编辑和重打包，通过telnet登陆固件系统，以及使用gdbserver调试程序，在此基础之上，相信读者完全可以对设备固件进行独立分析了。&#x20;

在这海康萤石智能网关的最后一篇文章中，我们就把上次的遗留问题处理了，即设备的认证方式以及加密密钥生成方法。

## **程序分析**

### **2.1 概述**

在上一篇的结尾部分，我们已经具备了调试能力，可以调试固件中的davinci程序以及libmicrokernel.so.1等动态连接库。为了节约篇幅，在本篇中我们先将一些分析结论与各位分享，然后再详细调试其中的某个细节。

在海康萤石的智能网关中，完整的通信流程涉及到3个密钥，分别是share key、master key以及session key。顾名思义，share key是智能网关与litedev服务器（与之对应的另一个服务器是MQTT服务器）共有的密钥，由设备序列号等常量经过多次MD5运算得到，每个智能网关设备的share key都是独一无二的，；master key是智能网关与litedev服务器经过密钥协商而来，用于加密传输session key，关于master key的密钥协商过程就是本篇分析的重点内容；最后session key是智能网关与MQTT服务器通信时使用的加密密钥，该密钥由litedev服务器直接下发给智能网关。

以上三个密钥在使用过程中，share key是与设备绑定，且固定不变的，一旦获取了share key，就可以完成所有的认证过程，最终被海康萤石认定为合法的网关设备；使用者通过手机app绑定智能网关时，会经过密钥协商生成master key，每绑定一次会就更新一次；最后的session key则每次运行davinci程序时，都会更新，这也意味着每次重启网关都会更新session key。三个不同级别的密钥，三个不同的密钥生存周期。&#x20;

在对海康萤石智能网关的密钥体系有所了解之后，我们就可以聚焦到某些细节上，下面来着重看一下master key和share key的生成过程。

### **2.2 master key生成**

#### **2.2.1 认证细节分析**

为了触发智能网关的密钥协商流程，我们需要先删除当前的master key，具体讲就是删除 “/cfg/dev\_masterkey”文件，如下图所示：

![图2-1 删除dec\_masterkey文件](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdKh8JZhJK-4LSXYEdv%2F-MdLH5-Jx9dgRrXq716s%2Fimage.png?alt=media\&token=f3f64e75-ac4b-4b07-87dd-ddf570b7e84d)

删除当前master key之后，继续按照上一篇所述的方法启动调试器，并在上一篇结尾时提到的send\_authentication\_i函数下断点，等到程序中断到调试器中，如下图所示：

![图2-2 程序中断在send\_authentication\_i函数](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdKh8JZhJK-4LSXYEdv%2F-MdLH7mn_tTgt2wM46Ux%2Fimage.png?alt=media\&token=ff4243c9-c1fd-42d1-8eb5-2a0537de3c35)

通过逆向分析该函数，可以获知它调用的common\_serialize和authentication\_i\_serialize用于构造将要发送的数据。我们在common\_serialize函数之前下断点，然后用gdb命令查看待发送数据的内容（本次调试时，地址为0x007d2dd0），如下图所示：

![图2-3 第一次打印发送数据](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdKh8JZhJK-4LSXYEdv%2F-MdLHCDTCc4_LXvgE9zT%2Fimage.png?alt=media\&token=e2c13e54-8c9e-451e-b6bc-4220c8920f21)

在上图中，可以看到待发送数据内容还是空的。待函数common\_serialize执行完毕之后，重新打印该地址的数据，如下图所示：

![图2-4 第二次打印发送数据](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdKh8JZhJK-4LSXYEdv%2F-MdLHEl95ASGbPrR8Li9%2Fimage.png?alt=media\&token=9350fd73-9be6-4ffe-8086-c9b731ad4663)

该地址的前几个字节已经被赋值了。继续调试该程序，在authentication\_i\_serialize函数之后下断点，待程序中断时，重新打印该内存处的数据，如下图所示：

![图2-5 第三次打印发送数据](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdKh8JZhJK-4LSXYEdv%2F-MdLHKofgaGqlDoCKFeE%2Fimage.png?alt=media\&token=f85aca53-9063-436e-aab8-01d23c9ee901)

可以观察到，authentication\_i\_serialize函数执行完毕之后，待发送数据基本构造完毕。我们对比一下本次发送数据和之前我们通过wireshark抓包获取的发送数据，如下图所示：

![图2-6 此前wireshark的抓包结果](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdKh8JZhJK-4LSXYEdv%2F-MdLHNQzXl79sN2DHitB%2Fimage.png?alt=media\&token=dc4919c2-d24e-467e-b13d-1f422981958e)

可以看到，本次构造的发送数据与之前的抓包结果是有一小部分相同的，而不同的这部分应该就是海康萤石智能网关密钥协商的关键部分。&#x20;

为了找到产生不同的原因，我们来重点逆向authentication\_i\_serialize函数，可以在该函数中发现其调用了一个签名函数digital\_sign\_serialize函数：

![图2-7 authentication\_i\_serialize函数的内部](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdKh8JZhJK-4LSXYEdv%2F-MdLHS5pZ_fLY8BwH1XE%2Fimage.png?alt=media\&token=e1c67cbf-e66d-4214-aeb1-54fa0eafaf1c)

在该签名函数之前和之后下断点，可以观察到需要签名的数据以及签名结果。结合之前用gdb调试send\_authentication\_i时获得的发送数据，就可以分析出发送的数据格式如下：

![图2-8 send\_authentication\_i函数发送的数据格式](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdKh8JZhJK-4LSXYEdv%2F-MdLHVP9RF6Yhm7mLD8X%2Fimage.png?alt=media\&token=1d099ca1-f968-4b20-bed3-9b8cb8c0258f)

其中，dev\_subserial是设备序列号；random\_1是1字节随机数，每次密钥协商时都是不同的。由于random\_1字节的不同，导致了digital\_sign不同，所以总共有33（1+32）字节是每次通信都不同的。经过本次通信，智能网关将random\_1参数上传至litedev服务器。&#x20;

通过类似的分析方法，就可以获知认证过程中的其他3个函数的作用，这3个函数分别是：wait\_authentication\_ii、send\_authentication\_iii以及wait\_authentication\_iv。加上send\_authentication\_i函数，网关和服务器之间总共同步了4个随机数。

#### **2.2.2 认证完整过程**

在上述的分析过程中，可以发现一个名为lbs\_affair的结构体贯穿了整个认证过程，4个随机数也保存在结构体之中，该结构体的内容如下：

```
00000000      lbs_affair struct
00000000      random_1:             .byte
00000001      random_2:             .byte
00000002      random_3:             .byte
00000003      random_4:             .byte
00000004      dev_subserial:        .byte 16
00000014      master_key:           .byte 16
00000024      dev_id:                 .byte 32
00000044      session_key:           .byte 16
00000054      share_key:             .byte 32
00000074      share_key_len: .half
00000076                                  .byte
00000077                                .byte
00000078      global_out_packet: lbs_packet
0000008C      global_in_packet:   lbs_packet
000000A0      lbs_net_work:        .word
000000A4      lbs_affair ends
```

表2-1 lbs\_affair结构体

其中，random\_1和random\_3由智能网关生成，发送给服务器；random\_2和randon\_4由服务器生成，发送给智能网关。&#x20;

通过这4个随机数以及share key就可以生成master key了，并进一步由master key获取session key。其master key的生成算法比较简单，可以在generate\_masterkey函数中找到，如下图所示：

![图2-9 master key的生成过程](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdKh8JZhJK-4LSXYEdv%2F-MdLHgvfJXkaKJaj8CNK%2Fimage.png?alt=media\&token=0a369b79-76d4-439f-834f-800a34324f5b)

根据图中红框标出的偏移可以知道，master key的生成过程就是将random\_1、random\_2、random\_3、random\_4和share\_key拼凑在一起，然后调用sha512函数，其hash结果就是最终的master key了。&#x20;

继续分析其固件的后续内容可以发现以master key作为密钥，使用aes cbc算法解密session key相关的代码段，这里就不截图了。获取session key之后，通信数据的加密密钥就完全切换为session key，不再使用master key了。

### **2.3 share key生成**

相比于master key的生成过程，share key的生成无疑简单了很多。可以在generate\_sharekey函数中找到关于share key的各种运算，通过阅读IDA反汇编后的代码，可以确认share key是通过对dev\_subserial和dev\_verification\_code以及一个固定的盐进行多次MD5而得到，其中dev\_verification\_code是设备的认证码，该认证码被贴在海康萤石智能网关背面的标签上。在md5运算过程中，固定的盐值如下图所示：

![图2-10 share key的生成过程](https://3519990514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Mc9RUlvJLCDxdpf1zh2%2F-MdKh8JZhJK-4LSXYEdv%2F-MdLHnM8d0W1ZN9BwtSe%2Fimage.png?alt=media\&token=7d05ccae-8202-41dc-b234-f4925d46c83c)

上图中，“ 88075998”是海康的联系电话，在此处，“[www.88075998.com”作为盐参与了第二次MD5运算中。](http://www.88075998.com”作为盐参与了第二次MD5运算中。)

## **小结**

到此，关于海康萤石系列的四篇文章就结束了。在前3篇文章中，我们分别解决了开启uart串口、提取flash内容、固件重打包、gdb调试等问题；而在最后1篇中，我们分析了海康萤石的密钥体系，虽然写的有些模糊，但基本上涵盖了所有关键点，很多海康和萤石的其他IoT设备也使用了类似的密钥体系，本篇分析可以提供一个借鉴。
