콜 게이트
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
콜 게이트는 GDT 또는 LDT에 있는 특권 장벽을 넘는 호출에 필요한 정보가 기재된 특별한 항목을 가리키는 선택자를 사용하여 작동하는 메커니즘이다. 사용자 프로그램은 `CALL FAR` 명령어를 사용하여 콜 게이트를 호출하며, 커널은 `RET FAR` 명령어를 사용하여 사용자 공간 프로그램으로 돌아갈 수 있다. 이러한 메커니즘은 OS가 메모리 보호를 수행하고, 사용자 애플리케이션에서 커널의 함수나 시스템 호출을 제어할 수 있게 한다. 콜 게이트는 멀틱스, OS/2, Windows 95 등에서 사용되었으며, 최근에는 SYSENTER/SYSEXIT 및 SYSCALL/SYSRET과 같은 시스템 호출 메커니즘으로 대체되는 추세이다. GDT가 적절하게 보호되지 않으면 보안 취약점이 발생할 수 있다.
더 읽어볼만한 페이지
- X86 아키텍처 - 물리 주소 확장
물리 주소 확장(PAE)은 x86 아키텍처에서 32비트 주소를 36비트 이상으로 확장하여 CPU가 4GB 초과 물리 메모리에 접근하도록 하는 기술로, 페이지 테이블 확장 및 추가 페이지 테이블을 통해 최대 64GB 메모리를 지원하며 AMD64 아키텍처에서 가상 주소 공간 확장에 사용되고 운영 체제, 칩셋, 마더보드의 지원이 필요하며 CPUID 플래그로 지원 여부를 확인한다. - X86 아키텍처 - X86 가상화
X86 가상화는 x86 아키텍처 기반 시스템에서 가상 머신을 구현하는 기술로, 소프트웨어 기반 가상화와 하드웨어 지원 가상화로 나뉘며, CPU 제조사의 가상화 확장 기술을 활용하여 가상 머신의 성능을 향상시킨다.
콜 게이트 | |
---|---|
개요 | |
종류 | 시스템 프로그래밍 메커니즘 |
아키텍처 | 인텔 x86 |
기능 | |
역할 | 특권 수준 변경 메커니즘 |
상세 정보 | |
설명 | 코드 세그먼트에 대한 특수한 유형의 세그먼트 디스크립터 호출 게이트를 통해 실행 흐름을 보안 방식으로 특권 수준이 낮은 코드에서 높은 코드로 변경 가능 |
작동 방식 | 특권 수준이 낮은 코드가 호출 게이트를 '호출'하면 CPU는 대상 코드 세그먼트의 특권 수준으로 전환 전환은 스택을 변경하고 접근 권한을 검사하는 것을 포함 |
사용 사례 | 커널 모듈 또는 기타 특권 코드에 대한 안전한 인터페이스를 제공하는 데 사용 운영 체제와 같은 시스템 소프트웨어에서 중요한 역할 |
보안 | 악성 코드가 시스템의 취약점을 악용하는 것을 방지하는 데 도움 |
기술적 특징 | |
대상 코드 세그먼트 | 특권 수준이 더 높은 코드 세그먼트 |
스택 변경 | 호출 게이트를 통해 전환할 때 스택이 변경될 수 있음 |
접근 권한 검사 | CPU는 호출 게이트를 통해 코드를 실행하기 전에 접근 권한을 검사 |
2. 작동 방식
콜 게이트는 GDT(Global Descriptor Table) 또는 LDT(Local Descriptor Table)에 있는 특수한 디스크립터를 참조하여 작동한다. 이 디스크립터는 권한 경계를 넘는 호출에 필요한 정보를 담고 있으며, 소프트웨어 인터럽트와 유사한 메커니즘을 사용한다.[2]
이는 사용자 애플리케이션이 커널 함수나 시스템 호출을 OS가 제어하는 방식으로 사용할 수 있게 하므로, 메모리 보호를 수행하는 현대 OS에 필수적이다.[2]
세그먼트 선택자와 32비트 콜 게이트 디스크립터 형식은 다음과 같다.
'''세그먼트 선택자 형식'''
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Selector Index | TI | RPL |
- Selector Index: 선택자 번호
- TI: Table Indicator (TI=0은 GDT, TI=1은 LDT)
- RPL: Requestor Privilege Level (이 세그먼트 선택자를 생성한 프로그램의 특권 레벨)
'''32비트 콜 게이트 디스크립터 형식'''
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
목적지의 오프셋(상위)[31:16] | |||||||||||||||
P | DPL | S=0 | TYPE=1100 | 0 | 0 | 0 | 파라미터 수 | ||||||||
목적지의 코드 세그먼트 선택자[15:2] | X | X | |||||||||||||
목적지의 오프셋(하위)[15:0] |
- P: Present 비트
- DPL: Descriptor Privilege Level (디스크립터 특권 레벨)
- S: 세그먼트 타입 (S=0은 시스템 세그먼트)
- TYPE: 1100은 32비트 콜 게이트
현재 특권 레벨(CPL)에서 RPL을 가진 코드 세그먼트 선택자를 사용하여 DPLG의 콜 게이트로, 목적지의 특권 레벨(DPLS)로 제어를 이행할 때 다음 조건이 만족되어야 한다.
2. 1. 호출 과정
콜 게이트는 권한이 낮은 코드가 더 높은 권한 수준의 코드를 호출할 수 있도록 설계되었다. 이러한 유형의 메커니즘은 메모리 보호를 사용하는 현대 운영 체제에서 필수적인데, 사용자 애플리케이션이 커널 기능과 시스템 호출을 운영 체제에서 제어할 수 있는 방식으로 사용할 수 있도록 하기 때문이다.사용자 프로그램에서 콜 게이트를 사용하여 커널의 기능을 이용하는 경우, `CALL FAR` (또는 `LCALL`) 명령에 호출하고 싶은 함수의 콜 게이트를 세그먼트 선택자에 지정하여 실행하기만 하면 된다 (오프셋 지정은 무시된다).[3] 콜 게이트 항목의 확인과 호출 권한 유무를 확인한 후, CS/EIP가 세그먼트 디스크립터에서 읽혀지고, 호출 측의 정보(SS, ESP, CS, EIP)가 새로운 스택에 쌓인다.[3] 필요한 인수는 호출 측(낮은 권한) 스택에서 호출된 측(높은 권한) 스택으로 복사된다.[3] 복사할 인수의 수는 콜 게이트의 세그먼트 디스크립터로 지정되어 있다.[3]
운영 체제 커널에 의해 콜 게이트가 이미 설정되었다고 가정하면, 코드는 필요한 세그먼트 선택자를 사용하여 `CALL FAR`을 수행한다 (오프셋 필드는 무시됨).[1] 프로세서는 진입점이 유효하고 코드가 게이트를 사용할 수 있는 충분한 권한으로 작동하는지 확인하기 위해 여러 가지 검사를 수행한다.[1] 모든 검사를 통과하면 새 CS/EIP가 세그먼트 디스크립터에서 로드되고, 이전 정보(SS, ESP, CS, EIP)가 새 권한 수준의 스택에 푸시된다.[1] 필요한 경우 매개변수도 이전 스택에서 새 스택으로 복사될 수 있다.[1] 복사할 매개변수 수는 콜 게이트 디스크립터에 있다.[1]
커널 프로그램에서는 `RET FAR`(`LRET`)에 의해 원래의 권한 레벨로 돌아간다.[4]
세그먼트 선택자의 형식은 다음과 같다.
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Selector Index | TI | RPL |
- Selector Index: 선택자의 번호
- TI: Table Indicator (TI=0은 GDT, TI=1은 LDT)
- RPL: Requestor Privilege Level (이 세그먼트 선택자를 생성한 프로그램의 특권 레벨)
32비트 콜 게이트 디스크립터의 형식은 다음과 같다.
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
목적지의 오프셋(상위)[31:16] | |||||||||||||||
P | DPL | S=0 | TYPE=1100 | 0 | 0 | 0 | 파라미터 수 | ||||||||
목적지의 코드 세그먼트 선택자[15:2] | X | X | |||||||||||||
목적지의 오프셋(하위)[15:0] |
- P: Present 비트
- DPL: Descriptor Privilege Level (디스크립터 특권 레벨)
- S: 세그먼트 타입 (S=0은 시스템 세그먼트)
- TYPE: 1100은 32비트 콜 게이트
현재의 특권 레벨(CPL: Current Privilege Level)에서 RPL을 가진 코드 세그먼트 선택자를 사용하여 DPLG의 콜 게이트로, 목적지의 특권 레벨(DPLS)로 제어 이행할 때의 조건은 다음과 같다.
2. 2. 복귀 과정
커널 프로그램은 `RET FAR` (또는 `LRET`) 명령어를 사용하여 사용자 공간 프로그램으로 돌아간다. 이 명령어는 스택에 저장된 연속 정보(호출 측의 SS, ESP, CS, EIP)를 꺼내어 이전 권한 레벨(외부 권한 수준)로 복귀한다.3. 콜 게이트 디스크립터 형식
콜 게이트는 사용자 애플리케이션에서 커널의 함수나 시스템 호출을 호출할 때, 운영체제(OS)가 이를 제어하여 메모리 보호를 수행하는 데 필수적인 메커니즘이다. 이는 상위 특권 레벨의 코드를 실행하기 위한 방법이다.
콜 게이트를 사용한 호출은 GDT 또는 LDT에 있는 정보를 이용하며, 소프트웨어 인터럽트와 유사한 메커니즘을 가진다. 사용자 프로그램에서 콜 게이트를 통해 커널 기능을 이용하려면, CALL FAR (LCALL) 명령에 호출하려는 함수의 콜 게이트를 세그먼트 선택자에 지정하면 된다. (오프셋 지정은 무시)
콜 게이트 항목과 호출 권한을 확인한 후, CS/EIP가 세그먼트 디스크립터에서 읽혀지고, 호출 측의 정보(SS, ESP, CS, EIP)는 새로운 스택에 순서대로 쌓인다. 필요한 인수는 호출 측(낮은 권한) 스택에서 호출된 측(높은 권한) 스택으로 복사되며, 복사할 인수의 수는 콜 게이트의 세그먼트 디스크립터에 지정되어 있다. 커널 프로그램에서는 RET FAR (LRET) 명령을 통해 원래 권한 레벨로 돌아간다.
3. 1. 필드 설명
콜 게이트는 다음과 같은 구조를 가진다.```cpp
typedef struct _CALL_GATE
{
USHORT OffsetLow; // 오프셋 하위 16비트
USHORT Selector; // 세그먼트 선택자
UCHAR NumberOfArguments:5; // 인수의 개수 (0-31)
UCHAR Reserved:3; // 예약됨
UCHAR Type:5; // 타입 (i386에서는 01100, i286에서는 00100)
UCHAR Dpl:2; // DPL (0-3)
UCHAR Present:1; // 존재 비트
USHORT OffsetHigh; // 오프셋 상위 16비트
} CALL_GATE, *PCALL_GATE;
```
32비트 콜 게이트 디스크립터는 다음과 같은 형식을 가진다.
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
목적지 오프셋(상위)[31:16] | |||||||||||||||
P | DPL | S=0 | TYPE=1100 | 0 | 0 | 0 | 파라미터 수 | ||||||||
목적지 코드 세그먼트 선택자[15:2] | X | X | |||||||||||||
목적지 오프셋(하위)[15:0] |
- P (Present): Present 비트 (1: 유효, 0: 무효)
- DPL (Descriptor Privilege Level): 디스크립터 특권 레벨 (0-3)
- S: 세그먼트 타입 (S=0은 시스템 세그먼트)
- TYPE: 1100은 32비트 콜 게이트를 나타낸다.
- 목적지 오프셋(상위)[31:16]: 목적지 코드의 오프셋 상위 16비트이다.
- 파라미터 수: 복사할 인수의 개수 (0-31)
- 목적지 코드 세그먼트 선택자[15:2]: 목적지 코드 세그먼트 선택자이다.
- 목적지 오프셋(하위)[15:0]: 목적지 코드의 오프셋 하위 16비트이다.
세그먼트 선택자의 형식은 다음과 같다.
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Selector Index | TI | RPL |
- Selector Index: 선택자의 번호
- TI (Table Indicator): TI=0은 GDT, TI=1은 LDT를 나타낸다.
- RPL (Requestor Privilege Level): 이 세그먼트 선택자를 생성한 프로그램의 특권 레벨
현재 특권 레벨(CPL: Current Privilege Level)에서 RPL을 가진 코드 세그먼트 선택자를 사용하여 DPLG의 콜 게이트로, 목적지의 특권 레벨(DPLS)로 제어 이행할 때의 조건은 다음과 같다.
- (1) DPLG >= CPL 및 DPLG >= RPL
- (2) CPL >= DPLS
3. 2. 세그먼트 선택자 형식
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Selector Index | TI | RPL |
- Selector Index: 선택자의 번호이다.
- TI (Table Indicator): TI=0은 GDT(전역 디스크립터 테이블), TI=1은 LDT(로컬 디스크립터 테이블)를 나타낸다.
- RPL (Requestor Privilege Level): 이 세그먼트 선택자를 생성한 프로그램의 특권 레벨이다.[1]
3. 3. 권한 검사 조건
현재 특권 레벨(CPL)에서 RPL을 가진 코드 세그먼트 선택자를 사용하여 DPLG의 콜 게이트로, 목적지의 특권 레벨(DPLS)로 제어 이행할 때 다음 조건들이 만족되어야 한다.:(1) DPLG ≥ CPL 및 DPLG ≥ RPL
:(2) CPL ≥ DPLS
4. 역사적 사용 예시
멀틱스(Multics)는 콜 게이트를 처음 사용한 운영체제이다. 허니웰 6180(Honeywell 6180)은 아키텍처의 일부로 콜 게이트를 가지고 있었다.[1]
OS/2는 링 3에서 실행되는 응용 프로그램 코드, 링 2에서 실행되는 권한 있는 코드, 링 0의 커널 코드 간의 전송을 위해 인텔 콜 게이트를 초기에 사용했다.[1]
Windows 95는 링 0에서 드라이버와 프로세스 전환을 실행하며, kernel32.dll 및 krnl386.exe와 같은 API DLL을 포함한 응용 프로그램은 링 3에서 실행된다. 드라이버 VWIN32.VXD는 링 0에서 주요 운영 체제 기본 요소를 제공한다. 이것은 16비트 응용 프로그램(MSDOS 및 Win16)에서 드라이버 함수를 호출할 수 있게 한다. 이 주소는 AX 레지스터에 1684h를 넣고 INT 2Fh를 호출하여 얻는다. 어떤 VxD에 대한 진입점을 요청하는지 식별하기 위해 BX 레지스터가 16비트 VxD ID로 설정된다. INT 명령에서 반환되면 ES.DI 레지스터는 링 0에서 실행되는 VxD로 제어를 전송하기 위해 호출할 수 있는 far 포인터를 포함한다. ES가 가리키는 디스크립터는 실제로 콜 게이트이다.[1] 그러나 32비트 응용 프로그램은 Windows 95 드라이버 코드에 액세스해야 할 때 KERNEL32.DLL의 문서화되지 않은 VxDCall 함수를 호출하여 본질적으로 링 모드를 변경하는 INT 30h를 호출한다.[1]
5. 현대적 사용 및 대안
최근 x86 운영 체제는 콜 게이트 대신 더 빠르고 효율적인 시스템 호출 메커니즘을 사용하는 추세이다. 인텔의 SYSENTER/SYSEXIT 및 AMD의 SYSCALL/SYSRET과 같은 x86 명령어는 시스템 호출을 위한 더 빠른 제어 전송 메커니즘을 제공한다.[4] 콜 게이트는 SYSENTER/SYSEXIT 및 SYSCALL/SYSRET보다 유연하여 임의의 권한 레벨에서 더 높거나 같은 권한 레벨로 변경할 수 있지만, 대부분의 다른 아키텍처에서는 지원되지 않아 이식성 문제가 있다.[4] 빠른 SYS* 명령어는 보호 링 3에서 0으로 또는 그 반대로만 제어 전송을 허용한다.[4]
콜 게이트는 다른 아키텍처에서 지원되지 않기 때문에, 많은 커널이 이식성 문제로 소프트웨어 인터럽트를 사용했다. 솔라리스(Solaris)/x86은 콜 게이트를 사용한 예시 중 하나이다.[4]
6. 보안 문제
시스템 보안을 유지하기 위해 전역 서술자 테이블(Global Descriptor Table, GDT)은 보호된 메모리에 보관되어야 한다. 그렇지 않으면 모든 프로그램이 자체적인 콜 게이트(Call Gate)를 생성하여 권한 수준을 높이는 데 사용할 수 있기 때문이다. 콜 게이트는 이러한 보호 기능을 우회하는 방법이 발견되었을 때 보안 익스플로잇에 사용되어 왔다.[2]
GDT가 있는 메모리 영역이 적절하게 보호되지 않으면, 사용자 프로그램에서 콜 게이트를 설정하여 임의의 코드를 특권 레벨 0으로 실행할 수 있다는 보안 결함으로 악용될 수 있다. 2006년에 나타난 마이크로소프트 윈도우의 이메일 웜 '''Gurong.A'''는 \Device\PhysicalMemory를 통해 GDT를 조작하고 콜 게이트를 생성하여 권한 상승을 수행했다.[3]
참조
[1]
서적
Windows 95 System Programming Secrets
[2]
블로그
The Intel SYSRET privilege escalation
https://blog.xenproj[...]
[3]
보고서
Worm:W32/Gurong.A Description
https://www.f-secure[...]
F-Secure Labs
[4]
서적
Understanding the Linux Kernel
O'Reilly Media, Inc.
2006
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com