Windows에서 관리자 권한은 한때 공격자의 「목표」였습니다. 관리자로 커널 드라이버를 로드하고, LSASS 프로세스의 메모리를 덤프하면, 암호 해시와 Kerberos 티켓을 얻습니다. 그다음은 훔친 해시로 다른 머신으로 걸어가는 일뿐입니다.
Credential Guard가 도는 현행 Windows 11에서는──22H2 이후, Enterprise·Education 같은 라이선스 요건과 하드웨어 요건을 충족하는 장치에서 기본 상태──그 수법은 통하지 않습니다. 커널을 완전히 장악한 공격자가 메모리를 아무리 뒤져도, 보호된 도메인 자격 증명의 실제 해시는 「그 OS 안」에서 나오지 않습니다. 돌고 있지 않으면 옛 위험은 남으므로, 글 뒤의 확인 방법과 함께 읽으십시오.
그렇다면 어디에 있을까요? 답은 「같은 PC 안에 만들어진 다른 세계」입니다. 제1회에서 보았듯이, 호스트 Windows는 하이퍼바이저 위 루트 파티션에서 움직입니다(「당신의 Windows는 어디서 움직이고 있는가」). 이 글은 그다음을 이어, 하이퍼바이저가 같은 파티션 안에 긋는 경계선 하나를 더 따라갑니다.
제2회가 답하는 질문은 하나뿐입니다.
관리자도 커널도 읽을 수 없는 비밀을 Windows는 어디에 두는가?
대상 독자는 설정 화면이나 장애 사례에서 핵심 격리, 메모리 무결성, Credential Guard 같은 말을 보고, 실체를 구조부터 이해하고 싶은 개발자와 운용자입니다. 전제 환경은 x64 Windows 10/11 또는 현행 Windows Server입니다(제1회와 같이 링과 SLAT 논의는 x64를 가정합니다. Arm64는 예외 수준 등 다른 장치를 씁니다). 필요한 배경은 제1회에서 다룬 파티션과 SLAT의 개념입니다. 난이도는 중급입니다. 목표는 구조의 해설이며, 보안 기능의 설정 하우투가 아닙니다.
1. 먼저 결론
Windows는 VTL(Virtual Trust Level)이라는 특권 축을 더하고, 비밀을 VTL1에 두었습니다. VTL1의 메모리는 VTL0에서 도는 일반 커널에서 읽을 수 없습니다. 경계를 지키는 것은 커널 자신이 아니라, SLAT 변환 테이블을 쥐고 있는 하이퍼바이저입니다.
그게 가상화 기반 보안(VBS)의 골격입니다. VBS는 하이퍼바이저로 격리 환경을 만들고 보안 기능을 그곳에 둡니다. 커널이 침해되어도 격리 환경은 보호된 채로 남는다는 가정을 두고 설계되어 있습니다.1
flowchart TB
accTitle: VBS가 만드는 두 세계
accDescr: VTL0과 VTL1은 같은 파티션 안에 앉는다. VTL0은 일반 커널과 앱을, VTL1은 Secure Kernel과 격리된 보안 기능을 갖고, 하이퍼바이저가 경계를 지킨다
subgraph vtl0 ["VTL0(일반 세계)"]
apps["앱(링 3)"]
ntk["NT 커널과 드라이버(링 0)"]
end
subgraph vtl1 ["VTL1(격리된 세계)"]
ium["격리된 보안 기능"]
sk["Secure Kernel"]
end
hv["하이퍼바이저(SLAT로 경계를 강제)"] --- vtl0
hv --- vtl1
ntk -.->|읽을 수 없음| ium
그림 1: 하나의 Windows 안에 세계가 둘 있고, VTL0 커널은 VTL1 메모리에 접근할 수 없다.
중요한 점은, 이게 「다른 VM을 세우는」일이 아니라는 것입니다. VTL0과 VTL1은 같은 파티션 안, 같은 Windows 안에 있습니다. 이 분할이 어떻게 실현되는지를 차례로 봅니다.
2. 링 모델의 한계 ── 지키는 쪽과 지켜지는 쪽이 같은 높이에 있다
전통적인 Windows 보안은 링(특권 수준)의 사다리 위에 세워졌습니다. 사용자 모드(링 3)는 커널 모드(링 0)가 지킵니다. 그렇다면 링 0을 지키는 사람은──아무도 없습니다. 링 0이 최고 특권입니다.
이 구조에는 두 가지 구조적 약점이 있습니다.
- 커널은 하나의 덩어리가 아닙니다. 링 0에서는 Windows 자신뿐 아니라 수많은 타사 드라이버가 돕니다. 그중 하나에 취약점이 있으면, 공격자는 링 0에서 코드를 실행합니다.
- 링 0에서는 모든 것이 보입니다. LSASS 같은 사용자 모드 프로세스가 아무리 방어해도, 커널을 장악한 공격자에게 그 메모리는 자유롭게 읽을 수 있습니다. 보호 속성과 페이지 테이블도 커널 자신이 관리합니다.
flowchart TB
accTitle: 전통적인 링 모델에서의 자격 증명 탈취 경로
accDescr: 취약한 드라이버를 통해 링 0을 장악한 공격자는 커널의 전권으로 LSASS 프로세스 메모리를 읽고 암호 해시를 얻는다
mal["공격자 코드"] -->|취약한 드라이버를 악용| r0["링 0을 장악"]
r0 --> readall["모든 물리 메모리를 읽을 수 있다"]
readall --> lsass["LSASS 메모리에서 해시를 얻는다"]
lsass --> lateral["다른 머신으로의 횡적 이동에 악용"]
그림 2: 지키는 쪽(커널)과 지켜지는 쪽(비밀)이 같은 높이에 있으므로, 링 0이 무너지면 모든 것이 무너진다는 것이 근본 약점이다.
그렇다면 필요한 것은 「링 0보다 높은 자리」입니다. 그 자리는 제1회에 이미 나왔습니다. 하이퍼바이저는 커널보다 높은 특권에서 돌고, CPU의 메모리 접근 권한(SLAT)의 제어를 일찍 독점합니다. 하이퍼바이저가 지키는 격리 영역은 링 0(슈퍼바이저 모드) OS 소프트웨어의 접근에서도 보호됩니다.2
3. VSM과 VTL ── 특권 축을 하나 더
3.1. Virtual Trust Levels (VTL)
이 격리를 제공하는 하이퍼바이저 기능의 무리를 VSM(Virtual Secure Mode)이라고 합니다. VSM은 Device Guard, Credential Guard, 가상 TPM 등의 기반입니다.2
VSM의 중심 개념은 VTL(Virtual Trust Level)입니다. 요점은 다음과 같습니다.2
- VTL은 계층적이며, 숫자가 클수록 특권이 높습니다. VTL0이 가장 낮고, VTL1은 VTL0보다 특권이 높습니다.
- 아키텍처상 최대 16단계가 정의되어 있지만, 현재 구현된 것은 VTL0과 VTL1의 둘입니다.
- 각 VTL은 독립된 메모리 접근 보호를 가집니다. 이 보호는 하이퍼바이저가 파티션의 물리 주소 공간에 대해 관리하므로, 파티션 안의 시스템 소프트웨어는 이를 바꿀 수 없습니다.
- 가상 프로세서는 VTL마다 별도의 레지스터 상태와 인터럽트 장치를 가지며, 낮은 VTL은 높은 VTL의 상태를 엿볼 수 없습니다.
flowchart TB
accTitle: VTL 격리를 이루는 세 가지 독립
accDescr: 메모리 접근 보호, 가상 프로세서 레지스터 상태, 인터럽트 장치는 VTL마다 독립이며, 낮은 VTL은 높은 VTL의 어느 것도 만질 수 없다
vtl["VTL마다 독립인 것"] --> m1["메모리 접근 보호"]
vtl --> m2["가상 프로세서 레지스터 상태"]
vtl --> m3["인터럽트 장치"]
m1 -.-> rule["낮은 VTL은 높은 VTL을 만질 수 없다"]
m2 -.-> rule
m3 -.-> rule
그림 3: 메모리뿐 아니라 CPU 상태와 인터럽트까지 별세계로 만드는 것이, 엿볼 구멍을 남기지 않는 세 가지 세트다.
링(0과 3)이 「OS와 앱」을 나누는 축이라면, VTL은 「일반 세계와 격리된 세계」를 나누는 두 번째 축입니다. 두 축은 직교하며, VTL1 안에도 커널 모드와 사용자 모드가 있습니다.
flowchart TB
accTitle: 링과 VTL의 두 축이 만드는 네 영역
accDescr: 링 축은 커널 모드와 사용자 모드를, VTL 축은 일반 세계와 격리된 세계를 나누고, 조합하면 일반 앱, NT 커널, IUM 트러스틀릿, Secure Kernel의 네 영역이 된다
subgraph ax0 ["VTL0(일반 세계)"]
a0["링 3: 일반 앱"]
k0["링 0: NT 커널과 드라이버"]
end
subgraph ax1 ["VTL1(격리된 세계)"]
a1["링 3: IUM(트러스틀릿)"]
k1["링 0: Secure Kernel"]
end
a0 --- k0
a1 --- k1
k0 ~~~ a1
그림 4: 이제 특권의 축이 둘이고, 「커널인가?」와 「격리된 세계인가?」는 별개의 질문이 되었다.
3.2. 경계의 실체는 SLAT
제1회에서, 게스트 물리 주소(GPA)를 실제 RAM(SPA)에 대응시키는 두 번째 변환 테이블──SLAT──을 하이퍼바이저가 쥐고 있다고 말했습니다. VSM은 바로 이 성질을 씁니다. VTL 격리는 Hyper-V 하이퍼바이저와 SLAT를 써서 만들어집니다.3
VTL1이 「이 메모리는 VTL0에 보여 주지 않는다」고 선언하면, 하이퍼바이저는 VTL0의 변환 테이블에서 그 페이지에 대한 접근 권한을 내립니다. 이후 VTL0 커널이 그 주소를 만지려 해도, CPU의 주소 변환 단계에서 거절됩니다. 커널이 자신의 페이지 테이블을 아무리 다시 써도 소용없습니다. 페이지 테이블(GVA→GPA)은 커널의 것일 수 있지만, 그 너머의 변환(GPA→SPA)과 최종 접근 권한은 하이퍼바이저의 것입니다.
flowchart TB
accTitle: VTL0에서 VTL1 메모리로의 접근이 거절되는 흐름
accDescr: VTL0 커널이 VTL1 메모리를 읽으려 하면 자신의 페이지 테이블은 통과할 수 있지만 SLAT 접근 보호에서 거절되고, 제어는 하이퍼바이저로 넘어간다
try["VTL0 커널이 VTL1 페이지를 읽으려 함"] --> pt["커널 자신의 페이지 테이블은 통과"]
pt --> slat{"SLAT 접근 보호가 허용하는가?"}
slat -->|허용하지 않음| deny["하이퍼바이저가 개입해 접근을 거절"]
slat -->|허용| ok["평범한 메모리 접근"]
deny -.-> point["커널이 바꿀 수 없는 층에서 보호"]
그림 5: 장벽은 커널 밖에 있고, SLAT 보호는 파티션 안의 소프트웨어가 바꿀 수 없다.
메모리 연재 제1회에서는 「VAD, PTE, 보호 속성이 접근 허용 여부를 정한다」고 썼습니다. VBS 환경에서는 그것들을 모두 통과한 뒤에도 SLAT 검문소가 기다리고 있다고 정리할 수 있습니다.
3.3. Secure Kernel과 IUM
VTL1 안에서 도는 것은 일반 NT 커널이 아니라, Secure Kernel이라는 작은 커널입니다. VTL1의 사용자 모드는 IUM(Isolated User Mode)이라고 하고, 거기서 도는 프로그램을 트러스틀릿(신뢰된 프로세스)이라고 합니다.3
트러스틀릿은 일반 프로세스처럼 모든 일을 할 수 없습니다. 대부분의 시스템 호출은 VTL0 측 NT 커널로 마샬링되어 작업을 요청합니다.3 VTL1은 「무엇이든 할 수 있는 상위 세계」가 아니라, 비밀을 담는 금고로서 의도적으로 작게 만들어져 있습니다. 금고에 가져올 수 있는 코드가 적을수록 공격면은 작아집니다.
flowchart TB
accTitle: 트러스틀릿의 시스템 호출 흐름
accDescr: VTL1의 트러스틀릿은 대부분의 시스템 호출을 스스로 처리하지 않고 VTL0 NT 커널로 마샬링해 결과만 받으므로, VTL1은 작게 유지된다
tl["트러스틀릿(VTL1의 IUM)"] --> sc{"시스템 호출이 필요"}
sc -->|대부분의 경우| mar["요청을 VTL0 NT 커널로 마샬링"]
mar --> res["결과만 돌아온다"]
res -.-> small["VTL1이 작아져 공격면이 줄어든다"]
그림 6: 금고에는 자체 설비가 없고, 잡일은 바깥에 맡긴 채 비밀만 계속 지킨다.
4. HVCI ── 커널 코드 무결성을 금고에서 검증한다
4.1. 무엇을 검증하는가
VBS 위에 앉는 첫 대표 기능이 메모리 무결성──HVCI(hypervisor-protected code integrity)입니다. Windows에는 커널 모드 드라이버와 바이너리를 시작 전에 검사하고, 서명되지 않았거나 신뢰할 수 없는 것은 로드하지 않는 코드 무결성 장치가 있습니다. HVCI는 이 검증을 VBS의 격리 환경 안에서 돌립니다.1
검증 논리 자체를 VTL1로 옮기는 이유는 바로 2장의 약점입니다. 검증 코드가 VTL0 커널 안에 있으면, 커널을 장악한 공격자가 검증을 바꿔 치울 수 있습니다. VTL1에 있으면 바꿔 치우는 손이 닿지 않습니다.
flowchart TB
accTitle: 검증 코드가 사는 자리에 따른 차이
accDescr: 검증 코드가 VTL0 커널 안에 있으면 커널을 장악해 무력화할 수 있지만, VTL1에 있으면 커널을 장악한 공격자도 손이 닿지 않아 검증이 보호된다
atk["커널을 장악한 공격자"] --> q{"코드 무결성 검증은 어디에 있는가?"}
q -->|"VTL0 커널 안(고전)"| bad["검증 논리를 바꿔 치울 수 있다"]
q -->|"VTL1의 격리 환경(HVCI)"| good["바꿔 치우기가 손이 닿지 않는다"]
bad --> res1["서명되지 않은 코드가 커널에서 돌 수 있다"]
good --> res2["커널이 침해된 뒤에도 검증은 계속 동작한다"]
그림 7: 검문소를 뚫릴 수 있는 쪽 안에 두지 않는 것──그 검증 논리의 이전이 HVCI의 본질이다.
4.2. 실행 가능 페이지의 규칙
HVCI의 효과는 「시작 시의 검사」에 그치지 않습니다. 커널 메모리 할당도 제약합니다.4
- 커널 페이지는 코드 무결성 검증을 통과한 뒤에야 실행 가능해집니다.
- 실행 가능한 페이지는 쓰기 가능해지지 않습니다(이른바 W^X).
이 둘이 있으면, 버퍼 오버플로 같은 취약점으로 커널 메모리를 다시 쓸 수 있어도, 다시 쓴 내용을 실행에 넣을 수 없습니다. 실행 가능한 페이지는 다시 쓸 수 없고, 다시 쓸 수 있는 페이지는 실행할 수 없습니다.4 실행 권한의 최종 뒷받침은 SLAT 측의 실행 권리이며, VTL0 커널은 이를 조작할 수 없습니다.
flowchart TB
accTitle: HVCI 환경에서 커널 페이지가 실행 가능해지기까지
accDescr: 드라이버 로드 요청은 VBS의 격리 환경에서 코드 무결성 검증을 받고, 통과하면 실행 가능·쓰기 불가 페이지로 허용되며, 실패하면 차단되어 CodeIntegrity 로그에 기록된다
load["커널 코드를 로드·실행하라는 요청"] --> verify{"격리 환경의 코드 무결성 검증"}
verify -->|통과| exec["실행 가능 페이지로 허용(쓰기 금지)"]
verify -->|실패| block["로드가 차단된다"]
block --> log["CodeIntegrity Operational 로그에 기록(이벤트 ID 3087)"]
exec -.-> wx["쓰기 가능 페이지는 실행 불가로 남는다"]
그림 8: 실행과 쓰기를 공존시키지 않는 규칙의 검증은 VTL1 측에서 이루어지며, VTL0 커널은 이를 뒤집을 수 없다.
공격자의 시점에서 추적하면, 규칙이 어떻게 효력을 내는지가 분명해집니다.
flowchart TB
accTitle: HVCI 환경에서 코드 주입이 실패하는 흐름
accDescr: 취약점으로 커널 메모리를 다시 쓸 수 있어도, 쓸 수 있었던 페이지는 실행 가능하지 않고, 실행 가능한 페이지는 애초에 다시 쓸 수 없으므로, 주입한 코드를 실행에 넣을 수 없다
inj["취약점으로 커널 메모리를 변조하려 함"] --> which{"대상은 어느 페이지인가?"}
which -->|쓰기 가능 페이지| wok["쓰기는 성공한다"]
which -->|실행 가능 페이지| xfail["쓰기 자체가 불가능하다"]
wok --> nx["하지만 그 페이지는 실행 가능하지 않다"]
nx --> dead["주입한 코드를 실행할 수 없다"]
xfail --> dead
그림 9: 쓰기 가능 페이지와 실행 가능 페이지를 교차시키지 않는다는 의미는, 어느 입구로 들어가도 막다른 길에 닿는다는 것이다.
4.3. 드라이버 호환성의 대가
이 규칙은 예전 설계의 드라이버와 충돌합니다. 실행 중에 자신의 코드를 다시 쓰거나, 서명이 없거나, 실행 가능하면서 쓰기 가능한 메모리를 요구하는──그런 드라이버는 HVCI 환경에서 로드할 수 없습니다. 차단의 사실은 이벤트 뷰어의 Applications and Services Logs\Microsoft\Windows\CodeIntegrity\Operational에서 확인할 수 있습니다(이벤트 ID 3087이 대표적입니다).5
「메모리 무결성을 켠 뒤 주변 기기가 멈췄다」──많은 경우, 그게 장애의 진짜 정체입니다. 올바른 대응은 HVCI 호환 드라이버로 업데이트하는 것이고, 메모리 무결성을 끄는 일은 보호를 통째로 포기하는 최후의 수단으로 생각해야 합니다. 이 검증을 드라이버 개발 관점에서 본다면, 필터 드라이버 기사(「Windows 미니필터 드라이버」)도 보십시오.
flowchart TB
accTitle: 메모리 무결성 아래 주변 기기가 멈추는 사례를 가르기
accDescr: CodeIntegrity Operational 로그에서 차단된 드라이버를 식별한다. 올바른 대응은 HVCI 호환 버전으로 업데이트하는 것이고, 없으면 벤더에 요청하며, 해제는 영구 설정으로 만들지 않는 최후의 수단으로 둔다
sym["메모리 무결성을 켠 뒤 장치가 멈춤"] --> log2["CodeIntegrity 로그에서 차단된 드라이버를 식별"]
log2 --> upd{"HVCI 호환 드라이버가 있는가?"}
upd -->|예| fix2["업데이트하고 HVCI를 켠 채로 해결"]
upd -->|아니오| ask2["벤더에 호환 버전을 요청"]
ask2 -.-> temp["해제는 최후의 수단이며 영구 설정이 아님"]
그림 10: 먼저 볼 것은 설정 화면이 아니라 로그이며, 이벤트 ID 3087이 누가 로드를 막았는지 알고 있다.
5. Credential Guard ── 해시는 LSAIso 안에 있다
5.1. LSASS와 LSAIso
VBS 위에 앉는 두 번째 대표 기능이, 서두의 수수께끼에 대한 답인 Credential Guard입니다.
전통적인 Windows는 NTLM 해시와 Kerberos 티켓을 LSA 프로세스(lsass.exe)의 메모리에 두었습니다. Credential Guard를 켜면, 이 중 보호 대상 비밀──도메인 자격 증명의 NTLM 해시와 Kerberos TGT(Ticket Granting Ticket)──의 저장이 VTL1의 IUM에서 도는 트러스틀릿인 LSAIso.exe로 옮겨집니다.6
- lsass.exe(VTL0)는 예전처럼 인증 처리의 창구로 계속 돕니다.
- 실제 비밀은 LSAIso.exe(VTL1)가 쥐고, VTL0에서는 접근할 수 없습니다.
- 둘은 RPC(Remote Procedure Call)로 통신합니다.
- LSAIso는 디바이스 드라이버를 전혀 호스트하지 않고, 서명된 최소 바이너리만 담습니다. 서명은 VBS가 신뢰하는 인증서로 검증됩니다.6
flowchart TB
accTitle: Credential Guard가 켜졌을 때 자격 증명이 앉는 자리
accDescr: VTL0의 lsass는 인증 창구로서 RPC로 VTL1의 LSAIso와 통신한다. 보호된 도메인 자격 증명의 실제 해시와 TGT는 LSAIso가 쥐므로, VTL0에서 관리자 권한을 얻어 lsass를 덤프해도 보호된 실체는 나오지 않는다
subgraph v0 ["VTL0"]
lsassP["lsass.exe(인증 창구)"]
att["공격자(관리자 권한)"]
end
subgraph v1 ["VTL1"]
iso["LSAIso.exe(비밀의 금고)"]
end
lsassP <-->|RPC| iso
att -->|메모리 덤프| lsassP
att -.->|손이 닿지 않음| iso
그림 11: 창구와 금고가 나뉘었으므로, lsass를 덤프해도 보호된 도메인 자격 증명의 실제 해시는 나오지 않는다.
Windows 11 버전 22H2 이후, 라이선스 요건(Enterprise E3/E5, Education A3/A5)과 하드웨어 요건을 충족하는 장치에서는 VBS와 Credential Guard가 기본으로 켜집니다. Pro 같은 에디션에서는 Credential Guard가 자동으로 켜지지 않습니다(적격 라이선스에서 켜진 머신이 나중에 다운그레이드되는 경우 같은 예외는 있습니다).7 서두의 「수법이 더 이상 통하지 않는다」는 특수 추가 제품의 이야기가 아니라, 대상 에디션에서 현행 Windows의 표준 상태입니다.
flowchart TB
accTitle: 로그인부터 인증까지의 자격 증명 흐름
accDescr: 로그인 후 실제 비밀은 VTL1의 LSAIso에 저장된다. 인증이 필요할 때마다 VTL0의 lsass가 RPC로 계산을 요청하고, 보호된 장기 비밀 자체는 반환되지 않은 채 인증 처리의 결과만 VTL0으로 돌아온다
signin["사용자가 로그인"] --> front["lsass가 창구로 처리"]
front --> store["실제 비밀은 LSAIso에 저장"]
auth["이후의 인증 요청"] --> front
front -->|"RPC로 계산을 요청"| store
store -->|"결과를 반환(비밀은 반환하지 않음)"| front
그림 12: 보호된 장기 비밀 자체는 금고를 떠나지 않고, VTL0으로 돌아오는 것은 티켓 같은 인증 처리의 결과다.
5.2. 보호하지 않는 것을 정확히 알기
Credential Guard는 만능 방패가 아닙니다. 보호하는 것은 도메인 자격 증명의 NTLM 해시, Kerberos TGT(Ticket Granting Ticket), 도메인 자격 증명으로 저장된 것입니다. 다음은 범위 밖입니다.8
- Kerberos 서비스 티켓(TGT는 보호됩니다)
- 로컬 계정과 Microsoft 계정의 자격 증명
- 키로거에 의한 입력 탈취, 물리 공격
- NTLMv1, MS-CHAPv2, Digest, CredSSP를 쓰는 경로의 자격 증명
- 자격 증명을 자체 관리하는 타사 소프트웨어의 내부
또한 Credential Guard를 켜면 NTLMv1, 제약 없는 Kerberos 위임 등을 쓸 수 없게 되므로, 레거시 인증에 의존하는 업무 시스템은 호환성 확인이 필요합니다.8 「켜면 끝」이 아니라, 방어 범위의 안과 밖을 파악하고 나머지는 다른 통제로 메우는 것이 실무의 올바른 사용법입니다.
flowchart TB
accTitle: Credential Guard의 방어 범위
accDescr: 도메인 NTLM 해시와 TGT, 저장된 도메인 자격 증명은 보호되고, 서비스 티켓, 로컬 계정, 키로거, 물리 공격, 앱이 사적으로 저장한 자격 증명은 범위 밖이다
scope{"이 비밀은 보호 경계의 어느 쪽인가?"} --> inA["도메인 NTLM 해시와 TGT"]
scope --> outA["서비스 티켓과 로컬 계정"]
inA --> prot["LSAIso에서 보호"]
outA --> unprot["보호되지 않음(다른 통제가 필요)"]
unprot -.-> outB["키 입력, 물리 공격, 앱 사적 저장도 범위 밖"]
그림 13: 방어 범위는 분명한 선으로 그어지고, 선 밖은 다요소 인증과 앱 측 설계로 메운다.
6. 직접 확인해 보기
VBS와 각 기능의 실행 상태는 자기 머신에서 확인할 수 있습니다.
Get-CimInstance -Namespace root/Microsoft/Windows/DeviceGuard `
-ClassName Win32_DeviceGuard |
Select-Object VirtualizationBasedSecurityStatus,
SecurityServicesConfigured,
SecurityServicesRunning
읽는 법은 다음과 같습니다.9
VirtualizationBasedSecurityStatus가 2이면 VBS가 켜져 실행 중입니다.SecurityServicesRunning에 1이 있으면 Credential Guard가, 2가 있으면 메모리 무결성(HVCI)이 실행 중입니다.
GUI에서 실행 상태를 확인하려면 msinfo32의 「가상화 기반 보안」란을 보십시오(실행 중인 서비스가 「Hypervisor enforced Code Integrity」처럼 나열됩니다). Windows 보안 앱의 「디바이스 보안 > 핵심 격리」아래 「메모리 무결성」토글은 설정을 반영하는 화면이며, 켠 직후 재부팅을 기다리거나 시작 시 호환 문제가 있으면 HVCI가 실제로 돌지 않는데도 켜진 것처럼 보일 수 있습니다. 실행 여부는 msinfo32나 Win32_DeviceGuard의 SecurityServicesRunning으로 판단하십시오.5
작업 관리자의 세부 정보 탭에도 흔적이 있습니다. VBS가 도는 머신에는 「Secure System」이라는 프로세스가 보입니다. LsaIso.exe는 Isolated LSA 서비스가 VTL1에서 호스트될 때 나타나는 프로세스이며, HVCI만 켜진 구성에서는 보통 나타나지 않습니다. 다만 프로세스의 유무는 흔적일 뿐이므로, Credential Guard가 도는지는 위와 같이 SecurityServicesRunning(1이 포함되는지)으로 판단하십시오. 둘 다 VTL0에서 보이는, VTL1 측 세계에 대응하는 창입니다.
flowchart TB
accTitle: VBS 관련 기능이 도는지 확인하는 방법
accDescr: Win32_DeviceGuard를 조회해 VBS가 도는지 확인하고, Credential Guard와 HVCI는 SecurityServicesRunning 값으로 판단하며, 드라이버 문제는 CodeIntegrity 로그를 본다
q0["Win32_DeviceGuard"] --> q1{"VBS Status 2?"}
q1 -->|아니오| off["VBS가 돌지 않음"]
q1 -->|예| q2{"1 또는 2가 포함?"}
q2 -->|1| cg["Credential Guard 켜짐"]
q2 -->|2| hvciR["HVCI 켜짐"]
hvciR -.-> ev["CodeIntegrity 3087"]
그림 14: 상태 확인은 세 단계로 진행된다. VBS 자체, 그 위의 각 서비스, 문제가 났을 때의 로그.
7. 실무에서 피해야 할 세 가지 오해
7.1. 「관리자 권한을 지키면 충분하다. VBS는 서버 측 이야기다」
Credential Guard가 막는 것은 관리자 권한이 빼앗긴 뒤의 피해 확산(해시 유출과 횡적 이동)입니다. 즉 VBS는 침해를 가정한 다층 방어의 한 층이며, 효과를 내는 곳은 클라이언트 PC입니다. 요건을 충족하는 Windows 11에서는 기본 사용이 표준이므로, 「우리와 무관하다」가 아니라 「이미 돈다는 전제로 호환성을 관리한다」가 올바른 자세입니다.
flowchart TB
accTitle: 침해의 단계와 VBS가 효과를 내는 자리
accDescr: 초기 접근은 다요소 인증과 교육 등 다른 통제가 담당한다. HVCI는 권한 상승 후 커널로의 코드 주입을 막고, Credential Guard는 보호된 도메인 비밀의 탈취와 횡적 이동을 막지만 범위 밖 비밀에는 닿지 않는다
s1["초기 접근(피싱 등)"] --> s2["권한 상승"]
s2 --> s3["커널로의 코드 주입"]
s3 --> s4["보호된 도메인 비밀의 탈취와 횡적 이동"]
s1 -.-> d1["MFA, 교육, EDR이 담당"]
s3 -.-> d2["HVCI가 이 단계를 차단"]
s4 -.-> d3["Credential Guard가 차단(보호된 비밀만)"]
그림 15: VBS는 「들이지 않는」기술이 아니라 「들어온 뒤에 이기지 못하게 하는」기술이며, 지키는 단계는 다르다.
7.2. 「메모리 무결성이 문제를 내면 끄면 된다」
끄면 당장은 동작하지만, 커널로의 코드 주입에 대한 장벽을 통째로 내립니다. 올바른 대응은 먼저 CodeIntegrity 로그에서 차단된 드라이버를 식별하고, 벤더의 업데이트 버전을 적용하는 것입니다. 검증을 위해 일시적으로 끄더라도, 그걸 영구 설정으로 만들지 않는 운용을 권합니다.
7.3. 「Credential Guard가 있으면 암호를 훔칠 수 없다」
그건 방어 범위를 혼동한 과신입니다. 서비스 티켓, 로컬 계정, 키 입력 자체, 앱이 사적으로 저장한 자격 증명은 범위 밖입니다.8 피싱과 키로거에는 다른 통제(다요소 인증, Windows Hello, 앱 측 자격 증명 관리의 재검토)가 필요합니다.
8. 정리
- VBS는 하이퍼바이저로 격리 환경을 만들고, 커널이 침해될 수 있다는 가정 위에서 보안 기능을 보호합니다.1
- 격리의 단위는 VTL이며, 현재 구현된 것은 VTL0(일반 세계)과 VTL1(Secure Kernel과 IUM)의 두 단계입니다.2
- 경계의 실체는 SLAT 메모리 접근 보호이며, 커널을 포함한 파티션 안의 소프트웨어는 이를 바꿀 수 없습니다.2
- HVCI는 코드 무결성 검증을 격리 환경에서 돌리고, 「검증을 통과하기 전에는 실행 불가」, 「실행 가능 페이지는 쓰기 불가」를 강제합니다.4 대가는 드라이버 호환성을 관리해야 한다는 점입니다.5
- Credential Guard는 도메인 자격 증명의 NTLM 해시와 TGT를 VTL1의 LSAIso로 격리합니다. Windows 11 22H2 이후, 라이선스 요건(Enterprise, Education)과 하드웨어 요건을 충족하는 장치에서 기본으로 켜집니다(실행 상태 확인과 함께 쓰십시오).67
- 실행 상태는
Win32_DeviceGuard의 SecurityServicesRunning으로 확인할 수 있습니다(1 = Credential Guard, 2 = HVCI).9
이어지는 제3회, 「수초 만에 기동하는 가상 머신 ── WSL2, Windows Sandbox, 컨테이너」.
지금까지는 가상화를 「격리의 강도」쪽에서 보았습니다. 마지막 회는 반대의 「가벼움」쪽에서, 풀 VM의 무게를 버린 경량 VM이 어디서 짐을 내리는지를 따라갑니다.
관련 기사
- Windows 가상화의 심층(제1회) ── 당신의 Windows는 어디서 움직이고 있는가: 하이퍼바이저와 파티션
- The Depths of Windows Memory (Part 1) — The Moment a Virtual Address Becomes Physical RAM: A Page Fault from Start to Finish
- Windows I/O의 심층(제6회・최종회) ── 필터 드라이버와 미니필터: Procmon과 백신 검사가 I/O에 개입할 수 있는 이유
- Decoding Windows Error Codes — The Three-Layer Structure of Win32 Errors, HRESULT, and NTSTATUS
관련 상담 영역
합동회사 코무라소프트에서는 Windows 앱과 보안 기능의 호환성 조사, 드라이버가 일으킨 장애의 분석, 사내 PC 환경의 기술 검증을 다루고 있습니다.
참고 링크
-
Microsoft Learn, Virtualization-based Security (VBS). VBS가 하드웨어 가상화와 Windows 하이퍼바이저로 격리 환경을 만들고, 커널이 침해될 수 있다는 가정 위에서 그것을 OS의 신뢰 루트로 다룬다는 점, 메모리 무결성이 그 격리 환경 안에서 커널 모드 코드 무결성 검증을 돌린다는 점, SLAT가 VBS의 필수 요건이라는 점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Virtual Secure Mode. VSM이 Device Guard, Credential Guard, 가상 TPM 등의 기반이라는 점, 격리 영역에 대한 접근이 하이퍼바이저를 통해서만 제어되며 링 0 OS 소프트웨어에서도 보호된다는 점, VTL이 계층적이고 최대 16단계 중 2단계가 구현되었다는 점, VTL마다의 메모리 접근 보호를 파티션 안의 시스템 소프트웨어가 바꿀 수 없다는 점에 대해. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Isolated User Mode (IUM) Processes. VSM이 Hyper-V 하이퍼바이저와 SLAT로 VTL을 만든다는 점, Secure Kernel과 IUM이 VTL1에서 돈다는 점, 트러스틀릿이 시스템 호출을 VTL0 커널로 마샬링한다는 점, LSAIso가 VTL1에서 돌며 RPC로 lsass와 통신한다는 점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Memory integrity and virtualization-based security. 메모리 무결성(HVCI)이 격리 환경에서 코드 무결성 검증을 돌린다는 점, 커널 메모리 페이지가 검증을 통과한 뒤에야 실행 가능해지고 실행 가능 페이지는 쓰기 가능해지지 않는다는 점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Memory integrity and VBS enablement. 하드웨어가 호환되면 Windows 11 클린 설치에서 메모리 무결성이 기본으로 켜진다는 점, msinfo32와 Windows 보안 앱에서 상태를 확인한다는 점, CodeIntegrity Operational 로그의 이벤트 ID 3087로 차단된 드라이버를 확인한다는 점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, How Credential Guard works. Credential Guard가 켜지면 LSA가 Isolated LSA 프로세스(LSAIso.exe)와 통신해 비밀을 저장한다는 점, 저장된 데이터가 VBS로 보호되어 OS의 나머지에서 접근할 수 없다는 점, Isolated LSA 프로세스가 디바이스 드라이버를 호스트하지 않고 서명 검증된 최소 바이너리만 담는다는 점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Credential Guard overview. Windows 11 버전 22H2 이후, 라이선스·하드웨어·소프트웨어 요건을 충족하고 명시적으로 끄지 않은 장치에서 Credential Guard가 기본으로 켜진다는 점, 적격 에디션/라이선스가 Enterprise(E3/E5)와 Education(A3/A5)이며 Pro는 범위 밖이라는 점, 적격 라이선스에서 이전에 켜진 Pro 머신은 다운그레이드 후에도 기본 사용 대상으로 남는다는 점에 대해. ↩ ↩2
-
Microsoft Learn, Credential Guard protection limits. 서비스 티켓, 로컬 계정, 키로거, 물리 공격 등이 Credential Guard의 보호 범위 밖이라는 점, TGT는 보호되지만 서비스 티켓은 아니라는 점, 켜면 NTLMv1과 제약 없는 위임을 쓸 수 없게 된다는 점에 대해. ↩ ↩2 ↩3
-
Microsoft Learn, Enable virtualization-based protection of code integrity. Win32_DeviceGuard 클래스로 VBS와 메모리 무결성의 상태를 확인하는 방법, SecurityServicesRunning 값의 의미(1은 Credential Guard, 2는 메모리 무결성)에 대해. ↩ ↩2
관련 기사
같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.
Windows 가상화의 심층(제3회) ── 수초 만에 기동하는 가상 머신: WSL2, Windows Sandbox, 컨테이너가 가벼운 이유
WSL2와 Windows Sandbox가 수초 만에 기동하고 가벼운 이유는 무엇일까요. 동적 베이스 이미지와 다이렉트 맵, 동적 메모리 할당부터 Hyper-V 격리 컨테이너까지 구조를 해설합니다.
Windows 가상화의 심층(제1회) ── 당신의 Windows는 어디서 움직이고 있는가: 하이퍼바이저와 파티션
Hyper-V를 켜면 호스트 Windows 자체가 루트 파티션으로서 하이퍼바이저 위에서 움직입니다. VT-x, SLAT, VMBus의 역할까지, 가상화의 토대를 해설합니다.
네임드 파이프의 실무 ── Windows 프로세스 간 통신의 정석을 설계부터 보안까지
Windows 프로세스 간 통신의 정석인 네임드 파이프를 실무 관점에서 정리합니다. 바이트/메시지 모드 선택, 여러 클라이언트를 받는 서버 설계, ACL과 위장 보안, .NET NamedPipeStream까지 1차 정보를 바탕으로 설명합니다.
Windows 보안 감사 정책과 이벤트 로그 조사 실무 ── 4625를 읽어내는 정보시스템 담당자 되기
「로그온 실패 로그를 조사해 달라」는 요청에 대응하기 위한 실무 가이드입니다. 기본 감사 정책과 고급 감사 정책의 관계, 최소한 활성화해야 할 하위 범주, 이벤트 ID 4624/4625/4688을 읽는 법, Security 로그의 용량 설계, G...
Windows LAPS 실무 가이드 ── 전 PC 공통 로컬 관리자 비밀번호를 그만두기
전 PC 공통 로컬 관리자 비밀번호는 한 대의 침해가 전체로 번지는 Pass-the-Hash 공격의 온상입니다. OS 표준 기능이 된 Windows LAPS의 자동 로테이션과 AD/Entra ID 저장 설정, 운영상의 함정을 설명합니다.
관련 토픽
이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.
Windows 기술 토픽
Windows 개발, 장애 조사, 기존 자산 활용에 관한 KomuraSoft LLC 기사를 모은 토픽 허브입니다.
이 주제와 연결되는 서비스
이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.
Windows 앱 개발
상주 처리, 장비 연동, 운영 로그, 유지 보수 가능한 구조가 필요한 Windows 데스크톱 애플리케이션을 지원합니다.
자주 묻는 질문
이 기사 주제에 대해 상담 시 자주 나오는 질문을 모았습니다.
- VBS(가상화 기반 보안)와 핵심 격리는 같은 것인가요?
- 엄밀히는 다릅니다. VBS는 하이퍼바이저로 격리 환경을 만드는 기반 기술이고, Windows 보안 앱의 「핵심 격리」는 VBS 위에 만들어진 여러 보호를 묶은 화면의 이름입니다. 대표적인 것이 「메모리 무결성」이며, HVCI(하이퍼바이저로 보호되는 코드 무결성)를 가리킵니다. 각 서비스의 실행 상태는 화면 표시가 아니라 Win32_DeviceGuard를 조회해 확인하십시오.
- 관리자 권한이나 커널 드라이버에서도 VTL1 메모리를 정말 읽을 수 없나요?
- 읽을 수 없습니다. VTL마다의 메모리 접근 보호는 하이퍼바이저가 파티션의 물리 주소 공간에 대해 관리하며, 파티션 안에서 도는 소프트웨어는 이를 바꿀 수 없습니다. 커널(링 0)에서 도는 코드라도, VTL0에서 VTL1 메모리에 접근하는 것은 허용되지 않습니다.
- 메모리 무결성(HVCI)을 켜면 드라이버가 멈추는 이유는 무엇인가요?
- HVCI 환경에서는 커널 페이지가 무결성 검증을 통과한 뒤에야 실행 가능해지고, 실행 가능한 페이지에 대한 쓰기는 허용되지 않습니다. 서명되지 않은 드라이버나, 실행 가능 메모리를 다시 쓰는 예전 설계의 드라이버는 이 제약을 충족하지 못해 로드가 차단됩니다. 차단은 CodeIntegrity Operational 로그(이벤트 ID 3087 등)에서 확인할 수 있습니다.
- Credential Guard가 보호하는 것과 보호하지 않는 것은 무엇인가요?
- 도메인 자격 증명의 NTLM 암호 해시, Kerberos TGT, 앱이 도메인 자격 증명으로 저장한 것을 격리 환경에서 보호합니다. Kerberos 서비스 티켓, 로컬 계정과 Microsoft 계정의 자격 증명, 키로거에 의한 입력 탈취, 물리 공격은 범위 밖입니다.
- VBS가 도는지 어디서 확인할 수 있나요?
- msinfo32의 「가상화 기반 보안」란을 보거나, PowerShell에서 root/Microsoft/Windows/DeviceGuard 네임스페이스의 Win32_DeviceGuard 클래스를 조회하십시오. SecurityServicesRunning에 1이 있으면 Credential Guard가, 2가 있으면 메모리 무결성(HVCI)이 실행 중입니다.