반응형

주관적인 생각이지만, 이 개념을 잘 알고 있어야 BOF, ROP 등등의 여러기법을 이해하는데 수월합니다. 또한 설명에 있어서 이하 존칭은 생략하겟습니다.

<큰 그림>

 환경변수

 스택

 힙

데이터 

 코드(=text)

컴파일된 프로그램 메모리는

 텍스트(=code영역), 데이터, BSS,(Block Started Symbol), 힙, 스택의 5개 세그먼트로 나뉜다( 추가적으로 환경변수가 있지만 이번 설명에서 생략)


텍스트 세그먼트(=코드 세그먼트) ~>EIP가 이곳에 존재한다.

이 세그먼트에는 프로그램의 기계어 명령이 들어있다. 이 세그먼트의 명령 실행 순서는 순차적이지 않다. 왜냐하면 하이레벨 언어의 제어 구조가 어셈블리 언어의 branch,jump,call등의 명령으로 변환되기 떄문이다. 프로그램이 실행되면 EIP는 텍스트 세그먼트의 맨처음 위치로 설정된다. 그리고 프로세서는 다음 작업을 반복 실행한다.

정리해보면,

1.EIP가 가리키고 있는 명령을 읽는다

2. 해당 명령의 길이를 EIP에 더한다.

3.1단계에서 읽은 명령을 수행한다.

4.1단계로 돌아간다.


때때로 이 명령이 jump나 call일 경우가 있는데, 이 전 포스팅에서도 말했듯이 EIP는 메모리의 전혀 다른주소로 바뀌게 된다. EIP는 다음 명령어의 주소를 리턴값으로 저장해두고 넘어가게 된다.

또한, 텍스트 세그먼트는 변수가 아닌 코드만을 저장하고 있으므로 쓰기가 금지되어 있다.텍스트 세그먼트에 쓰려는 시도가 있을 경우 운영체제가 그 사실을 사용자에게 알리고 프로그램은 종료된다. 추가적으로 텍스트 세그먼트가 읽기 전용일 때의 장점으로는 한 프로그램을 여러번 실행했을 때에도 텍스트 세그먼트를 공유할 수 있다는 점이다. 그리고 텍스트 세그먼트는 바뀌는 것이 없으므로 크기도 고정되어 있다.


데이터,BSS세그먼트

전역 변수와 정적 프로그램 변수를 저장하는데 쓰인다. 

데이터 세그먼트: 초기화된 전역 변수와 정적변수가 저장된다.

BSS 세그먼트: 초기화되지 않은 전역 변수와 정적 변수가 저장된다.

~> 이 두 세그먼트 모두 쓰기가 가능하지만 크기는 고정되어 있다.


힙 세그먼트(낮은주소 ->높은주소)

프로그래머가 직접 접근할 수 있는 메모리 세그먼트다. 프로그래머가 어떤 것을 필요로 하든지 이 세그먼트의 메모리 블록을 할당해 사용할 수 있다. 힙 세그먼트의 특징은 크기가 고정되어 있지 않다는 것이다. 그래서 힙은 필요에 따라 크기가 커지거나 작아질 수 있다.

~>힙 세그먼트에 들어있는 모든 메모리는 '할당'알고리즘과 '해제'알고리즘에 의해 관리된다. 힙은 얼마나 많은 메모리가 예약 됐는지에 따라 크기가 증가하거나 감소한다.


스택 세그먼트(높은주소->낮은주소)

크기가 간변적이며, 지역 함수 변수를 저장하고 함수 호출시의 임시 컨텍스트를 저장하는데 쓰인다. 프로그램에서 어떤 함수를 호출할 경우 그 함수는 자신만의 변수 공간을 갖는다. 그리고 그함수의 코드는 다른 메모리에 위치해 있는 텍스트 세그먼트에 저장된다.

~>함수가 호출될 떄에는 컨텍스트와 EIP가 변경되어야 하므로 스택은 함수 호출시 전달된 모든 인자와 EIP가 되돌아 가야 할 주소와 함수에서 사용된 모든 지역 변수를 저장하는 데 쓰인다. PUSH 와 POP으로 메모리가 관리되며 FILO (First in Last Out)형태이다.


ESP는 스택의 맨 끝 주소를 추적하는데 사용한다. 이 주소는 스택에 데이터가 추가되거나 제거됨에 따라 계속 바뀐다. 스택은 매우 동적으로 변하므로 크기가 고정돼 있지 않다. 스택은 힙과 달리 높은 메모리주소에서 낮은 메모리 주소로 증가한다.


EBP는 현재 스택 프레임에 있는 지역함수 변수를 참조하는 데 쓰인다. 각 스택 프레임에는 함수의 입력인자, 함수의 로컬 변수, 자신을 호출한 곳으로 되돌아가는데 필요한 정보를 담고 있는 두 포인터, 저장된 프레임 포인터(SFP: Saved Frame Pointer)와 복귀주소가 있다. SFP는 EBP를 원래 값으로 돌리는데 쓰이고, 복귀 주소는 EIP의 값을 함수 호출이 끝난 뒤에 실행해야 할 주소로 되돌리는데 쓰인다.


반응형
,