Iriton's log

Stack BOF - RET Overwrite 본문

Security Lab

Stack BOF - RET Overwrite

Iriton 2023. 12. 4. 16:54

스택 오버플로우를 이용한 리턴 주소 변조(또는 덮어쓰기) 실습을 진행하려고 한다.

 

* 해당 실습은 window, Immunity Debugger, Python, CodeBlocks를 이용하였다.

 

취약한 타겟 코드

해당 코드에서 Integer Overflow 취약점을 찾을 수 있다.

 

len

len은 문자열 길이를 저장하는 변수이다.

char 타입으로, 7 bit(1 bit는 부호)만큼 사용한다. 따라서 최대 값은 128이다. (2의 7제곱수)

128이 넘으면 음수로 인식을 하기 때문에 조건문 else가 아닌 if문이 수행된다.

 

스택 구조 파악 및 시나리오

주요 스택 구조는 위와 같다.

정상적인 작동에서는 buffer 범위 내에서만 값이 저장되어야 하는데,

비정상적인 작동 즉, Overflow를 이용하면 buffer 범위를 넘어서 SFP(Stack Frame Pointer 스택 베이스 값), RET(RetrunAddress) 범위까지 침범하여 값이 덮어씌워지기 때문에 비정상 실행이 된다.

 

이를 이용하면 원래 RET 주소가 저장되어 있는 메모리에 임의의 값을 삽입할 수 있다.

그러려면 buffer의 크기를 알아야 한다.

buffer의 크기 이상(Buffer 크기 + SFP 크기)의 Dummy Data(불필요한 값)을 넣어서 오버플로우를 유도하고 RET 주소에 넣을 주소 값을 삽입하면 공격자가 원하는 주소로 이동할 수 있다.

 

시나리오는 아래와 같다.

1. buffer 시작 주소 파악

2. Dummy Data 크기 구하기

3. 쉘코드 제작

4. 쉘코드가 포함된 Dummy Data 생성하는 파이썬 코드 제작

5. 디버깅

 

1. buffer 시작 주소 파악

먼저 아까 CodeBlocks로 만들어진 exe 파일을 Immunity Debugger로 열고,

미리 생성한 test.txt 파일을 인자 값으로 넣어 준다. 나는 해당 파일에 '1'이라는 문자열 하나만 넣어뒀다.

>>> Debug - Arguments 에서 test.txt 입력, 이때 텍스트 파일은 exe 파일과 같은 경로에 있어야 한다.

 

main 함수를 찾기 위해서 msvcrt._cexit호출 명령어를 찾았다.

해당 함수는 프로그램이 종료될 때 자동으로 호출되는 함수로, 프로그램 종료 시 필요한 정리 작업을 수행한다.

그래서 이 함수 직전에 호출된 함수가 main 함수일 확률이 가장 높다.

 

BP를 걸어놓고 F7키로 해당 함수에 들어가 보자.

fopen, fget, printf 등 코드에서 쓰이는 함수들이 있는 것을 보아  main 함수가 맞다.

중요한 것은 memcpy이다. 이 함수를 통해 buffer가 저장되기 시작하는 메모리 주소를 알 수 있기 때문이다.

memcpy에 BP를 걸어두거나 F8로 한 줄씩 실행하여 흐름을 살펴 보자.

 

memcpy가 실행되니까 스택 창(오른쪽 아래 창)을 보니 0022FDAC 주소에 1 값이 저장된 걸 볼 수 있다.

buffer의 시작 주소는 0022FDAC 란 걸 알 수 있다.

 

2.  Dummy Data 크기 구하기

Dummy Data 크기를 구하려면 SFP 직전 주소를 알아야 한다.

그래야 Buffer 시작부터 SFP 직전까지 불필요한 값으로 덮어씌울 수 있기 때문이다.

SFP를 가리키고 있는 EBP 값을 이용하면 된다.

 

레지스터 창(오른쪽 윗 창)을 확인해 보니 EBP 값은 0022FEE8이다.

 

둘의 차를 구하면 316이 나온다.

316만큼의 Dummy Data가 필요하냐? 그건 아니다.

RET 주소까지 변조하기 위해서는 SFP 값까지 덮어씌워야 하기 때문이다.

즉, SFP 값의 크기인 4 byte까지 더해서 320만큼의 Dummy Data가 필요하다.

 

3. 쉘코드 제작(실패)

