题目环境见:
https://github.com/yichen115/hackasat-qualifier-2020/tree/master/bus
在搭建环境之前需要搭建一个基础环境,进入 generator-base 之后运行下列命令把基础的镜像生成出来,具体见之前的文章:HackaSat2020预选赛beckley
docker build -t generator-base .
然后进 bus 文件夹运行 make build 把环境搭建起来,然后运行下列命令环境就启动了
socat -v tcp-listen:31340,reuseaddr exec:"docker run --rm -i -e SEED=1234 -e FLAG=flag{1234} bus:challenge"
然后 nc 172.17.0.1 31340 上去得到一堆奇怪的字符,题目描述:There’s a very busy bus we’ve tapped a port onto, surely there is some juicy information hidden in the device memory… somewhere…
书上说的是通过搜索卫星常用总线协议报文格式确定了用的是 IIC,我就直接学吧,估计我搜到了也认不出来 2333
通信的起始信号和终止信号都是由主设备发送的,起始信号发送之后跟一个 7bit 的从设备地址和 1bit 的方向位(方向位 0 表示主设备发送数据,1 表示主设备接受数据)也叫读/写位
每当主设备发送完一个字节的数据后需要等待从设备给出一个应答信号,来确认从设备是不是接收到了数据
1、主设备发送起始信号(START)
2、主设备发送从设备地址和方向位 0
3、等待从设备响应(ACK)
4、主设备发送数据到从设备,一般每发送一个字节会等待从设备的响应(ACK)
5、数据发送完毕,主设备发送停止信号(STOP)
1、主设备发送起始信号(START)
2、主设备发送从设备地址和方向位 1
3、等待从设备响应(ACK)
4、主设备接收来自从设备的数据,一般每接收一个字节会向从设备发送一个相应(ACK)
5、一般主设备接收到最后一个数据后会发送一个无效响应(NACK),然后主设备发送停止信号(STOP)
对输出数据简单的处理一下,发现是根据 ^ 和 . 来区分每一段数据的,那么 ^ 就是 IIC 的 START 信号,. 就是 IIC 的 STOP 信号
^82+00+00+1f+00+00+00+12+47+40+41+c6+97+e1+3f+89+81+3f+c1+99+1d+a1+c0+20+18+a1+40+5e+42+ac+3c+.
^83+00+00+3f+.
^82+00+00+3f+00+00+00+20+fa+3f+41+c8+da+e2+3f+a6+64+3f+c1+ff+33+a1+c0+a4+d2+a0+40+de+50+55+40+.
^b4+01+c9+61+20+30+33+00+f0+28+65+f5+e6+8f+3c+ba+5b+35+28+c7+5b+8f+6d+f3+ee+a2+57+23+bb+3b+9c+f0+31+a9+ed+80+2e+42+57+.
^83+00+00+1f+.
^82+00+00+1f+00+00+00+1d+ec+3f+41+d8+04+e5+3f+67+4e+40+c1+38+1b+a1+c0+e1+dd+a0+40+b9+91+91+3c+.
^82+00+00+1f+00+00+00+1d+ec+3f+41+d8+04+e5+3f+67+4e+40+c1+38+1b+a1+c0+e1+dd+a0+40+b9+91+91+3c+.
^83+00+00+3f+.
^82+00+00+3f+00+00+00+da+81+3f+41+50+c7+e3+3f+9c+28+40+c1+77+df+a0+c0+44+1d+a0+40+7f+b7+52+40+.
^b4+01+7e+5f+9a+4a+75+69+63+79+20+44+61+74+61+20+30+32+00+90+2e+f3+7b+07+99+eb+9b+43+16+a2+b1+9a+a0+2d+f9+3a+72+f7+8f+cb+d7+e3+80+43+1d+.
^83+00+00+1f+.
^82+00+00+1f+00+00+00+41+85+40+41+e2+7a+e1+3f+e8+28+40+c1+fc+50+a0+c0+6e+09+9f+40+57+8c+e9+3c+.
..........
START 信号结束后就跟着从设备地址和方向位了,可以看到只有三种情况 0x82、0x83、0xb4
第一字节 |
从设备地址 |
读/写位 |
0x82 |
0x41 |
0 写 |
0x83 |
0x41 |
1 读 |
0xb4 |
0x5a |
0 写 |
按照这个规则我们看一下,0x83 开头的读操作内容都很少,比如:^83+00+00+1f+. 这里面必然不能含有 flag,因此可以假设这里的读写操作是与 I2C 标准相反的,那我们来梳理一下每一步都是做了什么事情
第一字节 |
从设备地址 |
读/写位 |
0x82 |
0x41 |
0 读 |
0x83 |
0x41 |
1 写 |
0xb4 |
0x5a |
0 读 |
从0x41读取:^82+00+00+1f+00+00+00+12+47+40+41+c6+97+e1+3f+89+81+3f+c1+99+1d+a1+c0+20+18+a1+40+5e+42+ac+3c+.
向0x41写入:^83+00+00+3f+.
从0x41读取:^82+00+00+3f+00+00+00+20+fa+3f+41+c8+da+e2+3f+a6+64+3f+c1+ff+33+a1+c0+a4+d2+a0+40+de+50+55+40+.
从0x5a读取:^b4+01+c9+61+20+30+33+00+f0+28+65+f5+e6+8f+3c+ba+5b+35+28+c7+5b+8f+6d+f3+ee+a2+57+23+bb+3b+9c+f0+31+a9+ed+80+2e+42+57+.
向0x41写入:^83+00+00+1f+.
从0x41读取:^82+00+00+1f+00+00+00+1d+ec+3f+41+d8+04+e5+3f+67+4e+40+c1+38+1b+a1+c0+e1+dd+a0+40+b9+91+91+3c+.
从0x41读取:^82+00+00+1f+00+00+00+1d+ec+3f+41+d8+04+e5+3f+67+4e+40+c1+38+1b+a1+c0+e1+dd+a0+40+b9+91+91+3c+.
向0x41写入:^83+00+00+3f+.
从0x41读取:^82+00+00+3f+00+00+00+da+81+3f+41+50+c7+e3+3f+9c+28+40+c1+77+df+a0+c0+44+1d+a0+40+7f+b7+52+40+.
从0x5a读取:^b4+01+7e+5f+9a+4a+75+69+63+79+20+44+61+74+61+20+30+32+00+90+2e+f3+7b+07+99+eb+9b+43+16+a2+b1+9a+a0+2d+f9+3a+72+f7+8f+cb+d7+e3+80+43+1d+.
向0x41写入:^83+00+00+1f+.
从0x41读取:^82+00+00+1f+00+00+00+41+85+40+41+e2+7a+e1+3f+e8+28+40+c1+fc+50+a0+c0+6e+09+9f+40+57+8c+e9+3c+.
从0x41读取:^82+00+00+1f+00+00+00+41+85+40+41+e2+7a+e1+3f+e8+28+40+c1+fc+50+a0+c0+6e+09+9f+40+57+8c+e9+3c+.
向0x41写入:^83+00+00+3f+.
从0x41读取:^82+00+00+3f+00+00+00+ce+79+3f+41+5e+35+e6+3f+5d+a7+3f+c1+4c+81+a0+c0+57+75+9f+40+0b+f3+50+40+.
从0x5a读取:^b4+01+93+99+eb+9b+43+16+a2+b1+9a+a0+2d+f9+3a+72+f7+8f+cb+d7+e3+80+43+1d+12+94+c7+59+78+58+87+6b+d3+8e+04+be+2a+47+d4+cc+f8+6e+6c+26+67+a6+98+5e+4a+75+69+63+79+20+44+61+74+61+20+30+33+00+f0+28+65+.
总结一下规律:首先从 0x41 读取,然后向 0x41 写入 3f,然后再读取 0x41,最后读取 0x5a 的内容,根据规律可以发现 0x5a 那一部分是内容最多的,里面最有可能隐藏 flag,那这个过程可以猜测为:首先读一下 0x41 的内容看看是不是 1f,是的话向 0x41 写入 0x3f,然后再次读取确认一下,是 0x3f 的话就可以读取 0x5a 的内容了
另外在题目的源码中有这么一段描述:
此挑战运行两分钟,并模拟连接了以下设备的 I2C 总线:
- OBC(车载电脑 - 总线主控)
- EEP(存储包含 "juicy data" + flag 的设备)
- EPS(电力系统控制器)
OBC 在运行时每十秒轮询一次总线,提供线索,并且通常在大部分时间占用总线。总线数据速率被人为限制以确保这一点。
我们需要转储 EEP,但是有两个问题:
1) EEP 电源在更新之间关闭。
2) OBC 大部分时间都在占用总线。
通过查看流量,我们看到 OBC 为设备启用电源,从中读取(在不包含标志的随机区域),然后将其关闭。在那之后,在轮询再次开始之前有一个短暂的停顿(几秒钟)。
理想情况下,参赛者将使用该暂停,发出 I2C 请求以关闭 OBC 的电源,释放总线,以便 EEP 可以在分配的时间内转储。
那么 0x41 就是 EPS 电源控制器了,0x5a 是 EEP,也就是存储着 “juicy data” + flag 的存储芯片。EPS 开关控制着我们能不能从 EEP 读取到数据,且每次我们发送开启后都会被再次关闭,根据我们发现的规律,电源控制器的二进制表示的第 6 位表示 EEP 的开关
EEP电源开关 |
EPS状态(十六进制) |
EPS状态(二进制) |
EEP电源开关关闭 |
0x1f |
0001 1111 |
EEP电源开关打开 |
0x3f |
0011 1111 |
因为总线被 OBC 占用了大部分时间,我们要做的就是发送 IIC 数据,把除了 EEP 之外的设备电源关闭以释放总线资源,EEP电源打开的情况是 00111111,关闭情况是 00011111,因此只打开 EEP 电源的情况是 0010 0000,也就是十六进制的 0x20,因此发送 ^83000020. 即可保持 EEP 打开而其他设备关闭,然后发送以下指令正常读取 EEP 数据即可
^b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
读取出来的数据如下,处理后将十六进制值转为字符串得到 flag:
^b4+00+00+4a+75+69+63+79+20+44+61+74+61+20+30+30+00+4b+fb+1b+a3+4a+05+7e+a3+63+46+f2+0c+57+b4+eb+50+68+cf+8b+e4+1f+6f+40+7b+91+82+23+fc+65+a6+3a+b0+a1+55+53+eb+5b+d1+8f+be+17+81+cb+6f+35+b6+bf+9e+85+4a+4a+75+69+63+79+20+44+61+74+61+20+30+31+00+d7+ac+75+32+7e+04+f1+95+85+bc+04+bb+72+c4+59+f7+0e+db+9c+c8+9e+bb+14+e2+fe+5b+8c+e6+dd+e5+70+b5+92+e6+e7+10+ea+d8+a5+70+94+aa+2b+06+6e+84+fe+7c+5f+9a+4a+75+69+63+79+20+44+61+74+61+20+30+32+00+90+2e+f3+7b+07+99+eb+9b+43+16+a2+b1+9a+a0+2d+f9+3a+72+f7+8f+cb+d7+e3+80+43+1d+12+94+c7+59+78+58+87+6b+d3+8e+04+be+2a+47+d4+cc+f8+6e+6c+26+67+a6+98+5e+4a+75+69+63+79+20+44+61+74+61+20+30+33+00+f0+28+65+f5+e6+8f+3c+ba+5b+35+28+c7+5b+8f+6d+f3+ee+a2+57+23+bb+3b+9c+f0+31+a9+ed+80+2e+42+57+1e+6a+bc+13+50+4b+50+0a+a6+85+32+6d+e0+c2+da+d3+b0+7c+2b+4a+75+69+63+79+20+44+61+74+61+20+30+34+00+2b+78+13+76+c8+1d+1c+4d+50+89+2d+12+63+01+c2+e0+2c+95+17+92+05+3f+2a+1d+55+43+64+ad+b2+c9+66+6c+61+67+7b+31+32+33+34+7d+00+85+02+5e+86+c4+3e+b2+59+55+4a+75+69+63+79+20+44+61+74+61+20+30+35+00+89+97+f4+29+
参考:
https://zhuanlan.zhihu.com/p/503219395
https://www.elecfans.com/d/1845634.html
原文始发于微信公众号(物联网IoT安全):卫星黑客挑战赛 | IIC协议破解