Archive for the 'Inside Windows' Category

Windows 7 & CR4

예전에 CR4에 관한 글을 하나 남긴적이 있습니다.( VMXE 관련 ) CR4 Register라는 놈이 굉장히 예민하기 때문에 Flag 하나 만으로도 바로 BSOD로 이어지는 경우가 많죠. ( 인터넷 뱅킹도중 많이 경험하셨을꺼라 생각합니다. ) Windows 7 부터는 한가지 부분에 대해서 더 유념해야 하는것이 생겼습니다.  바로 OSXSAVE Bit( 18 째 비트 ) 입니다.

기존 Windows에서는 XRSTOR 명령을 사용하지 않기때문에 18bit가 Reserved 되어 있었지만 Windows 7 부터는 XRSTOR 명령을 지원하는 CPU ( Intel CPU )의 경우 이 명령어를 사용하도록 되어 있습니다.
XRSTOR 명령은 기본적으로 CR4 레지스터의 18bit를 기본적으로 OSXSAVE인식 하는것이 BSOD가 발생할 수 있는 함정으로 작용할 수 있습니다.

Intel® 64 and IA-32 ArchitecturesSoftware Developer’s Manual 2.5 CONTROL REGISTERS
- http://www.intel.com/Assets/PDF/manual/253668.pdf
- OSXSAVE
 XSAVE and Processor Extended States-Enable Bit (bit 18 of CR4) — When set, this flag: (1) indicates (via CPUID.01H:ECX.OSXSAVE[bit 27]) that the operating system supports the use of the XGETBV, XSAVE and XRSTOR instructions by general software; (2) enables the XSAVE and XRSTOR instructions to save and restore the x87 FPU state (including MMX registers), the SSE state (XMM registers and MXCSR), along with other processor extended states enabled in the XFEATURE_ENABLED_MASK register (XCR0); (3) enables the processor to execute XGETBV and XSETBV instructions in order to read and write XCR0. See Section 2.6 and Chapter 13, “System Programming for Instruction Set Extensions and Processor Extended States”.

기존의 Windows에서는 대부분 15~31 bit를 Reserved로 사용하고 있었지만 최근의 Intel Manual를 참고하시면 15~31 bit 에 대해서 Reserved 되지 않은 영역이 있는것을 보실수 있습니다. 기존에 코드가 만약 상위 Bit를 Reserved로 생각하고 작성되어 있다면 이제는 바꿀 시기가 온거죠 !!

혹시나 관련 문제가 생긴다면 참고하시길 …

Enjoy Debugging

Message Hook Chain을 구하는 방법

Icesword라는 프로그램을 보면 Message Hook Chain을 구하는 기능을 가지고 있습니다. Message Hooking시 타모듈과의 충돌을 분석할때 유용하게 사용하곤합니다. 그렇다면 과연 이러한 Message Hook chain은 어디에 등록되어 있을까 ?

간단히 Win32 Thread의 Teb를 확인하면 추적이 가능합니다.

0: kd> !process 857295a0 3
PROCESS 857295a0 SessionId: 0 Cid: 0788 Peb: 7ffdd000 ParentCid: 06c4
DirBase: 064001e0 ObjectTable: e17d5a30 HandleCount: 45.
Image: notepad.exe
VadRoot 858351f0 Vads 67 Clone 0 Private 202. Modified 17. Locked 0.
DeviceMap e190da40
Token e1f29d48
ElapsedTime 00:00:03.062
UserTime 00:00:00.015
KernelTime 00:00:00.078
QuotaPoolUsage[PagedPool] 63204
QuotaPoolUsage[NonPagedPool] 2680
Working Set Sizes (now,min,max) (926, 50, 345) (3704KB, 200KB, 1380KB)
PeakWorkingSetSize 931
VirtualSize 31 Mb
PeakVirtualSize 36 Mb
PageFaultCount 1007
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 468

THREAD 85775518 Cid 0788.054c Teb: 7ffdf000 Win32Thread: e1ff3008 WAIT: (WrUserRequest) UserMode Non-Alertable
84976d98 SynchronizationEvent

