driver-online
  log-inmypagesitemap
top
   자유게시판
   로그북
    견우일지
    시스템팀 개발일지
    Beginning Driver
   유용한 팁&강좌
   CrashDump분석(beta)
   개발QnA
    WDM 입문
    USB
    NDIS
    File System
    Debugging 관련
    그 외
 

CR4 레지스터 관련한 BSOD 분석
 ·작성일 2008.10.11:16.52 (토)  · 작성자 drost  · 조 회 9,364


작성일 : 2008-10-11

김희준(drost@naver.com, http://insidekernel.net)

 

 

얼마전에 집에서 웹서핑을 하던 도중, 갑자기 사용하던 윈도우에서 BSOD를 띄우는 일이 발생하였다.

 

대체적으로 덤프가 발생한 순간 어떤 작업을 하였는지 떠올려보면 BSOD를 일으킨 주범이 누군지 밝혀낼 수 있다. 얼마전에는 하드디스크가 디스크 읽기 실패를 반복하며 계속 불이 들어와 있는 상황에서 KERNEL_DATA_INPAGE_ERROR라는 bugcheck가 발생하였는데, 우선 디스크 I/O 관련하여 에러를 예상하였고 실제로 bugcheck의 의미 역시, OS가 디스크에 데이터를 불러들이는 PAGE-IN 과정을 실패하여 발생한 것으로써 결과적으로 하드디스크의 물리적인 고장이였다. 이번 BSOD의 경우에도 마찬가지로, 난 웹서핑을 하다가 인터넷 뱅킹을 위하여 은행 사이트에 접속을 하였고, 로그인을 위하여 텍스트 입력 창을 클릭한 순간 BSOD가 발생하였다. 따라서 우선 떠오르는 용의자는 바로 키보드 보안 드라이버이다.

 

처음에는 키보드 보안 드라이버에 버그가 있겠거니하고 넘어가고 대수롭지 않게 여겼지만 일주일에 두세번 이상 BSOD를 일으킬 정도로 그 빈도가 자꾸 늘어가자 원인을 분석하기로 결심하고 우선 미니 덤프를 열어보았다.

 

1: kd> !analyze -v

*******************************************************************************

*                                                                             *

*                        Bugcheck Analysis                                    *

*                                                                             *

*******************************************************************************

 

UNEXPECTED_KERNEL_MODE_TRAP_M (1000007f)

This means a trap occurred in kernel mode, and it's a trap of a kind

that the kernel isn't allowed to have/catch (bound trap) or that

is always instant death (double fault).  The first number in the

bugcheck params is the number of the trap (8 = double fault, etc)

Consult an Intel x86 family manual to learn more about what these

traps are. Here is a *portion* of those codes:

If kv shows a taskGate

        use .tss on the part before the colon, then kv.

Else if kv shows a trapframe

        use .trap on that value

Else

        .trap on the appropriate frame will show where the trap was taken

        (on x86, this will be the ebp that goes with the procedure KiTrap)

Endif

kb will then show the corrected stack.

Arguments:

Arg1: 0000000d, EXCEPTION_GP_FAULT

Arg2: 00000000

Arg3: 00000000

Arg4: 00000000

 

 

발생한 bugcheck를 살펴보면 0x7F이고 Arg1d로써 CPUGP Fault를 띄운 것이다. 그렇다면 GP fault를 발생시킨 실제 에러 코드로 이동해보자.

 

b5d3f738 8bff            mov     edi,edi

b5d3f73a 50              push    eax

b5d3f73b c7057c73d4b501000000 mov dword ptr [xxx.sys+0x937c (b5d4737c)],1

b5d3f745 0f20e0          mov     eax,cr4

b5d3f748 25f7070000      and     eax,7F7h

b5d3f74d 0f22e0          mov     cr4,eax

b5d3f750 b800040000      mov     eax,400h

b5d3f755 0f23f8          mov     dr7,eax

b5d3f758 33c0            xor     eax,eax

b5d3f75a 0f23c0          mov     dr0,eax

b5d3f75d 0f23c8          mov     dr1,eax

b5d3f760 0f23d0          mov     dr2,eax

b5d3f763 0f23d8          mov     dr3,eax

b5d3f766 58              pop     eax

b5d3f767 c3              ret

 

전체 코드 흐름을 보자면 CR4 레지스터에 0x7F7 값을 마스킹하고, DR 레지스터들을 클리어 하는 안티 디버깅 코드로 보여진다. (DR 레지스터를 다루는 코드들은 대부분 디버깅을 방지하는 보안 관련 코드들인 경우가 많다) 실제 에러를 발생시킨 코드는 바로 아래 라인이다.

 

FOLLOWUP_IP:

xxx.sys+174d

b5d3f74d 0f22e0          mov     cr4,eax

 

CR4레지스터에 값을 넣으려는 순간 GP Fault가 발생했을까? CR4 레지스터에 MOV 명령어를 사용하여 값을 넣는 행동 자체에는 이상이 없다. 인텔 문서를 살펴봐도 CR4 레지스터에 쓰기 금지가 되어있다거나 하는 내용은 없고, 허용한다는 내용이 CR4 레지스터 설명에 존재한다.

 

그러나 잘 살펴보면 비트마스킹 하는 부분에 문제가 있음을 발견할 수 있다.

 

1: kd> .formats 0x7f7

Evaluate expression:

  Hex:     000007f7

  Decimal: 2039

  Octal:   00000003767

  Binary:  00000000 00000000 00000111 11110111

  Chars:   ....

  Time:    Thu Jan 01 09:33:59 1970

  Float:   low 2.85725e-042 high 0

Double:  1.0074e-320

 

0x7F7을 마스킹 한다는 것은 안티 디버깅 기능을 위하여 ‘Debugging Extensions’를 나타내는 3번째 비트를 클리어하는 것이 목적인데, 엉뚱하게도 11번째 이후 비트들마저 모두 0으로 클리어 시키고 있는 것이다. 그렇다면 위 CR4에 값을 넣는 과정에서 사라지는 비트가 존재할까?

 

1: kd> r cr4

cr4=000026f1

 

GP Fault가 발생한 순간의 레지스터들을 살펴보면 당시 CR4의 값은 0x26f1의 값이고 이것을 2진수로 바꿔보면 다음과 같다.

1: kd> .formats 000026f1

Evaluate expression:

  Hex:     000026f1

  Decimal: 9969

  Octal:   00000023361

  Binary:  00000000 00000000 00100110 11110001

  Chars:   ..&.

  Time:    Thu Jan 01 11:46:09 1970

  Float:   low 1.39695e-041 high 0

Double:  4.92534e-320

 

, 13번째 비트가 켜져 있는 것을 볼 수 있고, MOV CR4, EAX 명령어로 인해 13번째 비트가 클리어 된다. 그렇다면 13번째 비트는 무엇인가? 인텔 문서에는 아래와 같이 적혀있다.

 

VMXE

VMX-Enable Bit (bit 13 of CR4) — Enables VMX operation when set. See Chapter 19, “Introduction to Virtual-Machine Extensions.”

 

VMXE라는 비트이다. VMX 관련된 내용을 인텔 문서에서 좀더 검색해보면 결정적인 단서를 발견할 수 있다.

 

19.8 RESTRICTIONS ON VMX OPERATION

VMX operation places restrictions on processor operation. These are detailed below:

In VMX operation, processors may fix certain bits in CR0 and CR4 to specific

values and not support other values. VMXON fails if any of these bits contains an

unsupported value (see “VMXON—Enter VMX Operation” in Chapter 6 of the

Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 2B).

Any attempt to set one of these bits to an unsupported value while in VMX

operation (including VMX root operation) using any of the CLTS, LMSW, or MOV

CR instructions causes a general-protection exception. VM entry or VM exit

cannot set any of these bits to an unsupported value.2

 

 

, VMX가 동작중인 상황에서 이 비트를 쓰려고 한다면 GP fault를 발생시킨다는 내용이다. 좀더 디버깅한 결과 VirtualPC가 실행되고 있는 상태에서 이러한 충돌을 일으킨다는 것을 발견하였고, VirtualPCCPUVMX 모드로 동작시킬 때 키보드 보안 드라이버의 이러한 오래된 코드가 충돌을 일으킨 것으로 결론짓게 되었다.

 

앞으로 키보드 보안 드라이버가 업데이트 되기 전까지, VirtualPC를 한쪽에서 띄우고 한쪽에서 인터넷 뱅킹을 하는 일은 미뤄두어야 할 것이다. ^^

*답변을 받은 후 감사의 글을 남기는 것은 꼭 지켜야할 네티켓입니다.
 
  

이 전 : Kernel debugger 에서 User mode debug 하기

다 음 : BSOD 분석에 대한 인터뷰


·MovALFEOut64AL 우와, 블루스크린 자주보는데 명쾌하게 원인을 찾아내는
설명이 머리에 쏙쏙 들어오네요.
2008.11.27 코멘트 삭제
 
quick-menu
event
study
QnA
pds
family-site concert used used2 intro
address
address