IA-32 천천히 알아보자.

2018. 2. 22. 16:220x03 Reversing Theory

728x90

IA-32에 대해 공부를 하고 메모를 하는 시간을 가져보았습니다. 오늘 포스팅은 이야기를 전해주는 컨셉으로 진행해볼까합니다.



먼저, IA-32 프로세서 계열은 물리주소를 사용하여 8비트 물리메모리에 접근한다고 합니다. 해당 물리메모리는 마더보드에 있는 저장장치라고 하네요. 

물리메모리는 정수형이면서 0에서 부터 1씩 증가하는 형태로 되어있다고 합니다. 주소 0 가까이 있을 수록 하위 메모리라고 하고, 마지막 바이트 근처는 상위 메모리라고 합니다. 


IA-32 이름에서 볼 수 있듯이 주소라인은 32개입니다. 그림으로 보는게 이해가 빠를 것 같아 그림으로 만들어 보았습니다.



이 그림을 보면, 주소라인 32개와 버스 2개(데이터, 제어)가 CPU와 연결되어 있다는 것을 알 수 있게 됩니다.


각 바이트는 32비트 주소가 할당되어 있으며 주소공간은 2^32의 주소지정 가능한 바이트(4GB)로 구성되어 있습니다. 

중요한 사실이 하나 있습니다. 이용 가능한 물리 메모리의 실제 총량은 항상 주소공간의 크기와 일치하는 것은 아니라는 것입니다. 

물리 주소공간은 프로세서가 접근 가능한 물리 메모리의 최대 총량을 나타내게 됩니다. 


IA-32 프로세서는 물리 주소 확장(PAE : Pysical Address Extension)을 사용하여 32개의 주소라인보다 더 많은 접근을 허용하는 특성을 제공한다고 합니다. 이것은 프로세서의 물리 주소공간을 이전의 4GB 제한을 초과하여 52개의 주소라인까지 확장할 수 있습니다.


상기에서 그려둔 버스가 왜 필요한지에 대해서 궁금한 사람이 있을겁니다. 필요하니 그렸겠죠? ^^ 


물리메모리를 접근하고 갱신하기 위하여, 프로세서는 제어버스와 데이터버스를 사용하게 되는데 이때 버스는 프로세서가 하드웨어 서브시스템과 연결하는 일련의 전선입니다.

말이 되게 어려운 듯 한데, 버스라는것은 A와 B가 있으면 그 두개를 연결해주는 거라고 생각하면 됩니다. 왜 우리가 A장소에서 B장소 갈 때 버스를 이용하는 것 처럼요. 


제어버스와 데이터버스에 대해 서술해보면 제어 버스는 말 그대로 어떤 것을 컨트롤 해야하는데, 컨트롤은 프로세서가 하고 대상자는 메모리입니다. 프로세서가 메모리를 읽거나 쓸 때 제어버스를 이용하게 됩니다. 


데이터버스는 프로세서와 메모리 사이에서 데이터를 주고 받을 때 사용하게 됩니다. 


자 그렇다면, 프로세서가 메모리에서 데이터를 읽어올 때 어떤 단계들을 수행하는지 궁금해집니다. 


이해하기 쉽게 의인화 해보겠습니다.


Processor : " 야 RAM DATA 내놔" 

RAM : "알았어 기다려 왜이리 급해 3단계만 수행하면 되니까 참아" 

Processor : "뭐하면 되는데?"

RAM : "우선 너는 주소라인에서 읽어야 할 바이트 주소를 지정해봐"

Processor : "오케이 아까전에 그림에서 봤던 그 주소라인에서 지정하면 되는거지?"

RAM : "맞아. 지정을 다했다면, 이제 넌 제어버스를 이용해서 나에게 읽기 신호를 보내렴 으휴 내가 이것까지 다 너에게 설명해야하니?"

Processor: "미안 나도 아는건데 니가 굳이 설명하는걸 ..우째? 이제 내가 해야 하는 일은 끝난 것 같은데 그치?"

