Misc 總結 ----隱寫術之圖片隱寫(二)
實驗簡介
隱寫術是關於資訊隱藏,即不讓計劃的接收者之外的任何人知道資訊的傳遞事件(而不只是資訊的內容)的一門技巧與科學。英文寫作Steganography,而本套教程內容將帶大家瞭解一下CTF賽場上常見的圖片隱寫方式,以及解決方法。有必要強調的是,隱寫術與密碼編碼是完全不同的概念。
實驗內容
本次圖片隱寫實驗包括四大部分
- 一、附加式的圖片隱寫
- 二、基於檔案結構的圖片隱寫
- 三、基於LSB原理的圖片隱寫
- 四、基於DCT域的JPG圖片隱寫
- 五、數字水印的隱寫
- 六、圖片容差的隱寫
第二部分 基於檔案結構的圖片隱寫
實驗環境
- 操作機:Windows XP
- 實驗工具:
- 010Editor
- CRC Calculator
- 實驗工具:
背景知識
首先這裡需要明確一下我這裡所說的檔案結構是什麼意思。檔案結構特指的是圖片檔案的檔案結構。我們這裡主要講的是PNG圖片的檔案結構。
PNG,影象檔案儲存格式,其設計目的是試圖替代GIF和TIFF檔案格式,同時增加一些GIF檔案格式所不具備的特性。是一種點陣圖檔案(bitmap file)儲存格式,讀作“ping”。PNG用來儲存灰度影象時,灰度影象的深度可多到16位,儲存彩色影象時,彩色影象的深度可多到48位,並且還可儲存多到16位的α通道資料。
對於一個正常的PNG圖片來講,其檔案頭總是由固定的位元組來表示的,以16進製表示即位 89 50 4E 47 0D 0A 1A 0A,這一部分稱作檔案頭。 標準的PNG檔案結構應包括:
- PNG檔案標誌
- PNG資料塊 PNG圖片是有兩種資料塊的,一個是叫關鍵資料塊,另一種是輔助資料塊。正常的關鍵資料塊,定義了4種標準資料塊,個PNG檔案都必須包含它們。 它們分別是長度,資料塊型別碼,資料塊資料,迴圈冗餘檢測即CRC。 我們這裡重點先了解一下,png圖片檔案頭資料塊以及png圖片IDAT塊,這次的隱寫也是以這兩個地方位基礎的。png圖片檔案頭資料塊 即IHDR,這是PNG圖片的第一個資料塊,一張PNG圖片僅有一個IHDR資料塊,它包含了哪些資訊呢?IHDR中,包括了圖片的寬,高,影象深度,顏色型別,壓縮方法等等。
下面進行實驗Part 2 基於檔案結構的隱寫
高度被修改引起的隱寫
背景知識中,我們瞭解到,圖片的高度,寬度的值存放於PNG圖片的檔案頭資料塊,那麼我們就是可以通過修改PNG圖片的高度值,來對部分資訊進行隱藏的。
- 實驗:
- 在實驗機中找到隱寫術目錄,開啟圖片隱寫,開啟圖片隱寫第二部分資料夾
- 在該資料夾找到 hight.png,
- 雙擊開啟圖片,我們先確認一下圖片內容並沒有什麼異常
- 正如前文所說,我們這個實驗部分講的是圖片高度值被修改引起的的隱寫方式,所以我們010Editor
- 在010Editor執行PNG模板,這樣方便於我們修改PNG圖片的高度值
- 找到PNG圖片高度值對應的地方,然後修改為一個較大的值,並重新計算,修改CRC校驗值,並儲存檔案
- 開啟儲存後的圖片,發現底部看到了之前被隱寫的資訊
用010Editor開啟圖片,執行PNG模板 10 editor呢?因為這個16進位制編輯器,有模版功能,當我們執行模版後,可以輕易的找到圖片的各個資料塊的位置以及內容。
10 editor這個16進位制編輯器,有模版功能,當我們執行模版後,可以輕易的找到圖片的各個資料塊的位置以及內容。找到PNG圖片高度值所對應的位置,並修改為一個較大的值
我們找到IHDR資料塊,並翻到struct IHDR Ihdr位置,修改height的值到一個較大的值,如從700修改到800。使用CRC Calculator重新計算CRC校驗值
輸入引數,然後點選Calculator計算,得到CRC值 為什麼要重新計算CRC校驗值呢?防止圖片被我們修改後,自身的CRC校驗報錯,導致圖片不能正常開啟。
思考
這個實驗,我們進行了PNG圖片高度修改以及CRC校驗值的重計算,那麼請大家以下問題
- JPG圖片是否也有這樣的隱寫形式呢?
- 瞭解JPG以及GIF等圖片檔案的格式。
隱寫資訊以IDAT塊加入圖片
在背景知識中,我們提到了一個重要的概念就是圖片的IDAT塊是可以存在多個的,這導致了我們可以將隱寫西資訊以IDAT塊的形似加入圖片。
- 實驗:
- 在實驗機中找到隱寫術目錄,開啟圖片隱寫,開啟圖片隱寫第二部分資料夾
- 在該資料夾找到 hidden.png,
- 雙擊開啟圖片,我們先確認一下圖片內容並沒有什麼異常
- 使用pngcheck先對圖片檢測
- 在pngcheck的檢測下,我們會發現異常資訊,我們對異常的塊進行提取
- 編寫指令碼,提取異常資訊
前景知識 pngcheck可以驗證PNG圖片的完整性(通過檢查內部CRC-32校驗和&bra;位元&ket;)和解壓縮影象資料;它能夠轉儲幾乎所有任選的塊級別資訊在該影象中的可讀資料。 我們使用pngcheck -v hidden.png 如此的命令對圖片進行檢測
使用pngcheck對圖片進行檢測
pngcheck -v hidden.png
對圖片的檔案結構進行檢測。
發現異常,並判斷異常的原因 我們會發現,圖片的的資料塊形式是如下的 Type: IHDR Size: 13 CRC : 5412913F
Pos : 33 Type: IDAT Size: 10980 CRC : 98F96EEB
Pos : 11025 Type: IEND Size: 0 CRC : AE426082
我們會驚訝的發現pos為11025的size居然為0,這是一塊有問題的地方,我們可以懷疑,這一塊是隱寫的資訊。編寫指令碼並提取內容
#!/usr/bin/python
from struct import unpack
from binascii import hexlify, unhexlify
import sys, zlib
# Returns [Position, Chunk Size, Chunk Type, Chunk Data, Chunk CRC]
def getChunk(buf, pos):
a = []
a.append(pos)
size = unpack('!I', buf[pos:pos+4])[0]
# Chunk Size
a.append(buf[pos:pos+4])
# Chunk Type
a.append(buf[pos+4:pos+8])
# Chunk Data
a.append(buf[pos+8:pos+8+size])
# Chunk CRC
a.append(buf[pos+8+size:pos+12+size])
return a
def printChunk(buf, pos):
print 'Pos : '+str(pos)+''
print 'Type: ' + str(buf[pos+4:pos+8])
size = unpack('!I', buf[pos:pos+4])[0]
print 'Size: ' + str(size)
#print 'Cont: ' + str(hexlify(buf[pos+8:pos+8+size]))
print 'CRC : ' + str(hexlify(buf[pos+size+8:pos+size+12]).upper())
print
if len(sys.argv)!=2:
print 'Usage: ./this Stegano_PNG'
sys.exit(2)
buf = open(sys.argv[1]).read()
pos=0
print "PNG Signature: " + str(unpack('cccccccc', buf[pos:pos+8]))
pos+=8
chunks = []
for i in range(3):
chunks.append(getChunk(buf, pos))
printChunk(buf, pos)
pos+=unpack('!I',chunks[i][1])[0]+12
decompressed = zlib.decompress(chunks[1][3])
# Decompressed data length = height x (width * 3 + 1)
print "Data length in PNG file : ", len(chunks[1][3])
print "Decompressed data length: ", len(decompressed)
height = unpack('!I',(chunks[0][3][4:8]))[0]
width = unpack('!I',(chunks[0][3][:4]))[0]
blocksize = width * 3 + 1
filterbits = ''
for i in range(0,len(decompressed),blocksize):
bit = unpack('2401c', decompressed[i:i+blocksize])[0]
if bit == '\x00': filterbits+='0'
elif bit == '\x01': filterbits+='1'
else:
print 'Bit is not 0 or 1... Default is 0 - MAGIC!'
sys.exit(3)
s = filterbits
endianess_filterbits = [filterbits[i:i+8][::-1] for i in xrange(0, len(filterbits), 8)]
flag = ''
for x in endianess_filterbits:
if x=='00000000': break
flag += unhexlify('%x' % int('0b'+str(x), 2))
print 'Flag: ' + flag
指令碼如上,flag DrgnS{WhenYouGazeIntoThePNGThePNGAlsoGazezIntoYou}.
思考
- 我們是否可以將一張二維碼以IDAT塊的形式寫入圖片呢?
- 試著將資訊以IDAT塊的形式寫入圖片
儲存後,重新開啟圖片,我們就能看到被隱藏的內容
歸檔.zip (0.414 MB) 下載附件