이번엔 Stack의 구조와 Stack Frame Pointer에 대해 알아보겠습니다.

 

Stack이란?

Stack이란 RAM내의 영역 중 하나로

프로그램에서 함수가 호출될 때 필요한 지역변수와 매개변수가 저장되는 영역입니다.

또 Stack은 후입선출(Last In First Out)구조이기 때문에 데이터 저장시 높은 주소에서 낮은 주소방향으로 데이터를 저장하게 됩니다.


Stack의 구조

Stack은 기본적으로 저장공간이기 때문에 데이터를 담을 수 있는 상자가 쭉 늘어서 있는 창고라고 생각하면 됩니다.

 

그럼 이 Stack에 우리의 컴퓨터는 어떤 방식으로 데이터를 저장하는걸까요?

이해를 위해서 예시를 하나 보도록 하겠습니다.

main(){

  int A = sum(1,2)

  return A

}

sum(x,y){

   return x+y

}

위와 같은 단순한 코드하나를 만들어 봤습니다. 

 

우리가 이 코드로 만든 프로그램을 돌릴때 Stack에선 데이터를 어떻게 처리하는지 보겠습니다.


Stack의 구조

함수가 호출될 때 Stack엔 매개변수, 반환 주소값, 지역변수 이렇게 3가지의 데이터가 들어갑니다.

 

main()함수 실행시

  1. main()함수엔 매개변수가 없어 반환 주소값부터 들어가게 됩니다.
  2. 가장 아래(높은)주소부터 RET(반환 주소값), RBP(main()함수 스택 프레임의 시작점), 변수 c, 버퍼(지역변수) 이렇게 채워 가는걸 볼 수 있습니다.

 

위와 같은 함수의 호출 정보를 스택 프레임(Stack Frame) 이라고 합니다.

 

sum()함수 실행시

  1. sum()함수는 main()함수 안에서 호출되기 때문에
  2. sum()함수를 호출하게 되면 main()함수의 스택 프레임위에 다시 sum()함수의 스택 프레임을 쌓게 됩니다.
  3. sum()함수엔 매개변수가 있어 매개변수 x, y를 먼저 쌓아주는 모습을 볼 수 있습니다.

 


스택 프레임 포인터(Stack Frame Pointer)

이제 Stack이 어떤식으로 데이터를 저장하는지 알게됐습니다.

그럼 저걸 어떻게 사용해서 프로그램을 돌리는 걸까요?

 

CPU내에는 레지스터라고 하는 아주 작은 값만을 담을 수 있는(하지만 처리속도가 매우 빠른)  메모리가 있습니다.

CPU는 이 레지스터와 RAM에 저장되어있는 값들을 이용하여 프로그램을 돌립니다.

Stack의 데이터들을 이용할때도 이 레지스터들을 이용하게됩니다.

 

레지스터는 여러가지 종류가 있지만 Stack에 있는 데이터를 다룰 때 사용하는 레지스터는 SP, FP 레지스터입니다.

 

SP(Stack Pointer) 레지스터 : 다음 데이터가 저장될 스택의 주소를 담고 있는 레지스터

 

FP(Frame Pointer) 레지스터 : SP레지스터가 돌아갈 주소(함수 호출 전)를 담고있는 레지스터

 

SP레지스터는 함수 호출 중 데이터가 저장될 스택의 주소를 가리킵니다. CPU가 SP가 가리키고 있는 스택에 값을 넣고 나면 SP레지스터는 그 위의 주소를 가리키게 변경됩니다.

 

FP레지스터는 함수 호출 이전에 SP레지스터가 가리키고 있던 주소를 담고있게됩니다.

 

함수 호출이 끝난 후 SP레지스터는 FP레지스터에 쓰여져있는 주소를 참고하여 함수를 호출하기 이전의 주소로 돌아가게됩니다.

 

하지만 함수 호출을 여러번 하게 될 경우 FP레지스터의 값이 계속 바뀌기 때문에 스택에 FP레지스터의 값을 저장해 놓음으로써 스택 프레임간의 경계정보를 저장합니다.

'Security > Pwnable' 카테고리의 다른 글

메모리 구조  (1) 2023.03.29

+ Recent posts