RAM : "맞아. 이제 내가 너에게 읽기 신호를 받았으니까 너가 지정해둔 바이트를 데이터 버스로 다시 너에게 줄거야"

Processor : "오케이 쉽네. 빨랑 줘"


반대의 상황은 어떨까요? 이번에는 프로세서가 메모리에 데이터를 쓸 때 상황입니다.


Processor : "야 RAM DATA 좀 쓰자 자리 있냐?"

RAM : "응 있으니까 너가 어디 쓸 지 지정이나 하셔"

Processor : "지정 끝냈고...음 아까처럼 제어버스를 이용해서 신호를 보내면 되는데 이번엔 쓰기 신호지? 아 나 똑똑한듯? "

RAM : "오 이제 지 알아서 잘 처리하네 좋아"

RAM : "하지만 이번엔 너가 할일이 더 남았어."

Processor : "뭔데?"

RAM : "너가 직접 데이터를 써야하니까 지정한 만큼 데이터 버스에 보내줘야지"

Processor : "아... 읽을 때는 니가 반환하지만 쓸 때는 내가 보내야하는거구나.. 알았어"


이해가 되시나요? ㅎㅎ.. 


중요한 사실이 하나 있습니다. 

IA-32 프로세서는 한번에 4바이트 데이터를 읽고 쓸 수 있어요. 프로세서는 첫 바이트의 주소(가장 낮은 주소의 바이트)를 사용하여 32비트의 페이로드를 지정하게 되요. 


이번에는 IA-32 프로세서 계열이 어떻게 메모리 보호 서비스를 제공하는지 알아보겠습니다.


메모리 보호 서비스에는 2가지 상황이 부여되네요. 첫번째 평면(flat) 메모리 모델부터 살펴보도록 하죠.


평면 메모리 모델은 물리 메모리 모델과 다르게 추상적이라고 합니다. 평면 모델에서 메모리는 연속적인 순서로 된 바이트라고 표현한다네요. 주소는 물리주소와 마찬가지로 0부터 시작하여 임의의 값 까지입니다. 지금 우리가 공부중인 IA-32는 2^31 -1 이 되겠습니다. 이렇듯 특정 바이트의 주소를 선형 주소 공간(Linear address space)라고 합니다.


두번째로는 세그먼트된 메모리 모델이라고 합니다. 세그먼트된 메모리 모델 역시 추상적입니다. 세그먼트된 모델에서 메모리는 세그먼트(segment)라는 구분된 공간의 영역으로 나타난다고 합니다. 운영체제에서도 세그먼테이션이라고 하면 불특정한 크기로 쫙쫙 쪼개어 져있는 것을 나타내는데 여기서도 그런 구분된 공간의 영역으로 쓰이는걸까요? 암튼 이 까지는 확정 짓기 어려운 것 같고, 계속 이어가자면 특정 세그먼트 내에서 주소의 바이트는 논리 주소(logical address)라고 지정된다고 하네요. 논리 주소는 두 개의 부분인 세그먼트 선택자와 유효주소(offset address)로 구성되어 있다고 합니다. 아하 그렇다면 오프셋이라는것은 논리 주소안에 들어가는 구성요소 였다는 것도 한번 되 짚고 넘어 갈 수 있네요 헤헷

논리주소의 또 다른 구성요소인 세그먼트 선택자는 참조 되는 세그먼트를 결정하고, 유효 주소는 세그먼트 내의 바이트 위치를 지정하게 됩니다.


이런 건 역시 그림이 최고죠. 




이제 조금 어려워 지는데요. 운용모드에 대해서 알아볼겁니다. 예전에 64비트 멀티코어 책을 보면서 열심히 이해를 했었는데 사실 많이 까먹은 것 같기도 하니 새로 공부한다는 마음으로 알아볼겁니다.


IA-32에서 어떤 모드들을 지원하는지 알아야합니다. 이것을 운용모드라고 말하고요. 


IA-32에서 운용모드는 3가지가 있습니다. 3대장이라고 생각하죠 뭐. 


첫 번째 대장은 실제 모드(REAL MODE)입니다. 

