对各种类型的压缩包进行解压,也是CTF比赛的一个特点。无论什么类型的题目,都可能会遇到压缩包,这就要求选手对于压缩包的格式应烂熟于心。本节重点以ZIP压缩包为例,详细阐述压缩文件的格式及其破解方法,希望读者们熟练掌握,遇到其他压缩文件时也能够举一反三。
一个ZIP压缩文件由如下三部分组成:压缩源文件数据区、压缩源文件目录区和压缩源文件目录结束标志。具体而言,一个ZIP文件可以按如下方式分解:
[本地文件头+文件数据+数据描述符]{1,n}+目录区+目录结束标识
[本地文件头+文件数据+数据描述符]构成压缩源文件数据区,{1,n}表示这部分数据最少出现1次,也可以出现n次,n的数量和压缩前的文件数量一致。目录区(也称为核心目录)会保存压缩前文件和文件夹的目录信息,这部分数据一般均为明文显示。目录结束标识存在于整个压缩包的结尾,用于标记压缩的目录数据的结束。
1.压缩源文件数据区
这一部分记录压缩的所有文件的内容信息,每个压缩文件都由三部分组成,包括本地文件头、文件数据(已压缩)和数据描述符。该数据区中每一个压缩的源文件/目录都是一条记录(record)。本地文件头的格式如表1.5.1所示。
通用比特标志位占16比特,其中第0比特,即最低比特(也就是所占2字节的最右比特),代表文件是否被加密。也就是说,如果这2字节所代表的数是奇数就说明文件被加密。当通用比特标志位的第3比特为1时,数据描述符才会在ZIP文件中出现,数据描述符紧接在文件数据后。数据描述符只有在不能对输出的ZIP文件进行检索时才会被使用,例如在一个不能检索的驱动器(如磁带机)上的ZIP文件就会包含数据描述符;如果是保存在磁盘上的ZIP文件,则一般没有数据描述符。
表1.5.1 本地文件头的格式
2.压缩源文件目录区
这个区域也称为核心目录,记录了压缩前所有文件和文件夹的目录结构信息。在这个数据区中,每一条记录对应着压缩源文件数据区中的一条数据。其格式如表1.5.2所示。
表1.5.2 目录区格式
3.压缩源文件目录结束标识
目录结束标识位于整个压缩包的结尾,用于标记压缩的目录数据结束。每个压缩文件有且只有一个目录结束标识。其格式如表1.5.3所示。
表1.5.3 目录结束标识格式
使用WinHex工具,可以以十六进制的方式查看ZIP压缩包,但是WinHex并没有文件解析功能,需要我们根据上述文件格式手动解析,这么做显然不够“优雅”。那么,有没有工具可以对其自动解析呢?这里我们强烈推荐010 Editor这款工具,建议初学者们安装8.0及以上版本。
将ZIP压缩包拖入010 Editor,如图1.5.1所示。当单击“Hex”按钮时,文件以十六进制方式显示,否则以ASCII码显示。
图1.5.1 010 Editor查看压缩包
“Templates”工具栏是010 Editor中最为重要的部分,通过安装模板,就可以按照相应格式解析文件。这里我们展示如何安装模板。需要提醒大家注意的是:安装过程中需要联网。单击“Templates”工具栏,选择最下面一行“Template Repository”,如图1.5.2所示。.bt文件就是各种文件格式的解析模板,选择ZIP.bt,单击右侧的“install”按钮即可完成安装,安装时还可以在下方选择不同的版本。建议CTF参赛选手们提前安装好各种常见格式的模板,这样即使比赛没有外网,也可以解析文件。
图1.5.2 打开“Template Repository”模板仓库
安装好各个模板之后,单击“Templates”工具栏,如图1.5.3所示,即可手动选择模板来解析已经打开的文件,这里我们选择ZIP模板。选择之后,观察010 Editor窗口左下角,如果看到“Template executed successfully”,说明模板解析完成。但是,我们并没有看到解析结果,因此需要再调整下窗口,在010 Editor窗口的右下角选中图1.5.4的方框部分,将其向上拖拽,即可看到模板的解析结果,如图1.5.5所示。
图1.5.3 选择解析模板
图1.5.4 查看模板解析结果的关键操作
图1.5.5 ZIP模板解析结果
ZIP模板解析的结果和ZIP文件格式完全相同。在abcd文件夹下有两个文件,分别是BR.st和vps.txt。在ZIP模板的解析结果中,“record”就是压缩源文件数据区,“dirEntry”代表压缩源数据目录区,最后的“endLocator”是压缩源数据目录结束标识。单击“record[0]”最左侧的小三角,将第1个record的解析结果展开,如图1.5.6所示,可以看到每个字段的名称和值的详细说明,将BR.st对应的目录区展开,如图1.5.7所示。
图1.5.6 第1个record的解析结果
图1.5.7 第1个record对应的目录区
伪加密是一个总在不经意间出现的CTF考点,在ZIP和RAR文件格式相关题目中都会涉及。我们先介绍ZIP文件伪加密的原理。
在图1.5.6和图1.5.7中,“frFlags”和“deFlags”字段就是通用比特标志位(全局方式位标记),它们的最低比特(也就是所占2字节的最右比特)代表文件是否被加密。在图1.5.6和图1.5.7中,同一个文件(abcd/BR.st)在record中的“frFlags”和dirEntry中的“deFlags”的值是完全一样的。当文件压缩没有设置密码时,这两个字段均为相同的偶数,否则均为相同的奇数。
伪加密的原理是:ZIP压缩包生成时没有加密,手工修改“frFlags”或“deFlags”的值,使得同一个文件的这两个字段中 至少一个为奇数 ,这样在解压时会弹出密码输入框,无论输入什么密码都会报错。这种原压缩包没有加密,但通过人工修改造成解压时需要输入密码的现象,就叫作伪加密。
下面我们和大家一起练习一个ZIP伪加密的例子。对于任意txt文件,将其命名为vps.txt,压缩vps.txt文件,使用010 Editor解析的结果如图1.5.8所示,压缩时没有选择加密,“frFlags”和“deFlags”的值均为0。双击“frFlags”对应的值,修改为1后再按回车键,将文件保存后修改才能生效,如图1.5.9所示。
图1.5.8 未加密ZIP文件解析结果
图1.5.9 手工修改frFlags字段
不同的工具对于ZIP伪加密文件会有不同的解压效果,我们使用WinRAR、360压缩和binwalk对多种伪加密文件进行解压,其效果如表1.5.4所示。
表1.5.4 不同工具对ZIP伪加密文件的解压效果
破解ZIP伪加密的方法十分简单。如果“frFlags”和“deFlags”的值不相同,例如,“frFlags”的值是奇数,“deFlags”的值是偶数,那么可以把“frFlags”的值改为“deFlags”的值,然后解压查看结果。那么问题来了,我们能把“deFlags”的值改为“frFlags”的值吗?答案肯定是不可以,这是因为奇数表示加密,偶数表示未加密,所以为了去除伪加密效果,只能把奇数向偶数修改。
即使“frFlags”和“deFlags”都是同一个奇数,我们仍然怀疑该ZIP文件存在伪加密,那么可以把这两个字段的值都 减1 ,改为相同的偶数,然后进行解压查看其结果。如果解压后的结果是有意义的明文或者是可以识别的文件,则说明原ZIP文件压缩时并未加密,只是进行了伪加密;如果解压后的文件无法识别,也没有任何意义,则说明原ZIP文件很可能并不是伪加密,此时我们必须另辟蹊径,利用其他方法去寻找压缩包的解压密码。
RAR文件的伪加密
接下来,我们简单介绍一下RAR中的伪加密原理和破解方法。RAR格式有多个版本,目前较为常见的是RAR4和RAR5,利用WinRAR压缩时可以选择不同版本。RAR4的文件头为 52 61 72 21 1A 07 00 ,RAR5的文件头为5 2 61 72 21 1A 07 01 00, 读者们一定要注意其差别。RAR4伪加密需要利用RAR4格式中的相关字段。图1.5.10中展示了010 Editor对RAR4文件的解析结果,在block[0]的HEAD_FLAGS字段中,字段PASSWord_ENCRYPTED占1比特,表示文件是否被加密,将这个比特改为1,保存文件,就能实现对RAR文件的伪加密。
图1.5.10 010 Editor对RAR4文件的解析结果
如果一个RAR文件使用RAR4压缩,且人为修改过PASSWord_ENCRYPTED字段,那么用解压工具解压时,会报出“文件头损坏”的错误。这时候判断可能是RAR伪加密,需要我们手工将PASSWord_ENCRYPTED字段改为0,再尝试解压。如果此时能正常解压,就说明原文件确实存在伪加密,否则需要根据RAR的文件格式做进一步处理。
利用题目中的提示或者字典爆破压缩包密码,也是CTF比赛中经常出现的考点。针对ZIP压缩包的密码爆破主要是使用工具ARCHPR完成的。这个工具的功能非常强大,打开后的界面如图1.5.11所示。
图1.5.11 ARCHPR的界面
1.暴力破解
通过枚举的方式尝试所有可能的密码,理论上一定可以找到正确的密码,但这种暴力破解方法在实践中会极大地受到设备的限制。对于普通的笔记本电脑而言,当密码长度小于等于8字节时,可以考虑使用暴力破解。如图1.5.11所示,在ARCHPR中使用暴力破解的方法为:“攻击类型”选择暴力;在“范围”选项卡的“暴力范围选项”中选择密码中可能出现的字符,注意“范围”选项卡的右侧有“开始于”“结束于”等输入框,这些也可用于辅助限制爆破范围,如果没有特别要求,在爆破前一定把“开始于”“结束于”清空;切换到“长度”选项卡,根据需要设置爆破字节数,一般不超过8字节;最后单击左上角“打开”,选择要爆破密码的ZIP文件,单击“开始”就可以开始爆破。
对于几乎所有ZIP格式的压缩包,我们都可以尝试通过ARCHPR破解密码,RAR4也可以通过ARCHPR破解压缩密码。但是对于RAR5,则需要通过其他工具才可以破解密码。
【例题】银行卡里的秘密.pcapng
【题目来源】 世安杯CTF。
【题目描述】 找到flag。
【解题思路】 从流量中提取出一个ZIP压缩包,直接解压时发现需要密码。将其放到010 Editor中解析,经过尝试,发现该ZIP压缩包不存在伪加密的情况。结合题目名称中的“银行卡”,猜测密码可能是6位纯数字。于是,在ARCHPR中使用暴力破解方式破解密码,爆破范围只选择数字,将最小和最大长度都设置为6,爆破结果如图1.5.12所示。单击方框中的按钮可以复制解压密码,解压后就能看到flag。
图1.5.12 ARCHPR爆破结果
图1.5.13 指定字符集密码破解
除了使用“暴力选项范围”,还可以通过指定字符集进行密码破解。如图1.5.13所示,攻击方式选择“暴力”,“范围”中选择右下角的“用户定义”,再单击方框选中的按钮,如图1.5.14所示,字符集中输入的字母需要注意大小写。
图1.5.14 输入字符集
【例题】你需要一个字典.zip
【题目描述】 找到压缩包中的flag。
【题目描述】 我只记得密码是由abcdefg中不重复的6个字母随机排列组成的,但其中是不是有某些字母转为了大写,我已经记不得了。一切都靠你自己了。密码举例:cAeGfb。
【解题思路】 根据描述,我们可以选择生成字典,也可以使用ARCHPR的自定义字符集,如图1.5.15所示,长度设置为6字节,破解结果如图1.5.16所示,利用密码解压就能得到flag。
2.掩码攻击
图1.5.15 输入自定义字符集
如果我们知道密码中的一部分,只需按规则构造其余部分,这个时候就可以利用掩码方式破解密码。假设已知8位密码的前4字节是abcd,那么可以构造abcd????进行掩码攻击,其中“?”是占位符,表示该位置所代表的字节内容未知。掩码攻击的原理相当于构造了前4字节为abcd的字典,因此掩码攻击的效率会比暴力破解高出很多。利用掩码攻击时,“长度”选项卡暂时失效,需要我们自己确定破解的长度。
图1.5.16 破解结果
【例题】zippy.zip
【题目描述】 手机号还记得吗?139????????
【题目来源】 原创。
【解题思路】 根据题目描述,压缩包密码是一个手机号,但是只知道前3位,所以考虑用掩码攻击的方式爆破密码。如图1.5.17所示,解压后有两个文件,flag.txt中是假flag,f l4g.zip解压需要密码,拖入010 Editor中可以直接看到flag。f l4g.zip真正的考点是伪加密,“frFlags”和“deFlags”都改为0就能正常解压,但是由于出题人失误,可以在010 Editor中直接看到flag。
图1.5.17 掩码的爆破结果
3.字典攻击
如果密码是弱口令或者已经知道使用者的某些习惯,就可以把这些内容生成字典,再利用字典破解密码。字典攻击的效率更高,但是依赖于字典的质量,这就需要我们平时多积累一些弱口令。ARCHPR的字典攻击界面如图1.5.18所示。
图1.5.18 字典爆破
循环冗余校验(Cyclic Redundancy Check, CRC)是一种对给定的数据计算校验码的编码技术,主要用来检测或校验数据传输后可能出现的错误。大多数情况下,会把生成的计算结果附加到要传输的数据后面,由接收方进行校验,确定接收到的数据是否发生变化。一般来说,循环冗余校验的值都是32比特的整数。
ZIP文件的CRC值是压缩前原文件的CRC值,当原文件很大时,我们很难根据CRC校验值反推原始数据的内容;但是如果原文件很小(只占几个字节),就可以根据CRC值爆破原文件内容。其原理就是枚举原文件内容,计算CRC值,如果CRC值和目标CRC值一致,那么枚举的值就可能是原文件内容。这种方法一般会找到多个可能的结果,此时就需要我们再进行手工筛选。
在CTF比赛中,需要利用CRC碰撞技术破解的ZIP文件如图1.5.19所示,利用7z工具(强烈建议安装的解压工具,官网地址为https://www.7-zip.org/)或者WinRAR打开压缩包,就可以看到每个文件的原始大小以及CRC值。不难发现,有6个小文件(1.txt~6.txt),每个文件只有6字节。利用CRC值可以把每个小文件的原始内容爆破出来,但是,flag.txt原文件有31字节,利用CRC值无法反推出这个文件的原始内容。得到每个小文件(1.txt~6.txt)的内容后,把它们拼接起来就是这个压缩包正确的解压密码。
图1.5.19 具有CRC碰撞特征的ZIP压缩文件
利用CRC碰撞爆破ZIP压缩包解压密码的一个最大特点是压缩包中有许多小文件(4~6字节)。我们可以利用工具https://github.com/theonlypwner/crc32,快速得到原始数据内容。
【例题】3.zip
【题目来源】 原创。
【题目描述】 找到压缩包中的flag。
【解题思路】 利用WinRAR查看文件,解压密码未知,发现3个小文件,如图1.5.20所示,考虑进行CRC碰撞爆破。利用工具https://github.com/theonlypwner/crc32只能得到4字节和6字节的结果,但在本题中pass1.txt是5字节,因此我们修改了工具源码,使其可以 根据CRC值爆破1~6字节的明文 。工具使用方法如图1.5.21所示。使用中需要注意的是,要加“reverse”选项,WinRAR中的CRC值是十六进制,所以在命令中前面有“0x”。由于pass1.txt原文件大小是5字节,所以只有一种可能——“6u9ku”。采用同样的方法可以得到pass2.txt和pass3.txt的明文,最后的解压密码是6u9ku-_-#h0rs3。
图1.5.20 查看ZIP文件信息
图1.5.21 CRC碰撞爆破结果
【例题】108.zip
【题目来源】 2018央企大赛。
【题目描述】 找到压缩包中的flag。
【解题思路】 很明显,此题可进行CRC碰撞爆破。利用工具,最后拼接得到的明文是passwordisClassicalencryptionishint6,解压密码为Classicalencryptionishint6。
已知明文攻击是一种较为高效的攻击方法,它的特点是已知一个ZIP压缩包中某个文件的原文件(也就是明文),利用已知文件和其压缩加密后的数据获取到压缩包的解压密码或者能对其解压。
在CTF比赛中,常见的套路是给出一个×××.txt和一个flag.zip。查看flag.zip,发现里面有×××.txt和flag.txt,这就是非常明显地暗示我们考点就是ZIP已知明文攻击,这种考法称为常规已知明文攻击。高级一点的考法是利用部分明文(需要至少12字节且包含8个连续字节)进行密码破解。
常规已知明文攻击要想成功,需要具备3个条件:
1)完整的明文文件。
2)明文文件需要被相同的压缩算法标准压缩(也可理解为被相同压缩工具压缩)。
3)明文对应文件的加密算法是ZipCrypto Store。
针对第3个条件,我们来介绍一下已知明文攻击的原理。ZIP的加密算法大致分为两种:ZipCrypto和AES256,各自又分为Deflate和Store。ZipCrypto是传统的ZIP加密方式。只有使用ZipCrypto Deflate/Store方法加密的压缩包,才可以使用ZIP已知明文攻击进行破解,而AES256-Deflate/AES256-Store加密的文件不适用于明文攻击。
ZipCrypto本质上是异或加密,但并不是使用压缩时设置的压缩密码作为异或的密钥,而是在初始化阶段利用我们设置的压缩密码通过扩展算法扩展成3个密钥(每个密钥占4字节,共12字节),再利用这3个密钥生成伪随机数流。加密时,每加密一个字节,都会用这个字节作为输入更新密钥,以产生下一个伪随机数,然后用生成的伪随机数和下一个字节异或。解密时,每解密一个字节,都用解密后的字节作为输入更新密钥,以产生下一个伪随机数,然后用生成的伪随机数和下一个字节异或。感兴趣的读者可以查看ZipCrypto的源码(https://github.com/KLab/DotNetZip/blob/master/Zip/ZipCrypto.cs)。
如果读者不太理解上述过程,那么只需要记住,即使在没有压缩密码的情况下,只要能获取3个密钥,就能实现解密。如果我们已知压缩包中的某个文件,就可以利用算法获取这3个密钥。
在CTF比赛中,我们通常利用工具完成上述步骤。在Windows下,可以使用ARCHPR;在Linux系统下,可以使用pkcrack(https://github.com/keyunluo/pkcrack),或者bkcrack(https://github.com/kimci86/bkcrack)。下面我们以ARCHPR为例进行讲解。
【例题】ex.zip
【题目描述】 找到压缩包中的flag。
【解题思路】 解压ex.zip需要密码,放入010 Editor查看,发现并不是伪加密。此时可考虑使用爆破,发现密码是123456。解压后得到两个文件Tetris.java和Tetris.zip,再通过解压工具查看Tetris.zip,其中有文件Tetris.java和flag.zip。而Tetris.zip解压又需要密码,很明显,我们需要对其使用已知明文攻击。
我们使用360压缩对Tetris.java生成ZIP压缩文件,生成时选择默认选项,不要设置密码,如图1.5.22所示。这一步非常重要,对应攻击成功的第2个条件。很多题目需要我们尝试使用多个工具(建议可以尝试WinRAR、360压缩、7z、好压等)生成ZIP压缩包,本题中使用360压缩生成的压缩包即可完成已知明文攻击。
图1.5.22 对明文文件进行无密码压缩
ARCHPR的选项如图1.5.23所示。我们把需要破解密码的压缩包改为Tetris-o.zip,360压缩生成的压缩包命名为Tetris.zip,注意加密文件和明文文件的区别。单击“开始”按钮后,破解开始。使用ARCHPR进行已知明文攻击时有一个重大BUG,即使工具已经恢复出3个密钥,程序也不会自动停止,需要我们手动暂停。根据比赛经验,一般程序运行20~30分钟就可以手动停止,如果ARCHPR找到了3个密钥,也就是图1.5.23中的加密密钥,那么单击“停止”后会自动弹出窗口,如图1.5.24所示。单击“确定”后,会弹出新的保存文件窗口,如图1.5.25所示,文件名由ARCHPR自动命名。或者,在ARCHPR找到了3个密钥后,单击图1.5.23中方框内的按钮,也会有相同的效果。
图1.5.23 ARCHPR的已知明文攻击
图1.5.24 爆破成功
图1.5.25 破解后的ZIP文件需要另存
新生成的Tetris-o_decrypted.zip可以直接解压,得到flag.zip文件。由于该文件存在伪加密,因此把“frFlags”的值改为“deFlags”的值,就能正常解压。解压后的字符串经过Base62解码,就能获得flag{ca7b3196-c213-45e2-8adf-677f91521caa}。