CTF-压缩包篇

优秀的人,不是不合群,而是他们合群的人里面没有你

压缩包

docx本质就是压缩包,这两个可以直接修改后缀尝试一下

直接丢winhex看看

用 winhex 打开,搜索字符 pass 、 key 等,查看是否有含有压缩包密码

使用winrar避免异常

注意,有些猥琐逼喜欢把zip文件改后缀成rar,让人瞎折腾,一定要先看看文件头对应

格式    zip                 rar               7z

文件头(16进制)    504B0304         52617221         377ABCAF271C

文件头(ascii)    PK           Rar!         7z¼¯’

查看属性

右键查看属性获取信息

文件头修复

文件头使用winrar自动修复,或者使用010和winhex添加修改文件头。

如果是rar,则需要注意rar的固定格式。RAR文件下一文件固定块是:

A8 3C 7*

在RAR文件格式中,HEAD_TYPE的值是0x74则表明接下来的是文件块,

修复就是将这个改成74

伪加密

管他是不是,直接使用随波逐流工具自动修复,如果不行,就讲一下伪加密解题方法

无加密

压缩源文件数据区的全局加密应当为14 00 00 00(504B0304两个bytes之后)

且压缩源文件目录区的全局方式位标记应当为14 00 00 00(504B0304四个bytes之后)

假加密

压缩源文件数据区的全局加密应当为14 00 00 00

且压缩源文件目录区的全局方式位标记应当为14 00 09 00

真加密

压缩源文件数据区的全局加密应当为14 00 09 00

且压缩源文件目录区的全局方式位标记应当为14 00 09 00

发现伪加密,修改代码。或者用工具

  1. java -jar ZipCenOp.jar r download.zip
  2. binwalk -e 命令可以无视伪加密,从压缩包中提取文件
  3. 修改通用标志位,winrar修复

RAR的伪加密与ZIP的伪加密原理相同,号称伪加密的关键都是一个指定的位标记字段上。

PS:一般RAR伪加密的压缩包用WinRAR打开时都会显示文件头已损坏

在RAR的第24个字节,也就是010 Editor显示的文件结构中的ubyte PASSWORD_ENCRYPTED字段,修改其字段为1即可实现RAR伪加密。

或者修改第11个字节,也就是010 Editor显示的文件结构中的ubyte BLOCK_HEADERS_ENCRYPTED字段的值。修改为1即可造成RAR伪加密。

同理解法就是将其对应位置的值修改为0即可实现伪加密rar破解出来。不过一般rar在CTF中出现较少,重点还是zip的压缩包上面做文章。

暴力破解

直接使用AZPR破解,适用于密码长度小于等于6位数,如果爆破不成功可以根据题意或者社工 猜密码组合。例如某用户名叫王方,密码就有可能是 wangfang123

重点讲讲ARCHPR.exe这个玩意的使用~

这个工具可以暴力爆破,掩码爆破,以及字典爆破为主~

暴力破解就这么玩:

  1. 选择攻击类型-暴力
  2. 尝试选择范围内所有的字符组合-可以选择数字字母
  3. 选择长度-点击长度设置最短和最长的长度
  4. 开始爆破~

掩码爆破需要已知道密码某个位置的字符,比如你知道密码一共6位,并且都是数字,而且知道第一位和第五第六位,可以这么玩:

  1. 选择攻击类型-掩码
  2. 在掩码位置输入:2???67
  3. 范围选择所有的数字
  4. 开始爆破

掩码默认为:?

例如:掩码为:www.?????.com 范围选小写a-z

www.aaaaa.com 跑到www.zzzzz.com

字典爆破更加简单:

  1. 选择攻击类型-字典
  2. 点击字典-选择字典
  3. 开始爆破~~

附上一个想暴打出题人的题目,

题目提示密码是4位数,但是爆破不出来。方法就是,复制这个文件25份,每份保留一张图片,然后逐个爆破!真服了

明文攻击

原理:

大致原理是当你不知道一个zip的密码,但是你有zip中的一个已知文件(文件大小要大于12Byte)时,

因为同一个zip压缩包里的所有文件都是使用同一个加密密钥来加密的,所以可以用已知文件来找加密密钥,利用密钥来解锁其他加密文件。

要求条件:

  • 2个加密的压包
  • 其中一个压缩包没有加密
  • 两个压缩包有同一个文件
  • 这个文件的crc32数值一样
  • 明文对应文件的加密算法需要是 ZipCrypto Store(我们实际应用中常常会被忽略的。因竞赛中遇到的题目,都是提前设置好的。)

