C++의 함수 호출 형태를 보면 3가지(_cdecl / _stdcall / _fastcall)가 있는것을 알것이다.
3가지를 간략히 정리해 보면
1. _cdecl
    - 파라미터 전달은 오른쪽에서 왼쪽 방향으로 스택을 이용
    - 파라미터 해제는 호출한 함수가 정리(그러므로 가변인자가 가능)
2. _stdcall
    - 파라미터 전달은 오른쪽에서 왼쪽 방향으로 스택을 이용
    - 파라미터 해제는 불려진 함수 내에서 정리
3. _fastcall
    - 처음 두개를 레지스터(ecx, edx)를 이용하고 나머지 파라미터를 오른쪼에서 왼쪽으로 스택을 이용
    - 파라미터 해제는 불려진 함수 내에서 정리
위와 같이 정리해 볼수 있다.

그럼 int sum(int a, int b)함수를 3가지로 구현해서 직접 확인해 보자.
첫번째로 아래 코드는 RETN시 스택을 정리 해주기 위한 부분이 없다. 이를 통해서 _cdecl을 이용해 구현한 함수 임을 파악해 볼 수 있다.


다음 코드를 보면 RETN 8을 통해 스택을 정리 해주는 것을 알 수 있다. 또한 ecx, edx를 사용하지 않았으므로 이는 _stdcall을 통해서 구현한 함수 임을 파악이 가능하다.

마지막으로 아래 코드를 보면 ECX와 EDX를 이용하 였다는 것을 알 수 있다. 하지만 _fastcall의 경우 불려진 함수 내에서 스택을 정리한다고 되어있는데 RETN시 스택을 정리 하는 부분이 없어 의아해 할 수 있다. 이는 ECX와 EDX레지스트만 이용하였기 때문에 스택을 정리 해줄 필요가 없기 때문이다. 아래의 함수는 _fastcall임을 알 수 있다.

위와같이 calling convetion을 이해하고 어셈코드의 구조를 파악하고 있다면 리버싱 단계에서 해당 함수의 calling convetion을 파악하고 코드화 하는데 휠씬 도움이 될것 이다.

Posted by hazeyun
,