Stack Overflow

HackTricks 지원하기

스택 오버플로우란 무엇인가

스택 오버플로우는 프로그램이 할당된 것보다 더 많은 데이터를 스택에 쓸 때 발생하는 취약점입니다. 이 초과 데이터는 인접한 메모리 공간을 덮어쓰게 되어 유효한 데이터의 손상, 제어 흐름의 중단, 그리고 잠재적으로 악성 코드의 실행을 초래할 수 있습니다. 이 문제는 종종 입력에 대한 경계 검사를 수행하지 않는 안전하지 않은 함수의 사용으로 인해 발생합니다.

이 덮어쓰기의 주요 문제는 **저장된 명령 포인터 (EIP/RIP)**와 **저장된 기본 포인터 (EBP/RBP)**가 이전 함수로 돌아가기 위해 스택에 저장된다는 것입니다. 따라서 공격자는 이를 덮어쓰고 프로그램의 실행 흐름을 제어할 수 있습니다.

취약점은 일반적으로 함수가 스택에 할당된 양보다 더 많은 바이트를 복사할 때 발생하여 스택의 다른 부분을 덮어쓸 수 있게 됩니다.

이러한 취약점이 있는 일반적인 함수는: strcpy, strcat, sprintf, gets... 또한 fgets, **read & memcpy**와 같이 길이 인수를 사용하는 함수는 지정된 길이가 할당된 것보다 클 경우 취약하게 사용될 수 있습니다.

예를 들어, 다음 함수들이 취약할 수 있습니다:

void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}

스택 오버플로우 오프셋 찾기

스택 오버플로우를 찾는 가장 일반적인 방법은 매우 큰 입력의 As를 주는 것입니다 (예: python3 -c 'print("A"*1000)') 그리고 **주소 0x41414141에 접근하려고 시도했다는 것을 나타내는 Segmentation Fault**를 기대하는 것입니다.

게다가, 스택 오버플로우 취약점이 발견되면 리턴 주소를 덮어쓸 수 있는 오프셋을 찾아야 합니다. 이를 위해 일반적으로 De Bruijn 시퀀스가 사용됩니다. 주어진 크기 _k_의 알파벳과 길이 _n_의 부분 시퀀스에 대해, 모든 가능한 길이 _n_의 부분 시퀀스가 정확히 한 번 연속된 부분 시퀀스로 나타나는 순환 시퀀스입니다.

이렇게 하면 EIP를 제어하는 데 필요한 오프셋을 수동으로 파악할 필요 없이, 이러한 시퀀스 중 하나를 패딩으로 사용하고 덮어쓴 바이트의 오프셋을 찾을 수 있습니다.

이를 위해 pwntools를 사용할 수 있습니다:

from pwn import *

# Generate a De Bruijn sequence of length 1000 with an alphabet size of 256 (byte values)
pattern = cyclic(1000)

# This is an example value that you'd have found in the EIP/IP register upon crash
eip_value = p32(0x6161616c)
offset = cyclic_find(eip_value)  # Finds the offset of the sequence in the De Bruijn pattern
print(f"The offset is: {offset}")

또는 GEF:

#Patterns
pattern create 200 #Generate length 200 pattern
pattern search "avaaawaa" #Search for the offset of that substring
pattern search $rsp #Search the offset given the content of $rsp

스택 오버플로우 악용하기

오버플로우가 발생하는 동안(오버플로우 크기가 충분히 큰 경우) 스택 내의 지역 변수 값을 덮어쓸 수 있습니다. **EBP/RBP와 EIP/RIP(또는 그 이상)**에 도달할 때까지 가능합니다. 이러한 유형의 취약점을 악용하는 가장 일반적인 방법은 반환 주소를 수정하는 것입니다. 이렇게 하면 함수가 끝날 때 제어 흐름이 사용자가 지정한 위치로 리디렉션됩니다.

그러나 다른 시나리오에서는 스택 내의 일부 변수 값을 덮어쓰는 것만으로도 악용이 충분할 수 있습니다(예: 쉬운 CTF 챌린지에서).

Ret2win

이러한 유형의 CTF 챌린지에서는 결코 호출되지 않는 함수바이너리 내에 존재하며, 이를 호출해야 승리할 수 있습니다. 이러한 챌린지에서는 반환 주소를 덮어쓸 오프셋을 찾고 호출할 함수의 주소를 찾기만 하면 됩니다(보통 ASLR이 비활성화되어 있음) 그래서 취약한 함수가 반환될 때 숨겨진 함수가 호출됩니다:

Ret2win

스택 셸코드

이 시나리오에서 공격자는 스택에 셸코드를 배치하고 제어된 EIP/RIP를 악용하여 셸코드로 점프하고 임의의 코드를 실행할 수 있습니다:

Stack Shellcode

ROP 및 Ret2... 기술

이 기술은 이전 기술의 주요 보호 장치를 우회하기 위한 기본 프레임워크입니다: 실행 불가능한 스택(NX). 그리고 이는 기존의 바이너리 명령어를 악용하여 임의의 명령을 실행하는 여러 다른 기술(ret2lib, ret2syscall...)을 수행할 수 있게 해줍니다:

ROP - Return Oriented Programing

힙 오버플로우

오버플로우는 항상 스택에서 발생하는 것은 아니며, 예를 들어 에서도 발생할 수 있습니다:

Heap Overflow

보호 유형

취약점 악용을 방지하기 위한 여러 가지 보호 장치가 있습니다. 자세한 내용은 다음을 확인하세요:

Common Binary Exploitation Protections & Bypasses
HackTricks 지원하기

Last updated