메모리는 다음과 같이 크게 4가지 영역으로 나누어집니다.
코드영역이 낮은주소 스택영역이 높은주소 쪽이다.
코드영역은 어셈블리어나 기계어가 있고 데이터영역은 초기화되거나 초기화되지않은 전역변수 및 정적변수가 있습니다. 힙영역은 동적할당되는 곳이고 스택은 지역변수들이 있는 곳입니다.
더 자세한 내용
http://shayete.tistory.com/entry/7-Use-After-Free
위의 사이트에 들어가서 pdf를 다운로드 받으시면 첫번째 페이지에 메모리영역이보다 더 자세히 나와있습니다.
ebp, esp
ebp는 스택에 베이스 포인터로 기준점이라고 생각하시면 이해하는데 더욱 도움이 됩니다.
esp는 스택 포인터로 현재 스택이 가리키고 있는 주소를 의미합니다.
함수의 프롤로그
함수가 호출이 되면 그 전에 함수의 부분과 겹치지 않기 위해서 ebp를 esp의 값으로 맞춰줍니다. 그리고 esp에서 이 함수에서 필요한 공간만큼 빼줍니다. 예를 들어서 이 함수에서 0x20바이트 만큼 필요하면 esp-0x20을 해줍니다. 이러한 부분이 함수의 프롤로그 입니다.
함수의 에필로그
함수가 종료되기 직전에 지역변수를 정리해 주고(esp를 ebp로 맞춰주고)ret을 통해서 그 다음 명령어를 수행한다.
위의 그림의 어셈블리어는 인텔형식이고 sfp는 세이브 프레임 포인터로 이 함수가 호출되기 전 ebp의 값입니다.
예를 들어서 밑의 그림처럼 메인함수에서 printf함수를 호출했을때 스택의 상황입니다.
회색으로 색칠되어있는 ret밑에는 main함수의 스택이고 회색으로 색칠된 ret부터는 printf함수가 호출되어 쓰고 있는 스택입니다. printf 스택에서 저장되어 있는 sfp(회색 ret위에 있는 ebp)는 초록색 ebp의 주소를 가리키고 있습니다(여기서 주의 해야 하는 것! 초록색으로 색칠되어 있는 값을 가리키고 있는게 아니라 주소를 가리키고 있다는 점!!!)
위의 그림을 보시면 왼쪽의 c소스코드가 있고 오른쪽은 어셈으로 본 것입니다.
하늘색 상자는 함수의 에필로그와 프롤로그를 보여줍니다. 위의 코드는 변수를 할당하지 않았기 때문에 rsp(64비트 환경에서는 esp가 확장되어 rsp가 됩니다. 또한 ebp도 확장이 되어 rbp가 됩니다.)에서 -0x땡땡을 해주지 않습니다.
그리고 값이 저장되어 있는 방식은 환경에 따라 빅엔디안 , 리틀엔디안으로 나누어집니다.
리틀엔디안은 우리가 보기 불편한 형식으로 4바이트씩 끊어서 반대로 저장이 되어 있습니다. 간단한 예를 들자면 abcd를 저장하였다고 가정했을때 메모리에는 dcba로 저장이 되어있습니다. 빅엔디안은 리틀에디안에 반대라고 생각하시면 됩니다.
따라서 whatchang은 리틀엔디안에서 tahw nahc ??\0g로 저장이 되어있습니다(?는 쓰레기값을 의미하고 \0은 문자열의 끝을 표현해주는 것입니다.)
뜬금없는 말:
시스템 해킹쪽(보안공부)을 공부한지 얼마되지는 않았지만 공부하면서 느꼈던 점은 스택이 어떻게 쌓이는 지와 스택의 특징들을 잘 이해하면 공격 기법들을 공부할때 이해하기가 훨씬 수월하다-라는 것을 느꼈습니다. 그래서 이 글의 내용이 분명 부족할 것입니다. 따라서 구글링을 더 하셔서 스택이랑 메모리에 대한 공부를 더 하시면 공부하는 데 훨씬 도움이 될거라 생각이 듭니다.