함수 호출 규약은 함수를 호출 했을 때와 함수를 실행하고 반활할 떄의 약속이다.
예를 들어 Main함수에서 sum함수를 호출 할 때, sum으로 인자값을 전달해주는데 어떤 방법을 사용하고, sum함수의 호출이 끝났을 때 sum함수에서 return한 값을 어떻게 main함수로 가져오는지 등을 정해놓은 것이 함수 호출 규약이다.
x86 함수 호출 규약
함수호출규약 | 사용 컴파일러 | 인자 전달 방식 | 스택 정리 | 적용 | |
stdcall | MSVC | Stack | Callee | WINAPI | |
cdecl | GCC, MSVC | Stack | Caller | 일반 함수 | |
fastcall | MSVC | ECX, EDX | Callee | 최적화된 함수 | |
thiscall | MSVC | ECX(인스턴스), Stack(인자) | Callee | 클래스의 함수 |
x86-64 함수 호출 규약
함수호출규약 | 사용 컴파일러 | 인자 전달 방식 | 스택 정리 | 적용 | |
MS ABI | MSVC | RCX, RDX, R8, R9 | Caller | 일반 함수, windows syscall |
|
System ABI | GCC | RDI,RSI,RDX,RCX,R8,R9,XMM0-7 | Caller | 일반 함수 |
Caller 와 Callee
Caller는 호출자 즉, 함수를 호출한 쪽이고 Callee는 피호출자 즉, 호출을 당한 함수를 말한다.
예를 들어 main()에서 add()를 호출 했다면, Caller는 main()이고 Callee는 add()이다.
cdecl
#include "stdio.h"
int add(int a, int b)
{
return (a + b);
}
int main(int argc, char* argv[])
{
return add(1, 2);
}
위 코드를 디버거로 살펴보면 401010 main()에서 파라미터 1,2를 401000 add()로 넘겨주고, 함수가 끝난 뒤 Caller였던 main 함수에서 ADD ESP,8 명령어를 통해 스택포인터의 위치를 조정해주는 것을 볼 수있다.
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 방식에서는 add()함수에서 RETN 8을 통해 Callee가 직접 스택을 정리하는 모습을 볼 수있다.
'.study > pwnable' 카테고리의 다른 글
[포너블 기초] 버퍼 오버플로우 (0) | 2023.10.01 |
---|---|
[포너블 기초] x86_handray (0) | 2023.09.14 |
[포너블 기초] Docker (0) | 2023.09.13 |
[포너블 기초] 스택 프레임 (0) | 2023.09.12 |
[포너블 기초] x86-32, x86-64 레지스터 (0) | 2023.09.12 |