Commit c071f903 authored by Giovanni's avatar Giovanni 🖥

de1 2020 ecdh writeup init

parent f73c7cd2
Pipeline #142330963 passed with stages
in 25 seconds
This diff is collapsed.
#!/usr/bin/env python3
# CLIENT
import sys
from pwn import *
from Crypto.Util.number import bytes_to_long as bl
from factordb.factordb import FactorDB
from Crypto.Util.number import long_to_bytes as lb
from sage.all import *
import multiprocessing
import string
import subprocess
import time
def crack(to_crack):
alphabet = string.digits + string.ascii_letters
for x in alphabet:
for y in alphabet:
for z in alphabet:
for w in alphabet:
key = x+y+z+w + secret
_hash = hashlib.sha256(key.encode()).hexdigest()
if _hash == to_crack:
return x + y + z + w
def xor_string(s1, s2):
return bytes(x ^ y for x, y in zip(s1, s2))
def pad(m):
pad_length = 256*2 - len(m)
for _ in range(pad_length):
m.insert(0,0)
return m
def point_to_keys(p):
x = p[0]
y = p[1]
tmp = x << 256 | y
res = pad([int(i) for i in list('{0:0b}'.format(tmp))])
return res
def bytes_to_bit(a):
l = []
for b in a:
c = bin(b)[2:].rjust(8, '0')
for d in c:
l.append(int(d))
return l
def keys_to_point(k):
y = int(''.join(str(i) for i in k[-256:]), 2)
x = int(''.join(str(i) for i in k[:256]), 2)
return (x, y)
def read_sage_point(P):
tmp = P.replace('(', '').replace(')', '').split(' : ')
return (tmp[0], tmp[1])
def compute_dlog(G, Q, prime, crt_solver):
print(f"trying to crack {Q} = {G} * secret")
dlog = G.discrete_log(Q)
crt_solver[prime] = dlog
print(f"done {dlog}")
a = 0x4cee8d95bb3f64db7d53b078ba3a904557425e2a6d91c5dfbf4c564a3f3619fa
b = 0x56cbc73d8d2ad00e22f12b930d1d685136357d692fa705dae25c66bee23157b8
q = 0xdd7860f2c4afe6d96059766ddd2b52f7bb1ab0fce779a36f723d50339ab25bbd
# Solve PoW
context.log_level = 'DEBUG'
conn = remote('134.175.225.42', 8848)
conn.recv(12)
secret = conn.recvuntil(b')')[:-1].decode()
conn.recvuntil(b'== ')
to_find = conn.recvline().strip(b'\n').decode()
print(secret)
print(to_find)
hash = crack(to_find)
conn.recvuntil(b':')
conn.sendline(hash)
generators = {
2: ('81972374812864690693014852714727745978362841318289396397361414563375734501921', '51896212619465579275373796571948358799405679959558638822560270744499831979432', 1327481), 3: ('53326919872607738273172644810428986036094490647068694645393694893278040069026', '58081551953623943565565755936599269753986052376062491850282542721957212970679', 71337711241), 4: ('8148101487581648484053574525912222209338990886522507033183350100344852533064', '15225235739470967392827134243865327994823593728240653822041518660024750505853', 287038167079), 8: ('50666337867992575803820658750430197277695458978329092014096425844774763149719', '13421860369980853123427220383308870579014596017199802188611416857274407341576', 14007550114741), 9: ('27693266742860373879830235866293233339575293329402286516010276136420544358905', '8279872853041474338063561217165295999844712166288430478991978486297227230411', 17003163806851), 11: ('73177225050788643134380595317533550828476603067177547542601837469105448675189', '16845507613964658793645291408091138189402262042994290641383029874357951799263', 80599), 12: ('87927856259936467933865576887569931721798540127844175083299758091155998566253', '73204268729977825848740410829132875207119846783884288746044087556556009530393', 19813513), 14: ('20443758771121867411286144646166868372450547941066474097899222621364635384017', '71171557090899672647440713736403327367383103843027405297306364952443383551107', 20731), 15: ('89027666840299255236885552248007867044183365676188167946721016933234594434812', '90004068319753094768603992580255539598521077777716506807086729772395186348302', 119653)
}
manager = multiprocessing.Manager()
crt_solver = manager.dict()
processes = []
for i in range(len(list(generators.keys()))):
# Exchange like a beast
b = list(generators.keys())[i]
E = EllipticCurve(GF(q), [a, b])
G = generators[b][:2]
print("\n\nEXCHANGE\n")
print(f"trying b: {b}")
if i != 0:
conn.recvuntil(b'choice:\n')
conn.sendline(b'Exchange')
conn.recvuntil(b'X:')
conn.sendline(str(G[0]))
conn.recvuntil(b'Y:')
conn.sendline(str(G[1]))
# Solve DLOG muthafucka
conn.recvuntil(b'Tell me your choice:')
conn.sendline('Encrypt')
conn.recvuntil('Give me your message(hex):')
to_cipher = ""
to_cipher += 'f1'
for _ in range(63):
to_cipher += '41'
conn.sendline(to_cipher)
print(conn.recvuntil(b'is:\n'))
res = conn.recvline().strip(b'\n').decode()
key = xor_string(bytes.fromhex(to_cipher), bytes.fromhex(res))
Q = keys_to_point(bytes_to_bit(key))
print(f"Q: {Q}")
print(f"G: {G}")
G_e = E([G[0], G[1]])
Q_e = E([Q[0], Q[1]])
proc = multiprocessing.Process(target=compute_dlog, args=(G_e, Q_e, generators[b][2], crt_solver))
processes.append(proc)
proc.start()
print(f"done: {i}")
for _ in range(6):
conn.recvuntil(b'choice:\n')
conn.sendline(b'Exchange')
conn.recvuntil(b'X:')
conn.sendline(str(1))
conn.recvuntil(b'Y:')
conn.sendline(str(1))
time.sleep(30)
for p in processes:
p.join()
super_secret = CRT_list(list(crt_solver.values()), list(crt_solver.keys()))
print(super_secret)
conn.recvuntil(b'choice:\n')
conn.sendline(b'Backdoor')
conn.sendline(str(super_secret))
conn.interactive()
#!/usr/bin/env python3
# CLIENT
import sys
#import random
from pwn import *
from Crypto.Util.number import bytes_to_long as bl
from factordb.factordb import FactorDB
from Crypto.Util.number import long_to_bytes as lb
from sage.all import *
import string
import subprocess
def crack(HASH):
alphabet = string.digits + string.ascii_letters
for x in alphabet:
for y in alphabet:
for z in alphabet:
for w in alphabet:
key = x+y+z+w + secret
_hash = hashlib.sha256(key.encode()).hexdigest()
if _hash == HASH:
return x + y + z + w
def xor_string(s1, s2):
return bytes(x ^ y for x, y in zip(s1, s2))
def pad(m):
pad_length = 256*2 - len(m)
for _ in range(pad_length):
m.insert(0,0)
return m
def pointToKeys(p):
x = p[0]
y = p[1]
tmp = x << 256 | y
res = pad([int(i) for i in list('{0:0b}'.format(tmp))])
return res
def bytes_to_bit(a):
l = []
for b in a:
c = bin(b)[2:].rjust(8, '0')
for d in c:
l.append(int(d))
return l
def keysToPoint(k):
y = int(''.join(str(i) for i in k[-256:]), 2)
x = int(''.join(str(i) for i in k[:256]), 2)
return (x, y)
def read_sage_point(P):
tmp = P.replace('(', '').replace(')', '').split(' : ')
return (tmp[0], tmp[1])
a = 0x4cee8d95bb3f64db7d53b078ba3a904557425e2a6d91c5dfbf4c564a3f3619fa
b = 0x56cbc73d8d2ad00e22f12b930d1d685136357d692fa705dae25c66bee23157b8
q = 0xdd7860f2c4afe6d96059766ddd2b52f7bb1ab0fce779a36f723d50339ab25bbd
# Solve PoW
"""
conn = remote('134.175.225.42', 8848)
conn.recv(12)
secret = conn.recvuntil(b')')[:-1].decode()
conn.recvuntil(b'== ')
to_find = conn.recvline().strip(b'\n').decode()
print(secret)
print(to_find)
hash = crack(to_find)
conn.recvuntil(b':')
conn.sendline(hash)
"""
context.log_level = 'DEBUG'
generators = {}
for i in range(2, 50):
if generators.get(i, None) is None:
E = EllipticCurve(GF(q), [a, i])
order = E.order()
f = FactorDB(order)
f.connect()
primes = f.get_factor_list()
valid = 0
for p in primes:
if p <= 122985417205330:
valid = p
prime = valid
G = E.gen(0) * int(order / prime)
G = read_sage_point(str(G))
generators[i] = (G[0], G[1], prime)
print(generators)
print(generators)
blacklist_dlog = [30]
"""
pp = []
dlog = []
blacklist = [20, 16, 41, 34, 24, 46, 36, 17, 37, 28]
for i in range(15):
# Exchange like a beast
print("\n\nEXCHANGE\n")
b = randint(10, 50)
while b in blacklist:
b = randint(10, 50)
print(f"b: {b}")
E = EllipticCurve(GF(q), [a, b])
print(f"Curve: {E}")
order = E.order()
print("computing prime factors")
f = FactorDB(order)
f.connect()
primes = f.get_factor_list()
#primes = prime_factors(order)
valid = []
# 12298541720533
for p in primes:
if p <= 122985417205330:
valid.append(p)
prime = valid[-1:][0]
pp.append(prime)
print(f"prime order: {prime}")
print("computing generator")
G = E.gen(0) * int(order / prime)
G = read_sage_point(str(G))
if i != 0:
conn.recvuntil(b'choice:\n')
conn.sendline(b'Exchange')
conn.recvuntil(b'X:')
conn.sendline(str(G[0]))
conn.recvuntil(b'Y:')
conn.sendline(str(G[1]))
# Solve DLOG muthafucka
conn.recvuntil(b'Tell me your choice:')
conn.sendline('Encrypt')
conn.recvuntil('Give me your message(hex):')
to_cipher = ""
to_cipher += 'f1'
for _ in range(63):
to_cipher += '41'
conn.sendline(to_cipher)
print(conn.recvuntil(b'is:\n'))
res = conn.recvline().strip(b'\n').decode()
key = xor_string(bytes.fromhex(to_cipher), bytes.fromhex(res))
Q = keysToPoint(bytes_to_bit(key))
print(f"Q: {Q}")
print(f"G: {G}")
G_e = E([G[0], G[1]])
Q_e = E([Q[0], Q[1]])
print("computing dlog")
logg = G_e.discrete_log(Q_e)
dlog.append(logg)
print(f"dlog: {logg}")
print(f"done: {i}")
print(f"dlog: {dlog}")
print(f"primes: {pp}")
super_secret = CRT_list(dlog, pp)
print(super_secret)
conn.interactive()
"""
import os,random,sys,string
from hashlib import sha256
import SocketServer
import signal
from FLAG import flag
from gmpy2 import invert
from Crypto.Util.number import bytes_to_long, long_to_bytes
q = 0xdd7860f2c4afe6d96059766ddd2b52f7bb1ab0fce779a36f723d50339ab25bbd
a = 0x4cee8d95bb3f64db7d53b078ba3a904557425e2a6d91c5dfbf4c564a3f3619fa
b = 0x56cbc73d8d2ad00e22f12b930d1d685136357d692fa705dae25c66bee23157b8
zero = (0,0)
def add(p1,p2):
if p1 == zero:
return p2
if p2 == zero:
return p1
(p1x,p1y),(p2x,p2y) = p1,p2
if p1x == p2x and (p1y != p2y or p1y == 0):
return zero
if p1x == p2x:
tmp = (3 * p1x * p1x + a) * invert(2 * p1y , q) % q
else:
tmp = (p2y - p1y) * invert(p2x - p1x , q) % q
x = (tmp * tmp - p1x - p2x) % q
y = (tmp * (p1x - x) - p1y) % q
return (int(x),int(y))
def mul(n,p):
r = zero
tmp = p
while 0 < n:
if n & 1 == 1:
r = add(r,tmp)
n, tmp = n >> 1, add(tmp,tmp)
return r
def pointToString(p):
return "(" + str(p[0]) + "," + str(p[1]) + ")"
Px = 0xb55c08d92cd878a3ad444a3627a52764f5a402f4a86ef700271cb17edfa739ca
Py = 0x49ee01169c130f25853b66b1b97437fb28cfc8ba38b9f497c78f4a09c17a7ab2
P = (Px,Py)
class Task(SocketServer.BaseRequestHandler):
def proof_of_work(self):
random.seed(os.urandom(8))
proof = "".join([random.choice(string.ascii_letters+string.digits) for _ in range(20)])
digest = sha256(proof).hexdigest()
self.request.send("sha256(XXXX+%s) == %s\n" % (proof[4:],digest))
self.request.send("Give me XXXX:")
x = self.request.recv(10)
x = x.strip()
if len(x) != 4 or sha256(x+proof[4:]).hexdigest() != digest:
return False
return True
def recvall(self, sz):
try:
r = sz
res = ""
while r > 0:
res += self.request.recv(r)
if res.endswith("\n"):
r = 0
else:
r = sz - len(res)
res = res.strip()
except:
res = ""
return res.strip("\n")
def dosend(self, msg):
try:
self.request.sendall(msg)
except:
pass
def handle(self):
try:
if not self.proof_of_work():
return
signal.alarm(300)
self.secret = random.randint(0,q)
Q = mul(self.secret,P)
self.dosend("Welcome to the ECDH System.\n")
self.dosend("The params are: \n")
self.dosend("q: " + str(q) + "\n")
self.dosend("a: " + str(a) + "\n")
self.dosend("b: " + str(b) + "\n")
self.dosend("P: " + pointToString(P) + "\n")
self.dosend("Q: " + pointToString(Q) + "\n")
self.exchange()
for _ in range(90):
self.dosend("Tell me your choice:\n")
choice = self.recvall(9)
if choice == "Exchange":
self.exchange()
elif choice == "Encrypt":
self.encrypt()
elif choice == "Backdoor":
self.backdoor()
else:
self.dosend("No such choice!\n")
self.dosend("Bye bye~\n")
self.request.close()
except:
self.dosend("Something error!\n")
self.request.close()
def pad(self,m):
pad_length = q.bit_length()*2 - len(m)
for _ in range(pad_length):
m.insert(0,0)
return m
def encrypt(self):
self.dosend("Give me your message(hex):\n")
msg = self.recvall(150)
data = [int(i) for i in list('{0:0b}'.format(bytes_to_long(msg.decode("hex"))))]
enc = [data[i] ^ self.key[i%len(self.key)] for i in range(len(data))]
result = 0
for bit in enc:
result = (result << 1) | bit
result = long_to_bytes(result).encode("hex")
self.dosend("The result is:\n")
self.dosend(result + "\n")
def pointToKeys(self,p):
x = p[0]
y = p[1]
tmp = x << q.bit_length() | y
res = self.pad([int(i) for i in list('{0:0b}'.format(tmp))])
return res
def exchange(self):
self.dosend("Give me your key:\n")
self.dosend("X:\n")
x = int(self.recvall(80))
self.dosend("Y:\n")
y = int(self.recvall(80))
key = (x,y)
result = mul(self.secret,key)
self.key = self.pointToKeys(result)
self.dosend("Exchange success\n")
def backdoor(self):
self.dosend("Give me the secret:\n")
s = self.recvall(80)
if int(s) == self.secret:
self.dosend('Wow! How smart you are! Here is your flag:\n')
self.dosend(flag)
else:
self.dosend('Sorry you are wrong!\n')
exit(0)
class ForkedServer(SocketServer.ForkingTCPServer, SocketServer.TCPServer):
pass
if __name__ == "__main__":
HOST, PORT = "0.0.0.0", 8848
server = ForkedServer((HOST, PORT), Task)
server.allow_reuse_address = True
server.serve_forever()
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment