[System] 어셈블리어 명령

 

시스템 해킹


(1) 어셈블리어 기본 명령

  • CPU 종류에 따라 동작 가능한 작동 코드가 다른 경우도 있지만, 대부분 비슷

 

1-1. 산술 연산 명령

  • 메모리나 범용 레지스터에 위치한 바이트, 워드, 더블 워드 정수에서 기본적 정수 계산

 

ADD (add)

  • 제1피연산자와 제2피연산자 값을 더한 결과 값을 제1피연산자에 저장

형식 ADD  [제1피연산자], [제2피연산자]
사용 예 ADD AL 4
AL이 원래 3이었다면, 명령 실행 후에는 7이 됨

 

 

SUB (Subtract)

  • 제1피연산자에서 제2피연산자 값을 뺀 결과 값을 제1피연산자에 저장

형식 SUB [제1피연산자], [제2피연산자]
사용 예 SUB AL 4
AL이 원래 7이었다면, 명령 실행 후에는 3이 됨

 

 

CMP (Compare)

  • 데이터의 두 값을 비교할 때 사용

  • 예로 'cmp a, b'는 a에서 b를 뺀 값이 0이면 참이 됨

형식 CMP [제1피연산자], [제2피연산자]
사용 예 CMP AL 4
AL이 원래 7이었다면, 명령 실행 후에는 3이 되고 0이 아니므로 거짓이 됨

 

 

기타 산술 연산 명령

  • ADD, SUB, CMP 외 기타 산술 연산 명령은 다음과 같다.

명령 설명
ADC ADd with Carry 캐리를 포함한 덧셈 수행
SBB SuBtraction with Borrow 캐리를 포함한 뺄셈 수행
DEC DECrement 피연산자 내용을 1 감소 시킴
NEG Change Sign 피연산자 2의 보수로 부호를 반전
INC INCrement 피연산자 내용을 1 증가 시킴
AAA ASCII Adjust for Add 덧셈 결과의 AL 값을 UNPACK 10진수로 보정
DAA Decimal Adjust for Add 덧셈 결과의 AL 값을 PACK 10진수로 보정
AAS ASCII Adjust For Subtact 뺄셈 결과의 AL 값을 UNPACK 10진수로 보정
DAS Decimal Adjust for Subtract 뺼셈 결과의 AL 값을 PACK 10진수로 보정
MUL MUltipLy (Unsigned) AX와 피연산자의 곱셈 결과를 AX 또는 DX:AX에 저장
IMUL Integer MULtiply (Signed) 부호화된 곱셈 수행
AAM ASCII Adjust for Multiply 곱셈 결과의 AX 값을 UNPACK 10진수로 보정
DIV DIVide (Unsigned) AX 또는 DX:AX 내용을 피연산자로 나누고, 몫은 AL 또는 AX에 저장한 다음 나머지는 AH 또는 DX에 저장
IDIV Integer DIVide (Signed) 부호화된 나눗셈 수행
AAD ASCII Adjust for Divide 나눗셈 결과 AX 값을 UNPACK 10진수로 보정
CBW Convert Byte to Word AL의 바이트 데이터를 부호 비트를 포함해 AX 워드로 확장
CWD Convert Word to Double word AX 워드 데이터를 부호를 포함해 DX:AX의 더블 워드로 변환

1-2. 데이터 전송 명령

  • 메모리, 범용 레지스터, 세그먼트 레지스터로 참조되는 주소에 들어 있는 데이터 전송

  • 조건 이동, 스택 접근, 데이터 변환 같은 특정 연산도 수행

 

 

MOV (Move)

  • 데이터를 이동할 때 사용

  • 제1피연산자는 데이터 이동의 목적지이고, 제2피연산자는 이동의 대상

  • 제1피연산자는 레지스터와 메모리가 될 수 있고, 제2피연산자는 수치, 레지스터, 메모리 등이 될 수 있음

  • 하지만 메모리에서 메모리로 이동은 불가능

형식 MOV [제1피연산자], [제2피연산자]
사용 예 MOV AX, [BP+8]
BP의 주소에 8 더한 주소에 있는 데이터 값을 AX에 대입

 

[그림 1] MOV 명령을 실행할 때 스택 동작

 

 

위 그림에서 BP의 현재 값이 0x10000004라면, BP+8은 0x1000000C가 된다.

 

그리고 0x1000000C에 있는 값이 1,024이므로 AX에는 1024가 입력된다.

 

 

PUSH (Push)

  • 스택에 데이터를 삽입할 때 사용

형식 PUSH [제1피연산자]

[그림 2] PUSH 명령을 실행할 때 스택 동작

 

위 그림과 같이 스택은 커지고, 스택 포인터는 데이터 크기만큼 감소한다.

 

 

POP (Pop)

  • 스택에서 데이터를 삭제할 때 사용

  • 스택에서 삭제된 명령은 반환 값으로 받아 사용 가능

형식 POP [제1피연산자]

[그림 3] POP 명령을 실행할 때 스택 동작

 

위 그림과 같이 스택 포인터는 삭제하는 데이터 크기만큼 증가한다.

 

 

LEA (Load effective address to register)

  • 데이터 값을 이동할 때 사용하며, MOV와 조금 다름

  • MOV와 LEA 명령의 공통점은 제1피연산자는 데이터 이동의 목적지지만, 제2피연산자에서 추가 연산을 처리하는 방식이 다름

  • 예로 제2피연산자에 'BP+4'가 있을 때 MOV 명령은 'BP+4'를 주소 값 하나로 처리하지만, LEA 명령은 'BP'만 주소 값으로 인식하고 +4는 BP 주소 값의 추가 연산으로 처리

형식 LEA [제1피연산자] [제2피연산자]
사용 예 LEA AX, [BP+4]
BP의 현재 값이 0x10000004라면, MOV 명령처럼 BP+4인 0x10000008의 주소 값을 가져오는 것이 아닌 0x10000004의 주소에 있는 값에 4를 더해 AX에 대입

 

[그림 4] LEA 명령을 실행할 때 스택 동작

 

 

기타 데이터 전송 명령

  • MOV, PUSH, POP, LEA 외 기타 데이터 전송 명령은 다음과 같다.

명령 설명
XCHG Exchange Register /
Memory with Register
첫 번째 피연산자와 두 번째 피연산자를 바꿈
IN Input from AL / AX to Fixed
port
피연산자로 지시한 포트로 AX에 데이터를 입력
OUT Output from AL / AX to
Fixed port
피연산자가 지시한 포트로 AX의 데이터 출력
XLAT Translate byte to AL BX:AL이 지시한 테이블 내용을 AL로 로드
LES Load Pointer to ES LEA 명령과 유사한 방식으로 다른 ES 데이터의 주소 내용을 참조할 때 사용
LAHF Load AH with Flags 플래그 내용을 AH의 특정 비트로 로드
SAHF Store AH into Flags AH의 특정 비트를 플래그 레지스터로 전송
PUSHF Push Flags 플래그 레지스터 내용을 스택에 삽입
POPF Pop Flags 스택에 저장된 플래그 레지스터 값 삭제

1-3. 논리 명령

  • 연산 부호가 논리 연산을 지정

  • 자리 옮김, 논리합(OR), 논리곱(AND), 기호 변환 등이 있음

 

 

AND (And)

  • 대응되는 비트가 둘 다 1일 때만 결과가 1이고, 그 외는 모두 0

형식 AND [제1피연산자], [제2피연산자]
사용 예 AND AX, 10h
AX 값이 0x08h일 때, 이를 2진수로 표현하면 1000이 된다.
0x10h는 1010이므로 명령을 수행한 후 AX 값은 1000이 된다.

 

 

OR (Or)

  •  대응되는 비트 중 하나만 1이어도 결과가 1이고, 둘 다 0일 때만 0이 됨

형식 OR [제1피연산자], [제2피연산자]
사용 예 OR AX, 10h
AX 값이 0x08h일 때, 이를 2진수로 표현하면 1000이 된다.
0x10h는 1010이므로 명령을 수행한 후 AX 값은 1010이 된다.

 

 

XOR (Exclusive Or)

  • 대응되는 비트 중에서 한 비트가 1이고 다른 비트가 0이면 결과가 1이 됨

  • 비트 두 개가 모두 0 또는 1일 때는 0이 됨

형식 XOR [제1피연산자], [제2피연산자]
사용 예 XOR AX, 10h
AX 값이 0x08h일 때, 이를 2진수로 표현하면 1000이 된다.
0x10h는 1010이므로 명령을 수행한 후 AX 값은 0010이 된다.

 

 

NOT (Invert)

  • 피연산자 1의 보수를 구하는 작동 코드로 각 비트를 반전시켜 줌

형식 NOT [제1피연산자]
사용 예 NOT AX
AX 값이 0x08h일 때, 이를 2진수로 표현하면 1000이 된다.
명령을 수행한 후 AX 값은 0111이 된다.

 

 

TEST (And function to flags, no result)

  • CMP 명령처럼 데이터의 두 값을 비교할 때 사용

  • 단 CMP처럼 제1피연산자에서 제2피연산자 값을 빼는 과정이 없음

  • 즉, 데이터 변경 없이 단순 비교만 함

형식 TEST [제1피연산자] [제2피연산자]
사용 예 TEST AL 00001001b
AL 레지스터에 비트 0과 비트 3이 둘아 0인지 확인하고  싶다면, 제2피연산자에 비트 0(오른쪽의 첫 번째 비트)과 비트 3(오른쪽에서 네 번째 비트)에 1을 적고 나머지에는 0을 적은 후 TEST 명령을 실행한다.
AL의 비트 0과 비트 3이 모두 0이라면 ZF가 세트된다.
비트 0과 비트 3 중 하나라도 1이면 ZF는 클리어된다.
AX가 0x08h라면 비트 3이 1이므로 ZF는 클리어된다.

 

 

기타 논리 명령

  • AND, OR, XOR, NOT, TEST 외 기타 논리 명령은 다음과 같다.

명령 설명
SHL / SAL Shift Left / Shift Arithmetic Left 왼쪽으로 피연산자만큼 자리옮김(이동)
SHR / SAR Shift Right / Shift Arithmetic Right 오른쪽으로 피연산자만큼 자리옮김(이동)
ROL Rotate Left 왼쪽으로 피연산자만큼 회전 이동
ROR Rotate Right 오른쪽으로 피연산자만큼 회전 이동
RCL Rotate through Carry Left 자리 올림(Carry)을 포함 왼쪽으로 피연산자만큼 회전 이동
RCP Rotate through Carry Right 자리 올림(Carry)을 포함 오른쪽으로 피연산자만큼 회전 이동

1-4. 스트링 명령

  • 바이트로 구성된 데이터를 메모리에서 가져오거나 메모리로 전송

 

REP (Repeat)

  • ADD나 MOVS 같은 작동 코드 앞에 위치

  • CX가 0이 될 때까지 뒤에 오는 스트링 명령을 반복

형식 REP 작동 코드 -

 

 

MOVS (Move String)

  • 바이트나 워드, 더블 워드를 옮기는 명령으로 각각 MOVSB, MOVSW, MOVSD가 있음

  • DS:SI가 지시한 메모리 데이터를 ES:DI가 지시한 메모리로 전송

  • MOVS는 피연산자 없이 단독으로 쓰며, 다음 REP 등과 함께 사용되기도 함

형식 MOVSB
사용 예                                     CLD
                                    LEA                          SI,                        String_1
                                    LEA                          DI,                        String_2
                                   MOV                         CX,                       384
REP                         MOVSB  
CLD (Clear Direction) : 디렉션 플래그를 지움
LEA SI, String_1 : String 1의 주소 값을 SI (Source Index)에 저장
LEA DI, String_2 : String 2의 주소 값을 DI (Destination Index)에 저장
MOV CX, 384 : CX에 384를 저장
REP MOVSB : SI에서 DI까지 CX가 0이 될 때까지 1바이트씩 복사

 

 

기타 스트링 명령

  • REP, MOVS 외 기타 스트링 명령은 다음과 같다.

명령 설명
CMPS CoMPare String DS:SI와 ES:DI 내용을 비교한 결과에 따라 플래그 설정
SCAS SCAn String AL 또는 AX와 ES:DI가 지시한 메모리 내용을 비교한 결과에 따라 플래그 설정
LODS LOaD String SI 내용을 AL 또는 AX로 로드
STOS STOre String AL 또는 AX를 ES:DI가 지시하는 메모리에 저장

1-5. 제어 전송 명령

  • 점프 (분기), 조건 점프 (조건 분기), 루프, 호출과 리턴 연산 등으로 프로그램 흐름 제어

 

JMP (Unconditional Jump)

  • 대표적인 점프 명령

  • 프로그램 실행 주소 또는 라벨로 이동

형식            JMP                   [제1피연산자]
사용 예            JMP                         100h
주소로 직접 지정한 100h번지로 점프
          String:                       MOV                  CX,                      384
                                                 ...
                                              JMP                  String
라벨로 JMP를 지정하는 경우

 

이외에도 JMP 명령은 조건에 따라 다음과 같이 다양하게 사용된다.

명령 점프 조건 설명
JC Carry Flag Set CF = 1 CF 값이 1이면 점프
JNC Not Carry Flag Set CF = 0 CF 값이 0이면 점프
JE / JZ Equal / Zero ZF = 1 결과가 0이면 점프
JA / JNBE above / Not below Not Equal CF = 0 and ZF = 0 결과가 크면 점프 (부호화되지 않은 수)
JAE / JNB above Or Equal / Not below CF = 0 결과가 크거나 같으면 점프 (부호화되지 않은 수)
JB / JNAE below / Not above Nor below CF = 1 결과가 작으면 점프 (부호화되지 않은 수)
JL / JNGE Less / Not Greater Nor Equal SF != OF 결과가 작으면 점프 (부호화된 수)
JBE / JNA below Or Equal / Not above (CF or ZF) = 1 결과가 작거나 같으면 점프 (부호화되지 않은 수)
JG / JNLE Greater / Not Less Nor Equal ZF = 0 and SF = OF 결과가 크면 점프 (부호화되지 않은 수)
JGE / JNL Greater Or Equal / Not Less SF = OF 결과가 크거나 같으면 점프 (부호화된 수)
JLE / JNG Less Or Eqal / Not Greater ZF = 1 or SF != OF 결과가 작거나 같으면 점프 (부호화되지 않은 수)
JNE / JNZ Not Equal / Not Zero ZF = 0 결과가 0이 아니면 점프
JNO Not Overflow OF = 0 오버플로가 아니면 점프
JNP / JPO Not Parity / Parity Odd PF = 0 PF가 1이면 점프
JNS Not sign SF = 0 SF가 1이면 점프
JO Overflow OF = 1 오버플로 발생 시 점프
JP / JPE Parity / Parity Even PF = 1 PF가 1이면 점프
JS Sign SF = 1 SF가 1이면 점프
JCXZ CX Zero CX = 0 CX가 0이면 점프

 

  • above, below : 부호 없는 두 수의 크기 관계

  • Greater, Less : 부호 있는 두 수의 크기 관계

 

 

CALL (Call)

  • JMP처럼 함수 호출 시에 사용하며, 제1피연산자에 라벨 지정

  • 하지만 CALL은 리턴 주소로 IP 주소를 백업하여 'PUSH + EIP + JMP'와 의미가 같음

형식 CALL [제1피연산자]

 

 

RET (Return from CALL)

  • 함수에서 호출한 곳으로 돌아갈 때 사용하는 명령

  • 'POP EIP'와 의미가 같음

 

다음은 CALL과 RET의 예시이며, AX에는 0x08h 값이 저장되었다고 가정한다.

                                                    CALL                              SUBR
                                                    ADD                                  AX,                           10h
                                                      ...
              SUBR :                         INC                                   AX
                                                      ...
                                                    RET

 

위 에에서는 SUBR 함수를 호출하면, SUBR 라벨이 있는 곳에서 RET까지 실행된다.

 

이때 INC AX가 있으므로 AX는 0x09h가 된다.

 

RET 명령이 실행되면 CALL 다음 줄인 'ADD AX, 10h'를 실행한다.

 

따라서 AX는 0x19h가 될 것이다.

 

 

LOOP (Loop CX times)

  • 문장들의 블록을 지정된 횟수만큼 반복

  • CX는 자동으로 카운터로 사용하며, 루프를 반복할 때마다 감소

형식 LOOP [제1피연산자]
사용 예                               MOV                   AX,                   0
                              MOV                   CX,                   5
         L1 :               INT                    INT                  AX
                              LOOP                  L1
제1피연산자는 라벨이 되며, 예에서 L1이 CX 숫자만큼 다섯 번 회전하므로 결과적으로 AX는 5가 된다.

 

 

INT (Interupt)

  • 인터럽트가 호출되면 CS:IP와 플래그를 스택에 저장하고, 그 인터럽트와 관련한 서브 루틴 실행

  • 제1피연산자는 인터럽트의 번지로 00~FF(256개) 번지가 할당되어 있고, INT 10H와 INT 21H 인터럽트 많이 사용

  • INT 10H는 화면 클리어 기능, 커서 위치 설정, 커서 현재 위치 찾기 기능이 있음

  • INT 21H는 모니터에 문자 출력, 키보드에서 문자열 데이터 입력 기능이 있음

형식 INT [제1피연산자]

 

 

 

기타 제어 전송 명령

명령 설명
INTO INTerrupt on Overflow 오버플로 발생 시 인터럽트 실행
IRET Interrupt RETurn 인터럽트에서 복귀 (리턴)
LOOPZ / LOOPE LOOP while Zero / Equal 제로 플래그가 1이고 CX 값이 0보다 크면 루프 계속 수행
LOOPNZ /
LOOPNE
LOOP while Not Zero /
Not Equal
제로 플래그가 0이고 CX 값이 0보다 크면 루프 계속 수행

1-6. 프로세서 제어 명령

  • 레지스터의 플래그 값을 세트하거나 클리어

 

STC (Set Carry)

  • 피연산자 없이 사용

  • EFLAGS 레지스터의 CF 값을 세트

 

NOP (No Operation)

  • 아무 의미 없는 명령

  • 일종의 빈칸을 채우는 데 사용

 

기타 프로세서 제어 명령

  • 기타 프로세서 제어 명령은 다음과 같다.

명령 설명
CLC CLear Carry 캐리 플래그 클리어
CMC CoMplement Carry 캐리 플래그 반전
HLT HaLT 정지
CLD CLear Direction 디렉션 플래그 클리어
CLI CLear Interrupt 인터럽트 플래그 클리어
STD SeT Direction 디렉션 플래그 세트
STI SeT Interrupt 인터럽트 인에이블 플래그를 세트
WAIT WAIT 프로세스 일시 정지 상태
ESC ESCape to External Device 종료 명령

# Reference

 

https://www.hanbit.co.kr/store/books/look.php?p_code=B3283906872

[System] 어셈블리어 구조 & 주소

 

시스템 해킹


(1) 어셈블리어의 구조

  • 어셈블리어에는 Intel과 AT&T 문법이 존재

  • 윈도우는 Intel 문법, 리눅스는 AT&T 문법 주로 사용

  • 두 문법의 차이점은 제1피연산자와 제2피연산자의 위치

  • Intel 문법은 목적지가 앞에 오고 원본이 뒤에 오지만, AT&T 문법은 반대

 

1-1. 어셈블리어 명령 형식 (Intel 문법)

  • Label  : (라벨)

  • MOV (작동 코드)

  • AX (제1피연산자)

  • BX (제2피연산자)

  • ; comment (설명)

 

MOV는 제2피연산자 값을 제1피연산자로 복사하는 명령이다.

 

라벨은 기계어 코드로 직접 번역하지 않고, 점프(분기) 명령 등에서 참조할 때 메모리 주소를 계산하는 데 사용한다.

 

사용법은 다음과 같다.

Label_1 : MOV AX, BX
         	...
         	...
         	JMP Label_1 (Label_1로 무조건 이동하라는 명령)

 

다음 코드는 MOV부터가 기계어로 번역되는 부분으로 어셈블리어 작동 코드(명령 코드)라고 한다.

 

그리고 피연산자는 레지스터, 문자, 숫자, 메모리 주소가 될 수 있다.


(2) 어셈블리어 데이터 타입과 리틀 엔디안 방식

2-1. 데이터 타입

  • 바이트(Byte) : 1바이트(8비트) 데이터 항목

  • 워드(word) : 2바이트(16비트) 데이터 항목

  • 더블 워드(Double word) : 4바이트(32비트) 데이터 항목

[그림 1] 어셈블리어 데이터 타입

 

 

2-2. 리틀 엔디안 방식

  • 데이터는 리틀 엔디안 방식에 따라 스택에 저장, 참조

  • 번지 두 개로 나누어 저장해야 하는 16비트 데이터의 경우 하위 바이트는 하위 번지 저장, 상위 바이트는 상위 번지 저장

  • 예로 HEX 값 0x34F3을 1500번지에 저장하기 위해 하위 값 0xF3은 1500번지에 저장하고, 상위 값 0x34는 1501번지에 저장 

주소 1500번지 1501번지
저장된 데이터 F3 34

[그림 2] 어셈블리어 데이터 타입별 메모리 저장 위치

 

2-3. 빅 엔디안 vs 리틀 엔디안

  • 메모리에 데이터를 저장하는 바이트 순서를 바이트 정렬이라 함

  • RISC 칩을 기반으로 한 IBM 컴퓨터 등은 빅 엔디안 방식 사용

  • 0x86, DEC 시스템 등은 리틀 엔디안 방식 사용

  • 빅 엔디안은 최상위 바이트(MSB)부터 차례로 저장하는 방식, 리틀 엔디안은 최하위 바이트(LSB)부터 차례로 저장하는 방식


(3) 어셈블리어 주소 지정 방식

  • 80x86 시스템에서는 메모리에 접근할 수 있도록 다양한 주소 지정 방식 제공

 

3-1. 레지스터 주소 지정

  • 일반적으로 생각하는 메모리에 접근하는 방식은 아님

  • 레지스터 주소 값을 직접 지정하여 복사하는 방식으로 처리 속도가 가장 빠름

 

다음 내용은 BX 레지스터 내용을 DX 레지스터로 복사하는 명령의 예이다.

MOV DX, BX

 

3-2. 직접 메모리 주소 지정

  • 가장 일반적인 주소 지정 방식

  • 피연산자 하나가 메모리 위치를 참조하고, 다른 하나는 레지스터를 참조

  • 두 피연산자가 메모리를 직접 참조하는 것은 MOVS와 CMPS만 가능

 

다음 내용은 메모리 주소를 레지스터에 복사하고 레지스터를 메모리에 저장하는 두 가지 명령의 예이다.

MOV AL, DS:[8088h]
MOV DS:[1234h], DL

 

예에서 DS:[8088h]와 DS:[1234h]는 각각 '세그먼트:오프셋' 형식으로 메모리에 직접 접근하는 방식이다.

 

[그림 3] 직접 메모리 주소 지정 예

 

위 그림과 같이 각각 메모리에 접근한다.

 

 

3-3. 레지스터 간접 주소 지정

  • 직접 메모리 주소 방식처럼 '세그먼트:오프셋' 형식 사용

  • 단지 세그먼트를 명시적으로 적지 않음

MOV AL, [BX]
MOV AL, [BP]

[BX]와 [BP]는 실제로는 DS:BX, SS:BP 주소를 가리킨다.

 

[그림 4] 레지스터 간접 주소 지정 예

 

 

그리고 다음과 같이 기본이 아닌 세그먼트를 강제로 지정할 수도 있다.

MOV AL, CS:[BX]
MOV AL, DS:[BP]

 

3-4. 인덱스 주소 지정

  • 레지스터 간접 지정 방식에 변위가 더해진 메모리 주소 지정 방식

 

다음은 20h만큼 더해 메모리를 참조한 명령의 예이다.

MOV AL, [BX+20h]
MOV AL, [BP+20h]

 

위 예에서 [BX+20h]와 [BP+20h]는 DS:[BX+20h], SS:[BP+20h] 주소를 가리킨다.

 

[그림 5] 인덱스 주소 지정 예

 

위의 예는 다음과 같이 바꾸어 표현할 수 있다.

MOV AL, 20h[BX]
MOV AL, 20h[BP]

 

 

3-5. 베이스 인덱스 주소 지정

  • 실제 주소를 생성하기 위해 베이스 레지스터(BX 또는 BP)와 인덱스 레지스터(DI 또는 SI)를 결합

 

다음 예처럼 베이스 레지스터(BX 또는 BP)와 인덱스 레지스터(DI 또는 SI)를 결합한다.

MOV AL, [BX+SI]
MOV AL, [BP+SI]

 

[그림 6] 베이스 인덱스 주소 지정 예

 

 

베이스 인덱스 주소 지정도 인덱스 주소 지정처럼 다음과 같이 바꾸어 표현이 가능하다.

MOV AL, [BX][SI]
MOV AL, [BP][SI]

 

베이스 인덱스 주소 지정은 보통 2차원 배열 주소를 지정할 때 사용한다.

 

 

 