일반적인 Notepad의 Process와 Thread입니다. 이 중에서 우리에게 필요한 부분인 Message Hook Chain에 대한 정보는 Thread의 TEB에 포함되어 있습니다.

0: kd> .process 857295a0
Implicit process is now 857295a0

0: kd> dt _TEB 7ffdf000
ntdll!_TEB
   +0×000 NtTib            : _NT_TIB
   +0×01c EnvironmentPointer : (null)
   +0×020 ClientId         : _CLIENT_ID
   +0×028 ActiveRpcHandle  : (null)
   +0×02c ThreadLocalStoragePointer : (null)
   +0×030 ProcessEnvironmentBlock : 0×7ffdd000 _PEB
   +0×034 LastErrorValue   : 0
   +0×038 CountOfOwnedCriticalSections : 0
   +0×03c CsrClientThread  : (null)
   +0×040 Win32ThreadInfo  : 0xe1ff3008
   +0×044 User32Reserved   : [26] 0
   +0×0ac UserReserved     : [5] 0
   +0×0c0 WOW32Reserved    : (null)
   +0×0c4 CurrentLocale    : 0×412
   +0×0c8 FpSoftwareStatusRegister : 0
   +0×0cc SystemReserved1  : [54] (null)
   +0×1a4 ExceptionCode    : 0
   +0×1a8 ActivationContextStack : _ACTIVATION_CONTEXT_STACK
 … 생략

Thread TEB를 확인하면 Win32ThreadInfo라는 녀석이 존재합니다.  기본적으로  PVOID 형을 가지고 있는데 물론 Undocument 된 부분이라 이렇게 표시 되죠 .
Win32ThreadInfo의 메모리에 있는 데이터는 MessageQueue, KeyboardLayout, Desktop, DesktopInfo, WindowList 등 Win32를 UI를 구동하는데 필요한 데이터들을 포함하고 있습니다.
그리고 Global Message Hook과 Local Message Hook에 대한 정보는 Win32ThreadInfo,  DesktopInfo 정보를 통해서 추적이 가능합니다.
0: kd> dt finter!_THREADINFO 0xe1ff3008
   +0×000 W32Thread        : W32THREAD
   +0×028 ptl              : (null)
   +0×02c ppi              : 0xe10531c8
   +0×030 pq               : 0xe1e4a9e8 _Q
   +0×034 spklActive       : 0xe147db58
   +0×038 pcti             : 0xbc638820
   +0×03c rpdesk           : 0×858afe88
   +0×040 pDeskInfo        : 0xbc630650 _DESKTOPINFO
   +0×044 pClientInfo      : 0×7ffdf6cc
   +0×048 TIF_flags        : 0×1100000
   +0×04c pstrAppName      : (null)
   +0×050 psmsSent         : (null)
   +0×054 psmsCurrent      : (null)
   +0×058 psmsReceiveList  : (null)
   +0×05c timeLast         : 2543531
   +0×060 idLast           : 0xe11bab48
   +0×064 cQuit            : 0
   +0×064 exitCode         : 0
   +0×068 hdesk            : 0×0000002c
   +0×06c cPaintsReady     : 0
   +0×070 cTimersReady     : 0
   +0×074 pMenuState       : (null)
   +0×078 ptdb             : (null)
   +0×078 pwinsta          : (null)
   +0×07c psiiList         : (null)
   +0×080 dwExpWinVer      : 0×400
   +0×084 dwCompatFlags    : 0
   +0×088 dwCompatFlags2   : 0
… 생략
   +0×0e0 fsReserveKeys    : 0
   +0×0e4 apEvent          : (null)
   +0×0e8 amdesk           : 0xf01ff
   +0×0ec cWindows         : 6
   +0×0f0 cVisWindows      : 0
   +0×0f4 aphkStart        : [16] (null)

간단히 정리한 구조체를 이용해서 Win32ThreadInfo의 데이터를 확인해 봤습니다. 이 중 _DESKTOPINFO의 값을 다시 확인해보죠

