windows內核代碼之進程操做

[toc]windows

一丶簡介

整理一下windows內核中.經常使用的代碼.這裏只整理下進程的相關代碼.函數

二丶 windows內核之遍歷進程

內核中記錄進程的結構體是EPROCESS結構.因此只須要遍歷這個結構便可.標準方法可使用ZwQuerySystemInformation函數.使用SystemProcessInformation功能號. 另外也有不少種枚舉進程的方法好比找到EPROCESS結構進行枚舉的.(CPU結構體 KPCR)等等.不過兼容性都是不太好.另外一種方法是枚舉句柄表 PspCidTable裏面有記錄EPROCESS 也能檢查出斷鏈等隱藏的進程.不過缺點就是. PspCidTable並非一個公開的變量.要活的它的地址的話.你就須要使用硬編碼或者符號了.可是你們知道使用硬編碼那麼就不會跟着系統走了.若是想要通用那麼就最好不要使用. 這裏看到網上有更簡單的方法.
只用使用幾個公開API便可.編碼

  • PsLookUpProcessByProcessId 根據進程Pid返回進程的EPROCESS3d

  • ObDereferenceObject 返回的EPROCESS會被引用一次,進行解引用.code

另外還須要幾個API能夠得到進程的名字 進程的父PID等等orm

  • PsGetProcessImageFileName(IN PEPROCESS proc)
  • PsGetProcessInheritedFromUniqueProcessId(IN PEPROCESS proc)

遍歷多大,根據進程PID排列.步進爲4, 總工是 2^31 -1便可.blog

具體代碼以下:進程

#include <ntifs.h>

NTKERNELAPI UCHAR* PsGetProcessImageFileName(IN PEPROCESS Process); //未公開的進行導出便可
NTKERNELAPI HANDLE PsGetProcessInheritedFromUniqueProcessId(IN PEPROCESS Process);//未公開進行導出

void DriverUnLoad(PDRIVER_OBJECT pDriverObj)
{
    KdPrint(("驅動卸載成功"));
}
/*
1.枚舉全部進程.  2^31方
*/
PEPROCESS GetEprocessByPid(HANDLE pid)
{
    //根據PID 返回PEPROCESS
    PEPROCESS pEpro = NULL;
    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
    ntStatus = PsLookupProcessByProcessId(pid, &pEpro);
    if (NT_SUCCESS(ntStatus))
    {
        return pEpro;
    }
    return NULL;
}
void IteratorProcess()
{
    PEPROCESS pCurrentEprocess = NULL;
    for (int i = 0; i < 2147483648; i += 4)
    {
        pCurrentEprocess = GetEprocessByPid((HANDLE)i);
        if (pCurrentEprocess != NULL)
        {
            DbgPrint("進程名字爲: %s 進程PID = %d 進程的父Pid = %d\r\n", 
                PsGetProcessImageFileName(pCurrentEprocess),
                PsGetProcessId(pCurrentEprocess),
                PsGetProcessInheritedFromUniqueProcessId(pCurrentEprocess));
            ObDereferenceObject(pCurrentEprocess); //解引用
        }
    }
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath)
{
    ULONG iCount = 0;
    NTSTATUS ntStatus;
    pDriverObj->DriverUnload = DriverUnLoad;
    IteratorProcess();  //遍歷進程

    return STATUS_SUCCESS;
}

結果
內存

三丶Windows內核之暫停與恢復進程

在Ring3咱們想暫停與恢復進程通常都是使用NativeApi.動態獲取等等.
在內核中同樣也有.在VISTA以後,便有導出了.ci

  • ** NTKERNELAPI NTSTATUS PsSuspendProcess(PEPROCESS Proc) **
  • ** NTKERNELAPI NTSTATUS PsResumeProcess(PEPROCESS Proc) ;**

未掛起前

加載驅動進行掛起

#include <ntifs.h>