3-6. 변위를 갖는 베이스 인덱스 주소 지정

  • 베이스-인덱스 변형으로 실제 주소를 생성하려고 베이스 레지스터, 인덱스 레지스터, 변위를 결합

 

다음과 같이 표현할 수 있다.

MOV AL, [BX+SI+20h]
MOV AL, [BP+SI+20h]

[그림 7] 변위를 갖는 베이스 인덱스 주소 지정 예

 

 

변위를 갖는 베이스 인덱스 주소 지정 방식도 인덱스 주소 지정 방식처럼 다음과 같이 바꾸어 표현 가능하다.

MOV AL, [BX][SI][20h]
MOV AL, [BP][SI][20h]

# Reference

 

https://www.hanbit.co.kr/store/books/look.php?p_code=B3283906872

[System] 80x86 시스템 메모리 구조와 동작

 

시스템 해킹


(1) 80x86 시스템 메모리의 구조와 동작

1-1. 메모리의 기본 구조

[그림 1] 80x86 시스템 메모리 구조

 

1-1-1. 스택 (Stack)

  • 후입선출(LIFO) 방식에 의해 정보를 관리하는 데이터 구조

  • Top이라 불리는 스택 끝부분에서 데이터 삽입과 삭제가 발생 (스텍에 데이터 삽입 > Top에 정보 위치)

  • 스택에서 정보를 읽어 오려고 하면 스택의 Top 위치에 있는 정보가 반환

  • 스택에서는 가장 나중에 삽입된 정보가 가장 먼저 읽히는 특징이 있음

 

컴퓨터 사전에서 정의한 스택은 데이터 구조론을 기반으로 한 정의이며, 컴퓨터 메모리에서도 기본 작동 방식은 같다.

 

단지 차이는 스택에 저장되고 사용 목적이 프로그램 실행에 있다는 것이다.

 

컴퓨터 메모리 상의 스택은 프로그램 함수 내부에서 정의, 함수 종료와 동시에 사라지는 자동 변수가 저장되고 함수를 호출할 때 함수 내부의 로컬 변수 등이 저장되는 곳이다.

 

함수를 실행하는 동안만 존재하며, 함수 실행을 종료하면 해당 변수들도 사라진다.

 

ESP 레지스터는 항상 스택의 가장 위(끝)을 가리킨다.

 

 

1-1-2. 힙 (Heap)

  • 프로그램을 실행할 때까지 가변적 양의 데이터를 저장하는 데 사용하는 메모리 영역

  • 프로그램 실행 중에 데이터 저장을 위해 기억 장소 요청 시, OS는 힙에 존재하는 기억 장소를 프로그램에 할당

  • 프로그램에서는 기억 장치가 더 이상 필요 없으면 할당 받았던 기억 장소를 OS에 반납하며, 이때 OS는 반납된 기억 장소를 다시 힙에 돌려줌

  • 힙에 대한 기억 장소는 포인터를 통해 동적 할당되거나 반환되며 연결 리스트, 트리, 그래프처럼 동적인 데이터 구조에서 널리 사용

  • 스택 영역은 LIFO 방식으로 운영, 힙은 프로그램들이 요구하는 블록 크기나 요구/횟수 순서에 일정한 규칙이 없음

  • 프로그램 실행 중 해당 힙이 없어지면 메모리 부족으로 이상 종료함

 

프로그램에서는 new나 malloc() 함수로 메모리를 동적 할당하여 힙 영역을 사용할 수 있다.

 

예를 들어 다음 코드 실행 시에는 힙 영역에 메모리 1,000 바이트 할당한다.

char * p = new char[1000];

 

 

1-1-3. BSS 세그먼트

static int a;
  • 초기화 되지 않은 데이터 세그먼트라고도 함

  • 프로그램 실행할 때 0이나 Null 포인터로 초기화되는 영역

  • 위 코드는 외부 변수나 static 변수 중 초기화가 되지 않은 변수들을 저장하는 영역을 의미 

 

 

1-1-4. 데이터 세그먼트

static int a = 1;
  • 초기화 된 데이터 세그먼트라고도 하며, 위 코드처럼 외부 변수나 static 변수 등을 저장하는 영역

  • 보통 텍스트 세그먼트와 데이터 세그먼트 영역을 합쳐 프로그램이라 함

 

 

1-1-5. 텍스트 세그먼트

  • CPU로 실행되는 머신 코드가 있는 영역

  • EIP가 다음에 실행하는 명령을 가리킴


(2) 메모리 접근 모드와 동작

  • 초기 8086 CPU를 사용한 IBM-PC는 등장 당시 메모리가 1MB였으며, 상당히 큰 편이었음

  • IBM은 프로그램이 앞의 640KB(0~0x9fff)만 사용할 수 있게 하고, 나머지 384KB(0xa000~0xffff)는 BIOS와 ISA 장치용으로 사용하게 했음

  • 요즘은 메모리가 1MB인 PC는 볼 수 없으며, 최소 1GB 이상이며, 4GB도 흔함

  • 메모리가 1MB에서 4GB 이상으로 커지면서 메모리에 접근하여 데이터를 저장하고 읽는 방법도 달라짐

 

2-1. 실제 모드

  • x86 계열로 처음 등장한 8086 CPU에서 사용하던 동작 모드

  • 20비트 주소 버스로 총 1MB(2**20 = 1,048,567) 메모리를 사용하였음

  • 16비트 레지스터로 20비트 주소 버스를 사용

  • 20비트 주소 표현을 위해 세그먼트 레지스터를 도입

  • 16비트 세그먼트 레지스터와 16비트 오프셋을 중첩시킨 20비트 물리 주소를 생성

[그림 2] 20비트 메모리 주소 구성 방법

 

  • 예로 세그먼트 주소인 CS 레지스터가 0x2525h이고 오프셋인 IP가 0x95F3h
  • 0x2525h 뒤에 한 자리의 0x0h를 붙여 95F3h를 더한 2E843h가 실제 가리키는 물리 주소가 됨
  • 이를 2525h : 95F3h 또는 [CS] : 96F3h로 표현

 

모든 메모리 접근에는 세그먼트와 오프셋이 함께 필요하다.

 

세그먼트 하나를 사용하면 64KB(2**16 = 65,536) 메모리 사용 가능하다. 

 

 

[표 1] 세그먼트 레지스터별 기본 오프셋 레지스터

세그먼트 레지스터 오프셋 레지스터
CS IP
DS SI, DI, BX
SS SP, BP
ES SI, DI, BS

 

각 세그먼트 레지스터마다 사용하는 오프셋 레지스터는 위 표와 같다.

 

실제 모드는 16비트 CPU 8086, 80286뿐만 아닌 80386 이상의 CPU에서도 지원한다.

 

모든 프로그램은 처음 시작할 때는 실제 모드에서 동작한다.

 

[그림 3] 20비트 메모리 주소 구성 예

 

2-2. 보호 모드

  • 32비트 주소 버스 사용

  • 4GB 메모리 사용 가능

  • 메모리 보호 기능 & 페이징 등으로 가상 메모리 효율적 구현 가능

  • 인터럽트 & 예외 처리 등 모두 보호 모드에서 지원하는 기능을 활용

  • 세그먼테이션과 페이징을 이용 > 메모리 관리

  • 세그먼테이션은 4GB 메모리를 세그먼트 단위로 쪼갠 것으로, 16비트 셀렉터와 32비트 오프셋을 이용해 4GB 범위 32비트 선형 주소를 생성하는 일을 함

 

[그림 3] 보호 모드에서 메모리 변환 과정

 

만들어진 선형 주소는 위 그림과 같이 메모리를 4KB 단위로 쪼개서 관리하는 페이징을 이용 > 물리 주소로 변환한다.


# Reference

 

https://www.hanbit.co.kr/store/books/look.php?p_code=B3283906872

[System] 80x86 시스템 CPU 구조와 레지스터

 

시스템 해킹


(1) 80x86 시스템 CPU 구조와 레지스터

1-1. 80x86 시스템

  • 8086/8088 시스템은 XT라고 칭했던 인텔 CPU의 IBM PC 중 아주 초기 보급형 모델

  • 그러다 AT라는 80286 시스템 발표, 이후부터 익숙한 이름의 모델이 등장

  • 바로 80을 떼고 80386을 386, 80486을 486으로 칭했던 시스템들이며 80x86은 이런 시스템을 통칭하는 말

[그림 1] 인텔 CPU 모델별 관련 정보

 

1-2. 80x86 시스템 CPU 구조

 

[그림 2] 80x86 시스템 구조

 

