png高度爆破
IHDR的结构
png图片的各种基础信息保留在 IHDR
块中, IHDR
块的数据部分长度固定为 13
个字节, 整个数据的分布如下:
字段名称 | 字段长度(字节) | 描述及取值范围 |
---|---|---|
length | 4 | IHDR数据块的长度, 固定为13字节 |
type | 4 | IHDR的标志, 固定为字符串 "IHDR" |
Width | 4 | 图像的宽度,单位为像素 |
Height | 4 | 图像的高度,单位为像素 |
Bit depth | 1 | 图像的位深度,即每个颜色通道的比特数 |
Color type | 1 | 图像的颜色类型 |
Compression method | 1 | 图像的压缩方法 |
Filter method | 1 | 图像的滤波器方法 |
Interlace method | 1 | 图像的扫描方法 |
一个完整的 IHDR
块还会在末尾加上一个四字节的 crc
, 在010中查看是这样的(整个chunk[0]):

IHDR
之前的是文件头, 占8个字节
crc的计算
整个 IHDR
块最后的 crc 值 是直接通过 type
到 Interlace method
这一段数据计算得到的
可以通过调用 zlib
模块的 zlib.crc32(data)
来完成计算, 也就是说可以通过遍历整个数据段, 爆破高度值并计算crc来与最后的 crc进行对比
读取文件信息
使用 with open
打开文件, 并用 read
逐步读取对应的字节数并将其打印出来
# 获得png图片的路径
png_path = input("输入png图片的路径:")
# 打开图片
with open(png_path, 'rb') as f:
# 文件头
head = f.read(8)
print(f"文件头: \t\t\t{head}")
# length
ihdr_length = f.read(4)
print(f"length字段: \t\t\t{ihdr_length}")
# type
ihdr_type = f.read(4)
print(f"type字段: \t\t\t{ihdr_type}")
# width
width = f.read(4)
print(f"width字段: \t\t\t{width}")
# height
height = f.read(4)
print(f"height字段: \t\t\t{height}")
# bit_depth
bit_depth = f.read(1)
print(f"bit_depth字段: \t\t\t{bit_depth}")
# color_type
color_type = f.read(1)
print(f"color_type字段: \t\t{color_type}")
# compression_method
compression_method = f.read(1)
print(f"compression_method字段: \t{compression_method}")
# filter_method
filter_method = f.read(1)
print(f"filter_method字段: \t\t{filter_method}")
# interlace_method
interlace_method = f.read(1)
print(f"interlace_method字段: \t\t{interlace_method}")
# crc
crc = f.read(4)
print(f"crc的值: {crc}")
遍历高度值
使用for循环遍历高度并组成新的ihdr块:
for new_height in range(1000):
# 将整型打包为字节
new_height = struct.pack(">I", new_height)
# 拼接成新的ihdr
ihdr = (head +
ihdr_length +
ihdr_type +
width +
new_height +
bit_depth +
color_type +
compression_method +
filter_method +
interlace_method)
print(ihdr)
计算crc
# 使用zlib的crc32方法计算crc
new_crc = zlib.crc32() # 返回的是整数
# 使用pack进行打包
new_crc = struct.pack(">I", new_crc)
# 判断计算的crc是否等于原来的
if new_crc == crc:
print(new_crc)
break
else:
pass
整合
将前面的代码整合起来得到:
import struct
import zlib
# 获得png图片的路径
png_path = input("输入png图片的路径:")
# 打开图片
with open(png_path, 'rb') as f:
print("读取文件信息......")
# 文件头
head = f.read(8)
print(f"文件头: \t\t\t{head}")
# length
ihdr_length = f.read(4)
print(f"length字段: \t\t\t{ihdr_length}")
# type
ihdr_type = f.read(4)
print(f"type字段: \t\t\t{ihdr_type}")
# width
width = f.read(4)
print(f"width字段: \t\t\t{width}")
# height
height = f.read(4)
print(f"height字段: \t\t\t{height}")
# bit_depth
bit_depth = f.read(1)
print(f"bit_depth字段: \t\t\t{bit_depth}")
# color_type
color_type = f.read(1)
print(f"color_type字段: \t\t{color_type}")
# compression_method
compression_method = f.read(1)
print(f"compression_method字段: \t{compression_method}")
# filter_method
filter_method = f.read(1)
print(f"filter_method字段: \t\t{filter_method}")
# interlace_method
interlace_method = f.read(1)
print(f"interlace_method字段: \t\t{interlace_method}")
# crc
crc = f.read(4)
print(f"crc的值: {crc}\n")
print("爆破高度.....")
# 假定高度是0-999
for new_height in range(1000):
# 将整型打包为字节
new_height = struct.pack(">I", new_height)
# 拼接成新的ihdr
ihdr = (ihdr_type +
width +
new_height +
bit_depth +
color_type +
compression_method +
filter_method +
interlace_method)
# 使用zlib的crc32方法计算crc
new_crc = zlib.crc32(ihdr)
new_crc = struct.pack(">I", new_crc)
if new_crc == crc:
print("计算得到的crc:", new_crc.hex())
print("原来的高度是:", height.hex())
break
else:
pass
03 十一月 2024