minhui study
Stack구조 및 Stack Frame 본문
메모리 구조
컴퓨터의 운영체제는 프로그램의 실행을 위해 다양한 메모리 공간을 제공하고 있다. 프로그램이 운영체제로부터 할당받는 대표적인 메모리 공간은 다음과 같다.
코드 영역
메모리의 코드 영역은 실행할 프로그램의 코드가 저장되는 영역으로 텍스트 영역이라고도 부른다. CPU는 코드 영역에 저장된 명령어를 하나씩 가져가서 처리하게 된다.
데이터 영역
메모리의 데이터 영역은 프로그램의 전역 변수와 정적 변수가 저장되는 영역이다. 데이터 영역은 프로그램의 시작과 함께 할당되며, 프로그램이 종료되면 소멸한다.
힙(heap) 영역
메모리의 힙 영역은 사용자가 직접 관리할 수 있는 그리고 해야만 하는 메모리 영역이다. 힙 영역은 사용자에 의해 메모리 공간이 동적으로 할당되고 해제된다. 힙 영역은 메모리의 낮은 주소에서 높은 주소의 방향으로 할당된다.
스택 영역
메모리의 스택 영역은 함수의 호출과 관계되는 지역변수와 매개변수가 저장되는 영역이다. 스택 영역은 함수의 호출과 함께 할당되며 함수의 호출이 완료되면 소멸한다.
이렇게 스택 영역에 저장되는 함수의 호출 정보를 스택 프레임이라고 한다.
스택(stack)
한 쪽 끝에서만 자료를 넣고 뺄 수 있는 LIFO(Last In First Out) 형식의 자료 구조로 가장 최근에 스택에 추가한 항목이 가장 먼저 제거될 항목이다. 프로세스에서 스택 메모리의 역할은 다음과 같다.
1) 함수 내의 로컬 변수 임시 저장
2) 함수 호출 시 파라미터 전달
3) 복기 주소(return address) 저장
▶ 스택에 값을 입력하면 스택 포인터(ESP)는 감소하고, 스택에서 값을 꺼내면 스택 포인터는 증가한다.
스택 프레임(stack frame)
스택 프레임이란 쉽게 말해서 ESP(스택 포인터)가 아닌 EBP(베이스 포인터) 레지스터를 사용하여 스택 내의 로컬 변수, 파라미터, 복귀 주소에 접근하는 기법을 말한다. ESP 레지스터 값은 프로그램 안에서 수시로 변경되기 때문에 스택에 저장된 변수, 파라미터에 접근하고자 할 때 ESP값을 기준으로 하면 프로그램을 만들기 힘들고, CPU가 정확환 위치를 참고할 때 어려움이 있다. 따라서 어떤 기준 시점(함수 시작)의 ESP값을 EBP에 저장하고 이를 함수 내에서 유지해주면 ESP값이 아무리 변하더라도 EBP를 기준으로 안전하게 해당 함수의 변수, 파라미터, 복귀 주소에 접근할 수 있다.
메모리의 스택(stack)영역은 함수의 호출과 관계되는 지역변수와 매개변수가 저장되는 영역이다. 스택 영역은 함수의 호출과 함께 할당되며 함수의 호출이 완료되면 소멸한다.
함수가 호출되면 스택에는 함수의 매개변수, 호출이 끝난 뒤 돌아갈 반환 주소값, 함수에서 선언된 지역 변수 등이 저장된다. 이렇게 스택 프레임 덕분에 함수의 호출이 모두 끝난 뒤에, 해당 함수가 호출되기 이전 상태로 되돌아갈 수 있다.
스택 프레임의 동작 방식
int main(void)
{
func1(); // func1() 호출
return 0;
}
void func1()
{
func2(); // func2() 호출
}
void func2()
{
}
다음 그림은 위 예제 코드에서 함수 호출에 의한 스택 프레임의 변화를 보여준다.
① 프로그램이 실행되면 가장 먼저 main()함수가 호출되어 main()함수의 스택 프레임이 스택에 저장된다.
② func1()함수를 호출하면 해당 함수의 매개변수, 반환 주소값, 지역 변수 등의 스택 프레임이 스택에 저장된다.
③ func2()함수를 호출하면 해당 함수의 스택 프레임이 추가로 스택에 저장된다.
④ func2()함수의 모든 작업이 완료되어 반환되면 func2()함수의 스택 프레임만이 스택에서 제거된다.
⑤ func1()함수의 호출이 종료되면 func1()함수의 스택 프레임이 스택에서 제거된다.
⑥ main()함수의 모든 작업이 완료되면 main()함수의 스택 프레임이 스택에서 제거되면서 프로그램이 종료된다.
<참고 자료>
리버싱 핵심원리 (이승원 지음)
tcpschool.com/c/c_memory_structure
'Hacking > Reversing' 카테고리의 다른 글
[WEEK1] 어셈블리어 C언어로 변환하기 (0) | 2020.09.13 |
---|---|
Wargame 'Dreamhack' rev-0 (0) | 2020.09.13 |
Crackme #1 (0) | 2020.09.13 |
[WEEK1]호출규약(32bit/64bit) 정리 (0) | 2020.09.11 |
32bit Register (범용, 세그먼트, EFLAGS...) (0) | 2020.09.02 |