View difference between Paste ID: JRz7L2z0 and gmKZmS3M
SHOW: | | - or go back to the newest paste.
1
#!/usr/bin/env python2
2
3
import urllib2
4
import sys
5
import subprocess
6
import os
7
TARGET = 'http://crypto-class.appspot.com/po?er='
8
#--------------------------------------------------------------
9
# padding oracle
10
#--------------------------------------------------------------
11
class PaddingOracle(object):
12
    def query(self, q):
13
        target = TARGET + urllib2.quote(q)    # Create query URL
14
        req = urllib2.Request(target)         # Send HTTP request to server
15
        try:
16
            f = urllib2.urlopen(req)          # Wait for response
17
            sys.exit(0)
18
        except urllib2.HTTPError, e:
19
            if e.code == 404:
20
                sys.exit(1)
21
            else:
22
                sys.exit(-1)
23
24
def from_text_pair(code):
25
    assert(len(code)==2)
26
    return int('0x' + code, 16)
27
28
def from_text(text):
29
    assert(len(text) % 2 == 0)
30
    result=[]
31
    for i in range(0,int(len(text)/2)):
32
        l=text[i*2]
33
        h=text[i*2+1]
34
        r=from_text_pair(l+h)
35
        result.append(r)
36
    return result
37
38
def to_hex_byte(b):
39
    h = hex(b)
40
    if not (len(h) == 3 or len(h) == 4):
41
        print "to_hex_byte(%s) problem" % b
42
        sys.exit(0)
43
    def byte(b, i):
44
        return int('0x' + hex(b)[i], 16)
45
    if len(h) == 3:
46
        return '0' + h[-1]
47
    else:
48
        return h[-2] + h[-1]
49
50
def to_hex(t):
51
    return ''.join(map(to_hex_byte, t))
52
53
def to_text(data):
54
    return ''.join(list(map(chr,data)))
55
56
def norm(data):
57
    return to_text(from_text(data))
58
59
def guess(result, IV, C, last=False):
60
    l=len(result)
61
    pl=[]
62
    for g in xrange(0,256):
63
        iv=from_text(IV)
64
        for i in xrange(0,l):
65
            k=i+1
66
            iv[-k] = iv[-k] ^ result[i] ^ (l+1)
67
        m=l+1
68
        iv[-m] = iv[-m] ^ g ^ (l+1)
69
        pl.append(subprocess.Popen(["./padding_oracle.py", (to_hex(iv)+C), "oracle"], cwd=os.getcwd()))
70
    map(lambda p: p.wait(), pl)
71
    rl=map(lambda p: p.returncode, pl)
72
    for_return=[]
73
    for (g,r) in enumerate(rl):
74
        if r == 0:
75
            print "ACCEPTED=%s" % g
76
        elif r == 1:
77
            if (not last) or g != (l+1) or (len(result) and result[0] == (l+1)):
78
                print "PASSED=%s" % g
79
                for_return.append(g)
80
    assert(len(for_return)==1)
81
    return for_return[0]
82
            
83
if __name__ == "__main__":
84
    result=""
85
    if len(sys.argv) == 1:
86
        print >>sys.stderr, "Specify cipher text as argument"
87
        sys.exit(-1)
88
    elif len(sys.argv) == 2:
89
        ORIG=sys.argv[1]
90
        if len(ORIG) % 32 != 0:
91
            print >>sys.stderr, "Invalid cipher text length"
92
            sys.exit(-1)
93
    elif len(sys.argv) == 3 and sys.argv[-1] == "oracle":
94
        po = PaddingOracle()
95
        po.query(sys.argv[1])
96
    else:
97
        print >>sys.stderr, "Specify cipher text as argument"
98
        sys.exit(-1)
99
    block_count=len(ORIG)/32
100
    if block_count < 2:
101
        print >>sys.stderr, "You have just IV, no cypher text given"
102
        sys.exit(-1)
103
    block_count-=1
104
    for i in xrange(0,block_count):
105
        print "Decode block %s/%s" % (i+1, block_count)
106
        a=i*32
107
        b=a+32
108
        c=b+32
109
        IV=ORIG[a:b]
110
        C=ORIG[b:c]
111
        block=[]
112
        while len(block) < 16:
113-
            block.append(guess(block,IV,C,last=(i==block_count+1)))
113+
            block.append(guess(block,IV,C,last=(i+1==block_count)))
114
        if i == 2:
115
            pad = block[0]
116
            block=block[pad:]
117
        text=to_text(reversed(block))
118
        print "Block %s/%s is '%s'" % (i,block_count,text)
119
        result+= "".join(text)
120
    print "Result is '%s'" % result