首页
社区
课程
招聘
[讨论]Win7x64调试函数[PspExitThread]逆向
发表于: 2016-11-24 15:39 5736

[讨论]Win7x64调试函数[PspExitThread]逆向

2016-11-24 15:39
5736
VOID
        PspExitThread(
        IN NTSTATUS ExitStatus
        )
{
        PETHREAD_S Thread,ForThread;
        PEPROCESS_S Process;
        ULONG i;
        PEX_CALLBACK_ROUTINE_BLOCK CallBack;
        PCREATE_THREAD_NOTIFY_ROUTINE Rtn;
        PETHREAD_S WaitThread;
        PETHREAD_S DerefThread;
        BOOLEAN LastThread;
        PLIST_ENTRY Entry, FirstEntry;
        PTERMINATION_PORT TerminationPort, NextPort;
        NTSTATUS Status;
        LPC_CLIENT_DIED_MSG CdMsg;
        PVOID ExceptionPort;
        BOOLEAN bPspUmsUnInitThread;
        PTEB Teb;
        PPEB Peb;
        PACCESS_TOKEN ProcessToken;
        PKAPC_S Apc;
        BOOLEAN bGetNext;
        ULONG_PTR OldValue;
        PETHREAD_S CurThreadOr;

        Thread = (PETHREAD_S)PsGetCurrentThread();//rdi
        Process = Thread->Tcb.Process;
       
        if (Process != (PEPROCESS_S)Thread->Tcb.ApcState.Process)
        {
                KeBugCheckEx (
                        INVALID_PROCESS_ATTACH_ATTEMPT,
                        (ULONG_PTR)Process,
                        (ULONG_PTR)Thread->Tcb.ApcState.Process,
                        (ULONG)Thread->Tcb.ApcStateIndex,
                        (ULONG_PTR)Thread);
        }

        KeLowerIrql(PASSIVE_LEVEL);

        if (Thread->ActiveExWorker) //454
        {
                KeBugCheckEx (
                        ACTIVE_EX_WORKER_THREAD_TERMINATION,
                        (ULONG_PTR)Thread,
                        0,
                        0,
                        0);
        }

        if (Thread->Tcb.CombinedApcDisable) //1C4
        {
                KeBugCheckEx (KERNEL_APC_PENDING_DURING_EXIT,
                        (ULONG_PTR)0,
                        (ULONG_PTR)Thread->Tcb.CombinedApcDisable,
                        (ULONG_PTR)0,
                        1);
        }
       
        ExWaitForRundownProtectionRelease ((PEX_RUNDOWN_REF)&Thread->RundownProtect.Ptr);/*0x438*/

        if (Thread->LegacyPowerObject)///*0x420*/
        {
                PoDeletePowerRequest(Thread->LegacyPowerObject);
                Thread->LegacyPowerObject = NULL;
        }

        ((Old_WmiTraceThread)EtwTraceThread)(Thread,NULL,FALSE);
        //检查到这里OK
        Thread->ExitStatus = ExitStatus;/*0x380*/

        Thread->Tcb.KernelApcDisable--;
       
        if ((*(PDWORD)((ULONGLONG)PspNotifyEnableMask)) & 8)
        {
                for (i=0; i < 0x40; i++)
                {
                        CallBack = ((Old_ExReferenceCallBackBlock)ExReferenceCallBackBlock)
                                (&((PEX_CALLBACK)PspCreateThreadNotifyRoutine)[i]);
                        if (CallBack)
                        {
                                Rtn = (PCREATE_THREAD_NOTIFY_ROUTINE) ((Old_ExGetCallBackBlockRoutine)ExGetCallBackBlockRoutine) (CallBack);
                                Rtn (Process->UniqueProcessId,
                                        Thread->Cid.UniqueThread,
                                        FALSE);
                                ((Old_ExDereferenceCallBackBlock)ExDereferenceCallBackBlock )
                                        (&((PEX_CALLBACK)PspCreateThreadNotifyRoutine)[i],CallBack);
                        }
                }
        }
        //检查到这里OK
        LastThread = FALSE;
        DerefThread = NULL;
        ExAcquirePushLockExclusive (&Process->ProcessLock);
        //检查到这里OK
        Process->ActiveThreads--;
        if (Process->ActiveThreads == 0)
        {
                PS_SET_BITS(&Process->Flags, PS_PROCESS_FLAGS_PROCESS_DELETE);
                PS_SET_BITS(&Process->Flags2, PS_PROCESS_FLAGS_OUTSWAPPED);
                LastThread = TRUE;
                if (ExitStatus == STATUS_THREAD_IS_TERMINATING)
                        Process->ExitStatus = Process->LastThreadExitStatus;
            else
                        Process->ExitStatus = ExitStatus;
               
                for (Entry = Process->ThreadListHead.Flink;//308
                        Entry != &Process->ThreadListHead;
                        Entry = Entry->Flink)
                {
                        WaitThread = CONTAINING_RECORD (Entry, ETHREAD_S, ThreadListEntry);
                        if (WaitThread != Thread &&
                                !KeReadStateThread (&WaitThread->Tcb) &&
                                ((Old_ObReferenceObjectSafe)ObReferenceObjectSafe)(WaitThread))
                        {
                                ExReleasePushLockExclusive(&Process->ProcessLock);
                                KeLeaveCriticalRegionThread((PKTHREAD_S)Thread);

                                KeWaitForSingleObject (WaitThread,
                                        Executive,
                                        KernelMode,
                                        FALSE,
                                        NULL);

                                if (DerefThread)
                                        ObDereferenceObject (DerefThread);
                               
                                DerefThread = WaitThread;
                                Thread->Tcb.KernelApcDisable--;
                                //PspLockProcessExclusive (Process, Thread);
                                ExAcquirePushLockExclusive(&Process->ProcessLock);
                        }
                }
        }
        else
        {
                if (ExitStatus != STATUS_THREAD_IS_TERMINATING)
                {
                        Process->LastThreadExitStatus = ExitStatus;
                }
                LastThread = FALSE;
        }

        ExReleasePushLockExclusive(&Process->ProcessLock);
        KeLeaveCriticalRegionThread((PKTHREAD_S)Thread);

        if (DerefThread)
                ObfDereferenceObject (DerefThread);

        if (Process->DebugPort != NULL)  /*------ DebugPort -----------*/
        //if (MyReturnProcessDbgObject(Process) != NULL)  /*------ DebugPort -----------*/
        {
                if (!_bittest((LONG*)&Thread->Tcb.MiscFlags, 0x0D))
                {
                        if (LastThread)
                                DbgkExitProcess (Process->ExitStatus);
                         else
                                DbgkExitThread (ExitStatus);
                }
        }
        //上面检查没有问题OK

        if (KD_DEBUGGER_ENABLED)
        {

                if (Thread->CrossThreadFlags & PS_CROSS_THREAD_FLAGS_BREAK_ON_TERMINATION)
                {
                        if( !( Process->Flags & 0x40000008))
                        {
                                PspCatchCriticalBreak("Critical thread 0x%p (in %s) exited\n",
                                        Thread,
                                        Process->ImageFileName);
                        }
                }
        }

        if (LastThread && _bittest((const signed long *)&Process->Flags, 0xDu) )
        {
                        if (KD_DEBUGGER_ENABLED)
                        {
                                PspCatchCriticalBreak ("Critical process 0x%p (%s) exited\n",
                                        Process,
                                        Process->ImageFileName);
                        } else
                        {
                                KeBugCheckEx (CRITICAL_PROCESS_DIED,
                                        (ULONG_PTR)Process,
                                        0,
                                        0,
                                        0);
                        }
        }

        //ASSERT(Thread->Tcb.KernelApcDisable == 0);
        //上面检查没有问题OK
        TerminationPort = Thread->TerminationPort;
        if (TerminationPort)
        {
                CdMsg.PortMsg.u1.s1.DataLength = sizeof(LARGE_INTEGER);//8
                CdMsg.PortMsg.u1.s1.TotalLength = sizeof(LPC_CLIENT_DIED_MSG);//0x30
                CdMsg.PortMsg.u2.s2.Type = LPC_CLIENT_DIED;//6
                CdMsg.PortMsg.u2.s2.DataInfoOffset = 0;//0
                CdMsg.CreateTime.QuadPart = PS_GET_THREAD_CREATE_TIME (Thread);

                do
                {
                        while (TRUE)
                        {
                                Status = ((Old_LpcRequestPort)LpcRequestPort) (TerminationPort->Port, (PPORT_MESSAGE)&CdMsg);
                                if (Status == STATUS_NO_MEMORY || Status == STATUS_INSUFFICIENT_RESOURCES)
                                {
                                        KeDelayExecutionThread (KernelMode, FALSE, (PLARGE_INTEGER)PspShortTime);
                                        continue;
                                }
                                break;
                        }

                        ObfDereferenceObject (TerminationPort->Port);
                        NextPort = TerminationPort->Next;
                        ExFreePoolWithTag (TerminationPort, 'pTsP'|PROTECTED_POOL);
                        TerminationPort = NextPort;
                } while (TerminationPort);
        }
        //上面检查没有问题OK
        if (Thread->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_DEADTHREAD )
        {
                ExceptionPort = PsCaptureExceptionPort(Process);

                if (ExceptionPort)
                {
                        CdMsg.PortMsg.u1.s1.DataLength = sizeof (LARGE_INTEGER);
                        CdMsg.PortMsg.u1.s1.TotalLength = sizeof (LPC_CLIENT_DIED_MSG);
                        CdMsg.PortMsg.u2.s2.Type = LPC_CLIENT_DIED;
                        CdMsg.PortMsg.u2.s2.DataInfoOffset = 0;
                        CdMsg.CreateTime.QuadPart = PS_GET_THREAD_CREATE_TIME (Thread);

                        while (TRUE)
                        {
                                PETHREAD_S CueThread;
                                CueThread = PsGetCurrentThread();
                                CueThread->Tcb.KernelApcDisable--;
                                Status = ((Old_AlpcpSendMessage)AlpcpSendMessage)(
                                        &ExceptionPort,
                                        &CdMsg.PortMsg.u1.s1.DataLength,
                                        0,
                                        0);
                                CueThread = PsGetCurrentThread();
                                KeLeaveCriticalRegionThread((PKTHREAD_S)CueThread);
                                if (Status != STATUS_NO_MEMORY && Status != STATUS_INSUFFICIENT_RESOURCES)
                                        break;
                                KeDelayExecutionThread (KernelMode, FALSE, (PLARGE_INTEGER)PspShortTime);
                        }
                        ObfDereferenceObject (ExceptionPort);
                }
        }
        //上面检查没有问题OK
        if (Thread->Tcb.Win32Thread)
                ((PKWIN32_THREAD_CALLOUT)(PspW32ThreadCallout)) (Thread, PsW32ThreadCalloutExit);
       
        if (LastThread && Process->Win32Process)
                ((PKWIN32_PROCESS_CALLOUT)(PspW32ProcessCallout)) (Process, FALSE);

        if (!Thread->Tcb.EnableStackSwap)
                KeBugCheckEx (KERNEL_STACK_LOCKED_AT_EXIT, 0, 0, 0, 0);
       
        ((Old_IoCancelThreadIo)IoCancelThreadIo )(Thread);
        ((Old_ExTimerRundown)ExTimerRundown) ();
        CurThreadOr = Thread;
        ((Old_CmNotifyRunDown)CmNotifyRunDown) (Thread);
        ((Old_KeRundownThread)KeRundownThread) ();

        //if ((*(PBYTE)((ULONGLONG)Thread+3))&0x40)
        //{
        //        bPspUmsUnInitThread = TRUE;
        //        ((Old_PspUmsUnInitThread)PspUmsUnInitThread)(Thread);
        //}
        //else
        //{
        //        bPspUmsUnInitThread = FALSE;
        //        if ((*(PBYTE)((ULONGLONG)Thread+3))&0x80)
        //        {
        //                ((Old_PspUmsUnInitThread)PspUmsUnInitThread)(Thread);
        //        }
        //}

        if ((*(PBYTE)((ULONGLONG)Thread + 3)) & 0x40)
                bPspUmsUnInitThread = TRUE;
        else
        {
                bPspUmsUnInitThread = FALSE;
                if (!((*(PBYTE)((ULONGLONG)Thread + 3)) & 0x80))
                        goto LABEL_35;
        }
        ((Old_PspUmsUnInitThread)PspUmsUnInitThread)(Thread);
LABEL_35:
       
        bGetNext = FALSE;
        if (bPspUmsUnInitThread)
        {
                Thread->Tcb.KernelApcDisable--;
                ExAcquirePushLockExclusive (&Process->ProcessLock);
                if ( (Process->UmsScheduledThreads -= 1)  == 0)
                {
                        bGetNext = FALSE;
                        if (Process->Flags&0x40000008)
                                bGetNext = TRUE;
                }
                ExReleasePushLockExclusive(&Process->ProcessLock);
                KeLeaveCriticalRegionThread((PKTHREAD_S)Thread);
        }
        //上面检查没有问题OK
        if (bGetNext)
        {
                for (ForThread = PsGetNextProcessThread (Process, NULL);
                        ForThread != NULL;
                        ForThread = PsGetNextProcessThread (Process, ForThread))
                {
                        if (ExAcquireRundownProtection(&ForThread->RundownProtect))
                        {
                                PETHREAD_S TempThread;
                                if (ForThread == NULL)
                                        TempThread = PsGetCurrentThread();
                                else
                                        TempThread = ForThread ;
                                if ((*(PBYTE)((ULONGLONG)TempThread+3))&0x80)
                                {
                                        ((Old_KeRundownQueueEx)KeRundownQueueEx)(ForThread->Tcb.Ucb->UmsAssociatedQueue,TRUE);
                                }
                                ExReleaseRundownProtection(&ForThread->RundownProtect);
                        }
                }
        }
       
        Teb = (PTEB)Thread->Tcb.Teb;
        Thread->Tcb.Teb = NULL;
        Thread->Tcb.KernelApcDisable--;
       
        _InterlockedOr((volatile LONG *)&CurThreadOr, 0);
        _mm_lfence();
        _InterlockedOr((volatile LONG *)&CurThreadOr, 0);
        _mm_lfence();
        if (Thread->ThreadLock.Value&1)
        {
                ((Old_ExfAcquirePushLockExclusive)ExfAcquirePushLockExclusive) (&Thread->ThreadLock);
                ((Old_ExfReleasePushLockExclusive)ExfReleasePushLockExclusive)(&Thread->ThreadLock);
        }
        //上面检查没有问题OK
        KeLeaveCriticalRegionThread((PKTHREAD_S)Thread);

        //if (Thread->Tcb.SystemThread == 0)
        if (!_bittest((const signed long *)&Thread->Tcb.MiscFlags, 0xDu))
        {
                if (!(Process->Flags&0x40000008))
                {
                        if (Thread->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_DEADTHREAD)
                        {

                                SIZE_T Zero;
                                PVOID BaseAddress;

                                Zero = 0;
                                BaseAddress = Teb->DeallocationStack;
                                ((Old_ZwFreeVirtualMemory)ZwFreeVirtualMemory) (
                                        NtCurrentProcess (),
                                        &BaseAddress,
                                        &Zero,
                                        MEM_RELEASE);

                                if (Process->Wow64Process)
                                         ((Old_RtlFreeUserStack)RtlFreeUserStack)(*(ULONG*)((ULONGLONG)Teb+0x2E0C));
                        }
                        if (Teb->DbgSsReserved[1])
                                ObCloseHandle (Teb->DbgSsReserved[1], UserMode);
                        ((Old_MmDeleteTeb)MmDeleteTeb)(Process,Teb);
                }
        }

        //Thread->ExitStatus = ExitStatus;
        KeQuerySystemTime (&Thread->ExitTime);
       
        if (LastThread)
        {
                Process->ExitTime = Thread->ExitTime;
                ((Old_PspExitProcess)PspExitProcess) (TRUE, Process);

                ProcessToken = ((Old_PsReferencePrimaryToken)PsReferencePrimaryToken) (Process);
                if (((Old_SeAuditingWithTokenForSubcategory)SeAuditingWithTokenForSubcategory) (0x82,ProcessToken))
                {
                        ((Old_SeAuditProcessExit)SeAuditProcessExit) (Process,ExitStatus);
                }

                PsDereferencePrimaryTokenEx (Process, ProcessToken);
                ((Old_ObKillProcess) ObKillProcess) (Process);

                if (Process->SectionObject != NULL)
                {
                        ObDereferenceObject (Process->SectionObject);
                        Process->SectionObject = NULL;
                }

                if (Process->Job != NULL)
                        ((Old_PspExitProcessFromJob)PspExitProcessFromJob )(Process->Job, Process);
        }
        //上面检查没有问题OK
       
        Thread->Tcb.KernelApcDisable--;
        _interlockedbittestandreset((volatile signed long *)&Thread->Tcb.ThreadFlags, 5u);
        ((Old_KeForceResumeThread)KeForceResumeThread) (&Thread->Tcb);
        KeLeaveCriticalRegionThread((PKTHREAD_S)Thread);

        FirstEntry = ((Old_KeFlushQueueApc)KeFlushQueueApc )(Thread, UserMode);

        if (FirstEntry != NULL)
        {
                Entry = FirstEntry;
                do
                {
                        Apc =(PKAPC_S) CONTAINING_RECORD (Entry, KAPC, ApcListEntry);
                        Entry = Entry->Flink;

                        if (Apc->RundownRoutine)
                                (Apc->RundownRoutine) (Apc);
                         else
                                ExFreePool (Apc);
                } while (Entry != FirstEntry);
        }

        if (LastThread)
        {
                ((Old_MmCleanProcessAddressSpace)MmCleanProcessAddressSpace) (Process);
            ((Old_MmCleanProcessAddressSpace)LpcExitProcess)(Process);
        }

        if (Thread->Tcb.LegoData && *(ULONGLONG*)((ULONGLONG)PspLegoNotifyRoutine)) {
                ((PBBT_NOTIFY_ROUTINE)PspLegoNotifyRoutine) (Thread);
        }

        FirstEntry = ((Old_KeFlushQueueApc)KeFlushQueueApc ) (Thread, KernelMode);
       
        if (FirstEntry != NULL || Thread->Tcb.KernelApcDisable != 0)
        {
                KeBugCheckEx (KERNEL_APC_PENDING_DURING_EXIT,
                        (ULONG_PTR)FirstEntry,
                        (ULONG_PTR)Thread->Tcb.KernelApcDisable,
                        (ULONG_PTR)KeGetCurrentIrql(),
                        0);
        }

        if (LastThread) {
                ((Old_KeSetProcess)KeSetProcess )((PRKPROCESS_S)&Process->Pcb, 0, FALSE);
        }
       
        ((Old_KeTerminateThread)KeTerminateThread) ((PVOID)Thread);
}

