首页
社区
课程
招聘
[原创]Windows内核学习笔记之线程(中)
发表于: 2021-12-22 19:06 12665

[原创]Windows内核学习笔记之线程(中)

2021-12-22 19:06
12665

上篇:Windows内核学习笔记之线程(上)

普通的函数调用是阻塞的,直到子函数执行完毕和返回后,父函数才能继续执行。如果子函数所用的时间很久,那么这次函数调用就会导致线程阻塞在这个函数内部。对于典型的Windows GUI程序,如果这样的阻塞发生在UI线程中,那么便会导致界面无法更新,失去响应。为了避免这样的情况,Windows系统的很多API支持以异步的方式工作,它们所依赖的便是NT内核的异步过程调用(APC)机制。

APC是针对线程的,每个APC都是在特定的线程环境中运行的,每个线程都有字节特有的APC链表。同一个线程的APC也是被排队执行的。由于APC的IRQL为APC_LEVEL,会高于普通线程代码的PASSIVE_LEVEL。所以,当一个线程获得控制时,它的APC过程就会立刻被执行。这一特性使得APC非常适合于实现各种异步通知事件。例如,I/O的完成通知就是通过APC来实现的。

APC是通过一种内核控制对象来表达的,称为APC对象,其定义如下:

APC对象要挂载到相应的线程对象链表中才会执行,在线程结构体ETHREAD中与APC对象比较有关联的成员有如下几个:

ApcState和SaveApcState是KAPC_STATE类型的成员,ApcStatePointer是一个包含两个元素的指针数组,ApcStateIndex则是KAPC_ENVIRONMENT的枚举类型索引。当一个线程在它所属的进程中运行时,使用的APC链表是ApcState成员,此时ApcStatePointer[0]指向的就是ApcState,并且ApcStateIndex等于0。如果线程挂载(attach)到另一个进程中,那么,尚未交付的APC对象从ApcState转移到SaveApcState中,并且ApcStatePointer[0]指向的就是SaveApcState,ApcStatePointer[1]指向的就是ApcState,ApcStateIndex等于1。所以,挂载完成以后,ApcStateIndex知名了ApcState将包含的当前进程的信息,包括在新进程环境中要执行的APC对象。此后插入的APC对象都将进入到ApcState链表中。

等到线程回到它自己的进程(detach)时,KeDetachProcess首先让属于当前进程的APC对象,即ApcState中的APC对象被交付,然后,将SaveApcState中的APC转移到ApcState中,并且设置ApcStateIndex等于0。这样就恢复了该线程被挂载以前的状态。因此,ApcState总包含了要在当前进程环境中执行的APC对象;ApcStateIndex总是指向ApcState在指针数组ApcStatePointer中的下标值。APC对象的插入操作总数以ApcStateIndex为下标来访问数组ApcStatePointer中的元素。

KAPC_STATE和定义如下:

KAPC_ENVIRONMENT枚举类型的定义如下:

OriginalApcEnvironment表示原始的进程环境;AttachedApcEnvironment表示挂载以后的新进程环境;CurrentApcEnvironment表示在APC对象初始化时线程所属的进程环境;最后的InsertApcEnvironment表示在APC对象被插入时线程所属的进程环境。在APC_STATE结构中,Process域指向了一个进程对象,代表了这些APC所关联的进程,PsGetCurrentProcess函数会从该与域获取进程对象的原因就是无论是否是挂载状态,总能获取正确的进程对象

ApcListHead数组有两个元素,分别代表了内核模式APC对象链表和用户模式APC对象链表。三个布尔变量KernelApcInProcess, KernelApcPending和UserApcPending分别表示:该线程当前正在处理一个内核APC,有内核模式APC对象正在等待被交付,以及有用户模式APC对象正在等待被交付。

不仅内核可以向一个线程发出APC请求,别的线程乃至目标线程自身也可以发出这样的请求。Win32 API为应用程序提供了一个函数QueueUserAPC就是用于此目的,而该函数是通过调用内核的NtQueueApcThread来实现的,第三个参数为函数BaesDispatchAPC函数地址,所以当从用户层插入APC的时候NormalRoutine被指定为BaseDispatchAPC,而用户真正要指向的函数则用第三个参数NormalContext传递进去

在NtQueueApcThread函数中,首先将线程的先前模式保存在局部变量中

调用函数来获得线程句柄的线程对象

对解析到的线程对象的CrossThreadFlags进行检测

如果通过检测,接下来就调用函数来申请0x30大小的内存用来保存APC对象

通过函数来初始化APC对象

将初始化完成的APC对象插入到线程中

最后退出函数

因此可以得出结论,向一个线程插入APC对象的之前需要申请一块0x30大小的内存,这块内存用来保存要插入的APC的对象,在调用KeInitializeApc的时候,指定了KernelApc的函数地址是IopDeallocateApc,根据该函数反汇编的结果可以得知,该函数的作用就是将申请到的保存APC对象的内存空间释放掉

在内核中,初始化APC对象是通过KeInitializeApc函数来实现的,而插入APC对象则是通过函数KeInsertQueueApc来实现的,KiDeliverApc则是用来交付插入的APC

在KeInitializeApc函数中首先对APC对象的类型和大小赋值,判断环境是否等于2,也就是是否是在CurrentApcEnvironment环境中

如果处在CurrentApcEnvironment环境中,则将dl赋值为当前线程的ApcStateIndex

使用传入的参数为APC对象中的Thread, KernelRoutine, RundownRoutine赋值,使用dl的值为APC对象中的ApcStateIndex赋值

判断传入的NormalRoutine是否为NULL

如果不为NULL,则会用传入的ApcMode和NormalContext为APC对象中的ApcMode和NormalContext赋值

如果为NULL,则将APC对象中的ApcMode和NormalContext赋值为寄存器edx中保存的0

将APC对象中的Inserted赋值为0,代表APC对象还未插入到APC链表中

在KeInsertQueueApc中首先要先获取APC锁

判断线程的ApcQueueable是否为0,即是否可以插入APC对象

如果可以插入,就调用KiInsertQueueApc将APC对象插入到相应的线程对象中,注意在调用之前将KAPC对象的地址赋给了ecx

最后释放掉APC锁

所以正在将APC对象插入到线程对象中是通过KiInsertQueueApc来实现的,继续看该函数的实现,函数首先将ecx赋给eax,因为ecx此时保存的是APC对象的地址,所以经过赋值以后eax保存的是APC对象的地址,判断APC的ApcStateIndex是否等于3

如果等于3则会将线程的ApcStateIndex赋给KAPC的ApcStateIndex

通过KAPC中的ApcStateIndex从线程对象中获取相应的APC_STATE,判断NormalRoutine是否为NULL

如果不为NULL,获取KAPC_STATE地址赋给edi,根据ApcMode从KAPC_STATE队列中的将上一个APC赋给esi

判断esi与edi是否相等

如果不相等,则判断KPAC队列的下一个KPAC对象是否为0

如果不为NULL,则将esi指向下一个KAPC,并跳转到上面的loc_402CB0执行

所以这个过程就是在从线程的KAPC_STATE中获取APC队列的最后一个KAPC对象,当esi执行队列中的最后一个KAPC对象的时候,就将要插入的APC对象插入到APC队列中

如果NormalRoutine为NULL,此时的edx保存的是ApcMode,所以会判断ApcMode是否为0,如果不为0,接着判断APC对象的KernelRoutine是否为PsExitSpecialApc

如果ApcMode为0或者当它不为0但是KernelRoutine不为PsExitSpecialApc的时候,将APC对象插入到线程APC队列的尾部

如果ApcMode不为0且APC对象的KernelRoutine为PsExitSpecialApc的时候,依然会把APC对象插入到APC队列中,只是此时的线程对象的ApcState的UserApcPending赋值为1

当APC对象插入到线程的APC队列以后,会将APC对象的Inserted赋值为1代表APC对象插入到线程中,将KAPC的ApcStateIndex和线程的ApcStateIndex分别赋给edi和esi,判断edi和esi是否相等

如果相等继续判断ApcMode是否为0

如果为0,则会将KernelApcPending赋值为1

如果不为0,则会继续判断线程的State, WaitMode, Alertable

如果都符合条件,就会将线程的UserApcPending赋值为1

APC对象成功插入到线程链表以后,在以下的几种情况下会执行APC的交付

当内核代码离开一个临界区或守护区,也就是在调用KeLevelGuardedRegion或KeLeaveCritiicalRegion时,通过KiCheckForKernelApcDeliver函数直接调用KiDeleverApc,或者调用KiRequestSoftwareInterrupt函数请求一个APC_LEVEL的软件中断。这是因为,当线程进入临界区或守护区时,内核模式APC被禁止了,所以,当离开时,KiCheckForKernelApcDelivery函数被调用,以便即使交付内核模式APC

当一个线程经过一次线程切换而获得控制权时,如果内核模式APC需要被交付,则在函数KiSwapThread函数返回以前,调用KiDeliverApc函数交付该内核模式APC

当系统服务或异常处理函数返回用户模式时,KiDeliverApc函数被调用以便交付用户模式APC

在APC_LEVEL软件中断发生时,HAL模块中的软件中断处理函数(HalpDispatchSoftwareInterrupt)调用KIDeliverApc交付内核模式APC。当内核代码调用KeLowerIrql函数降低IRQL到PASSIVE_LEVEL时,KiDeliverApc函数也会被调用

在交付函数KiDeliverApc中,首先对局部变量进行赋值,获得APC锁,将进程对象ETHREAD中的KernelApcPending赋值为0,代表线程没有要执行的内核APC

判断ApcState第一个链表是否有成员,也就是是否有内核APC,loc_45E56这个地址到后面执行完内核APC以后会在跳上来,通过这种方式就能遍历链表将内核APC都执行完毕

如果有内核APC,则从链表中将其取出,由于挂载到线程链表中的APC对象是通过偏移0x0C的ApcListEntry来连接的,所以需要将线程链表中获取的APC对象地址减去0x0C才可以得到APC对象的真正地址

将成员赋值到局部变量,判断NormalRoutine是否为NULL

如果NormalRoutine为NULL,则将APC对象从链表中删除,清空Inserted成员,释放APC锁并通过调用保存在KernelRoutine中的函数来释放APC对象的内存空间,最后跳转到loc_405E56继续判断是否有下一个内核APC需要执行

如果NormalRoutine不为NULL,先对线程中的KernelApcInProgress和KernelApcDisable两个成员进行判断,分别判断是否有内核APC在执行,以及内核APC是否被禁止

如果有内核APC在执行或内核APC被禁止,则结束执行

如果通过验证,则将内核APC从链表中摘除,将Inserted赋值为0,释放APC锁

调用KernelRoutine释放APC对象内存

再次判断NormalRoutine是否为NULL

不为NULL,则将KernelApcInProgress赋值为1,代表内核APC正在执行,且通过函数降低IRQL

调用NormalRoutine中保存的内核APC函数

通过函数提高IRQL

释放APC锁,将KernelApcInProgress赋值为0,代表没有内核APC函数正在执行,然后依然返回到loc_405E56处继续寻找下一个内核APC

当执行完内核APC以后,就会判断用户APC链表中是否有需要处理的APC对象

如果没有,就会释放APC锁,退出KiDeliver函数

如果有用户APC要执行,会首先判断先前模式是否为用户模式以及用户APC是否等待交互。如果先前模式不是用户模式,或者用户APC正在等待交付,则会退出函数执行

