본문 바로가기
CTF/Dreamhack

[Dreamhack] System Hacking STAGE 5 - Stack Buffer Overflow

by 8희 2022. 10. 30.

Calling Convention

함수 호출 규약

함수 호출 규약은 함수의 호출 및 반환에 대한 약속

- 함수를 호출할 때는 반환된 이후를 위해 호출자(Caller)의 상태(Stack frame) 및 반환 주소(Return Address)를 저장해야 한다. 또한, 호출자는 피호출자(Callee)가 요구하는 인자를 전달해줘야 하며, 피호출자의 실행이 종료될 때는 반환 값을 전달받아야 한다.

- 함수 호출 규약을 적용하는 것은 일반적으로 컴파일러의 몫으로 프로그래머가 고수준 언어로 코드를 작성하면, 컴파일러가 호출 규약에 맞게 코드를 컴파일

 

함수 호출 규약의 종류

- 컴파일러는 지원하는 호출 규약 중, CPU 아키텍처에 적합한 것을 선택

 

ex1) x86(32bit) 아키텍처

: 레지스터를 통해 피호출자의 인자를 전달하기에는 레지스터의 수가 적으므로, 스택으로 인자를 전달하는 규약을 사용

ex2) x86-64 아키텍처

:  레지스터가 많으므로 적은 수의 인자는 레지스터만 사용해서 인자를 전달하고, 인자가 너무 많을 때만 스택을 사용

 

x86

  • cdecl
  • stdcall
  • fastcall
  • thiscall

x86-64

  • System V AMD64 ABI의 Calling Convention
  • MS ABI의 Calling Convention

 

x86호출 규약: cdecl

- x86아키텍처는 레지스터의 수가 적으므로, 스택을 통해 인자를 전달한다. 또한, 인자를 전달하기 위해 사용한 스택을 호출자가 정리하는 특징이 있다. 스택을 통해 인자를 전달할 때는, 마지막 인자부터 첫 번째 인자까지 거꾸로 스택에 push한다.

 

x86-64호출 규약: SYSV

- SYSV ABI는 ELF 포맷, 링킹 방법, 함수 호출 규약 등의 내용을 담고 있다.

- SYSV에서 정의한 함수 호출 규약은 다음의 특징이 있다. 

  1. 6개의 인자를 RDI, RSI, RDX, RCX, R8, R9에 순서대로 저장하여 전달합니다. 더 많은 인자를 사용해야 할 때는 스택을 추가로 이용한다.
  2. Caller에서 인자 전달에 사용된 스택을 정리한다.
  3. 함수의 반환 값은 RAX로 전달한다.

 


Memory Corruption: Stack Buffer Overflow

버퍼

- 버퍼(Buffer)는 일상에서 ‘완충 장치'라는 뜻으로 사용되며, 컴퓨터 과학에서는 ‘데이터가 목적지로 이동되기 전에 보관되는 임시 저장소’의 의미로 쓰이인다.

- 빠른 속도로 이동하던 데이터가 안정적으로 목적지에 도달할 수 있도록 완충 작용을 하는 것이 버퍼의 역할이라고 할 수있다. 

 

버퍼 오버플로우

- 버퍼 오버플로우(Buffer Overflow)는 문자 그대로 버퍼가 넘치는 것을 의미

- 만약 10바이트 크기의 버퍼에 20바이트 크기의 데이터가 들어가려 하면 오버플로우가 발생

- 일반적으로 버퍼는 메모리상에 연속해서 할당되어 있으므로, 어떤 버퍼에서 오버플로우가 발생하면, 뒤에 있는 버퍼들의 값이 조작될 위험이 있다.

- 버퍼 오버플로우는 일반적으로 어떤 메모리 영역에서 발생해도 큰 보안 위협으로 이어진다.

 

버퍼 오버플로우에서 이어지는 보안 위협

1) 중요 데이터 변조

- 버퍼 오버플로우가 발생하는 버퍼 뒤에 중요한 데이터가 있다면, 해당 데이터가 변조됨으로써 문제가 발생할 수 있다.

- 예를 들어, 입력 데이터에서 악성 데이터를 감지하여 경고해주는 프로그램이 있을 때, 악성의 조건이 변경되면 악성 데이터에도 알람이 울리지 않을 수 있다. 또한, "https://twitter.com"와 통신하는 프로그램이 있다면 주소를 "https://example.evil"로 조작하여 악성 서버와 데이터를 주고받게 할 수도 있다.

 

2) 데이터 유출

- C언어에서 정상적인 문자열은 널바이트로 종결되며, 표준 문자열 출력 함수들은 널바이트를 문자열의 끝으로 인식한다.

- 만약 어떤 버퍼에 오버플로우를 발생시켜서 다른 버퍼와의 사이에 있는 널바이트를 모두 제거하면, 해당 버퍼를 출력시켜서 다른 버퍼의 데이터를 읽을 수 있다.

- 획득한 데이터는 각종 보호기법을 우회하는데 사용될 수 있으며, 해당 데이터 자체가 중요한 정보일 수도 있다.

 

3) 실행 흐름 조작

- 스택 버퍼 오버플로우로 함수의 반환 주소를 조작하면 프로세스의 실행 흐름을 바꿀 수 있다. 

 


실습: Return Address Overwrite

https://dreamhack.io/wargame/challenges/351/

 

Return Address Overwrite

Description Exploit Tech: Return Address Overwrite에서 실습하는 문제입니다.

dreamhack.io

 

풀이 참고: https://ksl2950.tistory.com/111

 

실습 성공