From 002f99764111f537e3ddb38ea14f6abf113394ef Mon Sep 17 00:00:00 2001 From: itoid Date: Sat, 11 Oct 2025 22:45:10 +0700 Subject: [PATCH 1/7] Delete services/phew directory --- services/phew/Dockerfile | 32 -------- services/phew/chall.py | 126 ------------------------------- services/phew/dist/chall.py | 126 ------------------------------- services/phew/docker-compose.yml | 16 ---- services/phew/requirements.txt | 1 - services/phew/run.sh | 3 - services/phew/start.sh | 25 ------ 7 files changed, 329 deletions(-) delete mode 100644 services/phew/Dockerfile delete mode 100644 services/phew/chall.py delete mode 100644 services/phew/dist/chall.py delete mode 100644 services/phew/docker-compose.yml delete mode 100644 services/phew/requirements.txt delete mode 100644 services/phew/run.sh delete mode 100644 services/phew/start.sh diff --git a/services/phew/Dockerfile b/services/phew/Dockerfile deleted file mode 100644 index 0d0920d..0000000 --- a/services/phew/Dockerfile +++ /dev/null @@ -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"] diff --git a/services/phew/chall.py b/services/phew/chall.py deleted file mode 100644 index a7bea1b..0000000 --- a/services/phew/chall.py +++ /dev/null @@ -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() diff --git a/services/phew/dist/chall.py b/services/phew/dist/chall.py deleted file mode 100644 index a7bea1b..0000000 --- a/services/phew/dist/chall.py +++ /dev/null @@ -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() diff --git a/services/phew/docker-compose.yml b/services/phew/docker-compose.yml deleted file mode 100644 index 48b947b..0000000 --- a/services/phew/docker-compose.yml +++ /dev/null @@ -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} diff --git a/services/phew/requirements.txt b/services/phew/requirements.txt deleted file mode 100644 index c21b6ec..0000000 --- a/services/phew/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -pycryptodome \ No newline at end of file diff --git a/services/phew/run.sh b/services/phew/run.sh deleted file mode 100644 index 6ae49cb..0000000 --- a/services/phew/run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -exec socat tcp-l:8000,reuseaddr,fork exec:"python3 ./chall.py" diff --git a/services/phew/start.sh b/services/phew/start.sh deleted file mode 100644 index 7b40126..0000000 --- a/services/phew/start.sh +++ /dev/null @@ -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 From cbe65e88bd7f55a331dc64ed36da28aead4deeb3 Mon Sep 17 00:00:00 2001 From: itoid Date: Sat, 11 Oct 2025 22:45:20 +0700 Subject: [PATCH 2/7] Delete services/sheesh directory --- services/sheesh/Dockerfile | 32 -------- services/sheesh/chall.py | 116 ----------------------------- services/sheesh/dist/chall.py | 116 ----------------------------- services/sheesh/docker-compose.yml | 16 ---- services/sheesh/requirements.txt | 1 - services/sheesh/run.sh | 3 - services/sheesh/start.sh | 24 ------ 7 files changed, 308 deletions(-) delete mode 100644 services/sheesh/Dockerfile delete mode 100644 services/sheesh/chall.py delete mode 100644 services/sheesh/dist/chall.py delete mode 100644 services/sheesh/docker-compose.yml delete mode 100644 services/sheesh/requirements.txt delete mode 100644 services/sheesh/run.sh delete mode 100644 services/sheesh/start.sh diff --git a/services/sheesh/Dockerfile b/services/sheesh/Dockerfile deleted file mode 100644 index 073dd6a..0000000 --- a/services/sheesh/Dockerfile +++ /dev/null @@ -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"] diff --git a/services/sheesh/chall.py b/services/sheesh/chall.py deleted file mode 100644 index 1b507bf..0000000 --- a/services/sheesh/chall.py +++ /dev/null @@ -1,116 +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() - -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 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 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 rand(rng, d, lo, hi): - while True: - v = [rng.randint(lo, hi) for _ in range(d)] - if any(v): - return v - -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) - -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 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) - -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 - - if choice == 1: - data = inp_hex("data: ") - iv, ct = enc(key, data) - print(iv.hex()) - print(ct.hex()) - - elif choice == 2: - print(iv.hex()) - print(ct.hex()) - print(saltx.hex()) - print(salty.hex()) - - elif choice == 3: - print("bubay") - return - - else: - print("when you feel like quitting, remember why you started :v (yapping)") - - except Exception: - print("zzz") - -if __name__ == "__main__": - main() diff --git a/services/sheesh/dist/chall.py b/services/sheesh/dist/chall.py deleted file mode 100644 index 1b507bf..0000000 --- a/services/sheesh/dist/chall.py +++ /dev/null @@ -1,116 +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() - -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 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 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 rand(rng, d, lo, hi): - while True: - v = [rng.randint(lo, hi) for _ in range(d)] - if any(v): - return v - -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) - -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 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) - -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 - - if choice == 1: - data = inp_hex("data: ") - iv, ct = enc(key, data) - print(iv.hex()) - print(ct.hex()) - - elif choice == 2: - print(iv.hex()) - print(ct.hex()) - print(saltx.hex()) - print(salty.hex()) - - elif choice == 3: - print("bubay") - return - - else: - print("when you feel like quitting, remember why you started :v (yapping)") - - except Exception: - print("zzz") - -if __name__ == "__main__": - main() diff --git a/services/sheesh/docker-compose.yml b/services/sheesh/docker-compose.yml deleted file mode 100644 index e1eb8ca..0000000 --- a/services/sheesh/docker-compose.yml +++ /dev/null @@ -1,16 +0,0 @@ -version: "3.8" - -services: - sheesh: - container_name: sheesh_container - hostname: sheesh - restart: always - build: - context: . - args: - - PASSWORD=root - ports: - - "12000:8000" - - "12022:22" - environment: - - FLAG=GEMASTIK{local_flag} diff --git a/services/sheesh/requirements.txt b/services/sheesh/requirements.txt deleted file mode 100644 index c21b6ec..0000000 --- a/services/sheesh/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -pycryptodome \ No newline at end of file diff --git a/services/sheesh/run.sh b/services/sheesh/run.sh deleted file mode 100644 index 6ae49cb..0000000 --- a/services/sheesh/run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -exec socat tcp-l:8000,reuseaddr,fork exec:"python3 ./chall.py" diff --git a/services/sheesh/start.sh b/services/sheesh/start.sh deleted file mode 100644 index 74ea114..0000000 --- a/services/sheesh/start.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -set -e - -ssh-keygen -A - -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 From ec3bc02ddd4da25b9d48fee6ea493610a593f79b Mon Sep 17 00:00:00 2001 From: itoid Date: Sat, 11 Oct 2025 22:46:04 +0700 Subject: [PATCH 3/7] Add files via upload --- services/sheesh/Dockerfile | 32 +++++++++ services/sheesh/chall.py | 101 +++++++++++++++++++++++++++++ services/sheesh/dist/chall.py | 101 +++++++++++++++++++++++++++++ services/sheesh/docker-compose.yml | 16 +++++ services/sheesh/requirements.txt | 1 + services/sheesh/run.sh | 3 + services/sheesh/start.sh | 24 +++++++ 7 files changed, 278 insertions(+) create mode 100644 services/sheesh/Dockerfile create mode 100644 services/sheesh/chall.py create mode 100644 services/sheesh/dist/chall.py create mode 100644 services/sheesh/docker-compose.yml create mode 100644 services/sheesh/requirements.txt create mode 100644 services/sheesh/run.sh create mode 100644 services/sheesh/start.sh diff --git a/services/sheesh/Dockerfile b/services/sheesh/Dockerfile new file mode 100644 index 0000000..073dd6a --- /dev/null +++ b/services/sheesh/Dockerfile @@ -0,0 +1,32 @@ +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"] diff --git a/services/sheesh/chall.py b/services/sheesh/chall.py new file mode 100644 index 0000000..cdaf6a2 --- /dev/null +++ b/services/sheesh/chall.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 + +import os +import binascii +import hashlib +from Crypto.Cipher import AES +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_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) +K2 = hash(seed2) + +with open("/flag.txt","rb") as f: + FLAG = f.read() + +def read(prompt: str): + s = input(prompt).strip() + try: + return binascii.unhexlify(s) + except Exception: + print("hmm") + return None + +def enc_cfb(pt: bytes) -> bytes: + iv = os.urandom(16) + aes = AES.new(key, AES.MODE_CFB, iv=iv, segment_size=128) + pt2 = pt + FLAG[:len(FLAG)//2] + ct = aes.encrypt(pt2) + return iv + ct + +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 menu(): + print(""" +1. encrypt +2. profit +3. get third +4. exit + """) + +third = 0 +while True: + menu() + op = input("> ").strip() + + if op == "1": + data = read("pt: ") + if data is None: + print() + continue + out = enc_cfb(data) + print("ct: ", out.hex()) + print() + + elif op == "2": + 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 op == "3": + if third: + print("sheesh") + continue + block = read("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=0) + print("iv1: ", iv1.hex()) + print("iv2: ", iv2.hex()) + print("ct: ", ct.hex()) + third = 1 + print() + + elif op == "4": + break + else: + print("mabokkkk?") diff --git a/services/sheesh/dist/chall.py b/services/sheesh/dist/chall.py new file mode 100644 index 0000000..cdaf6a2 --- /dev/null +++ b/services/sheesh/dist/chall.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 + +import os +import binascii +import hashlib +from Crypto.Cipher import AES +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_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) +K2 = hash(seed2) + +with open("/flag.txt","rb") as f: + FLAG = f.read() + +def read(prompt: str): + s = input(prompt).strip() + try: + return binascii.unhexlify(s) + except Exception: + print("hmm") + return None + +def enc_cfb(pt: bytes) -> bytes: + iv = os.urandom(16) + aes = AES.new(key, AES.MODE_CFB, iv=iv, segment_size=128) + pt2 = pt + FLAG[:len(FLAG)//2] + ct = aes.encrypt(pt2) + return iv + ct + +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 menu(): + print(""" +1. encrypt +2. profit +3. get third +4. exit + """) + +third = 0 +while True: + menu() + op = input("> ").strip() + + if op == "1": + data = read("pt: ") + if data is None: + print() + continue + out = enc_cfb(data) + print("ct: ", out.hex()) + print() + + elif op == "2": + 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 op == "3": + if third: + print("sheesh") + continue + block = read("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=0) + print("iv1: ", iv1.hex()) + print("iv2: ", iv2.hex()) + print("ct: ", ct.hex()) + third = 1 + print() + + elif op == "4": + break + else: + print("mabokkkk?") diff --git a/services/sheesh/docker-compose.yml b/services/sheesh/docker-compose.yml new file mode 100644 index 0000000..e1eb8ca --- /dev/null +++ b/services/sheesh/docker-compose.yml @@ -0,0 +1,16 @@ +version: "3.8" + +services: + sheesh: + container_name: sheesh_container + hostname: sheesh + restart: always + build: + context: . + args: + - PASSWORD=root + ports: + - "12000:8000" + - "12022:22" + environment: + - FLAG=GEMASTIK{local_flag} diff --git a/services/sheesh/requirements.txt b/services/sheesh/requirements.txt new file mode 100644 index 0000000..c21b6ec --- /dev/null +++ b/services/sheesh/requirements.txt @@ -0,0 +1 @@ +pycryptodome \ No newline at end of file diff --git a/services/sheesh/run.sh b/services/sheesh/run.sh new file mode 100644 index 0000000..6ae49cb --- /dev/null +++ b/services/sheesh/run.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +exec socat tcp-l:8000,reuseaddr,fork exec:"python3 ./chall.py" diff --git a/services/sheesh/start.sh b/services/sheesh/start.sh new file mode 100644 index 0000000..74ea114 --- /dev/null +++ b/services/sheesh/start.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -e + +ssh-keygen -A + +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 From 84f2e7d8d0eb23215cb38a75c13ddb67355074d8 Mon Sep 17 00:00:00 2001 From: itoid Date: Mon, 13 Oct 2025 22:34:04 +0700 Subject: [PATCH 4/7] Delete services/sheesh directory --- services/sheesh/Dockerfile | 32 --------- services/sheesh/chall.py | 101 ----------------------------- services/sheesh/dist/chall.py | 101 ----------------------------- services/sheesh/docker-compose.yml | 16 ----- services/sheesh/requirements.txt | 1 - services/sheesh/run.sh | 3 - services/sheesh/start.sh | 24 ------- 7 files changed, 278 deletions(-) delete mode 100644 services/sheesh/Dockerfile delete mode 100644 services/sheesh/chall.py delete mode 100644 services/sheesh/dist/chall.py delete mode 100644 services/sheesh/docker-compose.yml delete mode 100644 services/sheesh/requirements.txt delete mode 100644 services/sheesh/run.sh delete mode 100644 services/sheesh/start.sh diff --git a/services/sheesh/Dockerfile b/services/sheesh/Dockerfile deleted file mode 100644 index 073dd6a..0000000 --- a/services/sheesh/Dockerfile +++ /dev/null @@ -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"] diff --git a/services/sheesh/chall.py b/services/sheesh/chall.py deleted file mode 100644 index cdaf6a2..0000000 --- a/services/sheesh/chall.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python3 - -import os -import binascii -import hashlib -from Crypto.Cipher import AES -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_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) -K2 = hash(seed2) - -with open("/flag.txt","rb") as f: - FLAG = f.read() - -def read(prompt: str): - s = input(prompt).strip() - try: - return binascii.unhexlify(s) - except Exception: - print("hmm") - return None - -def enc_cfb(pt: bytes) -> bytes: - iv = os.urandom(16) - aes = AES.new(key, AES.MODE_CFB, iv=iv, segment_size=128) - pt2 = pt + FLAG[:len(FLAG)//2] - ct = aes.encrypt(pt2) - return iv + ct - -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 menu(): - print(""" -1. encrypt -2. profit -3. get third -4. exit - """) - -third = 0 -while True: - menu() - op = input("> ").strip() - - if op == "1": - data = read("pt: ") - if data is None: - print() - continue - out = enc_cfb(data) - print("ct: ", out.hex()) - print() - - elif op == "2": - 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 op == "3": - if third: - print("sheesh") - continue - block = read("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=0) - print("iv1: ", iv1.hex()) - print("iv2: ", iv2.hex()) - print("ct: ", ct.hex()) - third = 1 - print() - - elif op == "4": - break - else: - print("mabokkkk?") diff --git a/services/sheesh/dist/chall.py b/services/sheesh/dist/chall.py deleted file mode 100644 index cdaf6a2..0000000 --- a/services/sheesh/dist/chall.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python3 - -import os -import binascii -import hashlib -from Crypto.Cipher import AES -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_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) -K2 = hash(seed2) - -with open("/flag.txt","rb") as f: - FLAG = f.read() - -def read(prompt: str): - s = input(prompt).strip() - try: - return binascii.unhexlify(s) - except Exception: - print("hmm") - return None - -def enc_cfb(pt: bytes) -> bytes: - iv = os.urandom(16) - aes = AES.new(key, AES.MODE_CFB, iv=iv, segment_size=128) - pt2 = pt + FLAG[:len(FLAG)//2] - ct = aes.encrypt(pt2) - return iv + ct - -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 menu(): - print(""" -1. encrypt -2. profit -3. get third -4. exit - """) - -third = 0 -while True: - menu() - op = input("> ").strip() - - if op == "1": - data = read("pt: ") - if data is None: - print() - continue - out = enc_cfb(data) - print("ct: ", out.hex()) - print() - - elif op == "2": - 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 op == "3": - if third: - print("sheesh") - continue - block = read("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=0) - print("iv1: ", iv1.hex()) - print("iv2: ", iv2.hex()) - print("ct: ", ct.hex()) - third = 1 - print() - - elif op == "4": - break - else: - print("mabokkkk?") diff --git a/services/sheesh/docker-compose.yml b/services/sheesh/docker-compose.yml deleted file mode 100644 index e1eb8ca..0000000 --- a/services/sheesh/docker-compose.yml +++ /dev/null @@ -1,16 +0,0 @@ -version: "3.8" - -services: - sheesh: - container_name: sheesh_container - hostname: sheesh - restart: always - build: - context: . - args: - - PASSWORD=root - ports: - - "12000:8000" - - "12022:22" - environment: - - FLAG=GEMASTIK{local_flag} diff --git a/services/sheesh/requirements.txt b/services/sheesh/requirements.txt deleted file mode 100644 index c21b6ec..0000000 --- a/services/sheesh/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -pycryptodome \ No newline at end of file diff --git a/services/sheesh/run.sh b/services/sheesh/run.sh deleted file mode 100644 index 6ae49cb..0000000 --- a/services/sheesh/run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -exec socat tcp-l:8000,reuseaddr,fork exec:"python3 ./chall.py" diff --git a/services/sheesh/start.sh b/services/sheesh/start.sh deleted file mode 100644 index 74ea114..0000000 --- a/services/sheesh/start.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -set -e - -ssh-keygen -A - -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 From 343278c71aafc201a60e3d391a14d2f3230aa286 Mon Sep 17 00:00:00 2001 From: itoid Date: Mon, 13 Oct 2025 22:36:03 +0700 Subject: [PATCH 5/7] Add files via upload --- services/sheesh/Dockerfile | 32 ++++++++ services/sheesh/chall.py | 116 +++++++++++++++++++++++++++++ services/sheesh/dist/chall.py | 116 +++++++++++++++++++++++++++++ services/sheesh/docker-compose.yml | 16 ++++ services/sheesh/requirements.txt | 1 + services/sheesh/run.sh | 3 + services/sheesh/start.sh | 24 ++++++ 7 files changed, 308 insertions(+) create mode 100644 services/sheesh/Dockerfile create mode 100644 services/sheesh/chall.py create mode 100644 services/sheesh/dist/chall.py create mode 100644 services/sheesh/docker-compose.yml create mode 100644 services/sheesh/requirements.txt create mode 100644 services/sheesh/run.sh create mode 100644 services/sheesh/start.sh diff --git a/services/sheesh/Dockerfile b/services/sheesh/Dockerfile new file mode 100644 index 0000000..073dd6a --- /dev/null +++ b/services/sheesh/Dockerfile @@ -0,0 +1,32 @@ +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"] diff --git a/services/sheesh/chall.py b/services/sheesh/chall.py new file mode 100644 index 0000000..a3eca5f --- /dev/null +++ b/services/sheesh/chall.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +import os +import binascii +import hashlib +import threading +import time +import sys +from Crypto.Cipher import AES +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() + +def read_hex(prompt: str): + s = input(prompt).strip() + try: + return binascii.unhexlify(s) + except Exception: + print("hmm") + return None + +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 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 menu(): + print(""" +1. encrypt +2. profit +3. get third +4. exit + """) + +third = 0 +iv11 = None +iv22 = None + +def alarm(): + time.sleep(180) + print("zzz") + sys.exit(0) + +threading.Thread(target=alarm, daemon=True).start() + +while True: + menu() + op = input("> ").strip() + + if op == "1": + data = read_hex("pt: ") + if data is None: + print() + continue + out = enc_cfb(data) + print("ct: ", out.hex()) + print() + + 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 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() + + elif op == "4": + break + else: + print("mabokkkk?") diff --git a/services/sheesh/dist/chall.py b/services/sheesh/dist/chall.py new file mode 100644 index 0000000..a3eca5f --- /dev/null +++ b/services/sheesh/dist/chall.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +import os +import binascii +import hashlib +import threading +import time +import sys +from Crypto.Cipher import AES +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() + +def read_hex(prompt: str): + s = input(prompt).strip() + try: + return binascii.unhexlify(s) + except Exception: + print("hmm") + return None + +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 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 menu(): + print(""" +1. encrypt +2. profit +3. get third +4. exit + """) + +third = 0 +iv11 = None +iv22 = None + +def alarm(): + time.sleep(180) + print("zzz") + sys.exit(0) + +threading.Thread(target=alarm, daemon=True).start() + +while True: + menu() + op = input("> ").strip() + + if op == "1": + data = read_hex("pt: ") + if data is None: + print() + continue + out = enc_cfb(data) + print("ct: ", out.hex()) + print() + + 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 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() + + elif op == "4": + break + else: + print("mabokkkk?") diff --git a/services/sheesh/docker-compose.yml b/services/sheesh/docker-compose.yml new file mode 100644 index 0000000..e1eb8ca --- /dev/null +++ b/services/sheesh/docker-compose.yml @@ -0,0 +1,16 @@ +version: "3.8" + +services: + sheesh: + container_name: sheesh_container + hostname: sheesh + restart: always + build: + context: . + args: + - PASSWORD=root + ports: + - "12000:8000" + - "12022:22" + environment: + - FLAG=GEMASTIK{local_flag} diff --git a/services/sheesh/requirements.txt b/services/sheesh/requirements.txt new file mode 100644 index 0000000..c21b6ec --- /dev/null +++ b/services/sheesh/requirements.txt @@ -0,0 +1 @@ +pycryptodome \ No newline at end of file diff --git a/services/sheesh/run.sh b/services/sheesh/run.sh new file mode 100644 index 0000000..6ae49cb --- /dev/null +++ b/services/sheesh/run.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +exec socat tcp-l:8000,reuseaddr,fork exec:"python3 ./chall.py" diff --git a/services/sheesh/start.sh b/services/sheesh/start.sh new file mode 100644 index 0000000..74ea114 --- /dev/null +++ b/services/sheesh/start.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -e + +ssh-keygen -A + +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 From a76de1408655ad1224e053a529d764a6b45c98c8 Mon Sep 17 00:00:00 2001 From: itoid Date: Mon, 13 Oct 2025 23:32:09 +0700 Subject: [PATCH 6/7] Create sheesh.txt --- receiver/flags/sheesh.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 receiver/flags/sheesh.txt diff --git a/receiver/flags/sheesh.txt b/receiver/flags/sheesh.txt new file mode 100644 index 0000000..3fe32e3 --- /dev/null +++ b/receiver/flags/sheesh.txt @@ -0,0 +1 @@ +GEMASTIK{PLACEHOLDER} From edab268592244231fc35a3fad62ab545a33683a3 Mon Sep 17 00:00:00 2001 From: itoid Date: Mon, 13 Oct 2025 23:38:37 +0700 Subject: [PATCH 7/7] Add files via upload --- receiver/challenges/test_sheesh_standalone.py | 191 ++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 receiver/challenges/test_sheesh_standalone.py diff --git a/receiver/challenges/test_sheesh_standalone.py b/receiver/challenges/test_sheesh_standalone.py new file mode 100644 index 0000000..3512f6d --- /dev/null +++ b/receiver/challenges/test_sheesh_standalone.py @@ -0,0 +1,191 @@ +from .Challenge import Challenge + +import subprocess +import time +import re +import os + +class Sheesh(Challenge): + flag_location = 'flags/sheesh.txt' + history_location = 'history/sheesh.txt' + + _CONTAINER = "sheesh_container" + _SERVICE_CMD = ["docker", "exec", "-i", _CONTAINER, "python3", "/usr/local/bin/chall.py"] + _HEX_RE = re.compile(r'^[0-9a-fA-F]+$') + + def _read_container_flag(self) -> str: + out = subprocess.run(["docker", "exec", self._CONTAINER, "cat", "/flag.txt"], + capture_output=True, text=True) + if out.returncode != 0 or not out.stdout.strip(): + raise FileNotFoundError("Flag not found in container (/flag.txt)") + return out.stdout.strip() + + def _spawn(self): + return subprocess.Popen( + self._SERVICE_CMD, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + bufsize=0, + ) + + def _read_until(self, proc, token, timeout=5.0, max_bytes=1_000_000): + start = time.time() + buf = [] + r = proc.stdout.read + while True: + if time.time() - start > timeout: + tail = ''.join(buf)[-500:] + raise TimeoutError(f"Timeout waiting for '{token}'. Got so far:\n{tail}") + ch = r(1) + if ch == "" and proc.poll() is not None: + raise RuntimeError(f"Process ended while waiting for '{token}'. Output:\n{''.join(buf)}") + buf.append(ch) + if len(buf) > max_bytes: + raise RuntimeError("Exceeded max read size") + if token in "".join(buf): + return "".join(buf) + + def _send_line(self, proc, s: str): + proc.stdin.write(s + "\n") + proc.stdin.flush() + + def _expect_hex_field(self, text: str, label: str) -> str: + m = re.search(rf"{re.escape(label)}\s*:\s*([0-9a-fA-F]+)", text) + assert m, f"Missing '{label}' in output. Tail:\n{text[-400:]}" + hx = m.group(1) + assert self._HEX_RE.match(hx), f"{label} is not hex" + return hx + + def distribute(self, flag): + try: + os.makedirs(os.path.dirname(self.flag_location), exist_ok=True) + with open(self.flag_location, 'w') as f: + f.write(flag) + + os.makedirs(os.path.dirname(self.history_location), exist_ok=True) + with open(self.history_location, 'a') as f: + f.write(flag + '\n') + + self.logger.info(f'Flag {flag} written to {self.flag_location}') + return True + except Exception as e: + self.logger.error(f'Could not write flag to {self.flag_location}: {e}') + return False + + def check(self): + try: + with open(self.flag_location, 'r') as f: + host_flag = f.read().strip() + container_flag = self._read_container_flag() + assert host_flag == container_flag, 'Flag mismatch between host and container' + self.logger.info('[ok] flag parity (sheesh)') + + proc = self._spawn() + + def menu(): + self._read_until(proc, "> ", timeout=5.0) + + menu() + + self._send_line(proc, "1") + self._read_until(proc, "pt: ", timeout=3.0) + pt_hex = "414243444546" # "ABCDEF" + self._send_line(proc, pt_hex) + out = self._read_until(proc, "\n\n", timeout=3.0) + ct_hex = self._expect_hex_field(out, "ct") + ct = bytes.fromhex(ct_hex) + assert len(ct) == 16 + len(bytes.fromhex(pt_hex)), "CFB ct length mismatch (IV+PT)" + iv_a = ct[:16] + self.logger.info("[ok] encrypt(1) basic") + + menu() + self._send_line(proc, "1") + self._read_until(proc, "pt: ", timeout=3.0) + pt_hex2 = "00" * 8 + self._send_line(proc, pt_hex2) + out2 = self._read_until(proc, "\n\n", timeout=3.0) + ct2_hex = self._expect_hex_field(out2, "ct") + ct2 = bytes.fromhex(ct2_hex) + assert len(ct2) == 16 + len(bytes.fromhex(pt_hex2)), "Second CFB ct length mismatch" + iv_b = ct2[:16] + assert iv_a != iv_b, "CFB IV appears reused" + self.logger.info("[ok] encrypt(1) IV rotates") + + menu() + self._send_line(proc, "3") + self._read_until(proc, "pt: ", timeout=3.0) + self._send_line(proc, "00" * 15) + out3a = self._read_until(proc, "\n", timeout=3.0) + assert "hmmm" in out3a.lower(), "Option 3 must reject non-16-byte input (15B)" + + menu() + self._send_line(proc, "3") + self._read_until(proc, "pt: ", timeout=3.0) + self._send_line(proc, "00" * 17) + out3b = self._read_until(proc, "\n", timeout=3.0) + assert "hmmm" in out3b.lower(), "Option 3 must reject non-16-byte input (17B)" + + menu() + self._send_line(proc, "3") + self._read_until(proc, "pt: ", timeout=3.0) + self._send_line(proc, "11" * 16) + out3 = self._read_until(proc, "\n\n", timeout=3.0) + ct3_hex = self._expect_hex_field(out3, "ct") + ct3 = bytes.fromhex(ct3_hex) + assert len(ct3) in (16, 32), f"Unexpected CT length for option 3: {len(ct3)} (expected 16 or 32)" + if len(ct3) == 16: + self.logger.info("[ok] get third(3): vuln flavor (16-byte CT)") + else: + self.logger.info("[ok] get third(3): patched flavor (32-byte CT)") + + menu() + self._send_line(proc, "3") + out4 = self._read_until(proc, "\n", timeout=3.0) + assert "sheesh" in out4.lower(), "Second call to option 3 should be rejected with 'sheesh'" + self.logger.info("[ok] get third(3) lockout") + + menu() + self._send_line(proc, "2") + out5 = self._read_until(proc, "\n\n", timeout=3.0) + iv1_hex = self._expect_hex_field(out5, "iv1") + iv2_hex = self._expect_hex_field(out5, "iv2") + ct5_hex = self._expect_hex_field(out5, "ct") + assert len(bytes.fromhex(iv1_hex)) == 16, "iv1 length invalid" + assert len(bytes.fromhex(iv2_hex)) == 16, "iv2 length invalid" + assert len(bytes.fromhex(ct5_hex)) >= 16 and len(bytes.fromhex(ct5_hex)) % 16 == 0, "CBC ct invalid length" + self.logger.info("[ok] profit(2) first call") + + menu() + self._send_line(proc, "2") + out6 = self._read_until(proc, "\n\n", timeout=3.0) + iv1_hex_2 = self._expect_hex_field(out6, "iv1") + iv2_hex_2 = self._expect_hex_field(out6, "iv2") + assert iv1_hex_2 != iv1_hex or iv2_hex_2 != iv2_hex, "IVs did not change between consecutive '2' calls" + self.logger.info("[ok] profit(2) fresh IVs") + + menu() + self._send_line(proc, "4") + try: + proc.wait(timeout=2.0) + except subprocess.TimeoutExpired: + proc.kill() + raise AssertionError("Program did not exit after option 4") + self.logger.info("[ok] service exit on 4") + + proc_alarm = self._spawn() + self._read_until(proc_alarm, "zzz", timeout=190.0) # 180s + slack + try: + proc_alarm.wait(timeout=5.0) + except subprocess.TimeoutExpired: + proc_alarm.kill() + raise AssertionError("Alarm fired but process did not exit") + self.logger.info("[ok] alarm fired ('zzz') and process self-terminated") + + self.logger.info('Check passed for sheesh') + return True + + except Exception as e: + self.logger.error(f'Could not check sheesh: {e}') + return False