Created
December 16, 2018 02:48
-
-
Save ducnhse130201/5c190d2eff7464db370db62b7352db7b to your computer and use it in GitHub Desktop.
matesS3R2(fake_tictactoe)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# https://ed25519.cr.yp.to/python/ed25519.py | |
import hashlib | |
b = 256 | |
q = 2**255 - 19 | |
l = 2**252 + 27742317777372353535851937790883648493 | |
def H(m): | |
return hashlib.sha512(m).digest() | |
def expmod(b,e,m): | |
if e == 0: return 1 | |
t = expmod(b,e/2,m)**2 % m | |
if e & 1: t = (t*b) % m | |
return t | |
def inv(x): | |
return expmod(x,q-2,q) | |
d = -121665 * inv(121666) | |
I = expmod(2,(q-1)/4,q) | |
def xrecover(y): | |
xx = (y*y-1) * inv(d*y*y+1) | |
x = expmod(xx,(q+3)/8,q) | |
if (x*x - xx) % q != 0: x = (x*I) % q | |
if x % 2 != 0: x = q-x | |
return x | |
By = 4 * inv(5) | |
Bx = xrecover(By) | |
B = [Bx % q,By % q] | |
def edwards(P,Q): | |
x1 = P[0] | |
y1 = P[1] | |
x2 = Q[0] | |
y2 = Q[1] | |
x3 = (x1*y2+x2*y1) * inv(1+d*x1*x2*y1*y2) | |
y3 = (y1*y2+x1*x2) * inv(1-d*x1*x2*y1*y2) | |
return [x3 % q,y3 % q] | |
def scalarmult(P,e): | |
if e == 0: return [0,1] | |
Q = scalarmult(P,e/2) | |
Q = edwards(Q,Q) | |
if e & 1: Q = edwards(Q,P) | |
return Q | |
def encodeint(y): | |
bits = [(y >> i) & 1 for i in range(b)] | |
return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)]) | |
def encodepoint(P): | |
x = P[0] | |
y = P[1] | |
bits = [(y >> i) & 1 for i in range(b - 1)] + [x & 1] | |
return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)]) | |
def bit(h,i): | |
return (ord(h[i/8]) >> (i%8)) & 1 | |
def publickey(sk): | |
h = H(sk) | |
a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2)) | |
A = scalarmult(B,a) | |
return encodepoint(A) | |
def Hint(m): | |
h = H(m) | |
return sum(2**i * bit(h,i) for i in range(2*b)) | |
def signature(m,sk,pk): | |
h = H(sk) | |
a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2)) | |
r = Hint(''.join([h[i] for i in range(b/8,b/4)]) + m) | |
R = scalarmult(B,r) | |
S = (r + Hint(encodepoint(R) + pk + m) * a) % l | |
return encodepoint(R) + encodeint(S) | |
def isoncurve(P): | |
x = P[0] | |
y = P[1] | |
return (-x*x + y*y - 1 - d*x*x*y*y) % q == 0 | |
def decodeint(s): | |
return sum(2**i * bit(s,i) for i in range(0,b)) | |
def decodepoint(s): | |
y = sum(2**i * bit(s,i) for i in range(0,b-1)) | |
x = xrecover(y) | |
if x & 1 != bit(s,b-1): x = q-x | |
P = [x,y] | |
if not isoncurve(P): raise Exception("decoding point that is not on curve") | |
return P | |
def checkvalid(s,m,pk): | |
if len(s) != b/4: raise Exception("signature length is wrong") | |
if len(pk) != b/8: raise Exception("public-key length is wrong") | |
R = decodepoint(s[0:b/8]) | |
A = decodepoint(pk) | |
S = decodeint(s[b/8:b/4]) | |
h = Hint(encodepoint(R) + pk + m) | |
if scalarmult(B,S) != edwards(R,scalarmult(A,h)): | |
raise Exception("signature does not pass verification") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from ed25519 import * | |
import os | |
import string | |
alphabet = string.printable | |
hexdigits = string.hexdigits | |
def init_key(): | |
res = [] | |
for i in range(5): | |
sk = os.urandom(32) | |
pk = publickey(sk) | |
res.append([sk,pk]) | |
return res | |
def find(keys, _pk): | |
idx = 0 | |
while idx < len(keys): | |
sk, pk = keys[idx] | |
if pk == _pk: | |
break | |
idx += 1 | |
return idx % len(keys) | |
def check(s, a): | |
for i in s: | |
if i not in a: | |
return False | |
return True | |
if __name__ == '__main__': | |
print 'Welcome to the admin panel' | |
print 'You can choose one of these keys to sign your message' | |
keys = init_key() | |
for i in range(len(keys)): | |
print str(i+1) + '. ' + keys[i][1].encode('hex') | |
print 'Commands:' | |
print '1. Sign' | |
print '2. Execute' | |
while 1: | |
try: | |
inp = raw_input('Your choice: ') | |
if inp == '1': | |
pk = raw_input('Public key: ') | |
if not check(pk, hexdigits): | |
break | |
pk = pk.decode('hex') | |
sk = keys[find(keys, pk)][0] | |
m = raw_input('Your command: ') | |
if not check(m, alphabet) or 'tictactoe' in m: | |
break | |
s = signature(m, sk, pk) | |
print s.encode('hex') | |
elif inp == '2': | |
pk = raw_input('Public key: ') | |
if not check(pk, hexdigits): | |
break | |
pk = pk.decode('hex') | |
m = raw_input('Your command: ') | |
if not check(m, alphabet): | |
break | |
s = raw_input('Your signature: ') | |
if not check(s, hexdigits): | |
break | |
s = s.decode('hex') | |
checkvalid(s, m, pk) | |
if 'tictactoe' in m: | |
print open('flag.txt','r').read() | |
break | |
else: | |
break | |
except: | |
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from telnetlib import * | |
from ed25519 import * | |
from libnum import * | |
r = Telnet('125.235.240.166' ,15997) | |
def get_pub(): | |
r.read_until('You can choose one of these keys to sign your message') | |
r.read_until('1. ') | |
return r.read_until('\n').strip() | |
def sign_(pub,cmd): | |
r.read_until('Your choice: ') | |
r.write('1\n') | |
r.read_until('Public key: ') | |
r.write(pub+'\n') | |
r.read_until('Your command: ') | |
r.write(cmd+'\n') | |
return r.read_until('\n').strip() | |
def excute(pub,cmd,sig): | |
r.read_until('Your choice: ') | |
r.write('2\n') | |
r.read_until('Public key: ') | |
r.write(pub+'\n') | |
r.read_until('Your command: ') | |
r.write(cmd+'\n') | |
r.read_until('Your signature: ') | |
r.write(sig+'\n') | |
return r.read_until('\n').strip() | |
def forge_signature(m, pk, a): | |
r = 17011337 # lucky number | |
R = scalarmult(B, r) | |
S = (r + Hint(encodepoint(R) + pk + m) * a) % l | |
return encodepoint(R) + encodeint(S) | |
def recover(pk1, sig1, pk2, sig2, message1, message2): | |
R1 = decodepoint(sig1[0:b / 8]) | |
S1 = decodeint(sig1[b / 8:b / 4]) | |
h1 = Hint(encodepoint(R1) + pk1 + message1) | |
R2 = decodepoint(sig2[0:b / 8]) | |
S2 = decodeint(sig2[b / 8:b / 4]) | |
h2 = Hint(encodepoint(R2) + pk2 + message1) | |
a = (S1 - S2) * modular.invmod(h1 - h2, l) | |
print('Found secret: ', a) | |
forged_signature = forge_signature(message2, pk1, a) | |
checkvalid(forged_signature, message2, pk1) | |
return forged_signature.encode("hex") | |
msg = 'ahihidongoc' # same message | |
pub1 = get_pub().decode('hex') # get pub at index 0 | |
pub2 = pub1[-4:] + 'abcd' # invalid pub => index 0 | |
# => two pub difference but same message and same secret => exploited | |
s1 = sign_(pub1.encode('hex'), msg).decode('hex') | |
s2 = sign_(pub2.encode('hex'), msg).decode('hex') | |
forged_sig = recover(pub1, s1, pub2, s2, msg, 'tictactoehihi') | |
print excute(pub1.encode('hex'), 'tictactoehihi', forged_sig) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment