changed repo structure

This commit is contained in:
2025-06-06 02:50:04 +02:00
parent e887de976a
commit 6e6ee357b8
8848 changed files with 2089898 additions and 9 deletions

View File

@@ -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)

60
2025/cscg/crypto/intro1/main.py Executable file
View File

@@ -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()

View File

@@ -0,0 +1 @@
FLAG = "cscg{a1b2c3d4e5f67890abcdef1234567890abcdef1234567890abcdef1234}"

View File

@@ -0,0 +1,65 @@
from pwn import process, remote
from base64 import b64encode, b64decode
import hlextend
KEY_LENGTH_BYTES = 16
LOCAL = True
if LOCAL:
p = process(["python", "main.py"])# Define functions for convenience
else:
p = remote("2b571e00edfb5dd61b8f7f30-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:"
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: str):
p.recvuntil(menu_string)
p.sendline(b"3")
p.recvuntil(b": ")
p.sendline(token)
token = register()
string_token = b64decode(token)
claims, mac = string_token.split(b"|mac=")
print(f"{token} : {string_token}")
print(f"{claims}")
print(f"{mac}")
injection = "|admin=true".encode("latin1")
sha_forge = hlextend.new('sha1')
forged_msg = sha_forge.extend(injection, claims, KEY_LENGTH_BYTES, mac.decode("latin1"))
print(forged_msg)
forged_mac = sha_forge.hexdigest()
secure_token = forged_msg + f"|mac={forged_mac}".encode("latin1")
print(secure_token)
secure_token = b64encode(secure_token).decode("latin1")
print("------------ attacked system ---------")
show_flag(secure_token)
print(p.recvuntil(b":").decode())
p.close()

View File

