Tag Archive for 'KiUserExceptionDispatcher'

[NT Inside Study] Kernel To User Callback 3 - KiUserExceptionDispatcher

KiUserExceptionDispatcher 은 UserMode에서 Exception이 발생했을때 실행되는 Callback 입니다. KiUserExceptionDispatcher의 실행은 IDT -> KiTrapXX ->CommonDispatchException -> KiDispatchException -> KiUserExceptionDispatcher 와 같은 Flow를 지닙니다. 

lkd> uf nt!CommonDispatchEsception
... 중략
nt!CommonDispatchException+0x3e:
804e03f4 83e001 and eax,1
804e03f7 6a01 push 1
804e03f9 50 push eax
804e03fa 55 push ebp
804e03fb 6a00 push 0
804e03fd 51 push ecx
804e03fe e89ac70100 call nt!KiDispatchException (804fcb9d)
804e0403 8be5 mov esp,ebp
804e0405 e91ffeffff jmp nt!Kei386EoiHelper (804e0229

KiDispatcheException는 발생한 Exception을 User Mode 와 Kernel Mode 로 분해 하여 Dispatch 합니다. 또한 User Level에서 사용하는 RaiseException Function 같은 경우도 내부적으로 KiDispatcherException을 사용하여 Exception을 Dispatch 합니다.

lkd> uf nt!KiDispatchException
...
// KernelMode Exception, UserMode Exception
nt!KiDispatchException+0×101:
804fcc34 807d1400 cmp byte ptr [ebp+14h],0

804fcc38 0f8524a30000 jne nt!KiDispatchException+0×16c (80506f62)

KernelMode Exception일 경우

nt!KiDispatchException+0x107:
804fcc3e 807d1801 cmp byte ptr [ebp+18h],1
804fcc42 0f8592720200 jne nt!KiDispatchException+0×142 (80523eda)
nt!KiDispatchException+0x10d:
804fcc48 a164345680 mov eax,dword ptr [nt!KiDebugRoutine (80563464)]
804fcc4d 3bc7 cmp eax,edi
804fcc4f 0f84b1680100 je nt!KiDispatchException+0×131 (80513506)

nt!KiDispatchException+0×116:
804fcc55 57 push edi
804fcc56 57 push edi
804fcc57 8d8d18fdffff lea ecx,[ebp-2E8h]
804fcc5d 51 push ecx
804fcc5e 56 push esi
804fcc5f ffb510fdffff push dword ptr [ebp-2F0h]
804fcc65 53 push ebx
804fcc66 ffd0 call eax
804fcc68 84c0 test al,al
804fcc6a 0f8496680100 je nt!KiDispatchException+0×131 (80513506)

nt!KiDispatchException+0×131:
80513506 8d8518fdffff lea eax,[ebp-2E8h]
8051350c 50 push eax
8051350d 56 push esi
8051350e e805befeff call nt!RtlDispatchException (804ff318)
80513513 e9ba090100 jmp nt!KiDispatchException+0×13e (80523ed2)
… 중략

UserMode Exception일 경우
nt!KiDispatchException+0x16c:
80506f62 807d1801 cmp byte ptr [ebp+18h],1 // Is FirstCance
80506f66 0f8544d00100 jne nt!KiDispatchException+0×374 (80523fb0)
nt!KiDispatchException+0x176:
80506f6c 393d64345680 cmp dword ptr [nt!KiDebugRoutine (80563464)],edi
80506f72 7436 je nt!KiDispatchException+0×1eb (80506faa)

nt!KiDispatchException+0×1eb:
80506faa 57 push edi
80506fab 6a01 push 1
80506fad 56 push esi
80506fae e8e2d20700 call nt!DbgkForwardException (80584295) // Debug Port 또는 Subsystem Exception Port 로 Forward
80506fb3 84c0 test al,al
80506fb5 0f85d15cffff jne nt!KiDispatchException+0×1db (804fcc8c)

nt!KiDispatchException+0×1f8:
80506fbb 89bd60fcffff mov dword ptr [ebp-3A0h],edi
80506fc1 897dfc mov dword ptr [ebp-4],edi
80506fc4 837b7823 cmp dword ptr [ebx+78h],23h
80506fc8 0f8553cf0100 jne nt!KiDispatchException+0×20d (80523f21)

nt!KiDispatchException+0×207:
80506fce f6437202 test byte ptr [ebx+72h],2
80506fd2 0f8549cf0100 jne nt!KiDispatchException+0×20d (80523f21)

nt!KiDispatchException+0×22f:
80506fd8 b8cc020000 mov eax,2CCh
80506fdd 898504fdffff mov dword ptr [ebp-2FCh],eax
80506fe3 8bbddcfdffff mov edi,dword ptr [ebp-224h]
80506fe9 83e7fc and edi,0FFFFFFFCh
80506fec 2bf8 sub edi,eax
80506fee 89bd0cfdffff mov dword ptr [ebp-2F4h],edi
80506ff4 6a04 push 4
80506ff6 50 push eax
80506ff7 57 push edi
80506ff8 e8f4880600 call nt!ProbeForWrite (8056f8f1)
80506ffd b9b3000000 mov ecx,0B3h
80507002 8db518fdffff lea esi,[ebp-2E8h]
80507008 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
8050700a 8b8514fdffff mov eax,dword ptr [ebp-2ECh]
80507010 8b7010 mov esi,dword ptr [eax+10h]
80507013 8d34b517000000 lea esi,[esi*4+17h]
8050701a 83e6fc and esi,0FFFFFFFCh
8050701d 89b504fdffff mov dword ptr [ebp-2FCh],esi
80507023 8bbd0cfdffff mov edi,dword ptr [ebp-2F4h]
80507029 2bfe sub edi,esi
8050702b 89bd00fdffff mov dword ptr [ebp-300h],edi
80507031 6a04 push 4
80507033 8d4608 lea eax,[esi+8]
80507036 50 push eax
80507037 8d47f8 lea eax,[edi-8]
8050703a 50 push eax
8050703b e8b1880600 call nt!ProbeForWrite (8056f8f1)
80507040 8bce mov ecx,esi
80507042 8bb514fdffff mov esi,dword ptr [ebp-2ECh]
80507048 8bc1 mov eax,ecx
8050704a c1e902 shr ecx,2
8050704d f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
8050704f 8bc8 mov ecx,eax
80507051 83e103 and ecx,3
80507054 f3a4 rep movs byte ptr es:[edi],byte ptr [esi]
80507056 8b8d0cfdffff mov ecx,dword ptr [ebp-2F4h]
8050705c 8b8500fdffff mov eax,dword ptr [ebp-300h]
80507062 8948fc mov dword ptr [eax-4],ecx
80507065 8d50f8 lea edx,[eax-8]
80507068 8902 mov dword ptr [edx],eax
8050706a 6a20 push 20h
8050706c 53 push ebx
8050706d e8971ffeff call nt!KiSegSsToTrapFrame (804e9009)
80507072 52 push edx
80507073 53 push ebx
80507074 e8db1ffeff call nt!KiEspToTrapFrame (804e9054)
80507079 8b4514 mov eax,dword ptr [ebp+14h]
8050707c 8ac8 mov cl,al
8050707e f6d9 neg cl
80507080 1bc9 sbb ecx,ecx
80507082 83e103 and ecx,3
80507085 83c118 add ecx,18h
80507088 894b6c mov dword ptr [ebx+6Ch],ecx
8050708b 8ac8 mov cl,al
8050708d f6d9 neg cl
8050708f 1bc9 sbb ecx,ecx
80507091 83e103 and ecx,3
80507094 83c120 add ecx,20h
80507097 894b38 mov dword ptr [ebx+38h],ecx
8050709a 894b34 mov dword ptr [ebx+34h],ecx
8050709d f6d8 neg al
8050709f 1bc0 sbb eax,eax
805070a1 83e003 and eax,3
805070a4 83c038 add eax,38h
805070a7 894350 mov dword ptr [ebx+50h],eax
805070aa 83633000 and dword ptr [ebx+30h],0
805070ae a170345680 mov eax,dword ptr [nt!KeUserExceptionDispatcher (80563470)]
805070b3 894368 mov dword ptr [ebx+68h],eax
805070b6 834dfcff or dword ptr [ebp-4],0FFFFFFFFh
805070ba e9cd5bffff jmp nt!KiDispatchException+0×1db (804fcc8c)

nt!KiDispatchException는 KernelMode일 경우 RtlDispatchException을 수행하여 BugCheck를 발생시키고 UserMode일 경우 UserMode Statck을 조작하여 KeUserExceptionDispatcher를 발생시켜 줍니다. 이러한 과정을 거치면서 UserMode에서 아래와 같은 스택이 완성됩니다.


00 0013ff28 00412da8 00400000 00000000 00020934 ntdll!KiUserExceptionDispatcher (FPO: [2,0,0]) (CONTEXT @ 0013fb64)
01 0013ff28 004144cf 00400000 00000000 00020934 ExceptionTest!wWinMain+0×68 (FPO: [Non-Fpo]) (CONV: stdcall) [e:\per\exceptiontest\exceptiontest\exceptiontest.cpp @ 28]
02 0013ffc0 7c816fd7 019bf6f2 019bf766 7ffd4000 ExceptionTest!__tmainCRTStartup+0×176 (FPO: [Non-Fpo]) (CONV: cdecl) [f:\sp\vctools\crt_bld\self_x86\crt\src\crt0.c @ 324]
03 0013fff0 00000000 00411de8 00000000 78746341 kernel32!BaseProcessStart+0×23 (FPO: [Non-Fpo])

KiUserExceptionDispatcher는 Exception이 발생했을때 종종 스택상에서 나타 나며 Kernel Debugging 시에 User Exception이 발생하게 되면 스택상에 나타나게 됩니다.  ( Kernel Debugging시에는  KiUserExceptionDispatcher는 보이지만 그외의 Kernel Stack 들이 보이지 않는 경우도 있으니 참고하시길… )

[NT Inside Study] Kernel To User Callback Function의 Address는 어디에 가지고 있나 ??

아래의 3가지 Function은 Kernel To User Callback을 대표하는 함수 입니다. 그러면 이 녀석들의 Address는 Kernel의 어디에서 들고 있을까 ?

7c93ead0 ntdll!KiUserCallbackDispatcher = <no type information>
7c93eac0 ntdll!KiUserApcDispatcher = <no type information>
7c93eaec ntdll!KiUserExceptionDispatcher = <no type information>

간단히 nt Symbol에서 확인이 가능합니다.

lkd> X nt!KeUser*
80563474 nt!KeUserCallbackDispatcher = <no type information>
80563478 nt!KeUserApcDispatcher = <no type information>
805701cc nt!KeUserModeCallback = <no type information>
80563470 nt!KeUserExceptionDispatcher = <no type information>

 커널쪽 심볼중 이름이 비슷한 세녀석이 있지요. 실제로 이 세녀석의 Memory를 열어 보면 User Mode Callback의 Address가 담겨 있는것을 확인 할 수가 있습니다.

lkd> dd 80563470
80563470 7c93eaec 7c93ead0 7c93eac0 00002626
80563480 00000000 00000000 00000000 00000000
80563490 00000000 00000000 00000000 00000000
805634a0 00000000 00000000 00000000 00000000
805634b0 00000000 00000000 00000000 00000000
805634c0 804e68b0 00000000 0000011c 80519fc4
805634d0 bf999980 00000000 0000029b bf99a690
805634e0 00000000 00000000 00000000 00000000

User Callback Function 세녀석의 주소가 나란히 저장되어 있는것을 확인할 수 가 있습니다.