隱寫術總結

wyzsk發表於2020-08-19
作者: AppLeU0 · 2015/02/10 10:14

0x00 前言


之前還沒有見到drops上有關於隱寫術的總結,我之前對於隱寫術比較有興趣,感覺隱寫術比較的好玩。所以就打算總結總結一些隱寫術方面的東西。寫的時候,可能會有錯誤的地方,請不吝賜教,謝謝。

本篇章中用到的隱寫術的圖片,都打包在了這裡:隱寫術圖片,想去自己嘗試一遍的話可以去下載。

最開始接觸到隱寫術,是看到一種叫做圖種的東西,當時不懂,只說要另存為zip,然後解壓出來就可以了,當時覺得特別神奇,就像發現了新大陸,然後就嘗試了一下,發現可以用另存為zip的方式,用7z或者是winzip等工具開啟,然後就可以看到福利了。

enter image description here

圖1.png

後來才懂得了,先製作一個1.zip,把想要隱藏的東西放進去,再需要一張jpg圖片2.jpg,然後就可以執行一個命令 copy /b 2.jpg+1.zip output.jpg。就可以得到一張圖種,這是利用了copy命令,將兩個檔案已二進位制方式連線起來,生成output.jpg的新檔案。而在jpg中,是有結束符的,16進位制是FF D9,利用winhex可以看到正常的jpg結尾都是FF D9的,圖片檢視器會忽視jpg結束符之後的內容,所以我們附加的zip,自然也就不會影響到影像的正常顯示。

enter image description here

圖2.png

這種型別的隱寫也是比較容易被發現的,如果發現是jpg圖片的話,觀察檔案結束符之後的內容,檢視是否附加的內容,正常圖片都會是FF D9結尾的。還有一種方式來發現就是利用binwalk這個工具,在kali下自帶的一個命令列工具。

enter image description here

圖片3.png

利用binwalk可以自動化的分析圖片中附加的其他的檔案,其原理就是檢索匹配檔案頭,常用的一些檔案頭都可以被發現,然後利用偏移可以配合winhex或者是dd分割出隱藏的部分。

0x01 修改資料


上面說到的隱藏方式,是利用了增加資料的方式,把資料直接增加在了jpg後面。還有另一類隱藏的方法,就是利用了修改資料的方式來隱藏自己傳遞的資訊。

一種常見的方式是利用LSB來進行隱寫,LSB也就是最低有效位 (Least Significant Bit)。原理就是圖片中的像數一般是由三種顏色組成,即三原色,由這三種原色可以組成其他各種顏色,例如在PNG圖片的儲存中,每個顏色會有8bit,LSB隱寫就是修改了像數中的最低的1bit,在人眼看來是看不出來區別的,也把資訊隱藏起來了。譬如我們想把’A’隱藏進來的話,如下圖,就可以把A轉成16進位制的0x61再轉成二進位制的01100001,再修改為紅色通道的最低位為這些二進位制串。

enter image description here

圖4.png

enter image description here

圖4.png

如果是要尋找這種LSB隱藏痕跡的話,有一個工具是個神器,可以來輔助我們進行分析。Stegsolve這個軟體的下載地址是

http://www.caesum.com/handbook/Stegsolve.jar

開啟之後,使用Stegsolve——Analyse——Frame Browser這個可以瀏覽三個顏色通道中的每一位,可以在紅色通道的最低位,發現一個二維碼,然後可以掃描得到結果。

enter image description here

圖6.png

再解一下qrcode,用線上的就可以http://tool.chinaz.com/qrcode/,得到了flag{AppLeU0},如果是隱寫的使用了ascii的話,可以使用Stegsolve——Analyse——Data Extract來檢視ascii碼。

在這個過程中,我們要注意到,隱寫的載體是PNG的格式,如果是像之前的jpg圖片的話就是不行的,原因是jpg圖片對像數進行了有損的壓縮,你修改的資訊可能會被壓縮的過程破壞。而PNG圖片雖然也有壓縮,但卻是無損的壓縮,這樣子可以保持你修改的資訊得到正確的表達,不至於丟失。BMP的圖片也是一樣的,是沒有經過壓縮的,可以發現BMP圖片是特別的大的,因為BMP把所有的像數都按原樣儲存,沒有壓縮的過程。

0x02 隱寫與加密


我們先要區分一個概念,隱寫術和加解密的區別。其實說起來很簡單,加解密的話,就是會出現一些神秘的,可疑的字串或者是資料之類的。而隱寫術的話,就是資訊明明就在你的面前,你卻對他視而不見。隱寫術在CTF中出現時,常常會和加解密結合起來一起出現,或者是一些編碼方式一起出現,以提高題目的難度。

