Hacking a Tapo TC60 Camera

IoT 8个月前 admin
103 0 0

A little while ago, I spotted a Tapo TC60 “Smart Security Camera” on sale at Amazon UK. After my adventures with a smart lockbox and an old safe lock, I wanted to try hacking something with a few more features. This is what happened.
不久前,我在英国亚马逊上发现了一款 Tapo TC60“智能安全摄像头”。在我使用智能密码箱和旧保险箱进行冒险之后,我想尝试破解具有更多功能的东西。这就是发生的事情。

Hacking a Tapo TC60 Camera

Inside the box, we get the usual collection of manuals, a power adapter, and the camera itself. The camera was much smaller than I expected, with no obvious way into the case.
在盒子里,我们得到了通常的手册、电源适配器和相机本身。相机比我想象的要小得多,没有明显的进入箱子的途径。

Hacking a Tapo TC60 Camera

I powered it on, and set it up on the Tapo app. I probably should have captured the setup traffic in BurpSuite, but I’m more interested in the hardware for this post.
我打开了它的电源,并在 Tapo 应用程序上进行了设置。我可能应该捕获 BurpSuite 中的设置流量,但我对这篇文章的硬件更感兴趣。

Hacking a Tapo TC60 Camera

With the setup complete, I started taking the camera to bits. First removing the stand, then finding a disassembly video of the TC100 on YouTube, which showed how to get into the main camera body.
设置完成后,我开始将相机切成碎片。首先卸下支架,然后在 YouTube 上找到 TC100 的拆卸视频,该视频展示了如何进入主摄像头机身。

Hacking a Tapo TC60 Camera

There are 4 clips holding the front of the case on, which releases when another of the IFixIt picks are inserted. This gives us access to the main board.
有 4 个夹子固定外壳前部,当插入另一个 IFixIt 拨片时,该夹子会松开。这使我们能够访问主板。

Hacking a Tapo TC60 Camera

One of the first things to do when approaching something like this is try and identify the chips on the board, as well as any UART/JTAG interfaces. Identifying the chips will give us a high-level understanding of what the device is doing, and help us understand where we might find interesting data. This board has a few obvious components.
在处理此类问题时,首先要做的一件事是尝试识别电路板上的芯片以及任何UART/JTAG接口。识别芯片将使我们对设备正在做什么有一个高层次的了解,并帮助我们了解在哪里可以找到有趣的数据。该板有几个明显的组件。

Hacking a Tapo TC60 Camera

The big chip is an Ingenic T31, a system on chip video processor. There is very little information on this chip available, but we know it’s going to be handing video for us.
大芯片是Ingenic T31,一种片上系统视频处理器。关于这个芯片的信息很少,但我们知道它将为我们提供视频。

There is also a RTL8188FTV, a WiFi and network USB chip, designed for use in devices including IP-cameras. There are some other ICs, including an audio amplifier, and the usual selection of passive components. Crucially, there is no memory chip on this side of the board.
还有一个RTL8188FTV,一个WiFi和网络USB芯片,设计用于包括IP摄像机在内的设备。还有一些其他的IC,包括音频放大器,以及通常选择的无源元件。至关重要的是,电路板的这一侧没有存储芯片。

Turning the board over, we can see the camera assembly, which can be removed. Taking this off reveals the sensor and another IC.
将电路板翻过来,我们可以看到相机组件,可以拆卸。取下它,可以看到传感器和另一个IC。

Hacking a Tapo TC60 Camera

This is a XMC 25QH64C, a serial flash memory chip. This is almost certainly where the firmware for this device is stored.
这是XMC 25QH64C,一个串行闪存芯片。几乎可以肯定,这是存储此设备固件的位置。

Examining the board also reveals some pads, which look suspiciously like a UART interface, just above the T31 chip.
检查电路板还会发现一些焊盘,这些焊盘看起来很像 UART 接口,就在 T31 芯片上方。

A quick check with a multi-meter reveals one of the pins is tied to ground, one likely to Vcc, leaving two unidentified pins. Probing these pins with the oscilloscope reveals what looks like data going out.
用万用表快速检查会发现其中一个引脚接地,一个可能与 Vcc 相连,留下两个不明引脚。用示波器探测这些引脚,可以发现数据流出的样子。

Hacking a Tapo TC60 Camera

Connecting up the logic analyser verifies that this is indeed a UART interface. We can see the U-Boot logs being displayed when the power is connected.
连接逻辑分析仪可验证这确实是一个UART接口。我们可以看到连接电源时显示的 U-Boot 日志。

