BUUCTF misc wp(3)

[toc]

这篇文章记录一下BUUCTF一些难题的wp,即我做题时分值大于90分的部分题目,更新速度应该比较慢,且文章篇幅较大时会新开一篇。(题目难度没有顺序)

[DDCTF2018]流量分析

下载附件得到一个流量包。

有一个hint文件,看了下大概是一个上传密钥的题

用wireshark打开后,在tcp.stream eq 2005中发现一个zip文件

另存zip文件,发现一个加密的数据库文件,好像作用不大。

在tcp.stream eq 2020看到了一段聊天记录,跟刚刚分离出的ZIP文件有关

但是并没有密钥信息。

在tcp.stream eq 2016 里有一段十六进制,看起来像是中文。

解码得:

看来这题需要的就是将上传密钥,接下来需要的就是找到密钥。

在同一数据流下,发现了一个很长的base64编码,看到开头的iVB,很明显就是一张图片的base64编码。

将base64解码后得到一张图片:

看样子挺像是私钥格式的,利用QQ自带的OCR功能识别文字,然后一个一个对照一下,加上私钥格式,得到私钥字符串:

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDCm6vZmclJrVH1AAyGuCuSSZ8O+mIQiOUQCvN0HYbj8153JfSQ
LsJIhbRYS7+zZ1oXvPemWQDv/u/tzegt58q4ciNmcVnq1uKiygc6QOtvT7oiSTyO
vMX/q5iE2iClYUIHZEKX3BjjNDxrYvLQzPyGD1EY2DZIO6T45FNKYC2VDwIDAQAB
AoGAbtWUKUkx37lLfRq7B5sqjZVKdpBZe4tL0jg6cX5Djd3Uhk1inR9UXVNw4/y4
QGfzYqOn8+Cq7QSoBysHOeXSiPztW2cL09ktPgSlfTQyN6ELNGuiUOYnaTWYZpp/
QbRcZ/eHBulVQLlk5M6RVs9BLI9X08RAl7EcwumiRfWas6kCQQDvqC0dxl2wIjwN
czILcoWLig2c2u71Nev9DrWjWHU8eHDuzCJWvOUAHIrkexddWEK2VHd+F13GBCOQ
ZCM4prBjAkEAz+ENahsEjBE4+7H1HdIaw0+goe/45d6A2ewO/lYH6dDZTAzTW9z9
kzV8uz+Mmo5163/JtvwYQcKF39DJGGtqZQJBAKa18XR16fQ9TFL64EQwTQ+tYBzN
+04eTWQCmH3haeQ/0Cd9XyHBUveJ42Be8/jeDcIx7dGLxZKajHbEAfBFnAsCQGq1
AnbJ4Z6opJCGu+UP2c8SC8m0bhZJDelPRC8IKE28eB6SotgP61ZqaVmQ+HLJ1/wH
/5pfc3AmEyRdfyx6zwUCQCAH4SLJv/kprRz1a1gx8FR5tj4NeHEFFNEgq1gmiwmH
2STT5qZWzQFz8NRe+/otNOHBR2Xk4e8IS+ehIJ3TvyE=
-----END RSA PRIVATE KEY-----

将私钥数据写入ssc.key,上传到wireshark的TLS流:

最终在tcp.stream eq 2019的TLS数据流中得到flag

所以到最后才发现,那个sqlmap.zip和Fl-g.zip好像并没有什么用。

[b01lers2020]image_adjustments

下载附件得到一张图片:

看到这张图片我就感觉特别熟悉,因为在杭电赛博杯的时候我写过和这个题目一样的脚本。就是把所有红线全放到上面或者下面,然后使得黑线跟着移动,最终得到flag。直接放exp:

from PIL import Image

def re_turn(pixels,num):
    return pixels[num:]+pixels[:num]
p = Image.open('attachment.png').convert('RGB')
a,b = p.size
pixels = []
for x in range(a):
    pixel = []
    for y in range(b):
        pixel.append(p.getpixel((x,y)))
    pixels.append(pixel)
data = []
for i in pixels:
    for j in range(len(i)):
        if i[j] != i[j-1] and i[j-1] == (255, 0, 0):
            data.append(j)
            break
_pixels = []
for i in range(len(data)):
    _pixels.append(re_turn(pixels[i],data[i]))
p1 = Image.new('RGB',(a,b))
for x in range(a):
    for y in range(b):
        p1.putpixel((x,y),_pixels[x][y])
p1.save('flag.png')

得到flag.png:

