2012年7月5日星期四

驱动层结束进程的办法

#include "ntddk.h"

typedef struct _KAPC_STATE {
    LIST_ENTRY ApcListHead[MaximumMode];
    struct _KPROCESS *Process;
    BOOLEAN KernelApcInProgress;
    BOOLEAN KernelApcPending;
    BOOLEAN UserApcPending;
} KAPC_STATE, *PKAPC_STATE, *PRKAPC_STATE;

VOID KeStackAttachProcess(__inout  PRKPROCESS Process,__out    PRKAPC_STATE ApcState);
VOID KeUnstackDetachProcess(__in  PRKAPC_STATE ApcState);
NTSTATUS PsLookupProcessByProcessId(__in   HANDLE ProcessId,__out  PEPROCESS *Process);

NTSTATUS KillProcessByPID(HANDLE hProcess)
{//通过进程ID号,来结束进程
    PEPROCESS    m_process;
    NTSTATUS     status = STATUS_SUCCESS;
    KAPC_STATE   m_kapc_state;
    ULONG        m_index=0;
    PVOID        m_base_address=NULL;

    //分配一块只读类型的,大小为0x1000的内存块出来//返回值为分配内存的指针  
    m_base_address=ExAllocatePoolWithTag(NonPagedPool,0x1000,'Read');
    if(m_base_address==NULL)   return STATUS_UNSUCCESSFUL;//如果分配内存失败
    memset(m_base_address,0xcc,0x1000);  //初始化相关内存,未初始化的变量会被系统赋初值为0xCC  

    status=PsLookupProcessByProcessId(hProcess,&m_process);    //得到指定进程ID的进程环境块
    if(!NT_SUCCESS(status))    return status;//返回失败

    KeStackAttachProcess (m_process,&m_kapc_state); //附加当前线程到目标进程空间内  
    for(m_index=0;m_index<0x80000000;m_index+=0x1000)//循环遍历
    {      
        if(MmIsAddressValid((PVOID)(m_index)))//如果指定内存大小空间能读能写的话
        {
            __try
            {   //复制m_base_address内存空间内容到m_index大小的空间
                RtlCopyMemory((PVOID)(m_index),m_base_address,0x1000);
            }
            __except(1)
            {continue;}
        }
        else
        {
            if(m_index>0x1000000)    break;
        }
    }

    KeUnstackDetachProcess(&m_kapc_state);//解除附加
    return status;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT  pDriverObject, PUNICODE_STRING  pRegistryPath)
{  
    KillProcessByPID(999);  //拿360Safe.exe或者ZhuDongFangYu.exe的PID试试看。
    return 0;
}

//修改整理与网络。
//made at 2012.03.29
//感谢我的老婆:杜岷娟,有她才有了我的今天。

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//改进版的如下:
//made at 2013.08.02

NTSTATUS KillProcessByPID(IN HANDLE hProcess)
    /*
    通过进程ID号,来结束进程。
    估计这个办法结束不了系统进程(system),因为他没有用户空间。
    */
{
    PEPROCESS    m_process;
    NTSTATUS     status = STATUS_SUCCESS;
    KAPC_STATE   m_kapc_state;
    PVOID        m_base_address=NULL;
    int          size = 0x1000;

#ifdef _X86_
    unsigned int m_index = 0;
    //unsigned int m_base_address = 0;
#endif

#if defined(_AMD64_) || defined(_IA64_)
    unsigned __int64 m_index = 0;
    //unsigned __int64 m_base_address = 0;
#endif
 
    m_base_address=ExAllocatePoolWithTag(NonPagedPool,size,TAG);//分配一块只读类型的,大小为0x1000的内存块出来  
    if(m_base_address==NULL)   {
        return STATUS_UNSUCCESSFUL;
    }
    memset(m_base_address,0xcc,size);//初始化相关内存,未初始化的变量会被系统赋初值为0xCC  

    status=PsLookupProcessByProcessId(hProcess,&m_process);//得到指定进程ID的进程环境块
    if(!NT_SUCCESS(status)) {
        ExFreePoolWithTag(m_base_address, TAG);
        return status;
    }

    KeStackAttachProcess (m_process,&m_kapc_state); //附加当前线程到目标进程空间内  
    for(m_index = 0; m_index < MmSystemRangeStart; m_index += size)//系统的基地址是一个全局变量。0x80000000
    {      
        if(MmIsAddressValid((PVOID)(m_index)))//如果指定内存大小空间能读能写的话
        {
            __try
            {
                RtlCopyMemory((PVOID)(m_index),m_base_address,size);//复制m_base_address内存空间内容到m_index大小的空间
            }  __except(EXCEPTION_EXECUTE_HANDLER)  {
                continue;
            }
        } else {
            if(m_index > MmSystemRangeStart)  {//0x1000000
                break;
            }
        }
    }

    ExFreePoolWithTag(m_base_address, TAG);
    KeUnstackDetachProcess(&m_kapc_state);//解除附加
    return status;
}

/*
说明这个在64位系统很费时间,所以放弃.
改进的思路为:枚举所有的模块,包括主模块,然后ZwUnmapViewOfSection.

别的办法还有:
KeInsertQueueApc结束进程
利用PspTerminateThreadByPointer结束进程
可以考虑把这些代码补上.
*/

没有评论:

发表评论