본문 바로가기

Reversing

05. 스택, 스택프레임

1. 스택(Stack)


스택의 구조나 부가적인걸 설명하기에 앞서서 스택의 기본을 설명하겠습니다.


스택은 일단 후입선출구조(FILO)로 마지막에 들어간게 제일 먼저 꺼내지는 특징을 지니고 있다.

그리고 높은주소에서 낮은주소로 성장한다. 그림으로 살펴보면


대략 이런식으로 생겼다. 저 안에 들어있는건 신경쓸 필요없다.

중요한 부분은 높은주소에서 낮은주소로 성장한다는 것, 그리고 저 옆의 esp라는 것이다.

높은주소에서 낮은주소는 그렇다치자. 그럼 esp는 무엇일까?


ESP(Extend Stack Pointer) 즉, 말 그대로 스택 포인터다. 스택이 현재 어디에 있는지를 가리키는 역할을 하는 레지스터다.

그럼 저 esp는 어디에 쓰일까?



이 그림을 보자. 스택에 메인함수,3,2,function1(),1이 들어있다.

현재 스택의 상태는 1을 가리키고 있고, 프로그램의 실행 상태도 그에 맞게 실행되고 있을것이다.

그렇다면 1에 맞는 실행상황이 끝나고나서 function1()로 돌아가려면 스택은 어떻게 되어야할까?

현재 ESP가 가리키고 있는 부분을 function1()의 부분으로 옮겨주면된다.


이 그림과 같이 말이다. 이러한 역할을 하는게 ESP이다.



2. 스택 프레임(Stack Frame)


위에서 스택에 대해서 간략히 알아봤다.

그럼 스택 프레임이란건 뭘까?


간단하게 말하자면 ESP레지스터가 아니라 EBP라는 레지스터를 사용해서 

스택 내 변수들이나 복귀주소 파라미터에 접근하는 방식이다.


그럼 EBP는 뭘까?

EBP(Extend Base Pointer) , 베이스 포인터이다. 사실상 스택의 최하단(?).. 을 가리키고 있다고 보면된다.

(최하단이란것은 그림상의 가장 높은 주소에 해당하는 부분을 말한다)


이 스택 프레임이란것에 대해 그림으로 살펴보자.



그림을 보면 위 스택에서 보인것과 별반 다르지않다.

일단 ESP가 main을 가리키면서 시작한다.


달라진건 이부분이다. ESP뿐만 아니라 EBP라는 레지스터가 등장해서 스택의 최하단을 가리키고있다.

그럼 저 EBP는 어떻게 저길 계속 가리키는건가?


어셈코드로 보면 이해가 빠른데


push esp -> esp를 push

mov ebp, esp -> esp의 주소를 ebp로 넘겨준다. 즉, 스택의 가장 최하단 부분의 주소값을 ebp가 가지고있는다.


이렇게 되는것이다. 그래서 EBP는 계속 스택의 최하단을 가리키고, ESP만 이동하면서 스택의 현재 실행위치를 가리키게된다.

그럼 여기서 오는 이점이 무엇인가? 사실 이렇게만봐서는 이점이 보이지않는다.


아래 그림을 보자.


main 함수 안의 function1() 함수 안의 function2() 함수 안의 function3()을 설명하고 싶었다..

어쨌든 그림을 보면 현재 ESP의 위치는 function3()을 가리키고있다.

그렇다면 다시 main 함수로 복귀하려면 function3() -> function2() -> function1() -> main 과 같은 루틴을 거쳐야한다.

하지만 스택 프레임에서는 EBP가 스택의 최하단, 즉 main 함수를 가리키고 있지않은가?

굳이 ESP가 한 단계씩 거치면서 main 함수로 돌아올 필요가 없다.


한줄의 어셈 코드로 ESP는 단숨에 EBP와 같은 위치로 돌아올 수 있는것이다.


mov esp, ebp


이렇게 EBP의 위치를 ESP로 저장해버리면 그림과 같이 ESP의 위치가 바뀐다.


이런식으로 말이다. 속도면에서 엄청난 이점이 아닐 수 없다.

사실 저 function1(), function2()와 같은 함수나 main 함수의 시작전에

이전 EBP, 즉 function1()의 경우에서는 main함수의 EBP, function2()의 경우에서는 function1()의 EBP가 있다.


이런식으로 말이다. 저 이전 EBP를 이용해서 다른 함수 내에서도 복귀할 함수로 빠르게 돌아갈 수 있는것이다.

즉, 어떤 함수내에서 문제가 발생해도 디버깅을 원활히 수행할 수 있게된다.



대략적으로 스택, 스택프레임에 대해서 알아봤는데 필자의 능력부족으로 내용이 풍성하지 못하고, 틀린점이 있을수도 있다.

다른 문서들을 참고하며 공부하는걸 추천한다!

반응형

'Reversing' 카테고리의 다른 글

07. arm 어셈블리어 정리  (0) 2017.10.27
06. gdb 명령어 정리  (0) 2017.09.29
04. 함수 호출 규약  (0) 2017.08.02
03. 패킹 & 언패킹  (0) 2017.05.26
02. IAT & EAT  (0) 2017.05.24