KeStackAttachProcess+ZwTerminateProcess结束进程的分析

本文详细分析了使用ZwTerminateProcess函数结束进程的原理,包括其内部工作流程、关键代码段及参数设置的含义。通过实例测试验证了不同参数值对进程结束行为的影响,揭示了在不同环境下的正确使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

某些ARK会用以下代码来结束进程,对于很多有进程保护的程序都很有效: 
PsLookupProcessByProcessId();

KeStackAttachProcess();

ZwTerminateProcess(0,0);

注意ZwTerminateProcess函数的第一个参数,这是要结束进程的句柄。对于进程句柄来说,-1表示当前进程,而在这里为什么用0呢?我们来分析下NtTerminateProcess:


(图1) 

图1中可以看到代码一开始先是获取当前线程的ETHREAD,然后获得当前先得的当前进程的KPROCESS(也就是EPROCESS),判断ProcessHandle是否为NULL,如果不为NULL则设置局部标志IsProcessHandleSpecified为TRUE,如果为NULL的话则先设置ProcessHandle为-1,然后把IsProcessHandleSpecified设置为FALSE。 

图(2)

这里很简单,仅仅是根据传入的进程句柄得到对应的EPROCESS对象,这里我们称作TerminateProcess,也就是要结束的进程。 

图(3)

图(3)就是一个循环,利用PsGetNextProcessThread来遍历进程中的每个线程,如果线程不是当前线程,就用PspTerminateThreadByPointer结束掉,显然,没有这个判断如果在遍历过程中遍历到当前线程,把自己结束了,就无法继续了。 
转换成C代码就是:

for (Thread = PsGetNextProcessThread (Process, NULL); 
         Thread != NULL; 
         Thread = PsGetNextProcessThread (Process, Thread)) {

        st = STATUS_SUCCESS; 
        if (Thread != SelfThread) { 
            PspTerminateThreadByPointer (Thread, ExitStatus, FALSE); 
        } 
    }


图(4)

图4可以看到,这里有两个判断,一个是判断TerminateProcess是不是当前进程,如果是的话再判断IsProcessHandleSpecified是不是TRUE,如果为真,则结束当前线程,如果不为真则不会结束当前线程。 
这里是关键,在Attach环境下,虽然是在别的线程的地址空间,但是线程仍然是原始的线程,因此,上面的结束进程的代码可以结束掉其他进程,然后ProcessHandle设置为NULL,就会避免NtTerminateProcess把自己的线程也给结束掉。我写了个测试程序,在IOCTL里调用ZwTerminateProcess结束自己的进程,如果ProcessHandle设置为-1,则IsProcessHandleSpecified为TRUE,那么在上面的循环结束本进程的其他线程后,就会走到图4的代码段里,结束当前线程,这样进程就自杀了。而如果把ProcessHandle设置为0,会导致把本进程除当前线程外的线程都给杀掉,却无法结束当前线程,如果当前线程是主线程的话,就无法结束进程。因此在本文开始的代码中,ZwTerminateProcess的ProcessHandle参数必须设置为NULL才行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值