Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html
用户APC的执行过程
一、一个启发式问题
有一个问题,线程什么时候检查自己的APC队列,答案前面已经介绍过,是执行KiServerExit函数时。
KiServiceExit函数:这个函数是系统调用、异常或中断的必经之路。
也就是说:当线程发现自己有APC要执行时,已经处于内核了,我们在系统调用那一节介绍过,从三环到零环,将数据保存在 _KTRAP_FRAME 结构体中。
现在,我们发现有用户APC要执行,肯定要返回三环,肯定也需要借助 _KTRAP_FRAME 结构体。
但是,_KTRAP_FRAME结构体保存着是原先的三环地址,返回绝对不可能返回到那里去,一定返回另外一个地方。
可一个线程只有一个_KTRAP_FRAME,返回只能通过这个返回。
因此,我们真正要做的:将原来的_KTRAP_FRAME结构体保存起来,之后建立一个新的,往里面写入返回时执行的ESP(栈地址)与EIP(代码地址),之后返回三环执行。
执行完之后返回到零环,继续执行原来的任务。(如果搞懂这一点,那么用户APC的执行过程已经解决一大半了!)
二、用户APC过程分析:
由于分析量大,代码繁杂,直接整理成图标的形式展现出来,最后附带反汇编代码可以自己观看。
三、反汇编代码
1. KiserviceExit(ntkrnlpa.exe)代码分析
1 :004667F0 _KiServiceExit2 proc near ; CODE XREF: NtContinue(x,x)+3A↓j 2 .text:004667F0 ; NtRaiseException(x,x,x)+3C↓j ... 3 .text:004667F0 4 .text:004667F0 arg_C = dword ptr 10h 5 .text:004667F0 arg_10 = dword ptr 14h 6 .text:004667F0 arg_38 = dword ptr 3Ch 7 .text:004667F0 arg_3C = dword ptr 40h 8 .text:004667F0 arg_40 = dword ptr 44h 9 .text:004667F0 arg_44 = dword ptr 48h 10 .text:004667F0 arg_48 = dword ptr 4Ch 11 .text:004667F0 arg_60 = dword ptr 64h 12 .text:004667F0 arg_64 = dword ptr 68h 13 .text:004667F0 arg_68 = dword ptr 6Ch 14 .text:004667F0 arg_6C = dword ptr 70h 15 .text:004667F0 16 .text:004667F0 cli 17 .text:004667F1 test dword ptr [ebp+70h], 20000h 18 .text:004667F8 jnz short loc_466800 ; 获取Kthread 19 .text:004667FA test byte ptr [ebp+6Ch], 1 20 .text:004667FE jz short loc_466834 21 .text:00466800 22 .text:00466800 loc_466800: ; CODE XREF: _KiServiceExit2+8↑j 23 .text:00466800 ; _KiServiceExit2+41↓j 24 .text:00466800 mov ebx, ds:0FFDFF124h ; 获取Kthread 25 .text:00466806 mov byte ptr [ebx+2Eh], 0 26 .text:0046680A cmp byte ptr [ebx+4Ah], 0 ; 判断是否有用户APC请求 27 .text:0046680E jz short loc_466834 ; 如果有APC请求则不会跳转 28 .text:00466810 mov ebx, ebp 29 .text:00466812 mov ecx, 1 ; NewIrql 30 .text:00466817 call ds:__imp_@KfRaiseIrql@4 ; KfRaiseIrql(x) 31 .text:0046681D push eax 32 .text:0046681E sti 33 .text:0046681F push ebx 34 .text:00466820 push 0 35 .text:00466822 push 1 ; 这里处理用户层的APC函数 36 .text:00466824 call _KiDeliverApc@12 ; 该函数实现对APC的处理 37 .text:00466829 pop ecx ; NewIrql 38 .text:0046682A call ds:__imp_@KfLowerIrql@4 ; KfLowerIrql(x) 39 .text:00466830 cli 40 .text:00466831 jmp short loc_466800 ; 获取Kthread 41 .text:00466831 ; --------------------------------------------------------------------------- 42 .text:00466833 db 90h 43 .text:00466834 ; --------------------------------------------------------------------------- 44 .text:00466834 45 .text:00466834 loc_466834: ; CODE XREF: _KiServiceExit2+E↑j 46 .text:00466834 ; _KiServiceExit2+1E↑j 47 .text:00466834 mov edx, [esp+arg_48] 48 .text:00466838 mov ebx, large fs:50h 49 .text:0046683F mov large fs:0, edx 50 .text:00466846 mov ecx, [esp+arg_44] 51 .text:0046684A mov esi, large fs:124h 52 .text:00466851 mov [esi+140h], cl 53 .text:00466857 test ebx, 0FFh 54 .text:0046685D jnz short loc_4668B0 55 .text:0046685F 56 .text:0046685F loc_46685F: ; CODE XREF: _KiServiceExit2+D0↓j 57 .text:0046685F ; _KiServiceExit2+FB↓j 58 .text:0046685F test [esp+arg_6C], 20000h 59 .text:00466867 jnz loc_466FD4 60 .text:0046686D test word ptr [esp+arg_68], 0FFF8h 61 .text:00466874 jz short loc_4668F0 62 .text:00466876 mov edx, [esp+arg_38] 63 .text:0046687A mov ecx, [esp+arg_3C] 64 .text:0046687E mov eax, [esp+arg_40] 65 .text:00466882 cmp word ptr [ebp+6Ch], 8 66 .text:00466887 jz short loc_466895 67 .text:00466889 lea esp, [ebp+30h] 68 .text:0046688C pop gs 69 .text:0046688E pop es 70 .text:0046688F pop ds 71 .text:00466890 lea esp, [ebp+50h] 72 .text:00466893 pop fs 73 .text:00466895 74 .text:00466895 loc_466895: ; CODE XREF: _KiServiceExit2+97↑j 75 .text:00466895 lea esp, [ebp+54h] 76 .text:00466898 pop edi 77 .text:00466899 pop esi 78 .text:0046689A pop ebx 79 .text:0046689B pop ebp 80 .text:0046689C cmp word ptr [esp-60h+arg_64], 80h 81 .text:004668A3 ja loc_466FF0 82 .text:004668A9 add esp, 4 83 .text:004668AC iret 84 .text:004668AC ; --------------------------------------------------------------------------- 85 .text:004668AD db 8Dh 86 .text:004668AE db 49h ; I 87 .text:004668AF db 0 88 .text:004668B0 ; --------------------------------------------------------------------------- 89 .text:004668B0 90 .text:004668B0 loc_4668B0: ; CODE XREF: _KiServiceExit2+6D↑j 91 .text:004668B0 test dword ptr [ebp+70h], 20000h 92 .text:004668B7 jnz short loc_4668C2 93 .text:004668B9 test dword ptr [ebp+6Ch], 1 94 .text:004668C0 jz short loc_46685F 95 .text:004668C2 96 .text:004668C2 loc_4668C2: ; CODE XREF: _KiServiceExit2+C7↑j 97 .text:004668C2 xor ebx, ebx 98 .text:004668C4 mov esi, [ebp+18h] 99 .text:004668C7 mov edi, [ebp+1Ch] 100 .text:004668CA mov dr7, ebx 101 .text:004668CD mov dr0, esi 102 .text:004668D0 mov ebx, [ebp+20h] 103 .text:004668D3 mov dr1, edi 104 .text:004668D6 mov dr2, ebx 105 .text:004668D9 mov esi, [ebp+24h] 106 .text:004668DC mov edi, [ebp+28h] 107 .text:004668DF mov ebx, [ebp+2Ch] 108 .text:004668E2 mov dr3, esi 109 .text:004668E5 mov dr6, edi 110 .text:004668E8 mov dr7, ebx 111 .text:004668EB jmp loc_46685F 112 .text:004668F0 ; --------------------------------------------------------------------------- 113 .text:004668F0 114 .text:004668F0 loc_4668F0: ; CODE XREF: _KiServiceExit2+84↑j 115 .text:004668F0 mov ebx, [esp+arg_C] 116 .text:004668F4 mov [esp+arg_68], ebx 117 .text:004668F8 mov ebx, [esp+arg_10] 118 .text:004668FC sub ebx, 0Ch 119 .text:004668FF mov [esp+arg_60], ebx 120 .text:00466903 mov esi, [esp+arg_6C] 121 .text:00466907 mov [ebx+8], esi 122 .text:0046690A mov esi, [esp+arg_68] 123 .text:0046690E mov [ebx+4], esi 124 .text:00466911 mov esi, [esp+arg_64] 125 .text:00466915 mov [ebx], esi 126 .text:00466917 mov eax, [esp+arg_40] 127 .text:0046691B mov edx, [esp+arg_38] 128 .text:0046691F mov ecx, [esp+arg_3C] 129 .text:00466923 add esp, 54h 130 .text:00466926 pop edi 131 .text:00466927 pop esi 132 .text:00466928 pop ebx 133 .text:00466929 pop ebp 134 .text:0046692A mov esp, [esp-64h+arg_60] 135 .text:0046692D iret 136 .text:0046692D _KiServiceExit2 endp ; sp-analysis failed
2. KiDeliverApc(ntkrnlpa.exe)代码分析
1 ; __stdcall KiDeliverApc(x, x, x) 2 .text:00426A2E public _KiDeliverApc@12 3 .text:00426A2E _KiDeliverApc@12 proc near ; CODE XREF: KiSwapThread()+5F↓p 4 .text:00426A2E ; _KiSystemService+21B↓p ... 5 .text:00426A2E 6 .text:00426A2E LockHandle = _KLOCK_QUEUE_HANDLE ptr -28h 7 .text:00426A2E var_1C = dword ptr -1Ch 8 .text:00426A2E BugCheckParameter1= dword ptr -18h 9 .text:00426A2E var_14 = dword ptr -14h 10 .text:00426A2E var_10 = dword ptr -10h 11 .text:00426A2E var_C = dword ptr -0Ch 12 .text:00426A2E var_8 = dword ptr -8 13 .text:00426A2E var_4 = dword ptr -4 14 .text:00426A2E arg_0 = byte ptr 8 15 .text:00426A2E arg_4 = dword ptr 0Ch 16 .text:00426A2E arg_8 = dword ptr 10h 17 .text:00426A2E 18 .text:00426A2E mov edi, edi 19 .text:00426A30 push ebp 20 .text:00426A31 mov ebp, esp 21 .text:00426A33 sub esp, 28h 22 .text:00426A36 mov ecx, [ebp+arg_8] 23 .text:00426A39 test ecx, ecx 24 .text:00426A3B jz short loc_426A54 25 .text:00426A3D mov edx, [ecx+68h] 26 .text:00426A40 mov eax, offset _ExpInterlockedPopEntrySListResume@0 ; ExpInterlockedPopEntrySListResume() 27 .text:00426A45 cmp edx, eax 28 .text:00426A47 jb short loc_426A54 29 .text:00426A49 cmp edx, offset _ExpInterlockedPopEntrySListEnd@0 ; ExpInterlockedPopEntrySListEnd() 30 .text:00426A4F ja short loc_426A54 31 .text:00426A51 mov [ecx+68h], eax 32 .text:00426A54 33 .text:00426A54 loc_426A54: ; CODE XREF: KiDeliverApc(x,x,x)+D↑j 34 .text:00426A54 ; KiDeliverApc(x,x,x)+19↑j ... 35 .text:00426A54 push ebx 36 .text:00426A55 push esi 37 .text:00426A56 push edi 38 .text:00426A57 mov eax, large fs:124h 39 .text:00426A5D mov esi, eax 40 .text:00426A5F mov eax, [esi+134h] 41 .text:00426A65 mov [ebp+var_1C], eax 42 .text:00426A68 mov eax, [esi+44h] 43 .text:00426A6B mov [esi+134h], ecx 44 .text:00426A71 lea ecx, [esi+0E8h] ; SpinLock 45 .text:00426A77 lea edx, [ebp+LockHandle] ; LockHandle 46 .text:00426A7A mov [ebp+BugCheckParameter1], eax 47 .text:00426A7D call ds:__imp_@KeAcquireInStackQueuedSpinLock@8 ; KeAcquireInStackQueuedSpinLock(x,x) 48 .text:00426A83 mov byte ptr [esi+49h], 0 49 .text:00426A87 lea ebx, [esi+34h] ; 取内核APC列表(双向链表 第一个内核 第二个用户) 50 .text:00426A8A jmp loc_426B70 ; 判断第一个链表是否为空,如果内核与当前地址一样,说明没有内核APC函数。 51 .text:00426A8F ; --------------------------------------------------------------------------- 52 .text:00426A8F 53 .text:00426A8F loc_426A8F: ; CODE XREF: KiDeliverApc(x,x,x)+144↓j 54 .text:00426A8F mov eax, [ebx] 55 .text:00426A91 lea edi, [eax-0Ch] 56 .text:00426A94 mov ecx, [edi+14h] 57 .text:00426A97 mov [ebp+var_14], ecx 58 .text:00426A9A mov ecx, [edi+1Ch] 59 .text:00426A9D test ecx, ecx 60 .text:00426A9F mov [ebp+var_4], ecx 61 .text:00426AA2 mov edx, [edi+20h] 62 .text:00426AA5 mov [ebp+var_10], edx 63 .text:00426AA8 mov edx, [edi+24h] 64 .text:00426AAB mov [ebp+var_C], edx 65 .text:00426AAE mov edx, [edi+28h] 66 .text:00426AB1 mov [ebp+var_8], edx 67 .text:00426AB4 jnz short loc_426AF2 68 .text:00426AB6 mov ecx, [eax] 69 .text:00426AB8 mov eax, [eax+4] 70 .text:00426ABB mov [eax], ecx 71 .text:00426ABD mov [ecx+4], eax 72 .text:00426AC0 lea ecx, [ebp+LockHandle] ; LockHandle 73 .text:00426AC3 mov byte ptr [edi+2Eh], 0 74 .text:00426AC7 call ds:__imp_@KeReleaseInStackQueuedSpinLock@4 ; KeReleaseInStackQueuedSpinLock(x) 75 .text:00426ACD lea eax, [ebp+var_8] 76 .text:00426AD0 push eax 77 .text:00426AD1 lea eax, [ebp+var_C] 78 .text:00426AD4 push eax 79 .text:00426AD5 lea eax, [ebp+var_10] 80 .text:00426AD8 push eax 81 .text:00426AD9 lea eax, [ebp+var_4] 82 .text:00426ADC push eax 83 .text:00426ADD push edi 84 .text:00426ADE call [ebp+var_14] 85 .text:00426AE1 lea edx, [ebp+LockHandle] ; LockHandle 86 .text:00426AE4 lea ecx, [esi+0E8h] ; SpinLock 87 .text:00426AEA call ds:__imp_@KeAcquireInStackQueuedSpinLock@8 ; KeAcquireInStackQueuedSpinLock(x,x) 88 .text:00426AF0 jmp short loc_426B70 ; 判断第一个链表是否为空,如果内核与当前地址一样,说明没有内核APC函数。 89 .text:00426AF2 ; --------------------------------------------------------------------------- 90 .text:00426AF2 91 .text:00426AF2 loc_426AF2: ; CODE XREF: KiDeliverApc(x,x,x)+86↑j 92 .text:00426AF2 cmp byte ptr [esi+48h], 0 93 .text:00426AF6 jnz loc_426C05 94 .text:00426AFC cmp dword ptr [esi+0D4h], 0 95 .text:00426B03 jnz loc_426C05 96 .text:00426B09 mov ecx, [eax] 97 .text:00426B0B mov eax, [eax+4] 98 .text:00426B0E mov [eax], ecx 99 .text:00426B10 mov [ecx+4], eax 100 .text:00426B13 lea ecx, [ebp+LockHandle] ; LockHandle 101 .text:00426B16 mov byte ptr [edi+2Eh], 0 102 .text:00426B1A call ds:__imp_@KeReleaseInStackQueuedSpinLock@4 ; KeReleaseInStackQueuedSpinLock(x) 103 .text:00426B20 lea eax, [ebp+var_8] 104 .text:00426B23 push eax 105 .text:00426B24 lea eax, [ebp+var_C] 106 .text:00426B27 push eax 107 .text:00426B28 lea eax, [ebp+var_10] 108 .text:00426B2B push eax 109 .text:00426B2C lea eax, [ebp+var_4] 110 .text:00426B2F push eax 111 .text:00426B30 push edi 112 .text:00426B31 call [ebp+var_14] 113 .text:00426B34 cmp [ebp+var_4], 0 114 .text:00426B38 jz short loc_426B5D 115 .text:00426B3A xor cl, cl ; NewIrql 116 .text:00426B3C mov byte ptr [esi+48h], 1 117 .text:00426B40 call ds:__imp_@KfLowerIrql@4 ; KfLowerIrql(x) 118 .text:00426B46 push [ebp+var_8] 119 .text:00426B49 push [ebp+var_C] 120 .text:00426B4C push [ebp+var_10] 121 .text:00426B4F call [ebp+var_4] 122 .text:00426B52 mov cl, 1 ; NewIrql 123 .text:00426B54 call ds:__imp_@KfRaiseIrql@4 ; KfRaiseIrql(x) 124 .text:00426B5A mov [ebp+LockHandle.OldIrql], al 125 .text:00426B5D 126 .text:00426B5D loc_426B5D: ; CODE XREF: KiDeliverApc(x,x,x)+10A↑j 127 .text:00426B5D lea edx, [ebp+LockHandle] ; LockHandle 128 .text:00426B60 lea ecx, [esi+0E8h] ; SpinLock 129 .text:00426B66 call ds:__imp_@KeAcquireInStackQueuedSpinLock@8 ; KeAcquireInStackQueuedSpinLock(x,x) 130 .text:00426B6C mov byte ptr [esi+48h], 0 131 .text:00426B70 132 .text:00426B70 loc_426B70: ; CODE XREF: KiDeliverApc(x,x,x)+5C↑j 133 .text:00426B70 ; KiDeliverApc(x,x,x)+C2↑j 134 .text:00426B70 cmp [ebx], ebx ; 判断第一个链表是否为空,如果内核与当前地址一样,说明没有内核APC函数。 135 .text:00426B72 jnz loc_426A8F ; 如果有内核APC,则跳转去执行内核APC,否则继续执行处理用户APC。 136 .text:00426B78 lea ecx, [esi+3Ch] ; 取第二个双向链表,第二个APC队列。 137 .text:00426B7B mov eax, [ecx] ; 判断当前队列是否为空 138 .text:00426B7D cmp eax, ecx 139 .text:00426B7F jz loc_426C05 ; 如果不为空,则说明存在用户APC,则跳转去处理. 140 .text:00426B85 cmp [ebp+arg_0], 1 ; 判断参数是0还是1,如果为1的时候才处理用户APC 141 .text:00426B89 jnz short loc_426C05 ; 如果是用户APC,则去跳转执行。 142 .text:00426B8B cmp byte ptr [esi+4Ah], 0 143 .text:00426B8F jz short loc_426C05 144 .text:00426B91 mov byte ptr [esi+4Ah], 0 145 .text:00426B95 lea edi, [eax-0Ch] ; 获取_KAPC的首地址,因为链表在偏移+0ch处 146 .text:00426B98 mov ecx, [edi+_KAPC.NormalRoutine] 147 .text:00426B9B mov ebx, [edi+_KAPC.KernelRoutine] 148 .text:00426B9E mov [ebp+var_4], ecx 149 .text:00426BA1 mov ecx, [edi+_KAPC.NormalContext] 150 .text:00426BA4 mov [ebp+var_10], ecx 151 .text:00426BA7 mov ecx, [edi+24h] 152 .text:00426BAA mov [ebp+var_C], ecx 153 .text:00426BAD mov ecx, [edi+28h] 154 .text:00426BB0 mov [ebp+var_8], ecx 155 .text:00426BB3 mov ecx, [eax] ; 链表操作 将当前APC从用户队列中拆除,因为变量已经存储在局部变量中,方便存储。 156 .text:00426BB5 mov eax, [eax+4] 157 .text:00426BB8 mov [eax], ecx 158 .text:00426BBA mov [ecx+4], eax 159 .text:00426BBD lea ecx, [ebp+LockHandle] ; LockHandle 160 .text:00426BC0 mov byte ptr [edi+2Eh], 0 161 .text:00426BC4 call ds:__imp_@KeReleaseInStackQueuedSpinLock@4 ; KeReleaseInStackQueuedSpinLock(x) 162 .text:00426BCA lea eax, [ebp+var_8] 163 .text:00426BCD push eax 164 .text:00426BCE lea eax, [ebp+var_C] 165 .text:00426BD1 push eax 166 .text:00426BD2 lea eax, [ebp+var_10] 167 .text:00426BD5 push eax 168 .text:00426BD6 lea eax, [ebp+var_4] 169 .text:00426BD9 push eax 170 .text:00426BDA push edi 171 .text:00426BDB call ebx ; 调用_KAPC.KernelRoutine 释放APC函数 172 .text:00426BDD cmp [ebp+var_4], 0 173 .text:00426BE1 jnz short loc_426BEC 174 .text:00426BE3 push 1 175 .text:00426BE5 call _KeTestAlertThread@4 ; KeTestAlertThread(x) 176 .text:00426BEA jmp short loc_426C0E 177 .text:00426BEC ; --------------------------------------------------------------------------- 178 .text:00426BEC 179 .text:00426BEC loc_426BEC: ; CODE XREF: KiDeliverApc(x,x,x)+1B3↑j 180 .text:00426BEC push [ebp+var_8] 181 .text:00426BEF push [ebp+var_C] 182 .text:00426BF2 push [ebp+var_10] 183 .text:00426BF5 push [ebp+var_4] 184 .text:00426BF8 push [ebp+arg_8] 185 .text:00426BFB push [ebp+arg_4] 186 .text:00426BFE call _KiInitializeUserApc@24 ; 用户APC中调用APC用来初始化用户APC执行的环境 187 .text:00426C03 jmp short loc_426C0E 188 .text:00426C05 ; --------------------------------------------------------------------------- 189 .text:00426C05 190 .text:00426C05 loc_426C05: ; CODE XREF: KiDeliverApc(x,x,x)+C8↑j 191 .text:00426C05 ; KiDeliverApc(x,x,x)+D5↑j ... 192 .text:00426C05 lea ecx, [ebp+LockHandle] ; LockHandle 193 .text:00426C08 call ds:__imp_@KeReleaseInStackQueuedSpinLock@4 ; KeReleaseInStackQueuedSpinLock(x) 194 .text:00426C0E 195 .text:00426C0E loc_426C0E: ; CODE XREF: KiDeliverApc(x,x,x)+1BC↑j 196 .text:00426C0E ; KiDeliverApc(x,x,x)+1D5↑j 197 .text:00426C0E mov ecx, [ebp+BugCheckParameter1] 198 .text:00426C11 cmp [esi+44h], ecx 199 .text:00426C14 jz short loc_426C30 200 .text:00426C16 mov eax, large fs:994h 201 .text:00426C1C push eax ; BugCheckParameter4 202 .text:00426C1D movzx eax, byte ptr [esi+165h] 203 .text:00426C24 push eax ; BugCheckParameter3 204 .text:00426C25 push dword ptr [esi+44h] ; BugCheckParameter2 205 .text:00426C28 push ecx ; BugCheckParameter1 206 .text:00426C29 push 5 ; BugCheckCode 207 .text:00426C2B call _KeBugCheckEx@20 ; KeBugCheckEx(x,x,x,x,x) 208 .text:00426C30 ; --------------------------------------------------------------------------- 209 .text:00426C30 210 .text:00426C30 loc_426C30: ; CODE XREF: KiDeliverApc(x,x,x)+1E6↑j 211 .text:00426C30 mov eax, [ebp+var_1C] 212 .text:00426C33 pop edi 213 .text:00426C34 mov [esi+134h], eax 214 .text:00426C3A pop esi 215 .text:00426C3B pop ebx 216 .text:00426C3C leave 217 .text:00426C3D retn 0Ch 218 .text:00426C3D _KiDeliverApc@12 endp
3. KiDeliverApc(ntkrnlpa.exe)代码分析
1 :0042A9FE ; =============== S U B R O U T I N E ======================================= 2 .text:0042A9FE 3 .text:0042A9FE ; Attributes: bp-based frame 4 .text:0042A9FE 5 .text:0042A9FE ; __stdcall KiInitializeUserApc(x, x, x, x, x, x) 6 .text:0042A9FE _KiInitializeUserApc@24 proc near ; CODE XREF: KiDeliverApc(x,x,x)+1D0↑p 7 .text:0042A9FE 8 .text:0042A9FE var_34C = dword ptr -34Ch 9 .text:0042A9FE var_340 = dword ptr -340h 10 .text:0042A9FE var_2FC = dword ptr -2FCh 11 .text:0042A9FE var_2F8 = dword ptr -2F8h 12 .text:0042A9FE var_2F4 = dword ptr -2F4h 13 .text:0042A9FE BugCheckParameter3= dword ptr -2F0h 14 .text:0042A9FE var_2EC = dword ptr -2ECh 15 .text:0042A9FE var_2E8 = dword ptr -2E8h 16 .text:0042A9FE var_228 = dword ptr -228h 17 .text:0042A9FE var_224 = dword ptr -224h 18 .text:0042A9FE var_1C = dword ptr -1Ch 19 .text:0042A9FE ms_exc = CPPEH_RECORD ptr -18h 20 .text:0042A9FE arg_0 = dword ptr 8 21 .text:0042A9FE arg_4 = dword ptr 0Ch 22 .text:0042A9FE arg_8 = dword ptr 10h 23 .text:0042A9FE arg_C = dword ptr 14h 24 .text:0042A9FE arg_10 = dword ptr 18h 25 .text:0042A9FE arg_14 = dword ptr 1Ch 26 .text:0042A9FE 27 .text:0042A9FE ; __unwind { // __SEH_prolog 28 .text:0042A9FE push 33Ch 29 .text:0042AA03 push offset stru_4020B0 30 .text:0042AA08 call __SEH_prolog 31 .text:0042AA0D mov eax, ___security_cookie 32 .text:0042AA12 mov [ebp+var_1C], eax 33 .text:0042AA15 mov eax, [ebp+_KAPC.Thread] 34 .text:0042AA18 mov [ebp+var_2F4], eax 35 .text:0042AA1E mov ebx, [ebp+arg_4] 36 .text:0042AA21 mov [ebp+BugCheckParameter3], ebx 37 .text:0042AA27 test byte ptr [ebx+72h], 2 38 .text:0042AA2B jnz loc_42AB7B 39 .text:0042AA31 mov [ebp+var_2E8], 10017h 40 .text:0042AA3B lea ecx, [ebp+var_2E8] 41 .text:0042AA41 push ecx ; context对象的首地址 42 .text:0042AA42 push eax 43 .text:0042AA43 push ebx ; trap_frame的地址 44 .text:0042AA44 call _KeContextFromKframes@12 ; 因为要返回3环去处理,_TRAP_FRAME保存的EIP与ESP显然需要修改,因此这里就需要来进行备份处理。 45 .text:0042AA49 ; __try { // __except at loc_42AB4E 46 .text:0042AA49 and [ebp+ms_exc.registration.TryLevel], 0 47 .text:0042AA4D mov eax, 2DCh ; 一个CONTEXT 和 另外四个值的大小 48 .text:0042AA52 mov [ebp+var_2F8], eax 49 .text:0042AA58 mov esi, [ebp+var_224] ; ebp指向context堆栈 context -2e8 50 .text:0042AA5E and esi, 0FFFFFFFCh ; 1100 四字节对齐 51 .text:0042AA61 sub esi, eax ; z在0环直接修改三环的堆栈,将用户三环堆栈减少为0x2DC字节 52 .text:0042AA63 mov [ebp+var_2EC], esi 53 .text:0042AA69 push 4 ; Alignment 54 .text:0042AA6B push eax ; Length 55 .text:0042AA6C push esi ; Address 56 .text:0042AA6D call _ProbeForWrite@12 ; 修改新增部分的内存属性 57 .text:0042AA72 lea edi, [esi+10h] ; 先让过前面4个成员 58 .text:0042AA75 mov ecx, 0B3h ; 0B3*4 + 10 = 2DC 59 .text:0042AA7A lea esi, [ebp+var_2E8] 60 .text:0042AA80 rep movsd ; 复制context到用户栈 61 .text:0042AA82 mov dword ptr [ebx+6Ch], 1Bh 62 .text:0042AA89 push 23h 63 .text:0042AA8B pop eax 64 .text:0042AA8C mov [ebx+78h], eax 65 .text:0042AA8F mov [ebx+38h], eax 66 .text:0042AA92 mov [ebx+34h], eax 67 .text:0042AA95 mov dword ptr [ebx+50h], 3Bh 68 .text:0042AA9C and dword ptr [ebx+30h], 0 69 .text:0042AAA0 mov ecx, [ebp+var_228] 70 .text:0042AAA6 test ecx, 20000h 71 .text:0042AAAC jz short loc_42AAC6 72 .text:0042AAAE cmp byte ptr _KeI386VdmIoplAllowed, 0 73 .text:0042AAB5 jz short loc_42AAC6 74 .text:0042AAB7 mov eax, _KeI386EFlagsAndMaskV86 75 .text:0042AABC and eax, ecx 76 .text:0042AABE or eax, _KeI386EFlagsOrMaskV86 77 .text:0042AAC4 jmp short loc_42AAD4 78 .text:0042AAC6 ; --------------------------------------------------------------------------- 79 .text:0042AAC6 80 .text:0042AAC6 loc_42AAC6: ; CODE XREF: KiInitializeUserApc(x,x,x,x,x,x)+AE↑j 81 .text:0042AAC6 ; KiInitializeUserApc(x,x,x,x,x,x)+B7↑j 82 .text:0042AAC6 and ecx, 3E0DD7h 83 .text:0042AACC or ecx, 200h 84 .text:0042AAD2 mov eax, ecx 85 .text:0042AAD4 86 .text:0042AAD4 loc_42AAD4: ; CODE XREF: KiInitializeUserApc(x,x,x,x,x,x)+C6↑j 87 .text:0042AAD4 mov [ebx+KTRAP_FRAME.EFlags], eax 88 .text:0042AAD7 mov eax, large fs:292 ; 直接来进行修改fs寄存器 89 .text:0042AADD mov [ebp+var_2FC], eax 90 .text:0042AAE3 cmp byte ptr [eax+KTRAP_FRAME.SegGs], 0 91 .text:0042AAE7 jz short loc_42AAED 92 .text:0042AAE9 or byte ptr [ebx+71h], 30h 93 .text:0042AAED 94 .text:0042AAED loc_42AAED: ; CODE XREF: KiInitializeUserApc(x,x,x,x,x,x)+E9↑j 95 .text:0042AAED mov eax, [ebp+var_2EC] 96 .text:0042AAF3 mov [ebx+KTRAP_FRAME.HardwareEsp], eax 97 .text:0042AAF6 mov ecx, _KeUserApcDispatcher 98 .text:0042AAFC mov [ebx+KTRAP_FRAME._Eip], ecx ; 将eip改为_KeUserApcDispatcher这个函数,这意味着跑回来,就执行这个函数。 99 .text:0042AAFF and [ebx+KTRAP_FRAME.ErrCode], 0 100 .text:0042AB03 mov ecx, [ebp+arg_8] 101 .text:0042AB06 mov [eax], ecx 102 .text:0042AB08 push 4 103 .text:0042AB0A pop ecx 104 .text:0042AB0B add eax, ecx 105 .text:0042AB0D mov [ebp+var_2EC], eax 106 .text:0042AB13 mov edx, [ebp+arg_C] 107 .text:0042AB16 mov [eax], edx 108 .text:0042AB18 add eax, ecx 109 .text:0042AB1A mov [ebp+var_2EC], eax 110 .text:0042AB20 mov edx, [ebp+arg_10] 111 .text:0042AB23 mov [eax], edx 112 .text:0042AB25 add eax, ecx 113 .text:0042AB27 mov [ebp+var_2EC], eax 114 .text:0042AB2D mov edx, [ebp+arg_14] 115 .text:0042AB30 mov [eax], edx 116 .text:0042AB32 add eax, ecx 117 .text:0042AB34 mov [ebp+var_2EC], eax 118 .text:0042AB3A jmp short loc_42AB77 119 .text:0042AB3C ; --------------------------------------------------------------------------- 120 .text:0042AB3C 121 .text:0042AB3C loc_42AB3C: ; DATA XREF: .text:stru_4020B0↑o 122 .text:0042AB3C ; __except filter // owned by 42AA49 123 .text:0042AB3C mov eax, [ebp+ms_exc.exc_ptr] 124 .text:0042AB3F push dword ptr [eax] 125 .text:0042AB41 lea eax, [ebp+var_34C] 126 .text:0042AB47 push eax 127 .text:0042AB48 call _KiCopyInformation@8 ; KiCopyInformation(x,x) 128 .text:0042AB4D retn 129 .text:0042AB4E ; --------------------------------------------------------------------------- 130 .text:0042AB4E 131 .text:0042AB4E loc_42AB4E: ; DATA XREF: .text:stru_4020B0↑o 132 .text:0042AB4E ; __except(loc_42AB3C) // owned by 42AA49 133 .text:0042AB4E mov esp, [ebp+ms_exc.old_esp] 134 .text:0042AB51 mov eax, [ebp+BugCheckParameter3] 135 .text:0042AB57 mov ecx, [eax+68h] 136 .text:0042AB5A mov [ebp+var_340], ecx 137 .text:0042AB60 push 1 ; char 138 .text:0042AB62 push 1 ; int 139 .text:0042AB64 push eax ; BugCheckParameter3 140 .text:0042AB65 push [ebp+var_2F4] ; int 141 .text:0042AB6B lea eax, [ebp+var_34C] 142 .text:0042AB71 push eax ; int 143 .text:0042AB72 call _KiDispatchException@20 ; KiDispatchException(x,x,x,x,x) 144 .text:0042AB72 ; } // starts at 42AA49 145 .text:0042AB77 146 .text:0042AB77 loc_42AB77: ; CODE XREF: KiInitializeUserApc(x,x,x,x,x,x)+13C↑j 147 .text:0042AB77 or [ebp+ms_exc.registration.TryLevel], 0FFFFFFFFh 148 .text:0042AB7B 149 .text:0042AB7B loc_42AB7B: ; CODE XREF: KiInitializeUserApc(x,x,x,x,x,x)+2D↑j 150 .text:0042AB7B mov ecx, [ebp+var_1C] 151 .text:0042AB7E call @xHalReferenceHandler@4 ; xHalReferenceHandler(x) 152 .text:0042AB83 call __SEH_epilog 153 .text:0042AB88 retn 18h 154 .text:0042AB88 ; } // starts at 42A9FE 155 .text:0042AB88 _KiInitializeUserApc@24 endp
4. KiUserApcDispatcher(ntdll.dll)分析
1 ; __stdcall KiUserApcDispatcher(x, x, x, x, x) 2 public _KiUserApcDispatcher@20 3 _KiUserApcDispatcher@20 proc near 4 arg_C= byte ptr 10h 5 lea edi, [esp+arg_C] 6 pop eax 7 call eax ; NormalRoutine 执行用户APC的总入口 8 push 1 9 push edi 10 call _ZwContinue@8 ; 返回到用户内核 11 nop 12 _KiUserApcDispatcher@20 endp ; sp-analysis failed