cryptopals解密之旅(完結篇)

由於微信文章的排序規則變化,小夥伴們可能錯過了不少我們的優質技術乾貨;怎麼才能及時接收到推送嘞,點擊上方的藍字“合天智匯“,星標置頂吧。

文章回顧:

cryptopals解密之旅 (一)

cryptopals解密之旅 (二)

cryptopals解密之旅 (三)

0x00前言

本系列文章將帶來cryptocals 這套密碼學挑戰的write-up.不同於通過上課或者看書的方式學習密碼學,這些題目來自於現在生活中一些軟件系統和密碼構造中的缺陷。

本系列每一個題的wp基本是採用如下結構:題目解釋、相關知識點講解、代碼實現及解釋,運行測試。代碼均採用python3實現,代碼實現部分是參考國外大佬ricpacca的,結合自己的理解及成文需要進行部分修改。

第二套一共有八關。

第二套題目

主要是和分組密碼相關的

  • 0x05

第13題

要求寫一個函數profile_for,傳入profile_for("[email protected]"),會生成

{
  email: '[email protected]',
  uid: 10,
  role: 'user'
}
編碼爲[email protected]&uid=10&role=user

注意,不需要編碼@,&等符號

接着生成隨機的AES密鑰,然後用這個密鑰加密編碼後的用戶信息,再解密得到編碼的結果,然後解析編碼的結果。

題目要去我們僅使用user和密文,要求進行攻擊,使得解密,解碼後得到的role是admin,而不是user

這種攻擊方法的原理利用的是ECB模式分塊單獨加密,之後按照順序將計算所得的數據連在一起即可,各段數據之間互不影響的特點。通過將故意構造的密文替換原密文,從而篡改解密後的信息。

具體代碼如下:

定義加密函數,使用AES-128-ECB加密編碼過的用戶信息,以及對應的解密函數

使用key=value鍵值對的格式將字典對象編碼爲字符串,比如將

    {
        foo: 'bar',
        baz: 'qux',
        zap: 'zazzle'
}
編碼爲
foo=bar&baz=qux&zap=zazzle

寫一個對應的解碼函數,將key-value格式解碼爲字典格式

給出email地址,按指定規則進行格式化,下圖中的replace是爲了刪除原有的&,=

下圖的函數是關鍵,通過cut-and-paste攻擊,將部分user的原密文替換成admin的。然後返回重新組合後的密文。

第一次加密的明文分爲三個塊,第一個塊爲email=xx..xx將這個填充成一個塊,第二個塊爲admin,然後根據pkcs#7填充規則,還需填充11個\x0b,第三個塊爲&uid=10&role=user

第二次加密的明文分爲三個塊。

第一個塊爲email=master@me.,

第二個塊爲com&uid=10&role=,

第三個塊爲user\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c

接下來我們組合三個塊成新的密文,

第一個塊爲email=master@me.,
第二個塊爲com&uid=10&role=,
第三個塊爲admin\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b。函數返回的就是這三個塊組成的密文。

該密文被解密,然後解碼後,得到的role就會是就會是admin而不是user

完整代碼及執行結果如下所示

  • 0x06

第14關

這一關比第12關難度大。要求我們生成隨機數量的隨機字符,作爲明文的前綴。

還是要求我們拿到target-bytes的明文

思路就是:

1.首先找到塊長度、加密模式,這些在12題裏實現過了

2.找到前綴長度

3.一次一個byte解密target-byte,這在12題也實現了

加密函數加密的內容就是隨機前綴+可控字符串+未知字符串

找到target-byte的一個字節。填充length_to_use個a,保證將塊的最後一個字符設置爲target-byte的第一個字符。然後計算我們將截取多少個字節進行比較,這個值在後面比較假的密文和實際密文時會用到。計算實際密文,然後暴力測試每個可能的字符,將每個可能字符加密後得到的密文與實際密文比較

檢查給出的密文是否包含兩個連續的相同塊

