-
Notifications
You must be signed in to change notification settings - Fork 262
/
Copy pathexploit.py
102 lines (88 loc) · 2.89 KB
/
exploit.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
from Crypto.Cipher import AES
from SocketServer import ThreadingMixIn
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
import sys
class Hasher:
def __init__(self):
self.aes = AES.new('\x00'*16)
def reset(self):
self.state = '\x00'*16
def ingest(self, block):
"""Ingest a block of 10 characters """
block += '\x00'*6
state = ""
for i in range(16):
state += chr(ord(self.state[i]) ^ ord(block[i]))
print "Before:", state.encode("hex")
self.state = self.aes.encrypt(state)
print "After:", self.state.encode("hex")
def final_ingest(self, block):
"""Call this for the final ingestion.
Calling this with a 0 length block is the same as calling it one round
earlier with a 10 length block.
"""
if len(block) == 10:
self.ingest(block)
self.ingest('\x80' + '\x00'*8 + '\x01')
elif len(block) == 9:
self.ingest(block + '\x81')
else:
self.ingest(block + '\x80' + '\x00'*(8-len(block)) + '\x01')
def squeeze(self):
"""Output a block of hash information"""
result = self.state[:10]
self.state = self.aes.encrypt(self.state)
return result
def hash(self, s):
"""Hash an input of any length of bytes. Return a 160-bit digest."""
self.reset()
blocks = len(s) // 10
for i in range(blocks):
self.ingest(s[10*i:10*(i+1)])
self.final_ingest(s[blocks*10:])
return self.squeeze() + self.squeeze()
def main():
HASHER = Hasher()
GIVEN = 'I love using sponges for crypto'
TARGET = HASHER.hash(GIVEN)
D='cba5d1139c347a3c6fc8afcfecd21a8d'.decode("hex")
# AES(AES(a) xor b) xor c = D
# AES(AES(a) xor b) = D xor c
aes=AES.new("\x00"*16)
print "Precalculating..."
if 0:
poss={}
for i in xrange(2**24):
if i%100000==0:
print i,"/",2**24
c=str(i)
c=c+(16-len(c))*"\x00"
D_xor_c="".join(chr(ord(q1)^ord(q2)) for q1, q2 in zip(D, c))
preimage=aes.decrypt(D_xor_c)
suffix=preimage[10:]
poss[suffix]=(preimage, c)
# AES(a) xor b is in poss set
# Let's brute force a, and check if it has good suffix.
for i in xrange(2**32):
if i%100000==0:
print i,"/",2**24
a=str(i)
a=a+(16-len(a))*"\x00"
aes_a=aes.encrypt(a)
suffix=aes_a[10:]
if suffix in poss:
print i, poss[suffix]
break
# Precalculated values...
a=10935004
a=str(a)
a=a+(16-len(a))*"\x00"
aes_a=aes.encrypt(a)
preimage='bI\xa5\xb2}*\xe5k\xbe\xad\xf3+\x86\\\x80\x07'
c='10779991\x00\x00\x00\x00\x00\x00\x00\x00'
b="".join(chr(ord(q1)^ord(q2)) for q1, q2 in zip(preimage, aes_a))
text=a[:10]+b[:10]+c[:10]+"o"
myhash=HASHER.hash(text)
print "Hashes equal:", (TARGET)==(myhash)
print "Input:", text.encode("hex")
main()