목차
함수 호출 규약(Calling Convention)이란?
함수를 호출할 때 파라미터를 어떤 방식으로 전달할지 정해놓은 규약을 말한다.
add라는 함수가 있다고 가정할 때 main 함수에서 add를 호출하면서 파라미터를 전달할 것이다.
그때 전달하는 파라미터는 스택에 저장된다. 그런데 만약 add함수를 또 호출하게 된다면 처음 호출할 때
쌓였던 파라미터 위에 또 파라미터가 쌓이기 때문에 유효하지 않은 파라미터를 삭제하는 과정이 필요하다. 그렇기 때문에 유효하지 않은 파라미터를 가리키고 있는 ESP를 증가시켜서 스택을 정리해주는 것이다.
그래서 스택을 정리하는 방식에 대한 규약이 함수 호출 규약이다.
32bit 함수 호출 규약
32bit 함수 호출 규약으로는 cdecl, stdcall, fastcall이 있다.
cdecl은 call을 하는 쪽에서 스택을 정리하는 방식이다.
만약 main 함수에서 add함수를 호출하는 경우에 add가 끝나고 main함수에서 스택에 저장되었던 파라미터를 정리하기 위해 esp 값을 증가시켜서 스택을 정리한다.
stdcall은 cdecl과 반대로 호출된 함수에서 스택을 정리하는 방식이다. 호출된 함수의 마지막 부분에서 RETN 8 명령을 사용해 함수 내에서 스택을 정리한다. main 함수에 따로 스택ㅇ을 정리하는 명령이 필요없기 때문에 코드의 길이가 줄어든다는 장점이 있다.
fastcall은 stdcall 방식과 같은데 함수에 전달하는 파라미터 일부(최대 2개)를 레지스터를 사용해 전달한다. 레지스터를 이용하기 때문에 빠르게 함수를 호출할 수 있다. 이용하는 레지스터는 ECX, EDX다.
64bit 함수 호출 규약
64bit는 32bit 함수 호출 규약과 다르게 fastcall 방식만 이용한다.
리눅스에서 정수는 EDI, ESI, EDX, ECX, R8, R9 레지스터, 실수는 XMM0~XMM7 레지스터를 사용해서 파라미터를 전달한다.
윈도우에서 정수는 ECX, EDX, R8, R9 레지스터, 실수는 XMM0~XMM4 레지스터를 사용해서 파라미터를 전달한다.
만약 add(int a, int b)라는 함수가 있으면 파라미터가 정수형이라서 EDI, ESI 레지스터에 들어가게 되는데
오른쪽에서 왼쪽 방향으로 파라미터가 들어가기 때문에 int b는 EDI 레지스터, int a는 ESI 레지스터에 들어간다.
'Study > 리버싱' 카테고리의 다른 글
[3] UPX 패킹과 언패킹 (0) | 2020.11.01 |
---|---|
[3] IAT와 EAT 로딩 과정 (0) | 2020.10.26 |
[3] ㄷㄹㅎ 4,5 (0) | 2020.10.25 |
[2] 2주차 과제 (0) | 2020.09.20 |
[0] 32bit 레지스터와 스택 구조, 스택 프레임 (0) | 2020.09.14 |