실제모드는 구형 인텔 8086/88 프로세서의 16비트 실행 환경을 구현한다고 하네요

실제모드는 역방향 호환성을 목적으로 구동 (뭔 소린지...) 책의 번역이 조금 이상한 것 같아서 구글링으로 지식을 얻어보았습니다.


위키백과에서는 이렇게 표현을 해두었습니다.

리얼 모드는 리얼 주소 모드 또는 호환 모드라고하고, 80286이후 x86 호환 CPU 운영방식이라고 하네요. 

리얼 모드는 20비트 세그먼트 메모리 주소 공간이 특징들을 결정하는데 최대 1 MB의 메모리가 번지에 기록 될 수 있다는 것을 뜻한다고 하네요. 

80286 계열 이후의 모든 x86 CPU들은 리얼 모드에서 전원이 켜질 때 시작된다고 합니다. 


두 번째 대장은 보호 모드(PROTECT MODE)입니다.


위키백과에서는 이렇게 표현을 해두었습니다.

보호 모드는 컴퓨터에서 보호 가상 주소 모드라고도 하며 X86 호환 CPU의 운영방식이라고 하네요. 처음에는 1982년, X86 아키텍처에 추가 되었다가 인텔의 80286(286) 프로세서로, 나중에 1985년 80386(386)으로 연장되었다고 합니다.

보호 모드는 시스템 소프트웨어가 다중 작업, 가상 메모리, 페이징 그리고 응용소프트웨어를 넘는 운영체제 제어 능력을 높이기 위해 고안된 운영체제의 다른 기능들을 이용할 수 있게 도와준다고 합니다. 

X86 보호모드를 지원하는 프로세서가 전원이 켜지면 리얼 모드에서 함수를 실행하여 초기의 X86 프로세서에서의 호환성을 보완한다고 합니다.

보호 모드는 시스템 소프트웨어가 몇 개의 서술자 테이블을 설정하고 제어 레지스터(CR0)에서 프로텍션 이네이블(PE:Protection Enable)비트를 설정한 뒤에 진입한다고 합니다. 보호 모드가 추가해 놓은 개선 사항(리얼모드와 비교하면 단연 호환성인 것같군요)덕에 폭 넓게 채택되어 사용 중이라고 합니다. 


보호모드는 16비트 보호 모드와 32비트 보호 모드로 나뉘어 진다고 합니다. 


우선 위키백과를 토대로 워밍업을 해보도록 하겠습니다. 


16비트 보호 모드는 24비트 물리 주소 공간에 접근할 수 있으며, 1 세그먼트 근처에 최대 64KB의 공간을 제공할 수 있다고 합니다. 세그먼트 레지스터를 기반으로 세그먼트 방식의 가상 환경을 만든답니다.(세그먼트 기반 -> 세그먼트 방식 기반에 따라 방식이 결정되는 그런 구조인가 봅니다.)

보호 된 공간 밖에 있는 메모리에 접근하면 바로 예외처리로 인해 처리가 중지됩니다. (이런건 cpu가 자기 자신을 인터럽트 하는 trap이라고 할 수도 있겠죠) 80286의 16비트 PVAM의 모든 보호 위반 예외는 인터럽트 벡터 테이블 INT13에만 할당할 수 있다고 합니다. INT13이 할당되게 되면 사용하던 프로세스로 돌아갈 수 없다고 합니다. 다시 말해 외부 저장 장치가 있는 가상 환경 시스템에서 페이지 위반을 예외로 처리하여 페이지를 스왑하고 나서 프로세스를 다시 시작할 수 있습니다. (그렇다면 우리는 여기서 알 수 있는 것이 잘못 된 스왑 즉, 스왑을 함에 있어서 허가되지 않은 보호된 공간에 접근하게 되면 EXCEPTION이 충분히 터질 수 있다는 것을 알 수 있습니다) 

세그먼트 서술자에는 쓰이지 않는 비트가 있기 때문에 이를 이용해 관리를 받을 수는 있지만, 메모리 접근 위반을 바탕으로 관리를 받을 수는 없습니다.


