ytn2001 发表于 2017-6-1 13:34:11

进程强杀

强杀进程
PsTerminateProcess?PspTerminateProcess?
PspTerminateThreadByPointer?PspExitThread未导出函数
暴力搜索
特征值 xp的
0x8B55ff8B
0xA16456EC
0x00000124
0x3B08758B
内核地址空间NtQueryXXX / AuxKlibQueryModuleInformation
ntosknlEndAddr
ntosknlBase


以下代码效率很低 而且只支持XP
#include <ntddk.h>
#include <ntimage.h>
#include <ntdef.h>
#include "Ioctlcmd.h"


const WCHAR deviceLinkBuffer[]= L"\\DosDevices\\KillProc";
const WCHAR deviceNameBuffer[]= L"\\Device\\KillProc";


typedef NTSTATUS (*NTQUERYSYSTEMINFORMATION)(
               
                IN ULONG                        SystemInformationClass,
                OUT PVOID                        SystemInformation,
                IN ULONG                        SystemInformationLength,
                OUT PULONG                        ReturnLength OPTIONAL);
typedef unsigned long DWORD;       
NTQUERYSYSTEMINFORMATION NtQuerySystemInformation;
#define        SystemModuleInformation        11       
typedef struct _SYSTEM_MODULE_INFORMATION
{
                ULONGReserved;
                PVOIDBase;
                ULONGSize;
                ULONGFlags;
                USHORT Index;
                USHORT Unknown;
                USHORT LoadCount;
                USHORT ModuleNameOffset;
                CHAR   ImageName;
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;


PDEVICE_OBJECT g_HookDevice;
NTSTATUSPsLookupProcessByProcessId(ULONG ProcessId,PEPROCESS *Process);


typedefNTSTATUS(*PSPTERPROC) ( PEPROCESS Process, NTSTATUS ExitStatus );
PSPTERPROC MyPspTerminateProcess = NULL ;




NTSTATUS OnUnload(IN PDRIVER_OBJECT DriverObject)
{
        UNICODE_STRING          deviceLinkUnicodeString;
        PDEVICE_OBJECT           p_NextObj;




        DbgPrint("OnUnload called\n");


        p_NextObj = DriverObject->DeviceObject;


        if (p_NextObj != NULL)
        {


                RtlInitUnicodeString( &deviceLinkUnicodeString, deviceLinkBuffer );
                IoDeleteSymbolicLink( &deviceLinkUnicodeString );


                IoDeleteDevice( DriverObject->DeviceObject );
        }
        return STATUS_SUCCESS;
}


NTSTATUS
DispatchControl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp)
{
    PIO_STACK_LOCATION      irpStack;
    PVOID                   inputBuffer;
    PVOID                   outputBuffer;
    PVOID                             userBuffer;
    ULONG                   inputBufferLength;
    ULONG                   outputBufferLength;
    ULONG                   ioControlCode;
    NTSTATUS                     ntstatus;


    unsigned int i;


    unsigned total = 0;
    ULONG count = 0;


    HANDLE handle;




    ULONG cnt;


    PEPROCESS Eprocess = NULL;
    DWORD pid;




    ntstatus = Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;


    irpStack = IoGetCurrentIrpStackLocation (Irp);


    inputBuffer             = Irp->AssociatedIrp.SystemBuffer;
    inputBufferLength       = irpStack->Parameters.DeviceIoControl.InputBufferLength;
    outputBuffer            = Irp->AssociatedIrp.SystemBuffer;
    outputBufferLength      = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
    ioControlCode         = irpStack->Parameters.DeviceIoControl.IoControlCode;


   
   
    switch (irpStack->MajorFunction)
   {
    case IRP_MJ_CREATE:
      break;


    case IRP_MJ_SHUTDOWN:
      break;


    case IRP_MJ_CLOSE:
      break;


    case IRP_MJ_DEVICE_CONTROL:


      if(IOCTL_TRANSFER_TYPE(ioControlCode) == METHOD_NEITHER)
        {
            outputBuffer = Irp->UserBuffer;
      }


      
        switch (ioControlCode )
        {


        case IOCTL_PROC_KILL:
                                if(MyPspTerminateProcess==NULL)
                                {
                                        *(DWORD*)outputBuffer = -1;
                                        Irp->IoStatus.Information = sizeof(DWORD);
                                }
                                else
                                {
                                        pid = *(DWORD*)inputBuffer;
                                        {
                                               
                                                ntstatus = PsLookupProcessByProcessId(pid , &Eprocess);
                                                if(!NT_SUCCESS(ntstatus))
                                                {
                                                        DbgPrint("Failed to lookup process 0x%x, status %8.8x\n", pid , ntstatus);
                                                        *(DWORD*)outputBuffer = 1;
                                                        Irp->IoStatus.Information = sizeof(DWORD);
                                                        break;
                                                }
                                                DbgPrint("Lookup of process 0x%x, PEPROCESS at %8.8x\n", pid, Eprocess);
                                                ntstatus = MyPspTerminateProcess(Eprocess, 0);
                                                if(!NT_SUCCESS(ntstatus))
                                                {
                                                        DbgPrint("Failed to terminate process 0x%x, status %8.8x\n", pid, ntstatus);
                                                        *(DWORD*)outputBuffer = 2;
                                                        Irp->IoStatus.Information = sizeof(DWORD);
                                                        break;
                                                }
                                                *(DWORD*)outputBuffer = 0;
                                                Irp->IoStatus.Information = sizeof(DWORD);
                                                DbgPrint("Process 0x%x terminated\n", pid);
                                        }
                                }
                                break;
                                       
      
        default:
                        break;
            }
    IoCompleteRequest( Irp, IO_NO_INCREMENT );
   
    }
    return ntstatus;
}


