压缩包作为misc中比较基础的一个考点,经常出现在各种比赛的misc方向中,如果没有一定的了解看到一层一层的压缩包难免会头痛。那么这里来简单的总结一下ctf中关于压缩包的一些考点。
CTF 压缩包总结 - Chi4ki - 博客园 (cnblogs.com)
工具准备
Wenhex或相似的16进制编辑器,ARCHPR(4.53或4.54最好),python环境和zipfile库。
暴力破解
通常这类题目会有密码几位数或有哪些符号的提示,只要给的不是很复杂的提示(比如密码是32位),就可以确定是暴力破解,用ARCHPR勾选对应的选项破解就可以了。
掩码爆破
其实和暴力破解相同,只是由于密码可能在一个范围内或者有一些字符确定,如我们已知密码开头是Ctf,后面是6位数字,那么掩码设置中写为Ctf??????,然后爆破即可。
字典爆破
对应的是弱口令密码的爆破,ARCHPR需要自己提供字典文件,然后就会将字典中的所有密码尝试爆破。有的题目会直接给字典文件,还有的则是需要自己去网上查找,需要注意有的弱口令密码相对并不简单(如123123@@@),要找一个比较全的字典。
伪加密
zip文件中,文件头和文件核心目录区50 4B 01 02(目录中文件文件头标记)、1E 03(压缩使用的pkware版本)、14 00(解压文件所需pkware版本)后即是压缩软件识别未加密标志,奇数代表加密,偶数代表无加密。将00 00改为09 00后再次打开压缩包,就会显示需要密码,然而事实上压缩包并未设置密码,所以这样的手段就被称为zip伪加密。而在这种时候只需要用16进制编辑器如wenhex打开压缩包,搜索504B0102,将其后的09 00改为00 00,便可解压压缩包。
注意的是由于有的zip压缩包中有多个文件,需要对所有显示加密的文件进行修改。
CRC32爆破
循环冗余校验(CRC)是一种产生简短固定位数校验码的信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。CRC32 即是会产生一个32 bit的校验值,由于 CRC32 产生校验值时源数据块的每一个bit都参与了计算,所以数据块中即使只有一位发生了变化,也会得到不同的 CRC32 值。而这也就导致了基于 CRC32 的攻击手法。
例题:buuctf zip
用如下脚本爆破(摘自网上的脚本并做了一些修改,类似的题目调整一下都可以使用)
import zipfile import string import binascii def CrackCrc(crc): for i in dic: for j in dic: for k in dic: for h in dic: s = i + j + k + h if crc == (binascii.crc32(s.encode())): f.write(s) return def CrackZip(): for i in range(0,68): file = 'out'+str(i)+'.zip' crc = zipfile.ZipFile(file,'r').getinfo('data.txt').CRC CrackCrc(crc) print('\r'+"loading:{:%}".format(float((i+1)/68)),end='') dic = string.ascii_letters + string.digits + '+/=' f = open('out.txt','w') CrackZip() f.close()
明文攻击
在传统的zip加密中,文件会根据口令生成3个密钥来加密文件,所以假如获得与压缩包中相同的文件(判断方式是CRC32是否相同),则可以将获得的文件进行未加密压缩,通过一定的手段将加密与未加密文件进行对比从而求出3个加密密钥,虽然并不一定能解出口令,但也足够可以获得其中的文件。
比赛中除了直接给相同的文件外,还有可能是要求自己查找构造明文,对应的难度会高上很多,比如设置的明文是github上的一个文件。
同时由于不同压缩软件之间压缩方式的不同,构造明文的压缩方式如果不相同则可能无法解出,这种时候我们需要将常见的几种压缩方式都进行尝试。
还要补充的一点是,ARCHPR的版本也会有影响。对于同样的一道题目,用4.00版本没有解出来,用4.53很快出现结果,而4.54则会显示要很长时间,但十几秒后手动暂停就会显示解出。
python脚本类题目
在许多比赛中会有几百层压缩包的题目,有的是名字就是密码或者没有密码但文件非常大,还有的则是额外需要爆破。形式上有的是压缩包套压缩包,有的则是一次性好多个压缩包,对于这类题目,我们往往需要利用python的zipfile库来写脚本爆破。
例题:[MRCTF2020]千层套路
一个套娃的压缩包,每一个压缩包的名字就是它的密码,写如下脚本解出:
import zipfile zip_src='0573.zip' while(1): r = zipfile.is_zipfile(zip_src) if r: fz = zipfile.ZipFile(zip_src,"r") fz.extractall(pwd=bytes(zip_src[0:4],'utf-8')) zip_src=fz.filelist[0].filename else: break
打开后是三个一组的数字,看到255和0猜到是颜色且对应二维码。用python的PTL库写脚本得到是一个二维码,再用软件QR Research扫码,得到flag。