strncpy 함수
Buffer Over Flow(이하 BOF)를 막기위해서 쓰는 함수 中 strncpy 라는 함수가 있다. 하지만 strncpy 함수에서도 취약한 부분이 발생할 수 있다는것을 BOF 원정대 (golem -> darkknight) 문제를 풀면서 공부할 수 있었다.
= strncpy 함수에 대한 설명 =
#include <string.h> // C++ 에서는 <cstring>
char * strncpy ( char * destination, const char * source, size_t num );
- 간략한 설명 -
문자열에서 일부 문자들 만을 복사한다.
source 에서 destination 으로 source 의 처음 num 개의 문자들 만을 복사(NULL 도 포함해서) 한다. num 보다 source 의 문자 수가 더 적다면은 모자란 부분은 0 으로 생각되어서 destination 에 복사가 된다. 다시 말해 source 가 "abc" 인다, num 이 5 라면 destination 에는 "abc\0\0" 가 들어가게 된다.
strncpy 함수는 복사시 destination 끝에 반드시 NULL 문자를 붙이는 것이 아니므로 사용에 주의를 해야 한다.
- 인자 -
destination : destination 배열을 가리키는 포인터로 문자열이 복사될 곳이다.
source : 복사 될 C 문자열이다.
num : source 에서 복사 할 문자의 개수 이다.
- 리턴값 -
destination 을 리턴한다.
[출처] : http://itguru.tistory.com/80
이제 strncpy 함수에 대한 설명은 알았는데 어떻게 취약한 부분이 발생할 수 있는지에 대해서 알아보자. 간단한 예를 Wiki 검색 결과 내에서 찾을 수 있었다.
아래의 C 소스 코드는 일반적인 프로그래밍 실수를 보여준다. 일단 컴파일 되면, 너무 긴 커맨드라인 인자 문자열을 가지고 실행하면 프로그램은 버퍼 오버플로우 오류를 발생할 것이다. 왜냐하면 이 인자의 길이를 체크하지 않고 버퍼를 채우는 데 사용하기 때문이다. [2]
/* overflow.c - 버퍼 오버플로우를 설명한다 */ #include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { char buffer[10]; if (argc < 2) { fprintf(stderr, "사용법: %s 문자열\n", argv[0]); return 1; } strcpy(buffer, argv[1]); return 0; }
9개 이하의 문자 스트링은 버퍼 오버플로우를 일으키지 않는다. 10 이상의 문자들은 오버플로우를 일으킨다. 이것은 언제나 부정확하지만 프로그램 오류나 세그먼트 폴트를 일으키지는 않는다. strncpy는 버퍼에 쓰일 문자의 개수를 제한할 수 있다.
이 프로그램은 strncpy를 이용해 아래와 같이 안전하게 다시 쓸 수 있다: [2]
/* better.c - 문제 해결 방법 하나를 설명한다 */ #include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { char buffer[10]; if (argc < 2) { fprintf(stderr, "사용법: %s 문자열\n", argv[0]); return 1; } strncpy(buffer, argv[1], sizeof(buffer)); buffer[sizeof(buffer) - 1] = '\0'; /* 문자열의 끝을 분명히 맺는다 */ return 0; }