1-2-1. 연산 장치

  • 연산 장치(ALU)는 CPU(중앙 처리 장치) 핵심 부분 중 하나이며, 산술과 논리 연산을 수행하는 연산 회로 집합으로 구성

구성 요소 기능
내부 장치 가산기(Adder) 덧셈 연산 수행
보수기(Complementer) 뺄셈 연산 수행, 1의 보수나 2의 보수 방식 이용
시프터(Shifter) 비트를 오른쪽 / 왼쪽으로 이동하여 나눗셈, 곱셈 연산 수행
관련 레지스터 누산기(Accumulator) 연산의 중간 결과 저장

데이터 레지스터

(Data Register)

연산에 사용할 데이터 저장

          상태 레지스터           

(Status Register)

연산 실행 결과로 나타나는 양수나 음수, 자리 올림, 오버플로 상태 기억

 

1-2-2. 제어 장치

  • 제어 장치(CU)는 입출력, 기억 장치, 연산 장치를 제어하고 감시

  • 주기억 장치에 저장된 명령을 차례로 해독 > 연산 장치로 보내 처리하도록 지시

구성 요소 기능
내부 장치

명령 해독기

(Instruction Decoder)

명령 레지스터에 있는 명령 해독 > 부호기로 전송
부호기(Decoder) 명령 해독기가 전송한 명령 > 신호로 만들어 각 장치로 전송
주소 해독기(Address Decoder)

명령 레지스터에 있는 주소 해독 > 메모리 실제 주소로 변환

>  데이터 레지스터에 저장

관련 레지스터

프로그램 카운터

(Program Counter)

다음에 실행할 명령 주소를 저장

명령 레지스터

(Instruction Register)

현재 실행 중인 명령을 저장

메모리 주소 레지스터

(Memory Address Register)

주기억장치의 번지 저장

메모리 버퍼 레지스터

(Memory Buffer Register)

메모리 주소 레지스터에 저장된 주소 실제 내용 저장

 

1-3. 레지스터

  • 처리 중인 데이터나 처리 결과를 임시 보관하는 CPU 안의 기억장치

  • 대개 연산 장치나 제어 장치에 함께 포함

 

1-3-1. 레지스터 종류 & 기능

  • 사람이 일상 생활에서 메모하는 것처럼, 프로그램도 메모를 하는 데 이때 메모지 역할을 하는 것

  • 프로그램이 사용하는 메모지 종류와 내용을 알면 프로그램 동작 원리 이해에 도움

 

1-3-2. 범용 레지스터

범주 80386 레지스터 이름 비트 용도

범용 레지스터

(General Register)

EAX 누산기(Accumulator) 32

주로 산술 연산에 사용

(함수 결과 값 저장)

EBX

베이스 레지스터

(Base Register)

32

특정 주소 저장

(주소 지정 확대하는 인덱스로 사용)

ECX

카운트 레지스터

(Count Register)

32

반복적 실행되는 특정 명령에 사용

(루프 반복 횟수 & 좌우 방향 시프트 비트 수 기억)

EDX

데이터 레지스터

(Data Register)

32 일반 자료 저장(입출력 동작에 사용)

 

  • 연산 장치가 수행한 계산 결과의 임시 저장, 산술 및 논리 연산, 주소 색인 등 여러 목적으로 사용

  • 80386 CPU에서 사용하는 범용 레지스터는 EAX, EBX, ECX, EDX 등이 있음 

[그림 3] 범용 레지스터 종류 & 구분

 

  • 앞의 E는 '확장된'을 의미하며, 32비트 레지스터

  • 이 레지스터의 오른쪽 16비트를 각각 AX, BX, CX, DX라고 하며, 다시 둘로 나뉨

  • 예를 들어, AX는 왼쪽 8비트 상위 부분을 AH, 오른쪽 8비트 부분을 AL이라 함

 

EAX 레지스터

  • 누산기인 EAX 레지스터는 입출력과 대부분의 산술 연산에서 사용 (예 : 곱셈, 나눗셈, 변환 명령은 EAX 사용)

  • 사용 시에 더 효율적인 기계 코드를 생성하는 명령도 있으며, Win32 API 함수들은 모두 리턴 값을 EAX에 저장한 후에 리턴

 

EBX 레지스터

  • DS 세그먼트의 포인터를 주로 저장하며, ESI나 EDI와 결합하여 인덱스에 사용

  • BX는 메모리 주소 지정을 확장하기 위한 인덱스로 사용할 수 있는 유일한 범용 레지스터

 

ECX 레지스터

  • 루프가 반복되는 횟수를 제어하는 값, 왼쪽이나 오른쪽으로 이동되는 비트 수 등을 포함할 수 있음

 

EDX 레지스터

  • 입출력 연산에 사용하며, 큰 수의 곱셈과 나눗셈 연산에서 EAX와 함께 사용

 

 

1-3-3. 세그먼트 레지스터

범주 80386 레지스터 이름 비트 용도

세그먼트  레지스터

(Segment Register)

CS

코드 세그먼트 레지스터

(Code Segment Register)

16

실행할 기계 명령어가 저장된 메모리   주소 지정

DS

데이터 세그먼트 레지스터

(Data Segment Register)

16

프로그램에서 정의된 데이터, 상수,     작업 영역

메모리 주소 지정

SS

스택 세그먼트 레지스터

(Stack Segment Register)

16

프로그램 스택 세그먼트 시작 주소 저장

메모리 상에 스택 구현을 가능하게 함

ES, FS, GS

엑스트라 세그먼트 레지스터

(Extra Segment Register)

16 문자 연산과 추가 메모리를 지정하는 데 사용하는 여분의 레지스터

 

  • 세그먼트는 프로그램에 정의한 메모리 상의 특정 영역 (코드, 데이터, 스택 등을 포함)

  • 세그먼트는 메모리 대부분에 위치 가능, 실제 모드에서는 최대 64KB 크기까지 가능

  • 각 세그먼트의 주소를 지정하고, 특히 PC 계열에 사용하는 인텔 프로세서는 자신의 주소 지정 기능을 제공

  • 기본으로 CS, DS, SS 등 레지스터 세 개를 사용하며, ES나 FS, GS 레지스터는 여분으로 프로그램 크기나 필요에 따라 사용 가능

 

[그림 4] 세그먼트 레지스터 & 세그먼트 맵핑

 

CS 레지스터

  • 코드 세그먼트는 실행될 기계 명령을 포함

  • 코드 세그먼트의 시작 주소를 가리키며, 일반 프로그래밍에서는 이 레지스터를 직접 참조할 필요 X

 

DS 레지스터

  • 데이터 세그먼트는 프로그램에 정의된 데이터, 상수, 작업 영역을 포함

  • 데이터 세그먼트의 시작 주소를 가리키며, 프로그램은 참조하려는 데이터의 오프셋을 DS 레지스터에 저장된 주소 값에 더해 데이터 세그먼트 안의 데이터를 참조

 

SS 레지스터

  • 스택 세그먼트는 프로그램 실행 시, 실행 과정에서 필요 데이터나 연산 결과 등을 임시로 저장 / 삭제하는 목적 사용

  • 스택 세그먼트의 시작 주소를 가리킴

 

ES / FS / GS 레지스터

  • ES 레지스터는 추가로 사용된 데이터 세그먼트 주소를 가리킴

  • 메모리 주소 지정을 다루는 문자 데이터 연산에 사용하는 데, 이때 EDI 레지스터와 함께 사용

  • FS와 GS 레지스터도 목적은 비슷, 실제로는 거의 사용 X

 

 

2-3-4. 포인터 레지스터

범주 80386 레지스터 이름 비트 용도

포인터 레지스터

(Pointer Register)

EBP

베이스 포인터

(Base Pointer)

32

SS 레지스터와 함께 사용

스택 안의 변수 값을 읽는 데 사용

ESP

스택 포인터

(Stack Pointer)

32

SS 레지스터와 함께 사용

스택 가장 끝 주소를 가리킴

EIP

명령 포인터

(Instruction Pointer)

32

다음 명령어 오프셋(상대 위치 주소)을 저장

CS 레지스터와 합쳐 다음에 수행할 명령 주소 형성

 

  • 프로그램 실행 과정에서 사용하는 주요 메모리 주소 값을 저장

 

