1.简介
本篇是关于海康萤石智能网关分析的第3篇,在中,我们完成了固件编辑和重打包工作。在我们自己修改的固件中,海康萤石的智能网关上电启动之后会运行telnetd,此后我们只要通过telnet远程连接网关即可使用shell,不需要再连接不稳定的串口了。
继续上一篇的内容,我们从本篇开始分析智能网关里面的关键应用,研究一下智能网关到底与服务器通信了什么内容。
2. 程序逆向分析
2.1 预处理
在海康萤石智能网关中执行ps指令,查看所有正在运行的程序,通过简单的排除法,就可以确定我们要分析主程序是:’/dav/davinci’(达芬奇?达文西?),如下图所示:
图2-1 固件中运行的所有进程
通过逆向分析davinci程序,我们可以发现该程序是有运行日志的,只是把不重要的日志屏蔽了(debug、verbose等),只输出了较为严重的日志内容(fatal、error等)。那么我们修改几条指令,使其跳过对日志严重程度的判断,如下图:
图2-2 patch日志输出代码
除了输出日志的函数需要patch之外,还有另一个函数也需要做一些调整。davinci在启动之后,初始化了一个线程操作看门狗,该线程会不断向/dev/watchdog进行写操作。如果一段时间内/dev/watchdog没有收到任何数据,那么整个设备就会重启。由于我们计划调试davinci程序,如果在调试过程中,触发断点导致看门狗线程挂起,那么整个系统就会重启。为此,我们先把该线程patch掉,然后再弄一个写入/dev/watchdog的小脚本,用以专门喂狗防止重启。相关位置的代码截图如下:
图2-2 patch watchdog相关代码
喂狗的小脚本内容如下:
图2-3 喂狗小脚本
相信脚本内容一眼就能够看懂,所以我们不做太多的解释了。此外,还有个guard.sh也是用于检测davinci程序是否运行的,但它不影响我们的操作,所以就不讨论该脚本了,有兴趣的读者可以去看看。
完成上述操作之后,就可以把被patch的davinci上传至海康萤石的智能网关,此处我们不再采用烧录固件的方法,因为过于麻烦。通过翻阅该设备的文件系统,可以在设备中发现tftp程序,这是一个使用tftp协议传输文件的程序,可以用它从tftpd服务器上传或下载文件。我们使用从这个链接下载到的tftpd程序:http://tftpd32.jounin.net/tftpd64_download.html,运行后,调整tftpd服务器的文件目录和监听网卡,如下图:
图2-4 配置tftpd程序
上图中,被patch的davinci程序就在红框标识的目录中。然后在智能网关设备中使用tftp程序获取相关文件即可,相关命令截图如下:
图2-5 使用tftp下载文件
待相关文件下载到海康萤石的设备中之后,就可以运行FeedWatchdog.sh脚本开始喂狗,然后终止原本的davinci进程,接着删除/home/pidfile文件,该文件相当于互斥体,用于控制davinci仅运行了一次,最后启动我们自己的davinci_1进程,相关命令如下:
图2-6 启动patch之后的davinci进程
待程序运行一段时间之后,就可以查看程序的运行日志,然后通过日志分析程序的各种行为。
2.2 日志分析
待程序运行一段时间之后,就会在‘/applog/devlog’目录下生成日志文件,每个文件500KB左右,如下图所示:
图2-7 程序运行时生成的日志
用tftp程序将日志取回,然后打开程序日志,在日志中搜索litedev.ys7.com,这个地址是智能网关上电之后第一个访问的地址,我们在本专题第9篇,也就是分析海康萤石智能网关的第一篇中介绍过。搜索结果如下图:
图2-8 与litedev.ys7.com有关的日志
上图中,我们可以看到由litedev.ys7.com解析而来的ip地址:115.231.107.14,这与我们用wireshark抓包时得到的结果是相同的。
继续翻看日志,在距离图2-8不远的地方,可以看到另一条日志,看起来像是与海康萤石MQTT服务器相关的日志内容,截图如下:
图2-9 与MQTT服务器有关的日志
从图中,我们可以看到另一个ip地址:101.71.30.172,该地址同样与我们wireshark抓包的结果吻合。MQTT通信协议是构建于TCP/IP协议之上的一种轻量级通信协议,经常出现在IoT设备系统中设备端与云端的通信过程中。
结合这两条日志内容和wireshark的抓包结果,我们可以进一步确认设备的工作流程:与litedev.ys7.com通信,获取了MQTT服务器的地址;然后与MQTT服务器通信,实现设备的逻辑功能。
在图2-8和图2-9中,我们分别用红框标识了一个关键字符串。在海康萤石智能网关的文件系统中,二进制搜索其中一个字符串“lbs_connect”,确认该字符串出现在libmicrokernel.so.1中。用IDA加载该so文件,可以发现此动态链接库中,有一个函数名字即为lbs_connect,查找该函数的交叉引用,可以看到有多处代码调用了此函数,我们随便找一处点开看下,如下图所示:
图2-10 调用lbs_connect函数
可以看到在lbs_connect函数返回成功之后,就会调用send_authentication_i函数。这个函数看起来就是加密和认证相关的函数。
3. 程序调试
找到了关键点之后,就需要进一步分析这些函数的功能和作用了。在本专题之前的文章中,我们都是纯静态分析,所以在本篇中,我们就不再单纯地进行静态分析,而是想办法调试一下这个程序。
对于嵌入式Linux操作系统,我们通常选用gdb和gdbserver作为调试工具。gdb是一个应用非常广泛的调试器,在以后的文章中也会反复出现,其全称是GNU Project Debugger,其官网是https://www.gnu.org/software/gdb/;gdbserver是gdb的一部分,常用于解决交叉编译环境下的远程调试问题。我们可以直接在设备上使用gdb进行本地调试,但gdb程序体积比较大,而且直接在设备上运行gdb会有很多不方便的地方,所以我们选择通过gdbserver进行远程调试。为了完成调试工作,我们首先需要一个可以运行在海康萤石智能网关设备上的gdbserver程序。
在此前关于海康萤石智能网关分析的第二篇文章中,我们下载了MT7688 SDK相关的资料。在进一步翻阅相关的资料之后,我们发现官方MT7688开发板是内置了gdbserver程序。因此,我们下载了官方提供的固件包,并用binwalk提取了固件内容,最后找到了gdbserver程序。但此gdbserver程序运行之后没有任何输出,推测是官方定制了gdbserver的代码,导致我们无法使用该程序调试,截图如下:
图3-1 官方gdbserver无法使用
所以,就只能去找一找有没有其他可以正常运行在海康萤石智能网关中的gdbserver程序了,毕竟自己编译一个有点太麻烦了。幸运的是,在rapid7官方github账户上有一些已经编译好的gdbserver程序,链接如下:https://github.com/rapid7/embedded-tools/tree/master/binaries/gdbserver, 我们选择下载mipsle版本的gdbserver。截图如下:
图3-2 rapid7官方github页面中的embedded-tools仓库
下载完毕之后,通过tftp下载至海康萤石智能网关的设备中,并尝试执行此程序。截图如下:
图3-3 执行gdbserver.mipsle程序
程序没有报错,看来是可以顺利执行的。接下来就用此程序开始调试吧。
首先,使用 gdbserver启动davinci。如果直接用 gdbserver附加davinci进程,很可能会错过davinci程序与服务器通信的认证过程。所以我们直接使用gdbserver启动程序,这样一来,在远程调试器连接之前,davinci程序将处于挂起状态。命令如下:
图3-4 通过gdbserver启动程序
此时,gdbserver就开始监听23946端口,等待远程调试器的连接。
接下来,我们可以选择gdb或IDA作为远程调试器连接gdbserver。IDA提供图形界面,可以帮助我们理解程序的逻辑;但gdb要更稳定,可以有效避免IDA调试时出现的奇怪错误。我们这里直接选择gdb作为远程调试器,在后续的文章中会有介绍用IDA作为调试器的例子。
由于我们需要调试的是MIPS指令集的程序,而gdb默认情况下,仅支持调试与当前环境采用相同指令集的程序(i386),所以我们需要安装可以调试MIPS指令集的gdb程序。安装方法比较简单,直接输入sudo apt install gdb-multiarch即可。还可以给gdb程序加一个pwndbg插件,用于辅助我们的调试工作,该插件的官方地址是:https://github.com/pwndbg/pwndbg,只需要下载下来,然后运行./setup.sh即可。此插件并非必需品,但是推荐装上。
完成gdb的配置工作之后,就可以使用gdb连接gdbserver开始远程调试了。gdb的调试命令非常多,可以直接搜索到很多整理好的常用命令,在这里,我们就遇见什么指令就解释什么指令吧。运行gdb-multiarch,截图如下:
图3-5 运行gdb-multiarch程序
上图中,我们分别设置architecture为MIPS,读取davinci的符号文件,在main函数设置断点,并连接远程的gdbserver,关键位置已用绿框圈出。然后,我们用快捷键c(continue),让程序开始执行,截图如下:
图3-6 程序运行到main时中断
上图中,红框部分表示触发了main函数中的断点。此时,我们加载libmicrokernel.so.1的符号文件,同样用file命令,就不截图了。然后,我们在lbs_connect函数下个断点,并继续执行程序,如下图:
图3-7 在lbs_connect函数下断点
稍等片刻,就会看到程序断在lbs_connect函数中,等待我们的调试命令,截图如下:
图3-8 程序命中lbs_connect断点
从图中可以看到,程序是从lbs_redirect调用过来的,可以在外层函数下断点,继续调试,帮助我们理解程序的逻辑,但是本篇内容先到此为止。
4. 小结
从本篇起,我们开始分析海康萤石智能网关的固件程序。在我们的分析过程中,程序的日志给我们提供了很多帮助。借助日志的输出内容,我们很快定位到了通信加密相关的代码。接着为了进一步研究设备是如何认证和加密的,我们尝试使用gdb和gdbserver调试固件中的程序。关于进一步的分析内容将在下一篇分析中展开讨论。
作者:Yimi Hu & Light @ PwnMonkeyLabs