用一個ctf的題目作為例子吧,iscc2014中有一個題目,給了一個名為 此為gif圖片.gif的檔案,開啟發現了報錯。有的時候,會需要我們去修復圖片,這對我們對於圖片的檔案結構要有了解。找到gif的檔案格式,然後對照這個破損的檔案。Gif的圖片格式文件可以檢視這個連結,http://dev.gameres.com/Program/Visual/Other/GIFDoc.htm

enter image description here

圖片8.png

用winhex開啟,我們會發現他和普通的GIF圖片不一樣,頭部缺少了東西,在對比一些文件,會發現是少了GIF8。

enter image description here

圖片9.png

我們手動修復一下,增加GIF8。

enter image description here

圖片10.png

然後瀏覽圖片後會發現,有個PASSWORD一閃而過,gif和別的圖片最大的區別就是gif是動態圖,它是可以由多幀組成的可以順序播放的,有的題就是把播放的時間弄得特別慢,幾乎就不會動的,所以我們可以用工具一幀一幀的觀察圖片。Stegsolve就帶有這種功能。

Stegsolve——Analyse——Frame Brower就可以看到是有8幀的圖片,有點重疊不太好觀察,也可以用Namo_GIF_gr這個工具。得到了PASSWORD is Y2F0Y2hfdGhlX2R5bmFtaWNfZmxhZ19pc19xdW10ZV9zaW1wbGU=。很明顯,這個時候PASSWORD是經過的編碼的,我們可以看到字元範圍是0-9a-Z結尾還有=,所以判斷是base64編碼,解碼得到了catch_the_dynamic_flag_is_qumte_simple。這個就是和編碼方式結合,傳遞一些可疑的資料,隱寫術常常會與加解密或編碼結合在一起,對一些常見的編碼和加密方法也要了解,得到密文的字元範圍和長度能發現這是什麼加密或者是編碼。

0x03 載體


資料在隱藏的時候,我們常常是需要先分析是資料隱藏在哪裡,也就是他在利用是什麼做載體,之後才可以進一步的分析是加密或編碼的。這也就是說我們要對一個圖片的格式要有了解,才能知道哪些地方是可疑的,哪些是可以隱藏起資訊的,會有冗餘的成分在。舉個例子吧,比如給了一個jpg的圖片。除了我們之前說到的隱藏在結束符之後的資訊,jpg圖片還可以把資訊隱藏的exif的部分。exif的資訊是jpg的頭部插入了數碼照片的資訊,比如是用什麼相機拍攝的。這些資訊我們也是可以控制的,用檢視屬性的方式可以修改一部分的資訊,還可以用exif編輯器來進行編輯。Power_exif這個可以用來編輯。

enter image description here

圖片11.png

可以看到flag{AppLeU0},就是需要了解隱藏資訊的地方,隱寫術有的時候難,就是難在了一張圖片有太多的地方可以隱藏資訊了,有的時候根本連隱藏的載體都找不到,在你的眼裡他就是一張正常的圖片。

0x04 程式設計輔助


有一些情況下,我們也是沒有現成的工具來完成的,可以自己寫一些簡單的程式來輔助我們進行分析,或者是加解密。比如sctf的misc400的題目,就需要用到一些簡單的程式設計。題目給出了一個png圖片,需要我們找到有SCTF{}標誌的flag。

這個題需要我們對於png圖片的格式有一些瞭解,先用stegsolve檢視一下,其他的LSB之類的並沒有發現什麼問題,然後看了一下結構發現,有一些異常的IDAT塊。IDAT是png圖片中儲存影像像數資料的塊。Png圖片格式的擴充套件閱讀可以看看這篇

http://www.cnblogs.com/fengyv/archive/2006/04/30/2423964.html

有詳細的介紹。

enter image description here

圖片12.png

可以用pngcheck來輔助我們觀察,可以看得更加清晰。pngcheck.exe -v sctf.png

enter image description here

圖片13.png

可以看到,正常的塊的length是在65524的時候就滿了,而倒數第二個IDAT塊長度是45027,最後一個長度是138,很明顯最後一個IDAT塊是有問題的,因為他本來應該併入到倒數第二個未滿的塊裡。

enter image description here

圖片14.png

