用户APC的执行过程

Posted onetrainee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用户APC的执行过程相关的知识,希望对你有一定的参考价值。

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

 

以上是关于用户APC的执行过程的主要内容,如果未能解决你的问题,请参考以下文章

用户层APC队列使用

当活动被破坏但我必须继续执行片段中的代码时该怎么办?

异步过程调用被另一个线程中断?

注入理解之APC注入

深入学习APC

Ring3 APC注入