Home | Info | Research | Blog | Repos | Messages | Contact Me

 


VS2005의 버그 때문에 이 VS2005로 컴파일한 exe 파일만 실행해도 재부팅이 발생할 수 있습니다.

그 조합은 Windows XP SP2, IE6(기타 보안패치를 설치하지 않은 상태)에 Visual Studio 2005 상세 버전 8.0.50727.42로 빌드한 exe 파일을 실행할때 입니다.

문제는 exe 파일을 한번만 실행하면 괜찮은데, 2회에서 3회 반복 실행하면 재부팅이 발생합니다. (이것도 PC마다 다름)

*** An Access Violation occurred in C:\WINDOWS\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,3072,512 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ProfileControl=Off MaxRequestThreads=16:

The instruction at 7C9401B3 tried to write to an invalid address, 75DE193E

 *** enter .exr 018FECE8 for the exception record
 ***  enter .cxr 018FED04 for the context
 *** then kb to get the faulting stack

Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
001b:7c93120e cc              int     3
1: kd> !analyze -v
FAULTING_IP:
ntdll!RtlAllocateHeap+1da
001b:7c9401b3 884706          mov     byte ptr [edi+6],al

EXCEPTION_RECORD:  ffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 7c93120e (ntdll!DbgBreakPoint)
   ExceptionCode: 80000003 (Break instruction exception)
  ExceptionFlags: 00000000
NumberParameters: 3
   Parameter[0]: 00000000
   Parameter[1]: 7c997810
   Parameter[2]: 00000028

