首页
论坛
专栏
课程

[原创]ZwTerminateProcess在WINDOWS 7 RC中改变

2009-5-10 00:30 6979

[原创]ZwTerminateProcess在WINDOWS 7 RC中改变

2009-5-10 00:30
6979
在WINDOWS 7 BETA(BUILD 7000)中,ntoskrnl!ZwTerminateProcess 仍是以KiSystemService stub的形式出现

即:

mov eax , IdOfZwTerminateProcess
lea edx , [esp+arg_0]
pushf
push 8
call KiSystemService
retn 0x8


但在WINDOWS 7 beta之后的某个版本(我不确定,似乎是在7068)中,该函数发生了变化,并且,WINDOWS 7 RC (build 7100)中保留了这一变化:

即ZwTerminateProcess变成了一个真正实现的函数,而不是一个SSDT函数的转发

该函数大体被实现成了如下形式,即调用PsTerminateProcess实现结束进程,并且在内部称为ZwTerminateProcessAssist:

NTSTATUS ZwTerminateProcessAssist(HANDLE ProcessHandle, NTSTATUS   ExitStatus)
{
NTSTATUS status ;
PVOID ProcessObject;

if ( ProcessHandle )
{
    status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_TERMINATE, PsProcessType, 0, &ProcessObject, 0);
    if ( NT_SUCESS(stat))
    {
       status = PsTerminateProcess(ProcessObject, ExitCode);
      ObfDereferenceObject(ProcessObject);

    }
}
else
{
     status = STATUS_NOT_SUPPORTED;
}
return status ;
}



于是所有在RING0调用的ZwTerminateProcess都进入了这个函数来处理,而RING3调用ntdll!ZwTerminateProcess并经由SysEnter进入系统服务调用时,调用的却仍是NtTerminateProcess,该函数照旧使用遍历进程线程并挨个调用PspTerminateThreadByPointer来进行结束

等价于RING0的调用绕过了SSDT HOOK对这个函数的拦截,同时,这个函数不允许对ProcessHandle = 0的进程进行结束
而此前ZwTerminateProcess是可以传入ProcessHandle = 0 的,当传入为0,WINDOWS默认认为要结束的是当前进程,即:

NtTerminateProcess
....
.....

    if (ARGUMENT_PRESENT (ProcessHandle)) {
        ProcessHandleSpecified = TRUE;
    } else {
        ProcessHandleSpecified = FALSE;
        ProcessHandle = NtCurrentProcess();
    }


做这样的修改,可能的原因猜想是WINDOWS希望内核调用此函数时避过一些安全软件的SSDT HOOK,并达到对其的良好兼容

这样做确实是一个比较正确的做法,原因是系统的异常处理时,调用KiDispatchException函数,此函数将实现将内核中检测到的异常分发的到RING3的程序中,如果分发不成功,就调用ZwTerminateProcess结束此进程(也就是当前进程), KiDispatchException认为ZwTerminateProcess必然成功,如果ZwTerminateProcess返回(即未成功自杀),KiDispatchException则立即引发KeBugCheckEx

如果有一些安全软件保护了ZwTerminateProcess调用并拒绝来自KernelMode的请求,又遇到目标程序的异常处理没有正常分发,那么系统就会BSOD

当然,仅为了这一目的,替换KiDispatchException中调用的函数即可,但是可能MS觉得希望自己的调用不受到该死的HIPS的影响(其他WINDOWS组件,例如Windows User Mode framework reflector也使用了这个函数),所以做了这样一个改动

这样的改动使驱动级的进程结束更加轻松,但一些安全产品可能面临需要修改自己代码的问题~如果他们从nt!ZwTerminateProcss来定位ZwTerminateProcess的ID的话,那么就会失败了~
另外,一些使用0号HANDLE结束进程技巧的程序,例如著名的EVA同学的knlps,也将会失效了

[公告]安全服务和外包项目请将项目需求发到看雪企服平台:https://qifu.kanxue.com

最新回复 (7)
weolar 10 2009-5-10 10:04
2
0
嗯,多谢提醒~
whilster 2009-5-10 12:26
3
0
收下了~

if ( NT_SUCESS(stat) 少了个括号,大牛也会不小心
qihoocom 9 2009-5-10 12:33
4
0
多谢LS指正
scm 2009-5-10 15:42
5
0
支持,顺路问问。
为什么我SSDT HOOK ZwTerminateProcess,怎么会让部分程序非法退出?是不是跟我机器上装卡巴有关?
函数如下:
NTSTATUS MyZwTerminateProcess(IN HANDLE ProcessHandle OPTIONAL,IN NTSTATUS ExitStatus)
{
        NTSTATUS        nStatus = STATUS_SUCCESS;
        PEPROCESS        EPROCESSPROTECT = NULL,EPROCESSKILL =NULL;
       
        PsLookupProcessByProcessId((ULONG)dwProtectPID,&EPROCESSPROTECT);

        if(ObReferenceObjectByHandle(ProcessHandle,GENERIC_READ,NULL,KernelMode,(PVOID*)&EPROCESSKILL,0)==STATUS_SUCCESS)
        {
                if(EPROCESSKILL==EPROCESSPROTECT)
                {
                        if(EPROCESSPROTECT!=PsGetCurrentProcess()){
                                nStatus = STATUS_ACCESS_DENIED;
                        }
                        else{
                                KdPrint(("进程保护,程序自身退出请求!"));
                        }
                }

                if(nStatus!=STATUS_SUCCESS){
                        KdPrint(("程序简单自我保护中..."));
                        return nStatus;
                }
        }

        return(OldZwTerminateProcess(ProcessHandle,ExitStatus));
}
qihoocom 9 2009-5-10 15:52
6
0
你的代码欠考虑的太多,仔细看看万能的MSDN,打好基础,再来写程序
scm 2009-5-10 16:12
7
0
大牛能不能指点一二?上面代码我是在黑防上COPY的。那知道,问题多多。
Isaiah 10 2009-5-11 12:09
8
0
黑防<-垃圾书还是别看比较好。
不说内容如何,单说读者导向就不是一个负责任的刊物.
游客
登录 | 注册 方可回帖
返回