About the Stack Frame

‍김상빈·2023년 9월 29일
0

computer_architecture

목록 보기
4/6

오늘은 메모리 Segment 중 Stack Segment에서 사용되는 Stack Frame에 대해서 자세히 설명하겠다.

우선 어떻게 Stack Frame이 생성이 되며 소멸이 되는지 과정부터 이해하기 위해선 함수의 프롤로그와 에필로그에 대해서 이해해볼 필요가 있다.

함수의 프롤로그(Prolog)

소설 책을 읽을 때 프롤로그라는 단어를 많이 보았을 것이다. 말 그래도 이야기를 시작하기 전 사전 작업이라고 보아도 무방하다. 이 처럼 함수의 프롤로그는 함수가 Call로 호출이 되었을 때 함수가 잘 돌아가게 끔 하기 위해 하는 사전 작업이라고 이해하면 편하다.

함수가 호출이 되면 이렇게 스택 프레임이 생성이 되는데 RET은 말 그대로 호출 된 후 다음 코드의 주소를 담고 있으며 RET에 오면 그 주소로 jmp하는 것을 의미한다. SFP는 Stack Frame Pointer로 호출하여 넘어가기 직전에 있던 스택 프레임의 주소를 담고 있는 포인터로 이해하면 편하다.

이렇게 기초적인 스택 프레임 구조를 잡고 함수를 호출하여 이 스택 프레임을 사용하는 이런 단계를 함수의 프롤로그라고 한다.

함수가 계속 계속 호출이 된다면 그림과 같이 스택 프레임이 쌓여가는 것을 볼 수가 있다.

그 다음 함수의 에필로그에 대해서 알아보겠다.

함수의 에필로그(Epilog)

프롤로그의 반대라고 생각해도 무관하다. 프롤로그는 함수를 호출하기 전 스택 프레임을 생성했다면 에필로그는 함수가 끝나고 돌아가려고 스택 프레임을 해제시키는 행위를 말한다. 전에 이야기했다시피 RET을 이용해 돌아갈 때 스택 프레임을 해제시키고 돌아간다. 다음 그림을 보면 이해가 쉬울 것이다.

이제는 어떻게 스택 프레임이 생성이 되고 소멸하는지에 대해서 알아 보았다. 이제는 스택 프레임의 구성에 대해서 자세히 알아보려고 한다.

스택 프레임의 구조


낮은 주소에서 높은 주소로 볼 때 변수들의 값을 저장하는 Buf가 존재하고 그 다음 SFP, RET 그리고 매개인자 순으로 존재하는 것을 사진으로 볼 수가 있다. 사진에서 SFP와 buf1 사이에 rbp가 있고 다음 함수를 콜 할 때 스택 프레임 크기만큼 rsp에서 그 크기를 빼서 공간을 확보한다. 이 설명은 메인 함수가 콜 되고 처음 스택 프레임에서 어떻게 다른 함수가 콜 되면서 어떤 일들이 일어나는지를 설명하는 것이다.

Buffer Over Flow (BOF)

변수가 값을 런타임에서 값을 받을 때 변수의 크기는 정해져 있지만 쓸 수 있는 바이트 수가 무한정이라면 buffer도 다 채우고 SFP RET까지 채울 수 있게 되는 것이다. 이렇게 된다면 다른 변수들의 값을 원하는 대로 바꿀 수 있을 뿐만 아니라 리턴할 주소를 내가 원하는 주소로 바꿀 수가 있어 컴퓨터의 주도권을 빼았아 올 수 있기 때문에 위험하다. 더 자세한 이야기는 다른 글들을 참고하면 감사하겠다.

이해하면 좋은 요약

바이너리를 실행 했을 때 __start에서 처음으로 메인 함수를 콜하면서 스택 프레임이 생성돼자나 그럼 여기서 메인 함수에 있는 변수들의 크기 만큼 버퍼가 생성될거고 그럼 그 다음 함수가 콜 되면 버퍼 주소중 제일 낮은 주소를 기점으로 해서 그 주소에서 다음 함수 call 할 만큼의 스택 프레임을 빼주고 그 공간에 스택 프레임을 넣는것이다.

profile
nickname: pwn_newbe

0개의 댓글