NTKERNELAPI NTSTATUS PsSuspendProcess(PEPROCESS proc);  //暫停進程
NTKERNELAPI NTSTATUS PsResumeProcess(PEPROCESS proc);   //恢復進程
void DriverUnLoad(PDRIVER_OBJECT pDriverObj)
{
    KdPrint(("驅動卸載成功"));
}
/*
1.枚舉全部進程.  2^31方
*/
PEPROCESS GetEprocessByPid(HANDLE pid)
{
    //根據PID 返回PEPROCESS
    PEPROCESS pEpro = NULL;
    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
    ntStatus = PsLookupProcessByProcessId(pid, &pEpro);
    if (NT_SUCCESS(ntStatus))
    {
        return pEpro;
    }
    return NULL;
}

void TestSusPendProcess(ULONG pid)
{
    PEPROCESS pCurrentEprocess = NULL;
    pCurrentEprocess = GetEprocessByPid((HANDLE)pid);
    if (pCurrentEprocess != NULL)
    {
        PsSuspendProcess(pCurrentEprocess);
        DbgPrint("掛起進程成功\r\n");
        ObDereferenceObject(pCurrentEprocess);
    }

}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath)
{
    ULONG iCount = 0;
    NTSTATUS ntStatus;
    pDriverObj->DriverUnload = DriverUnLoad;
    //IteratorProcess();  //遍歷進程
    TestSusPendProcess(2728); //掛起進程,傳入指定PID
    return STATUS_SUCCESS;
}

恢復進程代碼同上.不一一舉例.

四丶結束進程

4.1 標準方法結束

標準方法結束 就是採用ZwOpenProcess 打開進程獲取句柄.而後使用內核函數 ZwTerminateProcess結束. 最後ZwClose關閉句柄.
非標準結束就是Attach進程.而後內存清零來結束這個進程.若是能Attach上.那麼就能夠用來強殺進程.固然Attach能夠. 本身修改頁表.(PDE PTE)等.修改指定內存也是同樣的.

代碼以下

void ZwKillProcess(ULONG pid)
{
    HANDLE ProcessHandle = NULL;
    OBJECT_ATTRIBUTES obj;
    CLIENT_ID cid = { 0 };
    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
    InitializeObjectAttributes(&obj,NULL,OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,NULL,NULL);
    cid.UniqueProcess = (HANDLE)pid;
    cid.UniqueThread = 0;
    ntStatus =  ZwOpenProcess(&ProcessHandle, GENERIC_ALL, &obj, &cid);
    if (NT_SUCCESS(ntStatus))
    {
        ZwTerminateProcess(ProcessHandle, 0);
        ZwClose(ProcessHandle);
    }
    ZwClose(ProcessHandle);
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath)
{
    ULONG iCount = 0;
    NTSTATUS ntStatus;
    pDriverObj->DriverUnload = DriverUnLoad;
    //IteratorProcess();  //遍歷進程
    ZwKillProcess(2728); //掛起進程,傳入指定PID
    return STATUS_SUCCESS;
}

4.2非標準方法結束進程

非標準的方式就是Attach進進程進行內存清零.這裏提供了兩種方法.原理是同樣

KeAttachProcess方法 與 KeStackAttachProcess方法. 其中第一種屬於舊方法了.根據MSDN所說API已經升級爲了KeStackAttachProcess

代碼以下

#include <ntifs.h>

NTKERNELAPI UCHAR* PsGetProcessImageFileName(IN PEPROCESS Process); //未公開的進行導出便可


NTKERNELAPI VOID NTAPI KeAttachProcess(PEPROCESS Process);
NTKERNELAPI VOID NTAPI KeDetachProcess();

void DriverUnLoad(PDRIVER_OBJECT pDriverObj)
{
    KdPrint(("驅動卸載成功"));
}
/*
1.枚舉全部進程.  2^31方
*/
PEPROCESS GetEprocessByPid(HANDLE pid)
{
    //根據PID 返回PEPROCESS
    PEPROCESS pEpro = NULL;
    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
    ntStatus = PsLookupProcessByProcessId(pid, &pEpro);
    if (NT_SUCCESS(ntStatus))
    {
        return pEpro;
    }
    return NULL;
}



