#!/usr/bin/env python2 """ http://robertheaton.com/2013/07/29/padding-oracle-attack/ """ import urllib2, sys, encodings class PaddingOracle(object): def __init__(self): self.TARGET = 'http://crypto-class.appspot.com/po?er=' def query(self, q): target = self.TARGET + urllib2.quote(q) req = urllib2.Request(target) try: f = urllib2.urlopen(req) except urllib2.HTTPError, e: if e.code == 404: return True # good padding return False # bad padding def ct(): return "f20bdba6ff29eed7b046d1df9fb7000058b1ffb4210a580f748b4ac714c001bd4a61044426fb515dad3f21f18aa577c0bdf302936266926ff37dbf7035d5eeb4".decode("hex") assert len(ct()) == 64 def listify(s): ret = [] for c in s: ret.append(c) return ret assert listify("abc") == ['a','b','c'] def guesses(): for i in range(0,256): yield chr(i) assert [ord(x) for x in guesses()] == [x for x in range(0,256) ] def hammer(g, i, l, it, offset): c = listify(ct()[0:l]) c[i+offset] = g pad = 16 - i for x in range(i+1, 16): c[offset+x] = chr( ord(it[x]) ^ pad ) c = ''.join(c).encode('hex') return PaddingOracle().query(c) def hack(block): offset=block - 32 it = [" "] * 16 pt = [" "] * 16 for i in xrange(15, -1, -1): print i isol = "" for g in guesses(): if hammer(g, i, block, it, offset): isol = g break if isol == "": break print "found isol %d" % ord(isol) it[i] = chr( (16-i) ^ ord(isol) ) pt[i] = chr( ord(ct()[i+offset]) ^ ord(it[i]) ) return ''.join(pt) answer="" for block in (32, 48, 64): print "block %d" % block answer = answer + hack(block) print answer