png图片CRC爆破原理的学习

循环冗余校验码简称CRC码,是目前使用非常广泛的数据校验方式.它不仅能校验传递过来的数据正确性,还能筛查出哪一位出现了错误.它的局限性是只能校验一位数据发生跳变,在现实世界当中数据发生跳变很大很大的概率只有一位发生变化,因此CRC码也拥有很大的发挥舞台.

循环冗余校验码的定义与编码方法

用待校验的数据,除以某个约定代码,能除尽说明数据正常,否则通过循环位移校正出错为
视频学习-->中国大学MOOC 《计算机组成原理》
https://www.icourse163.org/learn/UESTC-1001543002?tid=1460688446#/learn/content?type=detail&id=1236902185&cid=1256678353

编码方法

1.将待编码的k位有效数据M(x)左移r位,得到全编码多项式M(x)*xr,空出r位,以装填r位余数
2.选取一个r+1位的生成多项式G(x),对M(x)*xr进行模2除运算,得到商Q(x)和余数R(x)的代码
3.将左移r位的待编码信息,与余数R(x)模2加,可拼接为包含有效数据在内的CRC编码

用举例的方法来解释:


不同CRC标准

不同的标准采用的Q(x)不同
CRC4:x4+x+1
CRC8: x8+x5+x4+1
CRC16: x16+x12+x5+1
CRC32: x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1

png图片格式

先来看一个正常png图片的开始部分

89 50 4E 47 0D 0A 1A 0A png文件头
00 00 00 0D 文件头数据块表示IDCH
49 48 44 52 IHDR 文件头数据块
00 00 03 84 宽度
00 00 01 7F 高度
08 06 00 00 00 每一位依次表示 图像深度, 颜色类型, 压缩方法, 滤波器方法,隔行扫描方法
11 84 07 C8 CRC32校验码

png图片IHDR部分的CRC校验码,是根据IDCH和IHDR数据计算出来的,即计算00 00 00 0D 49 48 44 52 00 00 03 84 00 00 01 7F 08 06 00 00 00的CRC校验码
如果修改了图片的宽高,没有修改CRC编码,那么可以通过计算发现CRC编码不一致。010 editor在打开图片时会检查CRC校验码,如果有问题会提醒。
可以使用python zlib库中的函数计算CRC校验值

import zlib

with open('1.png','rb') as image_data:
    bin_data=image_data.read()
data = bytearray(bin_data[12:29])#截取待计算的字符串
crc32key = zlib.crc32(data)#使用函数计算
print(hex(crc32key))

根据CRC校验值暴力破解png图片正确的宽高

由于CRC32只能对一位数据出错做出校正,而修改宽高时涉及的数据不一定只用一位,所以可以采取的办法只有枚举png图片的宽高,然后计算修改后图片的CRC值,与正确的CRC值比较看是否一致
从别的大佬博客里获得的脚本

import zlib
import struct

filename = '2.png'
with open(filename, 'rb') as f:
    all_b = f.read()
    crc32key = int(all_b[29:33].hex(), 16)
    data = bytearray(all_b[12:29])
    n = 4095  # 理论上0xffffffff,但考虑到屏幕实际/cpu,0x0fff就差不多了
    for w in range(n):  # 高和宽一起爆破
        width = bytearray(struct.pack('>i', w))  # q为8字节,i为4字节,h为2字节
        for h in range(n):
            height = bytearray(struct.pack('>i', h))
            for x in range(4):
                data[x + 4] = width[x]
                data[x + 8] = height[x]
            crc32result = zlib.crc32(data)
            if crc32result == crc32key:
                # 2021.7.20,有时候显示的宽高依然看不出具体的值,干脆输出data部分
                print(data.hex())
                print("宽为:", end="")
                print(width)
                print("高为:", end="")
                print(height)
                exit(0)

参考文献

png图片crc32爆破宽和高:https://moddemod.blog.csdn.net/article/details/103787186
png文件格式详解:https://www.cnblogs.com/mengfanrong/p/3801583.html

posted @ 2021-02-26 21:20  云千  阅读(3933)  评论(0编辑  收藏  举报