32비트 보호 모드는 인텔 80386 세대 이후 부터 지원이 되었다고 하네요. 32비트의 선형 주소 공간으로 접근할 수 있고 (위에서 언급했듯이 선형 주소 공간은 사용가능한 바이트 전체 영역) 1 세그먼트에 최대 4 GB 공간을 제공할 뿐만 아니라 (16비트에서 확실히 저장 공간이 진화했네요) 페이지 테이블을 통해 물리 주소로 변환 할 수 있고, 페이징 방식의 가상 기억을 사용할 수 있다고 합니다. (여기서 페이징이란, 정확한 크기로 딱딱 나누어져 있는 메모리 방을 의미합니다 정확한 말로는 고정 크기의 블록이라고 표현하죠...) 

한 페이지는 기본적으로 4KB, 프로세스가 직접 읽어들이도록 만들어져 있는 페이지 테이블도 4KB(그렇기 때문에 1024개의 엔트리를 보관가능)입니다. 

그렇다면, 우리는 또 한가지를 짚고 넘어갈 수 있겠습니다. 대충 이해를 위한 억지 슈도코드입니다.

if( !( (페이지 == 4KB) && (페이지 테이블 == 4KB) ) ) { nonononono... }


가상 86모드는 32비트 보호모드의 특별한 기능중에 하나라는 것도 알아두면 좋을 듯 합니다.


보호모드에서는 많은 기능을 지원합니다.

1) 페이징

2) 32비트 물리 및 가상 주소 공간

3) 32 비트 세그먼트 오프셋

4) 리얼 모드로 되돌아가는 기능

5) 가상 8086

6) 32비트 물리 주소 공간은 80386SX와 오래 된 286 버스를 사용하는 다른 386프로세서에는 존재하지 않음.


위에서 언급한 리얼 모드로 되돌아가는 기능에 대해서도 위키 백과에 간단하게 서술 되어 있어서 옮겨 적으면서 공부해보았습니다.


386이 나오기 전에는 보호모드(16비트겠죠?)에서 리얼모드로 돌아가는 방법이 없었다고 합니다. 그래서 IBM에서는 CPU를 다시 설정하고, 콜 스택(Stack Pointer) 시스템 레지스터를 저장하고 PIC(Programmable Interrupt Controller)안에서 인터럽트 마스크의 시간을 정하는 환경을 만들었다고 합니다. 


보호 모드로 들어가려면, GDT(Global Descriptor Table)에 적어도 3 항목을 만들어야 한다고 합니다. 으아 이놈 되게 어려웠었는데.. 


1) NULL 서술자

2) 코드 세그먼트 서술자

3) 데이터 세그먼트 서술자 


마지막 대장 시스템 관리 모드(SMM : System Management Mode) 입니다.

시스템 관리 모드는 인텔 386SL에 처음 등장하였고, x86 아키텍쳐 후반에 나온 마이크로프로세서에서 사용할 수 있다고 합니다. 운영 체제를 비롯하여 모든 프로세스를 일시 중단하고 펌웨어나 하드웨어 보조 디버거가 높은 권한을 받아 실행된다고 합니다. 


SMM은 이후에 나온 것 답게 용도가 많습니다.


1) 메모리, 칩셋 오류 관리 (시스템 이벤트 관리)


2) 높은 CPU 온도나 시스템 끄기 관리 (시스템 보안 기능 제공)


3) 팬 켜기, 전원 관리


4) 메인보드 하드웨어를 가상으로 구현하여 버그를 확인할 수 있음


5) USB로 부터 PS/2 마우스나 키보드를 가상으로 구현할 수 있음


6) 도시바, IBM 노트북 컴퓨터와 같은 시스템 구성을 담당할 수 있음


7) 높은 권한의 루트킷을 실행할 수 있음


8) 신뢰 플랫폼 모듈에 대한 콜을 가상으로 구현할 수 있음. 


몇 몇은 처음들어보는 생소한 말들 이군요... 차차 다 알 수 있겠죠?


조금 더 공부를 하고 포스팅을 진행해야겠습니다.