PVOID PsCaptureExceptionPort(
        IN PEPROCESS_S Process)
{
        PKTHREAD_S        Thread;
        PVOID                ExceptionPort;
       
        Thread = (PKTHREAD_S)PsGetCurrentThread();
        ExceptionPort = Process->ExceptionPortData;
        if (ExceptionPort != NULL)
        {
                Thread->KernelApcDisable--;
                ExAcquirePushLockShared(&Process->ProcessLock);
                ExceptionPort = (PVOID)((ULONGLONG)ExceptionPort & ~0x7);
                ObfReferenceObject(ExceptionPort);
                ExReleasePushLockShared(&Process->ProcessLock);
                KeLeaveCriticalRegionThread(Thread);
        }

        return ExceptionPort;
}

VOID
        FORCEINLINE
        ExReleasePushLockExclusive (
        IN PEX_PUSH_LOCK PushLock
        )
{
        EX_PUSH_LOCK OldValue;

#if DBG
        OldValue = *PushLock;

        ASSERT (OldValue.Locked);
        ASSERT (OldValue.Waiting || OldValue.Shared == 0);

#endif
        OldValue.Value = (ULONG32)InterlockedExchangeAdd64 ((PLONG64)&PushLock->Value, -(LONG64)EX_PUSH_LOCK_LOCK);
        if (!OldValue.Waiting || OldValue.Waking) {
                return;
        }

        ((Old_ExfTryToWakePushLock)ExfTryToWakePushLock) (PushLock);
}

