공부해요/리버싱_핵심원리

10장. 함수 호출 규약

yenas0 2024. 9. 22. 19:04
반응형
함수 호출 규약 (Calling Convention)

함수 호출 규약은 함수를 호출할 때 파라미터를 어떻게 전달하고 스택을 어떻게 관리하는지에 대한 규칙임. 이 규칙은 주로 함수 파라미터가 스택을 통해 전달될 때 적용되며, PE(Portable Executable) 헤더에 스택 크기가 명시되어 있음.

스택 관리 개요

  • 파라미터 전달: 함수 호출 시 파라미터는 스택에 역순으로 전달됨. 스택 크기는 프로세스 실행 시 결정됨.
  • 함수 종료 후 스택 상태: 함수가 실행을 마친 후에도 스택에 입력된 파라미터는 그대로 둠. 불필요한 CPU 자원을 사용하지 않기 위해 값을 지우지 않고, 어차피 다음 호출에서 덮어씌워질 것임.
  • ESP 복원: 함수 실행 완료 시 **ESP(스택 포인터)**는 함수 호출 전 상태로 복원되어야 함. 그렇지 않으면 참조 가능한 스택 크기가 줄어들 수 있음. ESP가 스택 끝을 가리키면 더 이상 스택을 사용할 수 없기 때문에 이를 관리하는 것이 중요함.

주요 함수 호출 규약

  • cdecl
  • stdcall
  • fastcall

cdecl

  • 주로 C언어에서 사용되는 호출 규약임.
  • **Caller(함수를 호출한 쪽)**가 스택을 정리함.
#include "stdio.h"

int add(int a, int b)
{
	return (a + b);
}
int main(int argc, char* argv[])
{
	return add(1, 2);
}

cdecl 예제 코드

 

cdecl에서는 add() 함수의 파라미터 1, 2를 역순으로 스택에 입력하고, ADD ESP, 8 명령어를 사용해 스택을 정리함. 즉, Caller인 main() 함수가 직접 스택을 정리하는 방식임.

장점:

  • 가변 길이의 파라미터 전달 가능함 (예: printf 함수).

 

 

 

stdcall

  • Win32 API에서 주로 사용됨.
  • **Callee(호출된 함수)**가 스택을 정리하는 방식임.
  • __stdcall 키워드를 사용해 컴파일할 수 있음.
#include "stdio.h"

int _stdcall add(int a, int b)
{
	return (a + b);
}
int main(int argc, char* argv[])
{
	return add(1, 2);
}

stdcall 예제코드

 

 

stdcall에서는 스택 정리를 add() 함수 내부에서 처리함. RETN 8 명령을 통해 ESP를 8바이트 증가시키며 스택을 정리함. 이로 인해 Caller가 스택을 정리할 필요가 없어짐.

장점:

  • 스택 정리 코드를 호출할 때마다 작성할 필요가 없어 코드 크기가 줄어듦.

 

 

fastcall

  • fastcallstdcall과 유사하지만, 파라미터 일부를 스택이 아닌 **레지스터(ECX, EDX)**로 전달함.
  • 이를 통해 함수 호출 속도가 더 빨라짐, 왜냐하면 레지스터 접근이 스택 접근보다 빠르기 때문임.

장점:

  • 빠른 함수 호출 가능함.

단점:

  • ECX, EDX 레지스터를 관리하기 위한 추가적인 오버헤드가 발생할 수 있음.
  • 함수가 복잡할 경우, 레지스터를 다른 용도로 사용해야 할 때 파라미터 값을 저장하는 추가적인 처리 과정이 필요할 수 있음.
반응형

'공부해요 > 리버싱_핵심원리' 카테고리의 다른 글

13. PE File Format  (1) 2024.10.02
11장. Lena's Reversing for Newbies  (0) 2024.09.24
9장. Process Explorer - 최고의 작업 관리자  (0) 2024.09.22
8장. abex' crackme #2  (0) 2024.09.18
7장. 스택 프레임  (1) 2024.09.18