쉘코드는 직접 작성이 가능하고, VS를 활용하여 몇 단계에 걸쳐 만들 수 있긴 하지만

칼리 리눅스의 Metasploit의 msfvenom 도구를 활용하면 쉽게 생성할 수 있다.

 

kali linux 가상머신을 키고, 별도의 설치 없이 msfvenom 명령어를 이용할 수 있다.

msfvenom -p windows/messagebox title="Iriton's Attack" text=using IntegerOverflow -f c

-p: 페이로드 사용

-f: 출력 형식

 

즉, 윈도우 메세지 박스 띄우는 명령을 c 형식으로 출력한다.

title과 text로 내용을 입력할 수 있다.

-f python으로 파이썬 형식으로 출력할 수도 있다.(c로 출력하는 게 더 깔끔해서 c 형식을 사용했다.)

 

실패 분석

실패라고 적어둔 이유는 해당 쉘 코드로 파이썬 코드를 제작하고 메모장을 만들면,

메모장 contents가 한줄이 아닌 줄바꿈이 되어서 출력이 된다.

아마 쉘 코드 제작 과정에서 줄바꾸는 기계어가 작성되어 있어서 그런 거 같은데 이 때문에 프로그램 실행 시, 전체 더미 데이터가 읽히지 않아서 오버플로우가 발생하지 않고 결국 메세지 박스를 띄우지 않게 된다.

이를 해결하기 위해서는 개행 문자 \n와 널바이트 \0을 읽을 수 있는 알고리즘을 짜든지, 자체적으로 제거한 후 쉘 코드를 출력할 수 있는지 알아 봐야 한다.

 

일단 Visual Studio를 이용해서 직접 쉘 코드를 추출해내거나 구글링을 통해 원하는 쉘 코드를 긁어다 써야 한다.

나는 아래 쉘 코드를 이용했다.

"\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42"
"\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03"
"\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b"
"\x34\xaf\x01\xc6\x45\x81\x3e\x46\x61\x74\x61\x75\xf2\x81\x7e"
"\x08\x45\x78\x69\x74\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c"
"\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x68\x69\x21"
"\x21\x01\x68\x6e\x6d\x69\x6e\x68\x20\x68\x79\x75\x89\xe1\xfe"
"\x49\x0b\x31\xc0\x51\x50\xff\xd7"

4. 쉘코드가 포함된 Dummy Data 생성하는 파이썬 코드 제작

쉘코드는 변수에 저장해 두고

오버 플로우를 위해 채울 더미 데이터는 A로 대체할 건데, 총 320 바이트 더미 데이터가 필요하다.

따라서 쉘 코드 길이를 제외한 나머지 크기만큼 A를 채운다.

마지막으로 리턴 주소에 넣을 값인 0x0022FDAC를 리틀엔디안 방식으로 형식화한다.

여기서 0022FDAC는 버퍼의 첫 주소이자, 쉘 코드의 시작 주소이다.

즉, 리턴 주소를 0022FDAC로 덮어씌웠으니 쉘 코드가 저장된 버퍼 시작 주소로 이동하게 되며

그로 인해 쉘 코드가 실행되는 원리이다.

 

5. 디버깅

memcpy를 호출하면 메모리에 인자 값으로 넣어 준 이름의 메모안에 저장된 값(메모의 contents)이 복사된다.

 

리턴 직전까지 가주면 22FEEC로 이동하는데, 여기는 리턴 주소가 저장된 곳이었다.

근데 오버플로우를 통해서(스택 앞에 AAAA...가 쌓여 있는 걸 볼 수 있다.) 다른 값이 들어와 있다.

이는 리틀엔디안 방식으로 pack 했던 0022FDAC이다.

그 후로 F9를 눌러 끝까지 실행시키면 메세지 박스가 뜬다.

현재 띄운 메세지 박스에 대한 쉘 코드는 내가 제작한 게 아니지만,

VS를 이용한 쉘 코드 제작 과정을 응용하면 메세지 박스도 띄울 수 있을 것이다.

 

Visual Studio 이용하여 ShellCode 제작

계산기를 띄우는 쉘 코드 제작 과정 필요한 것 windows OS stdafx.h와 windows.h 헤더 파일 (해당 포스트 맨 아래에 첨부) stdafx.cpp 파일 (해당 포스트 맨 아래에 첨부) 디버거 Visual Studio 순서 1. C++로 calc.exe

eunginius.tistory.com

 

Comments