20220311-西湖论剑-IoTSecPartWriteUp
Wow, IoT! Just make some ez tasks.
Toolkits provided
开发板(海特实验室自研)*4(板子上有两颗CPU,标有AVR的题目是由不同于Linux的处理器执行的),TF卡,TF读卡器,USB-ISP转接器,USB-TTL转接器,FPC及FPC连接器*2,杜邦线*4,排线,micro-USB连接线*若干,还有开发板的与原理图,比赛现场提供电烙铁
TASK1-Linux IoT
tqmm
题目只给了个ip地址,尝试扫描端口,发现开了下面四个端口。nc 9999,提示MQTT通信,并要求公布一串base64编码
不太懂,网上搜一波,发现最后只要作为服务端发送主题和这串base64编码,就可以在客户端收到flag
TASK2-AVR MCU IoT(Aka 找串口
no more time
提供附件内容如下,F_CPU即AVR单片机CPU的时钟频率,其逻辑是若PD2为0则自减1万赫兹,否则不变
最直接的想法,连接板子,和程序交互,满足上述逻辑,便能得到某些东西。用串口调试工具连接UART调试串口,但提示no tf card,如下图所示。而这块板子是有两块CPU的,很明显该题目的程序没有运行起来,或者串口找的不对
1 | 这题直接输出flag。AVR时钟F_CPU存在下面逻辑: |
根据开发板各元器件介绍,以及原理图,找比如RXD和TXD等这些输入输出串口。首先可以看到下图一右上方两个便是开发板上的micro口,分别是OTG和UART调试串口,结合下图一其他信息可以说有程序就是通过UART与外界交互的。接着观察微控制单元ATMEGA328P-MU如下图二,可以看到PD0、PD1分别对应RXD和TXD,可能是另外一个程序的输入输出,然后就可以看到附件中提到的PD2。综上,正确的思路应该是连接MCU的串口,!PD2
也就是短接PD2使之逻辑上为1,从而获得flag
操作如下,为了方便先溜进隔壁的电子实验室给FPC连接器焊上排针,注意正反(给大家看看我焊的球🤣
然后按照原理图,用杜邦线连接FPC与USB-TTL转接器对应的接口,如下图二,其中PD2连PC6或PD7也没什么问题,接地就行
接着用FPC连接开发板MCU的串口以及FPC连接器,注意蓝条在上
最后就是连电脑用串口工具查看了,如下图三所示,注意:插,电源最后插;拔,接地最后拔(来自学长的教诲,好像串口也不可以乱插拔来着
手动多次短接PD2引脚将flag打印出来,如下图所示
一些细节问题
如果是乱码,说明波特率不对,换个波特率多试几次,这里和MCU的串口是9600,和UART是115200
一般来说RXD连TXD,TXD连RXD,但好像也有反过来情况,不行的话尝试两者反接试试
为什么还要连UART这边呢?USB-TTL上虽然写着电源,但这里并没什么软用,所以连UART是为了给开发板供电的。学长说为了保护MCU,TTL这里的电源最好也连上
base64
比赛中的hint
- 逆向AVR固件
- radare2、simavr、avr-gdb
- 自定义base64字母表
需要的工具
复现了上一题,我们就知道怎么和开发板上已有的程序进行交互了,同样是连PD0和PD1引脚看输出
在Ubuntu里,连接好设备后dev路径下会有两个tty,ttyACM0对应UART调试串口,ttyUSB0对应MCU的调试串口
连接好,打开串口工具,并设置好参数,连接上之后点击开发板上的MCU-RST按钮,就可以和该题程序交互了。如下图所示,是一个变表base64编码,编码后的flag为
1 | UoH+U/D/U92lgdLnWMZIR/nOVo2JU9VKOi== |
这里不仅仅是输出一个加密后的flag,我们也可以使用这个变表的base64进行编码,所以如果MCU里面程序可以接收字节流的话,其实是可以直接打印变化后的表的。只要发送下面这串
1 | space = b'' |
但尝试发送十六进制数据,失败收尾,毕竟还要看里面程序接受的是不是字节数组
这道题可以直接提取固件(没有锁死熔丝位啥的
1 | avrdude -F -c usbasp -p atmega328p -U flash:r:base64.hex |
(这个我虚拟机提不出来,换了fuck@Scr1pt的mac才提出来
提完固件,分析思路就和一般的二进制题差不多了,主要是相应工具的使用。对于iot的题目,用到的是题目最开始所列的那些工具
静态分析
strings
首先使用strings
命令参看程序中硬编码的字符串
其中并没有变化后的base64表,推测其应该是程序运行时按照某顺序生成的
radare2
使用radare2进行分析,radare2是逆向分析工具,和ida类似,但是是开源的
加载程序,-a
参数设置程序架构
a命令
aaaaa
分析全部二进制代码,radare2为我们划分程序并命名
afl
列出所有函数
其中位于
0x00000068
处的entry0
即我们现在所处的位置,就是整个程序的入口
p命令
pdf
打出反汇编后的代码(太长了,不好看,不能f5反编译就折磨
pd @ <function name>
查看某一函数的反汇编,比如
entry0
如下可以看到入口函数,call了一些函数,也可以用
p
命令查看
之类的静态分析的常规操作
但纯汇编实在是太不友好。BTW上面这些用ida同样可以完成
接着,结合re的一般流程,当然可以想到通过动调的方式来获取base64变表
动态分析
qemu-system-avr
模拟固件
1 | qemu-system-avr -M uno -bios base64.hex -nographic |
使用ctrl a c
命令进入qemu monitor模式,使用如下命令查看qemu模拟器中的内存映射
1 | info mtree |
可以看到sram静态存储器的范围在0x0000000000800100-0x00000000008008ff
之间
使用memsave
指令将这段内存dump下来
1 | memsave 0x800100 2048 1.bin |
使用010editor查看,就能找到base64变表了
总的来说,和fuck@Scr1pt的那道病毒题很像,壳难脱,也是dump内存来得快
最后解密就好了
1 | import base64 |
滴滴答
附件提示如下
1 | 单片机实现摩斯加密过程,已知在处理高汉明重量时消耗的时间较长,串口输出为计数器Count日志,请输出明文。t = 1000000 * Count / 16000000) |
连接板子后的输出结果如下图所示
提示说处理高汉明重量时消耗的时间较长,这里科普一下
- 汉明距离:两个等长的字符串对应位置上的字符不同的个数
- 汉明重量:特殊的汉明距离,即一个字符串中非零的字符个数
然后说是hangming(“.”) = 4,hangming(“_”) = 6,但其实就算不知道,也就只有两种情况,都试一下就行
用输出的Count计算t,转成图表更加直观
1 | import matplotlib.pyplot as plt |
其中间隔最大的显然就是间隔符,间隔中等和间隔最小的要么是_
和.
,得到如下
1 | .-- . .---- -.-. ----- -- . |
1 | from exploit.Morse import morse |
(不要傻的(是本人)拿右边的进度做文章,然后得到了shit
1 | c = [0, 3, 7, 11, 14, 18, 22, 25, 29, 33, 37, 40, 44, 48, 51, 55, 59, 62, 66, 70, 74, 77, 81, 85, 88, 92, 96, 100] |
Reference
- 海特实验室wp
- u神wp-no more time
- ChaMd5团队wp
- https://www.waveshare.net/w/upload/DVD_AVR8_CN/data/product/USB_AVR_ISP_XPII_PG-2-3.htm
something else