news 2026/5/14 20:58:15

CTF新手必看:用Python脚本修复被篡改的PNG图片宽高(附CRC校验原理详解)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CTF新手必看:用Python脚本修复被篡改的PNG图片宽高(附CRC校验原理详解)

CTF实战:Python脚本修复PNG图片宽高与CRC校验原理全解析

当你第一次在CTF比赛中遇到一张无法正常显示的PNG图片时,可能会感到困惑。这张图片看起来像是被故意破坏了,但其中很可能隐藏着关键的Flag信息。本文将带你深入理解PNG文件结构,掌握CRC校验原理,并手把手教你编写Python脚本来自动修复被篡改的图片宽高参数。

1. PNG文件结构与CRC校验基础

PNG(Portable Network Graphics)文件由多个数据块(chunks)组成,每个数据块都有特定的结构和功能。理解这些结构是修复损坏图片的第一步。

一个典型的PNG文件包含以下关键数据块:

  • 文件头签名:8字节的固定值(89 50 4E 47 0D 0A 1A 0A),用于标识PNG文件
  • IHDR块:包含图像的基本信息(宽、高、位深、颜色类型等)
  • IDAT块:存储实际的图像数据
  • IEND块:标记文件结束

其中,IHDR块是我们关注的重点,它的结构如下:

字段长度(字节)说明
宽度4大端存储的图像宽度
高度4大端存储的图像高度
位深1每个通道的位数(如8)
颜色类型10(灰度)、2(RGB)、3(调色板)、4(灰度+alpha)、6(RGB+alpha)
压缩方法1通常为0(deflate压缩)
滤波方法1通常为0(自适应滤波)
隔行扫描10(非隔行)或1(Adam7隔行)

每个数据块(包括IHDR)都有一个CRC校验码,它是根据数据块类型和数据内容计算得出的32位循环冗余校验值。CRC校验的核心作用是确保数据在传输或存储过程中没有被意外或故意修改。

提示:在CTF比赛中,出题人常常会修改IHDR中的宽高值但不更新CRC校验码,导致图片无法正常显示。这正是我们需要修复的情况。

2. CRC校验原理深度解析

CRC(Cyclic Redundancy Check)校验是一种广泛使用的错误检测技术,它基于多项式除法原理。理解CRC的计算方式对于编写修复脚本至关重要。

CRC校验的基本特点:

  • 计算速度快,适合硬件实现
  • 对突发错误有很好的检测能力
  • 校验码长度固定(PNG使用CRC-32,即32位校验码)

CRC-32的计算过程可以概括为:

  1. 初始化一个32位的寄存器为全1(0xFFFFFFFF)
  2. 对每个输入字节,与寄存器高位进行异或
  3. 对寄存器进行8次移位操作,根据最低位决定是否与多项式(0xEDB88320)异或
  4. 处理完所有数据后,对寄存器值取反

在Python中,我们可以直接使用binascii.crc32函数来计算CRC值:

import binascii data = b'IHDR' + struct.pack('>i', width) + struct.pack('>i', height) + b'\x08\x02\x00\x00\x00' crc32 = binascii.crc32(data) & 0xffffffff

注意:& 0xffffffff操作是为了确保结果是无符号32位整数,避免Python自动转换为负数。

3. 手动分析与修复损坏的PNG

让我们通过一个实际案例来学习如何手动分析并修复被篡改的PNG文件。假设我们有一个名为corrupted.png的文件,无法正常显示。

步骤1:使用十六进制编辑器查看文件

推荐工具:

  • 010 Editor(Windows/Mac)
  • Bless(Linux)
  • xxd(命令行工具)

使用010 Editor打开文件,我们可以看到类似如下的结构:

00000000: 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 .PNG........IHDR 00000010: 00 00 03 84 00 00 00 96 08 02 00 00 00 76 EC 1E .............v.. 00000020: 40 00 00 00 01 73 52 47 42 00 AE CE 1C E9 00 00 @....sRGB.......

