APC异步过程调用
+ -

PsExitSpecialApc线程的退出示例

2023-08-02 14 0

在上一节KiInsertQueueApc中,可以看到有一个特殊的APC,其为PsExitSpecialApc,表示线程退出的APC.

    if (Apc->NormalRoutine)
    {
        /* Normal APC; is it the Thread Termination APC? */
        if ((ApcMode != KernelMode) &&
            (Apc->KernelRoutine == PsExitSpecialApc))
        {
            /* Set User APC pending to true */
            Thread->ApcState.UserApcPending = TRUE;

            /* Insert it at the top of the list */
            InsertHeadList(&ApcState->ApcListHead[ApcMode],
                           &Apc->ApcListEntry);
        }
        else
        {
            /* Regular user or kernel Normal APC */
            InsertTailList(&ApcState->ApcListHead[ApcMode],
                           &Apc->ApcListEntry);
        }
    }

我们找一个线程退出的时的调用:
PspTerminateThreadByPointer函数中:

        /* Initialize a Kernel Mode APC to Kill the Thread */
        KeInitializeApc(Apc,
                        &Thread->Tcb,
                        OriginalApcEnvironment,
                        PsExitSpecialApc,
                        PspExitApcRundown,
                        PspExitNormalApc,
                        KernelMode,
                        UlongToPtr(ExitStatus));//NormalContext=status

        /* Insert it into the APC Queue */
        if (!KeInsertQueueApc(Apc, Apc, NULL, 2))
        {
            /* The APC was already in the queue, fail */
            Status = STATUS_UNSUCCESSFUL;
        }
        else
        {
            /* Forcefully resume the thread and return */
            KeForceResumeThread(&Thread->Tcb);
            return Status;
        }

执行的是PsExitSpecialApc:

VOID NTAPI PsExitSpecialApc    (    PKAPC     Apc,
PKNORMAL_ROUTINE *     NormalRoutine,
PVOID *     NormalContext,
PVOID *     SystemArgument1,
PVOID *     SystemArgument2 
)    
{
    NTSTATUS Status;
    PAGED_CODE();
    PSTRACE(PS_KILL_DEBUG,
            "Apc: %p SystemArgument2: %p\n", Apc, SystemArgument2);

    /* Don't do anything unless we are in User-Mode */
    if (Apc->SystemArgument2)
    {
        /* Free the APC */
        Status = PtrToUlong(Apc->NormalContext);
        PspExitApcRundown(Apc);

        /* Terminate the Thread */
        PspExitThread(Status);
    }
}

其中PspExitApcRundown仅为释放APC.

VOID NTAPI PspExitApcRundown    (    IN PKAPC     Apc    )    
{
    PAGED_CODE();

    /* Free the APC */
    ExFreePool(Apc);
}

而最终执行的是:

VOID  PspExitThread    (IN NTSTATUS     ExitStatus)    ;

而我们在内核中熟知的PsTerminateSystemThread的代码如下:

NTSTATUS NTAPI PsTerminateSystemThread    (    IN NTSTATUS     ExitStatus    )    
{
    PETHREAD Thread = PsGetCurrentThread();

    /* Make sure this is a system thread */
    if (!Thread->SystemThread) return STATUS_INVALID_PARAMETER;

    /* Terminate it for real */
    return PspTerminateThreadByPointer(Thread, ExitStatus, TRUE);
}

所以,在内核中不调用PsTerminateSystemThread,可以看到无法真正的卸载线程。

0 篇笔记 写笔记

IRP完成APC执行函数IopCompleteRequest
IRP在完成时调用IoCompleteRequest,其最终会执行一个APC调用,该调用的函数名为IopCompleteRequest。其调用APC调用时的代码如下:KeInitializeApc(&Irp->Tail.Apc, &......
APC本质
APC全称Asynchronous Procedure Call,中文名异步过程调用。程序是以进程为载体的,其执行体是进程中的线程。一个线程在运行的过程中,因为其占有的CPU,其它进程或者线程是无法占用CPU的,所以从理论上来讲,这个线程是无法被杀死,挂起和恢复的。但在实际的软件开发中,以上的操作......
APC挂入
挂入ApcListHead链表中的叫做APC,每个APC的结构如下:2: kd> dt _KAPCnt!_KAPC +0x000 Type : UChar +0x001 SpareByte0 : UChar +0x002 Size ......
APC的执行及执行时机
当线程中的ApcListHead链表中不为空时,就表示该线程拥有APC,线程应在合适的时机执行该APCAPC执行时机APC常见的执行时机:线程切换:当当前线程处于阻塞状态,比如等待用户输入或者等待磁盘IO完成时,操作系统可以选择在这个时机执行排队中的 APC。这样可以充分利用线程的等待时间,......
SavedApcState与线程挂靠
_KTHREAD线程0x258地址处: +0x258 SavedApcState : _KAPC_STATE +0x258 SavedApcStateFill : [43] UChar此为备份SavedApcState,用于当线程挂靠到别的进程时,保存当前进程的APC State......
PsExitSpecialApc线程的退出示例
在上一节KiInsertQueueApc中,可以看到有一个特殊的APC,其为PsExitSpecialApc,表示线程退出APC. if (Apc->NormalRoutine) { /* Normal APC; is it the Thread Termin......
APC的执行KiDeliverApc
APC执行是通过KiDeliverApc实现的,不过该函数是一个内核函数。不过APC分为内核APC和应用层APC。对于内核层的APC直接调用即可,但对于应用层的APC,需要临时进入用户层,执行用户层的APC,执行完成后再进入内核层,再通过内核层返回到应用层原来的返回地址。ReactOS关于其代码如下......
作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!