SCTF 2020 AndroidDisplayBridge

本题官方分类是杂项,题目情景来自于一个实际的android投屏软件,出题者给出的解题目标非常明确,解析数据包中的视频流即可看到flag。这种杂项题目就非常的友好,实际软件、目标明确、思路清晰,并且自己在本题也收获了一些视频方面相关知识,故做此记录。解题方法概括为:1. 识别:识别投屏软件以及软件采用的视频技术。 2. 提取:从数据包中提取出原始的视频流信息。 3. 恢复:将视频流封装成文件并播放。

  • 题目描述:Finding his android phone’s touchscreen not working, he logged in his computer and painted something…
  • 题目附件:sctf_attachment.pcapng

识别

看题目大概知道是android相关的操作,用wireshark打开数据包发现有5555端口,这个一般是adb无线调试的默认端口,所以推断这个流量是adb操作相关的流量。不过我并没有着急去看adb相关协议,而且wireshark本身也支持分析adb协议,右键一条5555端口的流量记录,选择解码为,将当前一栏设置adb,为即可强制解析为目标协议。然后在adb协议的开始流量就发现了一个write命令,包含文件:/data/local/tmp/scrcpy-server.jar。查了一下,这是个投屏软件,而且是开源的:https://github.com/Genymobile/scrcpy。然后就用了一下,是真方便,安完之后一条命令就投屏了,然后还能控制。找了几篇关于这个软件的中文介绍:

总之是个好软件,在第一个知乎的帖子中提到了scrcpy的视频流是H264编码,并且推断这种性能很高也只是自己投屏用的软件应该不会有传输过程的加密。所以接下来就是去了解一下H264相关的知识,并且从数据包中把视频流提取出来。

提取

首先我们常见的视频格式是avi、mp4、mov这些,那H264是个啥呢?我们先看个视频:

mkv、mp4这些视频格式有啥不同?H.264又是什么格式?

原来H264是一种视频编码,其中是没有声音信息的,如果在配上一段AAC编码的音频,就能封装出一个完整有图像有声音的MP4视频啦。如果去显示一下自己电脑中MP4视频的详细信息,一般也会看到视频和音频的编码方式。所以,知道未经过封装的H264的数据长什么样我们就能从数据包中把他提取出来。那么这个家伙长啥样呢?

发现数据包中还真有00 00 00 01 67开头的数据包,server的jar文件传完之后的一段很大的分段的tcp报文就是,所以接下来就是想办法把视频流的数据提取出来。比赛的时候用了个偷懒的办法,虽然在一整个数据包中,视频流数据上下还穿插着adb的命令,不过我记得视频流编码的容错性非常强,而且如果播放器足够强大,花了呼哨的视频也能放出人来。所以我就直接导出了tcp流,选择数据为手机端发送,然后以原始数据导出,就获得了包含有H264的二进制文件。或者使用如下脚本:

import pyshark
captures = pyshark.FileCapture('./sctf_attachment.pcapng')
payload = ""
for capture in captures:
    if hasattr(capture.tcp,"payload") :
        if capture.ip.src == '192.168.1.103':
            payload += capture.tcp.payload.replace(":","").decode("hex") 
f = open("out.h264","wb")
f.write(payload)

恢复

当然,其实很多播放器是能直接播放裸的H264视频流的,不过这里还是尝试一下将H264视频流封装成MP4,毕竟也不难。

$ ffmpeg -i in.h264 output.mp4
$ ffmpeg -i out.mp4 -codec copy -bsf: h264_mp4toannexb -f h264 out.264

第一个命令是把H264格式的视频流直接封装成MP4。如果手头没有h264视频流的格式文件可以相面的话,用第二行命令,可以直接通过ffmpeg从mp4文件中抽一个出来看看。ffmpeg我以前用这个转换过视频格式,听说非常强大:

总之,用第一条命令,把我们刚才导出的文件使用ffmpeg封装成MP4,然后发现可以正常播放,flag就在视频中。

参考

官方WP的解法是数据包中存在着触屏绘图的坐标,提取坐标即可画出flag,自己没想到,也感觉略麻烦。