【Misc】PNG宽高修复实战 - CRC爆破与自动化工具解析

张开发
2026/4/11 9:48:05 15 分钟阅读

分享文章

【Misc】PNG宽高修复实战 - CRC爆破与自动化工具解析
1. PNG文件结构与宽高修改原理当你第一次遇到CTF竞赛中那些被故意压扁或拉长的PNG图片时可能会感到困惑。为什么修改几个数字就能让图片显示异常这要从PNG的文件结构说起。PNG文件就像个精心设计的集装箱每个数据块都有固定位置和明确分工。文件开头的8个字节89 50 4E 47 0D 0A 1A 0A是PNG的身份证任何正经的PNG文件都必须以这串魔数开头。紧接着就是关键的IHDR块它相当于图片的户口本记录了宽度、高度、色深等核心信息。具体来说宽度IHDR块的第16-19字节4字节大端序高度第20-23字节同样4字节大端序我曾在实际比赛中遇到过一张看似正常的图片用编辑器打开后发现宽度被改成了00 00 00 01。这种极端修改会导致大多数查看器直接报错但有些工具会尝试渲染结果就是显示一条1像素宽的细线。2. CRC校验机制详解这里有个有趣的保护机制——CRC校验码。每个数据块末尾都有4字节的CRC32值就像快递包裹上的防拆封条。IHDR块的CRC校验范围包括块类型标识IHDR4字节宽度数据4字节高度数据4字节后续的色深、颜色类型等参数5字节用Python验证CRC非常方便import zlib data bIHDR width_bytes height_bytes b\x08\x02\x00\x00\x00 crc32 zlib.crc32(data)有个坑我踩过多次不同工具计算CRC时可能包含/不包含块长度字段。比如010 Editor显示的CRC是包含长度字段的而Python的zlib.crc32默认不包含。这个细节差异曾让我调试了半天。3. 手工修复宽高实战假设我们拿到一个高度被篡改的CTF题目图片以下是详细修复步骤用Hex编辑器定位IHDR块跳过前8字节文件头接下来4字节是IHDR长度00 00 00 0D紧接着就是IHDR标识49 48 44 52修改宽高值宽度第16-19字节如00 00 02 58高度第20-23字节如00 00 01 2C重新计算CRC 使用前文Python代码生成新CRC替换最后4字节有个实用技巧可以先尝试把高度改大比如00 00 FF FF如果图片显示更多空白区域说明原图高度确实被改小了。我在某次比赛中用这个方法快速定位到了关键线索。4. 自动化爆破工具解析手工操作虽然直观但比赛时效率太低。推荐使用Brute_Crack_PNG这类工具其核心原理是读取原始CRC值遍历可能的宽高组合用zlib.crc32验证匹配工具的参数设置很有讲究搜索范围建议先设±1000像素太大影响速度步长设置常规设为1已知被整除时可调整多线程Go版本比Python快10倍以上实测一个800x600的图片在i7处理器上单线程完整搜索需12秒开启多线程后仅需1.8秒这里有个优化诀窍如果图片内容可见部分显示完整只是边缘有裁剪可以先估算大致比例。比如看到图片底部被切可以优先爆破高度值宽度保持原值。5. 进阶技巧与异常处理不是所有情况都能直接爆破成功。有次我遇到题目把CRC也改了常规方法失效。这时需要特征值搜索法在图片数据中寻找明显特征如连续FF字节反推可能尺寸文件尾验证PNG结尾必须是IEND块异常尺寸可能导致数据截断多工具交叉验证组合使用pngcheck、hexedit等工具互相验证特别提醒某些CTF题目会故意设置多个合法的CRC组合这时需要结合图片实际显示效果判断。曾有个题目设置了两个有效高度值只有较大的那个才会显示完整flag。6. 防御与检测方案作为出题方如果想防止选手简单爆破可以考虑修改IHDR块其他参数如色深增加爆破维度在IDAT块中插入尺寸校验逻辑使用非标准CRC计算方式检测工具开发建议def verify_png(file_path): with open(file_path, rb) as f: data f.read() ihdr_pos data.find(bIHDR) - 4 width int.from_bytes(data[ihdr_pos8:ihdr_pos12], big) height int.from_bytes(data[ihdr_pos12:ihdr_pos16], big) # 添加业务逻辑校验...实际开发中要注意内存映射处理大文件我曾用mmap优化过一个验证工具处理100MB的PNG时速度提升近20倍。

更多文章