//新方法
void MemKillProcess(HANDLE pid)
{
    PEPROCESS proc = NULL;
    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
    PKAPC_STATE pApcState = NULL;


    PsLookupProcessByProcessId((HANDLE)pid,&proc);
    if (proc == 0)
    {
        
        return;
    }
    
    //KeAttachProcess(proc);
    //KeDetachProcess()  等都已通過時.因此使用新的
    pApcState = (PKAPC_STATE)ExAllocatePoolWithTag(NonPagedPool, sizeof(PKAPC_STATE), '1111');
    if (NULL == pApcState)
    {
        ObDereferenceObject(proc);
        return;
    }
    __try{
        KeStackAttachProcess(proc, pApcState);
        //KeAttachProcess(proc);
        for (int i = 0x10000; i < 0x20000000; i += PAGE_SIZE)
        {
            __try
            {
                memset((PVOID)i, 0, PAGE_SIZE);
            }
            __except (1)
            {
                ;       //內部處理異常
            }
        }
        KeUnstackDetachProcess(pApcState);
        //KeDetachProcess();
        ObDereferenceObject(proc);
        return;
    }
    __except (1)
    {
        DbgPrint("強殺出錯\r\n");
        KeUnstackDetachProcess(pApcState);
        ObDereferenceObject(proc);
    }


    return;
}
HANDLE GetPidByProcessName(char *ProcessName)
{
    PEPROCESS pCurrentEprocess = NULL;
    HANDLE pid = 0;
    DbgPrint("尋找名爲%s的PID\r\n", ProcessName);
    for (int i = 0; i < 2147483647; i += 4)
    {
        pCurrentEprocess = GetEprocessByPid((HANDLE)i);
        if (pCurrentEprocess != NULL)
        {
            /*DbgPrint("進程名字爲: %s 進程PID = %d 進程的父Pid = %d\r\n",
                PsGetProcessImageFileName(pCurrentEprocess),
                PsGetProcessId(pCurrentEprocess),
                PsGetProcessInheritedFromUniqueProcessId(pCurrentEprocess));*/
            pid = PsGetProcessId(pCurrentEprocess);
            if (strstr(PsGetProcessImageFileName(pCurrentEprocess), ProcessName) != NULL)
            {
                ObDereferenceObject(pCurrentEprocess); //解引用
                DbgPrint("找到了\r\n");
                return pid;
            }
            ObDereferenceObject(pCurrentEprocess); //解引用
        }
    }
    DbgPrint("未找到\r\n");
    return (HANDLE)-1;
}
//舊方法
void OldMemKillProcess(HANDLE pid)
{
    SIZE_T i = 0;
    //依附進程
    PEPROCESS proc = 0;
    PsLookupProcessByProcessId(pid, &proc);
    if (NULL == proc)
    {
        return;
    }
    KeAttachProcess((PEPROCESS)proc); //這裏改成指定進程的 EPROCESS
    for (i = 0x10000; i < 0x20000000; i += PAGE_SIZE)
    {
        __try
        {
            memset((PVOID)i, 0, PAGE_SIZE); //把進程內存所有置零
        }
        _except(1)
        {
            ;
        }
    }
    //退出依附進程
    KeDetachProcess();
    ObDereferenceObject(proc);
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath)
{
    ULONG iCount = 0;
    NTSTATUS ntStatus;
    pDriverObj->DriverUnload = DriverUnLoad;

    MemKillProcess(GetPidByProcessName("calc.exe")); //新方法
    OldMemKillProcess(GetPidByProcessName("calc.exe"));//舊方法
    return STATUS_SUCCESS;
}

兩種方法在win7 64上面均可以.

相關文章
相關標籤/搜索