我們用winhex把這一部分異常的IDAT塊給扣出來。然後就是要研究研究這個塊是什麼情況,發現了載體之後就是要想辦法找出他的規律。觀察那一部分的資料,可以看到是16進位制的78 9C開頭的,百度一下分析是zlib壓縮的標誌。在png的百度百科裡也可以查到PNG的IDAT是使用從LZ77派生的無損資料壓縮演算法,可以用zlib解壓。那麼就嘗試用zlib來解一下這段資料。Zlib的擴充套件閱讀http://zlib.net/

我們使用python來程式設計,先把那段資料處理一下,儲存成16進位制的。

enter image description here

圖片15.png

得到16進位制的以方便python處理,前面的4位元組是長度 然後是標誌位IDAT 然後開始是資料,直到 D9 CF A5 A8是crc32校驗位。 所以實際的資料是:

789C5D91011280400802BF04FFFF5C75294B5537738A21A27D1E49CFD17DB3937A92E7E603880A6D485100901FB0410153350DE83112EA2D51C54CE2E585B15A2FC78E8872F51C6FC1881882F93D372DEF78E665B0C36C529622A0A45588138833A170A2071DDCD18219DB8C0D465D8B6989719645ED9C11C36AE3ABDAEFCFC0ACF023E77C17C7897667

然後用python來寫zlib解壓

#!python
#! /usr/bin/env python
import zlib
import binascii
IDAT = "789C5D91011280400802BF04FFFF5C75294B5537738A21A27D1E49CFD17DB3937A92E7E603880A6D485100901FB0410153350DE83112EA2D51C54CE2E585B15A2FC78E8872F51C6FC1881882F93D372DEF78E665B0C36C529622A0A45588138833A170A2071DDCD18219DB8C0D465D8B6989719645ED9C11C36AE3ABDAEFCFC0ACF023E77C17C7897667".decode('hex')
#print IDAT
result = binascii.hexlify(zlib.decompress(IDAT))
print result

#print result.decode('hex')

發現解出來了一些3031的字串,30和31是hex的 0和1的編碼,再解一次hex得到一串625長度的01字串。

1111111000100001101111111100000101110010110100000110111010100000000010111011011101001000000001011101101110101110110100101110110000010101011011010000011111111010101010101111111000000001011101110000000011010011000001010011101101111010101001000011100000000000101000000001001001101000100111001111011100111100001110111110001100101000110011100001010100011010001111010110000010100010110000011011101100100001110011100100001011111110100000000110101001000111101111111011100001101011011100000100001100110001111010111010001101001111100001011101011000111010011100101110100100111011011000110000010110001101000110001111111011010110111011011

得到的01 串的長度是625,除以8 除以7 都無法整除,也就是說沒法直接轉換成ascii碼。

enter image description here

圖片16.png

然後發現625 = 25*25,剛好是個正方形的形狀,那麼嘗試一下 把這些01 組成一個正方形 看看是什麼,可以用python的PIL程式設計可以很方便的畫圖,在kali自帶就可以有,win的環境需要安裝PIL的第三方庫。

#!python
#!/usr/bin/env python
import Image
MAX = 25
pic = Image.new("RGB",(MAX, MAX))
str = "1111111000100001101111111100000101110010110100000110111010100000000010111011011101001000000001011101101110101110110100101110110000010101011011010000011111111010101010101111111000000001011101110000000011010011000001010011101101111010101001000011100000000000101000000001001001101000100111001111011100111100001110111110001100101000110011100001010100011010001111010110000010100010110000011011101100100001110011100100001011111110100000000110101001000111101111111011100001101011011100000100001100110001111010111010001101001111100001011101011000111010011100101110100100111011011000110000010110001101000110001111111011010110111011011"
i=0
for y in range (0,MAX):
    for x in range (0,MAX):
        if(str[i] == '1'):
            pic.putpixel([x,y],(0, 0, 0))
        else:
            pic.putpixel([x,y],(255,255,255))
        i = i+1

pic.show()
pic.save("flag.png")

發現是一個二維碼 可以編碼來畫出 0代表了是白色 而1代表了黑色,然後可能會需要旋轉來調整一下,才能掃描出來。處理一下得到了一個二維碼。然後掃描得到了flag。

enter image description here

圖片17.png

enter image description here

圖片18.png

SCTF{(121.518549,25.040854)},成功得到了flag。

在有的情況下,是沒法用現成的工具來處理的,所以就要我們用程式設計來設法解決。Python的PIL是個好東西。批次處理圖片的時候可能會需要它。

0x05 雙圖


還有一種情況是比較特殊的,有的時候會給出兩張圖片,或者是需要你去尋找原來的圖片來進行對比尋找隱藏的資訊。這個一般是因為一張圖片給出來的隱藏資訊太過於隱蔽,無法找不到具體的位置,具體的資訊。這個時候就要用到一些對比的技巧來查詢了。比如ISG2014的misc200就是用到的這種給出了兩張圖的。有的情況下,第二張圖是需要你自己去找到的。

