#dokydoky

Stack Buffer OverFlow 본문

System Hacking

Stack Buffer OverFlow

dokydoky 2011. 8. 24. 22:57

ms visual studio 6.0에서 간단한 bof 코드를 컴파일해보고 분석해보자.


#include <stdio.h>
h4ck(void){
int i, *p;
p=&i;
p+=2;
*p+=13;
}

main(void){
h4ck();
printf("H4cking\n");
printf("Cr4cking\n");
}


우선 알아야 할 것이.

1. 메모리구조는 Text, Data, Heap, Stack 영역으로 나뉜다.

2. Stack영역은 다른영역과는 달리 높은주소->낮은주소로 변수가 쌓인다.(변수 내부에서는 낮은주소->높은주소)

3. 함수를 호출하면 우선 스택에 ret(retrun 주소), SFP(Stack Frame Pointer), 매개변수, 지역변수 순서대로 쌓인다.

   이 때, Stack BOF는 ret주소를 의도적으로 변경하기 위해 자료를 넘치게 하거나 포인터를 이용해 변화시키는 방법이다.

자세하게 스택버퍼오버플로우를 설명해준 사이트 참고
http://geundi.tistory.com/118
펼치기


실제 코드를 분석해 보면

vc6.0 으로 디버깅 한 어셈블리 코드다
1:    #include <stdio.h>
2:
3:    h4ck(void){
00401020 55                   push        ebp
00401021 8B EC                mov         ebp,esp
00401023 83 EC 48             sub         esp,48h
00401026 53                   push        ebx
00401027 56                   push        esi
00401028 57                   push        edi
00401029 8D 7D B8             lea         edi,[ebp-48h]
0040102C B9 12 00 00 00       mov         ecx,12h
00401031 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401036 F3 AB                rep stos    dword ptr [edi]
4:    int i, *p;
5:    p=&i;
00401038 8D 45 FC             lea         eax,[ebp-4]
0040103B 89 45 F8             mov         dword ptr [ebp-8],eax
6:    p+=2;
0040103E 8B 4D F8             mov         ecx,dword ptr [ebp-8]
00401041 83 C1 08             add         ecx,8
00401044 89 4D F8             mov         dword ptr [ebp-8],ecx
7:    *p+=13;
00401047 8B 55 F8             mov         edx,dword ptr [ebp-8]
0040104A 8B 02                mov         eax,dword ptr [edx]
0040104C 83 C0 0D             add         eax,0Dh
0040104F 8B 4D F8             mov         ecx,dword ptr [ebp-8]
00401052 89 01                mov         dword ptr [ecx],eax
8:    }
00401054 5F                   pop         edi
00401055 5E                   pop         esi
00401056 5B                   pop         ebx
00401057 8B E5                mov         esp,ebp
00401059 5D                   pop         ebp
0040105A C3                   ret
--- No source file  -------------------------------------------------------------------------------------------------
0040105B CC                   int         3
0040105C CC                   int         3
0040105D CC                   int         3
0040105E CC                   int         3
0040105F CC                   int         3
00401060 CC                   int         3
00401061 CC                   int         3
00401062 CC                   int         3
00401063 CC                   int         3
00401064 CC                   int         3
00401065 CC                   int         3
00401066 CC                   int         3
00401067 CC                   int         3
00401068 CC                   int         3
00401069 CC                   int         3
0040106A CC                   int         3
0040106B CC                   int         3
0040106C CC                   int         3
0040106D CC                   int         3
0040106E CC                   int         3
0040106F CC                   int         3
--- c:\documents and settings\owner\my documents\vc6.0\qw\ee.c  -----------------------------------------------------
9:
10:   main(void){
00401070 55                   push        ebp
00401071 8B EC                mov         ebp,esp
00401073 83 EC 40             sub         esp,40h
00401076 53                   push        ebx
00401077 56                   push        esi
00401078 57                   push        edi
00401079 8D 7D C0             lea         edi,[ebp-40h]
0040107C B9 10 00 00 00       mov         ecx,10h
00401081 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401086 F3 AB                rep stos    dword ptr [edi]
11:   h4ck();
00401088 E8 78 FF FF FF       call        @ILT+0(_h4ck) (00401005)
12:   printf("H4cking\n");
0040108D 68 28 00 42 00       push        offset string "H4cking\n" (00420028)
00401092 E8 39 00 00 00       call        printf (004010d0)
00401097 83 C4 04             add         esp,4
13:   printf("Cr4cking\n");
0040109A 68 1C 00 42 00       push        offset string "Cr4cking\n" (0042001c)
0040109F E8 2C 00 00 00       call        printf (004010d0)
004010A4 83 C4 04             add         esp,4
14:   }
004010A7 5F                   pop         edi
004010A8 5E                   pop         esi
004010A9 5B                   pop         ebx
004010AA 83 C4 40             add         esp,40h
004010AD 3B EC                cmp         ebp,esp
004010AF E8 9C 00 00 00       call        __chkesp (00401150)
004010B4 8B E5                mov         esp,ebp
004010B6 5D                   pop         ebp
004010B7 C3                   ret


중요한 부분은 h4ck()! 이 부분이다.

3:    h4ck(void){
00401020 55                   push        ebp
00401021 8B EC                mov         ebp,esp
00401023 83 EC 48             sub         esp,48h
00401026 53                   push        ebx
00401027 56                   push        esi
00401028 57                   push        edi
00401029 8D 7D B8             lea         edi,[ebp-48h]
0040102C B9 12 00 00 00       mov         ecx,12h
00401031 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401036 F3 AB                rep stos    dword ptr [edi]
4:    int i, *p;
5:    p=&i;
00401038 8D 45 FC             lea         eax,[ebp-4]
0040103B 89 45 F8             mov         dword ptr [ebp-8],eax
6:    p+=2;
0040103E 8B 4D F8             mov         ecx,dword ptr [ebp-8]
00401041 83 C1 08             add         ecx,8
00401044 89 4D F8             mov         dword ptr [ebp-8],ecx
7:    *p+=13;
00401047 8B 55 F8             mov         edx,dword ptr [ebp-8]
0040104A 8B 02                mov         eax,dword ptr [edx]
0040104C 83 C0 0D             add         eax,0Dh
0040104F 8B 4D F8             mov         ecx,dword ptr [ebp-8]
00401052 89 01                mov         dword ptr [ecx],eax
8:    }




스택의 구조를 보면

|            |
|  int *p  | <- esp
|  int  a   |
|   SFP   |  <- ebp
|    ret    |
+--------+

포인터 p는 i의 주소를 가리키고 +2를 했다. 따라서 8바이트가 증가하고, int와 SFP모두 각각 4바이트이므로

p는 ret을 가리키게 된다. 따라서 *p+=13은 ret을 13증가시키는 의미가 되고, 결국

ret값이 0040108D에서 0040109A으로 바뀌게 된다. 그러므로 첫번째 printf 함수는 출력이 되지 않는 것이다.



참고로 Stack Buffer Overflow는 위와 같이 ret값을 변조하는 방법과, SFP값을 변화시켜 적용하는 방법이 있다.

전 함수의 ebp를 저장하는 SFP를 변화시켜 공격하는 방법이다. 이에 대해 "naska21 in WiseGuys" 분이 쓴 글이 있다. 감사!

글 주소 : http://research.hackerschool.org/Datas/Research_Lecture/sfp.txt
펼치기


이밖에도
http://dakuo.egloos.com/v/1111692
http://blog.daum.net/sysnet924/156
글 참조하자. 좋은 글들이 많이 있다.!!
http://wiki.kldp.org/wiki.php/BufferOverFlow


Comments