VOID
FORCEINLINE
ExAcquirePushLockExclusive (
     IN PEX_PUSH_LOCK PushLock
     )
{
    if (InterlockedBitTestAndSet64 ((LONG64 *)&PushLock->Value, EX_PUSH_LOCK_LOCK_V))
        ((Old_ExfAcquirePushLockExclusive)ExfAcquirePushLockExclusive) (PushLock);
    ASSERT (PushLock->Locked);
}

已经逆向完成但是有一点小BUG:如果窗口是DOS窗口,进程能够关闭,但是DOS窗口居然关闭不了,哪位大神如果可以修补一下BUG吧,本人已尽力

如果只是单单拿来调试没有任何问题,也不会蓝屏,请放心

如果有哪位仁兄想讨论,可以加企鹅: 肆1六0七七壹

[培训]科锐逆向工程师培训第53期2025年7月8日开班!

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 614
活跃值: (724)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
躺下。。。
2016-11-24 17:01
0
雪    币: 615
活跃值: (765)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
3
逆向了多久呀?  能有过程就好了,直接给结果好像学习不到什么东西,楼主是怎么逆向的呀?  想学习下逆向的过程,第一步,第二步,第三步。楼主辛苦,顶下楼主
2016-11-26 12:42
0
游客
登录 | 注册 方可回帖
返回