본문 바로가기

리버스 엔지니어링

함수 호출 규약

함수 호출 규약(Calling Convention)에 대해 할아보자


함수 호출 규약은 함수를 호출할 때 파라미터를 어떤식으로 전달하는가에 대한 일종의 약속이다. 함수 호출 전에 파라미터를 스택을 통해서 전달한다. 스택이란 프로세스에서 정의된 메모리 공간이며 아래방향으로 자란다. 또한 PE헤더에 그 크기가 명시되어있다. 즉 프로세스가 실행될 때 스택 메모리의 크기가 결정된다.(malloc/new 같은 동적 메모리 할당과는 다르다.)


함수가 실행이 완료도었을 때 스택에 들어있던 파라미터는 그대로 놔두는데 어처피 덮어씌워서 사용하는 것을 지우거나 하면 CPU자원을 소모하게 되기 때문이다.


함수가 실행 완료되었을 때 ESP(스택포인터)는 함수 호출 전으로 복원되어야 한다. 그래야 참조가능한 스택의 크기가 줄어들지 않는다.ESP가 만약 끝을 가리킨다면 더이상 스택을 사용할 수 없기에 함수 호출후에 스택포인터를 어떻게 관리하는지에 대한 약속이 바로 함수 호출 규약이다. 주요한 함수 호출 규약은 아래와 같다.


- cdecl

- stdcall

- fastcall




cdecl

cdecl 방식은 주로 C언어에서 사용되는 방식이며 Caller(함수를 호출할 쪽)에서 스택을 정리하는 특징을 가지고 있다. 자신이 스택에 입력한 함수 파라미터를 직접 정리하는 방식이다.


stdcall

stdcall 방식은 Win 32 API에서 사용되며 Callee(호출을 당한 함수)에서 스택을 정리하는 것이 특징이다. 장점은 호출되는 함수 내부에 스택 정리 코드가 존재하므로 함수를 호출할때 마다 ADD ESP, XXX명령을 써줘야 하는 cdecl 방식에 비해서 코드 크기가 작아진다. Win 32 API는 C언어로 된 라이브러리이지만 기본 cdecl방식이 아닌 stdcall 방식을 사용한다. 이는 C이외의 다른 언어에서 API를 직접호출 할 때 호환성을 좋게 하기 위한 것이다.


fastcall

fastcall 방식은 기본적으로 stdcall방식과 같지만 함수에 전달하는 파라미터 일부(2개까지) 스택메모리가 아닌 레지스터를 이용하여 전달하는 것이 특징이다. 어떤 함수의 파라미터가 4개라며녀 앞의 두개의 파라미터는 각각 ECX,EDX파라미터를 이용하여 전달한다,

 fastcall의 장점은 레지스터에서 접근하기 때문에 이름 그대로 빠른 호출이 가능하다.  그렇지만 ECX, EDX 레지스터를 관리하는 추가적인 오버헤드가 필요한 경우가 있다.

'리버스 엔지니어링' 카테고리의 다른 글

PE 헤더 -1  (0) 2018.01.11
PE File Format -1  (0) 2018.01.10
Process Explorer란?  (0) 2018.01.10
abex' 2nd crackme 분석  (0) 2018.01.08
abex' crackme#1 분석  (0) 2018.01.04