시큐어코딩 (7) - CH 02-3 프로그램은 메모리에 어떻게 저장되는가
이번 포스트에서는 우리가 실행하는 프로그램이 어떻게 메모리에 저장되고 실행되는지에 대해 살펴보고자 한다
1. Process Memory Organization(프로세스 메모리 조직)
프로그램 : 명령어들의 집합
프로세스 : CPU에 의해 실행중인 프로그램
Organization은 다음에 따라 달라진다
- OS
- Compiler
- Linker
- Loader
2. x86 Registers
프로세스는 CPU에 의해 실행된다.
아래의 이미지는 32bit환경이다
EIP : Extended Instructuin Pointer (확장 명령어 포인터)
ESP: Extended Stack Pointer (확장 스택 포인터)
EBP: Extended Base Pointer (확장 베이스 포인터)
3. Program Stacks
프로그램 스택은 프로그램 실행 및 상태를 추적하는데 사용된다.
- 호출 함수의 반환 주소
- 함수에 대한 인수
- 지역 변수(임시)
4. Stack Segment
아래 코드에 대한 Stack Segment는 다음과 같다.
b() {...}
a() {
b();
}
main() {
a();
}
- 스택은 중첩된 호출을 지원
- 함수 호출의 결과로 스택에 푸시된 정보를 스택 프레임이라 한다
5.Stack Frames
- 스택은 다음을 저장하는데 사요된다.
- 호출 함수의 반환 주소
- 서브 루틴의 실제 인수
- 로컬(자동) 변수
- 현재 프레임의 주소는 레디스터에 저장된다
- 프레임 포인터는 다음 핫무 내에서 고정 참조점으로 사용된다
- 스택 은 다음 중 수정된다
- 서브루틴 호출
- 서브 루틴 초기화
- 서브루틴에서 반환
5-1 서브 루틴 호출에 대해 살펴보자
아래의 함수가 있다고 가정해보자
function(4, 2);
Stack은 다음과 같이 쌓일 것이다.
여기서 411A29h는 반환주소로 스택에 푸시하고 해당 주소로 점프한다
5-2 서브루틴 초기화
아래의 함수가 있다고 가정해보자
void function(int arg1, int arg2)
stack은 다음과 같이 쌓인다
push ebp에서 프레임 포인터를 저장하고
mov ebp, esp로 서브 루틴의 프레임 포인터가 현재 스택 포인터로 설정된다
sub esp, 44h로 로컬 변수에 대한 공간을 할당한다.
*여기서 ebp는 베이스 포인터를, esp는 스택 포인터를 의미한다.
5-3 서브 루틴 반환
아래의 코드가 실행되면
return();
다음의 스택이 쌓인다.
mov esp, ebp에서 스택 포인터를 복원하고
pop ebp에서 프레임 포인터를 복원하고
ret를 통해 스택에서 반환 주소를 꺼내고 해당 위치로 제어를 전송한다
5-1에서 살펴봤던 원래 스택에서 add가 추가된다.
add로 esp를 추가하여 스택 포인트를 조정(복원)함으로써 stack에 쌓여있던 함수 일부분을 삭제한다