用户APC的执行过程
阅读原文时间:2023年07月09日阅读:3

__**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)代码分析

:004667F0 _KiServiceExit2 proc near ; CODE XREF: NtContinue(x,x)+3A↓j
.text:004667F0 ; NtRaiseException(x,x,x)+3C↓j …
.text:004667F0
.text:004667F0 arg_C = dword ptr 10h
.text:004667F0 arg_10 = dword ptr 14h
.text:004667F0 arg_38 = dword ptr 3Ch
.text:004667F0 arg_3C = dword ptr 40h
.text:004667F0 arg_40 = dword ptr 44h
.text:004667F0 arg_44 = dword ptr 48h
.text:004667F0 arg_48 = dword ptr 4Ch
.text:004667F0 arg_60 = dword ptr 64h
.text:004667F0 arg_64 = dword ptr 68h
.text:004667F0 arg_68 = dword ptr 6Ch
.text:004667F0 arg_6C = dword ptr 70h
.text:004667F0
.text:004667F0 cli
.text:004667F1 test dword ptr [ebp+70h], 20000h
.text:004667F8 jnz short loc_466800 ; 获取Kthread
.text:004667FA test byte ptr [ebp+6Ch],
.text:004667FE jz short loc_466834
.text:
.text: loc_466800: ; CODE XREF: _KiServiceExit2+↑j
.text: ; _KiServiceExit2+↓j
.text: mov ebx, ds:0FFDFF124h ; 获取Kthread
.text: mov byte ptr [ebx+2Eh],
.text:0046680A cmp byte ptr [ebx+4Ah], ; 判断是否有用户APC请求
.text:0046680E jz short loc_466834 ; 如果有APC请求则不会跳转
.text: mov ebx, ebp
.text: mov ecx, ; NewIrql
.text: call ds:__imp_@KfRaiseIrql@ ; KfRaiseIrql(x)
.text:0046681D push eax
.text:0046681E sti
.text:0046681F push ebx
.text: push
.text: push ; 这里处理用户层的APC函数
.text: call _KiDeliverApc@ ; 该函数实现对APC的处理
.text: pop ecx ; NewIrql
.text:0046682A call ds:__imp_@KfLowerIrql@ ; KfLowerIrql(x)
.text: cli
.text: jmp short loc_466800 ; 获取Kthread
.text: ; ---------------------------------------------------------------------------
.text: db 90h
.text: ; ---------------------------------------------------------------------------
.text:
.text: loc_466834: ; CODE XREF: _KiServiceExit2+E↑j
.text: ; _KiServiceExit2+1E↑j
.text: mov edx, [esp+arg_48]
.text: mov ebx, large fs:50h
.text:0046683F mov large fs:, edx
.text: mov ecx, [esp+arg_44]
.text:0046684A mov esi, large fs:124h
.text: mov [esi+140h], cl
.text: test ebx, 0FFh
.text:0046685D jnz short loc_4668B0
.text:0046685F
.text:0046685F loc_46685F: ; CODE XREF: _KiServiceExit2+D0↓j
.text:0046685F ; _KiServiceExit2+FB↓j
.text:0046685F test [esp+arg_6C], 20000h
.text: jnz loc_466FD4
.text:0046686D test word ptr [esp+arg_68], 0FFF8h
.text: jz short loc_4668F0
.text: mov edx, [esp+arg_38]
.text:0046687A mov ecx, [esp+arg_3C]
.text:0046687E mov eax, [esp+arg_40]
.text: cmp word ptr [ebp+6Ch],
.text: jz short loc_466895
.text: lea esp, [ebp+30h]
.text:0046688C pop gs
.text:0046688E pop es
.text:0046688F pop ds
.text: lea esp, [ebp+50h]
.text: pop fs
.text:
.text: loc_466895: ; CODE XREF: _KiServiceExit2+↑j
.text: lea esp, [ebp+54h]
.text: pop edi
.text: pop esi
.text:0046689A pop ebx
.text:0046689B pop ebp
.text:0046689C cmp word ptr [esp-60h+arg_64], 80h
.text:004668A3 ja loc_466FF0
.text:004668A9 add esp,
.text:004668AC iret
.text:004668AC ; ---------------------------------------------------------------------------
.text:004668AD db 8Dh
.text:004668AE db 49h ; I
.text:004668AF db
.text:004668B0 ; ---------------------------------------------------------------------------
.text:004668B0
.text:004668B0 loc_4668B0: ; CODE XREF: _KiServiceExit2+6D↑j
.text:004668B0 test dword ptr [ebp+70h], 20000h
.text:004668B7 jnz short loc_4668C2
.text:004668B9 test dword ptr [ebp+6Ch],
.text:004668C0 jz short loc_46685F
.text:004668C2
.text:004668C2 loc_4668C2: ; CODE XREF: _KiServiceExit2+C7↑j
.text:004668C2 xor ebx, ebx
.text:004668C4 mov esi, [ebp+18h]
.text:004668C7 mov edi, [ebp+1Ch]
.text:004668CA mov dr7, ebx
.text:004668CD mov dr0, esi
.text:004668D0 mov ebx, [ebp+20h]
.text:004668D3 mov dr1, edi
.text:004668D6 mov dr2, ebx
.text:004668D9 mov esi, [ebp+24h]
.text:004668DC mov edi, [ebp+28h]
.text:004668DF mov ebx, [ebp+2Ch]
.text:004668E2 mov dr3, esi
.text:004668E5 mov dr6, edi
.text:004668E8 mov dr7, ebx
.text:004668EB jmp loc_46685F
.text:004668F0 ; ---------------------------------------------------------------------------
.text:004668F0
.text:004668F0 loc_4668F0: ; CODE XREF: _KiServiceExit2+↑j
.text:004668F0 mov ebx, [esp+arg_C]
.text:004668F4 mov [esp+arg_68], ebx
.text:004668F8 mov ebx, [esp+arg_10]
.text:004668FC sub ebx, 0Ch
.text:004668FF mov [esp+arg_60], ebx
.text: mov esi, [esp+arg_6C]
.text: mov [ebx+], esi
.text:0046690A mov esi, [esp+arg_68]
.text:0046690E mov [ebx+], esi
.text: mov esi, [esp+arg_64]
.text: mov [ebx], esi
.text: mov eax, [esp+arg_40]
.text:0046691B mov edx, [esp+arg_38]
.text:0046691F mov ecx, [esp+arg_3C]
.text: add esp, 54h
.text: pop edi
.text: pop esi
.text: pop ebx
.text: pop ebp
.text:0046692A mov esp, [esp-64h+arg_60]
.text:0046692D iret
.text:0046692D _KiServiceExit2 endp ; sp-analysis failed