方法:

  • 将明文压缩成压缩包
  • 确认和密文压缩方式相同,就是对比压缩之后的crc32值
  • 使用AZPR进行明文攻击

演示代码

1.如图第一个是加密处理的压缩包,CRC校验码为D3FC6621

2.未加密的压缩包

确保这两个文件的crc32值一样

3.打开AZPR

选择文本攻击(Plain-text),开始攻击

已知明文攻击高级版

只有一个文件,但是可以利用压缩方式进行明文攻击!!

上面说到必须要有一个明文的文件才能攻击,有一个更牛的,只需在已知加密压缩包中的少部分明文字节时即可进行攻击破解。但是有要求如下:

  • 至少已知明文的12个字节及偏移,其中至少8字节需要连续。
  • 明文对应的文件加密方式为ZipCrypto Store

总而言之就是长这样的加密方式

需要已知明文的12个字节,如果压缩包里面是png图片,我们知道png图片的文件头是固定的。504b0304这样,那这个就是已知明文。

举个例子,我知道压缩包的图片是flag.png,这个压缩包叫file.zip

准备一张png图片,叫fu.png的图片,用010删除到只剩下第一行

然后把这个文件压缩成fu.zip,我用的bandizip压缩的,用winrar好像不可以,他不是zipcryptostore方式压缩,360压缩(v4.0.0.1220)、好压(v6.2)使用的是ZipCrypto,如果要固定使用ZipCrypto Store算法加密,可以在压缩的时候指定压缩方式为“存储”。

我用bandizip压缩是这样配置的

发现好像不可以啊!!!

无奈下载360压缩

这下应该对了

输入如下命令开始获取key

bkcrack.exe -C file.zip -c flag.png -P fu.zip -p fu.png

获取到key之后

bkcrack.exe -C file.zip -c flag.png -k 你获取的key -d 1.png 
///1.png为输出的图片

ok,大功告成!

全部的工具我压缩好了,bkcr.rar,就在upload目录下,自己下载完

crc32碰撞

原理解释:

当压缩包被加密,密码又很难破解出来时;同时被加密的文本文档大小很小(CTF里面一般4KB),可以采取CRC32碰撞,碰撞成功后,该文件的原文将会被破解出来

演示步骤

  • 看CRC32值和文档字节大小

或者用代码读取文件获取CRC32值

# coding:utf-8
# 我这里flag.zip里有3个文档
import zipfile
import binascii

f = zipfile.ZipFile('ad71bf43131c4b3fa27066a3b408f843.zip', 'r')
for I in range(1,4):
    GetCrc = f.getinfo(str(I)+'.txt')
    crc = GetCrc.CRC
    print(hex(crc))

或者用笨方法逐个读取

# coding:utf-8
# 我这里flag.zip里有3个文档
import zipfile
import binascii

f = zipfile.ZipFile('2A636.zip', 'r')
GetCrc=f.getinfo('pass1.txt')
print(hex(GetCrc.CRC))

f = zipfile.ZipFile('2A636.zip', 'r')
GetCrc=f.getinfo('pass2.txt')
print(hex(GetCrc.CRC))

f = zipfile.ZipFile('2A636.zip', 'r')
GetCrc=f.getinfo('pass3.txt')
print(hex(GetCrc.CRC))

要是有中文文件,直接在winrar手工写入就行….

如果有一大堆的压缩文件

import string
import binascii
import zipfile

dic = string.ascii_letters + string.digits + '+/='

def crash_CRC32(crc):
    for a in dic:
        for b in dic:
            for c in dic:
                for d in dic:
                    s = a + b + c + d
                    encoded_s = s.encode('utf-8')  # 编码后的 s
                    if binascii.crc32(encoded_s) & 0xffffffff == crc:
                        return s
    return 0


def get_CRC32(zip_file_name):
    # 打开 zip 文件
    with zipfile.ZipFile(zip_file_name, 'r') as zip:
        # 使用字典来存储文件名与其 CRC32 值的映射
        crc_values = {}
        # 遍历 zip 文件中的每一个条目
        for zip_info in zip.infolist():
            # 将文件名和对应的 CRC32 值存入字典
            crc_values[zip_info.filename] = zip_info.CRC
        return crc_values


base = 'D:\工作\安全\Misc\zip'
str = ''
for i in range(0, 68):
    # 此处有68个文件,文件名为out0.zip-out67.zip
    zip_file_name = base + f'\\out{i}.zip'
    crc_list = get_CRC32(zip_file_name)
    # 遍历每一个压缩文件里面的每一个文件的CRC
    for j in crc_list.items():
        # 将获取的CRC32放入函数进行破解,然后将值进行拼接
        crc = j[1]
        crc = crash_CRC32(crc)
        if crc == 0:
            print('发生未知错误')
            exit(0)
        str += crc
        print(str)