关键字段解析:

  • 0000000C-0000000F:IHDR数据块长度(13字节,即0x0000000D)
  • 00000010-00000013:IHDR标识("IHDR")
  • 00000014-00000017:宽度(0x00000384 = 900像素)
  • 00000018-0000001B:高度(0x00000096 = 150像素)
  • 0000001C-0000001F:CRC校验码(0x76EC1E40)

步骤2:验证CRC校验码

计算IHDR数据块的CRC值并与文件中存储的校验码比较:

import binascii # IHDR数据块内容(不包括长度和类型字段) ihdr_data = b'\x49\x48\x44\x52\x00\x00\x03\x84\x00\x00\x00\x96\x08\x02\x00\x00\x00' calculated_crc = binascii.crc32(ihdr_data) & 0xffffffff stored_crc = 0x76EC1E40 print(f"计算CRC: {hex(calculated_crc)}") print(f"存储CRC: {hex(stored_crc)}") print(f"是否匹配: {calculated_crc == stored_crc}")

如果输出显示不匹配,说明宽高参数可能被篡改。

4. 自动化修复:Python爆破脚本编写

手动修改宽高并验证CRC效率低下,我们可以编写Python脚本自动爆破正确的宽高值。以下是完整的脚本实现:

import binascii import struct def fix_png_dimensions(filename): # 读取PNG文件 with open(filename, 'rb') as f: png_data = f.read() # 提取IHDR数据块中的CRC校验码(大端序) ihdr_crc = png_data[29:33] stored_crc = struct.unpack('>I', ihdr_crc)[0] # IHDR数据块固定部分 chunk_type = png_data[12:16] # 'IHDR' chunk_rest = png_data[24:29] # 位深、颜色类型等 print(f"开始爆破CRC: {hex(stored_crc)}...") # 尝试可能的宽高组合 for width in range(1, 2000): for height in range(1, 2000): # 构造IHDR数据块内容 data = chunk_type + struct.pack('>i', width) + struct.pack('>i', height) + chunk_rest # 计算CRC calculated_crc = binascii.crc32(data) & 0xffffffff if calculated_crc == stored_crc: print(f"找到匹配的宽高: {width}x{height}") print(f"宽度(hex): {hex(width)}") print(f"高度(hex): {hex(height)}") # 修复文件 fixed_data = png_data[:16] + struct.pack('>i', width) + struct.pack('>i', height) + png_data[24:] with open('fixed.png', 'wb') as f: f.write(fixed_data) print("已生成修复后的文件: fixed.png") return print("未找到匹配的宽高组合") # 使用示例 fix_png_dimensions('corrupted.png')

脚本优化技巧:

  1. 并行计算:对于大范围搜索,可以使用多进程加速
  2. 智能范围:根据图片内容猜测可能的宽高比例,缩小搜索范围
  3. 增量搜索:先以较大步长搜索,找到大致范围后再精细搜索
from multiprocessing import Pool def check_dimensions(args): width, height, chunk_type, chunk_rest, stored_crc = args data = chunk_type + struct.pack('>i', width) + struct.pack('>i', height) + chunk_rest calculated_crc = binascii.crc32(data) & 0xffffffff return (width, height) if calculated_crc == stored_crc else None def parallel_fix_png(filename): with open(filename, 'rb') as f: png_data = f.read() stored_crc = struct.unpack('>I', png_data[29:33])[0] chunk_type = png_data[12:16] chunk_rest = png_data[24:29] # 创建参数列表 params = [(w, h, chunk_type, chunk_rest, stored_crc) for w in range(1, 2000) for h in range(1, 2000)] with Pool() as pool: results = pool.map(check_dimensions, params) for result in results: if result: print(f"匹配的宽高: {result[0]}x{result[1]}") return

5. 实战案例与进阶技巧

让我们通过几个实际CTF题目来巩固所学知识。

案例1:基础CRC修复