計算前綴的長度。首先找到前綴在哪個塊結尾,然後找到前綴結尾的精確位置,就可以計算出前綴的長度

首先分別加密空消息和一個字符的消息,得到兩個密文。比較這兩個密文,第一個不同的塊就是前綴結束的塊。然後需要精確定位是在前綴是在哪個位置結束的。

加密“兩個塊長度+一個隨機增量”長度大小的相同的字節,如果字節數足夠了(在密文中找到了兩個連續的相同塊),我們就可以精確計算前綴在其最後一個塊中結束的位置。其在最後一塊中結束的位置爲塊長度-i

找到塊長度,判斷是否爲ECB模式,計算出target-byte的長度,這就是循環的次數。在循環中調用get_next_byte來計算。target-byte長度等於加密空字符串後的長度減去前綴長度

完整代碼及執行結果如下

拿到了target-bytes的明文

  • 0x07

第15題

要求實現一個函數,可以檢測一段明文是否爲pkcs#7填充,如果是話則去掉填充,不是的話則報異常

這個函數在s2p9.py中已經實現過了,這裏不再重複。

  • 0x08

第16關

cbc翻轉攻擊,這個知識點在CTF中也有出現過,那麼我們看看脫去CTF的外衣,其本質是怎樣的

題目要求首先生成隨機的AES密鑰

寫一個函數接收任意輸入字符串,加上前綴"comment1=cooking%20MCs;userdata=",加上後綴";comment2=%20like%20a%20pound%20of%20bacon",去掉;和=

然後,該函數應將輸入填充到16字節AES塊長度,並在隨機AES密鑰下對其進行加密。

寫一個函數解密該字符串並查找“; admin = true; “。根據字符串是否存在,返回true或false。如果上一個函數正確實現,則第二個函數會返回false。實際上,可以進行cbc翻轉攻擊,使其返回true。我們通過修改密文來實現這一點(無需密鑰)。

CBC翻轉攻擊技術可以通過修改密文來操縱解密後的明文。其原理就是如果對初始化向量中的任意比特進行反轉,則明文分組中相應的比特也會反轉,其原因是第一個明文分組會和初始化向量進行異或運算。

這樣我們所要做的就是對初始化向量進行攻擊。

在下面的cbc_bit_flip中我們攻擊的就是;和=

代碼實現:

實現加密函數,添加前綴和後綴後,使用AES-128-CBC進行加密

實現解密函數,還會檢查解密後的內容中是否有;admin=true;

計算塊長度。要找到一個塊的長度,我們需要加密越來越長的明文,直到輸出密文的大小也增加爲止。發生這種情況時,我們可以輕鬆地計算出塊的長度,其值等於新的密文長度與其初始長度之間的差

計算前綴的長度。

加密兩個不同的明文字節,得到兩個不同的密文,計算兩個密文間相同的長度,賦給common_length,確保其爲塊長度的整數倍。

從1開始將越來越多的相同字節添加到明文中,分別加密,比較兩個密文,直到它們有一個額外的相同塊爲止。如果找到了,這意味着通過添加i個字節,我們可以控制相同的輸入(包括前綴)爲塊大小的整數倍,這樣我們就可以得到前綴的長度了。

cbc翻轉攻擊的關鍵函數

首先得到塊長度和前綴長度,接着計算需要添加多少字節到前綴,才能使得其長度爲塊長度整數倍,接着計算要添加多少字節到明文才能使得其長度爲塊長度整數倍。然後將明文加長1個塊長度(用?填充),對其加密。使用異或的方法,我們可以通過更改明文之前的塊的字節來生成所需的字節。最後將僞造的密文片段放在一起,組成完整的密文

完整代碼及執行結果如下

可知,在解密之後的明文裏確實找到了; admin = true;,返回了true

參考:

1.https://cryptopals.com/sets/1

2.https://github.com/ricpacca/cryptopals

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章