ERROR_CODE: (NTSTATUS) 0x80000003 - {

EXCEPTION_CODE: (HRESULT) 0x80000003 (2147483651) -

EXCEPTION_PARAMETER1:  00000000

EXCEPTION_PARAMETER2:  7c997810

EXCEPTION_PARAMETER3:  00000028

NTGLOBALFLAG:  0

FAULTING_THREAD:  ffffffff

ADDITIONAL_DEBUG_TEXT:  Enable Pageheap/AutoVerifer

DEFAULT_BUCKET_ID:  HEAP_CORRUPTION

PRIMARY_PROBLEM_CLASS:  HEAP_CORRUPTION

BUGCHECK_STR:  APPLICATION_FAULT_HEAP_CORRUPTION_STATUS_BREAKPOINT

LAST_CONTROL_TRANSFER:  from 75df2137 to 7c9401b3

STACK_TEXT: 
7c9401b3 ntdll!RtlAllocateHeap+0x1da
75df2137 sxs!CSxsPointerBase<CXMLNamespaceManager::CNamespacePrefix,CSxsPointer<CXMLNamespaceManager::CNamespacePrefix,CXMLNamespaceManager::CNamespacePrefix::ms_szTypeName> >::HrAllocateBase+0x59
75de2f21 sxs!CXMLNamespaceManager::OnCreateNode+0x12e
75de38d2 sxs!CNodeFactory::CreateNode+0xa3
75de435f sxs!XMLParser::Run+0x2fc
75de8baa sxs!SxspIncorporateAssembly+0x8b8
75de9a0f sxs!SxspCloseManifestGraph+0x98
75de98cd sxs!SxsGenerateActivationContext+0x54c
75a9a5ed basesrv!BaseSrvSxsCreateActivationContextFromStruct+0x194
75a9a760 basesrv!BaseSrvSxsCreateActivationContextFromMessage+0x79
75a84a47 CSRSRV!CsrApiRequestThread+0x431


STACK_COMMAND:  .cxr 018FED04 ; kb ; dds 18fefd0 ; kb

SYMBOL_NAME:  heap_corruption!heap_corruption

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: heap_corruption

IMAGE_NAME:  heap_corruption

DEBUG_FLR_IMAGE_TIMESTAMP:  0

FAILURE_BUCKET_ID:  HEAP_CORRUPTION_80000003_heap_corruption!heap_corruption

BUCKET_ID:  APPLICATION_FAULT_HEAP_CORRUPTION_STATUS_BREAKPOINT_heap_corruption!heap_corruption

Followup: MachineOwner
---------


이 상태에서 F5(Go)를 하면 다시 아래와 같은 BugCheck이 발생하면서 완전히 재부팅됩니다.

1: kd> g

*** Fatal System Error: 0xc000021a
                       (0xE10C62F8,0xC0000005,0x7C9401B3,0x018FED04)

STOP: c000021a Unknown Hard Error
Unknown Hard ErrorBreak instruction exception - code 80000003 (first chance)

A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.

A fatal system error has occurred.

*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

Use !analyze -v to get detailed debugging information.

BugCheck C000021A, {e10c62f8, c0000005, 7c9401b3, 18fed04}

unable to get nt!KiCurrentEtwBufferOffset
unable to get nt!KiCurrentEtwBufferBase

*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

WINLOGON_FATAL_ERROR (c000021a)
The Winlogon process terminated unexpectedly.
Arguments:
Arg1: e10c62f8, String that identifies the problem.
Arg2: c0000005, Error Code.
Arg3: 7c9401b3
Arg4: 018fed04

Debugging Details:
------------------

unable to get nt!KiCurrentEtwBufferOffset
unable to get nt!KiCurrentEtwBufferBase

... 생략 ...

ERROR_CODE: (NTSTATUS) 0xc000021a - {

EXCEPTION_CODE: (NTSTATUS) 0xc000021a - {

EXCEPTION_PARAMETER1:  e10c62f8

EXCEPTION_PARAMETER2:  c0000005

EXCEPTION_PARAMETER3:  7c9401b3

EXCEPTION_PARAMETER4: 18fed04

ADDITIONAL_DEBUG_TEXT:  Windows SubSystem

BUGCHECK_STR:  0xc000021a_csrss.exe_c0000005

DEFAULT_BUCKET_ID:  DRIVER_FAULT

PROCESS_NAME:  System

LAST_CONTROL_TRANSFER:  from 8085f2bf to 8080ba52

SYMBOL_ON_RAW_STACK:  1

STACK_ADDR_RAW_STACK_SYMBOL: fffffffff78d2b8c

STACK_COMMAND:  dds F78D2B8C-0x20 ; kb

STACK_TEXT: 
f78d2b6c  8a2e8240
f78d2b70  00000000
f78d2b74  e165e4f8
f78d2b78  e15ae350
f78d2b7c  e165e488
f78d2b80  00000000
f78d2b84  00000000
f78d2b88  b78268a4 mrxdav!_NULL_IMPORT_DESCRIPTOR+0x3c
f78d2b8c  b77fe000 mrxdav!MrxDAVEfsControlCompletion <PERF> (mrxdav+0x0)
f78d2b90  808cf973 nt!MiSnapThunk+0x6f
f78d2b94  8a32c008
f78d2b98  b782735e mrxdav!_NULL_IMPORT_DESCRIPTOR+0xaf6
f78d2b9c  000000ff
f78d2ba0  b78268a4 mrxdav!_NULL_IMPORT_DESCRIPTOR+0x3c
f78d2ba4  b7804aa8 mrxdav!_imp__GetSecurityUserInfo
f78d2ba8  808cfae6 nt!MiSnapThunk+0x382
f78d2bac  00000001
f78d2bb0  00000000
f78d2bb4  b77fe000 mrxdav!MrxDAVEfsControlCompletion <PERF> (mrxdav+0x0)
f78d2bb8  f78ee924
f78d2bbc  b7804aa8 mrxdav!_imp__GetSecurityUserInfo
f78d2bc0  b78274ba mrxdav!_NULL_IMPORT_DESCRIPTOR+0xc52
f78d2bc4  00000000
f78d2bc8  e165e301
f78d2bcc  f7477958 KSecDD!DESParityTable <PERF> (KSecDD+0x14958)
f78d2bd0  00000000
f78d2bd4  0000000e
f78d2bd8  b7827372 mrxdav!_NULL_IMPORT_DESCRIPTOR+0xb0a
f78d2bdc  8a2e8240
f78d2be0  f78ee9b4
f78d2be4  f7b774ba Ntfs!NtfsFsdClose+0x3b0
f78d2be8  8a0c1978


FOLLOWUP_IP:
mrxdav!_NULL_IMPORT_DESCRIPTOR+3c
b78268a4 5c              pop     esp

SYMBOL_NAME:  mrxdav!_NULL_IMPORT_DESCRIPTOR+3c

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: mrxdav

IMAGE_NAME:  mrxdav.sys

DEBUG_FLR_IMAGE_TIMESTAMP:  41107b91

FAILURE_BUCKET_ID:  0xc000021a_csrss.exe_c0000005_mrxdav!_NULL_IMPORT_DESCRIPTOR+3c

BUCKET_ID:  0xc000021a_csrss.exe_c0000005_mrxdav!_NULL_IMPORT_DESCRIPTOR+3c

Followup: MachineOwner
---------

자세한 원인 분석은 생략하겠습니다. 귀찮기도 하고 분석을 해봐도 뭐가 잘못된건지도 잘 모르겠고...

해결책은 이렇습니다.

VS2005 서비스팩1(KB926605)과 패치(KB932237)를 설치한다.

결론은 서비스팩1과 패치가 설치되지 않은 VS2005는 잘못된 exe를 생성해낸다는 것입니다.

지금까지 설명한 것과 비슷한 문제가 발생한다면, Visual Studio 2005 서비스팩과 패치를 설치해보는 것을 권장합니다.

- 원인을 발견하기까지
빌드 서버에서 빌드한 exe를 실행하면 계속 재부팅 현상이 발생하는데, 개발자 PC에서 빌드한 바이너리는 정상적으로 동작하는 것이었습니다. 약 이틀동안의 삽질을 하면서 소스코드의 별별 장소를 다 바꿔보고, 컴파일 옵션도 바꿔봤지만 소용이 없었습니다.

더 웃긴것은 문제가 발생하는 사람도 있고 그렇지 않은 사람도 있었던 것입니다.

그때 문득 팀원 중 한명이... 개발자 PC와 빌드 서버의 환경이 다른것이 아닐까? 하는 의견과 함께 VS2005의 버전을 확인하기 시작했습니다.

문제가 생기지 않는 개발자의 VS2005 버전은 8.0.50727.867(서비스팩1과 패치 설치)이었고 문제가 생기는 개발자와 빌드 서버의 VS2005 버전은 8.0.50727.42 였던 것입니다.

- 끝으로
빌드 서버를 이용한 개발환경에서 개발 도구(VS2005)의 버전 때문에 예상치 못한 문제가 발생할 수 있다는 점을 경험하게 되었습니다.

개발자 PC의 개발 도구(VS2005)와 빌드 서버의 개발 도구(VS2005)의 버전은 항상 일치시키켜야 합니다. 그렇지 않으면 버전 차이로 인해 원인 추적이 까다로운 문제가 발생할 수 있습니다.





SQLite는 아주 가벼운 데이터베이스 라이브러리입니다. SQL 문법을 사용할 수 있고 트랜잭션을 지원합니다.

이번에 윈도우 커널 모드(드라이버)에서 사용할 수 있는 SQLite를 만들어봤습니다. 윈도우 드라이버에서도 데이터를 데이터베이스 형식으로 관리하고자 할 때 사용할 수 있습니다. 혹은 유저모드에서 만든 SQLite 데이터베이스 파일을 윈도우 드라이버에서 읽거나 쓸 때에도 사용할 수 있습니다.

SQLite 버전은 3.6.12이며 WDK 6000 이상에서 빌드 할 수 있도록 작업하였습니다.

다운로드는 SQLiteForWindowsKernel 페이지에서 할 수 있습니다.



커널 모드 드라이버에서도 유저 모드의 DLL과 비슷한 형태로 불러 쓸 수 있는 것이 Export Driver입니다.

커널 모드 DLL이라고도 하는데, 실제 형태를 보면 유저 모드의 DLL 보다는 커널 모드 드라이버 형태를 띄고 있기 때문에 Export Driver 쪽이 맞습니다.

이 Export Driver의 특성은 일반 커널 모드 드라이버의 특성과 유저 모드 DLL의 특성을 모두 가지고 있습니다.

유저 모드 DLL과의 공통점

  • .def 파일로 Export 할 함수를 정의한다.
  • DllMain 함수 역할을 하는 DllInitialize라는 함수가 있다. (하지만 유저 모드 DLL에는 없는 DllUnload라는 함수도 있다.)
  • 유저 모드 DLL의 Implicit Link와 비슷한 형태로 동작한다. 드라이버를 로드하면 Export Driver는 자동으로 로드된다. 또한 드라이버가 언로드 되면 Export Driver도 자동으로 언로드 된다. (단 언로드는 DllUnload 함수가 있어야 하고 .def 파일에 정의되어 있어야 한다.)
커널 모드 드라이버 특성
  • DriverEntry 함수가 꼭 정의되어 있어야 한다. 없으면 빌드가 되지 않음.
  • .sys 확장자를 가진다.
  • StartService와 같은 SCM 함수나, 레지스트리 설정을 통해 Export Driver 만 독자적으로 로드, 언로드할 수 있다.

Export Driver를 SCM 함수로 직접 로드한 것과, Implicit Link 형태로 자동 로드 되었을 때의 차이점.

  • SCM 함수로 로드한 것은 드라이버 로드, 언로드 될 때 DriverEntry와 Unload 함수가 호출 된다. 따라서 Driver Object가 생성된다.
  • Implicit Link 형태로 자동 로드 한 것은 드라이버 로드, 언로드 될 때 DriverEntry와 Unload 함수가 호출되지 않는다. 따라서 Driver Object가 생성되지 않는다. 대신 드라이버 로드, 언로드 될 때 DllInitialize, DllUnload 함수가 호출 된다.
  • SCM 함수로 직접 로드되었을 때에는 이후 DllInitialize, DllUnload 함수는 호출되지 않는다.
Implicit Link 형태로 로드하고자 한다면 레지스트리의 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services에 키를 만들지 않아도 되고, CreateService 함수로 서비스를 생성하지 않아도, Export Driver를 로드하는데에는 문제가 없습니다. 단 주의할 점은 Export Driver를 사용하는 드라이버와 같은 디렉토리에 있어야 합니다.

Export Driver를 만드는 방법 : http://www.wd-3.com/archive/KernelDlls.htm
Calling a DLL in a Kernel-Mode Driver
ExportDriver-src.zip : Export Driver 예제입니다.



WDM 필터드라이버를 로드할 때 SetupDiCallClassInstaller 함수를 많이 사용합니다.

이 함수는 장치 트리를 재구성 할 때 사용하는데, 필터 드라이버는 특정 디바이스에 필터값을 설정하고 장치 트리를 재구성하면서 드라이버를 로드하는 것입니다.

여기서 SetupDiCallClassInstaller 함수가 동작하지 않을 때가 있습니다. 함수가 리턴하는 값이 TRUE 이면서 별다른 이상이 없는데도, 드라이버는 로드가 되지 않는 현상이 발생합니다.

문제는 WM_DEVICECHANGE 메시지입니다.

SetupDiCallClassInstaller 함수를 호출하면 WM_DEVICECHANGE (wParam : DBT_DEVNODES_CHANGED 0x0007) 메시지가 발생하는데 특정 프로그램이 중간에서 이 메시지를 없애버리면 드라이버가 로드 되지 않습니다.

예를 들자면 CBT 훅과 같이 전역 훅을 설치해두고 WM_DEVICECHANGE 메시지를 받은 뒤 정상적으로 전달해주지 않고 없애버리는 프로그램들입니다.

SetupDiCallClassInstaller 함수로 필터 드라이버가 로드 되지 않을 때에는 Spy++로 WM_DEVICECHANGE 메시지가 전달되는지 확인해보는 것이 좋습니다.