def getPrefixLength(url: str, blockSize: int = None): if not blockSize: blockSize = getBlockSize(url) prev = b64decode(getSession().post(url=url, data=b64encode(b'a')).content) prev2 = b64decode(getSession().post(url=url, data=b64encode(b'b')).content) blockI = 0 for i in range(int(len(prev) / blockSize)): if prev[i * blockSize:(i + 1) * blockSize] != prev2[i * blockSize:(i + 1) * blockSize]: blockI = i break for i in range(2, blockSize + 1): cur = b64decode(getSession().post(url=url, data=b64encode(b'a' * i)).content) if cur[blockI * blockSize:(blockI + 1) * blockSize] == prev[blockI * blockSize:(blockI + 1) * blockSize]: return blockSize * blockI + blockSize - i + 1 prev = cur return blockSize * blockI
def decryptOneOraclePadding(toDecrypt: bytes, IV: bytes, nb: int, url: str) -> (bytes, bytes): nb += 1 for i in range(0x00, 0xFF+1): iv = IV[:-nb] + bytes([i]) + bytes([b ^ nb for b in IV[-(nb-1):]] if nb != 1 else []) res = getSession().post(url=url, data=b64encode(iv)+b'\n'+b64encode(toDecrypt)) if res.ok: #if nb == 0: # iv = IV[:-nb] + bytes([i+1]) + bytes([b ^ nb for b in IV[-(nb-1):]] if nb != 1 else []) # res = getSession().post(url=url, data=b64encode(iv)+b'\n'+b64encode(toDecrypt)) return bytes([i^nb]), bytes([i^IV[-nb]^nb])
def getNthByte(n: int, blockSize: int, alreadyDecrypt: bytes, url: str) -> bytes: sess = getSession() blockNb = math.ceil((n + 1) / blockSize) block = b'A' * (blockSize * blockNb - (n + 1)) expected = b64decode(sess.post(url=url, data=b64encode(block)).content) block += alreadyDecrypt for v in range(0x00, 0xFF + 1): result = b64decode( sess.post(url=url, data=b64encode(block + bytes([v]))).content) if expected[(blockNb - 1) * blockSize:blockNb * blockSize] == result[(blockNb - 1) * blockSize:blockNb * blockSize]: return bytes([v])
def insertWithAES_CBC(toInsert: bytes, prefixLength: int, url: str, blockSize: int = None): if not blockSize: blockSize = getBlockSize(url) extraLen = len(toInsert) extraLenRounded = math.ceil(extraLen / blockSize) * blockSize blockSize = extraLenRounded * 2 + (blockSize - (prefixLength % blockSize)) data = b'Z' * (blockSize) result = list( b64decode(getSession().post(url=url, data=b64encode(data)).content)) for i in range(extraLen): result[prefixLength + blockSize - extraLenRounded - extraLen + i] ^= ord(b'Z') ^ toInsert[i] return bytes(result)
# res = getSession().post(url=url, data=b64encode(iv)+b'\n'+b64encode(toDecrypt)) return bytes([i^nb]), bytes([i^IV[-nb]^nb]) def oraclePadding(encrypt: bytes, IV: bytes, url: str) -> bytes: blockSize = len(IV) nbBlock = math.ceil(len(encrypt) / blockSize) decrypt = b'' for i in range(nbBlock-1, -1, -1): iv = IV if i == 0 else encrypt[(i-1)*blockSize:i*blockSize] toDecrypt = encrypt[i*blockSize:(i+1)*blockSize] for j in range(blockSize): usedXor, l = decryptOneOraclePadding(toDecrypt, iv, j, url) iv = iv[:-j-1] + usedXor + (iv[-j:] if j != 0 else bytes([])) decrypt = l + decrypt return unpad(decrypt) from sys import stderr, exc_info if __name__ == '__main__': try: data = getSession().get(url=URL+"challenge14/encrypt").content data = data.split(b'\n') IV = b64decode(data[0]) cypher = b64decode(data[1]) data = oraclePadding(cypher, IV, url=URL+'challenge14/decrypt') print(b64encode(data).decode()) except: print(str(exc_info()[1]).capitalize(), file=stderr) exit(84)
#! /usr/bin/env python3 import math from base64 import b64decode, b64encode from networkUtil import URL, getSession, getBlockSize from sys import exc_info, stderr if __name__ == '__main__': try: blockSize = getBlockSize(URL+'challenge11/new_profile') strSize = blockSize - 23 + len(r'user') - len(b'@caesar.com') while strSize < 0: strSize += blockSize s = b'a' * strSize + b'@caesar.com' strSize2 = blockSize - 6 + len(b'admin') while strSize2 < 0: strSize2 += blockSize s2 = b'a' * (strSize2 - len(b'admin')) + b'admin' + bytes([blockSize-5]) * (blockSize-5) part1 = b64decode(getSession().post(url=URL+'challenge11/new_profile', data=b64encode(s)).content)[:strSize+30] part2 = b64decode(getSession().post(url=URL+'challenge11/new_profile', data=b64encode(s2)).content)[strSize2+1:strSize2+1+blockSize] print(getSession().post(url=URL+'challenge11/validate', data=b64encode(part1+part2)).content.decode()) except: print(str(exc_info()[1]).capitalize(), file=stderr) exit(84)
prefixLength: int, url: str, blockSize: int = None): if not blockSize: blockSize = getBlockSize(url) extraLen = len(toInsert) extraLenRounded = math.ceil(extraLen / blockSize) * blockSize blockSize = extraLenRounded * 2 + (blockSize - (prefixLength % blockSize)) data = b'Z' * (blockSize) result = list( b64decode(getSession().post(url=url, data=b64encode(data)).content)) for i in range(extraLen): result[prefixLength + blockSize - extraLenRounded - extraLen + i] ^= ord(b'Z') ^ toInsert[i] return bytes(result) from sys import stderr, exc_info if __name__ == '__main__': try: blockSize = getBlockSize(URL + 'challenge13/encrypt') prefixLength = getPrefixLength(URL + 'challenge13/encrypt', blockSize) data = insertWithAES_CBC(b';admin=true;', prefixLength, URL + 'challenge13/encrypt', blockSize) print(getSession().post(url=URL + 'challenge13/decrypt', data=b64encode(data)).content.decode()) except: print(str(exc_info()[1]).capitalize(), file=stderr) exit(84)