diff --git a/cscg25/crypto/intro1/__pycache__/secret.cpython-313.pyc b/cscg25/crypto/intro1/__pycache__/secret.cpython-313.pyc new file mode 100644 index 0000000..1814861 Binary files /dev/null and b/cscg25/crypto/intro1/__pycache__/secret.cpython-313.pyc differ diff --git a/cscg25/crypto/intro1/exploit.py b/cscg25/crypto/intro1/exploit.py new file mode 100644 index 0000000..678be31 --- /dev/null +++ b/cscg25/crypto/intro1/exploit.py @@ -0,0 +1,45 @@ +from pwn import * +import binascii + + +p = remote("a96a15c9c5222abacb014e80-1024-intro-crypto-1.challenge.cscg.live", 1337, ssl=True)# Define functions for convenience + +def recv_until(delim): + return p.recvuntil(delim) + +def interact(): + p.interactive() + +def send_payload(payload): + p.sendline(payload) + +def xor(bytes1, bytes2): + return bytes([b1 ^ b2 for b1, b2 in zip(bytes1, bytes2)]) + + +# Example interaction +recv_until(b":") +payload = b"41" * 74 +send_payload(payload) + +encrypted_plaintext = [] + +for _ in range(255): + data = binascii.unhexlify(recv_until(b"\n").replace(b"\n",b"").split(b" ")[-1]) + encrypted_plaintext.append(data) + +payload = b"\x41" * 74 + +print(payload) + +keystreams = [xor(enc, payload) for enc in encrypted_plaintext] + +enc_flag = binascii.unhexlify(recv_until(b"\n").replace(b"\n",b"").split(b" ")[-1]) +print(enc_flag) + +dec_flags = [xor(keystream, enc_flag) for keystream in keystreams] + +for flag in dec_flags: + if b'CSCG{' in flag: + print(flag) + diff --git a/cscg25/crypto/intro1/main.py b/cscg25/crypto/intro1/main.py new file mode 100755 index 0000000..dafdbe4 --- /dev/null +++ b/cscg25/crypto/intro1/main.py @@ -0,0 +1,60 @@ +#!/usr/bin/env pypy3 + +import os +from pydoc import plain +from sys import byteorder +from Crypto.Cipher import AES +from Crypto.Util import Counter +import hashlib + +# Create a secret.py file with a variable `FLAG` for local testing :) +from secret import FLAG + +secret_key = os.urandom(16) + +def encrypt(plaintext, counter): + m = hashlib.sha256() + m.update(counter.to_bytes(8, byteorder="big")) + + alg = AES.new(secret_key, AES.MODE_CTR, nonce=m.digest()[0:8]) + ciphertext = alg.encrypt(plaintext) + + return ciphertext.hex() + +def xor(bytes1, bytes2): + return bytes([b1 ^ b2 for b1, b2 in zip(bytes1, bytes2)]) + +def main(): + print("DES is broken, long live the secure AES encryption!") + print("Give me a plaintext and I'll encrypt it a few times for you. For more security of course!") + + try: + plaintext = bytes.fromhex("41" * 512) + print(plaintext) + except ValueError: + print("Please enter a hex string next time.") + exit(0) + + encrypted_plaintext = [] + + for i in range(0, 255): + crypt = encrypt(plaintext, i) + encrypted_plaintext.append(bytes.fromhex(crypt)) + print(f"Ciphertext {i:03d}: {crypt}") + + keystreams = [xor(enc, plaintext) for enc in encrypted_plaintext] + + enc_flag = encrypt(FLAG.encode("ascii"), int.from_bytes(os.urandom(1), byteorder="big")) + + print("Flag:", enc_flag) + + dec_flags = [xor(keystream, bytes.fromhex(enc_flag)) for keystream in keystreams] + + for flag in dec_flags: + if b'cscg' in flag: + print(flag) + + + +if __name__ == "__main__": + main() diff --git a/cscg25/crypto/intro1/secret.py b/cscg25/crypto/intro1/secret.py new file mode 100644 index 0000000..4778dda --- /dev/null +++ b/cscg25/crypto/intro1/secret.py @@ -0,0 +1 @@ +FLAG = "cscg{a1b2c3d4e5f67890abcdef1234567890abcdef1234567890abcdef1234}" diff --git a/cscg25/crypto/intro2/__pycache__/secret.cpython-313.pyc b/cscg25/crypto/intro2/__pycache__/secret.cpython-313.pyc new file mode 100644 index 0000000..f18542f Binary files /dev/null and b/cscg25/crypto/intro2/__pycache__/secret.cpython-313.pyc differ diff --git a/cscg25/crypto/intro2/exploit.py b/cscg25/crypto/intro2/exploit.py new file mode 100644 index 0000000..6d7d28b --- /dev/null +++ b/cscg25/crypto/intro2/exploit.py @@ -0,0 +1,144 @@ +from pwn import * +from base64 import b64encode, b64decode +import struct +import binascii + +KEY_LENGTH_BYTES = 16 +LOCAL = True + +if not LOCAL: + p = remote("190b6910a0ded80a0296d180-1024-intro-crypto-2.challenge.cscg.live", 1337, ssl=True)# Define functions for convenience + +menu_string = b"\n 1. Register\n 2. Show animal videos\n 3. Show flag\n 4. Exit\n \nEnter your choice:" + +class SHA1: + def __init__(self, h0, h1, h2, h3, h4, message_byte_length): + self.h0 = h0 + self.h1 = h1 + self.h2 = h2 + self.h3 = h3 + self.h4 = h4 + self.message_byte_length = message_byte_length + + def _left_rotate(self, n, b): + return ((n << b) | (n >> (32 - b))) & 0xffffffff + + def update(self, message): + message_byte_length = len(message) + message_bit_length = (self.message_byte_length + message_byte_length) * 8 + message += b'\x80' + message += b'\x00' * ((56 - (len(message) % 64)) % 64) + message += struct.pack('>Q', message_bit_length) + + for chunk_offset in range(0, len(message), 64): + w = list(struct.unpack('>16I', message[chunk_offset:chunk_offset + 64])) + w.extend(0 for _ in range(64)) + for i in range(16, 80): + w[i] = self._left_rotate(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1) + + a, b, c, d, e = self.h0, self.h1, self.h2, self.h3, self.h4 + for i in range(80): + if 0 <= i < 20: + f = (b & c) | (~b & d) + k = 0x5A827999 + elif 20 <= i < 40: + f = b ^ c ^ d + k = 0x6ED9EBA1 + elif 40 <= i < 60: + f = (b & c) | (b & d) | (c & d) + k = 0x8F1BBCDC + else: + f = b ^ c ^ d + k = 0xCA62C1D6 + + temp = (self._left_rotate(a, 5) + f + e + k + w[i]) & 0xffffffff + e = d + d = c + c = self._left_rotate(b, 30) + b = a + a = temp + + self.h0 = (self.h0 + a) & 0xffffffff + self.h1 = (self.h1 + b) & 0xffffffff + self.h2 = (self.h2 + c) & 0xffffffff + self.h3 = (self.h3 + d) & 0xffffffff + self.h4 = (self.h4 + e) & 0xffffffff + + def digest(self): + return struct.pack('>5I', self.h0, self.h1, self.h2, self.h3, self.h4) + +def recv_until(delim): + return p.recvuntil(delim) + +def interact(): + p.interactive() + +def send_payload(payload): + p.sendline(payload) + +def register() -> bytes: + p.recvuntil(menu_string) + p.sendline(b"1") + p.recvuntil(b"? ") + p.sendline(b"Simon") + p.recvuntil(b"? ") + p.sendline(b"Cat") + return p.recvuntil(b'\n').replace(b"\n", b"").split(b" ")[-1] + +def show_flag(token: bytes): + p.recvuntil(menu_string) + p.sendline(b"3") + p.recvuntil(b": ") + p.sendline(token) + interact() + +def sha1_padding(message_length): + padding = b'\x80' + padding += b'\x00' * ((56 - (message_length + 1) % 64) % 64) + padding += struct.pack('>Q', message_length * 8) + return padding + +def get_mac(data: bytes) -> str: + return sha1(KEY.encode("latin1") + data).hexdigest() + + +if LOCAL: + print("Enter token:") + token = input() +else: + token = register() + +string_token = b64decode(token) +claims, mac = string_token.split(b"|mac=") + +print(f"{token} : {string_token}") + +padding = sha1_padding(KEY_LENGTH_BYTES + len(claims)) +injection = "|admin=true".encode("latin1") + +forged_msg = claims + padding + injection + +h = struct.unpack('>5I', bytes.fromhex(mac.decode("latin1"))) + +sha1 = SHA1(*h, message_byte_length=len(forged_msg) - len(injection)) +sha1.update(injection) + +forged_mac = sha1.digest().hex() + +key = input("Input Key") + +orig_sha1 = SHA1(*[0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0], message_byte_length=(len(forged_msg) + KEY_LENGTH_BYTES)) +orig_sha1.update(key.encode("latin1") + forged_msg) + +real_mac = orig_sha1.digest().hex() + + +print(f"forged mac: {forged_mac} | real mac: {real_mac}") + +secure_token = forged_msg + f"|mac={forged_mac}".encode("latin1") +secure_token = b64encode(secure_token).decode("latin1") + +if LOCAL: + print(secure_token) +else: + show_flag(secure_token) diff --git a/cscg25/crypto/intro2/main.py b/cscg25/crypto/intro2/main.py new file mode 100755 index 0000000..3a84ab2 --- /dev/null +++ b/cscg25/crypto/intro2/main.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 + +from hashlib import sha1 +from base64 import b64encode, b64decode +from secrets import token_hex + +from secret import FLAG + + +KEY = token_hex(16) + +print(KEY) + + +def get_mac(data: bytes) -> str: + return sha1(KEY.encode("latin1") + data).hexdigest() + + +def parse_token(token: str) -> dict: + # Decode token + token = b64decode(token) + print(token) + + # Check the MAC + token, mac = token.split(b"|mac=") + print(token, mac) + print(f"Calculated mac = {get_mac(token)}") + if get_mac(token) != mac.decode("latin1"): + return None + + # Parse values + values = dict() + for part in token.decode("latin1").split("|"): + key, value = part.split("=") + values[key] = value + return values + + +def generate_token(values: dict) -> str: + token = "|".join(f"{key}={value}" for key, value in values.items()) + secure_token = f"{token}|mac={get_mac(token.encode('latin1'))}" + + return b64encode(secure_token.encode("latin1")).decode("latin1") + + +def handle_register(): + name = input("What is you name? ") + animal = input("What is your favorite animal? ") + + token = generate_token( + { + "name": name, + "animal": animal, + "admin": "false", + } + ) + + print("Here is your access token:", token) + + +def handle_show_animal_videos(): + user_data = parse_token(input("Enter access token: ")) + + if user_data is None: + print("Invalid token.") + return + + print( + f"\nHere are some {user_data['animal']} videos for you: https://www.youtube.com/results?search_query=funny+{user_data['animal']}+video+compilation" + ) + + +def handle_show_flag(): + user_data = parse_token(input("Enter access token: ")) + + if user_data is None: + print("Invalid token.") + return + + if user_data["admin"] == "true": + print("The flag is", FLAG) + else: + print("You are not an admin.") + + +def main(): + while True: + # Show main menu + + print( + """ + 1. Register + 2. Show animal videos + 3. Show flag + 4. Exit + """ + ) + + try: + choice = int(input("Enter your choice: ")) + except ValueError: + print("Please enter a number next time.") + continue + except EOFError: + break + + if choice == 1: + handle_register() + elif choice == 2: + handle_show_animal_videos() + elif choice == 3: + handle_show_flag() + elif choice == 4: + break + else: + print("Please enter a valid choice.") + + +if __name__ == "__main__": + main() diff --git a/cscg25/crypto/intro2/secret.py b/cscg25/crypto/intro2/secret.py new file mode 100644 index 0000000..4778dda --- /dev/null +++ b/cscg25/crypto/intro2/secret.py @@ -0,0 +1 @@ +FLAG = "cscg{a1b2c3d4e5f67890abcdef1234567890abcdef1234567890abcdef1234}" diff --git a/cscg25/forensics/intro3/intro-forensics-3 b/cscg25/forensics/intro3/intro-forensics-3 new file mode 100644 index 0000000..0a7a3a4 Binary files /dev/null and b/cscg25/forensics/intro3/intro-forensics-3 differ