print(str)

主要是把这些crc32的值读取出来后,在使用脚本碰撞,得出解压密码

  • 用工具碰撞,命令:python crc32.py reverse CRC32值

看到有两个输出,第一个0x??可以直接转出ascii码我们可以用脚本爆破下面,第二个其中一个可能就是密码

直接在下载的crc文件夹使用代码就行

附赠一个0x??转出ascii手工爆破脚本

# coding:utf-8

import binascii
import string

def crack_crc():
    print('-------------Start Crack CRC-------------')
    crc_list = [0x1D9F11E5, 0xE3A35EED, 0x694AEF57]#文件的CRC32值列表,注意顺序
    comment = ''
    chars = string.printable
    for crc_value in crc_list:
        for char1 in chars:
            for char2 in chars:
                for char3 in chars:
                    for char4 in chars:
                        res_char = char1 + char2 + char3 + char4#获取遍历的任意4Byte字符
                        char_crc = binascii.crc32(res_char.encode())#获取遍历字符的CRC32值
                        calc_crc = char_crc & 0xffffffff#将遍历的字符的CRC32值与0xffffffff进行与运算
                        if calc_crc == crc_value:#将获取字符的CRC32值与每个文件的CRC32值进行匹配
                            print('[+] {}: {}'.format(hex(crc_value),res_char))
                            comment += res_char
    print('-----------CRC Crack Completed-----------')
    print('Result: {}'.format(comment))

if __name__ == '__main__':
    crack_crc()

这是另一个脚本,我还没试过….

import string
import binascii
s=string.printable
c =[0xF3B61B38,0xF3B61B38,0X6ABF4A82,0X5ED1937E,0X09b9265b,0x84b12bae,0x70659eff,0x90b077e1,0x6abf4a82]
# 把文件的crc写进来
password = ''
for crc in c:
    for i in s:
        if crc==(binascii.crc32(i.encode())&0xffffffff):
            password =password + i
            print(password)

案例1

这三个文件这么短,说明可能用crc32碰撞,首先用代码读取出来crc32的值

然后用crc32脚本逐个碰撞密码

把带下划线长得像密码的凑在一起,得出密码

forum_91ctf_com_66

直接解压,然后得到一大窜二进制文本,使用二进制转文本工具,或者使用随波逐流工具箱,二进制转字符也能得到结果

二进制转文本工具

得到图片的base64加密

然后用随波逐流工具箱直接把base64转出图片

案例2:

这道题打开是68个加密的压缩文件,文件名为chunk1.zip,chunk2.zip…..寻找规律发现每个压缩包里面的内容都是4个字节,首要考虑就是CRC爆破。

import zipfile 
import string
from binascii import crc32
stR = string.printable
for i in range(0,68): 
    #直接从zip中读取CRC32
    zip_name = "chunk"+str(i)+".zip" 
    if zip_name.lower().endswith(('.zip')): 
        z = zipfile.ZipFile(zip_name, "r") 
    for info in z.infolist(): 
        crc = format(info.CRC & 0xFFFFFFFF, '08x')  #75f90d3a
        for c in stR:
            for j in stR:
                for k in stR:
                    for q in stR:
                        s = c+j+k+q
                        if crc32(s.encode())==int(crc,16):
                            print("out"+str(i)+': '+s)

结果是一串base64:

z5BzAAANAAAAAAAAAKo+egCAIwBJAAAAVAAAAAKGNKv+a2MdSR0zAwABAAAAQ01UCRUUy91BT5UkSNPoj5hFEVFBRvefHSBCfG0ruGnKnygsMyj8SBaZHxsYHY84LEZ24cXtZ01y3k1K1YJ0vpK9HwqUzb6u9z8igEr3dCCQLQAdAAAAHQAAAAJi0efVT2MdSR0wCAAgAAAAZmxhZy50eHQAsDRpZmZpeCB0aGUgZmlsZSBhbmQgZ2V0IHRoZSBmbGFnxD17AEAHAA==
坚持原创技术分享,您的支持将鼓励我继续创作!

-------------本文结束感谢您的阅读-------------

腾讯云主机优惠打折:最新活动地址


版权声明

LangZi_Blog's by Jy Xie is licensed under a Creative Commons BY-NC-ND 4.0 International License
由浪子LangZi创作并维护的Langzi_Blog's博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证
本文首发于Langzi_Blog's 博客( http://langzi.fun ),版权所有,侵权必究。

0%