[b01lers2020]minecraft_purdue

一道mc的游戏题,第一次进游戏的时候啥也不明白,就随意乱转,发现这个地图特别大,有好多建筑,转着转着找不到起点了。然后就重置了一下世界,重新进入游戏真正开始做题。

刚进入游戏的时候会踩在一个透明方块上,这里能看到整个地图的全貌

周围的木牌上都写着一样的东西,看起来没啥用

为了方便跑图,先开启创造模式,/gamemode creative

正对着的门那边有一个木牌,上面说了flag在某个建筑内

这里我运气也是比较好,因为第一次进地图瞎跑我是从这个门出去的,然后真正开始做题的时候我就想往另一个门出去。

向后转,可以看到后面还有一个门

从门出去后能看到一个单独的建筑,往前门走都是各种建筑在一起的。而这个建筑是单独的,旁边再没有其他建筑。墙上的缺口是已经被我敲掉了,刚开始是没缺口的。

敲出一些缺口,看到里面的地上有一些木块

进去发现,这个实际上就是flag。

虽然题目比较简单,flag直接放在了某个建筑里,但是这个地图建的是真的好。

[HITCON2018]ev3basic

下载附件得到一张图片和一个流量包

这张图表明了这个流量包是lego EV3设备的,flag是hitcon开头的,而且看这位数应该特别多。

百度可知lego EV3支持USB、蓝牙连接等等。分析流量包发现很多HCL RFCOMM协议,显然就是蓝牙传输数据了。

按照长度排序,在32长度里发现了hit:

但是后面并不是c,所以肯定不是就单纯按照这个顺序的。

在长度为33 34的数据包里也有同样的数据,{}的数据也是在长度为33的包里。所以大概就是长度32 33 34的包里储存着信息交互数据。

一个一个数据包看过去,可以发现,只有红框圈着的三个数值在变,其他都没变。第三个就是flag字符

长度为33的就是在第一个红框前加了个81,其余都一样。

长度为34的也一样,只有三个红框数据会变,只是第一个红框前变成了82,第二个红框前变成了00 81

通过观察可知,第二个数据只有四种情况,28 36 44 52。而附件下载下来的乐高图上恰好有四行数据。所以三个数据块代表的应该分别是: 行,列,字符。

按照这种规律提取数据,得到:

     0a 14 1e 28 32 3c 46 50 5a 64 6e 78 82 8c 96 a0
28   h  i  t  c  o  n  {  m  1  n  d  5  t  0  r  m
36   _  c  o  m  m  u  n  i  c  a  t  i  o  n  _  a
44   n  d  _  f  i  r  m  w  a  r  e  _  d  e  v  e
52   l  o  p  e  r  _  k  i  t  }

洞拐洞拐洞洞拐

一道三解题,我提交flag后就变成四解了

这题实际操作其实并不会太难,写的脚本都是一些很简单的脚本。主要就是他的脑回路可能是以前没有见过的。

下载附件得到一张图片:

上面全是黑白像素点,看起来还挺规整的。我直接就说解法了,一列一列读取黑白像素点,黑色为1,白色为0。脚本如下:

from PIL import Image

MAX = 320
pic = Image.open('qwe.png').convert('L')
fp = open('1.txt','w')
flag = ''
for x in range (0,MAX):
	for y in range (0,MAX):
		if pic.getpixel((x,y))==255:
			flag += '0'
		if pic.getpixel((x,y))==0:
			flag += '1'
fp.write(flag)

得到一串01字符串后,很明显是二进制,binary解码:

57 41 56 45,很明显是WAV的头文件,hex解码一下:

然后保存为1.wav。听一下并没有声音,用audacity打开分析,发现波形很异常

分析可得,每秒的帧频为10帧,一共318秒,3180帧。且每一秒的十个帧都在同一高度上。猜测可能会在这方面隐藏信息

观察发现一共有8个高度,0点以下3个,0点以上4个,0点一个。

既然有八种数据,猜测可能是八进制。按照从低到高取0到8。

import wave
f = wave.open("1.wav","rb")
params=f.getparams()
nchannels, sampwidth, framerate, nframes = params[:4]
flag = ''
for i in range(1): #range()内写几就是第几秒的数据
	strData=f.readframes(10)
print(strData)
print(flag)

range()内写几就是取第几秒的数据,以上脚本输出第一秒的数据,得到:

b'\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0'

第二秒也是这个数据,按照从低到高,前两秒应该取数据 '11'

将range内数据改成3,取第三秒数据,得到:

