Why Memory Structure
프로그램이 실행되기 위해서는 먼저 프로그램이 메모리에 로드 되어야 한다.
또한 프로그램에서 사용될 변수를 저장할 메모리도 필요하다.
기본적으로 메모리에 로드되는 메모리의 구조는 다음과 같다.
Code 영역
코드 영역은 실행할 프로그램 코드가 저장되는 공간으로 text 영역이라고도 부른다.
cpu 는 코드영역에 저장된 명령어를 하나씩 가져가서 패치한다.
Data 영역
데이터 영역은 프로그램의 전역 변수와 정적 변수가 저장되는 영역이다.
프로그램의 시작과 함께 할당되며 프로그램이 종료되면 소멸한다.
Stack 영역
높은 주소에서 낮은 주소로 자라는 LIFO 구조의 영역이다.
지역 변수나, 함수 내에서 필요한 인자, 스택 프레임 등이 저장된다.
push 명령어로 데이터를 저장하고 pop 명령어로 데이터를 인출한다.
Check
아래는 영역의 주소가 어떻게 이뤄지는지 확인해보기 위해 작성한 코드이다.
#include<stdio.h> #include<stdlib.h> char global[0x10] = "global"; int main(){ char stack[0x10] = "stack"; char * heap = malloc(0x10); printf("code : %p\n",(int *)main); printf("global : %p\n",&global); printf("heap : %p\n",(char *)heap); printf("library : %p\n", (char *)printf); printf("stack : %p\n",&stack); }
바이너리를 실행하고 br 을 걸고 vmmap으로 확인해보면 주소가 출력된다.
앞서 설명했던 주소들 이 외에 더 많은 영역을 볼 수 있었다.
vvar
[vvar] 영역은 access 불가능한 영역이라 안에 어떤 값들이 있는지 확인 못했다.
찾아보니 커널과 관련이 있는 영역이라고 한다.
커널 변수(kernel variables)의 약자라고 하는데 그러면 kvar 이여야 되는거 아닌가…?
kernel space와 user space 간의 상호 작용을 지원하기 위해 사용된다고 한다.
vdso
Virtual Dynamic Shared Object 로 가상 동적 공유 오브젝트 이다.
커널과 사용자 공간 프로세스 간의 인터페이스를 제공하는 중요한 메커니즘 중 하나다.
시스템 호출을 수행하기 위해서는 프로세스는 커널 모드로 전환 되어 커널 내부의 코드가 실행 되어야 한다.
이로 인해서 context switch 가 발생한다.
vdso 는 몇 가지 시스템 호출을 user space 에서 직접 처리하므로 kernel mode 로 전환이 필요하지 않는다.
vsyscall
vsyscall 은 Virtual System Call 의 약자로, 커널 내에서 system call 을 실행하는 데 사용되는 가상 메모리 영역이다.
user space 에서 일부 시스템 호출을 처리하는 데 사용된다.
예전 리눅스 커널에서 주로 사용되었으나 현대에는 vdso 및 vsyscall 을 함께 사용하거나 vdso 를 우선으로 사용하는 경우가 많다.
vsyscall 을 사용하는 시스템은 점차 희소해지고 있다.
실습 출력
실습 코드를 실행하면 다음과 같은 주소가 나온다.
위에서 본 영역에 알맞게 들어가있음을 확인할 수 있다.
출력을 보면 Heap과 Stack 사이에는 library 영역이 있음을 알 수 있다.
이 글은 옵시디언을 이용해서 작성되었습니다.
'TOOR' 카테고리의 다른 글
[TOOR] 5.2 NXbit (0) | 2023.09.19 |
---|---|
[TOOR] 5.1. BOF (내 안의 버퍼가 넘친다!) (0) | 2023.09.19 |
[TOOR] 4.Handray (0) | 2023.09.19 |
[TOOR] 3.Stack Frame (0) | 2023.09.19 |
[TOOR] 2.Calling Convention (0) | 2023.09.19 |