给定一个损坏的PNG文件,已知CRC校验码为0xEC9CCBC6,但宽高被修改。使用我们的脚本可以在几秒内找到正确的宽高组合(如900x606)。

案例2:GIF文件中的CRC修复

有些CTF题目会使用GIF文件,原理类似但需要注意:

  1. GIF文件由多个图像块组成,每个都有自己的逻辑屏幕描述符
  2. 需要修复的可能是某个帧的宽高
  3. 工具推荐:gifsplit可以将GIF分解为单帧
def fix_gif_dimensions(gif_file): # 分解GIF为单帧 subprocess.run(['gifsplit', gif_file]) # 对每帧应用PNG修复技术 for frame in glob.glob('frame_*.gif'): fix_png_dimensions(frame)

案例3:结合LSB隐写的综合题目

有时CRC修复只是第一步,修复后的图片可能还包含LSB隐写:

  1. 先修复PNG宽高使图片正常显示
  2. 使用StegSolve工具分析LSB隐写
  3. 提取隐藏信息获取最终Flag
from PIL import Image import numpy as np def extract_lsb(image_path): img = Image.open(image_path) pixels = np.array(img) # 提取每个颜色通道的最低位 lsb = (pixels & 1) * 255 lsb_img = Image.fromarray(lsb.astype('uint8')) lsb_img.save('lsb_extracted.png')

性能优化技巧:

  1. 使用Cython或Numba加速CRC计算
  2. 对已知比例的图片(如1:1、4:3、16:9)优先搜索
  3. 缓存中间计算结果,避免重复计算
# 使用Numba加速的CRC计算 from numba import jit @jit(nopython=True) def crc32_numba(data, crc=0xffffffff): for byte in data: crc ^= byte << 24 for _ in range(8): if crc & 0x80000000: crc = (crc << 1) ^ 0x04C11DB7 else: crc <<= 1 return crc & 0xffffffff

掌握这些技术后,你将能够应对大多数CTF比赛中与PNG文件修复相关的挑战。记住,理解原理比记住工具更重要,这将帮助你在遇到变种题目时能够灵活应对。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/14 20:56:49

ArduRemoteID架构深度解析:ESP32平台下的无人机远程识别技术实现

ArduRemoteID架构深度解析&#xff1a;ESP32平台下的无人机远程识别技术实现 【免费下载链接】ArduRemoteID RemoteID support using OpenDroneID 项目地址: https://gitcode.com/gh_mirrors/ar/ArduRemoteID 在全球无人机监管政策日益严格的背景下&#xff0c;RemoteID…

作者头像 李华
网站建设 2026/5/14 20:52:06

从CliffWalking到CartPole:表格型与DQN系列算法的实战环境搭建与对比实验

1. 强化学习环境搭建&#xff1a;从零开始的实战指南 第一次接触强化学习的朋友们&#xff0c;最头疼的往往不是算法本身&#xff0c;而是环境的配置。我当年在实验室配环境时&#xff0c;整整折腾了两天才跑通第一个demo。下面就把这些年踩过的坑和最佳实践分享给大家。 核心工…

作者头像 李华
网站建设 2026/5/14 20:45:35

大数据开发面试常问的 Linux 命令 总结

大数据开发面试必备Linux命令清单本文总结了大数据开发面试中高频考察的Linux命令&#xff0c;重点突出与实际开发场景相关的技能点。核心内容包括&#xff1a;文本处理三剑客&#xff08;grep/awk/sed&#xff09;的日志分析和数据处理应用进程管理&#xff08;ps/kill&#x…

作者头像 李华
网站建设 2026/5/14 20:43:08

VSCode 远程连接服务器 .vscode-server 目录权限冲突排查与修复

1. 为什么会出现.vscode-server权限冲突&#xff1f; 这个问题通常发生在混合使用不同用户权限连接远程服务器时。想象一下这样的场景&#xff1a;你第一次用VSCode连接服务器时&#xff0c;不小心使用了root账户&#xff08;或者某个高权限账户&#xff09;&#xff0c;这时候…

作者头像 李华