b'\xff?\xff?\xff?\xff?\xff?\xff?\xff?\xff?\xff?\xff?'

第三秒因取数据'5'

按照以上方法得到8种数据对应值,写如下脚本即可得到八进制数:

import wave
f = wave.open("1.wav","rb")
params=f.getparams()
nchannels, sampwidth, framerate, nframes = params[:4]
flag = ''
for i in range(319):
	strData=f.readframes(10)
	if strData == b'\x01\xa0\x01\xa0\x01\xa0\x01\xa0\x01\xa0\x01\xa0\x01\xa0\x01\xa0\x01\xa0\x01\xa0':
		flag += '0'
	if strData == b'\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0':
		flag += '1'
	if strData == b'\x01\xe0\x01\xe0\x01\xe0\x01\xe0\x01\xe0\x01\xe0\x01\xe0\x01\xe0\x01\xe0\x01\xe0':
		flag += '2'
	if strData == b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00':
		flag += '3'
	if strData == b'\xff\x1f\xff\x1f\xff\x1f\xff\x1f\xff\x1f\xff\x1f\xff\x1f\xff\x1f\xff\x1f\xff\x1f':
		flag += '4'
	if strData == b'\xff?\xff?\xff?\xff?\xff?\xff?\xff?\xff?\xff?\xff?':
		flag += '5'
	if strData == b'\xff_\xff_\xff_\xff_\xff_\xff_\xff_\xff_\xff_\xff_':
		flag += '6'
	if strData == b'\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f':
		flag += '7'
print(strData)
print(flag)

得到:

11513212710710313206306310706406410710711612212411010506310410511513212310712106412412111513212111513106212710311612213210713212310410311710213111010212210711511513212511510612312711111513212310712612212412113106310410711113212711113210410211706512310411311511406212011213113012511512212410711513212410713111410212012

由于目前水平不够,不知道简便的写法,只能写出这样的if判断语句。而且这个脚本有点小问题,最后一个数据本应该是5,但是这里不显示,缺少了最后的数据,补上即可。

所以实际数据应为:

115132127107103132063063107064064107107116122124110105063104105115132123107121064124121115132121115131062127103116122132107132123104103117102131110102122107115115132125115106123127111115132123107126122124121131063104107111132127111132104102117065123104113115114062120112131130125115122124107115132124107131114102120125

每三个为一组,作为八进制数转化为十进制,然后进行asc解码,即可得到一串字符串:

a = '115132127107103132063063107064064107107116122124110105063104105115132123107121064124121115132121115131062127103116122132107132123104103117102131110102122107115115132125115106123127111115132123107126122124121131063104107111132127111132104102117065123104113115114062120112131130125115122124107115132124107131114102120125'
flag = ''
for i in range(0,len(a),3):
	b = a[i]+a[i+1]+a[i+2]
	c = int(b,8)
	flag += chr(c)
print(flag)
MZWGCZ33G44GGNRTHE3DEMZSGQ4TQMZQMY2WCNRZGZSDCOBYHBRGMMZUMFSWIMZSGVRTQY3DGIZWIZDBO5SDKML2PJYXUMRTGMZTGYLBPU

最终base32解码一下,即可得到flag:

得到音频文件后的脚本一把梭:

import wave
import base64
f = wave.open("1.wav","rb")
params=f.getparams()
nchannels, sampwidth, framerate, nframes = params[:4]
flag = ''
rflag = ''
for i in range(319):
	strData=f.readframes(10)
	if strData == b'\x01\xa0\x01\xa0\x01\xa0\x01\xa0\x01\xa0\x01\xa0\x01\xa0\x01\xa0\x01\xa0\x01\xa0':
		flag += '0'
	if strData == b'\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0':
		flag += '1'
	if strData == b'\x01\xe0\x01\xe0\x01\xe0\x01\xe0\x01\xe0\x01\xe0\x01\xe0\x01\xe0\x01\xe0\x01\xe0':
		flag += '2'
	if strData == b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00':
		flag += '3'
	if strData == b'\xff\x1f\xff\x1f\xff\x1f\xff\x1f\xff\x1f\xff\x1f\xff\x1f\xff\x1f\xff\x1f\xff\x1f':
		flag += '4'
	if strData == b'\xff?\xff?\xff?\xff?\xff?\xff?\xff?\xff?\xff?\xff?':
		flag += '5'
	if strData == b'\xff_\xff_\xff_\xff_\xff_\xff_\xff_\xff_\xff_\xff_':
		flag += '6'
	if strData == b'\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f':
		flag += '7'
