System Hacking/Buffer Overflow

[Buffer Overflow] 8086 Memory Architecture

jir4vvit 2020. 3. 17. 17:21

참고문헌

제목 : 해커 지망생들이 알아야할 Buffer Overflow 기초

작성자 : 달고나

출처 : www.wowhacker.com

 

* 사진과 글은 위 문서를 참고하였습니다.

 

<8086 Memory Architecture>

8086? : 인텔사에서 개발한 16비트 마이크로프로세서이며, x86 아키텍처를 적용한 첫 제품이다.

 

8086 시스템의 기본적인 메모리 구조

시스템이 초기화 되기 시작하면 시스템은 커널을 메모리에 적재시키고 가용 메모리 영역을 확인하게 된다.

시스템은 운영에 필요한 기본적인 명령어 집합을 커널에서 찾기 때문에 커널 영역은 반드시 저 위치에 있어야 한다.

 

32bit 시스템에서는 CPU가 한꺼번에 처리할 수 있는 데이터가 32bit 단위로 되어 있다는 뜻이다.

그래서 메모리 영역에 주소를 할당할 수 있는 범위가 0~2^32-1 이다.

 

하지만 최근 시스템의 CPU는 한꺼번에 64bit씩 처리할 수 있으므로 메모리 영역 역시 0~2^64-1 이다.


<하나의 프로세스, 즉 하나의 프로그램이 실행되기 위한 메모리 구조>

segmented memory model

오늘날의 시스템은 멀티 테스킹(mylti-tasking)이 가능하여 메모리에는 여러 개의 프로세스가 저장되어 병렬적으로 작업을 수행한다.

-> 가용한 메모리 영역에는 여러 개의 segment들이 저장될 수 있다.

 

segment : 하나의 프로세스를 묶은 것

             실행 시점에 실제 메모리의 어느 위치에 저장될 지 결정된다.

 

segment는 code segment, data segment, stack segment의 구조로 되어 있다.

시스템에는 최대 16,383개의 segment가 생성될 수 있다.

그리고 하나의 segment는 최대 2^32byte 크기를 가질 수 있다.

 

 

code segment

시스템이 알아들을 수 있는 명령어, 즉 instruction이 있다.

이것은 기계어 코드로써 컴파일러가 만들어낸 코드이다.

 

instruction은 명령을 수행하면서 만흔 분기과정과 점프, 시스템 호출 등을 수행하기 되는데 분기와 점프의 경우 메모리 상의 특정 위치에 있는 명령을 지정해 주어야 한다.

 

분기? : 프로그램의 실행순서를 변경하여 다른 명령을 실행할 수 있도록 하는 것. ex) if문

 

하지만 segment는 자신의 현재 메모리 상의 어느 위치에 저장될 지 컴파일 과정에서는 알 수 없기 때문에 정확한 주소를 지정할 수 없다.

-> logical address 사용

 

logical address는 실제 메모리 상의 주소(physical address)와 매핑되어 있다.

즉 segment는 segment selector에 의해서 자신의 시작위치(offset)를 찾을 수 있고 자신의 시작 위치(offset)로부터의 위치(logical address)에 있는 명령을 수행할 지를 결정하게 되는 것이다.

 

실제 메모리 주소(physical address) = offset + logical address

 

example.

logical address, physical address

 

segment가 실제로 위치하고 있는 메모리 상의 주소를 0x80010000라 가정

code segment 내에 들어있는 하나의 instruction IS 1을 가리키는 주소는 0x000001000 => logical address

 

instruction IS 1의 실제 메모리 상의 주소(physical address) = 0x80010000(offset) + 0x00000100(logical address)

                          0x80010100

 

이 segment가 메모리상의 어느 위치에 있더라도 segment selector가 segment의 offset을 알아내어 해당 instruction의 정확한 위치를 찾아낼 수 있게 된다.

 

 

data segment

프로그램이 실행시에 사용되는 데이터가 들어간다.

여기서 말하는 데이터는 전역 변수 이다.

 

전역 변수? : 어떤 변수 영역에서나 사용될 수 있는 변수를 말한다.

 

data segment는 다시 4개의 data segment로 나뉘는데 각각 현재 모듈의 data structure, 상위 레벨로부터 받아들이는 데이터 모듈, 동적 생성 데이터, 다른 프로그램과 공유하는 공유 데이터 부분이다.

 

 

stack segment

현재 수행되고 있는 handler, task, program이 저장되는 데이터 영역으로

우리가 사용하는 버퍼가 자리잡게 된다.

 

multiple stack을 생성할 수 있고 각 스택들 간의 switch가 가능하다.

 

mutiple stack? :

배열스택은 처음에 크기가 고정되어 있다는 단점이 있다.

크게 잡을경우 데이터가 많이 몰려 스택에 데이터를 넣지 못하는 문제가 있을 수 있고, 이를 고려해 스택의 사이즈를 최대로 잡아 버리면, 쓰이지 않는 메모리 공간이 많이 낭비가 된다.

multiple stack은 이러한 배열스택의 문제점을 조금이나마 줄이고자 하는데 있으며, 기본적인 개념은 스택과 동일하다.

 

지역 변수들이 자리잡고 있다.

 

지역 변수? : 한 지역 내, 중괄호에 의해 만들어지는 영역에서만 사용될 수 있는 변수를 말한다.

 

스택은 처음 생성될 때 그 필요한 크기만큼 만들어지고 프로세스의 명령에 의해 데이터를 저장해 나가는 과정을 거치게 되는데 이것은 stack pointer(SP)라고 하는 레지스터가 스택의 맨 꼭데기를 가리키고 있다고 한다.

스택에 데이터를 저장하고 읽어 들이는 과정은 PUSH와 POP instruction에 의해서 수행된다.

스택은 가장 최근에 PUSH된 데이터를 POP명령을 통해서 가져오게 된다고 한다.

 

 

출처: https://yahma.tistory.com/2

위 그림은 stack을 표현한 것으로 왼쪽은 PUSH(삽입)를 의미하고 오른쪽은 POP(추출)을 의미한다.