본문 바로가기
Study/Reversing

[리버싱] 함수: 프롤로그&에필로그와 호출 규약

by graygreat 2017. 9. 1.
728x90
반응형


함수 호출 과정에 대해 알아보자.


1. 함수가 사용할 파라미터를 스택에 넣고 함수 시작지점으로 점프(함수 호출) 한다.


2. 함수 내에서 사용할 스택프레임을 설정한다. (프롤로그)


3. 함수의 내용을 수행한다.


4. 수행을 마치고 처음 호출한 지점으로 돌아가기 위해 스택을 복원한다. (에필로그)



함수의 프롤로그와 에필로그는 함수호출 규약에 따라 조금씩 다르다.



함수 호출 규약이란?


호출자(Caller)와 피호출자(Callee) 간에 '함수를 호출할 때 전달되는 인자의 순서나 사용이 끝나고 나서의 스택 정리 등'에 대한 약속이라고 할 수 있다. 


크게 _cdecl, _stdcall, _fastcall이 있다.



cdecl


주로 C언어에서 사용되며 함수를 호출한 함수(Caller)에서 스택이 정리된다.


가변 길이 파라미터를 전달할 수 있다는 장점이 있다.


함수 이름 앞에 언더바(_)를 추가하는 특징이 있다. 


EX) function abc --> _abc



stdcall


win32 API에 주로 사용되며 호출된 함수(Callee)에서 스택이 정리된다.


가변 인자를 전달하는 것이 불가능하나 함수 호출 후에 스택 정리를 하지 않아 속도면에서 빠르다는 장점이 있다.


함수명 앞에 언더바(_)를 붙이고 뒤에는 @를 붙인 후 매개변수의 전체 바이트 수를 10진수로 표기하는 것이 특징이다.


EX) function abc --> _abc@8



fastcall


파라미터의 마지막 2개는 스택이 아닌 레지스터(ecx, edx)에 저장하여 전달되며 호출된 함수(Callee)에서 스택이 정리된다.


빠른 함수 호출이 가능하지만 해당 레지스터에 민감한 데이터가 포함되어있거나 다른 목적이 있다면 파라미터를 따로 저장 해야한다는 단점이 있다.


함수명 앞과 뒤에 @를 붙이고 매개변수 크기를 10진수로 표기하는 것이 특징이다.


EX) function abc --> @abc@8



다시 정리해보자.




스택 정리 방법


- cdecl : Caller가 Callee의 스택을 정리함.


- stdcall : Callee가 자신의 스택을 정리함.





cdecl는 왜 Caller가 Callee의 스택을 정리하는 이유?


이유는 C언어의 가변인자 함수 때문이다.


Callee에서 스택 프레임 정리를 일관되게 처리할 수 있는 정형화된 routine을 만들기 어렵다.(파마리터의 값이 가변적이기 때문)


만약 이것을 Callee에서 모두 처리하려면, Callee의 파라미터가 몇 개인지 체크하고, 그에 따라 스택을 정리하는 복잡한 절차를 거쳐야 한다.


그런데 Caller는 Callee의 파라미터가 몇 개인지 Callee를 호출하는 순간 이미 알고 있기 때문에 작업이 더 수월하다.




stdcall에서 스택정리를 callee가 하는 이유?


윈도우 표준 함수(Win API)의 경우에는 가변 인자 함수가 없고, 모든 함수의 파라미터가 고정되어 있다.


그래서 Caller가 굳이 스택을 정리 할 필요 없이, Callee에서 스택을 정리한다.


(Callee에서 자기자신의 스택을 정리하는 것이 더 효율적이다.)




반응형

댓글