week06
This commit is contained in:
BIN
week05/hard/__pycache__/pwn_utils.cpython-312.pyc
Normal file
BIN
week05/hard/__pycache__/pwn_utils.cpython-312.pyc
Normal file
Binary file not shown.
44
week05/hard/bruteforec.py
Normal file
44
week05/hard/bruteforec.py
Normal file
@ -0,0 +1,44 @@
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import pad
|
||||
import base64
|
||||
import itertools
|
||||
|
||||
# Function to compute the CBC-MAC of a given message, IV, and key
|
||||
def cbc_mac(message: bytes, iv: bytes, key: bytes) -> bytes:
|
||||
cipher = AES.new(key, AES.MODE_CBC, iv)
|
||||
padded_message = pad(message, 16) # Ensure the message is padded to the block size
|
||||
return cipher.encrypt(padded_message)[-16:]
|
||||
|
||||
# Brute-force the key by trying all possible 16-byte keys
|
||||
def brute_force_keys(target_mac, iv, message, key_size=16):
|
||||
"""
|
||||
Attempts to brute-force the key used for CBC-MAC, given the target MAC.
|
||||
:param target_mac: The target MAC we're trying to guess.
|
||||
:param iv: The IV used for CBC-MAC.
|
||||
:param message: The plaintext message used to generate the MAC.
|
||||
:param key_size: The size of the key (16 bytes for AES-128).
|
||||
:return: The correct key if found, otherwise None.
|
||||
"""
|
||||
# Loop through all possible 16-byte keys (this is feasible since there are only 2^128 keys)
|
||||
# For demonstration purposes, we're assuming a small brute-force keyspace (e.g., 256^16)
|
||||
for candidate_key in itertools.product(range(256), repeat=key_size):
|
||||
candidate_key = bytes(candidate_key)
|
||||
computed_mac = cbc_mac(message, iv, candidate_key)
|
||||
if computed_mac == target_mac:
|
||||
return candidate_key
|
||||
return None
|
||||
|
||||
# Example usage:
|
||||
message = b"type=secrets&number=1337"
|
||||
iv = base64.b64decode('00000000000000000000000000000000') # Controlled IV (could be any IV)
|
||||
# Assume the target MAC is obtained from the server for this message and IV
|
||||
# In a real attack, you'd receive this MAC from the server
|
||||
target_mac = base64.b64decode('e0f8b77b2ac5fa872f5646ac90b056ac') # Example MAC
|
||||
|
||||
# Attempt to brute-force the key
|
||||
guessed_key = brute_force_keys(target_mac, iv, message)
|
||||
|
||||
if guessed_key:
|
||||
print(f"Found key: {guessed_key.hex()}")
|
||||
else:
|
||||
print("Failed to brute-force the key.")
|
@ -1,18 +1,20 @@
|
||||
import socket
|
||||
import random
|
||||
from Crypto.Cipher import AES
|
||||
import base64
|
||||
import time
|
||||
|
||||
# Fill in the right target here
|
||||
HOST = 'this.is.not.a.valid.domain' # TODO
|
||||
PORT = 0 # TODO
|
||||
|
||||
HOST = 'localhost' # TODO
|
||||
PORT = 20205 # TODO
|
||||
correct_message = "dHlwZT1zZWNyZXRzJm51bWJlcj0xMzM3;AAAAAAAAAAAAAAAAAAAAAA==;OpDnZaDSwwbQ7YoFg16Q3Q=="
|
||||
|
||||
def get_flag():
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
|
||||
s.connect((HOST, PORT))
|
||||
sf = s.makefile('rw') # we use a file abstraction for the sockets
|
||||
|
||||
# TODO
|
||||
|
||||
|
||||
sf.close()
|
||||
s.close()
|
||||
|
||||
|
27
week05/hard/pwn_utils.py
Normal file
27
week05/hard/pwn_utils.py
Normal 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")
|
@ -77,6 +77,7 @@ async def handle_client(client_reader: StreamReader, client_writer: StreamWriter
|
||||
return
|
||||
match message.split(';'):
|
||||
case [m, iv, mac]:
|
||||
print(m,iv,mac)
|
||||
m = base64.b64decode(m)
|
||||
iv = base64.b64decode(iv)
|
||||
mac = base64.b64decode(mac)
|
||||
@ -104,6 +105,7 @@ def accept_client(client_reader: StreamReader, client_writer: StreamWriter):
|
||||
|
||||
|
||||
def main():
|
||||
print(KEY)
|
||||
# start server
|
||||
loop = asyncio.get_event_loop()
|
||||
f = asyncio.start_server(accept_client, host=None, port=20205)
|
||||
|
36
week05/hard/test.py
Normal file
36
week05/hard/test.py
Normal file
@ -0,0 +1,36 @@
|
||||
import base64
|
||||
import random
|
||||
from Crypto.Cipher import AES
|
||||
|
||||
KEY = random.randbytes(16)
|
||||
# KEY =b'\xaab\xa65z"\xac\xb1,a\xff1\xdb6}\xb0' # The key should match the server's key
|
||||
IV = b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # The IV can be random
|
||||
|
||||
def pkcs7(message: bytes, block_size: int = 16) -> bytes:
|
||||
gap_size = block_size - (len(message) % block_size)
|
||||
return message + bytes([gap_size] * gap_size)
|
||||
|
||||
|
||||
def cbc_mac(message: bytes, iv: bytes, key: bytes) -> bytes:
|
||||
cipher = AES.new(key, AES.MODE_CBC, iv)
|
||||
message = pkcs7(message)
|
||||
last_block = cipher.encrypt(message)[-16:]
|
||||
return last_block
|
||||
|
||||
# Craft the message
|
||||
message = b"type=recrets&number=1337"
|
||||
|
||||
# Calculate the MAC
|
||||
mac = cbc_mac(message, IV, KEY)
|
||||
|
||||
# Base64 encode the message, IV, and MAC
|
||||
encoded_message = base64.b64encode(message).decode('utf-8')
|
||||
encoded_iv = base64.b64encode(IV).decode('utf-8')
|
||||
encoded_mac = base64.b64encode(cbc_mac(message, IV,KEY)).decode('utf-8')
|
||||
|
||||
# Final request to send
|
||||
final_message = f"{encoded_message};{encoded_iv};{encoded_mac}"
|
||||
|
||||
print(final_message)
|
||||
|
||||
# MAC verification failed: expected afb7f5f307ea507b631d964e089a820a, got a0b0b48844a7deaf9d917a5f11ae0359
|
Reference in New Issue
Block a user