作業題目
本次實驗主要是加深大家對MD5碰撞及其原理的理解,使用SEED實驗環境中的工具及程式語言,完成以下任務:
- 使用md5collgen生成兩個MD5值相同的檔案,並利用bless十六進位制編輯器檢視輸出的兩個檔案,描述你觀察到的情況;
- 參考Lab3_task2.c的程式碼,生成兩個MD5值相同但輸出不同的兩個可執行檔案。
- 參考Lab3_task3.c的程式碼,生成兩個MD5值相同但程式碼行為不相同的可執行檔案。
- 回答問題:透過上面的實驗,請解釋為什麼可以做到不同行為的兩個可執行檔案具有相同的MD5值?
實驗步驟及結果
A.
生成一個名為test測試txt檔案,往裡面存入字串“hello”,使用md5collgen生成兩個檔案out1.bin,out2.bin.
這兩個檔案不同,但md5值相同。
md5演算法以64個位元組為一組來處理輸入,用bless檢視out1.bin,out2.bin:
可以發現,輸入不足64個位元組(或不是64的倍數)時,md5collgen會給輸入自動補零。
用test2.txt再測試,test2.txt中有63個字元,加上結束符,一共64個位元組作為輸入。
用bless再檢視md5collgen生成的檔案outfile1.bin,這次沒有補零。
檢視out1.bin和outfile1.bin的內容:
可以發現,除了我們寫到txt裡的內容,md5collgen又加入了一些東西使生成的兩個檔案內容不同但md5值相同。
用bless開啟out1.bin檢視:
可以發現,這段加入的內容一共128個位元組。
在out1.bin和out2.bin中,加入相同的字串“world”:
發現兩個檔案md5值仍然相同,所以,在兩個md值相同的檔案中分別加入相同的內容,新的兩個檔案md5值仍然相同。
B.
透過A實驗得到的3個技巧可以完成B實驗。
修改程式碼(方便確定陣列內容所在位置):
編譯c程式碼為task2:
用bless開啟task2,找到陣列內容開始的位置在檔案的第12320個位元組處。
要保證最後得到的是可執行的檔案,就要保證md5collgen的輸入是64位元組的倍數(不能自動補零)。
所以,取task2前12352個位元組為prefix,留出128個位元組的位置(md5collgen會在生成檔案的末尾加上128個位元組),取第12480個位元組後的內容為suffix。
用prefix作為md5collgen的輸入,生成兩個md5值相同的檔案o1.bin,o2.bin。
取出這兩個檔案的後128個位元組為P,Q。
將prefix,P/Q,suffix合併為pro1/pro2,執行,pro1和pro2輸出內容不同,md5值相同。
也可以用o1.bin和o2.bin直接和suffix拼接:
兩種方法得到的可執行檔案相同:
完善task3程式碼,x和y內容相同就執行良性程式碼,內容不相同就執行惡性程式碼:
編譯c程式碼為task3:
用bless檢視task3,找到陣列開始的位置(12320)
用前12352個位元組作為md5cllgen輸入,得到o1.bin,o2.bin:
用bless檢視o1.bin:
發現陣列內容對應o1.bin最後160個位元組(陣列x前面的一部分)。
取這最後160個位元組為P。
從task3中取第12480後的全部位元組為suffix:
用bless檢視suffix:
將suffix分割成三部分,a1(陣列x剩下的部分),中間部分(陣列y前面的一部分,和P位元組相同),a2(檔案剩餘全部):
將中間部分替換為P,得到新的suffix_f:
再將suffix_f分別與o1.bin和o2.bin拼接,得到pro1,pro2。
pro1,pro2行為不相同,md5值卻相同。
D.
md5的輸出是128bit的值,一共有2的128次方種不同的可能,但md5的輸入卻是無限可能的,所以,不同的輸入資料也可以對映到相同的md5值上。
對於兩個可執行檔案,我們只改變對應程式碼中陣列內容的部分,而不改變程式碼結構,再利用if判斷陣列內容來選擇不同的行為,這樣就可以使它們md5值相同但行為不同了。