SJTU-CTF 2020 WriteUp Misc

Preface

这次是第二次参加比赛,爆肝两周混了个前十,虽然 Web 方向在某种程度上有所进步,然而 Reverse, Pwn 和 Crypto 还是一样地菜(

easy_adb

喜闻乐见的流量分析题,给出了一个 pcap 文件,用 Wireshark 打开,结果并没有识别出 ADB 数据流,只是显示为普通的 USB 数据流;在一堆 URB_BULK in 数据流中发现了 /dev/input/event 等字样,使用 tshark 将这部分数据流导出为字节流,自行编写脚本进行解码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import codecs
import re

f = open('usbdata.txt','r')
lines = f.readlines()
f.close()
f = open('parse1.txt', 'w')
data = []
for line in lines:
raw = bytes(line.strip(),'utf8')
raw = codecs.decode(raw, 'hex')
raw = raw.decode('ascii', 'ignore')
raw = re.sub(r"[^\d\w:\'\"\s]", '', raw)
f.write(raw.strip())
f.close()

得到类似这样的数据:

1
2
3
4
5
devinputevent2: 0003 0030 00000013
124793798544 devinputevent2: 0003 0031 00000010
124793798544 devinputevent2: 0003 003a 0000000f
124793798544 devinputevent2: 0000 0000 00000000124793806666
...

查找资料发现此类数据为屏幕触摸事件,可用 adb getevent 获取,猜想出题人应该是在手机上画出了 flag,因此只要使用 adb sendevent 反向模拟即可,先对数据进行进一步处理

需要注意的是 getevent 输出为十六进制,而 sendevent 输入应为十进制;同时,/dev/input/event1 在不同设备上也可能不同,可用 getevent 进行查看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import re

pat = r"devinputevent2: ([\da-f]{4}) ([\da-f]{4}) ([\da-f]{8})"
f = open('parse1.txt', 'r')
raw = f.read()
f.close()
data = re.findall(pat, raw)
f = open('parse2.txt', 'w')
for d in data:
arg = [int(str(x),16) for x in d]
# 坐标缩放
if arg[1] == 54 or arg[1] == 53:
arg[2] /= 2
f.write('sendevent /dev/input/event1 %d %d %d \n' % (arg[0], arg[1], arg[2]))

之后可以得到这样的文件:

1
2
3
4
5
sendevent /dev/input/event1 3 48 19 
sendevent /dev/input/event1 3 49 16
sendevent /dev/input/event1 3 58 15
sendevent /dev/input/event1 0 0 0
...

由于 ADB 模拟触摸事件需要 root,此处使用了以前 root 过的小屏手机,使用 ADB 模拟可看到绘制 flag 的动态过程,但由于一些坐标超出了屏幕范围,最终得到的图像并不完整,故将横纵坐标进行缩放,得到完整图像:

除使用真机模拟触摸事件外,还可使用脚本根据坐标绘制出图像

baby_1090

Flag: 0ops{[1]-[2]-[3]-[4]-[5]-[6]}

Flag parts:

Try to find the flight at those coordinates.

1
2
3
4
5
6
7
8
| No. | Lat     | Long     | Alt    |
|-----|---------|----------|--------|
| 1 | 31.279 | 121.332 | 1325 |
| 2 | 31.436 | 121.113 | 13800 |
| 3 | 31.588 | 120.315 | 14500 |
| 4 | 31.486 | 121.227 | 5100 |
| 5 | 31.686 | 121.007 | 7200 |
| 6 | 31.787 | 120.489 | 12650 |

顺带给了个 RF.raw 文件,起初还以为是 RAW 图像格式,后来才知道是无线电(Radio Frequency)

然而本人并没有任何无线电知识,也找不到相关的 CTF 资料,胡乱试了一堆工具无果,于是只好先搁置一边

接着后来放了个提示:tunefreq-1090MHz_samplerate-2.4MHz,看上去只是两个参数,但出于好奇还是去搜了下 1090MHz 是个什么东西,结果发现是 ADS-B(没错就是 Flightradar24 用的那个,伪航迷狂喜),于是就开始找 ADS-B 数据解码工具,花了一番功夫找到了 dump1090,然而这玩意儿貌似要自己编译,为了图方便我直接选择了 Debian 下直接可用的 dump1090-mutability

事实证明这是个正确的选择,因为原文件的采样率为 2.4MHz,而 dump1090 的采样率为 2.0MHz,无法直接使用

安装好之后使用 dump1090-mutability --ifile RF.raw > RF.txt 即可导出数据,大概长这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
*8d7811ce99400792e834041bf0b8;
CRC: 000000
RSSI: -15.6 dBFS
Score: 1400
Time: 155198.42us
DF:17 AA:7811CE CA:5 ME:99400792E83404
Extended Squitter Airborne velocity over ground, subsonic (19/1)
ICAO Address: 7811CE (Mode S / ADS-B)
Air/Ground: airborne
GNSS delta: 75 ft
Heading: 178
Speed: 150 kt groundspeed
Vertical rate: -768 ft/min barometric

*8d7811d0582d31237a473f4d5ef9;
CRC: 000000
RSSI: -25.9 dBFS
Score: 1400
Time: 208782.00us
DF:17 AA:7811D0 CA:5 ME:582D31237A473F
Extended Squitter Airborne position (barometric altitude) (11)
ICAO Address: 7811D0 (Mode S / ADS-B)
Air/Ground: airborne
Altitude: 7875 ft barometric
CPR type: Airborne
CPR odd flag: even
CPR NUCp/NIC: 7
CPR latitude: (37309)
CPR longitude: (18239)
CPR decoding: none
...

看起来经纬度和海拔信息都有了,按照题目寻找相应航班即可,需要注意的是经纬度存在舍入误差;此外还有一个小细节,上面的信息中所给的是 ICAO 地址,而经过实际验证,题目所需的是航班号,虽然根据 ICAO 地址和位置、时间等信息可以确定航班号,但未必有些繁琐;仔细查看上述文件,发现文件中还包含了另一类信息,类似这样:

1
2
3
4
5
6
7
8
9
10
11
*a00003bc200d3239c78da06dc464;
CRC: 7800d1
RSSI: -28.8 dBFS
Score: 1000
Time: 1568962.83us
DF:20 addr:7800D1 FS:0 DR:0 UM:0 AC:956 MB:200D3239C78DA0
Comm-B, Altitude Reply
ICAO Address: 7800D1 (Mode S / ADS-B)
Air/Ground: airborne?
Altitude: 5300 ft barometric
Ident: CSH9186

根据此类信息即可将 ICAO 地址与航班号相对应,得到 flag: 0ops{CSH9498-CCA1883-CHH7852-CSH9186-CSH9220-CQH8796}

SuperSecureHacking

Help! My server has been hacked because of a weak password :(

Thankfully, I have logged the network traffic and the attacker’s input(partially). Could you please help me trace his activity?

题目给出了 hacker.pcapkey.log 两个文件,其中 key.log 文件内容如下:

1
lswhoamiecho 0ops{theQ3nt1m9dDddis3N1qd5pp42attt33rPn3Ss1n0pSSEn0opSH}>flagexit

可以看到其中包含一些 shell 命令,还有 flag 的起始标记,应该是键盘输入的记录,然而其中的 flag 并不是正确答案,还需找到最终输入结果

查看 hacker.pcap,发现有 SSH 的流量数据,众所周知 SSH 流量是经过加密的,如需获取通讯内容还需破解加密

经过一番搜寻找到了一个年代久远的工具:ssh_decoder,然而由于 Ruby 环境等各种原因最后并没有跑起来…

又不知在网上逛了多少天,突然发现了一个神奇的工具:packetStrider,此工具虽然无法破解加密获取内容,但却可以从流量包中提取一些其他信息,比如键盘输入和退格事件,如下:(图源

有了这个,再加上 key.log,此题的解法就一目了然了,将分析得到的键盘输入事件与键盘日志匹配,即可得到 flag: 0ops{h1dd3Np4tt3rns1nSSH} (凭借多年混迹网络培养的搜索能力成为了此题的唯一解题者)

出题人语:实质上是一个侧信道问题

baby_super_easy_vmem

又是喜闻乐见的内存取证题,题目给出了一个虚拟内存文件 .vmem,按惯例使用 volatility 分析系统类型,为 Windows 8

接着看一眼进程列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
> volatility -f "vmem.vmem" --profile=Win8SP0x64 pslist
Volatility Foundation Volatility Framework 2.6
Offset(V) Name PID PPID Thds Hnds Sess Wow64 Start Exit

------------------ -------------------- ------ ------ ------ -------- ------ ------ ------------------------------ ------------------------------
...

0xffffe001b2baa8c0 ruby.exe 1508 528 10 0 0 0 2020-10-12 04:29:38 UTC+0000

0xffffe001b2be78c0 cygrunsrv.exe 1552 1412 0 -------- 0 0 2020-10-12 04:29:38 UTC+0000

0xffffe001b2be5640 conhost.exe 1568 1552 2 0 0 0 2020-10-12 04:29:38 UTC+0000

0xffffe001b2c3e080 sshd.exe 1608 1552 3 0 0 0 2020-10-12 04:29:38 UTC+0000

...

0xffffe001b2d33340 cmd.exe 2096 4028 1 0 2 0 2020-10-12 04:31:09 UTC+0000

0xffffe001b2755080 conhost.exe 1896 2096 3 0 2 0 2020-10-12 04:31:09 UTC+0000

0xffffe001b300f080 WmiApSrv.exe 2764 528 5 0 0 0 2020-10-12 04:32:02 UTC+0000

0xffffe001b37c68c0 SearchProtocol 3592 2368 6 0 0 0 2020-10-12 04:32:50 UTC+0000

0xffffe001b2259240 SearchFilterHo 3516 2368 5 0 0 0 2020-10-12 04:32:50 UTC+0000

0xffffe001b2f5e8c0 ffplay.exe 3876 2096 8 0 2 0 2020-10-12 04:32:52 UTC+0000

0xffffe001b2d788c0 cmd.exe 1668 1996 0 -------- 0 0 2020-10-12 04:32:57 UTC+0000

...

比较可疑的进程有 cmd.exeffplay.exeruby.exe

扫描一遍文件,看到桌面有一个 flag_part1.txt,导出得 flag 的第一部分:flag{40d24d145025012c6ae

既然有 cmd.exe,那就看一下命令行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
************************************************************************
System pid: 4
************************************************************************
...
ruby.exe pid: 1508
Command line : "C:\Program Files\Puppet Labs\Puppet\sys\ruby\bin\ruby.exe" -rubygems "C:\Program Files\Puppet Labs\Puppet\service\daemon.rb"
************************************************************************
cygrunsrv.exe pid: 1552
************************************************************************
conhost.exe pid: 1568
Command line : \??\C:\Windows\system32\conhost.exe 0x4
************************************************************************
sshd.exe pid: 1608
Command line : "C:\Program Files\OpenSSH\usr\sbin\sshd.exe"
************************************************************************
...
cmd.exe pid: 2096
Command line : "cmd.exe" /s /k pushd "C:\Users\IEUser\Desktop\ffmpeg"
************************************************************************
...
ffplay.exe pid: 3876
Command line : ffplay http://192.168.85.1:8000/flag_part2.jpg
************************************************************************
cmd.exe pid: 1668
************************************************************************
...

ffplay http://192.168.85.1:8000/flag_part2.jpg 表明使用 ffplay 显示了另一主机上的图片文件,故导出 ffplay.exe 的内存数据,使用 binwalk 扫描文件,foremost 导出,遗憾的是只得到了一个残缺的 jpg 文件,且看不见 flag 结束标志符,如下:

另寻他路,考虑到图片是通过网络传输的,故试图导出流量数据,搜索后发现 CapLoader 正好符合要求,导出得到 pcapng 格式的流量包,在 TCP Retransmission 中可以找到图片:

导出字节流并用脚本转换为图片,如下:

虽然仍然是残缺的图片,但已经可以辨认出字符,拼接得到 flag: flag{40d24d145025012c6ae2fbd5aaf9583322fb356a}

其实使用 binwalk 获取残缺的图像之后即可解题,预期解法是使用 GIMP 调整图像大小,将图片类型切换为 RGB Alpha 即可看清文字,不过由于并没有复现成功,在此不展开叙述

Author

Googleplex

Posted on

Jan 22, 2021

Updated on

Jan 24, 2021

Licensed under

Comments