EBP 레지스터

  • 스택 세그먼트에서 현재 호출해서 사용하는 함수의 시작 주소 값 저장

  • 함수로 전달되는 지역 변수 등을 참조할 때 기준이 됨

  • ESP 레지스터와 함께 써서 스택 프레임을 형성하기도 함

  • 스택 프레임 기법은 함수가 호출될 때 ESP를 EBP에 저장하고 있다가 (mov %esp, %ebp) 모든 루틴이 끝나고 함수를 리턴하면 ESP 값을 돌려주어 스택 형성에 문제가 생기지 않도록 함

  • 실제 메모리 상 주소를 참조할 때 SS 레지스터와 함께 사용

 

ESP 레지스터

  • 현재 스택 영역에서 가장 하위 주소를 저장

  • 스택은 높은 주소 > 낮은 주소로 이동하면서 데이터를 저장하므로, 스택이 확장되면 스택 포인터도 높은 주소에서 낮은 주소로 값 변경

  • EBP와 마찬가지로 실제 메모리 상 주소를 참조할 때 SS 레지스터와 함께 사용

 

EIP 레지스터

  • 다음에 실행될 명령의 오프셋을 포함

  • 현재 실행 중인 코드 세그먼트에 속한 현재 명령을 가리킴

  • 실제 메모리 상 주소를 참조할 때 CS 레지스터와 함께 사용

 

 

1-3-5. 인덱스 레지스터

범주 80386 레지스터 이름 비트 용도

인덱스 레지스터

(Index Register)

EDI

목적지 인덱스

(Destination Index)

32 목적지 주소 값 저장
ESI

출발지 인덱스

(Source Index)

32 출발지 주소 값 저장

 

  • 데이터를 복사할 때 출발지와 목적지 주소를 각각 가리키는 레지스터로 사용

  • EDI, ESI가 있으며 오른쪽 16비트를 각각 DI, SI라고 함

 

 

ESI & EDI 레지스터

  • 주로 메모리의 한 영역(Source)에서 다른 영역(Destination)으로 데이터를 연속적으로 복사할 때 사용

  • 예로 strcpy(Destination, Source) 함수는 Source의 문자열을 Destination으로 복사할 때 두 메모리 주소를 저장하는 데 ESI와 EDI 레지스터를 사용

 

 

1-3-6. 플래그 레지스터

범주 80386 레지스터 이름 비트 용도
플래그 레지스터 EFLAGS

플래그 레지스터

(Flag Register)

32 연산 결과 및 시스템 상태와 관련된 여러 플래그 값 저장

 

[그림 5] EFLAGS 레지스터의 플래그 맵핑

 

  • 크기가 32비트이며, 컴퓨터의 다양한 상태를 나타내는 비트를 포함

  • 상태 플래그, 제어 플래그, 시스템 플래그로 구성됨

  • 위 그림에서 각 비트는 1(Set), 0(Clear) 값을 가지며, 비교 연산과 산술 연산을 포함하는 많은 명령이 플래그 상태를 변화시키고, 어떤 명령은 다음 행동을 결정하려고 플래그 상태를 점검함

 

 

상태 플래그 (State Flag)

  • 상태 플래그(0, 2, 4, 6, 7, 11비트)는 산술 명령(ADD, SUB, MUL, DIV) 결과를 반영

  • CF(Carry Flag / 비트 0) : 산술 연산 결과로 자리 올림이나 자리 내림이 발생할 때 세트된다. (STC, CLC 같은 어셈블리어 명령으로 값 수정 가능)

  • ZF(Zero Flag / 비트 6) : 산술 연산 결과가 0이면 세트(1), 0 이외에는 클리어(0)

  • OF(Overflow Flag / 비트 11) : 부호가 있는 수의 오버플로가 발생하거나 MSB(Most Significant Bit)를 변경했을 때 세트(1)

  • PF(Parity Flag / 비트 2) : 산술 연산 결과가 짝수이면 세트(1)

  • AF(Adjust Flag / 비트 4) : 8비트 피연산자를 사용한 산술 연산에서 비트 3을 비트 4로 자리올림하면 세트(1)

  • SF(Sign Flag / 비트 7) : 산술 및 논리 연산 결과가 음수이면 세트(1) 

 

제어 플래그 (Control Flag)

  • 제어 플래그인 DF(Direction Flag / 비트 10)는 스트링 명령(MOVS, CMPS, SCAS, LODS, STOS)을 제어

  • DF가 1이면 스트링 명령은 자동 감소함(스트링을 높은 주소에서 낮은 주소로 처리)

  • DF가 0이면 스트링 명령은 자동 증가(스트링을 낮은 주소에서 높은 주소로 처리)

  • STD / CLD 명령은 각각 DF 플래그가 세트(1)되고 클리어(0)됨

 

시스템 플래그 (System Flag)

  • 운영체제나 장치 드라이버를 제어

  • TF(Trap Flag / 비트 8) : 디버깅 할 때 'Single Step Mode'를 활성화하면 세트되고, 비활성화하면 클리어

  • IF(Interupt enable Flag / 비트 9) : 프로세서의 인터럽트 처리 여부를 제어하며, IF가 세트되어 있으면 시스템의 인터럽트를 처리하고 클리어 되어 있으면 시스템 인터럽트 무시

  • IOPL(I/O Privilege Level / 비트 12, 13) : 현재 실행하는 프로그램이나 태스크의 입출력 특권 레벨을 지시하며, 현재 실행 중인 프로그램이나 태스크가 I/O 주소 공간에 접근하려면 CPL이 I/O 특권 레벨보다 낮거나 같아야 함

  • NT(Nested Task Flag / 비트 14) : 인터럽트하거나 호출된 태스크를 제어하며, 현재 태스크를 이전에 실행된 태스크와 연결했으면 세트되고, 연결하지 않으면 클리어

  • RF(Resume Flag / 비트 16) : 프로세서 디버그 예외 반응을 제어하며, 세트되어 있으면 디버그 오류를 무시하고 다음 명령어 수행

  • VM(Virtual 8086 Mode Flag /비트 17) : V86 모드를 활성화하면 세트, 사용하지 않고 보호 모드로 리턴 시 클리어

  • AC(Alignment Check /비트 18) : 메모리 참조 시에 정렬 기능을 활성화하면 세트

  • VIF(Virtual Interrupt Flag / 비트 19), VIP(Virtual Interrupt Pending / 비트 20) : 가상 모드 확장과 관련해 사용

  • ID(IDentification / 비트 21) : CPUID 명령의 지원 유무 결정


# Reference

 

https://www.hanbit.co.kr/store/books/look.php?p_code=B3283906872

[System] 운영체제 이해

 

시스템 해킹


(1) 운영체제 개념

 

1-1. 운영체제

  • 사용자가 컴퓨터 시스템을 손쉽게 사용하도록 하고, 시스템 자원(기억 장치, CPU, 입출력 장치, 정보, 네트워크 등)을 효율적으로 관리할 수 있도록 하는 프로그램 집합

  • 프로그램의 프로세스 생성과 메모리 접근 등 서로 충돌 없이 요구를 잘 실행하도록 도와주는 역할 

 

[그림 1] 운영체제 개념

 

1-2. 운영체제 기능

  • 사용자 명령 인터페이스(UCI)를 중심으로 메모리 관리자, 프로세서 관리자, 장치 관리자, 파일 관리자 등 네 가지 서브 시스템 관리자로 기본 구성

[그림 2] 단일 사용자 운영체제 구성 모델

 

1-3. 사용자 명령 인터페이스 (User Command Interface)

  • 사용자와 시스템의 대화 수단

  • 많은 운영체제에서 GUI를 적용하기에 아이콘과 메뉴, 마우스라는 인터페이스를 이용, 시스템과 대화


(2) 서브시스템 관리자

2-1. 메모리 관리자

  • 프로그램이 메모리를 요청하면 적합성 점검 & 적합하다면 메모리 할당

  • 할당된 메모리를 다른 프로그램이 접근하지 못하게 관리 & 보호

  • 프로그램이 종료할 떄는 할당된 메모리 회수

 

2-2. 프로세서 관리자

  • 명령어들을 쳬계적이고 효율적으로 실행할 수 있도록 작업 스케줄링

  • 사용자의 작업 요청을 수용 & 거부

 

2-3. 장치 관리자

  • 프린터, 디스크 드라이버, 모뎀, 모니터 등 시스템 안의 모든 장치를 프로그램에 할당 & 회수

  • 이런 장치들은 흔히 입출력(Input/Output)장치라고 부름

 

2-4. 파일 관리자

  • 시스템 안의 데이터, 응용 프로그램 등 모든 파일에 사용자별로 파일 접근 권한 부여

  • 접근 권한에 따라 파일을 할당 & 해제

 

