콜 스택 구조에서 함수는 자신만의 스택 프레임을 가지게 된다.
서로의 스택 프레임을 구분하기 위해 함수는 프롤로그와 에필로그 과정을 가진다.
(이 글에선 인텔 아키텍쳐 32비트의 어셈블리어를 기준으로 설명한다)
함수의 프롤로그(prolog)
함수의 첫 부분엔 아래와 같은 코드가 있다.
push ebp;
mov ebp, esp;
ebp 레지스터는 보통 스택 프레임의 맨 밑바닥을 가리킨다.
esp 레지스터는 스택 프레임의 최상단을 가리킨다.
스택에서 esp 보다 위에 있는 값들은 사용하지 않는다.
함수가 호출될 때 ebp와 esp는 새로운 스택 프레임의 빌드를 위해 움직이는데
push ebp를 통해
호출 함수(caller)의 ebp가 저장(백업)된다.
이 값은 호출된 함수(callee)가 실행을 마치고 retn을 만날 때
caller의 esp를 찾아가기 위해 저장해둔다.
mov ebp, esp를 통해
caller의 esp가 callee의 ebp가 된다.
이 과정을 통해 callee의 스택 프레임이 빌드되었다고 하며
push ebp를 통해 스택에 저장한 값을 SFP(Saved Frame Pointer)라고 한다.
함수의 에필로그(epilog)
함수의 마지막 부분엔 아래와 같은 코드가 있다.
mov esp, ebp;
pop ebp;
retn;
함수의 몸통이 다 수행되고 나면 함수는 caller로 돌아가는 리턴 과정을 밟게 된다.
이제 ebp는 caller의 ebp로 돌아가야 하며
esp는 callee의 ebp로 돌아가야 한다.
mov esp, ebp; pop ebp;를 합쳐서 leave; 로 표현하기도 한다.
ret 혹은 retn은 pop eip; 를 수행한다.
이는 caller로 돌아가기 위해 수행되는 과정이다.
저장된 리턴 주소를 꺼내 eip에 박아넣는다.
이로 인해 실행 흐름이 caller 함수쪽으로 바뀌게 된다.
(call 명령을 만나면 push eip가 수행됨)
(eip 레지스터는 다음에 실행할 명령어 주소를 가리킴)
아래 파일은 제가 작성한 그림 자료입니다.
'background > linux' 카테고리의 다른 글
Double Free Bug & Tcache Poisoning (0) | 2022.11.03 |
---|---|
ptmalloc2 (0) | 2022.11.01 |
환경 변수(environ) (0) | 2022.10.11 |
ELF 파일 보호 기법 (0) | 2022.10.08 |
mprotect (0) | 2022.09.29 |