일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- hackctf
- CSS
- The Loard of BOF
- C언어
- 생활코딩
- 드림핵
- c++
- SWEA
- hackerrank
- Javascript
- lob
- Python
- 파이썬
- BOJ
- 웹페이지 만들기
- c
- 백준
- 풀이
- XSS Game
- siss
- Sookmyung Information Security Study
- BOJ Python
- 자료구조 복습
- HTML
- 머신러닝
- WarGame
- 기계학습
- PHP 웹페이지 만들기
- 숙명여자대학교 정보보안동아리
- 숙명여자대학교 정보보안 동아리
- Today
- Total
혜랑's STORY
Memory Corruption - C (1) : 버퍼 오버플로우 본문
본 포스팅은 DreamHack 사이트의 Memory Corruption - C(1) 강의 내용을 요약한 것이다. 강의의 주소는 다음과 같다.
버퍼 오버플로우란?
* 버퍼(buffer) : 지정된 크기의 메모리 공간
즉, 버퍼 오버플로우(buffer overflow) 취약점은 버퍼가 허용할 수 있는 양의 데이터보다 더 많은 값이 저장되어 버퍼가 넘치는 취약점이다. 일반적으로 버퍼 오버플로우는 발생하는 위치에 따라 스택 버퍼 오버플로우, 힙 오버플로우로 나뉘어 진다.
# 스택 버퍼 오버플로우
-> 지역 변수가 할당되는 스택 메모리에서 오버플로우가 발생하는 경우
위의 그림과 같은 경우 복사된 메모리가 할당된 버퍼 A의 공간에 다 들어가지 못하기 때문에 이 데이터의 뒷부분은 버퍼 A를 넘어 뒤에 있는 데이터 영역 B에 쓰여지게 된다. 이때 우리는 버퍼 오버플로우가 발생하였다고 한다.
버퍼 오버플로우는 Undefined Behavior를 이끌어내고, Segmentation Fault를 발새애시킨다. 만약 공격자가 이를 악용한다면 공격 코드를 삽입한 후 함수 포인터를 공격자의 코드 주소로 덮어 코드를 실행할 수도 있다.
-> 예제(stack-1.c)
//stack-1.c
#include <stdio.h>
#include <stdlib.h>
int mamin(void){
char buf[16];
gets(buf);
printf("%s", buf);
}
위 코드는 16 바이트 버퍼(buf)를 스택에 할당한 후, gets 함수를 통해 사용자로부터 데이터르르 입력받아 그래로 출력하는 코드이다. gets 함수에는 별도의 길이 제한이 없기 때문에 16 바이트가 넘는 데이터를 입력한다면 스택에 버퍼 오버플로우가 발생하게 된다.
이처럼 버퍼 오버플로우의 취약점은 프로그래머가 버퍼의 길이에 대한 가정을 올바를지 않게 하여 발생한다. 보통 길이 제한이 없는 API 함수들을 사용하거나 버퍼의 크기보다 입력받는 데이터의 길이가 더 크게 될 때 자주 일어나는 실수이다.
-> 실습
드림핵에 있는 모듈을 사용해 실습을 진행해 보았다. 버퍼 오버플로우시켜 ret 영역을 0x41414141로 만들면 성공이다.
-> 예제(stack-2.c)
//stack-2.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int check_auth(char *password){
int auth = 0;
char temp[16];
strncpy(temp, password, strlen(password));
if(!strcmp(temp, "SECRET_PASSWORD"))
auth = 1;
return auth;
}
int main(int argc, char *argv[]){
if(argc != 2){
printf("Usage: ./stack-1 ADMIN_PASSWORD\n");
exit(1);
}
if(check_auth(argv[1]))
printf("Hello Admin!\n);
else
printf("Access Denied!\n);
}
위 코드의 line 10에서 strncpy 함수를 통해 temp 버퍼를 복사할 때, temp의 크기인 16 바이트가 넘는 문자열을 전달한다면 길이 제한 없이 문자열이 복사되어 스택 버퍼 오버플로우가 발생하게 된다.
temp 버퍼 뒤에 auth 값이 존재하므로, 오버플로우가 발생해 공격자의 데이터가 auth 값을 바꾼다면 auth가 0이 아닌 다른 값이 될 수 있는데 이 경우 실제 인증 여부와는 상관없이 line 24의 if(check_auth(argv[1])) 문은 항상 참을 반환하게 된다.
-> 실습
드림핵에 있는 모듈을 사용해 실습을 진행해 보았다. 버퍼 오버플로우시켜 if(check_auth(argv[1])) 문이 참을 반환하도록 만들면 성공이다.
-> 예제(stack-3.c)
//stack-3.c
#include <stdio.h>
#include <unistd.h>
int main(void){
char win[4];
int size;
char buf[24];
scanf("%d", &size);
read(0, buf, size);;
if(!strncmp(win, "ABCD". 4)){
printf("Theori{-----------redacted---------}");
}
}
위 코드는 24 바이트 크기의 버퍼 buf를 할당하고, scanf 함수를 통해 size 변수에 값을 입력받고, size 만큼 buf에 데이터를 입력받는다.
stack-1.c에서는 길이 검증이 없는 함수를 사용해 스택 버퍼 오버플로우를 발생했고, 이번에는 고정된 크기의 버퍼보다 더 긴 데이터를 입력받아 스택 버퍼 오버플로우를 발생했다.
-> 실습
드림핵에 있는 모듈을 사용해 실습을 진행해 보았다.
-> 예제(stack-4.c)
//stack-4.c
#include <stdio.h>
int main(void){
char buf[32] = {0, };
read(0, buf, 31);
sprintf(buf, "Your Input is: %s\n", buf);
puts(buf);
}
위 코드는 32 바이트 크기 buf를 초기화한 후 데이터를 31바이트 입력받고, sprintf 함수를 통해 출력할 문자열을 저장한 뒤 출력하는 코드인다.
read 함수에서 받는 입력이 32 바이트를 넘진 않지만, sprintf 함수를 통해 버퍼에 값을 쓸 때 "Your Input is:" 문자열을 추가되어 있다는 사실을 기억해야 한다. 만약 buf에 31 바이트를 꽉 채운다면 "Your Input is:" 문자열이 앞에 붙어 총 길이가 32 바이트를 넘게 된다.
-> 실습
드림핵에 있는 모듈을 사용해 실습을 진행해 보았다.
앞서 예제를 통해 버퍼 오버플로우에 대하여 알아보았다. 버퍼 오버플로우를 방지하기 위해서는 입력받을 때 길이 제한이 없는 함수를 사용하는 것을 피애햐 한다. 그리고 입력받은 데이터가 버퍼에 저장되기까지의 흐름을 따라가 버퍼의 크기를 넘는 양을 저장할 수 있는 가능성을 검토해야 한다. 만약 길이를 명시하는 함수를 사용한다면, 명시된 길이가 버퍼의 크기를 넘을 수 있는지를 검토해야 한다.
# 힙 오버플로우
여기서는 립 오버플로우가 어떻게 발생하는지에 대해서만 간단히 알아보도록 하자.
-> 예제(heap-1.c)
// heap-1.c
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *input = malloc(40);
char *hello = malloc(40);
memset(input, 0, 40);
memset(hello, 0, 40);
strcpy(hello, "HI!");
read(0, input, 100);
printf("Input: %s\n", input);
printf("hello: %s\n", hello);
}
위 코드는 40 바이트 크기의 힙 버퍼 input과 hello를 할당한 후, hello 버퍼에는 "HI" 문자열을 복사하고 reas 함수를 통해 input에 데이터를 입력받는 코드이다. 그러나 read 함수를 통해 입력받는 길이인 100바이트가 input 버퍼의 크기인 40 바이트보다 크기 때문에 힙 오버플로우가 발생한다.
힙 오버플로우가 발생했을 떄의 힙 메모리 상태는 아래의 그림으로 간략히 나타낼 수 있다.
input 영역에서 버퍼 오버플로우가 발생해 hello의 메모리 영역까지 침범할 경우, line 16에서 hello 메모리를 출력할 떄 "HI!" 문자열이 아니라 공격자에게 오염된 데이터가 출력된다.
'무지성 공부방 > Dreamhack SystemHacking' 카테고리의 다른 글
Linux Exploitation & Mitigation Part 2 (1) (0) | 2021.02.21 |
---|---|
Linux Exploitation & Mitigation Part 1 (2) (0) | 2021.02.07 |
Linux Exploitation & Mitigation Part 1(1) (0) | 2021.01.30 |
Memory Corruption - C (1) : Off-by-one (0) | 2021.01.19 |
Memory Corruption - C (1) : Out-of-boundary (0) | 2021.01.19 |