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

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

  1. windows 内核下获取进程路径

    windows 内核下获取进程路径 思路:1):在EPROCESS结构中获取.此时要用到一个导出函数:PsGetProcessImageFileName,申明如下: NTSYSAPI UCHAR *  ...

  2. [5]windows内核情景分析---进程线程

    本篇主要讲述进程的启动过程.线程的调度与切换.进程挂靠 进程的启动过程: BOOL CreateProcess ( LPCTSTR lpApplicationName,                 ...

  3. 【旧文章搬运】Windows内核常见数据结构(进程相关)

    原文发表于百度空间,2008-7-24========================================================================== 进程的相关结 ...

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

    进程 1 进程的含义: 1.1   一个是操作系统用来管理进程的内核对象. 内核对象也是系统用来存放关于进程的统计信息的地方. 1.2   还有一个是地址空间,它包括全部可运行模块或DL L 模块的代 ...

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

    1 进程终止的方法: <1>主线程的进入点函数返回(最好使用这种方法) <2>进程中的一个线程调用ExitProcesss函数(应该避免使用这样的方法). <3>还 ...

  6. 《天书夜读:从汇编语言到windows内核编程》八 文件操作与注册表操作

    1)Windows运用程序的文件与注册表操作进入R0层之后,都有对应的内核函数实现.在windows内核中,无论打开的是文件.注册表或者设备,都需要使用InitializeObjectAttribut ...

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

    Windows进程 进程是一个容器,包括程序运行须要的代码.数据.资源等信息, windows进程的特点: 每一个进程都有自己的ID号 每一个进程都有自己的地址空间.进程之间无法訪问对方的地址空间. ...

  8. 《Windows内核安全与驱动开发》 3.1 字符串操作

    <Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发> 3.1 字符串操作 一.字符串的初始化 1. 判断下列代码为什么会蓝屏? U ...

  9. Windows内核基础知识-8-监听进程、线程和模块

    Windows内核基础知识-8-监听进程.线程和模块 Windows内核有一种强大的机制,可以在重大事件发送时得到通知,比如这里的进程.线程和模块加载通知. 本次采用链表+自动快速互斥体来实现内核的主 ...

随机推荐

  1. SpringBoot,SSM和SSH

    Springboot的概念: 是提供的全新框架,使用来简化Spring的初始搭建和开发过程,使用了特定的方式来进行配置,让开发人员不在需要定义样板化的配置.此框架不需要配置xml,依赖于想MAVEN这 ...

  2. RxJS——可观察的对象(Observable)

    可观察的(Observable) 可观察集合(Observables)是多值懒推送集合.它们填补了下面表格的空白: SINGLE MULTIPLE Pull Function Iterator Pus ...

  3. Windows Server 2012 R2 配置IIS

    efs:http://www.07net01.com/storage_networking/windows_server_2012_anzhuang_IIS8_bingzhichi_asp_45191 ...

  4. Jackson 将数组json转List泛型

    闲话不多说,直接上干活,见代码就懂. package com.zzcloud.job.common; import java.util.ArrayList; import java.util.List ...

  5. Odoo onChange使用

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826155.html 转载请注明原文地址: [onchange=前端js函数,可以实现前端实时更新以及修改 ...

  6. cetos报错“Lack of free swap space” 解决方法

    前提:今天发现某台主机一直报警:swap内存被用光 1.查看了服务器的内存情况[发现在物理内存还剩余的情况下,swap开始被使用,甚至到被用光][root@note1 ~]# free -htotal ...

  7. pip换源-换成国内的源

    PyPI使用国内源   通过几次 pip 的使用,对于默认的 pip 源的速度实在无法忍受,于是便搜集了一些国内的pip源,如下: 阿里云 http://mirrors.aliyun.com/pypi ...

  8. deployment:声明式的升级应用

    9.1.使用RC实现滚动升级 #kubectl rolling-update kubia-v1 kubia-v2 --image=luksa/kubia:v2 使用kubia-v2版本应用来替换运行着 ...

  9. vue-cli配置移动端自适应flexible.js

    第一部分:项目中引入lib-flexible 一.项目中安装lib-flexible npm install lib-flexible --save-dev 二.在项目入口文件main.js中引入li ...

  10. js事件2-事件兼容问题

    对于不同的浏览器,事件响应会有一定的不同,所以我们为了更好的用户效果,必须要考虑好事件兼容性问题. 为了兼容不同的浏览器,我们可以自己编写一个事件对象,通过它的事件添加函数和删除函数来给元素添加/删除 ...