2. KiDeliverApc(ntkrnlpa.exe)代码分析

; __stdcall KiDeliverApc(x, x, x)
.text:00426A2E public _KiDeliverApc@
.text:00426A2E _KiDeliverApc@ proc near ; CODE XREF: KiSwapThread()+5F↓p
.text:00426A2E ; _KiSystemService+21B↓p …
.text:00426A2E
.text:00426A2E LockHandle = _KLOCK_QUEUE_HANDLE ptr -28h
.text:00426A2E var_1C = dword ptr -1Ch
.text:00426A2E BugCheckParameter1= dword ptr -18h
.text:00426A2E var_14 = dword ptr -14h
.text:00426A2E var_10 = dword ptr -10h
.text:00426A2E var_C = dword ptr -0Ch
.text:00426A2E var_8 = dword ptr -
.text:00426A2E var_4 = dword ptr -
.text:00426A2E arg_0 = byte ptr
.text:00426A2E arg_4 = dword ptr 0Ch
.text:00426A2E arg_8 = dword ptr 10h
.text:00426A2E
.text:00426A2E mov edi, edi
.text:00426A30 push ebp
.text:00426A31 mov ebp, esp
.text:00426A33 sub esp, 28h
.text:00426A36 mov ecx, [ebp+arg_8]
.text:00426A39 test ecx, ecx
.text:00426A3B jz short loc_426A54
.text:00426A3D mov edx, [ecx+68h]
.text:00426A40 mov eax, offset _ExpInterlockedPopEntrySListResume@ ; ExpInterlockedPopEntrySListResume()
.text:00426A45 cmp edx, eax
.text:00426A47 jb short loc_426A54
.text:00426A49 cmp edx, offset _ExpInterlockedPopEntrySListEnd@ ; ExpInterlockedPopEntrySListEnd()
.text:00426A4F ja short loc_426A54
.text:00426A51 mov [ecx+68h], eax
.text:00426A54
.text:00426A54 loc_426A54: ; CODE XREF: KiDeliverApc(x,x,x)+D↑j
.text:00426A54 ; KiDeliverApc(x,x,x)+↑j …
.text:00426A54 push ebx
.text:00426A55 push esi
.text:00426A56 push edi
.text:00426A57 mov eax, large fs:124h
.text:00426A5D mov esi, eax
.text:00426A5F mov eax, [esi+134h]
.text:00426A65 mov [ebp+var_1C], eax
.text:00426A68 mov eax, [esi+44h]
.text:00426A6B mov [esi+134h], ecx
.text:00426A71 lea ecx, [esi+0E8h] ; SpinLock
.text:00426A77 lea edx, [ebp+LockHandle] ; LockHandle
.text:00426A7A mov [ebp+BugCheckParameter1], eax
.text:00426A7D call ds:__imp_@KeAcquireInStackQueuedSpinLock@ ; KeAcquireInStackQueuedSpinLock(x,x)
.text:00426A83 mov byte ptr [esi+49h],
.text:00426A87 lea ebx, [esi+34h] ; 取内核APC列表(双向链表 第一个内核 第二个用户)
.text:00426A8A jmp loc_426B70 ; 判断第一个链表是否为空,如果内核与当前地址一样,说明没有内核APC函数。
.text:00426A8F ; ---------------------------------------------------------------------------
.text:00426A8F
.text:00426A8F loc_426A8F: ; CODE XREF: KiDeliverApc(x,x,x)+↓j
.text:00426A8F mov eax, [ebx]
.text:00426A91 lea edi, [eax-0Ch]
.text:00426A94 mov ecx, [edi+14h]
.text:00426A97 mov [ebp+var_14], ecx
.text:00426A9A mov ecx, [edi+1Ch]
.text:00426A9D test ecx, ecx
.text:00426A9F mov [ebp+var_4], ecx
.text:00426AA2 mov edx, [edi+20h]
.text:00426AA5 mov [ebp+var_10], edx
.text:00426AA8 mov edx, [edi+24h]
.text:00426AAB mov [ebp+var_C], edx
.text:00426AAE mov edx, [edi+28h]
.text:00426AB1 mov [ebp+var_8], edx
.text:00426AB4 jnz short loc_426AF2
.text:00426AB6 mov ecx, [eax]
.text:00426AB8 mov eax, [eax+]
.text:00426ABB mov [eax], ecx
.text:00426ABD mov [ecx+], eax
.text:00426AC0 lea ecx, [ebp+LockHandle] ; LockHandle
.text:00426AC3 mov byte ptr [edi+2Eh],
.text:00426AC7 call ds:__imp_@KeReleaseInStackQueuedSpinLock@ ; KeReleaseInStackQueuedSpinLock(x)
.text:00426ACD lea eax, [ebp+var_8]
.text:00426AD0 push eax
.text:00426AD1 lea eax, [ebp+var_C]
.text:00426AD4 push eax
.text:00426AD5 lea eax, [ebp+var_10]
.text:00426AD8 push eax
.text:00426AD9 lea eax, [ebp+var_4]
.text:00426ADC push eax
.text:00426ADD push edi
.text:00426ADE call [ebp+var_14]
.text:00426AE1 lea edx, [ebp+LockHandle] ; LockHandle
.text:00426AE4 lea ecx, [esi+0E8h] ; SpinLock
.text:00426AEA call ds:__imp_@KeAcquireInStackQueuedSpinLock@ ; KeAcquireInStackQueuedSpinLock(x,x)
.text:00426AF0 jmp short loc_426B70 ; 判断第一个链表是否为空,如果内核与当前地址一样,说明没有内核APC函数。
.text:00426AF2 ; ---------------------------------------------------------------------------
.text:00426AF2
.text:00426AF2 loc_426AF2: ; CODE XREF: KiDeliverApc(x,x,x)+↑j
.text:00426AF2 cmp byte ptr [esi+48h],
.text:00426AF6 jnz loc_426C05
.text:00426AFC cmp dword ptr [esi+0D4h],
.text:00426B03 jnz loc_426C05
.text:00426B09 mov ecx, [eax]
.text:00426B0B mov eax, [eax+]
.text:00426B0E mov [eax], ecx
.text:00426B10 mov [ecx+], eax
.text:00426B13 lea ecx, [ebp+LockHandle] ; LockHandle
.text:00426B16 mov byte ptr [edi+2Eh],
.text:00426B1A call ds:__imp_@KeReleaseInStackQueuedSpinLock@ ; KeReleaseInStackQueuedSpinLock(x)
.text:00426B20 lea eax, [ebp+var_8]
.text:00426B23 push eax
.text:00426B24 lea eax, [ebp+var_C]
.text:00426B27 push eax
.text:00426B28 lea eax, [ebp+var_10]
.text:00426B2B push eax
.text:00426B2C lea eax, [ebp+var_4]
.text:00426B2F push eax
.text:00426B30 push edi
.text:00426B31 call [ebp+var_14]
.text:00426B34 cmp [ebp+var_4],
.text:00426B38 jz short loc_426B5D
.text:00426B3A xor cl, cl ; NewIrql
.text:00426B3C mov byte ptr [esi+48h],
.text:00426B40 call ds:__imp_@KfLowerIrql@ ; KfLowerIrql(x)
.text:00426B46 push [ebp+var_8]
.text:00426B49 push [ebp+var_C]
.text:00426B4C push [ebp+var_10]
.text:00426B4F call [ebp+var_4]
.text:00426B52 mov cl, ; NewIrql
.text:00426B54 call ds:__imp_@KfRaiseIrql@ ; KfRaiseIrql(x)
.text:00426B5A mov [ebp+LockHandle.OldIrql], al
.text:00426B5D
.text:00426B5D loc_426B5D: ; CODE XREF: KiDeliverApc(x,x,x)+10A↑j
.text:00426B5D lea edx, [ebp+LockHandle] ; LockHandle
.text:00426B60 lea ecx, [esi+0E8h] ; SpinLock
.text:00426B66 call ds:__imp_@KeAcquireInStackQueuedSpinLock@ ; KeAcquireInStackQueuedSpinLock(x,x)
.text:00426B6C mov byte ptr [esi+48h],
.text:00426B70
.text:00426B70 loc_426B70: ; CODE XREF: KiDeliverApc(x,x,x)+5C↑j
.text:00426B70 ; KiDeliverApc(x,x,x)+C2↑j
.text:00426B70 cmp [ebx], ebx ; 判断第一个链表是否为空,如果内核与当前地址一样,说明没有内核APC函数。
.text:00426B72 jnz loc_426A8F ; 如果有内核APC,则跳转去执行内核APC,否则继续执行处理用户APC。
.text:00426B78 lea ecx, [esi+3Ch] ; 取第二个双向链表,第二个APC队列。
.text:00426B7B mov eax, [ecx] ; 判断当前队列是否为空
.text:00426B7D cmp eax, ecx
.text:00426B7F jz loc_426C05 ; 如果不为空,则说明存在用户APC,则跳转去处理.
.text:00426B85 cmp [ebp+arg_0], ; 判断参数是0还是1,如果为1的时候才处理用户APC
.text:00426B89 jnz short loc_426C05 ; 如果是用户APC,则去跳转执行。
.text:00426B8B cmp byte ptr [esi+4Ah],
.text:00426B8F jz short loc_426C05
.text:00426B91 mov byte ptr [esi+4Ah],
.text:00426B95 lea edi, [eax-0Ch] ; 获取_KAPC的首地址,因为链表在偏移+0ch处
.text:00426B98 mov ecx, [edi+_KAPC.NormalRoutine]
.text:00426B9B mov ebx, [edi+_KAPC.KernelRoutine]
.text:00426B9E mov [ebp+var_4], ecx
.text:00426BA1 mov ecx, [edi+_KAPC.NormalContext]
.text:00426BA4 mov [ebp+var_10], ecx
.text:00426BA7 mov ecx, [edi+24h]
.text:00426BAA mov [ebp+var_C], ecx
.text:00426BAD mov ecx, [edi+28h]
.text:00426BB0 mov [ebp+var_8], ecx
.text:00426BB3 mov ecx, [eax] ; 链表操作 将当前APC从用户队列中拆除,因为变量已经存储在局部变量中,方便存储。
.text:00426BB5 mov eax, [eax+]
.text:00426BB8 mov [eax], ecx
.text:00426BBA mov [ecx+], eax
.text:00426BBD lea ecx, [ebp+LockHandle] ; LockHandle
.text:00426BC0 mov byte ptr [edi+2Eh],
.text:00426BC4 call ds:__imp_@KeReleaseInStackQueuedSpinLock@ ; KeReleaseInStackQueuedSpinLock(x)
.text:00426BCA lea eax, [ebp+var_8]
.text:00426BCD push eax
.text:00426BCE lea eax, [ebp+var_C]
.text:00426BD1 push eax
.text:00426BD2 lea eax, [ebp+var_10]
.text:00426BD5 push eax
.text:00426BD6 lea eax, [ebp+var_4]
.text:00426BD9 push eax
.text:00426BDA push edi
.text:00426BDB call ebx ; 调用_KAPC.KernelRoutine 释放APC函数
.text:00426BDD cmp [ebp+var_4],
.text:00426BE1 jnz short loc_426BEC
.text:00426BE3 push
.text:00426BE5 call _KeTestAlertThread@ ; KeTestAlertThread(x)
.text:00426BEA jmp short loc_426C0E
.text:00426BEC ; ---------------------------------------------------------------------------
.text:00426BEC
.text:00426BEC loc_426BEC: ; CODE XREF: KiDeliverApc(x,x,x)+1B3↑j
.text:00426BEC push [ebp+var_8]
.text:00426BEF push [ebp+var_C]
.text:00426BF2 push [ebp+var_10]
.text:00426BF5 push [ebp+var_4]
.text:00426BF8 push [ebp+arg_8]
.text:00426BFB push [ebp+arg_4]
.text:00426BFE call _KiInitializeUserApc@ ; 用户APC中调用APC用来初始化用户APC执行的环境
.text:00426C03 jmp short loc_426C0E
.text:00426C05 ; ---------------------------------------------------------------------------
.text:00426C05
.text:00426C05 loc_426C05: ; CODE XREF: KiDeliverApc(x,x,x)+C8↑j
.text:00426C05 ; KiDeliverApc(x,x,x)+D5↑j …
.text:00426C05 lea ecx, [ebp+LockHandle] ; LockHandle
.text:00426C08 call ds:__imp_@KeReleaseInStackQueuedSpinLock@ ; KeReleaseInStackQueuedSpinLock(x)
.text:00426C0E
.text:00426C0E loc_426C0E: ; CODE XREF: KiDeliverApc(x,x,x)+1BC↑j
.text:00426C0E ; KiDeliverApc(x,x,x)+1D5↑j
.text:00426C0E mov ecx, [ebp+BugCheckParameter1]
.text:00426C11 cmp [esi+44h], ecx
.text:00426C14 jz short loc_426C30
.text:00426C16 mov eax, large fs:994h
.text:00426C1C push eax ; BugCheckParameter4
.text:00426C1D movzx eax, byte ptr [esi+165h]
.text:00426C24 push eax ; BugCheckParameter3
.text:00426C25 push dword ptr [esi+44h] ; BugCheckParameter2
.text:00426C28 push ecx ; BugCheckParameter1
.text:00426C29 push ; BugCheckCode
.text:00426C2B call _KeBugCheckEx@ ; KeBugCheckEx(x,x,x,x,x)
.text:00426C30 ; ---------------------------------------------------------------------------
.text:00426C30
.text:00426C30 loc_426C30: ; CODE XREF: KiDeliverApc(x,x,x)+1E6↑j
.text:00426C30 mov eax, [ebp+var_1C]
.text:00426C33 pop edi
.text:00426C34 mov [esi+134h], eax
.text:00426C3A pop esi
.text:00426C3B pop ebx
.text:00426C3C leave
.text:00426C3D retn 0Ch
.text:00426C3D _KiDeliverApc@ endp