NTSTATUS DispatchCreate (
                IN PDEVICE_OBJECT        pDevObj,
                IN PIRP                pIrp)
{


        pIrp->IoStatus.Status = STATUS_SUCCESS;
        pIrp->IoStatus.Information = 0;
        IoCompleteRequest( pIrp, IO_NO_INCREMENT );
        return STATUS_SUCCESS;
}


ULONG GetFunctionAddr( IN PCWSTR FunctionName)
        {
                UNICODE_STRING UniCodeFunctionName;
               
                RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
                return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );   
               
        }


VOID DoFind(IN PVOID pContext)
        {
                NTSTATUS ret;
                PSYSTEM_MODULE_INFORMATIONmodule = NULL;
                ULONG n=0;
                void*buf    = NULL;
                ULONG ntosknlBase;
                ULONG ntosknlEndAddr;
                ULONG curAddr;
                ULONG code1_sp3=0x8b55ff8b,code2_sp3=0xA16456EC,code3_sp3=0x00000124,code4_sp3=0x3B08758B;
                ULONG i;
               
                NtQuerySystemInformation=(NTQUERYSYSTEMINFORMATION)GetFunctionAddr(L"NtQuerySystemInformation");
                if (!NtQuerySystemInformation)
                {
                        DbgPrint("Find NtQuerySystemInformation faild!");
                        goto Ret;
                }
                ret=NtQuerySystemInformation(SystemModuleInformation,&n,0,&n);
                if (NULL==( buf=ExAllocatePoolWithTag(NonPagedPool, n, 'DFSP')))
                {
                        DbgPrint("ExAllocatePool() failed\n" );
                        goto Ret;
                }
                ret=NtQuerySystemInformation(SystemModuleInformation,buf,n,NULL);
                if (!NT_SUCCESS(ret))        {
                        DbgPrint("NtQuerySystemInformation faild!");
                        goto Ret;
                }
                module=(PSYSTEM_MODULE_INFORMATION)((PULONG)buf+1);
                ntosknlEndAddr=(ULONG)module->Base+(ULONG)module->Size;
                ntosknlBase=(ULONG)module->Base;
                curAddr=ntosknlBase;
                ExFreePool(buf);
                for (i=curAddr;i<=ntosknlEndAddr;i++)
                {
                                if (*((ULONG *)i)==code1_sp3)
                                {
                                        if (*((ULONG *)(i+4))==code2_sp3)
                                        {
                                                if (*((ULONG *)(i+8))==code3_sp3)
                                                {
                                                        if (*((ULONG *)(i+12))==code4_sp3)
                                                        {
                                                                MyPspTerminateProcess=(PSPTERPROC)i;
                                                                break;
                                                        }
                                                }
                                        }
                                }
                }
Ret:
        PsTerminateSystemThread(STATUS_SUCCESS);
        }