Hacking a Tapo TC60 Camera
Hacking a Tapo TC60 Camera

Now we know which pin is TX, we can connect up the Tigard board and try and talk to the device.
现在我们知道哪个引脚是 TX,我们可以连接 Tigard 板并尝试与设备通信。

Scrolling through the console data, there are no obvious ways to interrupt the boot sequence.
滚动浏览控制台数据,没有明显的方法可以中断启动序列。

At this point I started researching prior work on this device. While I couldn’t find anything on the TC60, I did find some information on the TC200 and TC100. It seems like the TC100 is essentially the same device, so a lot of the information could be useful.
在这一点上,我开始研究这个设备的先前工作。虽然我在 TC60 上找不到任何东西,但我确实找到了一些关于 TC200 和 TC100 的信息。看起来 TC100 本质上是同一个设备,所以很多信息可能很有用。

The most useful source of information was this blog post, which also links to a GitHub project related to the TC200.
最有用的信息来源是这篇博文,它还链接到与 TC200 相关的 GitHub 项目。

These projects contain some useful information, such as the escape sequence for the U-Boot loader, allowing us to interrupt the boot sequence and drop into a root shell.
这些项目包含一些有用的信息,例如 U-Boot 加载程序的转义序列,允许我们中断引导序列并放入 root shell。

------Firmware check pass!-----
Autobooting in 1 seconds
isvp_t31# 
isvp_t31# slp
Unknown command 'slp' - try 'help'
isvp_t31# setenv bootargs console=ttyS1,115200n8 mem=45M@0x0 rmem=19M@0x2d00000 root=/dev/mtdblock6 rootfstype=squashfs spdev=/dev/mtdblock7 noinitrd init=/bin/sh
isvp_t31# 
isvp_t31# printenv
baudrate=115200
bootargs=console=ttyS1,115200n8 mem=45M@0x0 rmem=19M@0x2d00000 root=/dev/mtdblock6 rootfstype=squashfs spdev=/dev/mtdblock7 noinitrd init=/bin/sh
bootcmd=sf probe;sf read 0x80700000 0x80200 0x175000; bootm 0x80700000
bootdelay=1
ethaddr=00:d0:d0:00:95:27
gatewayip=193.169.4.1
ipaddr=193.169.4.81
loads_echo=1
netmask=255.255.255.0
serverip=193.169.4.2
stderr=serial
stdin=serial
stdout=serial

Environment size: 437/16380 bytes
isvp_t31# sf probe;sf read 0x80700000 0x80200 0x175000; bootm 0x80700000
<snipped>