flag += '5'
for i in range(0,len(flag),3):
	b = flag[i]+flag[i+1]+flag[i+2]
	c = int(b,8)
	rflag += chr(c)
rflag += '======'
flag = base64.b32decode(rflag)
print(flag)

[NPUCTF2020]回收站

附件3.5个G,好大。下载下来有三个文件。testisadmin.E01,testisadmin.E02,testisadmin.E03。

通过题目回收站可知应该要在回收站里找文件,那么下载下来的附件应该就是硬盘文件了。通过百度可知,用 AccessData FTK Imager 打开。百度一下可以直接下载。

选择image Mounting,

此图像的alt属性为空;文件名为image-148.png

然后装载刚刚下载下来的testisadmin.E01文件。

此图像的alt属性为空;文件名为image-147.png

装载成功后打开硬盘,在回收站里发现了flag文件:

此图像的alt属性为空;文件名为image-149-1024x531.png

每个文件夹里都有一张图片,将他们全部取出来

此图像的alt属性为空;文件名为image-150-1024x306.png

最终拼一下即可获得flag:(这题居然是直接按照命名顺序拼就可以了,好久没见到这么仁慈的拼图了)

此图像的alt属性为空;文件名为image-151-1024x228.png

但是真正开始拼才发现,提交十几次都提交错误,把我整破防了。好吧,好久没见到这么令人绝望的拼图了。

大概尝试了30次左右,我才反应过来,为什么会是21位字符的flag,一般这种比赛都是32位MD5flag,所以应该是哪里出了问题。

然后就尝试了一下进入磁盘搜索flag文件

此图像的alt属性为空;文件名为image-152-1024x491.png

果然搜到了一个flag.png,38字节的文件,用记事本打开最终得到flag:

此图像的alt属性为空;文件名为image-153.png

之后看了下官方wp,发现是在虚拟机里进行的磁盘取证,那样能在桌面上看到一张hint图片。我是直接在物理机里操作的,所以只能看到硬盘,但是没想到最后直接搜索flag就搜到了,如果改个名字我这样做就没办法了。

官方wp:https://shimo.im/docs/6hyIjGkLoRc43JRs

[V&N2020 公开赛]Final Game

附件很大,4.1个G,解压后有一个10G左右的vmdk文件和一个加密的压缩包。

先看加密的压缩包文件,有注释,但是是一串不明所以的字符串:

