windows内核代码之进程操作

[toc]

一丶简介

整理一下windows内核中.常用的代码.这里只整理下进程的相关代码.

二丶 windows内核之遍历进程

内核中记录进程的结构体是EPROCESS结构.所以只需要遍历这个结构即可.标准方法可以使用ZwQuerySystemInformation函数.使用SystemProcessInformation功能号. 另外也有很多种枚举进程的方法比如找到EPROCESS结构进行枚举的.(CPU结构体 KPCR)等等.不过兼容性都是不太好.另一种方法是枚举句柄表 PspCidTable里面有记录EPROCESS 也能检查出断链等隐藏的进程.不过缺点就是. PspCidTable并不是一个公开的变量.要活的它的地址的话.你就需要使用硬编码或者符号了.但是大家知道使用硬编码那么就不会跟着系统走了.如果想要通用那么就最好不要使用. 这里看到网上有更简单的方法.
只用使用几个公开API即可.

  • PsLookUpProcessByProcessId 根据进程Pid返回进程的EPROCESS
  • ObDereferenceObject 返回的EPROCESS会被引用一次,进行解引用.

另外还需要几个API可以获得进程的名字 进程的父PID等等

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

遍历多大,根据进程PID排列.步进为4, 总工是 2^31 -1即可.

具体代码如下:

#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之后,便有导出了.

  • ** 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上面都可以.

原文地址:https://www.cnblogs.com/iBinary/p/11704838.html

时间: 2024-11-09 01:30:38

windows内核代码之进程操作的相关文章

windows 内核下获取进程路径

windows 内核下获取进程路径 思路:1):在EPROCESS结构中获取.此时要用到一个导出函数:PsGetProcessImageFileName,申明如下: NTSYSAPI UCHAR *    PsGetProcessImageFileName(    __in PEPROCESS Process    ); 此函数获取的是一个简单的进程名,并不是绝对路径. 2):ZwQueryInformationProcess. 要想获取进程的绝对路径,可用一个未公开的函数:ZwQueryInf

Windows内核原理研究——进程创建

进程可能是用户接触的Windows系统中最多的部分了,对于Windows系统而言,进程是一个独立的地址空间可以为线程提供一个独立的执行环境, 也就是说 进程= 独立的地址空间 一个进程内核对象 线程= 一个线程自己的栈 一个线程内核对象 当然这个栈是在进程的地址空间中.那么,也就是说线程才是真正“干活”的东西,进程只不过是一些资源的集合而已.只能说是“原材料”. 在我学习Windows内核以前一直觉得进程的种种特性很神奇,比如说地址空间独立是怎么实现的呢?我们的电脑使用的都是同一块内存怎么能实现

Windows内核之进程基本含义以及进程的创建

进程 1 进程的含义: 1.1   一个是操作系统用来管理进程的内核对象. 内核对象也是系统用来存放关于进程的统计信息的地方. 1.2   还有一个是地址空间,它包括全部可运行模块或DL L 模块的代码和数据.它还包括动态内存分配的空间. 如线程堆栈和堆分配空间. 2 操作系统启动应用程序的步骤 2.1 调用C/c++执行时的启动函数 启动函数总共4种,WinMainCRTStartup,wWinMainCRTStartup,mainCRTStartup,wmainCRTStartup. 启动函

Windows内核之进程的终止和子进程

1 进程终止的方法: <1>主线程的进入点函数返回(最好使用这个方法) <2>进程中的一个线程调用ExitProcesss函数(应该避免使用这种方法). <3>另一个进程中的线程调用TerminateProcess函数(应该避免使用这种方法). <4>进程中的所有线程自行终止运行(这种情况几乎从未发生). 1.1  主线程进入点函数返回 始终都应该这样来设计应用程序,即只有当主线程的进入点函数返回时,它的进程才终止运行.这是保证所有线程资源能够得到正确清除的

C++windows内核编程笔记day13 进程、线程与信号量

Windows进程 进程是一个容器,包含程序执行需要的代码.数据.资源等信息, windows进程的特点: 每个进程都有自己的ID号 每个进程都有自己的地址空间,进程之间无法访问对方的地址空间. 每个进程都有自己的安全属性 每个进程至少包含一个线程. 获取和释放环境信息 GetEnvironmentStrings FreeEnvironmentStrings 获取或设置 本程序的环境变量 GetEnvironmentVariable SetEnvironmentVariable 示例: char

Windows内核函数(3) - 内核模式下的注册表操作

Windows内核函数(3) - 内核模式下的注册表操作 2010-12-13 13:37:16|  分类: 驱动编程 |  标签:status  hkey  ulsize  注册  kdprint  |举报|字号 订阅 注册表里的几个概念: 1.       创建关闭注册表项 NTSTATUS   ZwCreateKey(    OUT PHANDLE  KeyHandle,    IN ACCESS_MASK  DesiredAccess, //访问权限,一般为KEY_ALL_ACCLESS

【转】Windows内核下操作字符串!

* Windows内核下操作字符串! */ #include <ntddk.h> #include <ntstrsafe.h> #define BUFFER_SIZE 1024 VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject) { KdPrint(("DriverUnload Load...\n")); } //==================================================

Windows编程 - 遍历所有进程(exe) 代码(C++)

遍历所有进程(exe) 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy/article/details/29381987 遍历所有进程, 即任务管理器中所有的进程目录, 包含名称和进程ID. 返回字典: Key: 进程名字, Value: 进程ID. 代码: /* * main.cpp * * Created on: 2014.06.08 * Author: Spike */ /*vs 2012*/ #include <iostream> #

Windows内核原理系列01 - 基本概念

1.Windows API Windows 应用编程接口(API)是针对WIndwos操作系统用户模式的系统编程接口,包含在WindwosSDK中. 2.关于.NET .NET由一个被称为FCL的类库和一个被称为CLR的公共语言运行库组成.FCL是建立在CLR之上的,而CLR是一组标准的COM服务器,提供了垃圾回收,即时编译类型检验等特性.由于CLR的这些特性,使得开发人员的生产效率得以提高..NET框架与组建的关系如下: .NET应用程序 用户模式(托管代码) —————————— 类库(FC