拆机抽Flash解密:TapoC260与发现协议v2逆向

admin 2026-10-03 04:45:22 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文复盘TapoC260摄像头拆机与固件逆向过程,重点分析TapoDiscoveryProtocolv2协议。作者通过拆机读取Flash芯片,利用硬编码AES-128-CFB1密钥解密文件系统,发现TDPv2采用大端、CRC32校验及RSA信息通道,并使用Qiling仿真验证协议包。文章指出文件系统加密密钥跨型号复用、UART调试口未默认启用等风险,建议厂商关闭调试通路、避免密钥复用,并对UDP20002/20010端口做网络隔离与监控。 综合评分: 88 文章分类: IoT安全,逆向分析,二进制安全,红队


拆机抽 Flash 解密:Tapo C260 与发现协议 v2 逆向

原创

黑卷 黑卷

赛博安全攻防日记

2026年10月2日 10:25 上海

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

拆机抽 Flash 解密:Tapo C260 与发现协议 v2 逆向

2025 年,原作者参加了新加坡网络安全局与 YesWeHack 合办的 SPIRITCYBER IoT 硬件黑客赛。赛中在多台设备上挖到若干 RCE 等有趣问题,目前仍在等厂商补丁与 CVE 分配——本文不会展开任何未公开漏洞细节,只复盘 Tapo C260 的固件逆向过程,以及作者顺带拆开的 Tapo Discovery Protocol v2(TDP v2)。

原作者:Spaceraccoon / Eugene Lim(2026-01-02)。本文为防御向技术整理;作者写明漏洞细节暂不公开,请勿把本文理解成「已公开 RCE / CVE」。

作者之前写过 Nokia Beacon 1、光猫 LAU-G150-C 一类设备;C260 在壳子硬度与固件加密上又上了一档。TDP v1 已被多方研究(含 Pwn2Own),v2 公开资料很少,所以把协议侧发现单独写出来也有价值。

拆机

C260 壳子质量很高:表面看不到螺丝,贴纸/胶垫底下也没有。

拆壳时 iFixit Jimmy 很管用。技巧不是当杠杆硬撬,而是先把刀片尖伸进缝,再上下微微晃,让刀片一点点吃深,空隙和杠杆会一起变大。

再拧掉几颗螺丝、撬开几层内壳,才能看到主板:

这是一台规格不低的摄像头:4K、AI 识别、microSD、蓝牙与 WiFi,元器件分散在多块板上。

第一张板子上能看到 UART_TX 丝印,但出厂并不能直接用——以往其他 Tapo 机型的研究者通常要先把相关焊点重新连通。作者这次更关心的是 Flash:左侧那颗 ESMT F50L1G41LB(WSON8)。

静态分析:读 Flash 与解密 rootfs

用 XGecu T48 读片。原装 WSON8 座偏小,卡不住这颗芯片;作者改用鳄鱼夹适配(正好咬住 WSON8 引脚),再接到 SOP8 座上。

芯片在 T48 支持列表里,读起来并不难。这次特意按数据手册去掉每页多出来的 64 字节 OOB:

The device contains 1024 blocks, composed by
64 pages consisting in two NAND structures of 32 series
connected Flash cells. Each page consists 2112-Byte and is
further divided into a 2048-Byte data storage area with a
separate 64-Byte spare area. The 64-Byte area is typically used
for memory and error management.

接下来要解文件系统——Tapo 会对文件系统加密。好在 Quentin Kaiser 在 C200 文中已经把方案摸清:仍是 硬编码的 AES-128-CFB1,密钥也没换。作者沿用同一套方案解出 SquashFS。

解开后重点看 /bin/main:Web 与各类协议处理器大多集中在这里。固件其他攻击面作者留待另文;本文只盯 Tapo Discovery Protocol 那条处理链。

Tapo Discovery Protocol v2

main 里日志很全,便于对上函数名。入口落在偏移 0x2a7e0 的 tdpd_listen_thread:在 UDP 20002 / 20010 上建监听。

收包后会把各字段打出来,伪代码大致如下(节选,便于对照结构):

  puVar8 = (undefined8 *)
           recvfrom(param_1,&DAT_00323530,0x1000,0,(sockaddr *)&DAT_00323310,&local_3c);
&nbsp; if ((int)puVar8 < 1) {
&nbsp; &nbsp; pcVar15 = "[TDPD]tdpd recv error.";
&nbsp; &nbsp; ...
&nbsp; }
&nbsp; if ((int)puVar8 < 0x10) {
&nbsp; &nbsp; ...
&nbsp; &nbsp; msg_debug(0,0x10,3,pcVar25,uVar11,pcVar15,puVar8,bVar37);
&nbsp; &nbsp; return;
&nbsp; }
&nbsp; msg_debug(0,0x10,1,"tdpd_handle",0x971,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "[TDPD]recv packet:\nversion:%d\nreserved:%d\nflag:%d\nresult:%d\nopcode:%d\npayloadleng th:%d\nsn:%lu\nchecksum:%lu\npayload=%s\n"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ,...);