Stupid mortal, you must enter the eighth circle of Hell to get the Tip of god。'=B;:?8\<;:921Uv.3,1*No'&J*)iF~%$#zy?w|{zsr8pun4rTji/PONMLKJIHGFEDCBA@?>=<;:
987SRQ3IHMFKDCBf)('&%$#"!~}|{zyxwvutsrqpon,+*)i'&%${zy?}|{t:xwp6Wsrkj0QPONML
KJIHGFEDCBA@VUTYXWVUTSRKoON0LKDCgfS

压缩包内的文件名有点特殊,好像是一个单词

google一下,发现了是一种密码

https://en.wikipedia.org/wiki/Malbolge

这些加密的例子和压缩包的注释也有点像,应该就是了。

在线解密网站:

http://malbolge.doleczek.pl/#

解密得:

所以压缩包的password为 %&^&#@()(*:";'/,,

解开压缩包,txt文件内写着:

神说:要有ELF!!!
神说:要有WORD!!!
神说:要有NTFS!!!
神说:要有PDF!!!
神说:要有OSZ!!!

地狱 -- 炼狱 -- 天堂

这应该算是这题的hint吧,估计要按照这个顺序解题之类的。

将vmdk装载后可以发现是一个完整的windows系统目录,可以直接装载在物理机的虚拟硬盘上,也可以利用vmware来装载进入系统。

我这里是直接在物理机上装载vmdk文件,进入硬盘,

在用户 lenovo,桌面目录上发现一张图片

在音乐目录里有个加密的压缩包paradise.zip,百度可知这个单词的意思是天堂,正好和图片上的地狱相反。在下载目录里有一个proverbs.pdf,文档目录下有一个加密的Purgatory.zip,百度可知这个单词的意思是炼狱。然后在其他文件夹下还有很多东西,不过没什么作用,但是无聊的时候看看也挺有趣的。

比如文档目录下就有很多资料

在公用图片目录下还能发现很多图片,当然跟解题没什么关系

回归正题,png图片尝试各种图片隐写均无效,想起了之前拿到的hint,其中对png图片有用的应该就只有这一句 神说:要有NTFS!!!

于是尝试一下查看NTFS数据流,发现有一个Purgatory.exe,这个单词的意思是炼狱,正好与图片上的文字吻合。

运行exe文件,得到:

请将该文件放入炼狱中执行(能进入天堂的是Mr.png,Mrs.jpg只能下地狱)

在\Program Files (x86)\Linux目录下发现了一个炼狱文件,用winhex打开查看一下可知是ELF文件

根据exe文件的描述,将exe文件和elf文件放在同一目录下再次运行exe文件,得到:

智慧之神evoA说,你需要修复ELF

运行完之后还会把原来的ELF文件删除掉,还好我有备份。

接下来就是修复ELF文件了,下面是ELF文件的资料

https://blog.csdn.net/qq_37431937/article/details/90369099

用readelf查看一下elf文件,头文件报错:

readelf:错误:不是 ELF 文件 - 它开头的 magic 字节错误

ELF文件的头文件应该是 7f 45 4c 46,但是这里是 20 45 4c 46,将20改为7f后再次readelf。可以读取了,发现它的类型是NONE,这里肯定有问题

00,即为NONE类型

01,为REL类型,即可重定位文件

02,为EXEC类型,即可执行文件

03,为DYN类型,即共享目标文件

猜测这是可执行文件,用010editor打开,将这里的ET_NONE改为ET_EXEC,保存。

再次放入kali里执行,发现可以执行了,而且后面还可以带一些字符串,随便输入后可以得到:

Wise man, Can you help me solve this problem: 30e308e8e7122579b8ea2fae774d1999 ?

易知这是一串32位的MD5码,解码可得evoA,但是我这里利用evoA来执行的时候发现还是给了fake flag,按照wp来说这样应该是没问题的。如果输入了evoa其中任意一个字母的大小写,也会生成一个fake flag。

理论上应该会输出 pdfkG@0zl_3ptmVPfa7LHuB8rs#cRdi$,我这里就直接先暂时跳过了。

这串字符串以pdf开头,大概率就是pdf文件的密码了,解密pdf文件,

字母全是键盘上相邻的键位,可知是键盘密码,每个空格分隔一个字母,每个表情分隔一个单词,解得:

The password of word is capital(PROVERBS OF GOD)

所以Purgatory.zip的压缩包password为: PROVERBS OF GOD

解压后得到一个docm文件,百度可知 docm文件是一种包含宏或启用了宏的文档,alt+F8可以查看宏

宏名为LargeSB,看起来可能跟LSB有点关系,点击运行后,得到很多base64字符串,可知是base64隐写

base64隐写解得:Hidden1nWord_

word文档内容是大量的十六进制,开头是FF D8 FF,jpg的头文件,结尾是AE 42 60 82,又是png的尾文件了。根据数据块内容可知是png图片,将开头的FF D8 FF E0改为89 50 4E 47,导入winhex中。

得到一张图片,通过word文档里的提示,有密钥,而且跟LSB有关,可知大概率是利用lsb脚本解密。

python2 lsb.py extract 4.png out.txt Hidden1nWord_

解得:

The password of paradise:Bliss_Syc!!!!

可知paradise.zip的password为 Bliss_Syc!!!!

得到一个osz文件,百度可知osz是一个游戏文件

但是是利用zip压缩的数据文件,所以可以也可以利用zip打开

发现一个readme.jpg,打开在最后发现flag的hint信息:

in,map.flag,is :0036112S0038362y0042112c0055162{0110912 0118712 0135512 0142112 0158163 0200412 0203862 0216312 0219762 0225312 0231312 0251862 0302512 0312112 0318412 0329628 0342412 0352837 0358537 0409337 0420137 0443462 0447137 0450062 0457862 0514737 0514737 0515862 0516537 0525312 0526062 0530187 0548562}Traversing.Time

在网上下载一个osu!,用编辑模式打开osz文件,可以调时间。

将时间调为0036112,可以看到一个S字母

将时间调成0038362,则能看到y字母

有些字符如下图所示,只显示了一个圈里面一个数字,这是就直接取里面的数字即可

将所有时间的字符全部提取出来,即可得到flag:

Syc{469ca48e237f59d6f847c623ceef5777}

这个flag的md5解密恰好就是 Welcome to paradise

这道题目覆盖了很多很多知识点,而且都是一些平时很有可能注意不到的知识点,从头到尾做一遍感觉学到了很多,尤其是ELF文件结构,感觉收获了很多。

发表评论