#BadgeLife @ Off-By-One Conference 2024 | STAR Labs
引言
如约而至,我们在活动结束大约一个月后,发布了Off-By-One徽章的固件和本文,以便感兴趣的参与者有机会探索它。如果您想了解更多关于徽章设计过程的信息,请告诉我们。我们很高兴在首届Off-By-One Conference 2024上推出Octopus Badge。该徽章是会议的亮点之一,因为它包含了以硬件为核心的CTF挑战。在本文中,我们将探讨徽章的构思和设计过程,并讨论解决这些挑战所需的概念。
硬件设计
徽章的图案由Sarah Tan设计,图案是一个有着可爱咕噜眼的章鱼。经过集思广益讨论各种设计后,我们决定为眼睛配备两个独立的圆形显示器。以下是早期原型的一张草图:
将概念转化为电路设计,该徽章围绕一个ESP32-S3主处理器构建,该处理器驱动一对GC9A01 OLED显示器。用户可以使用按钮和方向摇杆与徽章进行交互。此外,一个小的协处理器ATmega328P通过I2C协议进行通信。
电子设计是在KiCad中创建的,以下是3D渲染图。徽章有三种颜色变体,用于区分不同的人群,例如参与者、工作人员和志愿者。
最初的计划是包含一个可充电的LiPo电池,以支持整个会议期间的使用。然而,由于供应链困难,我们选择了AAA电池。希望我们能在明年的徽章中加入LiPo电池。
最后,这就是实际徽章的样子!
硬件CTF挑战
与任何会议徽章一样,我们的徽章也包含CTF挑战。在本节中,我将解释这些挑战背后的灵感以及预期的解决方案。
特别地,嵌入式系统与功能齐全的计算机有很大不同,它最初是为资源受限的应用而设计的。例如,ESP32-S3处理器没有内存管理单元(MMU)。这意味着嵌入式工程师编写代码的方式与软件工程师非常不同。
我们的目标是让参与者接触到硬件黑客技术,而不仅仅是在便携式硬件设备中提供软件挑战。在此过程中,我们也学会了如何改进我们的电子徽章。
1. USB字符串描述符
第一步是确定它是何种设备。因此,欢迎标志隐藏在USB字符串描述符中。
USB描述符将告诉我们设备的来源,例如供应商和产品标识符,并且您的PC也用它来确定要加载哪些驱动程序。
在Linux中,您可以使用dmesg打印内核调试消息。也可以在Windows中查看设备管理器。
$dmesg-w[3240249.488872]usb3-3.2: New USB device found,idVendor=303a,idProduct=4001,bcdDevice=1.00[3240249.488883]usb3-3.2: New USB device strings:Mfr=1,Product=2,SerialNumber=3[3240249.488887]usb3-3.2: Product:#BadgeLife[3240249.488889]usb3-3.2: Manufacturer: STAR LABS SG[3240249.488892]usb3-3.2: SerialNumber:{Welcome_To_OffByOne_2024}或者,您也可以使用lsusb打印出连接到PC的所有设备。
$ lsusb -vd 303a: iManufacturer1STAR LABS SG iProduct2#BadgeLifeiSerial3{Welcome_To_OffByOne_2024}2. C语言编译的内部库
下一个标志隐藏在一个名为flaglib的库中。这可以通过MicroPython REPL显示所有模块来看到。
>>>help('modules')[...]flaglib[...]>>>importflaglib>>>dir(flaglib)['__class__','__name__','__dict__','getflag']最简单的方法是编写一个脚本,通过暴力破解逐个字符地提取。
>>>flaglib.getflag("")''>>>flaglib.getflag("{____________________________}")'{??_????????_??????_??????????'>>>flaglib.getflag("{my_compiled_python_library}")'{my_compiled_python_library}'然而,了解到这是一个C语言编译的内部库,与固件捆绑在一起,这意味着如果转储出闪存内容,就可以检索到其内容。特别是在低成本系统中,加密资源消耗大,通过转储固件或闪存,我们可能会发现以明文形式保存的密码或密钥。
尝试转储固件时,首先要确定设备类型。从电路板上的标签,我们看到它是一个ESP32-S3-WROOM-1-N4。我们可以搜索数据手册,发现它有4MiB的闪存。
可以使用esptool.py包从ESP32-S3转储固件。按住BOOT按钮并按下RESET按钮,使其进入引导加载程序模式。运行以下命令将完整内容保存到文件中:
$ esptool.py --baud115200--port /dev/serial/by-id/usb-** read_flash 0x0 0x400000 fw-backup-4M.bin然后,通常会对比转储出的IoT设备固件进行简单的静态分析。
$ strings fw-backup-4M_black.bin|strings|grep{{my_compiled_python_library}3. 硬件随机数生成器
通过显示菜单,可以看到一个损坏的轮盘赌游戏。许多人通过逆向从设备提取的MicroPython编译库(roulette.mpy)来解决它。文件可以很容易地通过MicroPython IDE(如Thonny或Mu Editor)提取。
>>>fromstarlabsimportroulette>>>roulette.roulette()([1,0,1,2,1,2,2,1,2,2],None)尽管如此,我们预期的解决方案是理解,随机数生成的简单方法是使用模数转换器(ADC)产生的噪声。这对于缺乏硬件RNG外设的旧式微控制器尤其相关。
模数转换器(ADC)常用于将来自外部传感器的模拟信号转换为处理器可以在数字域中使用的数字格式。
这是周围噪声的可视化示例,可以用作随机数采样的来源。
可以通过硬件模糊测试找到正确的引脚。将引脚短路或焊接到地后,我们可以控制数字生成,并打印出标志。这可以使用电阻器完成,但裸线就足够了。
4. Arduino协处理器
该板还有一个使用Arduino平台构建的协处理器。
协处理器在许多IoT应用中很常见,例如拥有外部安全元件或处理单元(用于密码学、证书存储或神经网络处理器)。如果通信协议未加密,可以进行诸如物理中间人攻击之类的攻击。未来,可以进行重放或欺骗攻击来控制主处理器的行为。
根据我们在硬件介绍指南中提供的提示,用户可以访问I2C接口与Arduino通信。通过扫描I2C总线,用户可以发现总线上的地址。
>>>arduino.i2c.scan()[48,49]内部集成电路(I2C)是一种通信协议,常用于PCB上多个设备(微控制器、传感器或其他外部设备)之间。多个设备连接到I2C总线上,数据可以通过寻址方案交换。
这里我们看到两个I2C外设地址,分别是十六进制的0x30和0x31。通过从I2C外设执行读取请求,可以找到标志。
>>>arduino.i2c.readfrom(0x30,100).rstrip(b'\xff')b'Welcome to STAR LABS CTF. Your first flag is starlabs{i2c_flag_1}'5. 时序攻击
如果我们从第二个地址执行读取请求,会收到一条消息,指示我们应该重新启动并更早尝试。换句话说,该挑战要求参与者根据系统运行时间快速读取标志。
>>>arduino.i2c.readfrom(0x31,200).rstrip(b'\xff')b'The early bird catches the worm. System uptime: 221. You are too late. Reboot the arduino and try again.'这为我们呈现了一种情况:某些目标设备的信息可能只在启动序列的短暂瞬间存在于内存中。我们可以通过重置MCU,等待已知的时间,然后再读取内存来执行“时序攻击”。
注意:由于存在小的时序差异(我们谈论的是毫秒级),可能需要重复该过程直到获得相应的字符。
这是解决该挑战的一个示例实现。
defderp(x):globalarduino arduino.off()time.sleep(1)# shutdown the arduinoarduino.on()time.sleep(x);# turn on and wait a known amount of timereturnarduino.i2c.readfrom(0x31,200).rstrip(b'\xff')# immediately readforiinrange(200,500):print(derp(0.01*i))# repeat in sequence每个标志字符的获取如下:
b'The early bird catches the worm. System uptime: 197. You too early, wait a little longer!'b'The early bird catches the worm. System uptime: 198. You too early, wait a little longer!'b'The early bird catches the worm. System uptime: 199. You too early, wait a little longer!'b'The early bird catches the worm. System uptime: 200. You are an early bird, here is your gift: s'b'The early bird catches the worm. System uptime: 201. You are an early bird, here is your gift: t'b'The early bird catches the worm. System uptime: 201. You are an early bird, here is your gift: t'b'The early bird catches the worm. System uptime: 202. You are an early bird, here is your gift: a'b'The early bird catches the worm. System uptime: 203. You are an early bird, here is your gift: r'b'The early bird catches the worm. System uptime: 203. You are an early bird, here is your gift: r'b'The early bird catches the worm. System uptime: 204. You are an early bird, here is your gift: l'b'The early bird catches the worm. System uptime: 204. You are an early bird, here is your gift: l'b'The early bird catches the worm. System uptime: 205. You are an early bird, here is your gift: a'b'The early bird catches the worm. System uptime: 206. You are an early bird, here is your gift: b'b'The early bird catches the worm. System uptime: 206. You are an early bird, here is your gift: b'b'The early bird catches the worm. System uptime: 207. You are an early bird, here is your gift: s'b'The early bird catches the worm. System uptime: 208. You are an early bird, here is your gift: {'b'The early bird catches the worm. System uptime: 208. You are an early bird, here is your gift: {'b'The early bird catches the worm. System uptime: 209. You are an early bird, here is your gift: i'b'The early bird catches the worm. System uptime: 209. You are an early bird, here is your gift: i'b'The early bird catches the worm. System uptime: 210. You are an early bird, here is your gift: 2'b'The early bird catches the worm. System uptime: 211. You are an early bird, here is your gift: c'b'The early bird catches the worm. System uptime: 211. You are an early bird, here is your gift: c'b'The early bird catches the worm. System uptime: 212. You are an early bird, here is your gift: _'b'The early bird catches the worm. System uptime: 212. You are an early bird, here is your gift: _'b'The early bird catches the worm. System uptime: 213. You are an early bird, here is your gift: f'b'The early bird catches the worm. System uptime: 214. You are an early bird, here is your gift: l'b'The early bird catches the worm. System uptime: 214. You are an early bird, here is your gift: l'b'The early bird catches the worm. System uptime: 215. You are an early bird, here is your gift: a'b'The early bird catches the worm. System uptime: 216. You are an early bird, here is your gift: g'b'The early bird catches the worm. System uptime: 216. You are an early bird, here is your gift: g'b'The early bird catches the worm. System uptime: 217. You are an early bird, here is your gift: _'b'The early bird catches the worm. System uptime: 217. You are an early bird, here is your gift: _'b'The early bird catches the worm. System uptime: 218. You are an early bird, here is your gift: 3'b'The early bird catches the worm. System uptime: 218. You are an early bird, here is your gift: 3'b'The early bird catches the worm. System uptime: 219. You are an early bird, here is your gift: }'b'The early bird catches the worm. System uptime: 220. You are an early bird, here is your gift: 'b'The early bird catches the worm. System uptime: 220. You are an early bird, here is your gift: 'b'The early bird catches the worm. System uptime: 221. You are too late. Reboot the arduino and try again.'b'The early bird catches the worm. System uptime: 222. You are too late. Reboot the arduino and try again.'6. 电压毛刺攻击
要访问此挑战,我们必须读取Arduino的UART串口。USB串口适配器的示例包括CH340串口适配器或FT232串口适配器。
有方便的引脚引出供我们使用。这是连接的方法:
您将在新连接的串口上看到此消息。
Flag is Locked! Please help me to jailbreak it. int i = 0, k = 0; for (i = 0; i < 123456; i++) k++; if (k != 123456) { unlock(); } else { lock(); }在正常操作中,k == 123456的条件将始终满足。因此,我们可以推断,只有通过未定义的操作才能获得标志。这是通过在if语句处进行毛刺攻击来实现的。
电压毛刺攻击涉及在处理器处于未定义状态的短暂瞬间切断电源。此时,我们迅速恢复供电,使其继续正常操作而不会触发重启。重复此操作,希望在未定义状态期间发生毛刺。
从MicroPython REPL中,已经为我们编写了一些代码,可以通过简单的函数调用来打开和关闭Arduino。
>>>arduino<MyArduinoobjectat 3fcaac10>>>>arduino.off();>>>arduino.on();为了执行毛刺攻击,我们快速切换电源。当电压降低并迅速恢复时,可能会发生毛刺。
>>>arduino.on();arduino.off();arduino.on();我们可以使用示波器,这是一种允许我们实时查看电压波形的工具。(这对于解决挑战不是必需的,但它有助于我们可视化正在发生的事情)。下图描绘了从引出引脚测得的Arduino电压。
最后,如果我们幸运的话,会看到标志弹出:
Flag is Locked! Please help me to jailbreak it. int i = 0, k = 0; for (i = 0; i < 123456; i++) k++; if (k != 123456) { unlock(); } else { lock(); } This should not happen! k=123271 Unlocked. Here is your flag starlabs{voltage_glitching_is_cool}完美毛刺:
由于制造差异,可能不容易复现,因为我们看到切换可能导致Arduino完全重启,而不是产生毛刺。这是因为电源可能耗尽得太快(即毛刺“太强”)。
通过识别附近的元器件(Qx1:MOSFET),我们了解电源是通过一个MOSFET晶体管来切换的。还可以看到一个“Glitcher”测试点,它跨接在MOSFET晶体管上。我们可以通过在MOSFET晶体管上焊接一个电容器或电阻器来使毛刺更具可重复性。
结论
感谢所有参加会议并接受CTF挑战的各位!徽章设计成功地促进了对嵌入式系统的更深入理解,以及应对硬件设备所需的技能。我们希望徽章能激发进一步的兴趣,并在会议结束后很长一段时间内,为探索和学习提供一个宝贵的平台。FINISHED
77TgztTD6igmYTUGCtuNPnGjvND+lpulkikXKZWHZCZx+37urypYil6YTwb5lkpjWKX4tYio39urmcBVxNhCcRukR3yBgGga7j/CmBhvLlw=
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)