3. KiDeliverApc(ntkrnlpa.exe)代码分析

:0042A9FE ; =============== S U B R O U T I N E =======================================
.text:0042A9FE
.text:0042A9FE ; Attributes: bp-based frame
.text:0042A9FE
.text:0042A9FE ; __stdcall KiInitializeUserApc(x, x, x, x, x, x)
.text:0042A9FE _KiInitializeUserApc@ proc near ; CODE XREF: KiDeliverApc(x,x,x)+1D0↑p
.text:0042A9FE
.text:0042A9FE var_34C = dword ptr -34Ch
.text:0042A9FE var_340 = dword ptr -340h
.text:0042A9FE var_2FC = dword ptr -2FCh
.text:0042A9FE var_2F8 = dword ptr -2F8h
.text:0042A9FE var_2F4 = dword ptr -2F4h
.text:0042A9FE BugCheckParameter3= dword ptr -2F0h
.text:0042A9FE var_2EC = dword ptr -2ECh
.text:0042A9FE var_2E8 = dword ptr -2E8h
.text:0042A9FE var_228 = dword ptr -228h
.text:0042A9FE var_224 = dword ptr -224h
.text:0042A9FE var_1C = dword ptr -1Ch
.text:0042A9FE ms_exc = CPPEH_RECORD ptr -18h
.text:0042A9FE arg_0 = dword ptr
.text:0042A9FE arg_4 = dword ptr 0Ch
.text:0042A9FE arg_8 = dword ptr 10h
.text:0042A9FE arg_C = dword ptr 14h
.text:0042A9FE arg_10 = dword ptr 18h
.text:0042A9FE arg_14 = dword ptr 1Ch
.text:0042A9FE
.text:0042A9FE ; __unwind { // __SEH_prolog
.text:0042A9FE push 33Ch
.text:0042AA03 push offset stru_4020B0
.text:0042AA08 call __SEH_prolog
.text:0042AA0D mov eax, ___security_cookie
.text:0042AA12 mov [ebp+var_1C], eax
.text:0042AA15 mov eax, [ebp+_KAPC.Thread]
.text:0042AA18 mov [ebp+var_2F4], eax
.text:0042AA1E mov ebx, [ebp+arg_4]
.text:0042AA21 mov [ebp+BugCheckParameter3], ebx
.text:0042AA27 test byte ptr [ebx+72h],
.text:0042AA2B jnz loc_42AB7B
.text:0042AA31 mov [ebp+var_2E8], 10017h
.text:0042AA3B lea ecx, [ebp+var_2E8]
.text:0042AA41 push ecx ; context对象的首地址
.text:0042AA42 push eax
.text:0042AA43 push ebx ; trap_frame的地址
.text:0042AA44 call _KeContextFromKframes@ ; 因为要返回3环去处理,_TRAP_FRAME保存的EIP与ESP显然需要修改,因此这里就需要来进行备份处理。
.text:0042AA49 ; __try { // __except at loc_42AB4E
.text:0042AA49 and [ebp+ms_exc.registration.TryLevel],
.text:0042AA4D mov eax, 2DCh ; 一个CONTEXT 和 另外四个值的大小
.text:0042AA52 mov [ebp+var_2F8], eax
.text:0042AA58 mov esi, [ebp+var_224] ; ebp指向context堆栈 context -2e8
.text:0042AA5E and esi, 0FFFFFFFCh ; 四字节对齐
.text:0042AA61 sub esi, eax ; z在0环直接修改三环的堆栈,将用户三环堆栈减少为0x2DC字节
.text:0042AA63 mov [ebp+var_2EC], esi
.text:0042AA69 push ; Alignment
.text:0042AA6B push eax ; Length
.text:0042AA6C push esi ; Address
.text:0042AA6D call _ProbeForWrite@ ; 修改新增部分的内存属性
.text:0042AA72 lea edi, [esi+10h] ; 先让过前面4个成员
.text:0042AA75 mov ecx, 0B3h ; 0B3* + = 2DC
.text:0042AA7A lea esi, [ebp+var_2E8]
.text:0042AA80 rep movsd ; 复制context到用户栈
.text:0042AA82 mov dword ptr [ebx+6Ch], 1Bh
.text:0042AA89 push 23h
.text:0042AA8B pop eax
.text:0042AA8C mov [ebx+78h], eax
.text:0042AA8F mov [ebx+38h], eax
.text:0042AA92 mov [ebx+34h], eax
.text:0042AA95 mov dword ptr [ebx+50h], 3Bh
.text:0042AA9C and dword ptr [ebx+30h],
.text:0042AAA0 mov ecx, [ebp+var_228]
.text:0042AAA6 test ecx, 20000h
.text:0042AAAC jz short loc_42AAC6
.text:0042AAAE cmp byte ptr _KeI386VdmIoplAllowed,
.text:0042AAB5 jz short loc_42AAC6
.text:0042AAB7 mov eax, _KeI386EFlagsAndMaskV86
.text:0042AABC and eax, ecx
.text:0042AABE or eax, _KeI386EFlagsOrMaskV86
.text:0042AAC4 jmp short loc_42AAD4
.text:0042AAC6 ; ---------------------------------------------------------------------------
.text:0042AAC6
.text:0042AAC6 loc_42AAC6: ; CODE XREF: KiInitializeUserApc(x,x,x,x,x,x)+AE↑j
.text:0042AAC6 ; KiInitializeUserApc(x,x,x,x,x,x)+B7↑j
.text:0042AAC6 and ecx, 3E0DD7h
.text:0042AACC or ecx, 200h
.text:0042AAD2 mov eax, ecx
.text:0042AAD4
.text:0042AAD4 loc_42AAD4: ; CODE XREF: KiInitializeUserApc(x,x,x,x,x,x)+C6↑j
.text:0042AAD4 mov [ebx+KTRAP_FRAME.EFlags], eax
.text:0042AAD7 mov eax, large fs: ; 直接来进行修改fs寄存器
.text:0042AADD mov [ebp+var_2FC], eax
.text:0042AAE3 cmp byte ptr [eax+KTRAP_FRAME.SegGs],
.text:0042AAE7 jz short loc_42AAED
.text:0042AAE9 or byte ptr [ebx+71h], 30h
.text:0042AAED
.text:0042AAED loc_42AAED: ; CODE XREF: KiInitializeUserApc(x,x,x,x,x,x)+E9↑j
.text:0042AAED mov eax, [ebp+var_2EC]
.text:0042AAF3 mov [ebx+KTRAP_FRAME.HardwareEsp], eax
.text:0042AAF6 mov ecx, _KeUserApcDispatcher
.text:0042AAFC mov [ebx+KTRAP_FRAME._Eip], ecx ; 将eip改为_KeUserApcDispatcher这个函数,这意味着跑回来,就执行这个函数。
.text:0042AAFF and [ebx+KTRAP_FRAME.ErrCode],
.text:0042AB03 mov ecx, [ebp+arg_8]
.text:0042AB06 mov [eax], ecx
.text:0042AB08 push
.text:0042AB0A pop ecx
.text:0042AB0B add eax, ecx
.text:0042AB0D mov [ebp+var_2EC], eax
.text:0042AB13 mov edx, [ebp+arg_C]
.text:0042AB16 mov [eax], edx
.text:0042AB18 add eax, ecx
.text:0042AB1A mov [ebp+var_2EC], eax
.text:0042AB20 mov edx, [ebp+arg_10]
.text:0042AB23 mov [eax], edx
.text:0042AB25 add eax, ecx
.text:0042AB27 mov [ebp+var_2EC], eax
.text:0042AB2D mov edx, [ebp+arg_14]
.text:0042AB30 mov [eax], edx
.text:0042AB32 add eax, ecx
.text:0042AB34 mov [ebp+var_2EC], eax
.text:0042AB3A jmp short loc_42AB77
.text:0042AB3C ; ---------------------------------------------------------------------------
.text:0042AB3C
.text:0042AB3C loc_42AB3C: ; DATA XREF: .text:stru_4020B0↑o
.text:0042AB3C ; __except filter // owned by 42AA49
.text:0042AB3C mov eax, [ebp+ms_exc.exc_ptr]
.text:0042AB3F push dword ptr [eax]
.text:0042AB41 lea eax, [ebp+var_34C]
.text:0042AB47 push eax
.text:0042AB48 call _KiCopyInformation@ ; KiCopyInformation(x,x)
.text:0042AB4D retn
.text:0042AB4E ; ---------------------------------------------------------------------------
.text:0042AB4E
.text:0042AB4E loc_42AB4E: ; DATA XREF: .text:stru_4020B0↑o
.text:0042AB4E ; __except(loc_42AB3C) // owned by 42AA49
.text:0042AB4E mov esp, [ebp+ms_exc.old_esp]
.text:0042AB51 mov eax, [ebp+BugCheckParameter3]
.text:0042AB57 mov ecx, [eax+68h]
.text:0042AB5A mov [ebp+var_340], ecx
.text:0042AB60 push ; char
.text:0042AB62 push ; int
.text:0042AB64 push eax ; BugCheckParameter3
.text:0042AB65 push [ebp+var_2F4] ; int
.text:0042AB6B lea eax, [ebp+var_34C]
.text:0042AB71 push eax ; int
.text:0042AB72 call _KiDispatchException@ ; KiDispatchException(x,x,x,x,x)
.text:0042AB72 ; } // starts at 42AA49
.text:0042AB77
.text:0042AB77 loc_42AB77: ; CODE XREF: KiInitializeUserApc(x,x,x,x,x,x)+13C↑j
.text:0042AB77 or [ebp+ms_exc.registration.TryLevel], 0FFFFFFFFh
.text:0042AB7B
.text:0042AB7B loc_42AB7B: ; CODE XREF: KiInitializeUserApc(x,x,x,x,x,x)+2D↑j
.text:0042AB7B mov ecx, [ebp+var_1C]
.text:0042AB7E call @xHalReferenceHandler@ ; xHalReferenceHandler(x)
.text:0042AB83 call __SEH_epilog
.text:0042AB88 retn 18h
.text:0042AB88 ; } // starts at 42A9FE
.text:0042AB88 _KiInitializeUserApc@ endp

4. KiUserApcDispatcher(ntdll.dll)分析

; __stdcall KiUserApcDispatcher(x, x, x, x, x)
public _KiUserApcDispatcher@
_KiUserApcDispatcher@ proc near
arg_C= byte ptr 10h
lea edi, [esp+arg_C]
pop eax
call eax ; NormalRoutine 执行用户APC的总入口
push
push edi
call _ZwContinue@ ; 返回到用户内核
nop
_KiUserApcDispatcher@ endp ; sp-analysis failed

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章