혜랑's STORY

Memory Corruption - C (1) : Out-of-boundary 본문

무지성 공부방/Dreamhack SystemHacking

Memory Corruption - C (1) : Out-of-boundary

hyerang0125 2021. 1. 19. 14:47
본 포스팅은 DreamHack 사이트의 Memory Corruption - C(1) 강의 내용을 요약한 것이다. 강의의 주소는 다음과 같다.
 

해커들의 놀이터, Dreamhack

해킹과 보안에 대한 공부를 하고 싶은 학생, 안전한 코드를 작성하고 싶은 개발자, 보안 지식과 실력을 업그레이드 시키고 싶은 보안 전문가까지 함께 공부하고 연습하며 지식을 나누고 실력 향

dreamhack.io

# Out Of Boundary

OOB(Out Of Boundary)는 버퍼의 길이 범위를 벗어나는 인덱스에 접근할 때 발생하는 취약점이다.

-> 예제(oob-1.c)

// oob-1.c
#include <stdio.h>
int main(void) {
    int win;
    int idx;
    int buf[10];
    
    printf("Which index? ");
    scanf("%d", &idx);
    printf("Value: ");
    scanf("%d", &buf[idx]);
    printf("idx: %d, value: %d\n", idx, buf[idx]);
    if(win == 31337){
        printf("Theori{-----------redacted---------}");
    }
}

위 코드는 int형 배열 buf를 선언하고 idx 값을 입력받는다. 그 다음 buf[idx]에 정수를 입력받고 idx와 buf[idx] 값을 출력한다. 

여기서 주의할 점은 buf의 길이는 10이므로 buf의 인덱스로 사용될 수 있는 올바를 값은 0 이상 10 미만의 정수라는 사실이다. 그러나 코드에서는 line 10에서 받은 idx 값을 인덱스로 사용할 때 해당 값이 올바른 범위에 속해있는지 검사하지 않는다. 즉, 올바르지 않은 값을 사용한다면 buf의 영역 밖에 있는 값에 접근할 수 있다.

-> 실습

드림핵에 있는 모듈을 사용해 실습을 진행해 보았다. idx와 buf[idx]에 적당한 값을 줘서 win 변수를 31337로 만들면 성공이다.

드림핵 모듈로 OOB 실습을 진행한 결과(1)

-> 예제(oob-2.c)

// oob-2.c
#include <stdio.h>
int main(void) {
    int idx;
    int buf[10];
    int win;
    
    printf("Which index? ");
    scanf("%d", &idx);
    
    idx = idx % 10;
    printf("Value: ");
    scanf("%d", &buf[idx]);
    printf("idx: %d, value: %d\n", idx, buf[idx]);
    if(win == 31337){
        printf("Theori{-----------redacted---------}");
    }
}

이번 코드는 oob-1.c와는 달리 line 12에 idx = idx % 10이라는 코드가 추가되어있다. 이 코드로 OOB 취약점을 막을 수 있을까?

OOB의 발생 여부를 판단할 때는 버퍼의 인덱스로 사용할 수 있는 올바른 값의 번위와 버퍼의 인덱스가 될 수 있는 모든 값의 범위를 비교하면 된다. 인덱스가 될 수있는 값의 범위가 사용할 수 있는 올바른 값의 범위의 부분집합이라면 안전하다고 할 수 있다.

buf의 인덱스로 쓸 수 있는 값의 범위는 -9 ~ 9이므로 나머지가 음수가 되게 한다면 OOB를 발생시킬 수 있다.

-> 실습

드림핵 모듈로 OOB 실습을 진행한 결과(2)

-> 예제(oob-3.c)

//oob-3.c
#include <stdio.h>
int main(void) {
    int idx;
    int buf[10];
    int dummy[7];
    int win;
    printf("Which index? ");
    scanf("%d", &idx);
    
    if(idx < 0)
        idx = -idx;
    idx = idx % 10; // No more OOB!@!#!
    printf("Value: ");
    scanf("%d", &buf[idx]);
    printf("idx: %d, value: %d\n", idx, buf[idx]);
    if(win == 31337){
        printf("Theori{-----------redacted---------}");
    }
}

oob-2.c와 다르게 idx가 음수일 경우 이를 양수로 바꿔주는 코드가 추가되었다. line 14에 들어가게 되는 idx 값은 양수가 되고 , 10으로 나머지 연산을 했을 떄 값의 범위는 0부터 9가 되기 때문에 아무 문제가 없어 보인다.

그러나 C언어의 정수 표현을 생각해보면, int형으로 표현 가능한 정수의 범위는 -pow(2, 31) ~ pow(2, 31) -1이다. 즉, idx에 -pow(2,31) 값을 넣어주면 line 14의 연산을 한 뒤에도 -pow(2,31)로 저장되게 된다. 그렇다면 idx = idx%10을 할 때 idx에 음수가 저장되고 이는 buf 배열의 올바른 인덱스 범위를 벗어나기 때문에 OOB가 발생한다.

->실습

드림핵 모듈로 OOB 실습을 진행한 결과(3)