@@ -0,0 +1,441 @@
# Copyright (C) 2014 by Stephen Bradshaw
#
# SHA1 and SHA2 generation routines from SlowSha https://code.google.com/p/slowsha/
# which is: Copyright (C) 2011 by Stefano Palazzo
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
'''
Pure Python Hash Length Extension module.
Currently supports SHA1, SHA256 and SHA512, more algorithms will
be added in the future.
Create a hash by calling one of the named constuctor functions:
sha1(), sha256(), and sha512(), or by calling new(algorithm).
The hash objects have the following methods:
hash(message):
Feeds data into the hash function using the normal interface.
extend(appendData, knownData, secretLength, startHash):
Performs a hash length extension attack. Returns the bytestring to
use when appending data.
hexdigest():
Returns a hexlified version of the hash output.
Assume you have a hash generated from an unknown secret value concatenated with
a known value, and you want to be able to produce a valid hash after appending
additional data to the known value.
If the hash algorithm used is one of the vulnerable functions implemented in
this module, is is possible to achieve this without knowing the secret value
as long as you know (or can guess, perhaps by brute force) the length of that
secret value. This is called a hash length extension attack.
Given an existing sha1 hash value '52e98441017043eee154a6d1af98c5e0efab055c',
known data of 'hello', an unknown secret of length 10 and data you wish
to append of 'file', you would do the following to perform the attack:
>>> import hlextend
>>> sha = hlextend.new('sha1')
>>> print sha.extend(b'file', b'hello', 10, '52e98441017043eee154a6d1af98c5e0efab055c')
b'hello\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00xfile'
>>> print sha.hexdigest()
c60fa7de0860d4048a3bfb36b70299a95e6587c9
The unknown secret (of length 10), that when hashed appended with 'hello' produces
a SHA1 hash of '52e98441017043eee154a6d1af98c5e0efab055c', will then produce
a SHA1 hash of 'c60fa7de0860d4048a3bfb36b70299a95e6587c9' when appended with the output
from the extend function above.
If you are not sure of the exact length of the secret value, simply try the above
multiple times specifying different values for the length to brute force.
'''
from re import match
from math import ceil
from typing import Union
__version__ = "0.2"
class Hash(object):
'''Parent class for hash functions'''
def hash(self, message):
'''Normal input for data into hash function'''
length = bin(len(message) * 8)[2:].rjust(self._blockSize, "0")
while len(message) > self._blockSize:
self._transform(''.join([bin(a)[2:].rjust(8, "0")
for a in message[:self._blockSize]]))
message = message[self._blockSize:]
message = self.__hashBinaryPad(message, length)
for a in range(len(message) // self._b2):
self._transform(message[a * self._b2:a * self._b2 + self._b2])
def extend(self, appendData, knownData, secretLength, startHash):
'''Hash length extension input for data into hash function'''
self.__checkInput(secretLength, startHash)
self.__setStartingHash(startHash)
extendLength = self.__hashGetExtendLength(
secretLength, knownData, appendData)
message = appendData
while len(message) > self._blockSize:
self._transform(''.join([bin(a)[2:].rjust(8, "0")
for a in message[:self._blockSize]]))
message = message[self._blockSize:]
message = self.__hashBinaryPad(message, extendLength)
for i in range(len(message) // self._b2):
self._transform(message[i * self._b2:i * self._b2 + self._b2])
return self.__hashGetPadData(secretLength, knownData, appendData)
def hexdigest(self):
'''Outputs hash data in hexlified format'''
return ''.join([(('%0' + str(self._b1) + 'x') % (a)) for a in self.__digest()])
def __init__(self):
# pre calculate some values that get used a lot
self._b1 = self._blockSize/8
self._b2 = self._blockSize*8
def __digest(self):
return [self.__getattribute__(a) for a in dir(self) if match('^_h\d+$', a)]
def __setStartingHash(self, startHash):
c = 0
hashVals = [int(startHash[a:a+int(self._b1)], base=16)
for a in range(0, len(startHash), int(self._b1))]
for hv in [a for a in dir(self) if match('^_h\d+$', a)]:
self.__setattr__(hv, hashVals[c])
c += 1
def __checkInput(self, secretLength, startHash):
if not isinstance(secretLength, int):
raise TypeError('secretLength must be a valid integer')
if secretLength < 1:
raise ValueError('secretLength must be grater than 0')
if not match('^[a-fA-F0-9]{' + str(len(self.hexdigest())) + '}$', startHash):
raise ValueError('startHash must be a string of length ' +
str(len(self.hexdigest())) + ' in hexlified format')
def __byter(self, byteVal):
'''Helper function to return usable values for hash extension append data'''
if byteVal < 0x20 or byteVal > 0x7e:
return '\\x%02x' % (byteVal)
else:
return chr(byteVal)
def __binToByte(self, binary) -> bytearray:
return int(binary, 2).to_bytes(len(binary) // 8, byteorder='big')
def __hashGetExtendLength(self, secretLength, knownData, appendData):
'''Length function for hash length extension attacks'''
# binary length (secretLength + len(knownData) + size of binarysize+1) rounded to a multiple of blockSize + length of appended data
originalHashLength = int(ceil(
(secretLength+len(knownData)+self._b1+1)/float(self._blockSize)) * self._blockSize)
newHashLength = originalHashLength + len(appendData)
return bin(newHashLength * 8)[2:].rjust(self._blockSize, "0")
def __hashGetPadData(self, secretLength, knownData, appendData):
'''Return append value for hash extension attack'''
originalHashLength = bin(
(secretLength+len(knownData)) * 8)[2:].rjust(self._blockSize, "0")
padData = ''.join(bin(i)[2:].rjust(8, "0")
for i in knownData) + "1"
padData += "0" * (((self._blockSize*7) - (len(padData)+(secretLength*8)) %
self._b2) % self._b2) + originalHashLength
return self.__binToByte(padData) + appendData
def __hashBinaryPad(self, message, length):
'''Pads the final blockSize block with \x80, zeros, and the length, converts to binary'''
out_msg = ''
for i in message:
out_msg += bin(i)[2:].rjust(8, "0")
out_msg += "1"
out_msg += "0" * (((self._blockSize*7) - len(out_msg) % self._b2) % self._b2) + length
return out_msg
class SHA1 (Hash):
_h0, _h1, _h2, _h3, _h4, = 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
_blockSize = 64
def _transform(self, chunk):
def lrot(x, n): return (x << n) | (x >> (32 - n))
w = []
for j in range(len(chunk) // 32):
w.append(int(chunk[j * 32:j * 32 + 32], 2))
for i in range(16, 80):
w.append(lrot(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1)
& 0xffffffff)
a = self._h0
b = self._h1
c = self._h2
d = self._h3
e = self._h4
for i in range(80):
if i <= i <= 19:
f, k = d ^ (b & (c ^ d)), 0x5a827999
elif 20 <= i <= 39:
f, k = b ^ c ^ d, 0x6ed9eba1
elif 40 <= i <= 59:
f, k = (b & c) | (d & (b | c)), 0x8f1bbcdc
elif 60 <= i <= 79:
f, k = b ^ c ^ d, 0xca62c1d6
temp = lrot(a, 5) + f + e + k + w[i] & 0xffffffff
a, b, c, d, e = temp, a, lrot(b, 30), c, d
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
class SHA256 (Hash):
_h0, _h1, _h2, _h3, _h4, _h5, _h6, _h7 = (
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19)
_blockSize = 64
def _transform(self, chunk):
def rrot(x, n): return (x >> n) | (x << (32 - n))
w = []
k = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]
for j in range(len(chunk) // 32):
w.append(int(chunk[j * 32:j * 32 + 32], 2))
for i in range(16, 64):
s0 = rrot(w[i - 15], 7) ^ rrot(w[i - 15], 18) ^ (w[i - 15] >> 3)
s1 = rrot(w[i - 2], 17) ^ rrot(w[i - 2], 19) ^ (w[i - 2] >> 10)
w.append((w[i - 16] + s0 + w[i - 7] + s1) & 0xffffffff)
a = self._h0
b = self._h1
c = self._h2
d = self._h3
e = self._h4
f = self._h5
g = self._h6
h = self._h7
for i in range(64):
s0 = rrot(a, 2) ^ rrot(a, 13) ^ rrot(a, 22)
maj = (a & b) ^ (a & c) ^ (b & c)
t2 = s0 + maj
s1 = rrot(e, 6) ^ rrot(e, 11) ^ rrot(e, 25)
ch = (e & f) ^ ((~ e) & g)
t1 = h + s1 + ch + k[i] + w[i]
h = g
g = f
f = e
e = (d + t1) & 0xffffffff
d = c
c = b
b = a
a = (t1 + t2) & 0xffffffff
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
self._h5 = (self._h5 + f) & 0xffffffff
self._h6 = (self._h6 + g) & 0xffffffff
self._h7 = (self._h7 + h) & 0xffffffff
class SHA512 (Hash):
_h0, _h1, _h2, _h3, _h4, _h5, _h6, _h7 = (
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b,
0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f,
0x1f83d9abfb41bd6b, 0x5be0cd19137e2179)
_blockSize = 128
def _transform(self, chunk):
def rrot(x, n): return (x >> n) | (x << (64 - n))
w = []
k = [
0x428a2f98d728ae22, 0x7137449123ef65cd,
0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
0x3956c25bf348b538, 0x59f111f1b605d019,
0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
0xd807aa98a3030242, 0x12835b0145706fbe,
0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f, 0x80deb1fe3b1696b1,
0x9bdc06a725c71235, 0xc19bf174cf692694,
0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483,
0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
0x983e5152ee66dfab, 0xa831c66d2db43210,
0xb00327c898fb213f, 0xbf597fc7beef0ee4,
0xc6e00bf33da88fc2, 0xd5a79147930aa725,
0x06ca6351e003826f, 0x142929670a0e6e70,
0x27b70a8546d22ffc, 0x2e1b21385c26c926,
0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
0x650a73548baf63de, 0x766a0abb3c77b2a8,
0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001,
0xc24b8b70d0f89791, 0xc76c51a30654be30,
0xd192e819d6ef5218, 0xd69906245565a910,
0xf40e35855771202a, 0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
0x748f82ee5defb2fc, 0x78a5636f43172f60,
0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9,
0xbef9a3f7b2c67915, 0xc67178f2e372532b,
0xca273eceea26619c, 0xd186b8c721c0c207,
0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
0x06f067aa72176fba, 0x0a637dc5a2c898a6,
0x113f9804bef90dae, 0x1b710b35131c471b,
0x28db77f523047d84, 0x32caab7b40c72493,
0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
0x5fcb6fab3ad6faec, 0x6c44198c4a475817]
for j in range(len(chunk) // 64):
w.append(int(chunk[j * 64:j * 64 + 64], 2))
for i in range(16, 80):
s0 = rrot(w[i - 15], 1) ^ rrot(w[i - 15], 8) ^ (w[i - 15] >> 7)
s1 = rrot(w[i - 2], 19) ^ rrot(w[i - 2], 61) ^ (w[i - 2] >> 6)
w.append((w[i - 16] + s0 + w[i - 7] + s1) & 0xffffffffffffffff)
a = self._h0
b = self._h1
c = self._h2
d = self._h3
e = self._h4
f = self._h5
g = self._h6
h = self._h7
for i in range(80):
s0 = rrot(a, 28) ^ rrot(a, 34) ^ rrot(a, 39)
maj = (a & b) ^ (a & c) ^ (b & c)
t2 = s0 + maj
s1 = rrot(e, 14) ^ rrot(e, 18) ^ rrot(e, 41)
ch = (e & f) ^ ((~ e) & g)
t1 = h + s1 + ch + k[i] + w[i]
h = g
g = f
f = e
e = (d + t1) & 0xffffffffffffffff
d = c
c = b
b = a
a = (t1 + t2) & 0xffffffffffffffff
self._h0 = (self._h0 + a) & 0xffffffffffffffff
self._h1 = (self._h1 + b) & 0xffffffffffffffff
self._h2 = (self._h2 + c) & 0xffffffffffffffff
self._h3 = (self._h3 + d) & 0xffffffffffffffff
self._h4 = (self._h4 + e) & 0xffffffffffffffff
self._h5 = (self._h5 + f) & 0xffffffffffffffff
self._h6 = (self._h6 + g) & 0xffffffffffffffff
self._h7 = (self._h7 + h) & 0xffffffffffffffff
def new(algorithm) -> Union[SHA1, SHA256, SHA512]:
obj = {
'sha1': SHA1,
'sha256': SHA256,
'sha512': SHA512,
}[algorithm]()
return obj
def sha1():
''' Returns a new sha1 hash object '''
return new('sha1')
def sha256():
''' Returns a new sha256 hash object '''
return new('sha256', )
def sha512():
''' Returns a new sha512 hash object '''
return new('sha512', )
__all__ = ('sha1', 'sha256', 'sha512')

117
2025/cscg/crypto/intro2/main.py Executable file
View File

@@ -0,0 +1,117 @@
#!/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)
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(mac)
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()

View File

@@ -0,0 +1 @@
FLAG = "cscg{a1b2c3d4e5f67890abcdef1234567890abcdef1234567890abcdef1234}"

View File

@@ -0,0 +1,45 @@
from z3 import Solver, BitVec, sat
def rng(x, size):
return (x*A+B) & ((2**size)-1)
def gen_random(seed, bits, mask):
state = seed
while True:
state = rng(state, bits)
yield state & mask
A = BitVec("A", 56)
B = BitVec("B", 56)
SEED = BitVec("seed", 56)
BITS = 56
MASK = 0xFF
state = SEED
with open("./msg.txt", "r") as f:
nums = [int(n) for n in f.readlines()[1:]]
print(nums)
flag_bytes = [BitVec(f'flag_{i}', 56) for i in range(142)]
solver = Solver()
for i, n in enumerate(nums):
state = rng(state, BITS)
cur_num = state & MASK
solver.add(n == cur_num ^ flag_bytes[i])
solver.add(flag_bytes[i] >= 32, flag_bytes[i] <= 126)
if solver.check() == sat:
model = solver.model()
flag = ''.join([chr(model[flag_bytes[i]].as_long()) for i in range(142)])
print(model)
print(flag)
else:
print("Not solveable")

View File

@@ -0,0 +1,28 @@
import os
import struct
BITS = 56
FLAG = os.getenv("FLAG", "CSCG{TESTFLAG}")
A = int.from_bytes(os.urandom(BITS//8), "little")
B = int.from_bytes(os.urandom(BITS//8), "little")
SEED = int.from_bytes(os.urandom(BITS//8), "little")
def rng(x, size):
return (x*A+B) & ((2**size)-1)
def gen_random(seed, bits, mask):
state = seed
while True:
state = rng(state, bits)
yield state & mask
def main():
print("Here are some random numbers, now guess the flag")
rng = gen_random(SEED, BITS, 0xFF)
for i in range(len(FLAG)):
print(next(rng) ^ ord(FLAG[i]))
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,143 @@
Here are some random numbers, now guess the flag
131
133
203
41
107
11
53
11
25
236
124
4
220
107
146
127
121
204
156
100
59
75
242
95
217
44
44
71
135
171
85
171
57
12
92
167
231
139
181
139
153
108
252
132
92
235
18
255
249
76
28
228
188
203
117
207
89
172
188
199
7
43
213
43
185
140
204
39
103
11
53
15
25
236
124
4
219
107
149
107
121
219
140
100
59
75
242
95
217
44
44
68
155
171
85
175
57
27
76
164
252
139
181
143
153
108
252
135
71
235
21
239
249
76
28
228
187
203
117
207
89
187
172
196
27
43
213
43
185
140
204
36
124
11
53
15
25
236
105
115
141
91

View File

@@ -0,0 +1,24 @@
from pwn import remote
import re
from base64 import b64decode
from sympy import factorint
from Crypto.Util.number import bytes_to_long, inverse, long_to_bytes
with remote("d7c40d8ec4e734fe7ac812f9-1338-shadows-of-neon-city.challenge.cscg.live", "1337", ssl=True) as conn:
data = conn.recvuntil(b":\n").decode("utf-8")
print(data)
matches = re.findall(r'(\w+)\s*=\s*([\w/=+]+)', data)
locals().update({key: value if not value.isdigit() else int(value) for key, value in matches})
cipher = bytes_to_long(b64decode(cipher))
p,q = factorint(n).keys()
n = p * q
phi_n = (p-1) * (q-1)
d = inverse(e, phi_n)
plain_int = pow(cipher, d, n)
plaintext = long_to_bytes(plain_int)
conn.sendline(plaintext)
conn.interactive()