본문 바로가기
리버싱(Reversing)/리버싱 개념

리버싱 핵심 원리 10장 (함수 호출 규약)

by LIZ0904 2020. 9. 28.
반응형

함수 호출 전에는 파라미터를 스택을 통해 전달한다. 스택은 프로세스에서 정의된 메모리 공간이며, PE 헤더에 그 크기가 명시되어 있다. 이는 프로세스가 실행될 때 스택 메모리의 크기가 결정된다는 것과 같다. (동적 메모리 할당 X)ESP(스택 포인터)는 스택의 현재 위치를 가리키는 역할을 하는데, 함수 호출 후에 ESP를 어떻게 정리하는지에 대한 약속이 함수 호출 규약이다.

 

주요 함수 호출 규약은 3가지로 볼 수 있고, 이에 대해서 상세히 살펴보도록 하자!

 

 

 

 

1. cdecl

 cdecl 연습코드

 

주로 C언어에서 사용되는 방식으로, Caller(호출자: 함수를 호출한 쪽)에서 스택을 정리하는 특징을 갖고 있다. 이 방식의 장점은 C언어의 printf() 함수와 같이 가변 길이 파라미터를 전달할 수 있다는 점이다.

 

 

2. stdcall

stdcall 연습코드

Win32 API에서 사용되며, Callee(피호출자: 호출을 당한 함수)에서 스택을 정리하는 특징을 갖고 있다. 예를 들어 디버깅 시 cdecl에서는 RETN 명령어만 쓰여있는 반면, stdcall에서는 *RETN 8 처럼 리턴 후 지정된 크기만큼 ESP를 증가시킴으로써 스택정리가 수행된다. 

※RETN 8은 RETN + POP 8byte와 같은 의미이다.

 

이 방식의 장점은 Callee 내부에 스택 정리 코드가 존재하므로 함수를 호출할 때마다 ADD 명령을 써줘야 하는 cdecl 방식에 비해 코드 크기가 작아진다는 점이다. 참고로 Win32 API는 C언어로 된 라이브러리 이지만 cdecl 방식이 아닌 stdcall 방식을 사용한다.

 

※stdcall 방식으로 컴파일을 하고 싶을 땐 함수명 앞에 '_stdcall'을 붙여주면 된다.

 

 

 

 

3. fastcall

기본적으로 stdcall 방식과 비슷하지만, 함수에 전달하는 파라미터 일부(2개까지)를 스택메모리가 아닌 레지스터를 이용하여 전달한다는 특징을 갖고 있다. 예를 들어 어떤 함수의 파라미터가 4개라면, 앞의 두 개의 파라미터는 각각 ECX, EDX 파라미터를 이용하여 전달한다.

 

이 방식의 장점은 구조상 CPU는 메모리보단 레지스터에 접근하는 것이 빠르기 때문에 좀 더 빠른 함수 호출이 가능하다는 점이다. 하지만 ECX, EDX 레지스터를 관리하는 추가적인 오버헤드가 필요할 경우가 있고, 함수 내요이 복잡하다면 ECX, EDX 레지스터를 다른 용도로 사용할 필요가 있을 때 이들이 갖고 있는 파라미터 값을 어딘가에 따로 저장할 필요가 생기는 경우가 있다.

 

다음 시간에는 11장을 공부해봅시다!

반응형

댓글