YeoPEVA

80x86 시스템 및 CPU와 레지스터 본문

#Pwn, Crypto/Pwn - 정리

80x86 시스템 및 CPU와 레지스터

YeoPEVA 2016. 11. 12. 02:47

# 책과 관련 문서를 보고 정리하는것이기 때문에 저작권상 문제가 있을수 있습니다. 만약 저작권상으로 문의가 

들어온다면 이 글은 삭제 됩니다. # 


1. 80x86 ? 

인텔이 개발한 마이크로프로세서 계열을 부르는 말이자, 이들과 호환되는 프로세서들에서 사용한 

명령어 집합 구조들을 통칭하는 말이다. 

-> https://ko.wikipedia.org/wiki/X86


2. 80x86 시스템에 대해 알아보자. 


80x86 // 8088 시스템은 XT라고 불렸던 인텔 CPU의 IBM pc 중 아주 초기의 보급형 모델이라고 합니다.

이후 AT라고 불리는 80286 시스템이 나온 뒤 그 뒤로는 80을 떼 버리고 386,486이라 불렸던 익숙한 모델이 등장하는데

80 x 86 은 이러한 시스템을 통칭하는 말입니다.


3. 80 x 86 CPU 구조에 대해 알아봅시다. 



출처 -> 정보보안개론 (사진)


80x86 시스템의 구조는 전체적으로 이렇습니다. 저기에서 레지스터가 눈에 좀 띄는군요.


그럼 하나 하나 알아보도록 하겠습니다.


연산 장치란?

CPU의 핵심 부분 중 하나인데, 산술과 논리 연산을 수행하는 

연산 회로 집합으로 구성된다고 합니다.


내부장치 (연산장치)


 내부장치

기능  

가산기 

 덧셈 연산을 수행합니다

보수기 

뺄셈 연산을 수행합니다, 1의 보수나 2의 보수 방식을 이용한다고 하네요. 

시프터 

비트를 오른쪽이나 왼쪽으로 이동하여 나눗셈과 곱셈 연산 수행 합니다. 



관련 레지스터


 관련 레지스터

기능 

누산기 

연산의 중간 결과를 저장합니다  

데이터 레지스터 

연산에 사용할 데이터 저장  

 상대 레지스터

연산 실행 결과로 나타나는 양수와 음수, 자리 올림, 오버플로우 상태를 기억합니다. 


제어 장치 -> 입출력, 기억, 연산장치를 제어하고 감시합니다. 

또한 주기억 장치에 저장된 명령을 차례로 해독하여 연산장치 로 보내 

처리되도록 지시합니다.


내부장치 ( 제어장치) 


 내부장치

기능 

명령 해독기 

명령 레지스터에 있는 명령을 해독하여 부호기로 전송 

부호기 

명령 해독기가 전송한 명령을 신호로 만들어 각 장치로 전송 

주소 해독기 

 명령 레지스터에 있는 주소를 해독하여 메모리의 실제 주소로 변환한 후 이를 데이터  레지스터리에 저장합니다. 


관련 레지스터


 관련 레지스터

기능 

명령 해독기 

명령 레지스터에 있는 명령을 해독하여 부호기로 전송합니다. 

부호기 

명령 해독기가 전송한 명령을 신호로 만들어 각 장치로 전송합니다.  

 주소 해독기 

명령 레지스터에 있는 명령을 해독하여 메모리의 실제 주소로 변환. 이를 

데이터 레지스터리에 저장합니다.  


 -> 명령 해독기랑 주소 해독기는 명령을 해독한다는 점에서 일치하네요.


레지스터 -> 처리 중인 데이터나 처리 결과를 임시 보관하는 CPU 내의 기억 장치로

대개 연산 장치나 제어 장치에 함께 포함되어 있습니다.


+ 전반적으로 중요합니다 (시스템 해킹) 숙지하지 않으면 어셈블리어가 힘듭니다.

이건 다음 장에서 다루도록 하죠.


그리고 BUS interface는 

-> 노드의 외부 노드와 CIU 사이의 인터페이스 역할을 하는 것. RS-232C나 CCITT의 V.24가 대표적이다.