日志里有 version。后续按版本分流:v1 走旧处理(前人已逆向);v2 则进入新的 handler 集合(switch)。v2 侧例如会解析 JSON、调用 tdpd_get_basic_info_v2 等。

相对 v1,作者归纳的差异包括:

  • 大端

    (v1 为小端)

  • 校验改为 CRC32(不再用自定义校验)

  • 存在 tdpd_get_encrypt_info_v2:用 RSA 封装更完整的系统信息再回传

文中没有把全部 opcode / 字段铺开,也没有给出可直接打穿设备的 exploit 链——重点是协议形态与分析入口。

仿真与发包验证(Qiling)

静态分析够定位结构,但作者还想对「活着的」处理逻辑验包。手写脚本一开始失败,说明结构体尺寸/字段仍可能对不齐。两条路:继续抠 UART 拿壳,或用仿真。

手头已有完整 rootfs,作者用 Qiling 近似跑 /bin/main。途中要补配置初值:对 read_config 做 ql.hook_address,把缺的值写进内存;main 还会跑一堆与 TDP 无关的 handler,于是直接改 PC,跳到 tdpd_handle。发包则 hook recvfrom,把构造好的 TDP 包写进缓冲区。最后把调试日志从丢弃改到 stdout,方便在仿真输出里看报错。

核心逻辑示意(完整脚本作者已放 GitHub spaceraccoon/tapo-discovery-protocol-v2,此处仅作机制说明):

PACKET = create_tdpd_packet(version=2, opcode=2, payload=OPCODE_2_PACKET)

def my_recvfrom(ql, sockfd, buf, length, flags, addr, addrlen):
&nbsp; &nbsp; ql.mem.write(buf, PACKET)
&nbsp; &nbsp; return len(PACKET)

def redirect_tdpd_handle(ql):
&nbsp; &nbsp; ql.arch.regs.lr = EXIT_ADDRESS
&nbsp; &nbsp; ql.arch.regs.pc = 0x29728 | 1

def msg_debug_wrapper(ql):
&nbsp; &nbsp; ql.arch.regs.r2 = 3 &nbsp; # 日志打到 stdout

ql = Qiling(['squashfs-root/bin/main'], 'squashfs-root',
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; archtype=QL_ARCH.ARM, ostype=QL_OS.LINUX, multithread=True)
ql.os.set_syscall('recvfrom', my_recvfrom, QL_INTERCEPT.CALL)
ql.hook_address(redirect_tdpd_handle, 0x1CB66)
ql.hook_address(msg_debug_wrapper, 0x1C514)
# read_config hooks …
ql.run(end=EXIT_ADDRESS)

拼装感很强,但已经足以在真机上打通「能被设备认下的」构造包。对防御方而言:本地发现协议一旦暴露更多系统信息(尤其经 RSA 通道),评估面就不该只停在旧版 TDP。

小结(防御视角)

  • 拆机门槛高

    :无外露螺丝,但不等于无法进入;Flash 在板且可夹读。

  • UART 丝印不等于开壳即用

    :Tapo 常见要先恢复连通,本文重点走了 SPI/NAND 抽固件。

  • 文件系统加密未换钥

    :C200 时代的硬编码 AES-128-CFB1 在 C260 上仍可用——换代设备复用旧密钥,会显著降低逆向成本。

  • TDP v2 是新攻击面文档缺口

    :大端 + CRC32 + RSA 信息通道;分析入口在 tdpd_listen_thread / tdpd_handle(UDP 20002/20010)。

  • Qiling 可补静态不足

    :hook 配置与 recvfrom,把协议结构验证从「猜」变成「跑」。

  • 漏洞细节未公开

    :作者在等 SPIRITCYBER 相关补丁完成后再写;在此之前请只把本文当 RE / 协议研究笔记。

对厂商与防御方:量产关闭或强鉴权调试通路;文件系统加密密钥勿跨型号硬编码复用;发现协议的版本协商与信息回传应做最小暴露与鉴权;对 UDP 20002/20010 等本地发现端口做网络隔离与监控。

往期推荐

  • EOL 路由照样打穿:Netgear WGR614v9 UART + Bitdefender Box SPI 降级 RCE
  • 19.9 美元路由拆到 RCE:Dbit N300 UART + Boa 溢出(CVE-2026-20374)
  • 四根铜焊盘听出 root:TP-Link TL-WR845N UART 未认证调试口
  • 从 UART 焊到未认证后门:ANJIA PTZ 摄像头(CVE-2026-31077)
  • 从调试口抽到改固件:Sonoff ZigBee 网关的芯片到云端两条 CVE

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。

本文转载自:赛博安全攻防日记 黑卷 黑卷《拆机抽 Flash 解密:Tapo C260 与发现协议 v2 逆向》

评论:0   参与:  0