2-5. 네트워크 관리자

  • 네트워크에서 접근 가능한 CPU, 메모리, 프린터, 디스크 드라이버, 모뎀, 모니터 자원 관리


(3) 윈도우 역사

[그림 3] 윈도우 발전 과정


(4) 윈도우 구조

 

4-1. 커널(Kernel)

  • 운영체제 중심에 위치

  • 운영체제에서 어떤 작업을 시작하더라도 커널 동작으로 제어

  • 인터럽트 처리, 프로세스 관리, 메모리 관리, 파일 시스템 관리, 프로그래밍 인터페이스 제공 등 운영체제 기본 기능을 제공하는 핵심

 

4-1-1. 인터럽트

  • 작동 중인 컴퓨터에 예기치 않은 문제 발생 경우 CPU가 하드웨어적으로 상태를 체크하여 변화 대응

  • 발생 시, 운영체제 제어 프로그램에 있는 인터럽트 처리 루틴 작동하여 인터럽트를 해결하고, 인터럽트가 생기기 이전 상태로 복귀

 

4-1-2. 인터럽트 발생 원인

  • 갑작스런 정전

  • 기계적 문제 발생

  • 오퍼레이터나 타이머가 프로그램 의도적 중단

  • 입출력 종료나 입출력 오류로 CPU 기능 요청 시

  • 프로그램 실행 중 보호된 기억 공간 접근 & 불법적인 명령 수행으로 프로그램 문제 발생 시


(5) 윈도우 커널 구조

[그림 4] 윈도우 링 구조

  • 1. 하드웨어

  • 2. HAL (하드웨어 제어)

  • 3. 마이크로 커널

  • 4. 각종 관리자

  • 5. 응용 프로그램

 

[그림 5] 윈도우 시스템 구조

  • 하드웨어부터 각종 관리자까지 커널 모드로 구분하고, 응용 프로그램은 사용자 모드로 구분

  • 커널 모드는 기본적으로 사용자가 접근할 수 없는 영역, 프로그램을 실행하는 기본 관리 시스템이 위치

  • HAL은 하드웨어와 개발된 소프트웨어가 원활히 통신할 수 있도록 도와주는 번역자 역할

  • 마이크로 커널은 하드웨어와 하는 통신만 제어하는 최소한 커널(system32 폴더의 ntoskrnl.exe파일)


(6) 윈도우 관리자 역할

 

6-1. 입출력 관리자

  • 시스템 입출력 제어

  • 장치 드라이버 사이에서 메시지를 전달, 응용 프로그램이 하드웨어와 바로 통신할 수 있는 통로 제공

 

6-2. 개체 관리자

  • 파일, 포트, 프로세스, 스레드 등 모든 것을 개체로 정의

  • 이런 각 개체 정보를 제공

 

6-3. 보안 참조 관리자

  • 각 데이터나 시스템 자원의 제어를 허가 & 거부

  • 시스템 강제 보안 설정을 책임

 

6-4. 프로세스 관리자 

  • 스레드 생성 & 요청에 따라 처리

 

6-5. 로컬 프로시저 호출 관리자

  • 각 프로세스는 서로 메모리 공간을 침범하지 못해 프로세스 간 통신이 필요할 때 대신할 수 있는 장치

 

6-6. 가상 메모리 관리자 

  • 응용 프로그램의 요청에 따라 RAM 메모리 할당 & 가상 메모리 페이징 제어

 

6-7. 그래픽 장치 관리자

  • 화면에 선이나 곡선을 그리거나 폰트 등을 관리

 

6-8. 기타 관리자

  • 캐시 관리자, Plug and Play 관리자, 전원 관리자 등이 있음

 


(7) 서브 시스템

  • 윈도우에서 여러 응용 프로그램을 실행하는 컨테이너

  • 사용자가 로그인할 때 데이터를 보호하고, 운영체제가 이를 제어할 수 있도록 함

 

7-1. Win32

  • 기본 서브시스템으로 32비트 응용 프로그램이 동작할 수 있게 해준다.

  • 기본 윈도우 사용자 인터페이스 제공

  • 비디오 디스플레이, 키보드, 마우스 등을 지원

 

7-2. POSIX

  • 보안 서브 시스템과 유닉스 운영체제에 기반을 둔 일련의 표준 운영체제 인터페이스

 

7-3. 윈도우 리눅스 서브 시스템

  • 윈도우 10부터 도입된 특이한 서브 시스템

  • 윈도우에서 리눅스 운영체제를 설치해서 쓸 수 있게 하고, 리눅스 프로그램도 그 안에서 실행 가능


(8) 윈도우 파일 시스템

8-1. FAT

  • 기본적으로 2GB까지를 한 파티션으로 설정 가능

  • FAT 테이블 기본 크기는 16비트, 이는 하드 디스크에 파일을 담는 최소 단위인 클러스터가 32KB이기 때문

  • 전체 가능 용량은 2GB

 

8-2. FAT32

  • FAT와는 비교할 수 없을 만큼 용량이 커서 클러스터를 총 32비트개 가질 수 있음

  • 호환성이 좋아 리눅스나 다른 운영체제에 정보를 옮길 때 유용

  • 접근 제어를 설정할 수 없다는 문제점이 있음

 

8-3. NTFS

  • HPFS의 장점을 모아 만든 것

  • 현재 윈도우에 적용

  • 파일 시스템 결함을 관리하는 데 FAT나 FAT32보다 훨씬 좋은 성능을 보여줌

  • 보완 관점에서도 비교적 훌륭하며, 개별 폴더와 파일에 사용 권한 설정 가능

  • 각 파일과 폴더에 해당 계정만 접근하여 읽을 수 있게 암호화가 가능하며 폴더를 암호화하면 안에 있는 파일도 모두 암호화가 됨

  • 암호화된 폴더나 파일은 복사나 이동을 해도 암호화 속성을 잃지 않으며 감사 기능을 제공


(9) 윈도우 부팅 순서

9-1. POST 실행

  • 하드웨어 스스로 시스템에 문제가 없는지 기본 사항을 검사하는 과정

  • BIOS가 POST를 실행하고, 라우터나 스위치 등 장비에서도 처음 스위치를 켤 때 POST를 실행

  • POST 도중 하드웨어에서 문제 발견 시 여러 방법으로 알림

 

9-2. 기본 부팅 관련 설정 사항 로드

  • BIOS는 CMOS에 설정된 시스템 설정 사항 및 부팅과 관련된 여러 가지 정보를 읽어 시스템에 적용

 

9-3. MBR 로드

  • MBR은 저장 매체 첫 번째 섹터(LBA 0)에 위치하는 512바이트 영역

  • 부팅 매체의 기본 파일 시스템 정보가 들어 있음

  • 운영체제를 부팅할 때 저장 매체의 첫 번째 섹터를 호출하면 해당 부트 코드를 수행

  • 부트 코드의 주 역할은 파티션 테이블에서 부팅 가능한 파티션을 찾아 해당 파티션의 부트 섹터에 호출

  • 부팅 가능한 파티션이 없으면 오류 메시지를 출력

 

9-4. NTLDR 실행

  • NTLDR은 하드 디스크의 부팅 파티션에 있는 프로그램

  • 윈도우를 부팅할 수 있도록 간단한 파일 시스템을 실행

  • boot.ini 파일 내용을 읽어 가능한 부팅 옵션을 보여 줌

 

9-5. NTDETECT.com 실행

  • NTDETECT는 NTLDR에서 제어권을 위임받아 시스템에 설치 & 하드웨어 검사

  • PC의 CPU 유형 / 버스 유형 / 비디오 보드 유형 / 키보드와 마우스 종류 / 컴퓨터에 장착된 직렬 포트와 병렬 포트 / 플로피 드라이브

  • NTDETECT가 문제없이 작동 되면 레지스트리 하드웨어 키를 만들고, 이 키는 HKEY_LOCAL_MACHINE에 있음

  • 컴퓨터를 재부팅할 때마다 레지스트리의 해당 부분을 만들기에 항상 현재의 하드웨어 구성 반영

 

9-6. ntoskrnl.exe 실행

  • ntoskrnl은 HAL.DLL을 로드하며 네 가지가 있음

 

9-6-1. 커널 로드

  • 시스템 설정 로드

  • HKEY_LOCAL_MACHINE\System\Current Controlset\Services에 저장

  • 이 정보를 확인하여 로드할 드라이브와 그 순서를 결정

 

9-6-2. 커널 초기화

  • 드라이버에서 현재 제어 설정을 검사 & 작업 시작

 