[http://terms.naver.com/entry.nhn?docId=816933&cid=50376&categoryId=50376]

라고 하는데 저도 이쪽은 잘 모르겠네요, 추후에 정보가 생기면 작성하겠습니다.

[아마 운영체제쪽으로 들어가면 파게 될것 같은데..]


4. 레지스터리에 대해 알아봅시다. 


레지스터리는 CPU 내부에서 데이터를 일시적으로 저장하는 장소입니다.

그냥 변수인데 CPU가 쓰는 변수라고 생각하면 편할것 같네요 ㅇㅁㅇ 

조금 감이 안 잡히는것 같은데 예를 들어보죠,

CPU가 일하다가 잊어먹을것 같은게 생기면 어딘가에다가 끄적이고 다시 일을 할껍니다. 

물론 프로그램도 메모를 하는일이 생깁니다. 그 메모가 바로 레지스터리라는거죠 

그럼 이 레지스터리를 숙지한다면 시스템 해킹에서 유리하겠죠? 



그럼 더 자세히 파봅시다.


80286 시스템까지는 CPU가 16비트, 레지스터리도 16비트 였습니다.

80386 시스템, 즉 32비트 운영체제에서는 기본적으로 레지스터가 32비트이므로, 8비트나 16비트로 나누어

사용하기도 한다고 합니다. 


그럼 80386 이상 버전에서의 레지스터의 종료 및 용도에 대해 알아보죠,


종류에는 ->범용 레지스터, 세그먼트 레지스터, 포인터 레지스터, 인덱스 레지스터, 플래그 레지스터가 있습니다.



일반적인 시스템의 프로그램 레지스터 구성 (달고나 문서)


뭔가 엄청 많은데 하나, 하나씩 살펴보도록 하겠습니다;;


먼저 범용 레지스터입니다. 



범용 레지스터 (달고나 문서)

이게 범용 레지스터입니다, 연산 장치가 수행한 계산 결과의 임시 저장, 산술 및 논리연산, 주소 색인 등의 

여러 목적으로 사용이 가능합니다. 여기서 EAX,EBX,ECX,EDX가 있다는것을 알수있습니다.

그럼 차례대로 알아보도록 하죠

+ 참고로 저 앞에 E가 붙은 이유는 확장된을 표현한다고 합니다. 또한 32비트 경우에는 위처럼 

   AH,AL로 나뉘어 있는 것을 보실수 있으신데

   AH -> 왼쪽 8비트 (상위 부분) / AL -> 오른쪽 8비트 (하위 부분) 이라고 합니다.


그럼 차례대로 알아보도록 합시다 


EAX 레지스터 

입출력과 대부분 산술 연산에 사용됩니다! [ex -> 곱셈,나눗셈,변환 명령 등,,]

+ win 32 API 함수들은 모두 리턴 값을 EAX에 저장한 후 리턴한다고 한다.


EBX 레지스터 

DS 세그먼트에 대한 포인터를 저장합니다 (DS 세그먼트 안의 데이터를 가리킴)

ESI + DSI와 결함, 인덱스에 사용된다고 합니다. 또한 메모리의 주소 지정을 확장하기 위해 인덱스로 사용 가능한 

유일한 범용 레지스터 입니다.


ECX 레지스터

문자열 처리나 루프가 반복되는 횟수를 제어합니다(루프를 위한 카운터)


EDX 레지스터

입출력 연산에 사용,EAX와 함께 사용됩니다. (I/O 포인터)


ESI + EDI 레지스터  [인덱스 레지스터]

ESI는 DS 레지스터가 가리키고 있는 데이터 세그먼트 내의 어느 데이터를 가리키고 있습니다.

EDI는 ES 레지스터가 가리키고 있는 데이터 세그먼트 내의 어느 데이터를 가리키고 있으므로 

둘다 데이터 세그먼트 내의 어느 데이터를 가리키고 있는것 같으나

ESI는 문자열 처리에서 source를, EDI는 문자열 처리에서 destination을 가리키고 있습니다.

주로.. 메모리의 한 영역에서 다른 영역으로 데이터를 연속적으로 복사할때 쓰인다고 하는군요.


EBP 레지스터 [포인터 레지스터]

SS 레지스터가 가리키는 스텍 상의 한 데이터를 가리키는 포인터입니다.

함수의 시작주소 저장, 지역 변수 등을 참조할때 기준이 되며, ESP 레지스터와 함께 쓰이면서 스택 프레임을 형성,

스택 프레임? -> 함수가 호출 될때 ESP을 EBP에 저장하고 있다가(mov %esp, %ebp) , 모든 루틴이 끝나고 

함수가 리턴시 이 ESP 값을 돌려주어 스택 형성에 문제가 생기지 않도록 하는 기법이다.

(SS -> 스택 세그먼트 레지스터) <- 곧 배울것입니다. 


ESP 레지스터 [포인터 레지스터]

SS 레지스터가 가리키는 스택 세그먼트의 맨 꼭대기를 가리키는 포인터입니다. 

스택 확장시 -> 상위 주소에서 하위주소로 값이 바뀜

이때 가장 하위 주소를 저장하는 역할을 하는 것이 이 ESP 레지스터이다.


+ EIP 레지스터 [포인터 레지스터]  [Instruction Pointer] 

현재 실행 중인 코드 세그먼트에 속한 현재 명령을 가리키며, 실제 메모리상의 주소를 참조할 때 CS 레지스터와 

함께 사용됩니다.



이렇게 범용 레지스터를 다뤄 보았고.. 다음은 세그먼트 레지스터로 CS,DS,SS,ES,FS,G라는 종류로 나뉩니다. 


출처 -> 달고나 문서


세그먼트 레지스터는 프로세스의 특정 세그먼트를 가리키는 포인터 역할을 합니다. 

이때 세그먼트에 대해 조금 설명을 덧 붙이자면

프로그램에 정의된 메모리상의 특정영역.. 코드.데이터.스텍 등을 포함하여 메모리의 대부분에 위치할 수 있다고

합니다.  


출처 ->달고나 문서 


이와 같이 CS는 Code Segment를,  DS,ES,FS,GS 는 Data Segment를, SS는 Stack segment를 가리키고

있다는 것을 알수 있습니다. 이제 하나씩 설명을 붙여보겠습니다.


CS -> 실행될 기계 명령을 포함하며 코드 세그먼트의 시작 주소를 가리킵니다. 

   일반 프로그래밍에서는 이 레지스터리를 건드릴 일은 없습니다.


DS -> 프로그램에 정의된 데이터, 상수, 작업 영역을 포함합니다. 데이터 세그먼트의 시작 주소를 가리키며

   프로그램은 참조 하려는 데이터의 오프셋을 DS 레지스터에 저장된 주소 값에 더해 데이터 세그먼트 내에 

   위치해 있는 데이터의 주소를 참고한다고 합니다.


SS -> 스택 세그먼트로 실행 과정에서 필요한 데이터나 연산 결과 등을 임시로 저장하거나 삭제할때 사용됩니다.

  스택 세그먼트의 시작주소를 가리킵니다.


그외 ES,FS,GS ->  ES는 추가로 사용된 데이터 세그먼트의 주소를 가리킴, 메모리 주소 지정을 다루는

 스트링 연산(문자 데이터) 에 사용되며 이 경우 EDI 레지스터와 함께 사용된다고 합니다.

FS,GS도 위와 같은 역할이나 거의 사용되는 일은 없습니다.


이제 레지스터도 슬슬 끝을 달려가고 있네요. 

플래그 레지스터입니다.


플래그 레지스터는 상태 플래그, 제어 플래그, 시스템 플래그로 나뉘어져있습니다. 

각 플래그마다 사용 목적과 특징이 다르니 하나씩 알아보도록 하죠. 

출처 -> 달고나 문서


먼저 상태 플러그입니다. [Status flags]

상태 플래그는산술 명령 결과를 반영합니다 (ADD,SUB 같은 산술 명령) 

종류에는 CF,PF,AF,ZF,SF,OF,DF가 있습니다.


CF (carry flag)

연산을 수행하면서 carry 혹은 borrow가 발생하면 1이 됩니다. 

carry,borrow? -> 덧셈 연산시 bit bound를 넘거나 뺄셈을 할시 빌려오는 경우를 말하고 있습니다.


PF (Parity flag)

연산 결과 최하위 바이트의 값이 1이 짝수 일 경우에는 1이 되며, 패리티 체크를 하는데 사용된다고 합니다!


AF (Adjust flag)

연산 결과 carry나 borrow가 3bit 이상 발생할 경우 1이 됩니다.


ZF (Zero flag) 

결과가 zero임을 가리킵니다. if문 같은 조건문이 만족될 경우 set 됩니다.


SF (Sign flag)

이것은 연산 결과 최상위 비트와 값이 같습니다, Signed 변수의 경우에는 양수 - 0, 음수일시 1이면 됩니다.


OF (Overflow flag)

정수형 결과값이 너무 큰 양수이거나 너무 작은 음수여서 피연산자의 데이터 타입에 모두 들어가지 않을 경우 1이

됩니다.



DF (Direction flag)   +  [제어 플래그]

문자열 처리에서 1일 경우 문자열 처리 instruction이 자동으로 감소 ->(문자열 처리가 high address에서 low address로

이루어집니다) , 0일시 자동으로 증가 합니다.


[스트링 명령 (MOVS, CMPS ,SCAS, LODS, STOS)을 제어한다. DF가 1이면 스트링 명령은 자동 감소된다. 

(스트링을 상위 주소에서 하위주소로 처리한다.) 

DF가 0이라면 스트링 명령은 자동 증가되며 (스트링을 하위 주소에서 상위 주소로 처리)

STD/CLD 명령은 각각 DF 플래그를 세트하고 클리어한다.


-------------------------------------------------------------------

이렇게 상태 플래그를 다루어 보았는데요, 다음으로는 시스템 플래그를 보도록 하겠습니다.

시스템 플래그 또한 그 수가 많은 편인데요, (IF,TF,IOPL,NTT,RF,VM,AC,VIF,VIP,ID)가 있습니다.


TF - Trap flag로 디버깅을 할 때 single-step을 가능하게 하려면 1을 줍니다.

디버깅 시 'single step Mode 활성화시 세트, 비활성화 하면 클리어


IF - Interrupt enable flag. 프로세서에게 mask한 interrput에 응답할 수 있게 하려면 1을 주면 된다.

(프로세서의 인터럽트 처리 여부를 제어한다) -> IF가 세트되어 있을시 시스템의 인터럽트 처리, 클리어시에는 무시한다.


IOPL - I/O privilege level field. 현재 수행 중인 프로세스 혹은 task의 권한 레벨을 가리킨다.

현재 수행 중인 프로세스의 권한을 가리키는 CPL이 I/O address 영역에 접근하기 위해서는 

I/O privilege level보다 작거나 같아야한다.

(현재 실행되는 프로그램 및 태스크의 입출력 특권 레벨을 지시한다. 현재 실행 중인 프로그램이나 태스크가

 I/O 주소 공간에 접근하려면 CPL이 I/O 특권 레벨보다 낮거나 같아야 하며  CPL 0에서 PORF/IRET 

명령 실행으로 수정할수 있다.)


NT - Nested task flag. Interrput의 chain을 제어한다. 1이 되면 이전 실행 task와 현재 task가 연결되어 있음을 나타낸다.

인터럽트되거나 호출된 태스크를 제어한다. 현재 태스크가 이전에 실행된 태스크와 연결되었으면 세트되고,

연결되지 않으면 클리어된다.


RF- Resume flag Exception debug 하기 위해 프로세서의 응답을 제어한다.

프로세서의 디버그 예외 반응을 제어한다. 세트되어 있으면 디버그 오류를 무시하고 다음 명령어를 수행한다.


VM - Virtual -8086 mode flag. Virtual-8086 모드를 사용하려면 1을 준다.

V86 모드를 활성화하면 세트되고, V86 모드를 사용하지 않고 보호 모드로 리턴되면 클리어된다.


AC - Alignment check flag. 이 비트와 CR0 레지스터의 AM 비트가 set 되어 있으면 메모리 레퍼런스의 

alignment checking이 가능하다.

메모리 참조 시 정렬 기능을 활성화하면 세트된다.


VIF - Virtual interrput flag. IF flag의 가상 이미지이다. VIP flag와 결합시켜 사용한다.

VIP - Virtual interrput pending flag. 인터럽트가 pending(경쟁 상태) 되었음을 가리킨다.

(VIF,VIP)

-> 가상 모드 확장과 관련해서 사용된다.


ID - Identification flag. CPUID instruction을 지원하는 CPU인지를 나타낸다.

CPUID 명령의 지원 유무를 결정한다. 



+ 위에서 다룬 EIP 레지스터 관련 (Instruction Pointer)

Instruction 포인터 레지스터는 다음 실행할 명령어가 있는 현재 code 세그먼트의 offset 값을 가진다. 

이것은 하나의 명령어 범위에서 선형 명령 집합의 다음 위치를 가리킬 수 있다. 뿐만 아니라 JMP,Jcc,CALL,RET와 

IRET Instruction 이 있는 주소값을 가진다. EIP 레지스터는 소프트웨어에 의해 바로 엑세스 할 수 없고 

control-transfer Instruction ( JMP,Jcc,CALL,RET)이나 interrput와 exception에 의해서 제어된다. EIP 레지스터를 읽을 수 있는 방법은 CALL instruction을 수행하고 나서 프로시저 스택으로부터 리턴하는 instruction을 읽는 것이다.

프로시저 스택의 retrun instruction pointer의 값을 수정하고 retrun instruction(RET,IRET)을 수행함으로 해서 

EIP 레지스터의 값을 간접적으로 지정이 가능하다. 



다음 글에서는 8086의 시스템 메모리를 간략하게 정리할 예정입니다.


이러한 지식을 알아야하는 이유는 버퍼오버플로우 공격에서 적절한 padding 사용 및  return address를 찾고 

필요한 어셈블리 코드를 추출하고 이해하기 위해 필요합니다.


목적 -> 외우기 힘듬 8086 시스템의 구조가 기억이 안날때 다시 볼수있다면 완성.


1차 END


2차 - 2016/12/4 END 






'#Pwn, Crypto > Pwn - 정리' 카테고리의 다른 글

Centos 7 삽질기 - [0] 소개  (0) 2018.07.20
참고할만한 영상..?  (1) 2018.05.04
쉘코드 관련 링크  (0) 2018.02.18
시스템 해킹 - 전반적인 계획  (0) 2017.07.21