• 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
    ", 
    				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("挂起进程成功
    ");
    		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("强杀出错
    ");
    		KeUnstackDetachProcess(pApcState);
    		ObDereferenceObject(proc);
    	}
    
    
    	return;
    }
    HANDLE GetPidByProcessName(char *ProcessName)
    {
    	PEPROCESS pCurrentEprocess = NULL;
    	HANDLE pid = 0;
    	DbgPrint("寻找名为%s的PID
    ", ProcessName);
    	for (int i = 0; i < 2147483647; i += 4)
    	{
    		pCurrentEprocess = GetEprocessByPid((HANDLE)i);
    		if (pCurrentEprocess != NULL)
    		{
    			/*DbgPrint("进程名字为: %s 进程PID = %d 进程的父Pid = %d
    ",
    				PsGetProcessImageFileName(pCurrentEprocess),
    				PsGetProcessId(pCurrentEprocess),
    				PsGetProcessInheritedFromUniqueProcessId(pCurrentEprocess));*/
    			pid = PsGetProcessId(pCurrentEprocess);
    			if (strstr(PsGetProcessImageFileName(pCurrentEprocess), ProcessName) != NULL)
    			{
    				ObDereferenceObject(pCurrentEprocess); //解引用
    				DbgPrint("找到了
    ");
    				return pid;
    			}
    			ObDereferenceObject(pCurrentEprocess); //解引用
    		}
    	}
    	DbgPrint("未找到
    ");
    	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上面都可以.

  • 相关阅读:
    死信队列消息原因排查
    MQ中间件死信队列深度不断增加问题解决案例
    DB2 57016报错的解决办法(表状态不正常,导致表无法操作)
    万门大学--童哲
    eclipse jvm配置
    weblogic threadpool has stuck threads
    8-10 ObserveableCommand演示
    8-9 四种执行方式区别讲解
    8-8 toObserve两种形态演示
    8-7 Observe两种形态演示
  • 原文地址:https://www.cnblogs.com/iBinary/p/11704838.html
Copyright © 2020-2023  润新知