将线程对象中的UserApcPending赋值为0,并为局部变量赋值

将APC对象从链表中摘除,APC对象的Inserted赋值为0,释放APC锁

由于ebx此时保存的是KernelRoutine,所以接下来就是调用KernelRoutine来释放APC对象的内存

判断NormalRoutine是否为NULL

如果为NULL,则会调用KeTestAlertThread

如果不为NULL,则调用KiInitializeUserApc

对于用户APC函数,由于该函数是在用户空间执行的,所以需要返回到用户空间,而要返回到用户空间就会导致陷阱帧(Trap_Frame)遭到破坏,为了保证程序在执行完用户APC以后依然可以正常运行,就需要将陷阱帧中的内容保存起来,所以函数最开始除了把变量赋值到局部变量中,还通过KeContextFromKFrames函数将陷阱帧中的数据保存到Context结构的局部变量var_ContextFrame中

取出用户栈的栈顶指针,此时的指针指向陷阱帧的顶部,将其减去一段地址得到新的栈顶,验证栈顶是否可写

将局部变量var_ContextFrame中保存的陷阱帧数据赋值到新的栈顶偏移0x10处

为陷阱帧的各项寄存器赋值,验证Iopl是否为0

为0的时候,将新的栈顶指针赋给eax,继续陷阱帧中的寄存器赋值,此时陷阱帧的EIP被修改为ntdll.dll中的函数KeUserAcpDispatcher地址

由于eax此时指向新的栈顶的指针,所以接下来的代码就是将4参数赋值到栈顶,这也就是为什么在复制Context的时候,复制的目的地址是新的栈顶指针偏移0x10的地址,因为最开始的0x10的空间是用来保存这四个参数的

此时已经成功修改的陷阱帧的EIP,当函数返回到用户层的时候就会执行指定的ntdll.dll中的函数KeUserAcpDispatcher,且经过复制以后,此时用户栈的数据如下图所示

avatar

继续看ntll.dll中KeUserApcDispatcher中的函数的时候,可以看到该函数首先取出栈顶指针偏移0x10的地址赋给edi,随后弹出栈顶保存的NormalRoutine,调用该函数,将edi入栈后调用ZwContinue

NormalRoutine的函数地址是在用户层调用QueueUserApc插入用户APC的时候,指定为函数BaseDispatchAPC,该函数在kernel32.dll中,而该函数最重要的就是调用由用户所指定的NormalContext中保存的函数

调用结束以后,加下来继续调用ZwContinue进入内核,重复上面的操作

在线程创建的内核函数NtCreateThread中会调用KeInitThread函数来初始化线程对象,以及线程的启动函数。

初始化与同步有关的各个域

初始化系统服务表,APC的域

调用KeInitializeApc初始化一个内核APC对象

该APC对象的NormalRoutine为KiSuspendThread,该函数实现如下

初始化互斥体,定时器,WaitBlock,APC锁

创建内核栈

初始化栈信息

调用KeInitializeContextThread初始化域特定处理器相关的执行环境

在初始化线程的两个域以后退出函数

在KeInitializeContextThread中,函数会首先判断是否传递了ContextFrame参数,如果有该参数,说明创建的是用户线程,否则就是内核线程

如果是用户线程,就会将传递的ContextFrame赋值给局部变量var_Context

从线程对象中取出栈指针,并开辟一段空间用来吧保存数据

对局部变量var_Context进行赋值

调用KeContextToKframes将局部变量var_Context内容赋值到var_TrapFrame中,该函数的作用就是根据Context结构中的内容将数据赋值到陷阱帧(TrapFrame)结构中,此时局部变量var_SwitchFrame是在TrapFrame低地址处,该变量是KSWITCHFRAME结构,用来存储的内容就包括了创建的线程的启动函数

此时esi执行陷阱帧的头部,对陷阱帧中的几个寄存器进行赋值

对陷阱帧的先前模式和线程的先前模式赋值为用户模式

在栈中填充SystemRoutine, StartRoutine, StartContext,指定线程的启动函数以及线程的栈指针后退出函数

由上内容可以知道,启动函数为KiThreadStartup,该函数就是将栈顶的SystemRoutine弹出后调用,而SystemRoutine则是在调用KeInitThread的时候指定的,如果创建的是用户线程,该参数就会是PspUserThreadStartup,如果是内核线程就会是PspSystemThreadStartup。线程启动函数被当作第一个参数传入,该函数是kernel32.dll中的BaseProcessStart

以下是函数的部分代码,根据这些代码可以指代,该函数就是将全局变量PspSytemDll中保存的函数作为APC插入到线程中,而这个被插入的函数是ntdll.dll中的LdrInitializeThunk,该函数负责dll的装入和链接。当PspUserThreadStartup函数返回以后,KiThreadStartup函数返回到用户模式,此时,PspUserThreadStartup插入的APC被交付,于是LdrInitializeThunk函数被调用。当LdrInitializeThunk返回到用户模式APC分发器时,该线程开始在用户模式下执行,调用应用程序指定的线程启动函数,此启动函数的地址已经在APC交付时被压到用户栈中

下篇:Windows内核学习笔记之线程(下)

 
kd> dt _KAPC
nt!_KAPC
   +0x000 Type
   +0x002 Size
   +0x004 Spare0                               
   +0x008 Thread                              
   +0x00c ApcListEntry
   +0x014 KernelRoutine
   +0x018 RundownRoutine
   +0x01c NormalRoutine
   +0x020 NormalContext
   +0x024 SystemArgument1
   +0x028 SystemArgument2
   +0x02c ApcStateIndex
   +0x02d ApcMode
   +0x02e Inserted
kd> dt _KAPC
nt!_KAPC
   +0x000 Type
   +0x002 Size
   +0x004 Spare0                               
   +0x008 Thread                              
   +0x00c ApcListEntry
   +0x014 KernelRoutine
   +0x018 RundownRoutine
   +0x01c NormalRoutine
   +0x020 NormalContext
   +0x024 SystemArgument1
   +0x028 SystemArgument2
   +0x02c ApcStateIndex
   +0x02d ApcMode
   +0x02e Inserted
名称 含义
Type 为KOBJECTS枚举类型的ApcObject
Size 等于KAPC结构的大小
Thread 指向此APC对象所在的线程ETHREAD
ApcListEntry APC对象被加入到线程APC链表中的节点对象
KernelRoutine 指向释放APC对象的函数指针
RundownRoutine 函数指针(可选参数),当一个线程终止时,如果它的APC链表中还有APC对象,若RundownRoutine非空,则调用它所指函数
NormalRoutine 如果是内核APC,指向要指向的函数,如果是用户APC指向了所有用户APC都会运行的函数
NormalContext 如果是内核APC该参数为NULL,如果是用户APC该参数就是真正要执行的用户APC函数
SystemArgument1 APC函数的参数
SystemArgument2 APC函数的参数
AppStateIndex 说明了APC对象的环境状态,它是KAPC_ENVIRONMENT枚举类型的成员,一旦APC对象被插入到线程的APC链表中,则ApcStateIndex指示了它位于线程ETHREAD对象的哪个APC链表中
ApcMode 为0表示这是一个内核APC,为1说明这是用户APC
Inserted 指示该APC是否已被插入到线程的APC链表中
偏移 名称
0x034 ApcState
0x138 ApcStatePointer
0x014C SavedApcState
0x165 ApcStateIndex
 
 
 
kd> dt _KAPC_STATE
nt!_KAPC_STATE
   +0x000 ApcListHead   
   +0x010 Process       
   +0x014 KernelApcInProgress   
   +0x015 KernelApcPending   
   +0x016 UserApcPending
kd> dt _KAPC_STATE
nt!_KAPC_STATE
   +0x000 ApcListHead   
   +0x010 Process       
   +0x014 KernelApcInProgress   
   +0x015 KernelApcPending   
   +0x016 UserApcPending
