[CTF隱寫]png中CRC檢驗錯誤的分析
最近接連碰到了3道關於png中CRC檢驗錯誤的隱寫題,查閱了相關資料后學到了不少姿勢,在這里做一個總結
題目來源:
- bugku-MISC-隱寫2
- bugku-MISC-再來一道隱寫
- JarvisOJ-MISC-炫酷的戰隊logo
基礎知識:
先分析png的文件格式,用16進制編輯器010editor打開一張正常的png圖片,逐字節分析如下:
前八個字節89 50 4E 47 0D 0A 1A 0A為png的文件頭,該段格式是固定的
上圖中高亮部分稱為為chunk[0]段,可以分為以下幾塊:
前四個字節00 00 00 0D(即為十進制的13)代表數據塊的長度為13,數據塊包含了png圖片的寬高等信息,該段格式是固定的
之后的四個字節49 48 44 52(即為ASCII碼的IHDR)是文件頭數據塊的標示,該段格式也是固定的
之后進入13位數據塊,前8個字節00 00 05 56 00 00 03 00中:
前四個字節00 00 05 56(即為十進制的1366),代表該圖片的寬,該段數據是由圖片的實際寬決定的
后四個字節00 00 03 00(即為十進制的768),代表該圖片的高,該段數據是由圖片的實際高度決定的
這8個字節都屬於13位數據塊的內容,因此數據塊應再向后數5個字節,即為00 00 05 56 00 00 03 00 08 02 00 00 00
剩余的4位40 5C AB 95為該png的CRC檢驗碼,也就是本篇文章要重點討論的地方,該段數據是由IDCH以及十三位數據塊(即上文中的49 48 44 52 00 00 05 56 00 00 03 00 08 02 00 00 00)計算得到的
有了之上的基礎知識,再來看大部分png中CRC檢驗錯誤的出題思路:
對一張正常的圖片,通過修改其寬度或者高度隱藏信息,使計算出的CRC校驗碼與原圖的CRC校驗碼不一致;windows的圖片查看器會忽略錯誤的CRC校驗碼,因此會顯示圖片,但此時的圖片已經是修改過的,所以會有顯示不全或扭曲等情況,借此可以隱藏信息。
而Linux下的圖片查看器不會忽略錯誤的CRC校驗碼,因此用Linux打開修改過寬或高的png圖片時,會出現打不開的情況
以隱寫2題目舉例
在windows和Linux下分別打開圖片,如下圖,windows中可以打開,deepin系統顯示為空白,因此猜測是該png的寬或高被修改導致CRC校驗碼錯誤
於是用010editor打開該png分析其字節信息,如下圖
紅框圈住的部分即為該png的寬和高,紅圈圈住的部分為該png的CRC校驗碼,箭頭部分為010editor的templete檢測出了png的CRC錯誤
於是我們可以通過爆破圖片修改前的寬和高來匹配CRC校驗碼,並用正確的寬和高來修復圖片
為了做題的方便,先嘗試爆破高度,腳本如下:
# -*- coding: utf-8 -*-
import binascii
import struct
#\x49\x48\x44\x52\x00\x00\x01\xF4\x00\x00\x01\xA4\x08\x06\x00\x00\x00
crc32key = 0xCBD6DF8A
for i in range(0, 65535):
height = struct.pack('>i', i)
#CRC: CBD6DF8A
data = '\x49\x48\x44\x52\x00\x00\x01\xF4' + height + '\x08\x06\x00\x00\x00'
crc32result = binascii.crc32(data) & 0xffffffff
if crc32result == crc32key:
print ''.join(map(lambda c: "%02X" % ord(c), height))
運行腳本,輸出000001F4,即原圖片高度為00 00 01 F4爆破成功
因此我們用010editor修改png的高度為原高度,如下,並保存為新圖片
此時我們發現deepin的圖片查看器已經可以正常的打開圖片了,說明我們修復成功
第二題與第一題類似,不再復述;第三題較前兩題有所改變,留給大家動手實踐
幾點補充:
-
判斷是否為crc校驗碼錯誤的方法:
- windows下圖片可以打開,其他系統下圖片不能打開
- 使用010editor的template檢測,這也是我16進制編輯器力推010editor的原因之一
- 使用諸如tweakpng,pngcheck等工具
-
修復png的crc檢驗碼方法:
- 本文中所列的爆破出正確的寬或高,並用16進制編輯器修復
- 利用windows忽略crc檢驗碼的特性,我們可以用tweakpng任意修改圖片的寬和高,直至得到有用的信息,事實上,這是最快的方法
雖說在windows下使用tweakpng是最簡單的方法,但還是建議大家在練習過程中通過編程來實現,畢竟對於程序員而言,最大的成就莫過於用自己寫的代碼來解決問題。