0: kd> dt _DESKTOPINFO 0xbc630650
finter!_DESKTOPINFO
   +0×000 pvDesktopBase    : 0xbc630000
   +0×004 pvDesktopLimit   : 0xbc930000
   +0×008 spwnd            : 0xbc6306e8
   +0×00c fsHooks          : 0×850
   +0×010 aphkStart        : [16] (null)
   +0×050 spwndShell       : 0xbc63ead8
   +0×054 ppiShellProcess  : 0xe1956448
   +0×058 spwndBkGnd       : 0xbc63f2e0
   +0×05c spwndTaskman     : 0xbc63e548
   +0×060 spwndProgman     : (null)
   +0×064 pvwplShellHook   : 0xe1ce8ea0
   +0×068 cntMBox          : 0

Win32ThreadInfo의 aphkStart Member는 Local Hook의 데이터를 나타내는 Array고 DesktopInfo의 aphkStart Member는 Global Hook의 데이터를 나타내는 Arrary 입니다. 각각 Array의 인자는 HOOK Structure를 나타내며 각 Index는 Hooking Type을 나타내도록 구성됩니다.
이제 이 Array 안의 데이터를 확인해보겠습니다.

0: kd> dps 0xe1ff3008+0xf4 L16
e1ff30fc  00000000
e1ff3100  00000000
e1ff3104  00000000
e1ff3108  bc636de0
e1ff310c  00000000
e1ff3110  00000000
e1ff3114  00000000
e1ff3118  00000000
e1ff311c  bc636e20
e1ff3120  00000000
e1ff3124  00000000
e1ff3128  00000000
e1ff312c  00000000
e1ff3130  00000000
e1ff3134  00000000
e1ff3138  00000000
e1ff313c  00000000
e1ff3140  00000000
e1ff3144  00000000
e1ff3148  00000000
e1ff314c  00000000
e1ff3150  00000000

0: kd> dps 0xbc630650+0×10 L16
bc630660  00000000
bc630664  00000000
bc630668  00000000
bc63066c  00000000
bc630670  bc640530
bc630674  00000000
bc630678  bc640570
bc63067c  00000000
bc630680  00000000
bc630684  00000000
bc630688  00000000
bc63068c  bc6404f0
bc630690  00000000
bc630694  00000000
bc630698  00000000
bc63069c  00000000
bc6306a0  bc63ead8
bc6306a4  e1956448
bc6306a8  bc63f2e0
bc6306ac  bc63e548
bc6306b0  00000000
bc6306b4  e1ce8ea0
0: kd> dt _HOOK bc636e20
npkfinder!_HOOK
   +0×000 head             : _THRDESKHEAD
   +0×014 phkNext          : (null)
   +0×018 iHook            : 7
   +0×01c offPfn           : 0×0000ff89
   +0×020 flags            : 2
   +0×024 ihmod            : 1
   +0×028 ptiHooked        : 0xe1ff3008 _THREADINFO
   +0×02c rpdesk           : (null)
이 중 하나를 열어서 보면 위와 같은 구조로 이루어져 있습니다. phkNexe 인자는 다음 Hook Chain을 가르키는 인자인데 현재는 하나의 Hooking Function만이 등록되어 있는 상태군요 .

IceSword의 경우는 이러한 원리( ?? ) 를 이용해서 아마도 Hook Chain을 보여주는것 같습니다.  위에 설명한  Hook Chain를 잘이용하면 아래와 같은 샘플도 만들수 있죠. ( 샘플소스는 개인적으로 문의해주세요 …)

조금이나마 도움이 되셨으면합니다.

Enjoy Debugging…

[x64] 64bit Vista 환경에서의 Inline Hook에 어려움 ( Relative Address의 압박 )

