just for now

This commit is contained in:
2024-12-10 00:51:04 +09:00
parent c4c4547706
commit 022291f5af
18 changed files with 311 additions and 32 deletions

Binary file not shown.

View File

@ -1,25 +1,44 @@
import socket import socket
from Crypto.Util.number import getPrime, inverse
import re
# Fill in the right target here # Fill in the right target here
HOST = 'this.is.not.a.valid.domain' # TODO HOST = 'netsec.net.in.tum.de' # TODO
PORT = 0 # TODO PORT = 20106 # TODO
def int_to_bytes(m): def int_to_bytes(m):
return m.to_bytes((m.bit_length() + 7) // 8, 'big').decode() return m.to_bytes((m.bit_length() + 7) // 8, 'big').decode()
def modular_inverse(p, phi_q):
x = inverse(p, phi_q)
return x % phi_q
def decrypt_message(encrypted, p, q):
phi_q = q - 1
d = modular_inverse(p, phi_q)
message = pow(encrypted, d, q)
return message
def get_flag(): def get_flag():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT)) s.connect((HOST, PORT))
sf = s.makefile('rw') # we use a file abstraction for the sockets sf = s.makefile('rw') # we use a file abstraction for the sockets
m = sf.readline().rstrip('\n')
message1 = sf.readline().rstrip('\n') bit_len = int(re.search(r"[0-9]+", m).group())
# TODO print(f"bit_len is {bit_len}")
p = getPrime(bit_len*2)
q = getPrime(bit_len*2)
sf.write(f'{p};{q}\n')
sf.flush()
c_m = int(sf.readline().rstrip('\n'))
print("C_M: ", c_m)
d_m = decrypt_message(c_m, p, q)
sf.close() sf.close()
s.close() s.close()
print(int_to_bytes(d_m))
if __name__ == '__main__': if __name__ == '__main__':

27
week06/easy/pwn_utils.py Normal file
View File

@ -0,0 +1,27 @@
import asyncio
class utils:
@staticmethod
async def read_line_safe(reader):
"""
Simple implementation to read a line from an async reader
Mimics the original read_line_safe functionality
"""
try:
line = await reader.readline()
return line.decode().strip()
except Exception:
return None
def log_error(e, client_writer=None):
"""
Basic error logging function
"""
print(f"Error occurred: {e}")
if client_writer:
try:
client_writer.write(f"Error: {str(e)}\n".encode())
except Exception:
print("Could not send error to client")

View File

