壓縮包作為misc中比較基礎的一個考點,經常出現在各種比賽的misc方向中,如果沒有一定的了解看到一層一層的壓縮包難免會頭痛。那么這里來簡單的總結一下ctf中關於壓縮包的一些考點。
CTF 壓縮包總結 - Chi4ki - 博客園 (cnblogs.com)
工具准備
Wenhex或相似的16進制編輯器,ARCHPR(4.53或4.54最好),python環境和zipfile庫。
暴力破解
通常這類題目會有密碼幾位數或有哪些符號的提示,只要給的不是很復雜的提示(比如密碼是32位),就可以確定是暴力破解,用ARCHPR勾選對應的選項破解就可以了。
掩碼爆破
其實和暴力破解相同,只是由於密碼可能在一個范圍內或者有一些字符確定,如我們已知密碼開頭是Ctf,后面是6位數字,那么掩碼設置中寫為Ctf??????,然后爆破即可。
字典爆破
對應的是弱口令密碼的爆破,ARCHPR需要自己提供字典文件,然后就會將字典中的所有密碼嘗試爆破。有的題目會直接給字典文件,還有的則是需要自己去網上查找,需要注意有的弱口令密碼相對並不簡單(如123123@@@),要找一個比較全的字典。
偽加密
zip文件中,文件頭和文件核心目錄區50 4B 01 02(目錄中文件文件頭標記)、1E 03(壓縮使用的pkware版本)、14 00(解壓文件所需pkware版本)后即是壓縮軟件識別未加密標志,奇數代表加密,偶數代表無加密。將00 00改為09 00后再次打開壓縮包,就會顯示需要密碼,然而事實上壓縮包並未設置密碼,所以這樣的手段就被稱為zip偽加密。而在這種時候只需要用16進制編輯器如wenhex打開壓縮包,搜索504B0102,將其后的09 00改為00 00,便可解壓壓縮包。
注意的是由於有的zip壓縮包中有多個文件,需要對所有顯示加密的文件進行修改。
CRC32爆破
循環冗余校驗(CRC)是一種產生簡短固定位數校驗碼的信道編碼技術,主要用來檢測或校驗數據傳輸或者保存后可能出現的錯誤。CRC32 即是會產生一個32 bit的校驗值,由於 CRC32 產生校驗值時源數據塊的每一個bit都參與了計算,所以數據塊中即使只有一位發生了變化,也會得到不同的 CRC32 值。而這也就導致了基於 CRC32 的攻擊手法。
例題:buuctf zip
用如下腳本爆破(摘自網上的腳本並做了一些修改,類似的題目調整一下都可以使用)
import zipfile import string import binascii def CrackCrc(crc): for i in dic: for j in dic: for k in dic: for h in dic: s = i + j + k + h if crc == (binascii.crc32(s.encode())): f.write(s) return def CrackZip(): for i in range(0,68): file = 'out'+str(i)+'.zip' crc = zipfile.ZipFile(file,'r').getinfo('data.txt').CRC CrackCrc(crc) print('\r'+"loading:{:%}".format(float((i+1)/68)),end='') dic = string.ascii_letters + string.digits + '+/=' f = open('out.txt','w') CrackZip() f.close()
明文攻擊
在傳統的zip加密中,文件會根據口令生成3個密鑰來加密文件,所以假如獲得與壓縮包中相同的文件(判斷方式是CRC32是否相同),則可以將獲得的文件進行未加密壓縮,通過一定的手段將加密與未加密文件進行對比從而求出3個加密密鑰,雖然並不一定能解出口令,但也足夠可以獲得其中的文件。
比賽中除了直接給相同的文件外,還有可能是要求自己查找構造明文,對應的難度會高上很多,比如設置的明文是github上的一個文件。
同時由於不同壓縮軟件之間壓縮方式的不同,構造明文的壓縮方式如果不相同則可能無法解出,這種時候我們需要將常見的幾種壓縮方式都進行嘗試。
還要補充的一點是,ARCHPR的版本也會有影響。對於同樣的一道題目,用4.00版本沒有解出來,用4.53很快出現結果,而4.54則會顯示要很長時間,但十幾秒后手動暫停就會顯示解出。
python腳本類題目
在許多比賽中會有幾百層壓縮包的題目,有的是名字就是密碼或者沒有密碼但文件非常大,還有的則是額外需要爆破。形式上有的是壓縮包套壓縮包,有的則是一次性好多個壓縮包,對於這類題目,我們往往需要利用python的zipfile庫來寫腳本爆破。
例題:[MRCTF2020]千層套路
一個套娃的壓縮包,每一個壓縮包的名字就是它的密碼,寫如下腳本解出:
import zipfile zip_src='0573.zip' while(1): r = zipfile.is_zipfile(zip_src) if r: fz = zipfile.ZipFile(zip_src,"r") fz.extractall(pwd=bytes(zip_src[0:4],'utf-8')) zip_src=fz.filelist[0].filename else: break
打開后是三個一組的數字,看到255和0猜到是顏色且對應二維碼。用python的PTL庫寫腳本得到是一個二維碼,再用軟件QR Research掃碼,得到flag。