SH1R0_HACKER

008. Buffer Overflow in C++ (1) 본문

System/System Exploitation

008. Buffer Overflow in C++ (1)

SH1R0_HACKER 2021. 2. 9. 13:59

C++ 언어에서도 버퍼오버플로우가 발생할 수 있습니다.

 

[ String Buffer Overflow ]

 

 

위 예제는 20byte의 buf를 할당하고 std::cin 함수를 통해 문자열을 입력받습니다.

하지만 여기서도 입력한 문자열의 길이를 검사하는 부분이 없어서 20byte 이상의 문자열을 입력한다면

버퍼오버플로우가 발생할 수 있습니다.

 

위 예제에서는 string 타입으로 buf를 할당하는 모습입니다.

std::string는 입력받는 길이에 따라 메모리를 자동으로 할당하기 때문에 버퍼오버플로우가 발생하지 않습니다.


[ Container Overflow ]

C++에서는 데이터 관리를 편하게 하기 위해 벡터, 큐와 같은 여러 종류의 컨테이너들을 지원합니다.

 

main 함수를 살펴보면 다음과 같습니다.

 

std::vector<int> v;

13행에서 비어있는 vector v를 생성합니다.

vector 컨테이너는 자동으로 메모리가 할당되는 배열이라고 생각하면 됩니다.

 

v.resize(size);

15행에서 백터의 크기를 사용자가 입력한 size로 변경합니다.

 

v.assign(size, 0x41414141);

16행에서는 0x41414141로 초기화된 size개의 원소를 할당합니다.


다음은 f 함수입니다.

vector v를 src 매개변수로 받습니다.

 

std::vector<int> dest(5)

7행에서 기본값(0)으로 초기화 된 5개의 원소를 가지는 vector dest를 생성합니다.

 

std::copy(src.begin(), src.end(), dest.begin());

8행에서는 copy함수를 이용하여

src.begin() 부터 src.end() 전 까지의 모든 원소들을 dest.begin() 부터 시작하는 곳에 복사합니다.


src가 dest(5) 보다 크다면 오버플로우가 발생하기 때문에 7행을

std::vector<int> dest(src);

로 바꾸어주면 오버플로우 취약점을 막을 수 있습니다.


위 예제는 int형 vector v를 선언한 후 std::fill_n 함수를 통해

v.begin() 부터 10개의 배열을 0x42로 초기화 하는 코드입니다.

 

하지만 위 코드에서는 백터의 크기를 따로 지정해주지 않았기 때문에 7행의 코드가 실행되는 순간

버퍼오버플로우가 발생합니다.

 

이러한 취약점을 막기 위해서는 아래와 같이 벡터를 선언할 때 크기를 지정해 주면 됩니다.

 


C++에서 반복자(iterator)는 컨테이너에 저장된 원소를 순회하고 접근할 수 있도록 합니다.

반복자를 사용할 때 크기 계산을 정확하게 하지 않는다면 오버플로우가 발생할 수 있습니다.

 

위 코드는 int형 vector c를 20번 순회합니다.

그러나 f 함수의 매개변수로 전달된 c의 크기가 20을 넘지 않는다면 e의 위치는 c의 바깥을 가리키게 되어

Out-of-Bound Access가 발생합니다.

 

실제로 컴파일을 시도하면 아래와 같은 오류가 발생합니다.

 

 

이 취약점은 for문의 반복 횟수를 벡터의 크기로 지정해주면 됩니다.

 


아래의 예제는 long long형인 idx 변수를 insert_table 함수의 매개변수 pos로 넘겨주고

pos 값이 table.size() 보다 크거나 같다면 overflow! 문구를 출력하고 종료하고,

pos값이 table.size() 보다 작다면 table[pos]에 value를 대입하는 코드입니다.

 

long long 자료형의 범위는 아래와 같습니다.

-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807

 

따라서 idx 값으로 음수를 넘겨준다면 if문을 항상 만족하지 않으므로

std::vector 객체의 범위를 벗어난 쓰기가 발생합니다.

 

따라서 배열의 인덱스로 사용되는 정수형 변수는 unsigned 자료형으로 선언해 사용해야 합니다.

 

'System > System Exploitation' 카테고리의 다른 글

009. Buffer Overflow in C++ (3)  (0) 2021.02.13
009. Buffer Overflow in C++ (2)  (0) 2021.02.09
007. Integer issues  (0) 2021.02.07
006. 초기화되지 않은 메모리  (0) 2021.02.07
005. Double Free & Use After Free  (0) 2021.02.07