@ -46,18 +46,19 @@ async def handle_client(client_reader: StreamReader, client_writer: StreamWriter
return return
match resp.split(';'): match resp.split(';'):
case [e, n]: case [e, n]:
if not e.isdigit() or not n.isdigit(): if not e.isdigit() or not n.isdigit(): # has to be not
client_writer.write('Invalid input\n'.encode()) client_writer.write('Invalid input\n'.encode())
await client_writer.drain() await client_writer.drain()
return return
e, n = int(e), int(n) e, n = int(e), int(n)
if not (no_bits * 2 - 1 <= n.bit_length() <= no_bits * 2): if not (no_bits * 2 - 1 <= n.bit_length() <= no_bits * 2): # has to be not
client_writer.write('Wrong bit count\n'.encode()) client_writer.write('Wrong bit count\n'.encode())
await client_writer.drain() await client_writer.drain()
return return
flag = subprocess.check_output('flag').decode().strip() flag = "flaggy"
m = int.from_bytes(flag.encode(), 'big') m = int.from_bytes(flag.encode(), 'big')
c = pow(m, e, n) c = pow(m, e, n)
print(c)
client_writer.write(f'{c}\n'.encode()) client_writer.write(f'{c}\n'.encode())
case _: case _:
client_writer.write('Invalid input\n'.encode()) client_writer.write('Invalid input\n'.encode())

36
week06/easy/test.py Normal file
View File

@ -0,0 +1,36 @@
import random
from Crypto.Util.number import getPrime, inverse
from Crypto.Util.number import inverse
def moc_encryption_message(p, q):
message = int.from_bytes("flaggy".encode(), 'big')
print("original message: ", message)
c = pow(message,p,q)
return c
def modular_inverse(p, phi_q):
x = inverse(p, phi_q)
return x % phi_q
def decrypt_message(encrypted, p, q):
phi_q = q - 1
d = modular_inverse(p, phi_q)
message = pow(encrypted, d, q)
return message
if __name__ == "__main__":
bit_length = 992
o = getPrime(bit_length*2)
q = getPrime(bit_length*2)
e, n = int(o), int(q)
if not (bit_length * 2 - 1 <= n.bit_length() <= bit_length * 2): # has to be not
print("wrong bit count")
c = moc_encryption_message(o, q)
m = decrypt_message(c, o, q)
print("decrypted message: ", m)
byte_length = (m.bit_length() + 7) // 8
decoded_string = m.to_bytes(byte_length, 'big').decode()
print("Decrypted_message_to_string: ", decoded_string)

Binary file not shown.

Binary file not shown.

View File

@ -6,7 +6,30 @@ import logging
from asyncio import StreamReader, StreamWriter from asyncio import StreamReader, StreamWriter
from insecurelib import * from insecurelib import *
from pwn_utils.utils import read_line_safe
async def read_line_safe(reader):
"""
Simple implementation to read a line from an async reader
Mimics the original read_line_safe functionality
"""
try:
line = await reader.readline()
return line.decode().strip()
except Exception:
return None
def log_error(e, client_writer=None):
"""
Basic error logging function
"""
print(f"Error occurred: {e}")
if client_writer:
try:
client_writer.write(f"Error: {str(e)}\n".encode())
except Exception:
print("Could not send error to client")
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
clients = {} # task -> (reader, writer) clients = {} # task -> (reader, writer)
@ -73,20 +96,20 @@ class AuthenticatedChannel:
return None return None
# calculate shared key # calculate shared key
print("calculating key now")
key = str(pow(Y, a, mod=p)) key = str(pow(Y, a, mod=p))
key = KDRV256(key.encode()) key = KDRV256(key.encode())
# decrypt and verify signature # decrypt and verify signature
decrypted_sig = decrypt(key, s) decrypted_sig = decrypt(key, s)
if not verify(bob_public, message=f'{Y},{X}'.encode(), signature=decrypted_sig): if not verify(bob_public, message=f'{Y},{X}'.encode(), signature=decrypted_sig):
self.writer.write('Signature verification failed\n'.encode()) self.writer.write('Signature verification failed\n'.encode())
await self.writer.drain() await self.writer.drain()
return None return None
# sign X and Y and send signature # sign X and Y and send signature
sig = sign(privKey, f'{X},{Y}'.encode()) sig = sign(privKey, f'{X},{Y}'.encode())
sig = encrypt(key, sig) sig = encrypt(key, sig)
self.writer.write(sig + b'\n') self.writer.write(sig + b'\n')
print("finished the do_STS_key_exchange")
await self.writer.drain() await self.writer.drain()
self.shared_key = key self.shared_key = key
@ -111,7 +134,7 @@ async def do_session_key_DH_exchange(channel: AuthenticatedChannel) -> bytes | N
return return
p, g, X = map(int, pgX.split(',')) p, g, X = map(int, pgX.split(','))
print("p, g, x is here: ", (p,g,X))
# two checks to prevent DOSes and improve performance # two checks to prevent DOSes and improve performance
if not check_int_range(p): if not check_int_range(p):
await channel.send_encrypted(f'{p} must be in [{0}..{MAX_PRIME}]'.encode()) await channel.send_encrypted(f'{p} must be in [{0}..{MAX_PRIME}]'.encode())
@ -119,7 +142,7 @@ async def do_session_key_DH_exchange(channel: AuthenticatedChannel) -> bytes | N
if not check_int_range(g): if not check_int_range(g):
await channel.send_encrypted(f'{g} must be in [{0}..{MAX_PRIME}]'.encode()) await channel.send_encrypted(f'{g} must be in [{0}..{MAX_PRIME}]'.encode())
return return
print("two checks to prevent doses and improve performance finished")
# check if parameters are valid # check if parameters are valid
if not is_prime(p): if not is_prime(p):
await channel.send_encrypted(f'{p} is not a prime number!'.encode()) await channel.send_encrypted(f'{p} is not a prime number!'.encode())
@ -132,13 +155,13 @@ async def do_session_key_DH_exchange(channel: AuthenticatedChannel) -> bytes | N
if X >= p: if X >= p:
await channel.send_encrypted(f"X ({X} can't be larger or equal to p {p}!".encode()) await channel.send_encrypted(f"X ({X} can't be larger or equal to p {p}!".encode())
return return
print("check if parameters are valid finished")
# create own public/private key parts: # create own public/private key parts:
b = random.randint(1, p - 1) b = random.randint(1, p - 1)
Y = pow(g, b, mod=p) Y = pow(g, b, mod=p)
print("sending encryption")
await channel.send_encrypted(f'{Y}'.encode()) await channel.send_encrypted(f'{Y}'.encode())
print("sending encyrption finished")
# calculate shared key # calculate shared key
key = str(pow(X, b, mod=p)) key = str(pow(X, b, mod=p))
key = KDRV256(key.encode()) key = KDRV256(key.encode())
@ -165,7 +188,7 @@ async def handle_client(client_reader: StreamReader, client_writer: StreamWriter
msg = 'Hey Bob, plz send me my f14g :-)' msg = 'Hey Bob, plz send me my f14g :-)'
encrypted_msg = encrypt(session_key, msg.encode()) encrypted_msg = encrypt(session_key, msg.encode())
print("sending encypretd message about igving me flag")
await authenticated_channel.send_encrypted(encrypted_msg) await authenticated_channel.send_encrypted(encrypted_msg)
data = await authenticated_channel.recv_encrypted() data = await authenticated_channel.recv_encrypted()

View File

@ -0,0 +1,3 @@
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIEeMyeJI/JBSKPBQVfaOY/T6Ew9fH5JwVrievvcX85V7
-----END PRIVATE KEY-----

View File

@ -0,0 +1,3 @@
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAcn6Y7i8GkW0KvMTIaPWj+axVBY29ki2bdAmxza2X6EU=
-----END PUBLIC KEY-----

View File

@ -8,7 +8,31 @@ import random
from asyncio import StreamReader, StreamWriter from asyncio import StreamReader, StreamWriter
from insecurelib import * from insecurelib import *
from pwn_utils.utils import read_line_safe
async def read_line_safe(reader):
"""
Simple implementation to read a line from an async reader
Mimics the original read_line_safe functionality
"""
try:
line = await reader.readline()
return line.decode().strip()
except Exception:
return None
def log_error(e, client_writer=None):
"""
Basic error logging function
"""
print(f"Error occurred: {e}")
if client_writer:
try:
client_writer.write(f"Error: {str(e)}\n".encode())
except Exception:
print("Could not send error to client")
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
clients = {} # task -> (reader, writer) clients = {} # task -> (reader, writer)
@ -51,16 +75,16 @@ class AuthenticatedChannel:
async def do_STS_key_exchange(self): async def do_STS_key_exchange(self):
# receive p,q and public keypart to other server (over the client) and wait for response # receive p,q and public keypart to other server (over the client) and wait for response
pgX = await read_line_safe(self.reader) pgX = await read_line_safe(self.reader)
if pgX is None: if pgX is None:
return return
if pgX.count(',') != 2: if pgX.count(',') != 2:
self.writer.write('Invalid amount of arguments (expected 3; p,g,X)\n'.encode()) self.writer.write('Invalid amount of arguments (expected 3; p,g,X)\n'.encode())
await self.writer.drain() await self.writer.drain()
return return
p, g, X = map(int, pgX.split(',')) p, g, X = map(int, pgX.split(','))
print(p,g,X)
# primality and size checks not necessary since fixed values from RFC 3526 are used for STS key exchange # primality and size checks not necessary since fixed values from RFC 3526 are used for STS key exchange
@ -105,8 +129,7 @@ async def do_session_key_DH_exchange(channel: AuthenticatedChannel) -> bytes | N
# send p,q and public keypart # send p,q and public keypart
pgX = f'{p},{g},{X}' pgX = f'{p},{g},{X}'
await channel.send_encrypted(pgX.encode()) await channel.send_encrypted(pgX.encode()) # Start debuggin from here bob
Y = await channel.recv_encrypted() Y = await channel.recv_encrypted()
log.info(f'received "{Y}" as Y (public key)') log.info(f'received "{Y}" as Y (public key)')
@ -121,6 +144,7 @@ async def do_session_key_DH_exchange(channel: AuthenticatedChannel) -> bytes | N
# calculate shared key # calculate shared key
key = str(pow(Y, a, mod=p)) key = str(pow(Y, a, mod=p))
key = KDRV256(key.encode()) key = KDRV256(key.encode())
print("do seession dh is finished")
return key return key
@ -140,9 +164,9 @@ async def handle_client(client_reader: StreamReader, client_writer: StreamWriter
# do session key DH exchange # do session key DH exchange
session_key = await do_session_key_DH_exchange(authenticated_channel) session_key = await do_session_key_DH_exchange(authenticated_channel)
print("session key obtained")
message = await authenticated_channel.recv_encrypted() message = await authenticated_channel.recv_encrypted()
print("message received for last: ", message)
if message is None: if message is None:
return return
@ -155,7 +179,7 @@ async def handle_client(client_reader: StreamReader, client_writer: StreamWriter
) )
return return
flag = subprocess.check_output('flag') flag = "flaggy".encode()
encrypted_flag = encrypt(session_key, flag) encrypted_flag = encrypt(session_key, flag)
await authenticated_channel.send_encrypted(encrypted_flag) await authenticated_channel.send_encrypted(encrypted_flag)

View File

@ -0,0 +1,3 @@
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIBT9LU2Gd571saJkzcQzxwdfmejkLeKjsJy1WhVOjxY2
-----END PRIVATE KEY-----

View File

@ -0,0 +1,3 @@
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAeI+vbbnxM+olxPgHiYZUuvOFM6WpWBt7CvNuLSioCxQ=
-----END PUBLIC KEY-----

View File

@ -7,9 +7,9 @@ import socket
from insecurelib import KDRV256, HMAC, encrypt, decrypt from insecurelib import KDRV256, HMAC, encrypt, decrypt
# Fill in the right target here # Fill in the right target here
HOST = 'this.is.not.a.valid.domain' # TODO HOST = 'netsec.net.in.tum.de'
PORT1 = 20008 PORT1 = 20206
PORT2 = 20108 PORT2 = 20306
# note the numbers you encounter may be small for demonstration purposes. # note the numbers you encounter may be small for demonstration purposes.
@ -25,7 +25,7 @@ def debug_secure_channel(s1, s2, data: str):
else: else:
print(f"from {s1} to {s2}: '{data}...'") print(f"from {s1} to {s2}: '{data}...'")
iv, ciphertext, mac = data.split(',') iv, ciphertext, mac = data.split(';')
assert len(iv) == 16 * 2 # a hexlified byte is two bytes long, the IV should be 16 bytes assert len(iv) == 16 * 2 # a hexlified byte is two bytes long, the IV should be 16 bytes
assert ( assert (
len(ciphertext) % (16 * 2) == 0 len(ciphertext) % (16 * 2) == 0
@ -52,9 +52,18 @@ def main():
data = s1f.readline().rstrip('\n') data = s1f.readline().rstrip('\n')
print(f"from s1 to s2: '{data}'") print(f"from s1 to s2: '{data}'")
p, g, X = map(int, data.split(',')) p, g, X = map(int, data.split(','))
p = int(p)
g = int(g)
X = int(X)
print("p: {} g: {} X: {}".format(p, g, X))
# TODO: get the flag # TODO: get the flag
s2f.write(data)
s2f.flush()
# Receive answer (second step of DH)
data = s2f.readline().rstrip('\n')
print("from s2 to s1: `{}'".format(data))
s1f.close() s1f.close()
s2f.close() s2f.close()
s1.close() s1.close()

View File

@ -18,6 +18,8 @@ def write_keys(name: str, private_key: str, public_key: str):
if __name__ == '__main__': if __name__ == '__main__':
privA, pubA = generate_keys() privA, pubA = generate_keys()
privB, pubB = generate_keys() privB, pubB = generate_keys()
privC, pubC = generate_keys()
write_keys('alice', privA, pubA) write_keys('alice', privA, pubA)
write_keys('bob', privB, pubB) write_keys('bob', privB, pubB)
write_keys('mitm', privC, pubC)
print('Keys generated and written to files') print('Keys generated and written to files')

View File

@ -214,12 +214,13 @@ def decrypt(key: bytes, message: str) -> bytes:
key_int = key[16:] key_int = key[16:]
assert not message.endswith('\n'), 'message should not end with a newline!' assert not message.endswith('\n'), 'message should not end with a newline!'
print("message is: ", message)
try: try:
iv, ciphertext, mac = message.split(';') iv, ciphertext, mac = message.split(';')
iv = unhexlify(iv) iv = unhexlify(iv)
ciphertext = unhexlify(ciphertext) ciphertext = unhexlify(ciphertext)
mac = unhexlify(mac) mac = unhexlify(mac)
print(len(mac))
assert len(mac) == 16 assert len(mac) == 16
except Exception as e: except Exception as e:

27
week06/hard/pwn_utils.py Normal file
View File

@ -0,0 +1,27 @@
import asyncio
class utils:
@staticmethod
async def read_line_safe(reader):
"""
Simple implementation to read a line from an async reader
Mimics the original read_line_safe functionality
"""
try:
line = await reader.readline()
return line.decode().strip()
except Exception:
return None
def log_error(e, client_writer=None):
"""
Basic error logging function
"""
print(f"Error occurred: {e}")
if client_writer:
try:
client_writer.write(f"Error: {str(e)}\n".encode())
except Exception:
print("Could not send error to client")

98
week06/hard/test.py Normal file
View File

@ -0,0 +1,98 @@
#!/usr/bin/env python3
import socket
from Crypto.Cipher import AES
from binascii import hexlify, unhexlify
import random
from Crypto.PublicKey import ECC
HOST = 'localhost'
PORT1 = 20206
PORT2 = 20306
def debug_secure_channel(s1, s2, data):
data = data.rstrip('\n') # remove trailing newline
if len(data) >= 1024:
print("from {} to {}: `{}...'".format(s1, s2, data[:1024]))
else:
print("from {} to {}: `{}'".format(s1, s2, data))
iv, ciphertext, mac = data.split(";")
assert (len(iv) == 16 * 2) # a hexlified byte is two bytes long, the IV should be 16 bytes
assert (len(ciphertext) % (16 * 2) == 0) # a hexlified byte is two bytes long, AES block size is 128 bit (16 byte)
assert (len(mac) == 16 * 2) # a quite short MAC. Hint: you still don't want to brute force it!
print("relayed {} encrypted blocks of payload".format(len(unhexlify(ciphertext)) // AES.block_size))
def main():
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.connect((HOST, PORT1))
s1f = s1.makefile("rw") # file abstraction for the sockets
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.connect((HOST, PORT2))
s2f = s2.makefile("rw")
# First step of Diffie Hellman (compare slides)
data = s1f.readline()
print("from s1 to s2: '{}'".format(data)) # you should see the newline at the end printed
p, g, X = data.split(",")
p = int(p)
g = int(g)
X = int(X)
print("p: {} g: {} X: {}".format(p, g, X))
a = random.randint(1, p-1)
eve_X = pow(g, a, mod=p)
eve_data = f"{p},{g},{eve_X}\n"
# # forward to Bob
s2f.write(eve_data)
s2f.flush()
# # # Receive answer (second step of DH)
data = s2f.readline()
print("from s2 to s1: '{}'".format(data))
# # # Forward received
# s1f.write(data) # the data should still have a b'\n' at the end
# s1f.flush()
# # # Alice sends something to Bob
# data = s1f.readline()
# print("S1f {}".format(data))
# debug_secure_channel("Alice", "Bob", data)
# # # Forward received data to Bob
# s2f.write(data)
# s2f.flush()
# data = s2f.readline()
# debug_secure_channel("Bob", "Alice", data)
# print(f"get data from bob: {data}")
# s1f.write(data)
# s1f.flush()
# data = s1f.readline()
# debug_secure_channel("Bob", "Alice", data)
# print(f"get data from alice: {data}")
# # "alice sending hey bob, plz send me my f14g"
# s2f.write(data)
# s2f.flush()
# data = s1f.readline()
# print(f"get data from alice: {data}")
# s2f.write(data)
# s2f.flush()
# data = s2f.readline()
# print(f"get data from bob :{data}")
# s1f.write(data)
# s1f.flush()
# data = s1f.readline()
# print(f"get data from alice again: {data}")
s1f.close()
s2f.close()
s1.close()
s2.close()
if __name__ == "__main__":
main()