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 codecsimport ref = 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 repat = 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.pcap
和 key.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.exe
、ffplay.exe
和 ruby.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 即可看清文字,不过由于并没有复现成功,在此不展开叙述