VOID GetPspAddr()
{
                HANDLE hThread;
                PVOID objtowait=0;
                NTSTATUS dwStatus =
                        PsCreateSystemThread(
                        &hThread,
                      0,
                     NULL,
                        (HANDLE)0,
                      NULL,
                     DoFind,
                        NULL
                        );
                NTSTATUS st;
                if ((KeGetCurrentIrql())!=PASSIVE_LEVEL)
                {
                        st=KfRaiseIrql(PASSIVE_LEVEL);
               
                }
                if ((KeGetCurrentIrql())!=PASSIVE_LEVEL)
                {
                       
                        return;
                }
               
                ObReferenceObjectByHandle(
                        hThread,
                        THREAD_ALL_ACCESS,
                        NULL,
                        KernelMode,
                        &objtowait,
                        NULL
                        );


                st=KeWaitForSingleObject(objtowait,Executive,KernelMode,FALSE,NULL); //NULL表示无限期等待.
                return;
       
       
}


NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
        NTSTATUS rc;
       
        RTL_OSVERSIONINFOW osvi;
        NTSTATUS                ntStatus;
        UNICODE_STRING          deviceNameUnicodeString;
       UNICODE_STRING          deviceLinkUnicodeString;   


        RtlInitUnicodeString (&deviceNameUnicodeString,
          deviceNameBuffer );
        RtlInitUnicodeString (&deviceLinkUnicodeString,
          deviceLinkBuffer );


        ntStatus = IoCreateDevice ( DriverObject,
          0,
          &deviceNameUnicodeString,
          FILE_DEVICE_SWAP,
          0,
          TRUE,
          &g_HookDevice );


        if(! NT_SUCCESS(ntStatus))
        {
              DbgPrint(("Failed to create device!\n"));
              return ntStatus;
       }               
        ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
          &deviceNameUnicodeString );
        if(! NT_SUCCESS(ntStatus))
        {
               IoDeleteDevice(DriverObject->DeviceObject);
                DbgPrint("Failed to create symbolic link!\n");
                return ntStatus;
       }
      DriverObject->MajorFunction      =
      DriverObject->MajorFunction          =   DispatchCreate;
      DriverObject->MajorFunction         =   
       DriverObject->MajorFunction= DispatchControl;


        DriverObject->DriverUnload= OnUnload;


        GetPspAddr();
        if(MyPspTerminateProcess == NULL)
        {
                DbgPrint("PspFunc Not Find!\n");
        }
        return STATUS_SUCCESS;
}


下面一种就方便很多
Win7 x64下强制结束进程
对于用 ObRegisterCallbacks 进行自我保护的进程,要杀死他们的方法只有两种:一种
是温柔的方法,一种是暴力的方法。温柔的方法就是移除对象回调,而暴力的方法,就是找
到更底层的结束进程函数并调用。对付“保护句柄”类的进程保护手段,比较好的方法循坏
调 用 PspTerminateThreadByPointer 来 结 束 进 程 的 每 一 个线 程 。 下 文 拿 360 的
ZhuDongFangYu.exe举例,因为360在Win64上实现自我保护就是使用ObRegisterCallbacks。
总体思路很简单:通过 NTOSKRNL.EXE 导出的 PsTerminateSystemThread 动态定位未导出的
PspTerminateThreadByPointer 。 再 用 PspTerminateThreadByPointer 依 次 结 束
ZhuDongFangYu.exe 的每一个线程。
首先对 PsTerminateSystemThread 进行反汇编:


lkd> uf PsTerminateSystemThread
nt!PsTerminateSystemThread:
fffff800`03f65860 4883ec28 sub rsp,28h
fffff800`03f65864 8bd1 mov edx,ecx
fffff800`03f65866 65488b0c2588010000 mov rcx,qword ptr gs:
fffff800`03f6586f f6814804000010 test byte ptr ,10h
fffff800`03f65876 0f8485cd0200 je nt! ?? ::NNGAKEGL::`string'+0x29eb0
(fffff800`03f92601)
nt!PsTerminateSystemThread+0x1c:
fffff800`03f6587c 41b001 mov r8b,1
fffff800`03f6587f e8d0590500 call nt!PspTerminateThreadByPointer (fffff800`03fbb254)
fffff800`03f65884 90 nop
fffff800`03f65885 e97ccd0200 jmp nt! ?? ::NNGAKEGL::`string'+0x29eb5
(fffff800`03f92606)
nt! ?? ::NNGAKEGL::`string'+0x29eb0:
fffff800`03f92601 b80d0000c0 mov eax,0C000000Dh
nt! ?? ::NNGAKEGL::`string'+0x29eb5:
fffff800`03f92606 4883c428 add rsp,28h
fffff800`03f9260a c3 ret


注意染成蓝色的那两行,除了告诉我们 PsTerminateSystemThread 调用了
PspTerminateThreadByPointer 外,还提示了一个重要的信息:在 Windows 7 x64 上的
PspTerminateThreadByPointer 有三个参数,不同于 Windows XP x86 上的
PspTerminateThreadByPointer 只有两个参数。因为根据 WIN64 上的__fastcall 调用约
定,函数的前四个参数分别放在 rcx、rdx、r8、r9 里(r8b 是一个新增加的寄存器,长度
为 1 字节,是 r8 的低 8 位),从第五个参数开始才放在堆栈里。然后查了一下 WRK,估计
它的原型是:
typedef NTSTATUS (__fastcall *PSPTERMINATETHREADBYPOINTER)
(
        IN PETHREAD Thread,
        IN NTSTATUS ExitStatus,


        IN BOOLEAN DirectTerminate
);

根据反汇编代码可以看出 PspTerminateThreadByPointer 的特征码是 01e8,于是有了
以下代码:
        ULONG32 callcode=0;
        ULONG64 AddressOfPspTTBP=0, AddressOfPsTST=0, i=0;
        AddressOfPsTST=(ULONG64)GetFunctionAddr(L"PsTerminateSystemThread");
        if(AddressOfPsTST==0)
                return STATUS_UNSUCCESSFUL;
        for(i=1;i<0xff;i++)
        {
                if(MmIsAddressValid((PVOID)(AddressOfPsTST+i))!=FALSE)
                {
                        if(*(BYTE *)(AddressOfPsTST+i)==0x01 && *(BYTE *)(AddressOfPsTST+i+1)==0xe8) //目标地址-原始地址-5=机器码 ==> 目标地址=机器码+5+原始地址
                        {
                                RtlMoveMemory(&callcode,(PVOID)(AddressOfPsTST+i+2),4);
                                AddressOfPspTTBP=(ULONG64)callcode + 5 + AddressOfPsTST+i+1;
                        }
                }
        }
        PspTerminateThreadByPointer=(PSPTERMINATETHREADBYPOINTER)AddressOfPspTTBP;
               

接下来就是调用 PspTerminateThreadByPointer 干掉制定进程的所有线程即可。我的
办法是用 PsLookupThreadByThreadId 查询 0x4 至 0x40000 之间所有能被 4 整除的数字,如
果查询成功,就使用 IoThreadToProcess 得到此线程所属的进程。如果它是属于要干掉的
进程,就调用 PspTerminateThreadByPointer 结束之,否则不做处理。另外要注意的是,
但凡 Lookup,必需 Dereference,否则在某些时候会造成蓝屏的后果。代码如下:
        PETHREAD Thread=NULL;
        PEPROCESS tProcess=NULL;
        NTSTATUS status=0;
        for(i=4;i<0x40000;i+=4)
        {
                status=PsLookupThreadByThreadId((HANDLE)i, &Thread);
                if(NT_SUCCESS(status))
                {
                        tProcess=IoThreadToProcess(Thread);
                        if(tProcess==Process)
                                PspTerminateThreadByPointer(Thread,0,1);
                        ObDereferenceObject(Thread);
                }
        }

驱动部分基本写好了,最后在分发函数里获得 PID,并通过 PID 得到 EPROCESS 再调用
HwlTerminateProcess64 即可(以上两段代码是为了讲解方便才分开的,实际上它们在一
个函数里):
                case IOCTL_KILLPROCESS:
                {
                        __try
                                {
                                        Inbuff = *(ULONG*)pIoBuffer;
                                        KdPrint(("Kill Process:%d",Inbuff));
                                        Eprocess = (ULONGLONG)GetEProcessByPid((HANDLE)Inbuff);
                                        if(Eprocess != 0){
                                                MyPsTerminateSystemProcess((PEPROCESS)Eprocess);
                                                ObDereferenceObject((PEPROCESS)Eprocess);
                                                RtlCopyMemory(
                                                        pIrp->AssociatedIrp.SystemBuffer,
                                                        &Eprocess,
                                                        sizeof(ULONGLONG)
                                                        );
                                        }else
                                        {
                                                RtlCopyMemory(
                                                        pIrp->AssociatedIrp.SystemBuffer,
                                                        &Eprocess,
                                                        sizeof(ULONGLONG)
                                                        );
                                        }
                                        status = STATUS_SUCCESS;
                                }
                        __except(EXCEPTION_EXECUTE_HANDLER)
                                {
                                        KdPrint(("结束进程出现异常!"));
                                }
                        break;
                }

输入 ZhuDongFangYu.exe 的 PID,大概过了 20 秒,
ZhuDongFangYu.exe 就退出了。在测试例如 360safe.exe 之类的 GUI 进程,也可以结束
页: [1]
查看完整版本: 进程强杀