인프라

[보안] 버퍼 오버플로우 취약점 분석과 GDB를 활용한 디버깅 실습

HHRR 2024. 10. 16. 13:53
시스템 보안 수업 중 진행한 과제입니다.
실습

 

 overflow.c 코드를 컴파일하고, 버퍼 오버플로우가 발생하여 Segmentation Fault(세그멘테이션 폴트) 오류가 발생하는 최소 입력 길이를 찾고, 이를 GDB 디버거로 분석한다. 이 과정에서 버퍼 오버플로우 발생 전후의 스택 상태를 비교하여 비정상적인 실행 흐름의 원인을 파악해보자.

 overflow.c
#include <stdio.h>
 
int main(int argc, char *argv[]) {
    char buf[16];
    gets(buf);
    printf(“%s\n”, buf);
}

 

 

분석 과정

 

초기 세팅

1.     overflow.c 소스코드를 생성하고 문제에서 주어진 명령어로 컴파일을 해주기.

2.     Gdb를 실행하여 프로그램을 로드하고, list main으로 소스코드의 라인을 확인하기.

1) 19개 입력했을 경우

  1. Breakpoint 설정
    • 버퍼 오버플로우가 발생하는 시점 직전은 gets() 함수가 위치한 다음 라인 번호인 6으로 breakpoint를 지정한다.
  2. 프로그램 실행
    • run으로 프로그램을 실행하고, 19개의 A를 입력한다.
    • breakpoint에서 중단이 되면, info registers 명령어로 현재 레지스터의 상태를 확인.
      • 입력 길이 19 (`AAAAAAAAAAAAAAAAAAA`)일 때, ebp `0xffffd1f8`로 설정되고, esp `0xffffd1e8`로 설정됨.
    • 다음 x/16xw $esp 명령어로 스택 상태를 확인한다.
      • buf 16바이트의 크기를 가지므로, buf[16], buf[17], buf[18]이 덮어써 버퍼 오버플로우가 발생합니다. 이 때 ebp의 값은 여전히 `0xffffd1f8`로 저장된다.
      • 이 경우, 덮어쓰는 데이터가 리턴 주소와 저장된 ebp 값에 도달하지 않으므로 Segmentation Fault가 발생하지 않는다. 또한 리턴 주소 (스택 프레임 상의 저장된 ebp 위에 위치한 값) `0xf7de5ed5`로 정상적인 주소임을 알 수 있다.
    • continue를 했을 때 문제 없이 종료되는 것으로 보아 버퍼 오버플로우는 발생했지만, 덮어쓰는 데이터가 리턴 주소와 저장된 ebp 값에 도달하지 않으므로 Segmentation Fault가 발생하지 않았음을 알 수 있다.

2) 20개 입력했을 경우

  1. breakpoint 설정
    • 라인 번호인 6으로 breakpoint를 지정해준다.
  2. 프로그램 실행
    • run으로 프로그램을 실행하고, 20개의 A를 입력한다.
    • breakpoint에서 중단이 되면, info registers 명령어로 현재 레지스터의 상태를 확인한다
      • 입력 길이 20 (`AAAAAAAAAAAAAAAAAAAA`)일 때, ebp `0xffffd1f8`로 설정되고, esp `0xffffd1e8`로 설정된다.
    • 다음 x/16xw $esp 명령어로 스택 상태를 확인한다.
      • buf[16], buf[17], buf[18], buf[19]이 덮어쓴다.
      • 이 경우 ebp가 덮어쓰여져 `0x41414141`가 된다. (ASCII 'AAAA').
      • 리턴 주소는 정상적인 주소 `0xf7de5ed5`가 아닌 `0x41414141`와 관련된 잘못된 주소를 참조하게 된다.
    • 따라서 ebp가 덮어쓰여지고, continue를 했을 때 함수가 잘못된 주소인 `0x41414141` 로 리턴하려 하면서 Segmentation Fault가 발생한다.

 

결론

 

gets함수가 버퍼 크기를 초과하는 입력을 받았을 때 스택 메모리를 덮어씌우게 된다. printf함수 호출 직전에 break point를 설정하여 버퍼 오버플로우를 확인할 수 있다!!!!  스택 메모리에 리턴 주소가 덮어씌워질 경우 Segmentation Fault가 발생한다.

 

위와 같이19바이트의 입력의 경우, 버퍼 크기인 16바이트를 초과하여 버퍼 오버플로우는 발생하지만, ebp와 리턴 주소가 덮어쓰여지지 않아 Segmentation Fault가 발생하지 않는다는 것을 볼 수 있다.

 

따라서 최소 20바이트의 입력이 버퍼 오버플로우를 일으켜 비정상적인 실행 흐름을 유발하게 된다는걸 알 수 있었다.