728x90

1. Calling Convention

함수 호출 규약

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

호출자 : 프로그래밍에서 다른 함수 또는 메서드를 호출하는 주체. 쉽게 말해, 호출자는 특정 함수 또는 메서드를 실행하도록 명령한 코드 부분을 가리킴.

함수를 호출할 때는 반환된 이후를 위해 호출자의 상태 및 반환 주소를 저장해야함
또한, 호출자는 피호출자가 요구하는 인자를 전달해줘야하고, 피호출자의 실행이 종료될 때는 반환값을 전달받아야 함

함수 호출 규약의 종류

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

x86(32bit) 아키텍처 -> 레지스터 수 적음 -> 스택으로 인자 전달하는 규약 사용
x86-64 아키텍처 -> 레지스터 수 많음 -> 적은 인자는 레지스터만, 많은 인자는 스택 사용

CPU의 아키텍처가 같아도, 컴파일러가 다르면 적용하는 호출 규약이 다름
ex) C 컴파일, x86-64 아키텍처
윈도우 -> MSVC -> MS x64 호출 규약
리눅스 -> gcc -> SYSTEM V 호출 규약

SYSV

리눅스 gcc, x86-64 바이너리 컴파일 시 사용
리눅스 SYSTEM V(SYSV) Application Binary Interface(ABI) 기반, SYSV ABI는 ELF 포맷, 링킹 방법, 함수 호출 규약 등의 내용 포함

함수 호출 규약

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

cdecl

리눅스 gcc, x86 바이너리 컴파일 시 사용
스택을 통해 인자 전달, 인자 전달 위해 사용한 스택을 호출자가 정리
인자 전달시, 거꾸로 스택에 push

* push 횟수 x 4byte 만큼 esp가 증가됨

2. Stack Buffer Overflow

버퍼 오버플로우

버퍼

  • 데이터가 목적지로 이동되기 전에 보관되는 임시 저장소
  • 데이터가 안정적으로 목적지에 도달할 수 있도록 완충 작용을 함
  • 스택에 있는 지역 변수는 '스택 버퍼', 힙에 할당된 메모리 영역은 '힙 버퍼'라고 불림

오버플로우

  • 버퍼가 넘치는 것
  • int로 선언한 지역 변수는 4바이트 크기, 10개의 원소를 갖는 char배열은 10바이트 크기
  • 일반적으로 버퍼는 메모리상 연속 할당됨 -> 특정 버퍼에서 오버플로우 발생하면 뒤에 있는 버퍼들의 값이 조작될 위험이 있음

스택 버퍼 오버플로우 : 스택의 버퍼에서 발생하는 오버플로우

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

*C 언어에서 if는 0일 때 거짓, 0이 아닐 때 참으로 동작

  1. 데이터 유출
    C언어에서 정상적인 문자열은 널바이트로 종결되며, 표준 문자열 출력 함수들은 널바이트를 문자열의 끝으로 인식합니다. 만약 어떤 버퍼에 오버플로우를 발생시켜서 다른 버퍼와의 사이에 있는 널바이트를 모두 제거하면, 해당 버퍼를 출력시켜서 다른 버퍼의 데이터를 읽을 수 있습니다. 획득한 데이터는 각종 보호기법을 우회하는데 사용될 수 있으며, 해당 데이터 자체가 중요한 정보일 수도 있습니다.

  2. 실행 흐름 조작
    함수의 반환 주소를 조작하여 프로세스의 실행 흐름을 바꿀 수 있다.

+ Recent posts