Merge branch 'main' of github.com:rayhanhanaputra/gemastik18-final

This commit is contained in:
Jonathan
2025-10-19 18:42:26 +07:00
11 changed files with 392 additions and 529 deletions
-32
View File
@@ -1,32 +0,0 @@
FROM python:3.12-slim
ARG PASSWORD=root
ENV DEBIAN_FRONTEND=noninteractive
ENV HOME=/home/ctf
WORKDIR /home/ctf/chall
RUN apt-get update && apt-get install -y --no-install-recommends \
openssh-server \
build-essential \
libffi-dev \
libssl-dev \
python3-dev \
bash \
&& rm -rf /var/lib/apt/lists/*
RUN useradd -m -d /home/ctf -s /bin/bash ctf && \
echo "ctf:${PASSWORD}" | chpasswd
RUN mkdir -p /var/run/sshd
COPY requirements.txt /tmp/requirements.txt
RUN pip install --no-cache-dir -r /tmp/requirements.txt
COPY ./src /home/ctf/chall/src
COPY ./start.sh /start.sh
RUN chmod +x /start.sh /home/ctf/chall/src/run.sh
RUN chown -R root:root /home/ctf/chall && chmod -R 555 /home/ctf/chall
EXPOSE 8000 22
CMD ["/start.sh"]
-126
View File
@@ -1,126 +0,0 @@
#!/usr/bin/env python3
import os, sys, json, random, hashlib, hmac
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
with open("/flag.txt", "rb") as f:
flag = f.read()
menu = (
"1) encrypt\n"
"2) profit\n"
"3) nyerah\n"
">> "
)
k = 1024
n = 169
rng = random.SystemRandom()
def rand(k_bits: int) -> int:
return rng.randrange(1, 1 << k_bits)
def gen(n: int, k_bits: int):
a = [rand(k_bits) for _ in range(n)]
return a
def b2b(b: bytes) -> list[int]:
out = []
for byte in b:
for i in range(8):
out.append((byte >> i) & 1)
return out
def pack(bits) -> bytes:
out = bytearray()
for i in range(0, len(bits), 8):
chunk = bits[i:i+8]
val = 0
for j, bit in enumerate(chunk):
val |= (bit & 1) << j
out.append(val)
return bytes(out)
def gen_key(x_bits: list[int], saltx: bytes, salty: bytes, length: int = 16) -> bytes:
material = pack(x_bits)
prk = hashlib.pbkdf2_hmac("sha256", material, saltx, 131072, dklen=32)
return hmac.new(prk, b"afk-players-wanted-now" + salty + b"\x01", hashlib.sha256).digest()[:length]
def enc(k: bytes, data: bytes):
iv = os.urandom(16)
ct = AES.new(k, AES.MODE_CBC, iv).encrypt(pad(data, 16))
return iv, ct
def add(a, x_bits) -> int:
return sum(ai for ai, xi in zip(a, x_bits) if xi)
def main():
a = gen(n, k)
x_bits = b2b(flag)
if len(x_bits) < n:
x_bits += [rng.randrange(0, 2) for _ in range(n - len(x_bits))]
else:
x_bits = x_bits[:n]
s = add(a, x_bits)
saltx = os.urandom(16)
salty = os.urandom(16)
key = gen_key(x_bits, saltx, salty)
iv, ct = enc(key, flag)
header = {
"n": n,
"k_bits": k,
}
print(json.dumps(header, separators=(",", ":")), flush=True)
while True:
try:
print(menu, end="", flush=True)
line = sys.stdin.readline()
if not line:
break
try:
choice = int(line.strip())
except ValueError:
print("sheesh")
continue
if choice == 1:
print("data: ", end="", flush=True)
dline = sys.stdin.readline()
if not dline:
break
try:
data = bytes.fromhex(dline.strip())
except Exception:
print("hmmm")
continue
iv, ct = enc(key, data)
print(iv.hex())
print(ct.hex())
elif choice == 2:
print(json.dumps({"a": a}, separators=(",", ":")))
print(str(s))
print(saltx.hex())
print(salty.hex())
print(iv.hex())
print(ct.hex())
elif choice == 3:
print("bubay")
return
else:
print("tidak ada yang mustahil, hehehe")
except Exception:
print("zzz")
if __name__ == "__main__":
main()
-126
View File
@@ -1,126 +0,0 @@
#!/usr/bin/env python3
import os, sys, json, random, hashlib, hmac
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
with open("/flag.txt", "rb") as f:
flag = f.read()
menu = (
"1) encrypt\n"
"2) profit\n"
"3) nyerah\n"
">> "
)
k = 1024
n = 169
rng = random.SystemRandom()
def rand(k_bits: int) -> int:
return rng.randrange(1, 1 << k_bits)
def gen(n: int, k_bits: int):
a = [rand(k_bits) for _ in range(n)]
return a
def b2b(b: bytes) -> list[int]:
out = []
for byte in b:
for i in range(8):
out.append((byte >> i) & 1)
return out
def pack(bits) -> bytes:
out = bytearray()
for i in range(0, len(bits), 8):
chunk = bits[i:i+8]
val = 0
for j, bit in enumerate(chunk):
val |= (bit & 1) << j
out.append(val)
return bytes(out)
def gen_key(x_bits: list[int], saltx: bytes, salty: bytes, length: int = 16) -> bytes:
material = pack(x_bits)
prk = hashlib.pbkdf2_hmac("sha256", material, saltx, 131072, dklen=32)
return hmac.new(prk, b"afk-players-wanted-now" + salty + b"\x01", hashlib.sha256).digest()[:length]
def enc(k: bytes, data: bytes):
iv = os.urandom(16)
ct = AES.new(k, AES.MODE_CBC, iv).encrypt(pad(data, 16))
return iv, ct
def add(a, x_bits) -> int:
return sum(ai for ai, xi in zip(a, x_bits) if xi)
def main():
a = gen(n, k)
x_bits = b2b(flag)
if len(x_bits) < n:
x_bits += [rng.randrange(0, 2) for _ in range(n - len(x_bits))]
else:
x_bits = x_bits[:n]
s = add(a, x_bits)
saltx = os.urandom(16)
salty = os.urandom(16)
key = gen_key(x_bits, saltx, salty)
iv, ct = enc(key, flag)
header = {
"n": n,
"k_bits": k,
}
print(json.dumps(header, separators=(",", ":")), flush=True)
while True:
try:
print(menu, end="", flush=True)
line = sys.stdin.readline()
if not line:
break
try:
choice = int(line.strip())
except ValueError:
print("sheesh")
continue
if choice == 1:
print("data: ", end="", flush=True)
dline = sys.stdin.readline()
if not dline:
break
try:
data = bytes.fromhex(dline.strip())
except Exception:
print("hmmm")
continue
iv, ct = enc(key, data)
print(iv.hex())
print(ct.hex())
elif choice == 2:
print(json.dumps({"a": a}, separators=(",", ":")))
print(str(s))
print(saltx.hex())
print(salty.hex())
print(iv.hex())
print(ct.hex())
elif choice == 3:
print("bubay")
return
else:
print("tidak ada yang mustahil, hehehe")
except Exception:
print("zzz")
if __name__ == "__main__":
main()
-16
View File
@@ -1,16 +0,0 @@
version: "3.8"
services:
phew:
container_name: phew_container
hostname: phew
restart: always
build:
context: .
args:
- PASSWORD=root
ports:
- "13000:8000"
- "13022:22"
environment:
- FLAG=GEMASTIK{local_flag}
-1
View File
@@ -1 +0,0 @@
pycryptodome
-3
View File
@@ -1,3 +0,0 @@
#!/bin/sh
exec socat tcp-l:8000,reuseaddr,fork exec:"python3 ./chall.py"
-25
View File
@@ -1,25 +0,0 @@
#!/bin/bash
set -e
ssh-keygen -A
# Configure SSH
grep -q "^PermitRootLogin" /etc/ssh/sshd_config && \
sed -i "s/^PermitRootLogin.*/PermitRootLogin no/" /etc/ssh/sshd_config || \
echo "PermitRootLogin no" >> /etc/ssh/sshd_config
grep -q "^PasswordAuthentication" /etc/ssh/sshd_config && \
sed -i "s/^PasswordAuthentication.*/PasswordAuthentication yes/" /etc/ssh/sshd_config || \
echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config
echo "AllowUsers ctf" >> /etc/ssh/sshd_config
/usr/sbin/sshd
if [ -n "$FLAG" ]; then
echo "$FLAG" > /flag.txt
chmod 644 /flag.txt
chown root:root /flag.txt
fi
exec su -c "cd /home/ctf/chall/src && ./run.sh" -s /bin/bash ctf
+100 -100
View File
@@ -1,116 +1,116 @@
#!/usr/bin/env python3
import os, sys, json, random, hashlib, hmac
import os
import binascii
import hashlib
import threading
import time
import sys
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
with open("/flag.txt", "rb") as f:
from Crypto.Util.Padding import pad, unpad
seed_bits = 23
seed_max = 1 << seed_bits
seed_len = (seed_bits + 7) // 8
key = os.urandom(16)
def hash_seed(seed_int: int) -> bytes:
sb = seed_int.to_bytes(seed_len, "big")
return hashlib.sha256(sb).digest()[:16]
seed = int.from_bytes(os.urandom(4), "big") % seed_max
seed2 = int.from_bytes(os.urandom(4), "big") % seed_max
K1 = hash_seed(seed)
K2 = hash_seed(seed2)
with open("./flag.txt", "rb") as f:
flag = f.read()
B = 16
opts = (
"1) encrypt\n"
"2) profit\n"
"3) nyerah\n"
">> "
)
def exp(prk: bytes, info: bytes, L: int) -> bytes:
return hmac.new(prk, info + b"\x01", hashlib.sha256).digest()[:L]
def read_hex(prompt: str):
s = input(prompt).strip()
try:
return binascii.unhexlify(s)
except Exception:
print("hmm")
return None
def enc(k: bytes, data: bytes):
iv = os.urandom(B)
ct = AES.new(k, AES.MODE_CBC, iv).encrypt(pad(data, B))
return iv, ct
def enc_cfb(pt: bytes) -> bytes:
iv = os.urandom(16)
aes = AES.new(key, AES.MODE_CFB, iv=iv, segment_size=128)
ct = aes.encrypt(pt)
return iv + ct
def inp_hex(prompt: str) -> bytes:
print(prompt, end="", flush=True)
s = sys.stdin.readline()
if not s:
raise EOFError
return bytes.fromhex(s.strip())
def enc_cbc(data: bytes, iv1: bytes, iv2: bytes, padd: bool) -> bytes:
x = pad(data, 16) if padd else data
c1 = AES.new(K1, AES.MODE_CBC, iv=iv1).encrypt(x)
c2 = AES.new(K2, AES.MODE_CBC, iv=iv2).encrypt(c1)
return c2
def rand(rng, d, lo, hi):
while True:
v = [rng.randint(lo, hi) for _ in range(d)]
if any(v):
return v
def menu():
print("""
1. encrypt
2. profit
3. get third
4. exit
""")
def syst(rng):
d = rng.choice([2, 3])
m = rng.randint(5, 8)
x = rand(rng, d, -3, 3)
rows = []
for _ in range(m):
base = rand(rng, d, -3, 3)
r = rng.randint(1, 7)
scaled = [r * a for a in base]
e = rng.randint(0, 1)
bi = sum(ai * xi for ai, xi in zip(scaled, x)) + e
rows.append((scaled, bi))
rng.shuffle(rows)
A = [row for (row, _) in rows]
B = [b for (_, b) in rows]
pub = {"dim": d, "A": A, "b": B}
return pub, tuple(x)
third = 0
iv11 = None
iv22 = None
def bundle():
rng = random.Random(os.urandom(16))
systems = []
hidden = []
for _ in range(4):
pub, x = syst(rng)
systems.append(pub)
hidden.append(x)
return {"systems": systems}, tuple(hidden)
def alarm():
time.sleep(180)
print("zzz")
sys.exit(0)
def get_key(saltx: bytes, salty: bytes, b):
parts = []
for x in b:
parts.append(",".join(str(t) for t in x))
material = "|".join(parts).encode()
prk = hashlib.pbkdf2_hmac("sha256", material, saltx, 131072, dklen=32)
return exp(prk, b"g3m4zzzt1q" + salty, 16)
threading.Thread(target=alarm, daemon=True).start()
def main():
a, b = bundle()
print(json.dumps(a, separators=(",", ":")), flush=True)
saltx = os.urandom(16)
salty = os.urandom(16)
key = get_key(saltx, salty, b)
iv, ct = enc(key, flag)
while True:
try:
print(opts, end="", flush=True)
line = sys.stdin.readline()
if not line:
break
try:
choice = int(line.strip())
except ValueError:
print("sheesh")
continue
while True:
menu()
op = input("> ").strip()
if choice == 1:
data = inp_hex("data: ")
iv, ct = enc(key, data)
print(iv.hex())
print(ct.hex())
if op == "1":
data = read_hex("pt: ")
if data is None:
print()
continue
out = enc_cfb(data)
print("ct: ", out.hex())
print()
elif choice == 2:
print(iv.hex())
print(ct.hex())
print(saltx.hex())
print(salty.hex())
elif op == "2":
if iv11 is not None and iv22 is not None:
iv1, iv2 = iv11, iv22
iv11 = iv22 = None
else:
iv1 = os.urandom(16)
iv2 = os.urandom(16)
ct = enc_cbc(flag, iv1, iv2, padd=True)
print("iv1: ", iv1.hex())
print("iv2: ", iv2.hex())
print("ct: ", ct.hex())
print()
elif choice == 3:
print("bubay")
return
elif op == "3":
if third:
print("sheesh")
continue
block = read_hex("pt: ")
if block is None:
print()
continue
if len(block) != 16:
print("hmmm\n")
continue
iv1 = os.urandom(16)
iv2 = os.urandom(16)
ct = enc_cbc(block, iv1, iv2, padd=False)
iv11, iv22 = iv1, iv2
print("ct: ", ct.hex())
third = 1
print()
else:
print("when you feel like quitting, remember why you started :v (yapping)")
except Exception:
print("zzz")
if __name__ == "__main__":
main()
elif op == "4":
break
else:
print("mabokkkk?")
+100 -100
View File
@@ -1,116 +1,116 @@
#!/usr/bin/env python3
import os, sys, json, random, hashlib, hmac
import os
import binascii
import hashlib
import threading
import time
import sys
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
with open("/flag.txt", "rb") as f:
from Crypto.Util.Padding import pad, unpad
seed_bits = 23
seed_max = 1 << seed_bits
seed_len = (seed_bits + 7) // 8
key = os.urandom(16)
def hash_seed(seed_int: int) -> bytes:
sb = seed_int.to_bytes(seed_len, "big")
return hashlib.sha256(sb).digest()[:16]
seed = int.from_bytes(os.urandom(4), "big") % seed_max
seed2 = int.from_bytes(os.urandom(4), "big") % seed_max
K1 = hash_seed(seed)
K2 = hash_seed(seed2)
with open("./flag.txt", "rb") as f:
flag = f.read()
B = 16
opts = (
"1) encrypt\n"
"2) profit\n"
"3) nyerah\n"
">> "
)
def exp(prk: bytes, info: bytes, L: int) -> bytes:
return hmac.new(prk, info + b"\x01", hashlib.sha256).digest()[:L]
def read_hex(prompt: str):
s = input(prompt).strip()
try:
return binascii.unhexlify(s)
except Exception:
print("hmm")
return None
def enc(k: bytes, data: bytes):
iv = os.urandom(B)
ct = AES.new(k, AES.MODE_CBC, iv).encrypt(pad(data, B))
return iv, ct
def enc_cfb(pt: bytes) -> bytes:
iv = os.urandom(16)
aes = AES.new(key, AES.MODE_CFB, iv=iv, segment_size=128)
ct = aes.encrypt(pt)
return iv + ct
def inp_hex(prompt: str) -> bytes:
print(prompt, end="", flush=True)
s = sys.stdin.readline()
if not s:
raise EOFError
return bytes.fromhex(s.strip())
def enc_cbc(data: bytes, iv1: bytes, iv2: bytes, padd: bool) -> bytes:
x = pad(data, 16) if padd else data
c1 = AES.new(K1, AES.MODE_CBC, iv=iv1).encrypt(x)
c2 = AES.new(K2, AES.MODE_CBC, iv=iv2).encrypt(c1)
return c2
def rand(rng, d, lo, hi):
while True:
v = [rng.randint(lo, hi) for _ in range(d)]
if any(v):
return v
def menu():
print("""
1. encrypt
2. profit
3. get third
4. exit
""")
def syst(rng):
d = rng.choice([2, 3])
m = rng.randint(5, 8)
x = rand(rng, d, -3, 3)
rows = []
for _ in range(m):
base = rand(rng, d, -3, 3)
r = rng.randint(1, 7)
scaled = [r * a for a in base]
e = rng.randint(0, 1)
bi = sum(ai * xi for ai, xi in zip(scaled, x)) + e
rows.append((scaled, bi))
rng.shuffle(rows)
A = [row for (row, _) in rows]
B = [b for (_, b) in rows]
pub = {"dim": d, "A": A, "b": B}
return pub, tuple(x)
third = 0
iv11 = None
iv22 = None
def bundle():
rng = random.Random(os.urandom(16))
systems = []
hidden = []
for _ in range(4):
pub, x = syst(rng)
systems.append(pub)
hidden.append(x)
return {"systems": systems}, tuple(hidden)
def alarm():
time.sleep(180)
print("zzz")
sys.exit(0)
def get_key(saltx: bytes, salty: bytes, b):
parts = []
for x in b:
parts.append(",".join(str(t) for t in x))
material = "|".join(parts).encode()
prk = hashlib.pbkdf2_hmac("sha256", material, saltx, 131072, dklen=32)
return exp(prk, b"g3m4zzzt1q" + salty, 16)
threading.Thread(target=alarm, daemon=True).start()
def main():
a, b = bundle()
print(json.dumps(a, separators=(",", ":")), flush=True)
saltx = os.urandom(16)
salty = os.urandom(16)
key = get_key(saltx, salty, b)
iv, ct = enc(key, flag)
while True:
try:
print(opts, end="", flush=True)
line = sys.stdin.readline()
if not line:
break
try:
choice = int(line.strip())
except ValueError:
print("sheesh")
continue
while True:
menu()
op = input("> ").strip()
if choice == 1:
data = inp_hex("data: ")
iv, ct = enc(key, data)
print(iv.hex())
print(ct.hex())
if op == "1":
data = read_hex("pt: ")
if data is None:
print()
continue
out = enc_cfb(data)
print("ct: ", out.hex())
print()
elif choice == 2:
print(iv.hex())
print(ct.hex())
print(saltx.hex())
print(salty.hex())
elif op == "2":
if iv11 is not None and iv22 is not None:
iv1, iv2 = iv11, iv22
iv11 = iv22 = None
else:
iv1 = os.urandom(16)
iv2 = os.urandom(16)
ct = enc_cbc(flag, iv1, iv2, padd=True)
print("iv1: ", iv1.hex())
print("iv2: ", iv2.hex())
print("ct: ", ct.hex())
print()
elif choice == 3:
print("bubay")
return
elif op == "3":
if third:
print("sheesh")
continue
block = read_hex("pt: ")
if block is None:
print()
continue
if len(block) != 16:
print("hmmm\n")
continue
iv1 = os.urandom(16)
iv2 = os.urandom(16)
ct = enc_cbc(block, iv1, iv2, padd=False)
iv11, iv22 = iv1, iv2
print("ct: ", ct.hex())
third = 1
print()
else:
print("when you feel like quitting, remember why you started :v (yapping)")
except Exception:
print("zzz")
if __name__ == "__main__":
main()
elif op == "4":
break
else:
print("mabokkkk?")