32bit 환경에서 API Inline Hooking을 할 경우 상위 5Byte 또는 6Byte를 교체하여 Jmp Code를 만들어주고 Trampoline Function을 통해서 원본 코드를 실행하여 동작하도록 많이 하고 있습니다. ( 보통은 Detour Library를 사용하지요.  ) 실제로 코드를 보면 Hooking에 사용되는 상위 Byte는 대부분 그 Function의 Prologue에 해당하는 부분이지요. 하지만 64bit환경에서는 얘기가 조금 다릅니다. 32bit환경과 달리 64bit 환경에서는 Function 상위에 Prologue가 존재하지 않기 때문입니다. 가장 큰 문제가 되는 부분은 Function의 상위에 Relative Address를 사용하는 Instruction이 존재할 수 있다는 점이죠. 간단한 예를 들어보죠

lkd> u nt!IofCallDriver
nt!IofCallDriver:
fffff800`01c595e0 4883ec28        sub     rsp,28h
fffff800`01c595e4 488b05f50c1a00  mov     rax,qword ptr [nt!pIofCallDriver (fffff800`01dfa2e0)]
fffff800`01c595eb 4885c0          test    rax,rax
fffff800`01c595ee 0f85d8090600    jne     nt! ?? ::FNODOBFM::`string’+0×11a60 (fffff800`01cb9fcc)
fffff800`01c595f4 804243ff        add     byte ptr [rdx+43h],0FFh
fffff800`01c595f8 384243          cmp     byte ptr [rdx+43h],al
fffff800`01c595fb 0f8ed7090600    jle     nt! ?? ::FNODOBFM::`string’+0×11a6c (fffff800`01cb9fd8)
fffff800`01c59601 488b82b8000000  mov     rax,qword ptr [rdx+0B8h]

가장 많이 사용하고 있는 IofCallDriver 함수 입니다. 특이한 점은 함수 상위에 Relative Address를 사용하는 Instruction이 있다는 것이죠 .  위와 같은 경우 일반적인 Inline Hooking을 했을때 Trampoline함수에서 문제가 발생할 수 있습니다.  이런 부분은 좀더 고민해서 64bit 환경 Hooking을 구현해야 할 것으로 생각됩니다. ( 물론 x64 Vista환경에서 Patch Guard때문에 IofCallDriver를 Hooking 못할 꺼라 생각 할 수 있지만 실제로 DPC 를 Hooking 해서 Patch Guard 관련 함수를 Disable 하도록 Kernel patch를 하면 가능하긴 합니다. )

참고로 Relative Address의 경우 RIP를 통해서 Address를 연산해 냅니다.
예 )  32bit Operland + RIP = Virtual Address
lkd> ? fffff800`01c595e4+001a0cf5+7
Evaluate expression: -8796061588768 = fffff800`01dfa2e0

[Blogging] PAGED_CODE(), Spin Lock

견우님 블러그에 갔다가 재미 있는 내용을 읽었습니다. PAGED_CODE() mecro를 사용하게 되면 Driver Code를 pagedpool에 올려 놓게 되지요. 그럼 Spin Lock과 이게 무슨 관계일까 ?? 개인적으로는 PAGED_CODE Mecro를 잘 쓰지 않아 좀처럼 볼수 없는 현상인데 견우님이 Blog에 이 둘의 관계에서 발생하는 재미 있는 현상에 관해 써주셨군요

http://cjhnim.egloos.com/3829482

리플에 질럿님이 써주진 이야기가 맞는것 같습니다.

PAGED_CODE()를 이용해서 PagedPool로 내려 간것이 아닌듯 싶내요.

일단 메모리 상주관련해서 #pragma 부분을 체크해봐야할듯 .. 또는 static 여부를 확인해봐야할듯…

[blogging] Desktop Heap Overview

드라이버 온라인에 Jeff 님이 굉장히 좋은 글을 번역해 주셨습니다. Desktop Heap이 무엇이가 또 Desktop Heap으로 장해가 발생할 수 있는 상황에는 어떤 것이 있는가에 대한 내용이내요.

원문 : http://blogs.msdn.com/ntdebugging/archive/2007/01/04/desktop-heap-overview.aspx
번역 : http://www.driveronline.org/bbs/view.asp?tb=systembbs&no=126

이런 좋은 글을 읽을때 마다 항상 즐겁군요