在上课吃饱了没事干的情况下,花了点功夫还原了我电脑上的NtTerminateProcess的代码
我的系统是Windows XP Kernel Version 2600 (Service Pack 3) MP (2 procs) Free x86 compatible(来自windbg)
nt!NtTerminateProcess: mov edi,edi push ebp mov ebp,esp sub esp,10h push ebx push esi push edi mov eax,KPCR.PrcbData.CurrentThread ;eax = CurrentThread cmp ProcessHandle,0 mov edi,eax mov eax,CurrentThread.ApcState.Process mov Process,eax ;Process = CurrentThread.ApcState.Process je nt!NtTerminateProcess+0x25 ;if(ProcessHandle) ;{ nt!NtTerminateProcess+0x1f: mov ebp_1,1 ;ebp_1 = 1 jmp nt!NtTerminateProcess+0x2d ;} ;else ;{ nt!NtTerminateProcess+0x25: or ProcessHandle,0FFFFFFFFh ;ProcessHandle = NtCurrentProcess() mov ebp_1,0 ;ebp_1 = 0 ;} nt!NtTerminateProcess+0x2d: mov al,CurrentThread.PreviousMode push 0 mov PreviousMode,al ;ebp_8.PreviousMode = CurrentThread.PreviousMode lea eax,EPROCESS push eax push CurrentThread.PreviousMode push dword ptr [nt!PsProcessType] push 1 push ProcessHandle call nt!ObReferenceObjectByHandle ;NTSTATUS = ObReferenceObjectByHandle(ProcessHandle,1,PsProcessType,ebp_8.PreviousMode,&ebp_8.EPROCESS,NULL) test eax,eax mov esi,EPROCESS ;esi = EPROCESS mov ebx,esi ;ebx = esi jl nt!NtTerminateProcess+0x144 ;if(NT_SUCCESS(NTSTATUS)) ;{ nt!NtTerminateProcess+0x5c: lea eax,EPROCESS.Flags test byte ptr [eax+1],20h mov Flags,eax ;Flags = EPROCESS.Flags je nt!NtTerminateProcess+0x7d ;if(EPROCESS.Flags.BreakOnTermination) ;{ nt!NtTerminateProcess+0x6b: lea eax,EPROCESS.ImageFileName push eax push esi push offset "Terminating critical process 0x%p (%s)" call nt!PspCatchCriticalBreak ;PspCatchCriticalBreak("Terminating critical process 0x%p (%s)",EPROCESS,EPROCESS.ImageFileName) ;} nt!NtTerminateProcess+0x7d: lea ecx,EPROCESS.RundownProtect mov RundownProtect,ecx ;RundownProtect = &EPROCESS.RundownProtect call nt!ExAcquireRundownProtection test al,al jne nt!NtTerminateProcess+0xa0 ;if(!ExAcquireRundownProtection(&EPROCESS.RundownProtect)) ;{ nt!NtTerminateProcess+0x8f: mov ecx,esi call nt!ObfDereferenceObject ;ObfDereferenceObject(EPROCESS) mov eax,0C000010Ah ;NTSTATUS = 0xC000010A jmp nt!NtTerminateProcess+0x144 ;return ;} ;else ;{ nt!NtTerminateProcess+0xa0: cmp ebp_1,0 je nt!NtTerminateProcess+0xaf ;if(ebp_1) ;{ nt!NtTerminateProcess+0xa6: mov ecx,Flags push 8 pop eax lock or dword ptr [ecx],eax;EPROCESS.Flags.ProcessDelete = 1; ;} nt!NtTerminateProcess+0xaf: push 0 push ebx mov Flags,122h ;Flags = 0x122 call nt!PsGetNextProcessThread mov esi,eax test esi,esi je nt!NtTerminateProcess+0xe2 ;if(Thread = PsGetNextProcessThread(EPROCESS,NULL)) ;{ nt!NtTerminateProcess+0xc4: and Flags,0 ;Flags = 0 ;do ;{ nt!NtTerminateProcess+0xc8: cmp esi,edi je nt!NtTerminateProcess+0xd5 ;if(Thread != CurrentThread) ;{ nt!NtTerminateProcess+0xcc: push ExitStatus push esi call nt!PspTerminateThreadByPointer ;PspTerminateThreadByPointer(Thread,ExitStatus) ;} ;} nt!NtTerminateProcess+0xd5: push esi push ebx call nt!PsGetNextProcessThread mov esi,eax test esi,esi jne nt!NtTerminateProcess+0xc8 ;while(Thread = PsGetNextProcessThread(EPROCESS,Thread)) ;} nt!NtTerminateProcess+0xe2: mov ecx,RundownProtect call nt!ExReleaseRundownProtection ;ExReleaseRundownProtection(RundownProtect) cmp ebx,Process jne nt!NtTerminateProcess+0x107 ;if(EPROCESS == Process) ;{ nt!NtTerminateProcess+0xef: cmp byte ptr [ebp-1],0 je nt!NtTerminateProcess+0x118 ;if(ebp_1) ;{ nt!NtTerminateProcess+0xf5: mov ecx,ebx call nt!ObfDereferenceObject ;ObfDereferenceObject(EPROCESS) push ExitStatus push edi call nt!PspTerminateThreadByPointer ;PspTerminateThreadByPointer(CurrentThread,ExitStatus) jmp nt!NtTerminateProcess+0x118 ;} ;else ;{ nt!NtTerminateProcess+0x107: cmp ExitStatus,40010004h jne nt!NtTerminateProcess+0x118 ;if(ExitStatus == 0x40010004) ;{ nt!NtTerminateProcess+0x110: push 0 push ebx call nt!DbgkClearProcessDebugObject ;DbgkClearProcessDebugObject(EPROCESS,NULL) ;} ;} ;} nt!NtTerminateProcess+0x118: cmp Flags,122h je nt!NtTerminateProcess+0x130 nt!NtTerminateProcess+0x121: cmp EPROCESS.DebugPort,0 je nt!NtTerminateProcess+0x13a nt!NtTerminateProcess+0x12a: cmp ebp_1,0 je nt!NtTerminateProcess+0x13a ;if(Flags == 0x122 || (EPROCESS.DebugPort == 0 && ebp_1 == 0)) ;{ nt!NtTerminateProcess+0x130: push ebx call nt!ObClearProcessHandleTable ;ObClearProcessHandleTable(EPROCESS) and Flags,0 ;Flags = 0 ;} nt!NtTerminateProcess+0x13a: mov ecx,ebx call nt!ObfDereferenceObject ;ObfDereferenceObject(EPROCESS) mov eax,Flags ;NTSTATUS = Flags ;} ;} nt!NtTerminateProcess+0x144: pop edi pop esi pop ebx leave ret 8
大概的C代码如下
//Windows XP Kernel Version 2600 (Service Pack 3) MP (2 procs) Free x86 compatible NTSTATUS NtTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus) { NTSTATUS status; PEPROCESS eprocess, currentProcess; PETHREAD ethread, currendThread;; BOOLEAN bHandle; currendThread = PsGetCurrentThread(); currentProcess = (EPROCESS)currendThread->Tcb.ApcState.Process; if (ProcessHandle) { bHandle = TRUE; } else { ProcessHandle = NtCurrentProcess(); bHandle = FALSE; } status = ObReferenceObjectByHandle(ProcessHandle, 1, PsProcessType, currendThread->PreviousMode, &eprocess, NULL); if (NT_SUCCESS(status)) { if (eprocess->BreakOnTermination) { PspCatchCriticalBreak("Terminating critical process 0x%p (%s)", eprocess, eprocess->ImageFileName); } if (!ExAcquireRundownProtection(&eprocess->RundownProtect)) { ObfDereferenceObject(eprocess); return 0xC000010A; } else { if (bHandle) { eprocess->ProcessDelete = 1; } status = 0x122; if ((ethread = PsGetNextProcessThread(eprocess, NULL))) { status = STATUS_SUCCESS; do { if (ethread != currendThread) { PspTerminateThreadByPointer(ethread, ExitStatus); } } while ((ethread = PsGetNextProcessThread(eprocess, ethread))); } ExReleaseRundownProtection(&eprocess->RundownProtect); if (eprocess == currentProcess) { if (bHandle) { ObfDereferenceObject(eprocess); PspTerminateThreadByPointer(currendThread, ExitStatus); } else { if (ExitStatus == 0x40010004) { DbgkClearProcessDebugObject(eprocess, NULL); } } } if (status != 0x122 || (eprocess->DebugPort != NULL && bHandle == FALSE)) { ObClearProcessHandleTable(eprocess); status = STATUS_SUCCESS; } ObfDereferenceObject(eprocess); } } return status; }
再说几句废话...看了下PsTerminateProcess发现其实就是NtTerminateProcess调用ObReferenceObjectByHandle后的部分,既然如此,为什么不直接调用呢,还是有其他原因?在这点还是有点无法理解,莫非是为了防止NtTerminateProcess被修改?比较PsTerminateProcess貌似没被导出...