BusyBox v1.19.4 (2022-09-30 05:46:09 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands.

/bin/sh: can't access tty; job control turned off
/ # ls
bin      etc      mnt      proc     root     sp_rom   tmp      var
dev      lib      overlay  rom      sbin     sys      usr      www
/ # help
Built-in commands:
------------------
        . : [ [[ alias bg break cd chdir command continue echo eval exec
        exit export false fg getopts hash help jobs kill let local printf
        pwd read readonly return set shift source test times trap true
        type ulimit umask unalias unset wait

/ # id
uid=0(root) gid=0(root)

From here, we need to mount the /proc directory, which gets us access to some of the usual linux tools. We can also cat out the /etc/passwd file, which gives us the hash for the root user.
从这里,我们需要挂载 /proc 目录,这样我们就可以访问一些常用的 linux 工具。我们还可以输出 /etc/passwd 文件,它为我们提供了 root 用户的哈希值。

root:$1$Xr8fF4xx$BFl2tPv719kYGwDH5TFrm.:0:0:root:/root:/bin/ash
nobody:*:65534:65534:nobody:/var:/bin/false
admin:*:500:500:admin:/var:/bin/false
guest:*:500:500:guest:/var:/bin/false
ftp:*:55:55:ftp:/home/ftp:/bin/false
/ # cat /etc/shadow
root:x:0:0:99999:7:::
daemon:*:0:0:99999:7:::
ftp:*:0:0:99999:7:::
network:*:0:0:99999:7:::
nobody:*:0:0:99999:7:::

My research into prior work on this device also turned up an academic paper, talking about some potential risks around poorly secured IoT devices. This included a hypothetical scenario where an owner of a TC100 camera leaves it unattended during a power cut (so the camera doesn’t record being tampered with), and a house-mate uses this opportunity to extract the device firmware. This is then analysed off-line, eventually granting them access to the live feed from the device (assuming they are on the same network as the device). We will try and re-create this attack.
我对该设备先前工作的研究也发现了一篇学术论文,讨论了安全性差的物联网设备的一些潜在风险。这包括一个假设的场景,即 TC100 摄像机的所有者在停电期间无人看管(因此摄像机不会记录被篡改),而室友利用这个机会提取设备固件。然后对此进行离线分析,最终授予他们从设备访问实时源的权限(假设他们与设备位于同一网络上)。我们将尝试重新创建此攻击。

The camera model used in the paper has its flash chip located in a different position on the board, allowing easy access with a SOP8 clip. The authors were also able to bridge a connection on the board to put the main IC in reset mode. As we covered briefly in a previous post, we need to stop the main IC talking to the flash memory while we dump it, otherwise it will skew our results. In this device, the flash chip and the main IC share the same power rails. Supplying power to the chip while dumping its memory will also cause the main IC to power on. In our case, the main IC is on the opposite side of the board to the flash chip. The flash chip is also located under the camera lens assembly. While it would still be possible to extract the firmware this way, it would be much more complicated to do in the hypothetical scenario of a malicious actor with limited time to access the device. We need another approach.
论文中使用的相机型号的闪存芯片位于电路板上的不同位置,因此可以通过 SOP8 夹子轻松访问。作者还能够桥接电路板上的连接,使主IC处于复位模式。正如我们在上一篇文章中简要介绍的那样,我们需要在转储闪存时停止主 IC 与闪存通信,否则它会扭曲我们的结果。在该器件中,闪存芯片和主IC共享相同的电源轨。在转储存储器的同时为芯片供电也会导致主IC上电。在我们的例子中,主IC位于电路板的另一侧,与闪存芯片相对。闪光灯芯片也位于相机镜头组件下方。虽然仍然可以以这种方式提取固件,但在恶意行为者访问设备的时间有限的假设场景中,这样做要复杂得多。我们需要另一种方法。

When looking to attack a device, it is useful to have access to the manufacturers firmware. While some credential material is likely configured by the user during setup, an analysis of the firmware on the device may well reveal default credentials or other weaknesses which we can exploit, without having to extract the firmware from a running device. Fortunately (or unfortunately, depending on your point of view), manufactures are becoming more aware of these attacks and are often not supplying firmware downloads on their website. TPLink (who make the Tapo cameras), are one such company. They do provide copies of the GPL code used in these devices, which have contained useful information in other models of camera (see the linked research above). In our case, there did not appear to be any useful information in these files. We need the factory firmware.
当想要攻击设备时,访问制造商的固件很有用。虽然用户可能在设置过程中配置了一些凭据材料,但对设备上的固件的分析可能会揭示我们可以利用的默认凭据或其他弱点,而无需从正在运行的设备中提取固件。幸运的是(或不幸的是,取决于您的观点),制造商越来越意识到这些攻击,并且通常不会在其网站上提供固件下载。TPLink(制造 Tapo 相机)就是这样一家公司。它们确实提供了这些设备中使用的GPL代码的副本,这些代码包含其他型号相机中的有用信息(参见上面的链接研究)。在我们的案例中,这些文件中似乎没有任何有用的信息。我们需要工厂固件。

The TC60 has an “over the air” firmware update function. The camera likely reaches out to an update server and downloads the firmware image. The app also shows the current firmware version, and details of any pending updates, so it probably also talks out to an update server. As it’s much easier to intercept traffic between the app and the device, compared with trying to intercept traffic from the device itself, this is the path i tried first. After configuring my phone to proxy traffic through BurpSuite, I opened the Tapo app and clicked around. In the response body of one of the requests sent to the camera was a URL to download the firmware update.
TC60 具有“无线”固件更新功能。相机可能会连接到更新服务器并下载固件映像。该应用程序还显示当前固件版本以及任何待处理更新的详细信息,因此它可能还会与更新服务器对话。由于与尝试拦截来自设备本身的流量相比,拦截应用程序和设备之间的流量要容易得多,因此这是我首先尝试的路径。在将手机配置为通过 BurpSuite 代理流量后,我打开了 Tapo 应用程序并点击了一下。在发送到相机的其中一个请求的响应正文中,有一个用于下载固件更新的 URL。

Hacking a Tapo TC60 Camera

I downloaded the firmware and ran it through binwalk, with the -E flag. This shows the entropy of the file.
我下载了固件并通过 binwalk 运行它,带有 -E 标志。这显示了文件的熵。

binwalk -E Tapo_TC60v4_en_1.3.7_Build_230627_Rel.41895n_up_boot-signed_1691484740866.bin

WARNING: Failed to import matplotlib module, visual entropy graphing will be disabled

DECIMAL       HEXADECIMAL     ENTROPY
--------------------------------------------------------------------------------
0             0x0             Rising entropy edge (0.994108)

This doesn’t look good. High entropy likely means the firmware is encrypted, which we can verify using binwalk to try and extract and data.
这看起来不太好。高熵可能意味着固件已加密,我们可以使用 binwalk 来验证并尝试提取数据。

binwalk -e Tapo_TC60v4_en_1.3.7_Build_230627_Rel.41895n_up_boot-signed_1691484740866.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------

As expected, binwalk isn’t able to extract any data. running strings over the file also yields no results. The firmware on the camera must contain the keys we need to decrypt the download, but that’s not much use if we can’t access them. Luckily, we have a UART shell.
不出所料,binwalk 无法提取任何数据。在文件上运行字符串也不会产生任何结果。相机上的固件必须包含我们解密下载所需的密钥,但如果我们无法访问它们,那就没有多大用处了。幸运的是,我们有一个 UART 外壳。

As this device has an SD card slot, we can also dump the firmware via this shell. The “tapo 200 research project” blog has detailed instructions on how to extract the firmware. At a high level, we can mount the SD card, map the flash ram to files on disk and copy them into a flashdump.bin file. The full instructions are provided in the linked post, which I won’t recreate here.
由于此设备具有SD卡插槽,因此我们也可以通过此shell转储固件。“tapo 200 研究项目”博客提供了有关如何提取固件的详细说明。在较高层次上,我们可以挂载 SD 卡,将闪存 ram 映射到磁盘上的文件并将它们复制到 flashdump.bin 文件中。链接的帖子中提供了完整的说明,我不会在这里重新创建。

Now, we can run binwalk over the extracted firmware, which gives us access to the file system contents.
现在,我们可以在提取的固件上运行binwalk,这使我们能够访问文件系统内容。

 binwalk flashdump.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
15892         0x3E14          LZO compressed data
26624         0x6800          uImage header, header size: 64 bytes, header CRC: 0xA3F3CA56, created: 2022-09-29 21:36:29, image size: 155294 bytes, Data Address: 0x80100000, Entry Point: 0x0, data CRC: 0xCEE6C40F, OS: Firmware, CPU: MIPS, image type: Firmware Image, image name: "u-boot-lzo.img"
26688         0x6840          LZO compressed data
141029        0x226E5         CRC32 polynomial table, little endian
145193        0x23729         LZO compressed data
148629        0x24495         Android bootimg, kernel size: 0 bytes, kernel addr: 0x70657250, ramdisk size: 543519329 bytes, ramdisk addr: 0x6E72656B, product name: "mem boot start"
188181        0x2DF15         PEM certificate
188910        0x2E1EE         PEM certificate
190126        0x2E6AE         PEM certificate
191346        0x2EB72         PEM certificate
192538        0x2F01A         PEM certificate
196864        0x30100         gzip compressed data, from Unix, last modified: 2022-09-29 22:06:28
393216        0x60000         LZO compressed data
484818        0x765D2         CRC32 polynomial table, little endian
488822        0x77576         LZO compressed data
524800        0x80200         uImage header, header size: 64 bytes, header CRC: 0x1805EB61, created: 2022-09-29 22:06:13, image size: 1296787 bytes, Data Address: 0x80010000, Entry Point: 0x8031B470, data CRC: 0xD607E5B7, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "Linux-3.10.14__isvp_swan_1.0__"
524864        0x80240         LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: -1 bytes
1823232       0x1BD200        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 2405062 bytes, 647 inodes, blocksize: 131072 bytes, created: 2022-09-29 22:06:33
4456448       0x440000        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 3053252 bytes, 162 inodes, blocksize: 131072 bytes, created: 2022-09-29 22:06:35
8404500       0x803E14        LZO compressed data
8415232       0x806800        uImage header, header size: 64 bytes, header CRC: 0xA3F3CA56, created: 2022-09-29 21:36:29, image size: 155294 bytes, Data Address: 0x80100000, Entry Point: 0x0, data CRC: 0xCEE6C40F, OS: Firmware, CPU: MIPS, image type: Firmware Image, image name: "u-boot-lzo.img"
8415296       0x806840        LZO compressed data
8529637       0x8226E5        CRC32 polynomial table, little endian
8533801       0x823729        LZO compressed data
8537237       0x824495        Android bootimg, kernel size: 0 bytes, kernel addr: 0x70657250, ramdisk size: 543519329 bytes, ramdisk addr: 0x6E72656B, product name: "mem boot start"
8576789       0x82DF15        PEM certificate
8577518       0x82E1EE        PEM certificate
8578734       0x82E6AE        PEM certificate
8579954       0x82EB72        PEM certificate
8581146       0x82F01A        PEM certificate
8585472       0x830100        gzip compressed data, from Unix, last modified: 2022-09-29 22:06:28
8781824       0x860000        LZO compressed data
8873426       0x8765D2        CRC32 polynomial table, little endian
8877430       0x877576        LZO compressed data
8913408       0x880200        uImage header, header size: 64 bytes, header CRC: 0x1805EB61, created: 2022-09-29 22:06:13, image size: 1296787 bytes, Data Address: 0x80010000, Entry Point: 0x8031B470, data CRC: 0xD607E5B7, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "Linux-3.10.14__isvp_swan_1.0__"
8913472       0x880240        LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: -1 bytes
10211840      0x9BD200        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 2405062 bytes, 647 inodes, blocksize: 131072 bytes, created: 2022-09-29 22:06:33
12845056      0xC40000        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 3053252 bytes, 162 inodes, blocksize: 131072 bytes, created: 2022-09-29 22:06:35

Re-visiting the academic paper, we see that the authors followed the process outlined in the “tapo 200 research project” blog, namely, extracting the configuration data from the device and decrpyting offline. The configuration data is still encrypted on our device and, like the other devices, we can either decrypt the data manually, off-line, or there is a utility present on the device which allows it to be decrypted. We can verify this works, using the following steps via our UART shell.
重新审视这篇学术论文,我们看到作者遵循了“tapo 200 research project”博客中概述的过程,即从设备中提取配置数据并离线解压。配置数据在我们的设备上仍然加密,与其他设备一样,我们可以手动、离线解密数据,或者设备上存在允许解密的实用程序。我们可以通过我们的 UART shell 使用以下步骤来验证它是否有效。

  • Mount /proc 挂载 /proc
  • Mount /dev 挂载 /dev
  • Mount /tmp 挂载 /tmp
  • run the uc_convert utility
    运行 uc_convert 实用程序
mount -t proc none /proc
mount -t tmpfs tmpfs /dev -o mode=0755,size=512K
mount tmpfs /tmp -t tmpfs -o size=20633600,nosuid,nodev,mode=1777
mknod /dev/slp_flash_chrdev c 222 0
/bin/uc_convert -t 0

This creates a directory in /tmp, which contains the decrtypyed device configuration.
这将在 /tmp 中创建一个目录,其中包含已解码的设备配置。

In our hypothetical attack scenario, we could perform this step on the device, via our UART shell and exfiltrate the decrypted data either via terminal logs or writing to the SD card. We wouldn’t need to grab the firmware at all, which certainly helps for this device, where the flash chip is located under the camera lens assembly.
在我们假设的攻击场景中,我们可以通过我们的 UART shell 在设备上执行此步骤,并通过终端日志或写入 SD 卡泄露解密数据。我们根本不需要抓取固件,这当然对这款设备有帮助,因为闪存芯片位于相机镜头组件下方。

Hacking a Tapo TC60 Camera

However, as we can see, the “third_account” username and password values are blanked out. This differs from the device presented in the paper (where the authors were able to crack the hash for this account and use the credentials to access the video stream). So that’s it, game over, right? Not quite…
但是,正如我们所看到的,“third_account”用户名和密码值被屏蔽了。这与论文中介绍的设备不同(作者能够破解该帐户的哈希值并使用凭据访问视频流)。就是这样,游戏结束了,对吧?差一点。。。

We have access to the device as root. Can we simply add an account under the third_account section and gain acccess to the video feed?
我们以 root 身份访问设备。我们可以简单地在该 third_account 部分下添加一个帐户并获得对视频源的访问权限吗?

After some investigation, it turns out the answer is yes, with some caveats. Extracting the config using the uc_convert utility, we can find the user account details in /tmp/etc/uc_conf/user_management, as shown above.
经过一番调查,结果证明答案是肯定的,但有一些注意事项。使用 uc_convert 实用程序提取配置,我们可以在 /tmp/etc/uc_conf/user_management 中找到用户帐户详细信息,如上所示。

The “root” account blob contains credentials configured when we set up the camera. The passwd field is a simple MD5 hash of the password. We can try and crack this, but that might take some time, if the user selected a strong password. The ciphertext blob is RSA encrypted, which we’ll cover shortly.
“root”帐户 blob 包含我们设置相机时配置的凭据。passwd 字段是密码的简单 MD5 哈希值。我们可以尝试破解此问题,但如果用户选择了强密码,则可能需要一些时间。密文 blob 是 RSA 加密的,我们稍后会介绍。

The third_account blob is, by default, disabled. The username and password values are set to “—-”. This account is used to allow access to the RTSP stream from the camera, and must be enabled via the mobile app. enabling this comes with some warnings:
默认情况下,该 third_account blob 处于禁用状态。用户名和密码值设置为“—-”。此帐户用于允许从摄像机访问 RTSP 流,并且必须通过移动应用程序启用。 启用此功能会附带一些警告:

Hacking a Tapo TC60 Camera

I initially assumed that only the username and password values were required to access the RTSP stream. I modified the config, adding a “backdoor” account with a known password hash (note that this needs to be uppercase, or it won’t work), wrote the config back to flash, rebooted the camera and attempted to access the RTSP stream from VLC. This gave me an authentication error.
我最初假设只需要用户名和密码值即可访问 RTSP 流。我修改了配置,添加了一个具有已知密码哈希的“后门”帐户(请注意,这需要大写,否则将不起作用),将配置写回闪存,重新启动相机并尝试从 VLC 访问 RTSP 流。这给了我一个身份验证错误。

After lots of experimenting, it turns out that the ciphertext value must also be set to match the username and password values. The mobile app uses the passwd value to validate the password when you perform a “change password” option on the RTSP account, but the RTSP steam uses the ciphertext value. I’m not a reverse engineer, however, we can verify that this is likely RSA encrypted data using binary ninja and ghidra.
经过大量实验,事实证明,密文值也必须设置为与用户名和密码值匹配。当您对 RTSP 帐户执行“更改密码”选项时,移动应用程序使用 passwd 值来验证密码,但 RTSP Steam 使用密文值。我不是逆向工程师,但是,我们可以验证这可能是使用二进制忍者和 gedra 的 RSA 加密数据。

If we throw the cet application (which is what this device uses for RTSP) into binary ninja cloud, and search for ‘ciphertext’, we get the following result:
如果我们将 cet 应用程序(这是该设备用于 RTSP 的应用程序)放入二进制忍者云中,并搜索“密文”,我们得到以下结果:

Hacking a Tapo TC60 Camera

Looking at this function in more detail, we see it calls the following function after reading the ciphertext block in our config file:
更详细地查看此函数,我们看到它在读取配置文件中的密文块后调用了以下函数:

int32_t $v0_14 = rsa_decrypt("oP4b0Q2dUvDXKwK9gLnBfVpxcHUDg4V2…", 0xac)

rsa_decrypt is an external reference to libdecrypter.so which we can find by grepping the firmware we dumped from the device earlier.
rsa_decrypt是一个外部引用,我们可以通过grepping之前从设备转储的固件来找到它 libdecrypter.so 。

Opening this file with Ghidra, we can find the rsa_decrypt export and start our analysis from there.
使用 Ghidra 打开此文件,我们可以找到rsa_decrypt导出并从那里开始分析。

Hacking a Tapo TC60 Camera

In the private_decrypt function, we can see the code loading an RSA key from somewhere, then doing a base64 decode and an RSA decrypt.
在函数中 private_decrypt ,我们可以看到代码从某个地方加载 RSA 密钥,然后进行 base64 解码和 RSA 解密。

Hacking a Tapo TC60 Camera

I tried to figure out where the RSA key is loaded from, but I’m just not smart enough to figure out this decompiled code:
我试图弄清楚 RSA 密钥是从哪里加载的,但我只是不够聪明,无法弄清楚这个反编译的代码:

Hacking a Tapo TC60 Camera

Running strings over the file turns up some RSA keys, but I wasn’t able to figure out how to use them to decrypt the config file. I’m glossing over this step, as this post is long enough already, but you can run `strings libdecrypt.so` if you want to follow allong
在文件上运行字符串会出现一些 RSA 密钥,但我无法弄清楚如何使用它们来解密配置文件。我掩盖了这一步,因为这篇文章已经足够长了,但如果你想遵循 allong 的话,你可以运行“字符串 libdecrypt.so”

I had a hunch that the decryption keys are hard-coded, and likely the same on each device. Not being smart enough to reverse the decryption code properly, I did the next best thing and ordered another device to test this theory.
我有一种预感,解密密钥是硬编码的,并且在每台设备上可能都相同。由于不够聪明,无法正确反转解密代码,我做了第二件最好的事情,并订购了另一台设备来测试这个理论。

I set up this second device on a new tapo account, performed the initial setup then took it apart and connected to the UART interface. Note that the second device as connected to the same WiFi network. I doubt TPLink are using that as the seed for an encryption key, but I’ve been wrong before.
我在一个新的 tapo 帐户上设置了第二个设备,执行了初始设置,然后将其拆开并连接到 UART 接口。请注意,第二台设备连接到同一WiFi网络。我怀疑 TPLink 是否将其用作加密密钥的种子,但我以前错了。

With access to the uart console, I ran a simple python script to automate dumping the encrypted config. This is a modified version of the script persented in the c200 research project blog.
通过访问 uart 控制台,我运行了一个简单的 python 脚本来自动转储加密的配置。这是 c200 研究项目博客中坚持的脚本的修改版本。

Hacking a Tapo TC60 Camera

From here, I connected via serial, opened the user_manage file in vi (yes, that’s handily supplied on the device), and overwrite the username, passwd and ciphertext values in the file. For the username and passwd, I used backdoor and the MD5 hash of Password206 . For the cipher text, I copied one generated on the original device, which was generated by setting the username and password via the mobile app.
从这里,我通过串口连接,在 vi 中打开 user_manage 文件(是的,设备上很容易提供),并覆盖文件中的用户名、passwd 和密文值。对于用户名和 passwd,我使用了 backdoor Password206 MD5 哈希值。对于密文,我复制了原始设备上生成的密文,该密文是通过移动应用程序设置用户名和密码生成的。

I wrote the modified config back to flash, rebooted the camera and tried to connect to the RTSP stream with VLC:
我将修改后的配置写回闪存,重新启动相机并尝试使用 VLC 连接到 RTSP 流:

Hacking a Tapo TC60 Camera

As we can see, the re-used ciphertext value was accepted, granting us access to the cameras video stream (thats the sensepeak mat on my bench, if you were wondering). Actually performing this attack took around 5 minutes, starting from an un-opened camera body to having access to the stream.
正如我们所看到的,重复使用的密文值被接受,允许我们访问摄像机视频流(如果你想知道的话,这就是我工作台上的 sensepeak 垫子)。实际执行此攻击大约需要 5 分钟,从未打开的相机机身到访问流。

While we may not have re-created the exact attack presented in the paper, we’ve certainly achieved what we set out to do. As we are not dumping the flash ram, we are going to need to supply power to the device. This means we are no longer dependent on waiting for a random power cut to enable our attack. As we are interacting with the device with UART, we need to supply power, which will also enable video capture. You’ll have to use you imaginations to figure out how this could be done without being detected ;). While the steps taken to add the backdoor account have been discussed here, I’ve left out some steps and I’m choosing not to release the python code I used to backdoor the camera. You won’t be able to re-create this attack with the information in this post alone.
虽然我们可能没有重现论文中提出的确切攻击,但我们肯定已经实现了我们的目标。由于我们没有转储闪存内存,因此我们需要为设备供电。这意味着我们不再依赖等待随机断电来启用我们的攻击。当我们使用 UART 与设备交互时,我们需要供电,这也将启用视频捕获。你必须发挥你的想象力来弄清楚如何在不被发现的情况下做到这一点;)。虽然这里已经讨论了添加后门帐户所采取的步骤,但我省略了一些步骤,并且我选择不发布我用于后门相机的 python 代码。您将无法仅使用本文中的信息重新创建此攻击。

For completions sake, let’s see if we can get the off-line decryption vector working.
为了完成,让我们看看我们是否可以让离线解密向量工作。

The prior work we are referencing goes into detail on how the decryption code works, including where the decryption key is located. The academic paper noted that the key in their device, a TC100, differed from the key in the blog post (a TC200). They found the key in the same location, and were able to decrypt their config data using the same technique. Let’s see if our device uses the same approach.
我们引用的先前工作详细介绍了解密代码的工作原理,包括解密密钥的位置。学术论文指出,他们设备中的密钥TC100与博客文章中的密钥(TC200)不同。他们在同一位置找到了密钥,并能够使用相同的技术解密他们的配置数据。让我们看看我们的设备是否使用相同的方法。

First, we load the uc_convert binary into binary ninja cloud.
首先,我们将uc_convert二进制文件加载到二进制忍者云中。

Hacking a Tapo TC60 Camera

We’ve already established that I’m not a reverse engineer, but eventually I can figure out that this is parsing arguments.
我们已经确定我不是一个逆向工程师,但最终我可以弄清楚这是在解析参数。

This would probably end up looking something like this:
这最终可能会看起来像这样:

int main(int argc, char **argv)
{
    if(argc < 3)
    {
        showhhelp();
        return -1
    }
    while((c = getopt(argc, argv, "t:d:c")))
    {
        switch (c){
            case 'd':
                updateFWDescription(); //we dont care what this does
                break;
            case 't':
                int foo = atoi(optarg);
                break;
            case 'c':
                //do a thing
                break;
            default:
                return -1;
    }
}

At this point, i started to look for the other functions. The only other function which stood out was this one, which I quickly realised as beyond my ability to reverse engineer.
在这一点上,我开始寻找其他功能。唯一突出的其他功能是这个功能,我很快意识到它超出了我的逆向工程能力。

Hacking a Tapo TC60 Camera

Back to the drawing board.
从头再来。

The prior work we are referencing was able to locate the string used to derive the encryption key, which in their example was “C200 1.0”. The authors of the research paper found their key to be “C100 2.0”. In both cases this was the model number and firmware hardware version. Let’s just grep the firmware dump we have for our model number…
我们引用的先前工作能够找到用于派生加密密钥的字符串,在他们的示例中是“C200 1.0”。该研究论文的作者发现他们的关键是“C100 2.0”。在这两种情况下,这是型号和固件硬件版本。让我们来看看我们为型号准备的固件转储……

Hacking a Tapo TC60 Camera

This seems promising. Let’s try that in the hash function we have from the prior work.
这似乎很有希望。让我们在之前的工作中获得的哈希函数中尝试一下。

Hacking a Tapo TC60 Camera

And after converting that from ASCII to hex, we can run the OpenSSL command:
在将其从 ASCII 转换为十六进制后,我们可以运行 OpenSSL 命令:

openssl enc -d -des-ecb -nopad -K 3463666461643831 -in mtdblock3.bin -out test.bin`

If you’re wondering where the bin file here came from, I dumped it from the camera, using the SD card to exfiltrate it, in the same way as the full firmware dump, except I only dumped the “config” partition.
如果您想知道这里的 bin 文件是从哪里来的,我将其从相机中转储,使用 SD 卡将其泄露,与完整固件转储的方式相同,只是我只转储了“配置”分区。

Hacking a Tapo TC60 Camera

And after extracting, we get our config data.
提取后,我们得到配置数据。

Hacking a Tapo TC60 Camera

So, this model camera is using the same method to protect its config data as the C100 and C200, all be it with a different key. It’s worth noting that I’m really standing on the shoulders of giants here, there’s no way I’d have figured out that encryption method myself.
因此,该型号的相机使用与 C100 和 C200 相同的方法来保护其配置数据,所有这些都使用不同的密钥。值得注意的是,我真的站在巨人的肩膀上,我自己不可能想出这种加密方法。

Let’s wrap this up. To recap, we’ve seen how with physical access to one of these cameras we can dump the firmware. We can also connect to the UART console, access a root shell and add a backdoor account to the camera to allow surupticious access to the video stream. This backdoor accoount is not immidiatly obvious in the app, and would likely not be detected unless the user wanted to enable RSTP access. We’d need physical access to the device, and to be on the same network to actually view the feed, so the potential for attack here is quite low. We’ve also seen how we can decrypt the device config offline, using methods presented in other research. Finally, we learnt that I really have no idea how Ghidra works.
让我们总结一下。回顾一下,我们已经看到了如何通过物理访问其中一台相机来转储固件。我们还可以连接到 UART 控制台,访问 root shell 并向相机添加后门帐户,以允许对视频流进行随机访问。此后门帐户在应用程序中并不明显,除非用户想要启用 RSTP 访问,否则可能不会被检测到。我们需要对设备进行物理访问,并且在同一网络上才能实际查看提要,因此这里受到攻击的可能性非常低。我们还看到了如何使用其他研究中介绍的方法离线解密设备配置。最后,我们了解到我真的不知道 Ghidra 是如何工作的。

原文始发于James:Hacking a Tapo TC60 Camera

版权声明:admin 发表于 2024年4月1日 上午9:46。
转载请注明:Hacking a Tapo TC60 Camera | CTF导航

相关文章