下载题目文件,是个wav音频文件。放进Audacity查看,发现完全听不见,题目也提示了大声播放。放大后的波形填满了格子,联想到sstv,转换为频谱图后确认为sstv。
之前这个系列的Part11的第四题也是sstv,当时题目提示了是sstv,所以直接使用工具了,但如果我们回到当时那道题目,查看频谱图会发现也是长这个样子。下面是张对比图,上面的是这道题的频谱,下面是上次那道题的频谱,从形状特征的角度来看是非常相似的。
回到题目本身,解sstv需要用到专门的工具。这里还是使用这个在线工具。(https://sstv-decoder.mathieurenaud.fr/)解码后得到一个图像,我们需要的flag就在其中。
类型 | 图片隐写(sstv) |
---|---|
工具 | Audacity、在线sstv解码工具 |
Flag | flag{r3ce1ved_4n_img} |
原题有以下提示:
日常违规审计中频次有时候非常重要
CTF中的频次主要指的是字频或词频,其中字频考察居多。下载图片,直接放进随波逐流工具,工具输出了大量信息,有两点需要关注。第一点是文件末尾还有别的文件,并且binwalk的结果是分离出一个zip。
第二点是图片exif的详细信息中“XPComment”字段存在人工编写的单词。
先看第一个zip文件,在kali中用foremost直接分离,得到一个带有密码的zip文件。
第二点发现的评论内容“Pactera”就是密码。解压后查看文本文件,其中包含大段的无意义词组,这里排除了词频直接搜索文本的字频。
字频统计用这个在线工具,统计结果如下图所示,从高频字符到低频依次连接就是答案。
DCTF{huanwe1sik4o!}
类型 | 字频分析、图片隐写 |
---|---|
工具 | 在线字频分析工具、随波逐流工具、foremost |
Flag | flag{huanwe1sik4o!} |
下载题目文件。是个叫做“photo.dat”的文件。考察的是个小知识,微信在聊天过程中会把所有保存在本地的图片统一转换为.dat格式进行保存,说是进行了一个加密,其实原理就是对所有的字节进行了一次异或操作,只要我们能够找到异或的具体位,就可以破解加密从而不登陆微信也能看到图片。当然这里即便不知道,通过在百度上查找dat后缀文件,也很快能找到这一知识点。
知道后就可以做题了,我们只要找到这个dat文件具体是和什么位进行了异或,再全部异或一次就能得到原文件了。比较常规的办法是通过dat前两位和常见的文件前两位进行异或,如果异或出来的两个值是相同的,那么就可以猜测是该值。
直接看题,因为提示了是photo,常见的照片是jpg格式的,jpg的前两位是FF D8。用本地的计算器并选择程序员模式,讲jpg的前两位和dat文件的前两位进行异或。
得到结果3333,前后都是33,这说明dat文件很有可能是通过把原文件和0x33异或得到的。把dat文件放进010editor,通过以下路径对全文件进行异或。
把修改后的结果保存出来,得到一张jpg图片。
这个显示的是基站信息,通过基站搜索位置可以找到以下的地点,我用的搜索工具是这个地址。(http://api.cellocation.com:84/cell.html)
答案尝试了几遍,最后发现是这个校区的地址,感觉这个题目应该给个提示。
类型 | 微信文件解密、字符编码、基站定位 |
---|---|
工具 | 010editor、基站在线定位工具 |
Flag | flag{桂林电子科技大学花江校区} |
题目文件是个img文件,说明是个取证的题目。比较简单的取证或者数据恢复可以使用windows上的DiskGenius进行。这里直接将文件拖入该工具并选中“lost+found”文件夹后点击上方的“恢复文件”-“开始”就可以看到丢失的文件了。以下是恢复后的结果,其中flag就在被删除的“.cat.jpg”文件内。
类型 | 取证恢复 |
---|---|
工具 | DiskGenius |
Flag | flag{fugly_cats_need_luv_2} |
题目文件是两个看上去一样但实际大小不同的图片。
我们之前遇到过类似的情况,当时是考察的盲水印,是通过一张图片分离出来两张几乎一样的图。这里其实也是盲水印,只不过不是普通的盲水印而是频域盲水印,上次的工具blind_watermark用不了了,需要用新的工具脚本解题。这块没找到好用的工具,用一下别的大佬wp内的脚本。(该脚本必须用python2来跑,且opencv版本小于等于4.2.0.32)
# coding=utf-8
import cv2
import numpy as np
import random
import os
from argparse import ArgumentParser
ALPHA = 5
def build_parser():
parser = ArgumentParser()
parser.add_argument('--original', dest='ori', required=True)
parser.add_argument('--image', dest='img', required=True)
parser.add_argument('--result', dest='res', required=True)
parser.add_argument('--alpha', dest='alpha', default=ALPHA)
return parser
def main():
parser = build_parser()
options = parser.parse_args()
ori = options.ori
img = options.img
res = options.res
alpha = options.alpha
if not os.path.isfile(ori):
parser.error("original image %s does not exist." % ori)
if not os.path.isfile(img):
parser.error("image %s does not exist." % img)
decode(ori, img, res, alpha)
def decode(ori_path, img_path, res_path, alpha):
ori = cv2.imread(ori_path)
img = cv2.imread(img_path)
ori_f = np.fft.fft2(ori)
img_f = np.fft.fft2(img)
height, width = ori.shape[0], ori.shape[1]
watermark = (ori_f - img_f) / alpha
watermark = np.real(watermark)
res = np.zeros(watermark.shape)
random.seed(height + width)
x = range(height / 2)
y = range(width)
random.shuffle(x)
random.shuffle(y)
for i in range(height / 2):
for j in range(width):
res[x[i]][y[j]] = watermark[i][j]
cv2.imwrite(res_path, res, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
if __name__ == '__main__':
main()
运行以下命令,再次强调要使用python2,否则会出现一堆报错。
python pinyubwm.py --original huyao.png --image stillhuyao.png --result out.png
结果如图,水印内容就是答案。
类型 | 频域盲水印 |
---|---|
工具 | 脚本 |
Flag | flag{BWM_1s_c00l} |
建议跳过,题目目前没法做了,以下内容是参考多个师傅wp做的。
点击文章链接,通过点赞发现“出题人”,这个太阴了,真要做估计我也找不到。
并且这个账号被禁用了,现在没有办法看他的主页,所以这道题相当于无解了,wayback machine中也没有相关记录,以下是别的师傅的wp中截取的。
这是一串base64,但解出来的不是答案,后续怎么做我也不清楚了,也找不到具体的wp,更不会有新的wp了,挺懵的,也许是有什么特殊的加密方式,知道的大佬麻烦评论告诉我,感谢。
类型 | 社工 |
---|---|
工具 | 无 |
Flag | flag{31010419920831481363542021127} |
首先,文件打不开,放进随波逐流工具显示文件头不匹配,这里直接放进010editor看具体是什么情况,这里很显然,后面跟着一个JFIF,说明是个jpg文件。只需要把前面四位改为标准的FF D8 FF E0就行。
放入随波逐流工具,发现末尾存在16进制串,放入CyberChef后导出文件到本地。
由于光看文件头看不出什么,这里可以上传到这个在线工具中进行查看,这个工具集成了“TRiD”和其它文件搜索引擎,主要用途是分析恶意文件的,但在文件类型识别上也很准。也可以下载TRiD工具到本地使用。
这里显示是Python的序列化文件,是由Pickle这个模块实现的,我们需要做的就是进行反序列化得到原本的数据。写个简单脚本,输出为output.txt。
import pickle
with open("download.dat", "rb") as fp:
a = pickle.load(fp)
with open('output.txt', 'w') as fw:
fw.write(str(a))
输出的文本内容是多个坐标。看来这里还需要把这些坐标绘制出来。
还是用脚本来打印这些坐标点位。
with open("output.txt", "r", encoding="utf-8") as f:
data = eval(f.read())
for line_data in data:
if not line_data:
print()
continue
max_pos = max(coord[0] for coord in line_data)
temp = [' '] * (max_pos + 1)
for pos, char in line_data:
if pos < len(temp):
temp[pos] = char
print(''.join(temp))
类型 | 文件修复、图片隐写、文件识别、Python序列化 |
---|---|
工具 | 随波逐流工具、CyberChef、010editor、TRiD、Python脚本 |
Flag | flag{a273fdedf3d746e97db9086ebbb195d6} |
下载题目文件,是个压缩包,其中包含了一个Unity游戏。
运行游戏,按住w键一直往上飞,答案出现。
类型 | 游戏(签到题) |
---|---|
工具 | 无 |
Flag | flag{You_Are_The_Ready_Player_One!!!For_Sure!!!} |
下载题目文件,是个美女侧脸,放在这里欣赏一下。
放进随波逐流工具后发现有结尾有东西,并且binwalk的结果是分离出另外一个png图片。
放进kali用foremost进行分离,得到的png是半个二维码。经过一段时间的检查,发现这张图片没有别的隐藏信息了,说明另外半边没有数据位,只有信息位了。之前我们遇到缺了一个角的,需要补充一个定位角,但这道题更加复杂一些,光补充两个角是不够的,我们还需要补充信息位。
信息位就是二维码的格式字符串,代表着一些和二维码解析有关的数据,比如掩码模式位、计算纠错位等,下图中蓝色部分就是这个格式字符串的顺序,其中数字的越小代表越高的有效位,其中0最高。
相同数字的位置的颜色是相同的,目的是为了纠错,其中一个缺少了还可以参考另外一个。原图已经有了7-14的数据,但缺少0-6的数据,我的办法是都试一遍。我们先把原图一一对应的填入这个二维码绘画工具中。(https://merri.cx/qrazybox/)
点击任意一个0-6有效位,会出现可选的排列组合,只有图片为以下设置时才能正常解析。
画好图后点击右上方的工具中的提取功能,就得到我们需要的flag。
类型 | 图片隐写、二维码复原 |
---|---|
工具 | 随波逐流工具、foremost、qrazybox |
Flag | flag{OQWIC_4DS1A_S034S} |
类型 | 签到题 |
---|---|
工具 | 无 |
Flag | flag{welcome_to_dasctf_may} |
题目提示了有Autokey,我的理解就是一种维吉尼亚密码的变式,解密的方式是差不多的。先下载题目文件,是个pcapng的日志文件,用wireshark打开,发现全是USB数据。
USB考点要么是鼠标移动轨迹,要么是键盘输入记录,这里先用这个工具尝试一下键盘输入。
mplrvffczeyoujfjkybxgzvdgqaurkxzolkolvtufblrnjesqitwahxnsijxpnmplshcjbtyhzealogviaaissplfhlfswfehjncrwhtinsmambvexpziz
输出的正好是一个Autokey加密的密文,放进这个维吉尼亚解密在线工具,选中Autokey变体解密,就可以对密文进行爆破,同时会对结果进行英文词语的识别,能够快速帮助判断真正的原文。
所有的输出都会进行一个语义的打分,得分最高的往往就是原文,这里也确实是我们需要的答案,这里还需要进行一次大写处理。
类型 | 日志分析、加密解密 |
---|---|
工具 | wireshark、CTF-Usb_Keyboard_Parser、在线解密工具 |
Flag | flag{JHAWLZKEWXHNCDHSLWBAQJTUQZDXZQPF} |
题目文件包含一个压缩文件和一个文本文件,文本内容如下。
This file is very deep. Will you dare dig in it ?
这个意思应该就是套娃了,需要不断解压缩得到最终文件,看了一下这个压缩文件,也确实是这样,一层套一层。
用python脚本解决。
import os
import glob
import tarfile
def extract_tarxz_silent():
while True:
tarxz_files = glob.glob('**/*.tar.xz', recursive=True)
if not tarxz_files:
break
for file_path in tarxz_files:
try:
with tarfile.open(file_path, 'r:xz') as tar:
tar.extractall()
os.remove(file_path)
except:
continue
if __name__ == "__main__":
extract_tarxz_silent()
跑到最后出现一堆flag文件,直接打开其中后面没有后缀数字的flag文件,答案就在其中。
类型 | 压缩嵌套 |
---|---|
工具 | 脚本 |
Flag | flag{04ebb0d6a87f9771f2eea4dce5b91a85e7623c13301a8007914085a91b3ca6d9} |
感谢支持!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。