새소식

인기 검색어

Hacking/System

Calling Convention

  • -
반응형

함수 호출 규약

함수 호출 규약은 함수 호출 시 일어나는 행동에 대한 약속이다.

한 함수에서 다른 함수로 호출할 때, 프로그램의 실행 흐름은 다른 함수로 이동한다. 그리고 호출한 함수가 반환하면, 다시 원래의 함수로 돌아와서 기존의 실행 흐름을 이어나간다. 그러므로 함수를 호출할 때는 반환된 이후를 위해 호출자(Caller)의 상태(Stack frame) 및 반환 주소(Return address)를 지정해줘야 한다. 또한 호출자는 피호출자(Callee)가 요구하는 인자를 전달해 줘야 며, 피호출자의 실행이 종료될 때는 반환 값을 전달받아야 한다.

 

함수 호출 규약은 여러 가지 있는데 프로그래머가 코드에 명시하지 않는다면 컴파일러는 지원하는 호출 규약 중에서 CPU 아키텍처에 적합한 것을 선택한다.

함수 호출 규약의 종류는 다음과 같다.

x86

  • cdecl
  • stdcall
  • fastcall
  • thiscall

x86-64

  • System V AMD64 ABI이 Calling Convention
  • MS ABI의 Calling Convention

x86 아키텍처는 레지스터의 수가 적기 때문에 스택으로 인자를 전달하는 규약을 사용한다. 반면에 x86-64 아키텍처는 레지스터가 많으므로 적은 수의 인자는 레지스터만 사용하고, 인자가 많을 경우에는 스택을 사용한다.


cdecl

cdecl은 gcc에서 x86 바이너리를 컴파일할 때 사용하는 함수 호출 규약이다.

cdecl은 레지스터의 수가 적으므로, 스택을 통해 인자를 전달한다. 또한 인자를 전달하기 위해 사용한 스택을 호출자가 정리하는 특징이 있다.

스택을 통해 인자를 전달할 때는, 마지막 인자부터 첫 번째 인자까지 거꾸로 스택에 push 한다.

#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>

int caller(int a1, int a2, int a3)
{
    int ret = a1 + a2 + a3;
    return ret
}

void callee()
{
	caller(1,2,3);
}

int main()
{
    callee();
    return 0;
}

위 코드를 예시로 설명하겠다.

callee함수의 어셈블리어를 보면 push를 3번 하는 것을 확인할 수 있다.  순서는 0x3 -> 0x2 -> 0x1인데 caller함수의 인자랑 같이 보면 마지막 인자부터 순서대로 push 하는 것을 확인할 수 있다. 그리고 esp를 0xc만큼 옮기는데  push를 3번 했기 때문에 0xc만큼 옮긴다.

그리고 caller함수로 들어가면 esp에 0x56555516 주소가 들어가는데 이 주소는 caller함수가 끝나고 return 되는 주소를 의미한다. 

그럼 해당 스택은 위 그림과 같다. a3 -> a2 -> a1 -> callee ret 순으로 쌓이고 caller의 스택 공간을 생성한다.

그리고 해당 공간에서 작업을 한 후 다 끝나면 에필로그를 하고 ret 주소로 return 한다.

반응형

'Hacking > System' 카테고리의 다른 글

Master Canary  (0) 2023.08.22
unsorted bin attack  (0) 2023.05.30
Unsafe unlink  (0) 2023.05.23
Double Free  (0) 2023.04.18
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.