Calling Convention
Calling Convention(함수 호출 규약)이란 '함수 호출 시 인자(parameter) 전달 및 반환값을 처리하는 방식에 관한 규약'이다. Calling Convention은 다음과 같은 것들을 정의한다.
- 인수(argument)를 어떤 순서로 전달할지 - 오른쪽에서 왼쪽?
- 인수를 어디에 저장할지 - 레지스터에? 스택(stack)에?
- 함수가 반환값을 어디에 저장할지 - eax?
- stack frame을 누가 정리할지 - Caller? Callee?
- 어떤 레지스터를 보존해야 할지 - 함수 호출 전에 저장하고, 호출 후 복구해야하는 레지스터
대표적인 Calling Convention들은 다음과 같다.
Calling Convention들을 하나씩 살펴보자.
_cdecl
- 인자를 오른쪽 => 왼쪽으로 스택에 push
- caller 가 스택을 정리하기 때문에 callee(호출되는 함수)가 몇 개의 인자가 들어왔는지 몰라도 된다
- printf와 같은 가변 인자가 가능하다(인자의 개수가 바뀔 수 있음)
_cdecl의 예시를 보면, 오른쪽 -> 왼쪽 순으로 인자를 스택에 push하고, add 함수가 끝난 뒤 caller(main)이 ADD esp, 8 이라는 명령어를 통해 스택 프레임을 정리하는 것을 볼 수 있다.
** dword ptr ss:[ebp+8]은 뭘까?
dword: double word = 4byte 크기의 데이터를 다룬다
ss: stack segment(생략가능) - x86에서는 세그먼트가 기본적으로 정해져있기 때문이다
[ebp+8]: ebp를 기준으로 8byte만큼 떨어진(offset값) 메모리 주소
즉, dword ptr ss:[ebp+8] 은 ebp 기준으로 8만큼 떨어진 주소에 있는 4byte 값을 의미한다
_stdcall
- WIN32 API 및 C++ 표준 호출 규약
- callee가 RETN '인자크기' 형태로 stack frame을 정리하고 반환되기 때문에 _cdecl 보다 코드 크기가 작아진다
- callee가 미리 인자의 크기를 알아야 하기 때문에 가변 인자를 전달할 수 없다
- 인자는 오른쪽 => 왼쪽 순으로 스택에 push 된다
**RETN 정리
retn n : n byte 만큼 스택에 추가하여 정리한 후 retn
ret / retn : pop eip => jmp eip
_fastcall
- 표준화된 규약은 아니며, 컴파일러마다 다르게 처리한다
- 인자를 오른쪽 => 왼쪽 / 왼쪽 => 오른쪽 둘 다 push 가능
- 레지스터(eax/ecx/edx)를 먼저 사용하여 인자를 전달하고, 스택을 사용할 수도 있다
- 레지스터를 통해 인자를 전달하여 메모리 접근 수를 줄인다
- stack을 사용하는 경우 retn n 을 사용하여 callee가 스택 프레임을 정리한다
함수 결과값 반환 방식(x86)
함수가 호출된 후 어떤 값을 되돌려줄 때, x86에서는 주로 EAX 레지스터를 사용한다. 반환할 때, 함수 결과의 타입에 따라 반환 방식이 달라진다.
Value 타입 반환 - 정수, 실수와 같이 4byte(int) 이하의 값일 경우
- EAX 레지스터에 해당 값을 직접 넣어서 반환
- 만약 double과 같이 8byte의 경우 eax+edx 레지스터 조합을 이용하여 반환한다
Address 타입 반환 - 포인터, 배열, 구조체, 객체 등 상대적으로 큰 데이터를 반환하는 경우
- EAX에 반환할 데이터의 주소(pointer)를 담아서 반환
- 값 자체가 아닌 값을 담고 있는 메모리 주소를 전달하는 방식이다
'정보보안 > Reversing' 카테고리의 다른 글
[Reversing] Code to Execution(x86) (0) | 2025.04.07 |
---|---|
[Reversing] Memory Structure (0) | 2025.04.07 |
[Reversing] Assembly Language - Instruction Set (0) | 2025.03.31 |
[Reversing] Register (0) | 2025.03.31 |
[Reversing] 데이터 구성 단위, Endian, 보수(Complement) (0) | 2025.03.31 |