9-6-3. 서비스 로드

  • 세션 관리자 서브시스템(smss.exe)과 Win32 서브시스템을 로드

 

9-6-4. 서브시스템 시작

  • 윈도우 서브 시스템을 초기화

  • Win32 서브시스템은 로그인을 처리하고 Winlogon.exe를 시작

  • 로그인 창을 활성화, 계정과 패스워드를 입력받아 로컬 보안 인증 서버(lsass.exe)에 보냄

  • 전달받은 로컬 보안 인증 서버는 보안 계정 관리자(SAM)에 저장된 정보와 비교하여 일치하면 Userinit.exe 프로세스가 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon의 셸 값에서 참조되는 셸을 실행


(10) 윈도우 비스타 이후 부팅 순서

1~3. POST 실행 및 기본 부팅 관련 설정 사항 로드, MBR 로드

 

4. 윈도우 부트 서브 시스템 실행

  • MBR에서는 NTLDR을 실행하지 않고 윈도우 부트 서브 시스템을 실행

  • 윈도우 부트 서브 시스템은 bootmgr.exe를 실행, 부트 설정 데이터를 읽어 실행 가능한 운영체제 목록을 보여줌

 

5. 윈도우 OS 로더(Winload.exe)실행

  • Winload는 NTDETECT처럼 각종 장치 드라이버를 로드하고 ntoskrnl.exe를 실행


(11) 리눅스 / 유닉스 역사

[그림 6] 리눅스 / 유닉스 시스템 발전 과정


(12) 리눅스 / 유닉스 구조

12-1. 모놀리식 커널

  • 커널이 모든 기능을 수행하도록 만들었으며, 안정적이지만 문제가 발생하면 부분 수정이 어려움

  • 일반 시스템보다 거대한 슈퍼컴퓨터에 많이 적용

 

12-2. 마이크로 커널

  • 최소한의 커널인 윈도우 마이크로 커널과 달리 모듈 여러 개가 모여 커널 하나를 이루는 개념

  • 개별 모듈의 업로드와 언로드가 가능

  • 각 모듈 권한이 동일하여 잘못된 모듈을 업로드하면 커널 전체가 망가질 수도 있음


(13) 유닉스 링 구조 

[그림 7] 유닉스 링 구조

  • 링 개수가 많을수록 보안 레벨은 높지만, 윈도우가 유닉스보다 보안 레벨이 높다고는 할 수 없음

  • 유닉스 링 구조가 윈도우보다 명확하게 구분되어 있어 링 개수는 적지만 일반적으로 유닉스가 조금 더 높은 보안 수준을 유지


(14) 유닉스 시스템 구조

[그림 8] 유닉스 시스템 구조

 

  • 유닉스 커널 구조는 크게 파일 서브시스템, 장치 드라이버, 프로세스 제어로 나뉨

 

14-1. 프로세스 제어

  • 전체 프로세스 간 통신과 스케줄링, 메모리 관리 구현

 

14-2. 장치 드라이버

  • 윈도우처럼 하드웨어와 소프트웨어를 연결하는 인터페이스 제공

 

14-3. 파일 서브시스템

  • 하드 디스크 같은 저장 공간에 유닉스 파일을 저장하고 있는 역할


(15) 셸

  • 커널과 함께 유닉스의 중요한 요소

  • 원도우는 GUI 환경이며, 명령 창 기능이 제한적이어서 모든 것을 실행할 수 없지만, 유닉스는 GUI 환경을 지원하면서 셸 기능도 막강함

  • 응용 프로그램에서 명령을 받아 커널에 전송하는 역할

  • 사용자 키보드 입력을 인식하고 해당 프로그램을 수행

 

15-1. 셸의 주요 기능

  • 자체 내장 명령어 제공

  • 입출력, 오류의 방향 변경

  • 와일드카드

  • 파이프라인

  • 조건부, 무조건부 명령 열 작성

  • 서브 셸 생성

  • 백그라운드 처리

  • 셸 스크립트(프로그램 작성)


(16) 리눅스 / 유닉스 파일 시스템

16-1. 일반 파일 

  • 일반적으로 생각하는 데이터 파일 / 실행 파일

  • 텍스트 파일, BMP 파일, EXE 파일 등 일반적인 파일

  • 반드시 디렉터리 하나에 포함되어야 함

 

16-2. 디렉터리

  • 유닉스에서는 디렉터리도 파일에 해당

  • 디렉터리가 담고 있는 여러 파일과 하위 디렉터리 정보가 담김

 

16-3. 특수 파일

  • 유닉스에서는 프린터, 터미널, 테이프 드라이버 같은 물리적인 장치를 특수 파일로 접근

  • /dev(device)에 있음

 

16-4. 파이프 파일

  • | 문자를 뜻함

  • 명령 두 개를 연결할 때 사용

  • 임시 파일을 생성했다가 명령 수행을 마치면 사라지는 것


(17) 유닉스 디렉터리 구조

 

[그림 9] 유닉스 디렉터리 구조

 

/bin

  • 기본적으로 실행 가능한 파일을 담고 있음

  • echo, mv, copy, pwd, who 등

 

 /etc

  • 시스템의 환경 설정 및 주요 설정 파일을 담고 있음

  • passwd, hosts, xined.conf 등

 

/tmp

  • 프로그램 실행 및 설치 시 생성하는 임시 파일을 담고 있음

  • 이 디렉터리에 파일 저장 시, 재부팅할 때 임의로 삭제될 수 있음

 

 /lib

  • 기본 프로그램의 모듈을 담고 있음

 

 /boot

  • 커널용 프로그램 파일을 담고 있음

  • 부팅할 때 읽어서 수행

 

 /dev

  • 프린터나 터미널 같은 물리적인 장치를 다루는 특수 파일을 담고 있음

 

/home

  • 각 사용자의 작업 디렉터리를 담고 있음

  • 각 계정으로 로그인할 때 이 디렉터리 아래에 있는 자신의 작업 디렉터리가 시작 디렉터리가 됨

 

 /usr

  • 사용자가 직접 쓰는 파일을 담고 있음

  • 다른 디렉터리에 있는 파일이 똑같이 위치할 때가 많은데, 이는 링크되어 있는 것

 

 /usr /lib

  • C언어나 포트란 라이브러리를 담고 있음

 

/usr /include

  • C언어에서 사용하는 헤더 파일을 담고 있음


(18) 리눅스 / 유닉스 부팅 순서

18-1. POST 실행

 

18-2. 기본 부팅 관련 설정 사항 로드

 

18-3. MBR(마스터 부트 레코드) 로드

 

18-4. 부트 로더 실행

  • 리눅스는 부트 로더로 LILO와 GRUB를 사용

  • LILO는 /etc/lilo.conf에 설정 사항을 저장

  • GRUB는 레드햇 7.x 버전부터 기본 부트 로더로 제공

  • 사용이 편리하고 윈도우 계열 외에 다른 OS와 멀티 부팅 가능

  • GRUB는 /etc/grub.conf에 설정 사항을 저장하며, 부트 로더를 실행하면 부팅하고자 하는 운영체제 커널 이미지가 메모리에 로드

 

18-5. 실행 레벨에 따른 서비스 실행

  • 부트 로더는 스와퍼라는 pid 0번 프로세스 실행하고, 스와퍼는 다시 pid 1번 init 프로세스를 실행

  • init 프로세스는 다시 /etc/inittab 파일을 읽음

  • inittab 파일은 부팅할 기본 모드를 선택하여 그에 따른 환경을 제공하는 분기점이라 할 수 있음

  • inittab 파일에서는 프로그램 종류에 따라 다른 수준의 실행 레벨을 부여하여 부팅에 필요한 프로그램들을 실행, 일곱 개가 기본

 

[표 1] 실행 레벨

실행 레벨 0 시스템 종료 시에 사용
실행 레벨 1 단일 사용자 모드, 기본적으로 관리자 권한 셸을 얻음, 데몬을 실행하지 않아 기능 제약
실행 레벨 2 NFS를 지원하지 않는 다중 사용자 모드
실행 레벨 3 일반 셸 기반의 인터페이스를 가진 다중 사용자 모드
실행 레벨 4 기본적으로 사용하지 않지만, 사용자가 임의로 정의하여 사용 가능
실행 레벨 5 기본은 실행 레벨 3과 같으나, GUI 환경 지원
실행 레벨 6 재부팅

# Reference

 

https://www.hanbit.co.kr/store/books/look.php?p_code=B3283906872

+ Recent posts