이제 GDB 사용법 및 Pwntools 사용법을 알아보았습니다. 

그러면 이제 본격적으로 한번 포너블을 배워보도록 하겠습니다. 

 

 

Buffer Overflow? 

보통 포너블을 처음 시작할때 버퍼 오버플로우 취약점을 알아보는데요

이번에는 이 취약점을 알아보도록 합시다. 

 

C언어에서 버퍼라고 하면 지정된 크기의 메모리 공간을 의미합니다 

오버플로우는 그 의미 그대로 원래의 버퍼사이즈보다 더 큰 데이터 값을 저장해서

버퍼 즉 메모리 공간이 넘쳐서 다른 메모리 공간을 침범해버리는 취약점 입니다. 

 

일반적으로 발생하는 위치에 따라서 부르는 명칭이 조금 다릅니다.

여기서 알아볼것은 스책 오버플로우 입니다.  (당연히 스택에서 발생하는 취약점이겠죠??)

지역변수가 할당되는 스택 메모리에서 오버플로우가 발생하는 경우 입니다.

 

예제코드를 한번 보겠습니다. 

 

#include<stdio.h>

int main(void)
{
	
    char buf[16];
    gets(buf);
    
    printf("%s",buf);
    return 0;
}

 

자 여기서 buf라는 배열에 16이라는 버퍼 사이즈를 지정해주었습니다. 

그럼 gets함수를 통해서 입력을 받아오게 되는데

 

gets 함수는 사용자가 개행을 입력하기 전까지 입력했던 모든 내용을 저장하게 됩니다. 

그말은 16보다 사이즈가 크더라도 개행문자가 오지않으면 전부 저장한다는 이야기가 됩니다.

 

버퍼사이즈는 16이지만 이보다 큰 데이터의 크기를 입력해버리면

오버플로우가 발생 할 것입니다.

 

보통 길이 제한이 없는 API 함수들을 사용하거나 버퍼의 크기보다 입력받는 데이터의 크기가 

클 경우 발생하게 됩니다.

 

 

여기서 보면 Stack smashing detected 라는 문구가 나오게 됩니다.

스택영역에서 오버플로우가 일어났음을 의미합니다.  

생각했던대로 16보다 큰 사이즈를 입력하니까 오버플로우가 일어났습니다. 

gets 함수에서 버퍼의 크기를 검증하지 않았기 때문입니다.

 

이번엔 좀더 어려운 예제코드를 보도록 합시다.

 

// stack-2.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int check_auth(char *password) 
{
    int auth = 0;
    char temp[16];
    
    strncpy(temp, password, strlen(password));
    
    if(!strcmp(temp, "SECRET_PASSWORD"))
        auth = 1;
    
    return auth;
}

int main(int argc, char *argv[]) 
{
    if (argc != 2) 
    {
        printf("Usage: ./stack-1 ADMIN_PASSWORD\n");
        exit(-1);
    }
    
    if (check_auth(argv[1]))
        printf("Hello Admin!\n");
    else
        printf("Access Denied!\n");
}

 

main 함수에서 argv[1]을 함수의 인자로 전달하고 나서 return을 받아오는데

그 결과가 1이면 Hello Admin을 출력하고 0이면 Access Denied를 받아옵니다.

 

check_auth 함수를 보면 일단 auth를 0으로 초기화 합니다.

그리고나서 temp라는 배열에 16이라는 버퍼를 할당해주고 있습니다.

strcmp로 temp의 값을 password로 복사를 한다음, password의 길이를 측정합니다.

그리고 temp와 SECRET_PASSWORD와 일치하면 1을 리턴합니다. 

 

자 그럼 여기서 핵심부분은 check_auth함수라고 할 수 있습니다. 

 

strncpy(temp, password, strlen(password));

 

이 부분을 보면 temp가 복사를 할때 정해진 크기 16버퍼 만큼 복사하는것이 아닌 

인자로 전달된 password의 문자열 만큼 복사합니다. 

따라서 이것은 16보다 큰 문자열을 인자로 보내준다면 오버플로우가 날 것 입니다.

 

그리고 해당 코드를 보면 아래와 같은 코드가 있습니다.

 

if (check_auth(argv[1]))
        printf("Hello Admin!\n");

 

temp 버퍼 뒤에 auth 값이 있기 때문에 해당 값을 인위적으로 다른 값으로 바꾼다면

항상 이 코드의 값은 참이 될 것 입니다.(0이 아니기 때문에)

 

 

정상적으로 오버플로우가 발생합니다. 

이렇게 크기 검증을 하지 않은경우 오버플로우가 발생합니다. 

 

이런 경우가 1가지 있고,

다른 한가지는 해당 버퍼의 사이즈보다 큰 데이터를 입력했을때 입니다.

 

이번에는 길이나 크기를 검증하지 않은 함수로 인해서 발생하는 오버플로우를 알아보았습니다.

해당 주소를 참고 하였습니다.

 

https://dreamhack.io/lecture/curriculums/2

 

System Exploitation Fundamental

리눅스 시스템 해킹

dreamhack.io

 

'Theory > Pwnable' 카테고리의 다른 글

How to Assembly code in Linux (리눅스에서 어셈블리 사용)  (0) 2023.11.06
찬희의 포너블 기초 Stack Overflow 2  (0) 2021.09.29
Shellcode list  (0) 2021.09.26
Pwn tools 소개 2  (0) 2021.09.22
Pwntools 소개 1  (0) 2021.09.14

+ Recent posts