CTF中的壓縮包
-
壓縮包隐寫
實際上壓縮包本身并不具備隐藏資訊的功能,但由于在CTF競賽中,經常出現壓縮包與隐寫術結合在一起的題目,是以我們需要掌握在CTF競賽中有關壓縮包的題目的常見考察方向及分析手段。
-
winhex
Winhex是一款非常優秀的16進制編輯器,事實上,使用winhex單純進行16進制編譯在某些程度上有些大材小用,市場上很難找到像winhex一樣功能強大的16進制編輯器。當然,它是收費的。本節課我們使用的是winhex的評估版本,可以滿足需要。如果你想對winhex有更深層次的了解,建議您去官方網站上進行咨詢。
-
CTF中常見的壓縮包套路(這些套路也不一定是單獨出現,大多數情況都是組合出現的)
(1) 利用進制轉換隐藏資訊
(2) 作為備援資訊或隐藏資訊藏在其他檔案中,一般是圖檔
(3) 簡單密碼爆破
(4) 字典爆破/掩碼攻擊
(5) 僞加密
(6) 明文攻擊
(7) CRC32碰撞
(8) 檔案修複
(9) 備援資訊拼接
(10)注釋隐藏密碼4. ZIP檔案格式
ZIP檔案一般分為資料區與目錄區。資料區的開頭辨別為504B0304,而目錄區開始的辨別為504B0102,以下兩圖以上面圖檔顯示的壓縮包為例,對檔案格式進行解析。CTF中的壓縮包 CTF中的壓縮包 CTF中的壓縮包
套路一,利用進制轉換隐藏資訊。
1、 打開下載下傳的檔案,進入demo_1,浏覽flag.txt。
2、 分析字元串就會發現,這一長串字元串是十六進制字元串,嘗試十六進制解碼,這裡我使用的是Python進行解碼,雖然輸出了一堆亂碼,但是我們還是能看見存在敏感字元“flag.txt”。
3、其實根據字元串的開頭“504B0304”就可以判斷這串符串是ZIP壓縮檔案的十六進制值。(這個涉及到ZIP檔案格式的詳解,會在後面的僞加密中詳細解釋,隻需記住這是ZIP檔案的檔案辨別頭,為固定值。)
4、 判斷為壓縮包後,将其儲存為ZIP檔案。可以編寫腳本進行十六進制解碼後儲存為ZIP檔案,也可以直接使用winhex,這裡我使用winhex進行儲存。打開winhex後,建立一個空檔案,将十六進制字元串複制,右鍵點選winhex的十六進制資料區,選擇“Edit”->“Clipboard Data”->“Paste”->“ASCII hex”,儲存為ZIP檔案即可,如下圖。
5.、儲存後就可以正常解壓了。
套路二,作為備援資訊隐藏在其他檔案中,将壓縮包提取出來。
-
簡單的隐藏在圖檔後面,即制作圖種。(打開檔案夾demo_2,其中flag.jpg為已經隐藏了壓縮包的圖檔,timg.jpg為原圖檔,heetian_LSB.png為使用了LSB算法隐藏壓縮包的圖檔)
如何實作:使用windows的copy指令即可
2. 使用winhex打開“flag.jpg”,就會發現在jpg圖檔的結束辨別“FFD9”之後,就是ZIP檔案的檔案辨別“504B0304”,而且可以看到flag.txt字樣。
3. 解決方式:直接将圖檔字尾名改為zip,即可解壓。
4. 若是使用隐寫算法隐藏在圖檔中,則需要借助相應的工具,這裡以LSB隐寫算法為例。
使用StegSolve找到隐藏的資訊。
選擇下方的Save Bin,儲存二進制資訊,儲存的字尾名為.zip。
這樣就可以解壓出來了
套路三,簡單密碼爆破
- 使用工具進行爆破,一般需要爆破的壓縮包密碼不會複雜,大部分情況都是純數字,這裡使用ziperello對壓縮包進行爆破。
- 打開ziperello,選擇要解密的壓縮包。
CTF中的壓縮包 - 點選右下角的“NEXT”,然後選擇暴力破解。
CTF中的壓縮包 - 選擇字元集,一般比賽中使用到爆破的,都是純數字的密碼,且長度較短。
CTF中的壓縮包 - 再次“NEXT”,開始爆破,很快密碼就爆破出來了。
CTF中的壓縮包
套路四,掩碼攻擊。
- 掩碼攻擊的意思,就是已知這個壓縮包的密碼格式,比如已知它的密碼長度為六位,前三位為小寫字母,後三位為數字,又或者已經知道這個六位長的密碼第三位為“a”,其它位置有數字也有小寫字母,根據這些已知的條件,來構造一個符合已知條件的字典,将所有可能的結果列出來,進行爆破。
- 進入“demo_4”,先檢視readme.txt。得到如下資訊
3. 打開ziperello,選擇要解密的檔案,第二部選擇“基于模闆的破解”。
4. 根據所得的資訊構造符合條件的模闆,如圖所示,“a”,“A”,“#”分别代表一個字元集,也可以輕按兩下左邊的字元集窗格建構自定義的字元集。密碼模闆中的“a#A#a#”就是符合已知條件的密碼格式。
5. 開始爆破後,很快便得到解壓密碼。
常見套路五,ZIP僞加密。
- 根據實驗開始前的預備知識,我們已經知道ZIP檔案格式中存在兩個加密标志位,前面的加密标志位為資料區的加密标志位,後面的加密标志位為目錄區的加密标志位。所謂僞加密就是修改目錄區的加密标志位,使本來沒有加密的ZIP檔案,在解壓的時候,需要使用者輸入密碼來進行解壓,但是這個密碼又是不存在的。
- 我們以同一個壓縮檔案的無加密、僞加密、真加密三種形式來做比較,如圖,紅色框為資料區加密标志位,綠色框為目錄區加密标志位。從圖中的比較我們可以知道,真加密的ZIP檔案,兩個加密标志位應該都表示加密(一般為前面一位數為奇數即可表示為加密),無加密的ZIP檔案,兩個标志位均表示沒有加密,而僞加密則隻有目錄區的加密标志位表示為加密(為什麼隻有目錄區呢,我們可以測試,隻将資料區的加密标志位改為奇數,選擇解壓檔案時,會發現他還是沒有加密的)。
3. 是以,在判斷一個壓縮檔案為僞加密之後,隻需将其目錄區的加密标志位前面一位改為奇數即可。
4. 進入“demo_5”檔案夾,解壓“flag-僞加密.zip”會發現需要我們輸入密碼才能解壓,使用winhex打開“flag-僞加密.zip”,将圖示的0908改為0808(隻要将9改為偶數即可)。
5. 此時便可以正常解壓
常見套路六,明文攻擊。
- 明文攻擊是一種較為高效的攻擊手段,大緻原理是當你不知道一個zip的密碼,但是你有zip中的一個已知檔案(檔案大小要大于12Byte)時,因為同一個zip壓縮包裡的所有檔案都是使用同一個加密密鑰來加密的,是以可以用已知檔案來找加密密鑰,利用密鑰來解鎖其他加密檔案。在壓縮檔案時輸入的密碼,首先被轉換成3個32bit的key,是以可能的key的組合是2^96,如果用暴力窮舉的方式是不太可能的,除非密碼比較短或者有個厲害的字典。壓縮軟體用這3個key加密所有包中的檔案,所有檔案的key是一樣的,如果我們能夠找到這3個key,就能解開所有的檔案。如果我們找到加密壓縮包中的任意一個檔案,這個檔案和壓縮包裡的檔案是一樣的,我們把這個檔案用同樣的壓縮軟體同樣的壓縮方式進行無密碼的壓縮包(這裡可以通過比較壓縮後檔案的CRC32值來判斷,如果一樣,則使用的是同樣的壓縮方式和軟體),得到的檔案就是我們的Known plaintext(已知明文)。用這個無密碼的壓縮包和有密碼的壓縮包進行比較,分析兩個包中相同的那個檔案,抽取出兩個檔案的不同點,就是那3個key了,如此就能得到key。兩個相同檔案在壓縮包中的位元組數應該相差12個byte,就是那3個key了。雖然我們還是無法通過這個key還原出密碼,但是我們已經可以用這個key解開所有的檔案,是以已經滿足我的要求了,得到其中加密的其他檔案。更詳細的原理請讀者自行谷歌。
- 進入“demo_6”檔案夾,檔案夾中存在一個加密的壓縮包“明文攻擊.zip”和一個“已知明文.jpg”,輕按兩下點開壓縮包,即可看見壓縮包中也存在一個“已知明文.zip”。
3. 我們對“已知明文.jpg”進行無加密的壓縮,然後對比兩個壓縮檔案中“已知明文.jpg”的CRC32值,如果一緻,就可以進行明文攻擊,如果不一緻,則換一種壓縮方式繼續比較。
4. 使用工具進行明文攻擊,這裡使用AZPR進行明文工具。
5. 攻擊成功,得到其他的加密檔案。
常見套路七,CRC32碰撞。
- CRC32:CRC本身是“備援校驗碼”的意思,CRC32則表示會産生一個32bit(8位十六進制數)的校驗值。在産生CRC32時,源資料塊的每一位都參與了運算,是以即使資料塊中隻有一位發生改變也會得到不同的CRC32值,利用這個原理我們可以直接爆破出加密檔案的内容,但是CRC32值也存在被碰撞的可能,也就是會出現内容不一樣但是CRC32值一樣的情況,是以利用CRC32碰撞的方法得知壓縮檔案的内容,一般是在被壓縮的檔案很小的情況下,在CTF中一般為4個位元組。
- 進入“demo_7”檔案夾,檔案夾中存在四個加密的壓縮包,并且有一定的命名順序,readme.txt檔案中表明被壓縮的檔案中的内容為base64編碼的字元串。可以看見每個壓縮檔案内的檔案大小均為四個位元組,即檔案内容為四個位元組長度的字元串。
3. 是以使用CRC碰撞的方法循環碰撞出所有壓縮檔案的内容并按順序拼接即為最終的答案,運作目錄下的CRC32.py腳本,最後會生成一個flag.txt檔案,檔案的内容即為最終的答案。
4. 關于對腳本的解釋,都在代碼的注釋中。
#-*- coding: utf-8 -*_
import zipfile
import string
import binascii
#構造字元集,因為題目提及是base64字元串,是以使用大小寫字母+數字+‘+/=dic = string.ascii_letters + string.digits + '+/='
#具體碰撞CRC的函數
def CrackCRC32(crc_str):
#從字元集中依次取出字元組成四位字元串進行碰撞for i in dic:
for j in dic:
for p in dic:
for q in dic:
s = i +j +p +q
#在Python 2.x的版本中,binascii.crc32所計算出來的CRC值域為[-2^31,2^31-1]之間的有符号整數,為了要與一般CRC結果作比對,需要将其轉為無符号整數,是以加上&Oxffffffff來進行轉換。如果是 Python 3.x的版本,其計算結果為[0,2^32-1]間的無符号整數,是以不需額外加上& Oxffffffff 。
if crc_str ==(binascii.crc32(s)&oxffffffff):
print("Cracking Successfuly")
#碰撞成功後将碰撞出的内容寫入flag.txt檔案中flag.write(s)
return
#選擇ZIP檔案的函數
def CrackZIP():
for i in range(1,5):
file = str(i) + ".zip"#擷取壓縮包中檔案的CRC32值f = zipfile.ZipFile(file, 'r ')
GetCRC32 = f.getinfo(str(i)+ ".txt")
crc_str = GetCRC32.CRC
print("Cracking. . ......" + file)
CrackCRC32(crc_str)
flag = open( 'flag.txt' , 'wb')
CrackZIP()
flag.close
常見套路八,檔案修複
- 這個常見的套路也是跟檔案的格式有關,一般都是修改ZIP檔案的開始辨別,使得在解壓檔案時産生錯誤,無法解壓。
- 進入“demo_8”檔案夾下,嘗試解壓 “flag.zip”,會報錯。
CTF中的壓縮包 - 使用winhex打開這個壓縮檔案進行檢視,會發現檔案頭有些異常,從預備知識中我們知道ZIP檔案的頭部辨別為“504B0304”,且為固定值,是以我們将其修改回來,即可進行正常解壓。
CTF中的壓縮包
常見套路九,備援資訊拼接。
- 從預備知識中我們知道,ZIP壓縮檔案目錄結束辨別位為“504B0506”,且通常帶有18位元組(在預備知識中我們将每個偏移量視作一位,也是一個位元組)的備援資料,總共長度一般為22個位元組,是以這個套路就是将隐藏資訊分為多片隐藏在多個壓縮包的結尾。
- 進入“demo_9”檔案夾下,有四個壓縮檔案,解壓後檔案内容為空。使用winhex打開這些壓縮包,發現每個壓縮包的最後都有三個位元組的備援資料。
CTF中的壓縮包 CTF中的壓縮包 - 将這些備援資料複制取出(選中多出來的資料,右鍵選擇Edit -> Copy Block -> Normally),拼接後得到base64字元串,解碼後得到答案。
常見套路十,注釋隐藏密碼
- 進入“demo_10”檔案夾下,輕按兩下打開flag.zip,會發現旁邊多出了一個注釋框,而這個注釋框隻有在這個壓縮檔案存在注釋的情況下才會顯示。
2. 但是并沒有看見注釋框中有什麼内容,嘗試下拉右邊的下滑條,發現先一個字元串。