HacKerQWQ的博客空间

CRC32碰撞恢复png(含png块的知识)

Word count: 746Reading time: 3 min
2020/09/26 Share

png块的基本知识


前八个字节表示这是一个png文件,然后接着的四个字节表示数据块长度,最后四个字节表示数据块类型码,比如这里的IHDR类型码

文件署名域

8字节的PNG文件署名域用来识别该文件是不是PNG文件。该域的值是:
|十进制数|十六进制数|
|:-:|:-:|
|137|89|
|80|50|
|78|4e|
|71|47|
|13|0d|
|10|0a|
|26|1a|
|10|0a|

数据块

数据块分为关键数据块(critical chunk)**和辅助数据块(ancillary chunks)
每个数据块都由下表所示的4个域组成
|名称|字节数|说明|
|:–:|:–:|:–|
|Length(长度)|4字节|指定数据块中数据域的长度,其长度不超过(231−1)(231−1)字节|
|Chunk Type Code(数据块类型码)|4字节|数据块类型码由ASCII字母(A-Z和a-z)组成|
|Chunk Data(数据块内容)|可变长度|存储按照Chunk Type Code指定的数据|
|CRC(循环冗余检测)|4字节|存储用来检测是否有错误的循环冗余码|
其中
CRC是对Chunk Type Code域Chunk Data**域中的数据计算得到,是一种校验码。

IHDR

域的名称 字节数 说明
Width 4bytes 宽度,以像素为单位
Bit depth 4bytes 高度,以像素为单位
ColorType 1byte 图像深度:索引彩色图像:1,2,4或8 ;灰度图像:1,2,4,8或16 ;真彩色图像:8或16
Compression method 1byte 压缩方法
Filter method 1byte 滤波器方法
Interlace method 1byte 隔行扫描方法:0:非隔行扫描;1: Adam7(由Adam M. Costello开发的7遍隔行扫描方法)
(更多方法参考链接)[https://www.cnblogs.com/senior-engineer/p/9548347.html]

题目

题目来自攻防世界misc区的2-1[https://adworld.xctf.org.cn/task/answer?type=misc&number=1&grade=1&id=4954&page=3]

下载得到一个图片,无法打开,那就是文件格式出了问题了
用HxD打开看看

好几个地方都出错了,根据png块的知识修改png标识先

剩下一个宽度未知,这里我们就需要用到CRC32碰撞的知识,由于CRC32是根据Chunk Type CodeChunk Data计算而来的,因此类似于md5碰撞,我们这里也可以用脚本

1
2
3
4
5
6
7
8
9
10
11
12
import os 
import binascii
import struct

#用二进制方式打开文件
misc = open("misc4.png","rb").read()

for i in range(1024):
data = misc[12:16] + struct.pack('>i',i)+ misc[20:29]#struct.pack将数据转换为十六进制形式
crc32 = binascii.crc32(data) & 0xffffffff #计算crc32的值并转换为十进制形式
if crc32 == 0x932f8a6b: #符合结果则说明碰撞成功
print (i)

分析:

CATALOG
  1. 1. png块的基本知识
    1. 1.1. 文件署名域
    2. 1.2. 数据块
    3. 1.3. IHDR
  2. 2. 题目
  3. 3. Reference