정보보안 공부/운영체제, 시스템

[시스템 보안] 세그멘테이션 폴트를 gdb 디버깅을 통해 확인하기

pxatd 2022. 6. 26. 18:08
728x90

*2022-1 시스템보안 과제 백업입니다. 

 

1. 문제

아래 소스 코드를 컴파일하여, 버퍼 오버플로우 취약점으로 인해 Segmentation fault (세그멘테이션 폴트) 오류가 발생하게 하는 최소 길이의 입력 값을 찾고, 이유를 설명하라. 이 과정에서 gdb 디버거를 활용하여 버퍼 오버플로우가 발생하는 시점 직전에 breakpoint (중단점)를 설정하고, 버퍼 오버플로우가 일어난 직후의 스택을 gdb를 통해 각각 확인하여 비교하라 (스크린샷 첨부 필수). 비교 과정을 통해, 세그멘테이션 폴트가 해당 입력에서 왜 발생하게 되었는지를 설명하라.

 

<소스코드 overflow.c>

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

참고로, 위 프로그램은 gets() 함수를 활용하여 키보드 입력을 받아 지역 변수 buf에 입력된 내용을 string 형태로 저장한 뒤 출력하는 코드이며, 이 코드에서 argc, argv는 활용되지 않는다.

이 때, 컴파일은 다음의 옵션을 주어서 빌드한 뒤 분석하도록 한다.

user@ubuntu:~$ gcc -m32 -g -o overflow overflow.c -fno-stack-protector -fno-builtin 
-mpreferred-stack-boundary=2 -fno-pie -fno-asynchronous-unwind-tables

 

 

2. 문제 답 서술

Segmentation fault (세그멘테이션 폴트) 오류가 발생하게 하는 최소 길이의 입력 값은 AAAAAAAAAAAAAAAA(영문 16개)이다. 이 코드에서 버퍼는 12바이트인데 12 바이트가 넘는 긴 값을 인자로 전달하면 버퍼 오버플로우 오류가 발생하여 다른 메모리를 침범하게 된다.

 

그러나 13개가 아닌 16개인 이유는 주어진 코드에 정상 값(예: AAAA) 을 입력한 뒤 return 값 epb를 확인해보면 0xf7de4ee5 가 출력되는데, 그 주소값을 변형시키는 입력값이 A값 16개와 Null 값까지 포함하여 총 17바이트가 되었을 때이다.

 

따라서 A의 최소 개수는 16개일 때 세그멘테이션 폴트가 발생한다.

gdb 디버거를 활용하여 버퍼 오버플로우가 발생하는 시점 직전을 살펴보기 위해 b 5 명령어를 사용하여 브레이크 포인트를 걸어준 뒤 주소값을 확인하였다.

 

이 때, 값이 입력되기 전이므로 스택의 esp에는 쓰레기 값(무작위 값)이 입력된 것을 확인할 수 있다.

하지만 A를 16개 입력한 후 다시 x/16xw $esp 명령어를 통해 스택의 esp값을 확인한 결과 return 주소값으로 출력되어야 하는 0xf7de4ee5이 4ee5에서 4e00으로(00은 null char) overwrite된 것을 볼 수 있다. n(next) 명령어를 통해 코드를 끝까지 실행하면 기존에 갖고있던 주소값이 아니므로 Cannot find bounds of current function라는 오류와 함께 세그멘테이션 오류를 출력하며 프로그램이 종료된다.

728x90