x86 환경에서의 메모리 구조
메모리는 프로세스 동작과 실행에 필요한 정보를 저장한다.
(IA-32)x86 환경을 기준으로 4GB(2**32 byte = 4GB)의 메모리를 가지는데, 2GB 단위로 OS가 사용하는 커널 영역과 사용자가 실행한 프로세스가 사용하는 유저 영역으로 나뉜다.
지금까지 본 메모리의 구조는 물리(Real/Physical) 메모리이 구조이고, 다음에 알아야 할 것은 가상(Virtual/Logical) 메모리이다.
실제 프로세스가 저장된 물리 메모리는 2GB이지만, 하나의 프로세스는 4GB 크기의 하나의 가상 메모리를 가진다. 당연하지만, 물리 메모리 상의 실제 메모리 주소와 가상 메모리 상의 주소는 다르며 CPU에 있는 MMU(Memory Management Unit)이 가상 주소를 물리 주소로 변환해주는 역할을 한다.
**가상 메모리의 이유
: 프로세스 간 독립된 주소 공간을 갖기 때문에 다른 프로세스의 메모리에 직접 접근 불가하다(프로세스 간 격리)
가상 메모리를 통해 물리 메모리 접근 권한을 제어할 수 있어서 시스템 안정성과 보안이 향상된다.
유저 영역의 메모리 구조는 Code, Data, Heap, Stack으로 구분되어 있다. 아래의 설명을 참고하자.
Code(text)
- 실행할 명령어(프로그램 코드)가 저장
- 일반적으로 읽기 전용(무결성 보장)
Data
- 초기화된 전역 변수와 정적 변수 저장
- w, r 가능 영역, 프로그램 실행 중 값이 변할 수 있다
BSS(Block Started by Symbol section)
- 초기화되지 않은 전역 변수와 정적 변수 저장
- 프로그램 시작 시 0으로 초기화
Heap
- 동적 메모리 할당 (malloc, new..)
- 주소가 커지면서 확장
Stack
- 함수 호출 시 생성되는 지역 변수, 매개변수, 반환 주소, 스택 프레임 등 저장(임시 데이터 영역)
- 주소가 작아지면서 확장된다(높 -> 낮)
*code(text)를 제외하고 r-w이 가능하다.
다음은 유저 영역 메모리 구조 예시이다. (한번 정해진 변수의 위치는 변경되지 않는다)
Stack & Stack Frame
메모리의 한 영역인 Stack은 주로 함수 호출과 관련된 데이터를 관리하며 다음과 같은 특징들을 가진다
- LIFO: Last In First Out
- 자동 할당: 함수가 호출될 때 자동으로 메모리 할당, 종료 시 자동으로 해제
- 주소 증/감: push의 경우 ESP가 감소하면서 메모리가 할당되고, pop의 경우 ESP가 증가하면서 메모리 할당이 해제된다.
- 지역 변수, 스택 프레임, 함수 복귀 주소(Maintain Call Chain), Structured Exception Handler Chain(SEH)
Stack Frame은 함수 호출 정보를 스택에 저장하는 구조를 의미한다. 스택 프레임에는 함수에 전달된 인자, 함수 종료 시 복귀한 주소(Return Address), 이전 함수가 사용하는 스택 주소를 포함한다.
호출된 함수 별로 하나의 스택 프레임을 사용한다.
'정보보안 > Reversing' 카테고리의 다른 글
[Reversing] Code to Execution(x86) (0) | 2025.04.07 |
---|---|
[Reversing] Calling Convention(호출 규약) (0) | 2025.04.07 |
[Reversing] Assembly Language - Instruction Set (0) | 2025.03.31 |
[Reversing] Register (0) | 2025.03.31 |
[Reversing] 데이터 구성 단위, Endian, 보수(Complement) (0) | 2025.03.31 |