我們來看isg2014-misc200的題,題目給了一張png圖片,png的圖片,就怕裡面插個什麼rar之類的,所以先用linux下的binwalk命令跑一跑。

enter image description here

圖片19.png

跑一跑,發現了有兩個PNG圖片,binwalk會給出偏移,確定了偏移是0x1D55DC之後,用winhex把圖片扣出來,儲存成2.png。原來的圖final.png刪除後面那的一部分,儲存成1.png。肉眼檢視了一下,發現兩張圖片沒有太大的區別,我們用軟體來幫助我們區分他。

enter image description here

圖片20.png

用linux下的命令可以進行對比,生成一個有差異的圖片diff.png。compare 1.png 2.png diff.png 觀察一下發現了左下角有異常,png圖片像數儲存是從左到右,從下往上排列的。

enter image description here

圖片21.png

發現了左下的第二條畫素有異常,對比一下1.png 2.png發現了2.png有問題 那麼我們可以用神器stegsolve來輔助,stegsolve——Analyse——Image Combiner對比兩個檔案。檢視Sub或Xor,可以發現左下角,第二條像數條是有異常的,有紅色的出現。

enter image description here

圖片22.png

把1.png和2.png進行一下sub方法 把結果儲存成solved.bmp。

然後把2.png儲存成2.bmp 24位點陣圖的格式,這個是因為png圖片經過了壓縮,不好直接對比每個位元組,而bmp圖片是沒有壓縮的,直接儲存各個像數點的資料。

這個題還有一個坑點就是偏移的問題 png圖片的掃描是從左向右,從下往上來的。而坑的是這個圖的資訊隱藏並沒有在一開頭的像數,而是是第二行像數,所以就需要利用bmp的優勢,儲存無壓縮,方便尋找到偏移,從而找到資訊隱藏的地方。利用winhex開啟,黑色的像數的在bmp中的hex的00儲存的,那麼我們就尋找不是00的地方。在偏移0x1110的地方可以發現

enter image description here

圖片23.png

有不是00的位元組,一開始還以為這些就是flag的資訊了,後來才發現是因為兩個圖片sub影響到了效果,真正的資訊是隱藏在2.png中的,所以開啟由2.png轉換的2.bmp來對,透過之前diff得到的偏移,尋找到0x1110的地方,直到0x1330結束,這是隱藏的資訊。

enter image description here

圖片24.png

enter image description here

圖片25.png

只保留00 01,這個是因為RGB的關係,只隱藏在R通道里面了,其他通道都是圖片的正常像數資訊,過濾掉就可以了。

00010000010000010001000100000101000100000001010100010101010001010001000000010001000001010001000000010101000001010001000101000001000100010101010100010001000001010001010100010000000100000001000100010100000101010000010100010000000101000101010000000101000000000001010000010101000100010000010000000101000100000001010100000000000100000100000000010101010000010001010101010001

觀察一下可以發現,而奇數位都是0,是多餘的,把這些去除掉。直接把00 替換成0,01替換成1就可以了。

0100100101010011010001110111101101000101001101000111001101011001010111110101001101110100010001010110011100110100011011100011000001100111010100100011010001110000010010000111100101111101

得到了這個之後,可以發現他的長度是184,是8的倍數,把他轉換成ascii碼就可以了。可以使用JPK工具來進行轉換,工具的下載的連結是www.wechall.net/applet/JPK_406.jar。

對比2.bmp可以發現隱藏了一些00 01這些資訊,把這一部分扣出來。

enter image description here

圖片26.png

JPK——binary——binary to ascii

enter image description here

圖片27.png

就得到了flag,ISG{E4sY_StEg4n0gR4pHy}

這種就是利用的兩張圖片對比來尋找差異,從而找到資訊隱藏的地方,這樣子出題往往是因為一張圖片能提供的資訊太少。

0x06 後記


這個總結其實還是缺很多的,因為隱寫術能寫的東西太多了,比如jpg的冗餘資訊的壓縮也可以隱藏進資訊,還有其他的多媒體檔案也可以進行隱寫,例如音訊檔案,影片檔案等等,有很多東西可以研究。一開始是覺得隱寫術特別的有趣才接觸到的,就像是在藏寶尋寶一樣,特別好玩,希望你們也可以感受到這種快樂。歡迎大家和我交流,我的部落格地址是http://appleu0.sinaapp.com/。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章