typedef enum _KAPC_ENVIRONMENT{
    OriginalApcEnvironment,
    AttachedApcEnvironment,
    CurrentApcEnvironment,
    InsertApcEnvironment
}KAPC_ENVIRONMENT;
typedef enum _KAPC_ENVIRONMENT{
    OriginalApcEnvironment,
    AttachedApcEnvironment,
    CurrentApcEnvironment,
    InsertApcEnvironment
}KAPC_ENVIRONMENT;
.text:0040ED86                 public _PsGetCurrentProcess@0
.text:0040ED86 _PsGetCurrentProcess@0 proc near
.text:0040ED86                 mov     eax, large fs:124h ; IoGetCurrentProcess
.text:0040ED8C                 mov     eax, [eax+_KTHREAD.ApcState.Process]
.text:0040ED8F                 retn
.text:0040ED8F _PsGetCurrentProcess@0 endp
.text:0040ED86                 public _PsGetCurrentProcess@0
.text:0040ED86 _PsGetCurrentProcess@0 proc near
.text:0040ED86                 mov     eax, large fs:124h ; IoGetCurrentProcess
.text:0040ED8C                 mov     eax, [eax+_KTHREAD.ApcState.Process]
.text:0040ED8F                 retn
.text:0040ED8F _PsGetCurrentProcess@0 endp
.text:7C82C0CF loc_7C82C0CF:                           ; CODE XREF: QueueUserAPC(x,x,x)+18B79↓j
.text:7C82C0CF                 push    eax             ; SystemArgument2
.text:7C82C0D0                 push    [ebp+dwData]    ; SystemArgument1
.text:7C82C0D3                 push    [ebp+pfnAPC]    ; NormalContext
.text:7C82C0D6                 push    offset _BaseDispatchAPC@12 ; NormalRoutine
.text:7C82C0DB                 push    [ebp+hThread]   ; ThreadHandle
.text:7C82C0DE                 call    ds:__imp__NtQueueApcThread@20 ; NtQueueApcThread(x,x,x,x,x)
.text:7C82C0E4                 xor     ecx, ecx
.text:7C82C0E6                 test    eax, eax
.text:7C82C0E8                 setnl   cl
.text:7C82C0EB                 mov     eax, ecx
.text:7C82C0CF loc_7C82C0CF:                           ; CODE XREF: QueueUserAPC(x,x,x)+18B79↓j
.text:7C82C0CF                 push    eax             ; SystemArgument2
.text:7C82C0D0                 push    [ebp+dwData]    ; SystemArgument1
.text:7C82C0D3                 push    [ebp+pfnAPC]    ; NormalContext
.text:7C82C0D6                 push    offset _BaseDispatchAPC@12 ; NormalRoutine
.text:7C82C0DB                 push    [ebp+hThread]   ; ThreadHandle
.text:7C82C0DE                 call    ds:__imp__NtQueueApcThread@20 ; NtQueueApcThread(x,x,x,x,x)
.text:7C82C0E4                 xor     ecx, ecx
.text:7C82C0E6                 test    eax, eax
.text:7C82C0E8                 setnl   cl
.text:7C82C0EB                 mov     eax, ecx
PAGE:004C2AAA ; NTSTATUS __stdcall NtQueueApcThread(HANDLE ThreadHandle, PKNORMAL_ROUTINE ApcRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
PAGE:004C2AAA _NtQueueApcThread@20 proc near          ; DATA XREF: .text:0040DAF0↑o
PAGE:004C2AAA
PAGE:004C2AAA AccessMode      = byte ptr -4
PAGE:004C2AAA ThreadHandle    = dword ptr  8
PAGE:004C2AAA ApcRoutine      = dword ptr  0Ch
PAGE:004C2AAA NormalContext   = dword ptr  10h
PAGE:004C2AAA SystemArgument1 = dword ptr  14h
PAGE:004C2AAA SystemArgument2 = dword ptr  18h
PAGE:004C2AAA
PAGE:004C2AAA ; FUNCTION CHUNK AT PAGE:0052E6D5 SIZE 00000025 BYTES
PAGE:004C2AAA
PAGE:004C2AAA                 mov     edi, edi
PAGE:004C2AAC                 push    ebp
PAGE:004C2AAD                 mov     ebp, esp
PAGE:004C2AAF                 push    ecx
PAGE:004C2AB0                 push    ebx
PAGE:004C2AB1                 push    esi
PAGE:004C2AB2                 mov     eax, large fs:124h ; 将线程对象赋给eax
PAGE:004C2AB8                 mov     al, [eax+_KTHREAD.PreviousMode]
PAGE:004C2ABE                 mov     [ebp+AccessMode], al ; 为局部变量赋值
PAGE:004C2AAA ; NTSTATUS __stdcall NtQueueApcThread(HANDLE ThreadHandle, PKNORMAL_ROUTINE ApcRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
PAGE:004C2AAA _NtQueueApcThread@20 proc near          ; DATA XREF: .text:0040DAF0↑o
PAGE:004C2AAA
PAGE:004C2AAA AccessMode      = byte ptr -4
PAGE:004C2AAA ThreadHandle    = dword ptr  8
PAGE:004C2AAA ApcRoutine      = dword ptr  0Ch
PAGE:004C2AAA NormalContext   = dword ptr  10h
PAGE:004C2AAA SystemArgument1 = dword ptr  14h
PAGE:004C2AAA SystemArgument2 = dword ptr  18h
PAGE:004C2AAA
PAGE:004C2AAA ; FUNCTION CHUNK AT PAGE:0052E6D5 SIZE 00000025 BYTES
PAGE:004C2AAA
PAGE:004C2AAA                 mov     edi, edi
PAGE:004C2AAC                 push    ebp
PAGE:004C2AAD                 mov     ebp, esp
PAGE:004C2AAF                 push    ecx
PAGE:004C2AB0                 push    ebx
PAGE:004C2AB1                 push    esi
PAGE:004C2AB2                 mov     eax, large fs:124h ; 将线程对象赋给eax
PAGE:004C2AB8                 mov     al, [eax+_KTHREAD.PreviousMode]
PAGE:004C2ABE                 mov     [ebp+AccessMode], al ; 为局部变量赋值
PAGE:004C2AC1                 xor     esi, esi        ; esi清0
PAGE:004C2AC3                 push    esi             ; HandleInformation
PAGE:004C2AC4                 lea     eax, [ebp+Object]
PAGE:004C2AC7                 push    eax             ; Object
PAGE:004C2AC8                 push    dword ptr [ebp+AccessMode] ; AccessMode
PAGE:004C2ACB                 push    _PsThreadType   ; ObjectType
PAGE:004C2AD1                 push    10h             ; DesiredAccess
PAGE:004C2AD3                 push    [ebp+ThreadHandle] ; Handle
PAGE:004C2AD6                 call    _ObReferenceObjectByHandle@24 ; ObReferenceObjectByHandle(x,x,x,x,x,x)
PAGE:004C2ADB                 mov     ebx, eax
PAGE:004C2ADD                 cmp     ebx, esi
PAGE:004C2ADF                 jl      short loc_4C2B42
PAGE:004C2AC1                 xor     esi, esi        ; esi清0
PAGE:004C2AC3                 push    esi             ; HandleInformation
PAGE:004C2AC4                 lea     eax, [ebp+Object]
PAGE:004C2AC7                 push    eax             ; Object
PAGE:004C2AC8                 push    dword ptr [ebp+AccessMode] ; AccessMode
PAGE:004C2ACB                 push    _PsThreadType   ; ObjectType
PAGE:004C2AD1                 push    10h             ; DesiredAccess
PAGE:004C2AD3                 push    [ebp+ThreadHandle] ; Handle
PAGE:004C2AD6                 call    _ObReferenceObjectByHandle@24 ; ObReferenceObjectByHandle(x,x,x,x,x,x)
PAGE:004C2ADB                 mov     ebx, eax
PAGE:004C2ADD                 cmp     ebx, esi
PAGE:004C2ADF                 jl      short loc_4C2B42
PAGE:004C2AE1                 mov     eax, [ebp+Object]
PAGE:004C2AE4                 xor     ebx, ebx
PAGE:004C2AE6                 test    byte ptr [eax+_ETHREAD.___u24.CrossThreadFlags], OBJ_PERMANENT
PAGE:004C2AED                 jnz     loc_52E6D5
PAGE:004C2AE1                 mov     eax, [ebp+Object]
PAGE:004C2AE4                 xor     ebx, ebx
PAGE:004C2AE6                 test    byte ptr [eax+_ETHREAD.___u24.CrossThreadFlags], OBJ_PERMANENT
PAGE:004C2AED                 jnz     loc_52E6D5
PAGE:004C2AF3                 push    edi
PAGE:004C2AF4                 push    'pasP'          ; Tag
PAGE:004C2AF9                 push    30h             ; NumberOfBytes
PAGE:004C2AFB                 push    8               ; PoolType
PAGE:004C2AFD                 call    _ExAllocatePoolWithQuotaTag@12 ; ExAllocatePoolWithQuotaTag(x,x,x)
PAGE:004C2B02                 mov     edi, eax        ; 将申请到的内存地址赋给edi
PAGE:004C2B04                 cmp     edi, esi
PAGE:004C2B06                 jz      loc_52E6DF
PAGE:004C2AF3                 push    edi
PAGE:004C2AF4                 push    'pasP'          ; Tag
PAGE:004C2AF9                 push    30h             ; NumberOfBytes
PAGE:004C2AFB                 push    8               ; PoolType
PAGE:004C2AFD                 call    _ExAllocatePoolWithQuotaTag@12 ; ExAllocatePoolWithQuotaTag(x,x,x)
PAGE:004C2B02                 mov     edi, eax        ; 将申请到的内存地址赋给edi
PAGE:004C2B04                 cmp     edi, esi
PAGE:004C2B06                 jz      loc_52E6DF
PAGE:004C2B0C                 push    [ebp+NormalContext] ; NormalContext
PAGE:004C2B0F                 push    1               ; ApcMode
PAGE:004C2B11                 push    [ebp+ApcRoutine] ; NormalRoutine
PAGE:004C2B14                 push    esi             ; RundownRoutine
PAGE:004C2B15                 push    offset _IopDeallocateApc@20 ; KernelRoutine
PAGE:004C2B1A                 push    esi             ; int
PAGE:004C2B1B                 push    [ebp+ThreadHandle] ; Thread
PAGE:004C2B1E                 push    edi             ; Apc
PAGE:004C2B1F                 call    _KeInitializeApc@32
PAGE:004C2B0C                 push    [ebp+NormalContext] ; NormalContext
PAGE:004C2B0F                 push    1               ; ApcMode
PAGE:004C2B11                 push    [ebp+ApcRoutine] ; NormalRoutine
PAGE:004C2B14                 push    esi             ; RundownRoutine
PAGE:004C2B15                 push    offset _IopDeallocateApc@20 ; KernelRoutine
PAGE:004C2B1A                 push    esi             ; int
PAGE:004C2B1B                 push    [ebp+ThreadHandle] ; Thread
PAGE:004C2B1E                 push    edi             ; Apc
PAGE:004C2B1F                 call    _KeInitializeApc@32
PAGE:004C2B24                 push    esi             ; Increment
PAGE:004C2B25                 push    [ebp+SystemArgument2] ; SystemArgument2
PAGE:004C2B28                 push    [ebp+SystemArgument1] ; SystemArgument1
PAGE:004C2B2B                 push    edi             ; Apc
PAGE:004C2B2C                 call    _KeInsertQueueApc@16 ; KeInsertQueueApc(x,x,x,x)
PAGE:004C2B31                 test    al, al
PAGE:004C2B33                 jz      loc_52E6E9
PAGE:004C2B24                 push    esi             ; Increment
PAGE:004C2B25                 push    [ebp+SystemArgument2] ; SystemArgument2
PAGE:004C2B28                 push    [ebp+SystemArgument1] ; SystemArgument1
PAGE:004C2B2B                 push    edi             ; Apc
PAGE:004C2B2C                 call    _KeInsertQueueApc@16 ; KeInsertQueueApc(x,x,x,x)
PAGE:004C2B31                 test    al, al
PAGE:004C2B33                 jz      loc_52E6E9
PAGE:004C2B39 loc_4C2B39:                             ; CODE XREF: NtQueueApcThread(x,x,x,x,x)+6BC3A↓j
PAGE:004C2B39                                         ; NtQueueApcThread(x,x,x,x,x)+6BC4B↓j
PAGE:004C2B39                 pop     edi
PAGE:004C2B3A
PAGE:004C2B3A loc_4C2B3A:                             ; CODE XREF: NtQueueApcThread(x,x,x,x,x)+6BC30↓j
PAGE:004C2B3A                 mov     ecx, [ebp+ThreadHandle] ; Object
PAGE:004C2B3D                 call    @ObfDereferenceObject@4 ; ObfDereferenceObject(x)
PAGE:004C2B42
PAGE:004C2B42 loc_4C2B42:                             ; CODE XREF: NtQueueApcThread(x,x,x,x,x)+35↑j
PAGE:004C2B42                 pop     esi
PAGE:004C2B43                 mov     eax, ebx
PAGE:004C2B45                 pop     ebx
PAGE:004C2B46                 leave
PAGE:004C2B47                 retn    14h
PAGE:004C2B47 _NtQueueApcThread@20 endp
PAGE:004C2B39 loc_4C2B39:                             ; CODE XREF: NtQueueApcThread(x,x,x,x,x)+6BC3A↓j
PAGE:004C2B39                                         ; NtQueueApcThread(x,x,x,x,x)+6BC4B↓j
PAGE:004C2B39                 pop     edi
PAGE:004C2B3A
PAGE:004C2B3A loc_4C2B3A:                             ; CODE XREF: NtQueueApcThread(x,x,x,x,x)+6BC30↓j
PAGE:004C2B3A                 mov     ecx, [ebp+ThreadHandle] ; Object
PAGE:004C2B3D                 call    @ObfDereferenceObject@4 ; ObfDereferenceObject(x)
PAGE:004C2B42
PAGE:004C2B42 loc_4C2B42:                             ; CODE XREF: NtQueueApcThread(x,x,x,x,x)+35↑j
PAGE:004C2B42                 pop     esi
PAGE:004C2B43                 mov     eax, ebx
PAGE:004C2B45                 pop     ebx
PAGE:004C2B46                 leave
PAGE:004C2B47                 retn    14h
PAGE:004C2B47 _NtQueueApcThread@20 endp
PAGE:0049F852 ; int __stdcall IopDeallocateApc(PVOID P, int, int, int, int)
PAGE:0049F852 _IopDeallocateApc@20 proc near          ; DATA XREF: IoRaiseHardError(x,x,x)+16070↑o
PAGE:0049F852                                         ; IoRaiseInformationalHardError(x,x,x)+123↑o ...
PAGE:0049F852
PAGE:0049F852 P               = dword ptr  8
PAGE:0049F852
PAGE:0049F852                 mov     edi, edi
PAGE:0049F854                 push    ebp
PAGE:0049F855                 mov     ebp, esp
PAGE:0049F857                 push    0               ; Tag
PAGE:0049F859                 push    [ebp+P]         ; P
PAGE:0049F85C                 call    _ExFreePoolWithTag@8 ; ExFreePoolWithTag(x,x)
PAGE:0049F861                 pop     ebp
PAGE:0049F862                 retn    14h
PAGE:0049F862 _IopDeallocateApc@20 endp
PAGE:0049F852 ; int __stdcall IopDeallocateApc(PVOID P, int, int, int, int)
PAGE:0049F852 _IopDeallocateApc@20 proc near          ; DATA XREF: IoRaiseHardError(x,x,x)+16070↑o
PAGE:0049F852                                         ; IoRaiseInformationalHardError(x,x,x)+123↑o ...
PAGE:0049F852
PAGE:0049F852 P               = dword ptr  8
PAGE:0049F852
PAGE:0049F852                 mov     edi, edi
PAGE:0049F854                 push    ebp
PAGE:0049F855                 mov     ebp, esp
PAGE:0049F857                 push    0               ; Tag
PAGE:0049F859                 push    [ebp+P]         ; P
PAGE:0049F85C                 call    _ExFreePoolWithTag@8 ; ExFreePoolWithTag(x,x)
PAGE:0049F861                 pop     ebp
PAGE:0049F862                 retn    14h
PAGE:0049F862 _IopDeallocateApc@20 endp
.text:0040EBD9 ; int __stdcall KeInitializeApc(PRKAPC Apc, PRKTHREAD Thread, int, PKKERNEL_ROUTINE KernelRoutine, PKRUNDOWN_ROUTINE RundownRoutine, PKNORMAL_ROUTINE NormalRoutine, KPROCESSOR_MODE ApcMode, PVOID NormalContext)
.text:0040EBD9                 public _KeInitializeApc@32
.text:0040EBD9 _KeInitializeApc@32 proc near           ; CODE XREF: NtSetTimer(x,x,x,x,x,x,x)+12F↓p
.text:0040EBD9                                         ; IopfCompleteRequest(x,x)+11581↓p ...
.text:0040EBD9
.text:0040EBD9 Apc             = dword ptr  8
.text:0040EBD9 Thread          = dword ptr  0Ch
.text:0040EBD9 Environment     = dword ptr  10h
.text:0040EBD9 KernelRoutine   = dword ptr  14h
.text:0040EBD9 RundownRoutine  = dword ptr  18h
.text:0040EBD9 NormalRoutine   = dword ptr  1Ch
.text:0040EBD9 ApcMode         = byte ptr  20h
.text:0040EBD9 NormalContext   = dword ptr  24h
.text:0040EBD9
.text:0040EBD9                 mov     edi, edi
.text:0040EBDB                 push    ebp
.text:0040EBDC                 mov     ebp, esp
.text:0040EBDE                 mov     eax, [ebp+Apc]  ; 将APC赋给eax
.text:0040EBE1                 mov     edx, [ebp+Environment] ; 将APC环境赋给edx
.text:0040EBE4                 cmp     edx, 2          ; 判断APC环境是否为CurrentApcEnvironment
.text:0040EBE7                 mov     ecx, [ebp+Thread] ; 将线程对象赋给ecx
.text:0040EBEA                 mov     [eax+KAPC.Type], ApcObject ; 为APC类型赋值
.text:0040EBEF                 mov     [eax+KAPC.Size], 30h ; 为结构体的大小赋值
.text:0040EBF5                 jz      loc_40FB78
.text:0040EBD9 ; int __stdcall KeInitializeApc(PRKAPC Apc, PRKTHREAD Thread, int, PKKERNEL_ROUTINE KernelRoutine, PKRUNDOWN_ROUTINE RundownRoutine, PKNORMAL_ROUTINE NormalRoutine, KPROCESSOR_MODE ApcMode, PVOID NormalContext)
.text:0040EBD9                 public _KeInitializeApc@32
.text:0040EBD9 _KeInitializeApc@32 proc near           ; CODE XREF: NtSetTimer(x,x,x,x,x,x,x)+12F↓p
.text:0040EBD9                                         ; IopfCompleteRequest(x,x)+11581↓p ...
.text:0040EBD9
.text:0040EBD9 Apc             = dword ptr  8
.text:0040EBD9 Thread          = dword ptr  0Ch
.text:0040EBD9 Environment     = dword ptr  10h
.text:0040EBD9 KernelRoutine   = dword ptr  14h
.text:0040EBD9 RundownRoutine  = dword ptr  18h
.text:0040EBD9 NormalRoutine   = dword ptr  1Ch
.text:0040EBD9 ApcMode         = byte ptr  20h
.text:0040EBD9 NormalContext   = dword ptr  24h
.text:0040EBD9
.text:0040EBD9                 mov     edi, edi
.text:0040EBDB                 push    ebp
.text:0040EBDC                 mov     ebp, esp
.text:0040EBDE                 mov     eax, [ebp+Apc]  ; 将APC赋给eax
.text:0040EBE1                 mov     edx, [ebp+Environment] ; 将APC环境赋给edx
.text:0040EBE4                 cmp     edx, 2          ; 判断APC环境是否为CurrentApcEnvironment
.text:0040EBE7                 mov     ecx, [ebp+Thread] ; 将线程对象赋给ecx
.text:0040EBEA                 mov     [eax+KAPC.Type], ApcObject ; 为APC类型赋值
.text:0040EBEF                 mov     [eax+KAPC.Size], 30h ; 为结构体的大小赋值
.text:0040EBF5                 jz      loc_40FB78
.text:0040FB78 loc_40FB78:                             ; CODE XREF: KeInitializeApc(x,x,x,x,x,x,x,x)+1C↑j
.text:0040FB78                 mov     dl, [ecx+_KTHREAD.ApcStateIndex]
.text:0040FB7E                 jmp     loc_40EBFB
.text:0040FB78 loc_40FB78:                             ; CODE XREF: KeInitializeApc(x,x,x,x,x,x,x,x)+1C↑j
.text:0040FB78                 mov     dl, [ecx+_KTHREAD.ApcStateIndex]
.text:0040FB7E                 jmp     loc_40EBFB
.text:0040EBFB loc_40EBFB:                             ; CODE XREF: KeInitializeApc(x,x,x,x,x,x,x,x)+FA5↓j
.text:0040EBFB                 mov     [eax+KAPC.Thread], ecx ; 为APC对象所在的线程对象KTHREAD对象赋值
.text:0040EBFE                 mov     ecx, [ebp+KernelRoutine]
.text:0040EC01                 mov     [eax+KAPC.KernelRoutine], ecx ; 为KernelRoutine对象赋值
.text:0040EC04                 mov     ecx, [ebp+RundownRoutine]
.text:0040EC07                 mov     [eax+KAPC.ApcStateIndex], dl ; 将dl赋值给ApcStateIndex
.text:0040EC0A                 mov     [eax+KAPC.RundownRoutine], ecx
.text:0040EBFB loc_40EBFB:                             ; CODE XREF: KeInitializeApc(x,x,x,x,x,x,x,x)+FA5↓j
.text:0040EBFB                 mov     [eax+KAPC.Thread], ecx ; 为APC对象所在的线程对象KTHREAD对象赋值
.text:0040EBFE                 mov     ecx, [ebp+KernelRoutine]
.text:0040EC01                 mov     [eax+KAPC.KernelRoutine], ecx ; 为KernelRoutine对象赋值
.text:0040EC04                 mov     ecx, [ebp+RundownRoutine]
.text:0040EC07                 mov     [eax+KAPC.ApcStateIndex], dl ; 将dl赋值给ApcStateIndex
.text:0040EC0A                 mov     [eax+KAPC.RundownRoutine], ecx
.text:0040EC0D                 mov     ecx, [ebp+NormalRoutine]
.text:0040EC10                 xor     edx, edx        ; edx清0
.text:0040EC12                 cmp     ecx, edx
.text:0040EC14                 mov     [eax+KAPC.NormalRoutine], ecx ; 判断NormalRoutine是否为NULL
.text:0040EC17                 jnz     loc_40EDEF
.text:0040EC0D                 mov     ecx, [ebp+NormalRoutine]
.text:0040EC10                 xor     edx, edx        ; edx清0
.text:0040EC12                 cmp     ecx, edx
.text:0040EC14                 mov     [eax+KAPC.NormalRoutine], ecx ; 判断NormalRoutine是否为NULL
.text:0040EC17                 jnz     loc_40EDEF
.text:0040EDEF loc_40EDEF:                             ; CODE XREF: KeInitializeApc(x,x,x,x,x,x,x,x)+3E↑j
.text:0040EDEF                 mov     cl, [ebp+ApcMode]
.text:0040EDF2                 mov     [eax+KAPC.ApcMode], cl
.text:0040EDF5                 mov     ecx, [ebp+NormalContext]
.text:0040EDF8                 mov     [eax+KAPC.NormalContext], ecx
.text:0040EDFB                 jmp     loc_40EC23
.text:0040EDEF loc_40EDEF:                             ; CODE XREF: KeInitializeApc(x,x,x,x,x,x,x,x)+3E↑j
.text:0040EDEF                 mov     cl, [ebp+ApcMode]
.text:0040EDF2                 mov     [eax+KAPC.ApcMode], cl
.text:0040EDF5                 mov     ecx, [ebp+NormalContext]
.text:0040EDF8                 mov     [eax+KAPC.NormalContext], ecx
.text:0040EDFB                 jmp     loc_40EC23
.text:0040EC1D                 mov     [eax+_KAPC.ApcMode], dl
.text:0040EC20                 mov     [eax+KAPC.NormalContext], edx
.text:0040EC1D                 mov     [eax+_KAPC.ApcMode], dl
.text:0040EC20                 mov     [eax+KAPC.NormalContext], edx
.text:0040EC23 loc_40EC23:                             ; CODE XREF: KeInitializeApc(x,x,x,x,x,x,x,x)+222↓j
.text:0040EC23                 mov     [eax+KAPC.Inserted], dl ; Insert赋值为0,代表还未插入到APC链表中
.text:0040EC26                 pop     ebp
.text:0040EC27                 retn    20h
.text:0040EC27 _KeInitializeApc@32 endp
.text:0040EC23 loc_40EC23:                             ; CODE XREF: KeInitializeApc(x,x,x,x,x,x,x,x)+222↓j
.text:0040EC23                 mov     [eax+KAPC.Inserted], dl ; Insert赋值为0,代表还未插入到APC链表中
.text:0040EC26                 pop     ebp
.text:0040EC27                 retn    20h
.text:0040EC27 _KeInitializeApc@32 endp
.text:0040EC2F ; int __stdcall KeInsertQueueApc(PRKAPC Apc, PVOID SystemArgument1, PVOID SystemArgument2, KPRIORITY Increment)
.text:0040EC2F                 public _KeInsertQueueApc@16
.text:0040EC2F _KeInsertQueueApc@16 proc near          ; CODE XREF: ExpTimerDpcRoutine(x,x,x,x)+30↓p
.text:0040EC2F                                         ; IopfCompleteRequest(x,x)+11528↓p ...
.text:0040EC2F
.text:0040EC2F LockHandle      = _KLOCK_QUEUE_HANDLE ptr -0Ch
.text:0040EC2F Apc             = dword ptr  8
.text:0040EC2F SystemArgument1 = dword ptr  0Ch
.text:0040EC2F SystemArgument2 = dword ptr  10h
.text:0040EC2F Increment       = dword ptr  14h
.text:0040EC2F
.text:0040EC2F                 mov     edi, edi
.text:0040EC31                 push    ebp
.text:0040EC32                 mov     ebp, esp
.text:0040EC34                 sub     esp, 0Ch
.text:0040EC37                 push    ebx
.text:0040EC38                 push    esi             ; Increment
.text:0040EC39                 push    edi             ; Apc
.text:0040EC3A                 mov     edi, [ebp+Apc]
.text:0040EC3D                 mov     esi, [edi+_KAPC.Thread]
.text:0040EC40                 lea     ecx, [esi+_KTHREAD.ApcQueueLock]
.text:0040EC46                 lea     edx, [ebp+LockHandle]
.text:0040EC49                 call    ds:__imp_@KeAcquireInStackQueuedSpinLockRaiseToSynch@8 ; KeAcquireInStackQueuedSpinLockRaiseToSynch(x,x)
.text:0040EC4F                 mov     eax, large fs:20h
.text:0040EC55                 lea     ecx, [eax+418h]
.text:0040EC5B                 call    @KeAcquireQueuedSpinLockAtDpcLevel@4
.text:0040EC2F ; int __stdcall KeInsertQueueApc(PRKAPC Apc, PVOID SystemArgument1, PVOID SystemArgument2, KPRIORITY Increment)
.text:0040EC2F                 public _KeInsertQueueApc@16
.text:0040EC2F _KeInsertQueueApc@16 proc near          ; CODE XREF: ExpTimerDpcRoutine(x,x,x,x)+30↓p
.text:0040EC2F                                         ; IopfCompleteRequest(x,x)+11528↓p ...
.text:0040EC2F
.text:0040EC2F LockHandle      = _KLOCK_QUEUE_HANDLE ptr -0Ch
.text:0040EC2F Apc             = dword ptr  8
.text:0040EC2F SystemArgument1 = dword ptr  0Ch
.text:0040EC2F SystemArgument2 = dword ptr  10h
.text:0040EC2F Increment       = dword ptr  14h
.text:0040EC2F
.text:0040EC2F                 mov     edi, edi
.text:0040EC31                 push    ebp
.text:0040EC32                 mov     ebp, esp
.text:0040EC34                 sub     esp, 0Ch
.text:0040EC37                 push    ebx
.text:0040EC38                 push    esi             ; Increment
.text:0040EC39                 push    edi             ; Apc
.text:0040EC3A                 mov     edi, [ebp+Apc]
.text:0040EC3D                 mov     esi, [edi+_KAPC.Thread]
.text:0040EC40                 lea     ecx, [esi+_KTHREAD.ApcQueueLock]
.text:0040EC46                 lea     edx, [ebp+LockHandle]
.text:0040EC49                 call    ds:__imp_@KeAcquireInStackQueuedSpinLockRaiseToSynch@8 ; KeAcquireInStackQueuedSpinLockRaiseToSynch(x,x)
.text:0040EC4F                 mov     eax, large fs:20h
.text:0040EC55                 lea     ecx, [eax+418h]
.text:0040EC5B                 call    @KeAcquireQueuedSpinLockAtDpcLevel@4
.text:0040EC60                 xor     bl, bl          ; bl清0
.text:0040EC62                 cmp     [esi+_KTHREAD.ApcQueueable], bl ; 判断ApcQueueable是否为0
.text:0040EC68                 jz      short loc_40EC82
.text:0040EC60                 xor     bl, bl          ; bl清0
.text:0040EC62                 cmp     [esi+_KTHREAD.ApcQueueable], bl ; 判断ApcQueueable是否为0
.text:0040EC68                 jz      short loc_40EC82
.text:0040EC6A                 mov     eax, [ebp+SystemArgument1]
.text:0040EC6D                 mov     edx, [ebp+Increment]
.text:0040EC70                 mov     [edi+KAPC.SystemArgument1], eax
.text:0040EC73                 mov     eax, [ebp+SystemArgument2]
.text:0040EC76                 mov     ecx, edi
.text:0040EC78                 mov     [edi+KAPC.SystemArgument2], eax
.text:0040EC7B                 call    @KiInsertQueueApc@8 ; KiInsertQueueApc(x,x)
.text:0040EC80                 mov     bl, al          ; 将返回值赋给bl
.text:0040EC6A                 mov     eax, [ebp+SystemArgument1]
.text:0040EC6D                 mov     edx, [ebp+Increment]
.text:0040EC70                 mov     [edi+KAPC.SystemArgument1], eax
.text:0040EC73                 mov     eax, [ebp+SystemArgument2]
.text:0040EC76                 mov     ecx, edi
.text:0040EC78                 mov     [edi+KAPC.SystemArgument2], eax
.text:0040EC7B                 call    @KiInsertQueueApc@8 ; KiInsertQueueApc(x,x)
.text:0040EC80                 mov     bl, al          ; 将返回值赋给bl
.text:0040EC82 loc_40EC82:                             ; CODE XREF: KeInsertQueueApc(x,x,x,x)+39↑j
.text:0040EC82                 mov     eax, large fs:20h
.text:0040EC88                 lea     ecx, [eax+418h]
.text:0040EC8E                 call    @KeReleaseQueuedSpinLockFromDpcLevel@4 ; KeReleaseQueuedSpinLockFromDpcLevel(x)
.text:0040EC93                 lea     ecx, [ebp+LockHandle] ; LockHandle
.text:0040EC96                 call    ds:__imp_@KeReleaseInStackQueuedSpinLock@4 ; KeReleaseInStackQueuedSpinLock(x)
.text:0040EC9C                 pop     edi
.text:0040EC9D                 pop     esi
.text:0040EC9E                 mov     al, bl          ; 用bl赋值给al作为返回值
.text:0040ECA0                 pop     ebx
.text:0040ECA1                 leave
.text:0040ECA2                 retn    10h
.text:0040ECA2 _KeInsertQueueApc@16 endp
.text:0040EC82 loc_40EC82:                             ; CODE XREF: KeInsertQueueApc(x,x,x,x)+39↑j
.text:0040EC82                 mov     eax, large fs:20h
.text:0040EC88                 lea     ecx, [eax+418h]
.text:0040EC8E                 call    @KeReleaseQueuedSpinLockFromDpcLevel@4 ; KeReleaseQueuedSpinLockFromDpcLevel(x)
.text:0040EC93                 lea     ecx, [ebp+LockHandle] ; LockHandle
.text:0040EC96                 call    ds:__imp_@KeReleaseInStackQueuedSpinLock@4 ; KeReleaseInStackQueuedSpinLock(x)
.text:0040EC9C                 pop     edi
.text:0040EC9D                 pop     esi
.text:0040EC9E                 mov     al, bl          ; 用bl赋值给al作为返回值
.text:0040ECA0                 pop     ebx
.text:0040ECA1                 leave
.text:0040ECA2                 retn    10h
.text:0040ECA2 _KeInsertQueueApc@16 endp
.text:00402C6A ; int __cdecl KiInsertQueueApc(PKAPC Apc, KPRIORITY Increment)
.text:00402C6A @KiInsertQueueApc@8 proc near           ; CODE XREF: KeInsertQueueApc(x,x,x,x)+4C↓p
.text:00402C6A                                         ; KeSuspendThread(x)+68↓p ...
.text:00402C6A
.text:00402C6A var_Increament  = dword ptr -4
.text:00402C6A Apc             = dword ptr  8
.text:00402C6A Increment       = dword ptr  0Ch
.text:00402C6A
.text:00402C6A                 mov     edi, edi
.text:00402C6C                 push    ebp
.text:00402C6D                 mov     ebp, esp
.text:00402C6F                 push    ecx
.text:00402C70                 mov     eax, ecx
.text:00402C72                 cmp     [eax+KAPC.Inserted], 0 ; APC是否已经插入到线程中
.text:00402C76                 mov     ecx, [eax+_KAPC.Thread] ; 将线程对象赋给ecx
.text:00402C79                 mov     [ebp+var_Increament], edx
.text:00402C7C                 jnz     loc_44B3BF
.text:00402C82                 cmp     [eax+KAPC.ApcStateIndex], 3 ; ApcStateIndex是否等于3
.text:00402C86                 jz      loc_44B3C3
.text:00402C6A ; int __cdecl KiInsertQueueApc(PKAPC Apc, KPRIORITY Increment)
.text:00402C6A @KiInsertQueueApc@8 proc near           ; CODE XREF: KeInsertQueueApc(x,x,x,x)+4C↓p
.text:00402C6A                                         ; KeSuspendThread(x)+68↓p ...
.text:00402C6A
.text:00402C6A var_Increament  = dword ptr -4
.text:00402C6A Apc             = dword ptr  8
.text:00402C6A Increment       = dword ptr  0Ch
.text:00402C6A
.text:00402C6A                 mov     edi, edi
.text:00402C6C                 push    ebp
.text:00402C6D                 mov     ebp, esp
.text:00402C6F                 push    ecx
.text:00402C70                 mov     eax, ecx
.text:00402C72                 cmp     [eax+KAPC.Inserted], 0 ; APC是否已经插入到线程中
.text:00402C76                 mov     ecx, [eax+_KAPC.Thread] ; 将线程对象赋给ecx
.text:00402C79                 mov     [ebp+var_Increament], edx
.text:00402C7C                 jnz     loc_44B3BF
.text:00402C82                 cmp     [eax+KAPC.ApcStateIndex], 3 ; ApcStateIndex是否等于3
.text:00402C86                 jz      loc_44B3C3
.text:0044B3C3 loc_44B3C3:                             ; CODE XREF: KiInsertQueueApc(x,x)+1C↑j
.text:0044B3C3                 mov     dl, [ecx+_KTHREAD.ApcStateIndex]
.text:0044B3C9                 mov     [eax+KAPC.ApcStateIndex], dl
.text:0044B3CC                 jmp     loc_402C8C
.text:0044B3C3 loc_44B3C3:                             ; CODE XREF: KiInsertQueueApc(x,x)+1C↑j
.text:0044B3C3                 mov     dl, [ecx+_KTHREAD.ApcStateIndex]
.text:0044B3C9                 mov     [eax+KAPC.ApcStateIndex], dl
.text:0044B3CC                 jmp     loc_402C8C
.text:00402C8C loc_402C8C:                             ; CODE XREF: KiInsertQueueApc(x,x)+48762↓j
.text:00402C8C                 cmp     [eax+KAPC.NormalRoutine], 0 ; NormalRoutine是否为NULL
.text:00402C90                 movsx   edx, [eax+KAPC.ApcStateIndex] ; 将ApcStateIndex赋给edx
.text:00402C94                 push    ebx
.text:00402C95                 push    esi
.text:00402C96                 push    edi
.text:00402C97                 mov     edi, [ecx+edx*4+_KTHREAD.ApcStatePointer] ; 将相应的KAPC_STATE赋给edi
.text:00402C9E                 mov     dl, [eax+KAPC.ApcMode] ; 将ApcMode赋给dl
.text:00402CA1                 jnz     loc_41049E
.text:00402C8C loc_402C8C:                             ; CODE XREF: KiInsertQueueApc(x,x)+48762↓j
.text:00402C8C                 cmp     [eax+KAPC.NormalRoutine], 0 ; NormalRoutine是否为NULL
.text:00402C90                 movsx   edx, [eax+KAPC.ApcStateIndex] ; 将ApcStateIndex赋给edx
.text:00402C94                 push    ebx
.text:00402C95                 push    esi
.text:00402C96                 push    edi
.text:00402C97                 mov     edi, [ecx+edx*4+_KTHREAD.ApcStatePointer] ; 将相应的KAPC_STATE赋给edi
.text:00402C9E                 mov     dl, [eax+KAPC.ApcMode] ; 将ApcMode赋给dl
.text:00402CA1                 jnz     loc_41049E
.text:00402CA7                 movsx   esi, dl         ; 将ApcMode赋给esi
.text:00402CAA                 lea     edi, [edi+esi*8] ; 将KAPC_STATE地址赋给edi
.text:00402CAD                 mov     esi, [edi+LIST_ENTRY.Blink] ; 取出队列中的上一个APC
.text:00402CA7                 movsx   esi, dl         ; 将ApcMode赋给esi
.text:00402CAA                 lea     edi, [edi+esi*8] ; 将KAPC_STATE地址赋给edi
.text:00402CAD                 mov     esi, [edi+LIST_ENTRY.Blink] ; 取出队列中的上一个APC
.text:00402CB0 loc_402CB0:                             ; CODE XREF: KiInsertQueueApc(x,x)+4876A↓j
.text:00402CB0                 cmp     esi, edi        ; 判断上一个APC是否等于线程APC_STATE地址
.text:00402CB2                 jnz     loc_42615A
.text:00402CB0 loc_402CB0:                             ; CODE XREF: KiInsertQueueApc(x,x)+4876A↓j
.text:00402CB0                 cmp     esi, edi        ; 判断上一个APC是否等于线程APC_STATE地址
.text:00402CB2                 jnz     loc_42615A
.text:0042615A loc_42615A:                             ; CODE XREF: KiInsertQueueApc(x,x)+48↑j
.text:0042615A                 cmp     [esi+KAPC.ApcListEntry.Blink], 0
.text:0042615E                 jz      loc_402CB8
.text:00426164                 jmp     loc_44B3D1
.text:0042615A loc_42615A:                             ; CODE XREF: KiInsertQueueApc(x,x)+48↑j
.text:0042615A                 cmp     [esi+KAPC.ApcListEntry.Blink], 0
.text:0042615E                 jz      loc_402CB8
.text:00426164                 jmp     loc_44B3D1
.text:0044B3D1 loc_44B3D1:                             ; CODE XREF: KiInsertQueueApc(x,x)+234FA↑j
.text:0044B3D1                 mov     esi, [esi+LIST_ENTRY.Blink]
.text:0044B3D4                 jmp     loc_402CB0
.text:0044B3D1 loc_44B3D1:                             ; CODE XREF: KiInsertQueueApc(x,x)+234FA↑j
.text:0044B3D1                 mov     esi, [esi+LIST_ENTRY.Blink]
.text:0044B3D4                 jmp     loc_402CB0
.text:00402CB8 loc_402CB8:                             ; CODE XREF: KiInsertQueueApc(x,x)+234F4↓j
.text:00402CB8                 mov     ebx, [esi+LIST_ENTRY.Flink]
.text:00402CBA                 lea     edi, [eax+_KAPC.ApcListEntry]
.text:00402CBD                 mov     [edi+LIST_ENTRY.Flink], ebx
.text:00402CBF                 mov     [edi+LIST_ENTRY.Blink], esi
.text:00402CC2                 mov     [ebx+LIST_ENTRY.Blink], edi
.text:00402CC5                 mov     [esi+LIST_ENTRY.Flink], edi
.text:00402CB8 loc_402CB8:                             ; CODE XREF: KiInsertQueueApc(x,x)+234F4↓j
.text:00402CB8                 mov     ebx, [esi+LIST_ENTRY.Flink]
.text:00402CBA                 lea     edi, [eax+_KAPC.ApcListEntry]
.text:00402CBD                 mov     [edi+LIST_ENTRY.Flink], ebx
.text:00402CBF                 mov     [edi+LIST_ENTRY.Blink], esi
.text:00402CC2                 mov     [ebx+LIST_ENTRY.Blink], edi
.text:00402CC5                 mov     [esi+LIST_ENTRY.Flink], edi
.text:0041049E loc_41049E:                             ; CODE XREF: KiInsertQueueApc(x,x)+37↑j
.text:0041049E                 test    dl, dl          ; 判断ApcMode是否为0
.text:004104A0                 jz      short loc_4104AF
.text:004104A2                 cmp     [eax+KAPC.KernelRoutine], offset _PsExitSpecialApc@20 ; PsExitSpecialApc(x,x,x,x,x)
.text:004104A9                 jz      loc_42950C
.text:0041049E loc_41049E:                             ; CODE XREF: KiInsertQueueApc(x,x)+37↑j
.text:0041049E                 test    dl, dl          ; 判断ApcMode是否为0
.text:004104A0                 jz      short loc_4104AF
.text:004104A2                 cmp     [eax+KAPC.KernelRoutine], offset _PsExitSpecialApc@20 ; PsExitSpecialApc(x,x,x,x,x)
.text:004104A9                 jz      loc_42950C
.text:004104AF loc_4104AF:                             ; CODE XREF: KiInsertQueueApc(x,x)+D836↑j
.text:004104AF                 movsx   ebx, dl         ; 将ApcMode赋给ebx
.text:004104B2                 lea     edi, [edi+ebx*8] ; 取出KAPC_STATE地址赋给edi
.text:004104B5                 mov     ebx, [edi+LIST_ENTRY.Blink] ; 将KAPC_STATE的上一个APC对象赋给ebx
.text:004104B8                 lea     esi, [eax+KAPC.ApcListEntry] ; 将KAPC的ApcListEntry地址赋给esi
.text:004104BB                 mov     [esi+LIST_ENTRY.Flink], edi
.text:004104BD                 mov     [esi+LIST_ENTRY.Blink], ebx
.text:004104C0                 mov     [ebx+LIST_ENTRY.Flink], esi
.text:004104C2                 mov     [edi+LIST_ENTRY.Blink], esi
.text:004104C5                 jmp     loc_402CC7
.text:004104AF loc_4104AF:                             ; CODE XREF: KiInsertQueueApc(x,x)+D836↑j
.text:004104AF                 movsx   ebx, dl         ; 将ApcMode赋给ebx
.text:004104B2                 lea     edi, [edi+ebx*8] ; 取出KAPC_STATE地址赋给edi
.text:004104B5                 mov     ebx, [edi+LIST_ENTRY.Blink] ; 将KAPC_STATE的上一个APC对象赋给ebx
.text:004104B8                 lea     esi, [eax+KAPC.ApcListEntry] ; 将KAPC的ApcListEntry地址赋给esi
.text:004104BB                 mov     [esi+LIST_ENTRY.Flink], edi
.text:004104BD                 mov     [esi+LIST_ENTRY.Blink], ebx
.text:004104C0                 mov     [ebx+LIST_ENTRY.Flink], esi
.text:004104C2                 mov     [edi+LIST_ENTRY.Blink], esi
.text:004104C5                 jmp     loc_402CC7
.text:0042950C loc_42950C:                             ; CODE XREF: KiInsertQueueApc(x,x)+D83F↑j
.text:0042950C                 movsx   ebx, dl         ; 将ApcMode赋给ebx
.text:0042950F                 mov     [ecx+_KTHREAD.ApcState.UserApcPending], 1
.text:00429513                 lea     edi, [edi+ebx*8]
.text:00429516                 mov     ebx, [edi+LIST_ENTRY.Flink]
.text:00429518                 lea     esi, [eax+KAPC.ApcListEntry]
.text:0042951B                 mov     [esi+LIST_ENTRY.Flink], ebx
.text:0042951D                 mov     [esi+LIST_ENTRY.Blink], edi
.text:00429520                 mov     [ebx+LIST_ENTRY.Blink], esi
.text:00429523                 mov     [edi+LIST_ENTRY.Flink], esi
.text:00429525                 jmp     loc_402CC7
.text:0042950C loc_42950C:                             ; CODE XREF: KiInsertQueueApc(x,x)+D83F↑j
.text:0042950C                 movsx   ebx, dl         ; 将ApcMode赋给ebx
.text:0042950F                 mov     [ecx+_KTHREAD.ApcState.UserApcPending], 1
.text:00429513                 lea     edi, [edi+ebx*8]
.text:00429516                 mov     ebx, [edi+LIST_ENTRY.Flink]
.text:00429518                 lea     esi, [eax+KAPC.ApcListEntry]
.text:0042951B                 mov     [esi+LIST_ENTRY.Flink], ebx
.text:0042951D                 mov     [esi+LIST_ENTRY.Blink], edi
.text:00429520                 mov     [ebx+LIST_ENTRY.Blink], esi
.text:00429523                 mov     [edi+LIST_ENTRY.Flink], esi
.text:00429525                 jmp     loc_402CC7
.text:00402CC7 loc_402CC7:                             ; CODE XREF: KiInsertQueueApc(x,x)+D85B↓j
.text:00402CC7                                         ; KiInsertQueueApc(x,x)+268BB↓j
.text:00402CC7                 movsx   edi, [eax+KAPC.ApcStateIndex]
.text:00402CCB                 mov     [eax+KAPC.Inserted], 1
.text:00402CCF                 movzx   esi, [ecx+_KTHREAD.ApcStateIndex]
.text:00402CD6                 cmp     edi, esi
.text:00402CD8                 pop     edi
.text:00402CD9                 pop     esi
.text:00402CDA                 pop     ebx
.text:00402CDB                 jnz     short loc_402D12
.text:00402CC7 loc_402CC7:                             ; CODE XREF: KiInsertQueueApc(x,x)+D85B↓j
.text:00402CC7                                         ; KiInsertQueueApc(x,x)+268BB↓j
.text:00402CC7                 movsx   edi, [eax+KAPC.ApcStateIndex]
.text:00402CCB                 mov     [eax+KAPC.Inserted], 1
.text:00402CCF                 movzx   esi, [ecx+_KTHREAD.ApcStateIndex]
.text:00402CD6                 cmp     edi, esi
.text:00402CD8                 pop     edi
.text:00402CD9                 pop     esi
.text:00402CDA                 pop     ebx
.text:00402CDB                 jnz     short loc_402D12
.text:00402CDD                 test    dl, dl
.text:00402CDF                 jnz     loc_4106A4
.text:00402CDD                 test    dl, dl
.text:00402CDF                 jnz     loc_4106A4
.text:00402CE5                 mov     dl, [ecx+_KTHREAD.State]
.text:00402CE8                 cmp     dl, 2
.text:00402CEB                 mov     [ecx+_KTHREAD.ApcState.KernelApcPending], 1
.text:00402CEF                 jnz     loc_40EEB3
.text:00402CE5                 mov     dl, [ecx+_KTHREAD.State]
.text:00402CE8                 cmp     dl, 2
.text:00402CEB                 mov     [ecx+_KTHREAD.ApcState.KernelApcPending], 1
.text:00402CEF                 jnz     loc_40EEB3
.text:004106A4 loc_4106A4:                             ; CODE XREF: KiInsertQueueApc(x,x)+75↑j
.text:004106A4                 cmp     [ecx+_KTHREAD.State], 5
.text:004106A8                 jnz     loc_402D12
.text:004106AE                 cmp     [ecx+_KTHREAD.WaitMode], 1
.text:004106B2                 jnz     loc_402D12
.text:004106B8                 cmp     [ecx+_KTHREAD.Alertable], 0
.text:004106BF                 jz      loc_432270
.text:004106A4 loc_4106A4:                             ; CODE XREF: KiInsertQueueApc(x,x)+75↑j
.text:004106A4                 cmp     [ecx+_KTHREAD.State], 5
.text:004106A8                 jnz     loc_402D12
.text:004106AE                 cmp     [ecx+_KTHREAD.WaitMode], 1
.text:004106B2                 jnz     loc_402D12
.text:004106B8                 cmp     [ecx+_KTHREAD.Alertable], 0
.text:004106BF                 jz      loc_432270
.text:004106C5 loc_4106C5:                             ; CODE XREF: KiInsertQueueApc(x,x)+2F610↓j
.text:004106C5                 mov     [ecx+_KTHREAD.ApcState.UserApcPending], 1
.text:004106C9                 push    0
.text:004106CB                 mov     edx, 0C0h
.text:004106D0                 jmp     loc_40EED7
.text:004106C5 loc_4106C5:                             ; CODE XREF: KiInsertQueueApc(x,x)+2F610↓j
.text:004106C5                 mov     [ecx+_KTHREAD.ApcState.UserApcPending], 1
.text:004106C9                 push    0
.text:004106CB                 mov     edx, 0C0h
.text:004106D0                 jmp     loc_40EED7
.text:00405E01 ; int __stdcall KiDeliverApc(KPROCESSOR_MODE PreviousMode, int, int)
.text:00405E01                 public _KiDeliverApc@12
.text:00405E01 _KiDeliverApc@12 proc near              ; CODE XREF: KiUnlockDispatcherDatabase(x)+CA↑p
.text:00405E01                                         ; _KiServiceExit+54↓p ...
.text:00405E01
.text:00405E01 LockHandle      = _KLOCK_QUEUE_HANDLE ptr -28h
.text:00405E01 var_TrapFrame   = dword ptr -1Ch
.text:00405E01 var_EPROCESS    = dword ptr -18h
.text:00405E01 var_KernelRoutine= dword ptr -14h
.text:00405E01 NormalContext   = dword ptr -10h
.text:00405E01 SystemArgument1 = dword ptr -0Ch
.text:00405E01 SystemArgument2 = dword ptr -8
.text:00405E01 NormalRoutine   = dword ptr -4
.text:00405E01 PreviousMode    = byte ptr  8
.text:00405E01 ExceptionFrame  = dword ptr  0Ch
.text:00405E01 TrapFrame       = dword ptr  10h
.text:00405E01
.text:00405E01                 mov     edi, edi
.text:00405E03                 push    ebp
.text:00405E04                 mov     ebp, esp
.text:00405E06                 sub     esp, 28h
.text:00405E09                 mov     ecx, [ebp+TrapFrame] ; 将TrapFrame地址赋给ecx
.text:00405E0C                 test    ecx, ecx
.text:00405E0E                 jz      short loc_405E20
.text:00405E10                 mov     edx, [ecx+68h]  ; 从TrapFrame中取出eip赋给edx
.text:00405E13                 mov     eax, offset _ExpInterlockedPopEntrySListResume@0 ; ExpInterlockedPopEntrySListResume()
.text:00405E18                 cmp     edx, eax
.text:00405E1A                 jnb     loc_41137B
.text:00405E20
.text:00405E20 loc_405E20:                             ; CODE XREF: KiDeliverApc(x,x,x)+D↑j
.text:00405E20                                         ; KiDeliverApc(x,x,x)+B580↓j ...
.text:00405E20                 push    ebx
.text:00405E21                 push    esi
.text:00405E22                 push    edi
.text:00405E23                 mov     eax, large fs:124h ; 将线程对象地址赋给eax
.text:00405E29                 mov     esi, eax        ; 将线程对象地址赋给edi
.text:00405E2B                 mov     eax, [esi+_KTHREAD.TrapFrame]
.text:00405E31                 mov     [ebp+var_TrapFrame], eax
.text:00405E34                 mov     eax, [esi+_KTHREAD.ApcState.Process]
.text:00405E37                 mov     [esi+_KTHREAD.TrapFrame], ecx
.text:00405E3D                 lea     ecx, [esi+_KTHREAD.ApcQueueLock] ; SpinLock
.text:00405E43                 lea     edx, [ebp+LockHandle] ; LockHandle
.text:00405E46                 mov     [ebp+var_EPROCESS], eax
.text:00405E49                 call    ds:__imp_@KeAcquireInStackQueuedSpinLock@8 ; KeAcquireInStackQueuedSpinLock(x,x)
.text:00405E4F                 mov     [esi+_KTHREAD.ApcState.KernelApcPending], 0 ; 将KernelApcPending赋值为0
.text:00405E01 ; int __stdcall KiDeliverApc(KPROCESSOR_MODE PreviousMode, int, int)
.text:00405E01                 public _KiDeliverApc@12
.text:00405E01 _KiDeliverApc@12 proc near              ; CODE XREF: KiUnlockDispatcherDatabase(x)+CA↑p
.text:00405E01                                         ; _KiServiceExit+54↓p ...
.text:00405E01
.text:00405E01 LockHandle      = _KLOCK_QUEUE_HANDLE ptr -28h
.text:00405E01 var_TrapFrame   = dword ptr -1Ch
.text:00405E01 var_EPROCESS    = dword ptr -18h
.text:00405E01 var_KernelRoutine= dword ptr -14h
.text:00405E01 NormalContext   = dword ptr -10h
.text:00405E01 SystemArgument1 = dword ptr -0Ch
.text:00405E01 SystemArgument2 = dword ptr -8
.text:00405E01 NormalRoutine   = dword ptr -4
.text:00405E01 PreviousMode    = byte ptr  8
.text:00405E01 ExceptionFrame  = dword ptr  0Ch
.text:00405E01 TrapFrame       = dword ptr  10h
.text:00405E01
.text:00405E01                 mov     edi, edi
.text:00405E03                 push    ebp
.text:00405E04                 mov     ebp, esp
.text:00405E06                 sub     esp, 28h
.text:00405E09                 mov     ecx, [ebp+TrapFrame] ; 将TrapFrame地址赋给ecx
.text:00405E0C                 test    ecx, ecx
.text:00405E0E                 jz      short loc_405E20
.text:00405E10                 mov     edx, [ecx+68h]  ; 从TrapFrame中取出eip赋给edx
.text:00405E13                 mov     eax, offset _ExpInterlockedPopEntrySListResume@0 ; ExpInterlockedPopEntrySListResume()
.text:00405E18                 cmp     edx, eax
.text:00405E1A                 jnb     loc_41137B
.text:00405E20
.text:00405E20 loc_405E20:                             ; CODE XREF: KiDeliverApc(x,x,x)+D↑j
.text:00405E20                                         ; KiDeliverApc(x,x,x)+B580↓j ...
.text:00405E20                 push    ebx
.text:00405E21                 push    esi
.text:00405E22                 push    edi
.text:00405E23                 mov     eax, large fs:124h ; 将线程对象地址赋给eax
.text:00405E29                 mov     esi, eax        ; 将线程对象地址赋给edi
.text:00405E2B                 mov     eax, [esi+_KTHREAD.TrapFrame]
.text:00405E31                 mov     [ebp+var_TrapFrame], eax
.text:00405E34                 mov     eax, [esi+_KTHREAD.ApcState.Process]
.text:00405E37                 mov     [esi+_KTHREAD.TrapFrame], ecx
.text:00405E3D                 lea     ecx, [esi+_KTHREAD.ApcQueueLock] ; SpinLock
.text:00405E43                 lea     edx, [ebp+LockHandle] ; LockHandle
.text:00405E46                 mov     [ebp+var_EPROCESS], eax
.text:00405E49                 call    ds:__imp_@KeAcquireInStackQueuedSpinLock@8 ; KeAcquireInStackQueuedSpinLock(x,x)
.text:00405E4F                 mov     [esi+_KTHREAD.ApcState.KernelApcPending], 0 ; 将KernelApcPending赋值为0
.text:00405E53                 lea     ebx, [esi+_KTHREAD.ApcState]
.text:00405E56
.text:00405E56 loc_405E56:                             ; CODE XREF: KiDeliverApc(x,x,x)+14FDD↓j
.text:00405E56                                         ; KiDeliverApc(x,x,x)+15E53↓j ...
.text:00405E56                 cmp     [ebx+LIST_ENTRY.Flink], ebx
.text:00405E58                 jnz     loc_41BBEF
.text:00405E53                 lea     ebx, [esi+_KTHREAD.ApcState]
.text:00405E56
.text:00405E56 loc_405E56:                             ; CODE XREF: KiDeliverApc(x,x,x)+14FDD↓j
.text:00405E56                                         ; KiDeliverApc(x,x,x)+15E53↓j ...
.text:00405E56                 cmp     [ebx+LIST_ENTRY.Flink], ebx
.text:00405E58                 jnz     loc_41BBEF
.text:0041BBEF loc_41BBEF:                             ; CODE XREF: KiDeliverApc(x,x,x)+57↑j
.text:0041BBEF                 mov     eax, [ebx+LIST_ENTRY.Flink] ; 获取内核APC链表中的APC对象
.text:0041BBF1                 lea     edi, [eax-0Ch]  ; 获取APC对象的地址
.text:0041BBEF loc_41BBEF:                             ; CODE XREF: KiDeliverApc(x,x,x)+57↑j
.text:0041BBEF                 mov     eax, [ebx+LIST_ENTRY.Flink] ; 获取内核APC链表中的APC对象
.text:0041BBF1                 lea     edi, [eax-0Ch]  ; 获取APC对象的地址
.text:0041BBEF loc_41BBEF:                             ; CODE XREF: KiDeliverApc(x,x,x)+57↑j
.text:0041BBEF                 mov     eax, [ebx+LIST_ENTRY.Flink] ; 获取内核APC链表中的APC对象
.text:0041BBF1                 lea     edi, [eax-0Ch]  ; 获取APC对象的地址
.text:0041BBF4                 mov     ecx, [edi+KAPC.KernelRoutine]
.text:0041BBF7                 mov     [ebp+var_KernelRoutine], ecx
.text:0041BBFA                 mov     ecx, [edi+KAPC.NormalRoutine]
.text:0041BBFD                 test    ecx, ecx        ; 判断NormalRoutine是否为NULL
.text:0041BBFF                 mov     [ebp+NormalRoutine], ecx
.text:0041BC02                 mov     edx, [edi+KAPC.NormalContext]
.text:0041BC05                 mov     [ebp+NormalContext], edx
.text:0041BC08                 mov     edx, [edi+KAPC.SystemArgument1]
.text:0041BC0B                 mov     [ebp+SystemArgument1], edx
.text:0041BC0E                 mov     edx, [edi+KAPC.SystemArgument2]
.text:0041BC11                 mov     [ebp+SystemArgument2], edx
.text:0041BC14                 jnz     loc_41AD60
.text:0041BBEF loc_41BBEF:                             ; CODE XREF: KiDeliverApc(x,x,x)+57↑j
.text:0041BBEF                 mov     eax, [ebx+LIST_ENTRY.Flink] ; 获取内核APC链表中的APC对象
.text:0041BBF1                 lea     edi, [eax-0Ch]  ; 获取APC对象的地址
.text:0041BBF4                 mov     ecx, [edi+KAPC.KernelRoutine]
.text:0041BBF7                 mov     [ebp+var_KernelRoutine], ecx
.text:0041BBFA                 mov     ecx, [edi+KAPC.NormalRoutine]
.text:0041BBFD                 test    ecx, ecx        ; 判断NormalRoutine是否为NULL
.text:0041BBFF                 mov     [ebp+NormalRoutine], ecx
.text:0041BC02                 mov     edx, [edi+KAPC.NormalContext]
.text:0041BC05                 mov     [ebp+NormalContext], edx
.text:0041BC08                 mov     edx, [edi+KAPC.SystemArgument1]
.text:0041BC0B                 mov     [ebp+SystemArgument1], edx
.text:0041BC0E                 mov     edx, [edi+KAPC.SystemArgument2]
.text:0041BC11                 mov     [ebp+SystemArgument2], edx
.text:0041BC14                 jnz     loc_41AD60
.text:0041BC1A                 mov     ecx, [eax+LIST_ENTRY.Flink] ; 将APC对象从链表中删除
.text:0041BC1C                 mov     eax, [eax+LIST_ENTRY.Blink]
.text:0041BC1F                 mov     [eax+LIST_ENTRY.Flink], ecx
.text:0041BC21                 mov     [ecx+LIST_ENTRY.Blink], eax
.text:0041BC24                 lea     ecx, [ebp+LockHandle] ; LockHandle
.text:0041BC27                 mov     [edi+KAPC.Inserted], 0 ; 将Inserted赋值为0
.text:0041BC2B                 call    ds:__imp_@KeReleaseInStackQueuedSpinLock@4 ; KeReleaseInStackQueuedSpinLock(x)
.text:0041BC31                 lea     eax, [ebp+SystemArgument2]
.text:0041BC34                 push    eax
.text:0041BC35                 lea     eax, [ebp+SystemArgument1]
.text:0041BC38                 push    eax
.text:0041BC39                 lea     eax, [ebp+NormalContext]
.text:0041BC3C                 push    eax
.text:0041BC3D                 lea     eax, [ebp+NormalRoutine]
.text:0041BC40                 push    eax
.text:0041BC41                 push    edi
.text:0041BC42                 call    [ebp+var_KernelRoutine]
.text:0041BC45                 lea     edx, [ebp+LockHandle] ; LockHandle
.text:0041BC48                 lea     ecx, [esi+_KTHREAD.ApcQueueLock] ; SpinLock
.text:0041BC4E                 call    ds:__imp_@KeAcquireInStackQueuedSpinLock@8 ; KeAcquireInStackQueuedSpinLock(x,x)
.text:0041BC54                 jmp     loc_405E56
.text:0041BC1A                 mov     ecx, [eax+LIST_ENTRY.Flink] ; 将APC对象从链表中删除
.text:0041BC1C                 mov     eax, [eax+LIST_ENTRY.Blink]
.text:0041BC1F                 mov     [eax+LIST_ENTRY.Flink], ecx
.text:0041BC21                 mov     [ecx+LIST_ENTRY.Blink], eax
.text:0041BC24                 lea     ecx, [ebp+LockHandle] ; LockHandle
.text:0041BC27                 mov     [edi+KAPC.Inserted], 0 ; 将Inserted赋值为0
.text:0041BC2B                 call    ds:__imp_@KeReleaseInStackQueuedSpinLock@4 ; KeReleaseInStackQueuedSpinLock(x)
.text:0041BC31                 lea     eax, [ebp+SystemArgument2]
.text:0041BC34                 push    eax
.text:0041BC35                 lea     eax, [ebp+SystemArgument1]
.text:0041BC38                 push    eax
.text:0041BC39                 lea     eax, [ebp+NormalContext]
.text:0041BC3C                 push    eax
.text:0041BC3D                 lea     eax, [ebp+NormalRoutine]
.text:0041BC40                 push    eax
.text:0041BC41                 push    edi
.text:0041BC42                 call    [ebp+var_KernelRoutine]
.text:0041BC45                 lea     edx, [ebp+LockHandle] ; LockHandle
.text:0041BC48                 lea     ecx, [esi+_KTHREAD.ApcQueueLock] ; SpinLock
.text:0041BC4E                 call    ds:__imp_@KeAcquireInStackQueuedSpinLock@8 ; KeAcquireInStackQueuedSpinLock(x,x)
.text:0041BC54                 jmp     loc_405E56
.text:0041AD60 loc_41AD60:                             ; CODE XREF: KiDeliverApc(x,x,x)+15E13↓j
.text:0041AD60                 cmp     [esi+_KTHREAD.ApcState.KernelApcInProgress], 0
.text:0041AD64                 jnz     loc_405E6B
.text:0041AD6A                 cmp     [esi+_KTHREAD.KernelApcDisable], 0
.text:0041AD71                 jnz     loc_405E6B
.text:0041AD60 loc_41AD60:                             ; CODE XREF: KiDeliverApc(x,x,x)+15E13↓j
.text:0041AD60                 cmp     [esi+_KTHREAD.ApcState.KernelApcInProgress], 0
.text:0041AD64                 jnz     loc_405E6B
.text:0041AD6A                 cmp     [esi+_KTHREAD.KernelApcDisable], 0
.text:0041AD71                 jnz     loc_405E6B
.text:00405E6B loc_405E6B:                             ; CODE XREF: KiDeliverApc(x,x,x)+A6CD↓j
.text:00405E6B                                         ; KiDeliverApc(x,x,x)+A6D7↓j ...
.text:00405E6B                 lea     ecx, [ebp+LockHandle] ; LockHandle
.text:00405E6E                 call    ds:__imp_@KeReleaseInStackQueuedSpinLock@4
.text:00405E6B loc_405E6B:                             ; CODE XREF: KiDeliverApc(x,x,x)+A6CD↓j
.text:00405E6B                                         ; KiDeliverApc(x,x,x)+A6D7↓j ...
.text:00405E6B                 lea     ecx, [ebp+LockHandle] ; LockHandle
.text:00405E6E                 call    ds:__imp_@KeReleaseInStackQueuedSpinLock@4
.text:0041AD77                 mov     ecx, [eax+LIST_ENTRY.Flink]
.text:0041AD79                 mov     eax, [eax+LIST_ENTRY.Blink]
.text:0041AD7C                 mov     [eax+LIST_ENTRY.Flink], ecx
.text:0041AD7E                 mov     [ecx+LIST_ENTRY.Blink], eax
.text:0041AD81                 lea     ecx, [ebp+LockHandle] ; LockHandle
.text:0041AD84                 mov     [edi+KAPC.Inserted], 0
.text:0041AD88                 call    ds:__imp_@KeReleaseInStackQueuedSpinLock@4
.text:0041AD77                 mov     ecx, [eax+LIST_ENTRY.Flink]
.text:0041AD79                 mov     eax, [eax+LIST_ENTRY.Blink]
.text:0041AD7C                 mov     [eax+LIST_ENTRY.Flink], ecx
.text:0041AD7E                 mov     [ecx+LIST_ENTRY.Blink], eax
.text:0041AD81                 lea     ecx, [ebp+LockHandle] ; LockHandle
.text:0041AD84                 mov     [edi+KAPC.Inserted], 0
.text:0041AD88                 call    ds:__imp_@KeReleaseInStackQueuedSpinLock@4
.text:0041AD8E                 lea     eax, [ebp+SystemArgument2]
.text:0041AD91                 push    eax
.text:0041AD92                 lea     eax, [ebp+SystemArgument1]
.text:0041AD95                 push    eax
.text:0041AD96                 lea     eax, [ebp+NormalContext]
.text:0041AD99                 push    eax
.text:0041AD9A                 lea     eax, [ebp+NormalRoutine]
.text:0041AD9D                 push    eax
.text:0041AD9E                 push    edi
.text:0041AD9F                 call    [ebp+var_KernelRoutine]
.text:0041AD8E                 lea     eax, [ebp+SystemArgument2]
.text:0041AD91                 push    eax
.text:0041AD92                 lea     eax, [ebp+SystemArgument1]
.text:0041AD95                 push    eax
.text:0041AD96                 lea     eax, [ebp+NormalContext]
.text:0041AD99                 push    eax
.text:0041AD9A                 lea     eax, [ebp+NormalRoutine]
.text:0041AD9D                 push    eax
.text:0041AD9E                 push    edi
.text:0041AD9F                 call    [ebp+var_KernelRoutine]
.text:0041ADA2                 cmp     [ebp+NormalRoutine], 0
.text:0041ADA6                 jz      short loc_41ADCB
.text:0041ADA2                 cmp     [ebp+NormalRoutine], 0
.text:0041ADA6                 jz      short loc_41ADCB
.text:0041ADA8                 xor     cl, cl          ; NewIrql
.text:0041ADAA                 mov     [esi+_KTHREAD.ApcState.KernelApcInProgress], 1
.text:0041ADAE                 call    ds:__imp_@KfLowerIrql@4
.text:0041ADA8                 xor     cl, cl          ; NewIrql
.text:0041ADAA                 mov     [esi+_KTHREAD.ApcState.KernelApcInProgress], 1
.text:0041ADAE                 call    ds:__imp_@KfLowerIrql@4
.text:0041ADB4                 push    [ebp+SystemArgument2]
.text:0041ADB7                 push    [ebp+SystemArgument1]
.text:0041ADBA                 push    [ebp+NormalContext]
.text:0041ADBD                 call    [ebp+NormalRoutine]
.text:0041ADB4                 push    [ebp+SystemArgument2]
.text:0041ADB7                 push    [ebp+SystemArgument1]
.text:0041ADBA                 push    [ebp+NormalContext]
.text:0041ADBD                 call    [ebp+NormalRoutine]
.text:0041ADC0                 mov     cl, 1           ; NewIrql
.text:0041ADC2                 call    ds:__imp_@KfRaiseIrql@4 ; KfRaiseIrql(x)
.text:0041ADC8                 mov     [ebp+LockHandle.OldIrql], al
.text:0041ADC0                 mov     cl, 1           ; NewIrql
.text:0041ADC2                 call    ds:__imp_@KfRaiseIrql@4 ; KfRaiseIrql(x)
.text:0041ADC8                 mov     [ebp+LockHandle.OldIrql], al
.text:0041ADCB loc_41ADCB:                             ; CODE XREF: KiDeliverApc(x,x,x)+14FA5↑j
.text:0041ADCB                 lea     edx, [ebp+LockHandle] ; LockHandle
.text:0041ADCE                 lea     ecx, [esi+_KTHREAD.ApcQueueLock] ; SpinLock
.text:0041ADD4                 call    ds:__imp_@KeAcquireInStackQueuedSpinLock@8 ; KeAcquireInStackQueuedSpinLock(x,x)
.text:0041ADDA                 mov     [esi+_KTHREAD.ApcState.KernelApcInProgress], 0
.text:0041ADDE                 jmp     loc_405E56
.text:0041ADCB loc_41ADCB:                             ; CODE XREF: KiDeliverApc(x,x,x)+14FA5↑j
.text:0041ADCB                 lea     edx, [ebp+LockHandle] ; LockHandle
.text:0041ADCE                 lea     ecx, [esi+_KTHREAD.ApcQueueLock] ; SpinLock

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2021-12-29 09:30 被1900编辑 ,原因:
收藏
免费 7
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//