Windows内核中,为了实现高效的数据结构操作,通常会使用链表和结构体相结合的方式进行数据存储和操作。内核提供了一个专门用于链表操作的数据结构LIST_ENTRY,可以用来描述一个链表中的每一个节点。

使用链表来存储结构体时,需要在结构体中嵌入一个LIST_ENTRY类型的成员变量,用来连接相邻的节点。通过一些列链表操作函数,如InitializeListHead、InsertHeadList、InsertTailList、RemoveEntryList等,可以对链表中的结构体进行插入、删除、遍历等操作。

下面是一个简单的实现,用于枚举所有用户进程,并将进程信息存储到链表结构体中:

#include <ntifs.h>
#include <windef.h> extern PVOID PsGetProcessPeb(_In_ PEPROCESS Process);
NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE ProcessId, PEPROCESS *Process);
extern NTKERNELAPI PVOID PsGetProcessWow64Process(_In_ PEPROCESS Process);
extern NTKERNELAPI UCHAR* PsGetProcessImageFileName(IN PEPROCESS Process);
extern NTKERNELAPI HANDLE PsGetProcessInheritedFromUniqueProcessId(IN PEPROCESS Process); typedef struct
{
DWORD Pid;
UCHAR ProcessName[2048];
DWORD Handle;
LIST_ENTRY ListEntry;
}ProcessList; // 根据进程ID返回进程EPROCESS结构体失败返回NULL
PEPROCESS LookupProcess(HANDLE Pid)
{
PEPROCESS eprocess = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
Status = PsLookupProcessByProcessId(Pid, &eprocess);
if (NT_SUCCESS(Status))
{
return eprocess;
}
return NULL;
} // 内核链表操作
BOOLEAN GetAllProcess()
{
PEPROCESS eproc = NULL;
LIST_ENTRY linkListHead; // 初始化链表头部
InitializeListHead(&linkListHead);
ProcessList *pData = NULL; for (int temp = 0; temp < 100000; temp += 4)
{
eproc = LookupProcess((HANDLE)temp);
if (eproc != NULL)
{
STRING nowProcessnameString = { 0 };
RtlInitString(&nowProcessnameString, PsGetProcessImageFileName(eproc)); // DbgPrint("进程名: %s --> 进程PID = %d --> 父进程PPID = %d\r\n",
// PsGetProcessImageFileName(eproc), PsGetProcessId(eproc), PsGetProcessInheritedFromUniqueProcessId(eproc)); // 分配内核堆空间
pData = (ProcessList *)ExAllocatePool(PagedPool, sizeof(ProcessList));
RtlZeroMemory(pData, sizeof(ProcessList)); // 设置变量
pData->Pid = (DWORD)PsGetProcessId(eproc);
RtlCopyMemory(pData->ProcessName, PsGetProcessImageFileName(eproc), strlen(PsGetProcessImageFileName(eproc)) * 2);
pData->Handle = (DWORD)PsGetProcessInheritedFromUniqueProcessId(eproc); // 插入元素到
InsertTailList(&linkListHead, &pData->ListEntry);
ObDereferenceObject(eproc);
}
} // 输出链表内的数据
while (!IsListEmpty(&linkListHead))
{
LIST_ENTRY *pEntry = RemoveHeadList(&linkListHead);
pData = CONTAINING_RECORD(pEntry, ProcessList, ListEntry); DbgPrint("%d \n", pData->Pid);
DbgPrint("%s \n", pData->ProcessName);
DbgPrint("%d \n", pData->Handle);
ExFreePool(pData);
}
return TRUE;
} VOID UnDriver(PDRIVER_OBJECT driver)
{
DbgPrint(("Uninstall Driver Is OK \n"));
} NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
DbgPrint("hello lyshark \n"); GetAllProcess(); Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}

DbgView是一款用于监视内核和应用程序调试输出的工具,可以输出各种调试信息和日志信息,包括OutputDebugString函数输出的信息。当我们在内核中调用OutputDebugString函数输出信息时,可以通过DbgView查看输出结果,我们手动上述代码后将可以在DbgView中看到输出的进程信息,如下图所示;

如果需要在内核模式中返回一个结构体,可以通过定义一个结构体指针作为函数参数,将结构体指针作为函数返回值来实现。返回结构体,则可以这样来写代码。

#include <ntifs.h>
#include <windef.h> typedef struct
{
int count;
char username[256];
char password[256];
}MyData; // 模拟返回一个结构
BOOLEAN GetProcess(PVOID OutPut)
{
RtlZeroMemory(OutPut, sizeof(MyData));
MyData *data = OutPut; data->count = 100;
RtlCopyMemory(data->username, "lyshark.com", sizeof("lyshark.com"));
RtlCopyMemory(data->password, "https://www.cnblogs.com/lyshark", sizeof("https://www.cnblogs.com/lyshark"));
return TRUE;
} VOID UnDriver(PDRIVER_OBJECT driver)
{
DbgPrint(("Uninstall Driver Is OK \n"));
} NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
DbgPrint("hello lyshark \n");
PVOID Ptr = (PVOID)ExAllocatePool(NonPagedPool, sizeof(MyData)); GetProcess(Ptr); MyData *data = (MyData *)Ptr; DbgPrint("count = %d \n", data->count);
DbgPrint("username = %s \n", data->username);
DbgPrint("password = %s \n", data->password); Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}

输出效果如下图所示;

2.1 Windows驱动开发:内核链表与结构体的更多相关文章

  1. Windows驱动开发-内核常用内存函数

    搞内存常用函数 C语言 内核 malloc ExAllocatePool memset RtlFillMemory memcpy RtlMoveMemory free ExFreePool

  2. windows 驱动开发入门——驱动中的数据结构

    最近在学习驱动编程方面的内容,在这将自己的一些心得分享出来,供大家参考,与大家共同进步,本人学习驱动主要是通过两本书--<独钓寒江 windows安全编程> 和 <windows驱动 ...

  3. Windows驱动开发(中间层)

    Windows驱动开发 一.前言 依据<Windows内核安全与驱动开发>及MSDN等网络质料进行学习开发. 二.初步环境 1.下载安装WDK7.1.0(WinDDK\7600.16385 ...

  4. [Windows驱动开发](一)序言

    笔者学习驱动编程是从两本书入门的.它们分别是<寒江独钓——内核安全编程>和<Windows驱动开发技术详解>.两本书分别从不同的角度介绍了驱动程序的制作方法. 在我理解,驱动程 ...

  5. windows驱动开发推荐书籍

    [作者] 猪头三 个人网站 :http://www.x86asm.com/ [序言] 很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资料少有关系.大多学的驱动开发资料都 ...

  6. Windows驱动——读书笔记《Windows驱动开发技术详解》

    =================================版权声明================================= 版权声明:原创文章 谢绝转载  请通过右侧公告中的“联系邮 ...

  7. Windows驱动开发-IRP的完成例程

    <Windows驱动开发技术详解 >331页, 在将IRP发送给底层驱动或其他驱动之前,可以对IRP设置一个完成例程,一旦底层驱动将IRP完成后,IRP完成例程立刻被处罚,通过设置完成例程 ...

  8. C++第三十八篇 -- 研究一下Windows驱动开发(二)--WDM式驱动的加载

    基于Windows驱动开发技术详解这本书 一.简单的INF文件剖析 INF文件是一个文本文件,由若干个节(Section)组成.每个节的名称用一个方括号指示,紧接着方括号后面的就是节内容.每一行就是一 ...

  9. C++第三十三篇 -- 研究一下Windows驱动开发(一)内部构造介绍

    因为工作原因,需要做一些与网卡有关的测试,其中涉及到了驱动这一块的知识,虽然程序可以运行,但是不搞清楚,心里总是不安,觉得没理解清楚.因此想看一下驱动开发.查了很多资料,看到有人推荐Windows驱动 ...

  10. Windows 驱动开发 - 5

    上篇<Windows 驱动开发 - 4>我们已经完毕了硬件准备. 可是我们还没有详细的数据操作,比如接收读写操作. 在WDF中进行此类操作前须要进行设备的IO控制,已保持数据的完整性. 我 ...

随机推荐

  1. Grafana-安装饼状图

    官网:https://grafana.com/grafana/plugins/grafana-piechart-panel/?tab=installation 使用grafana-cli直接安装 [r ...

  2. Docker 和 VMware不兼容问题

    直接贴解决方案: 当想使用 VMware bcdedit /set hypervisorlaunchtype off 当想使用 Docker 时 bcdedit /set hypervisorlaun ...

  3. AtCoder ABC 164 (D~E)

    比赛链接:Here ABC水题, D - Multiple of 2019 (DP + 分析) 题意: 给定数字串S,计算有多少个子串 \(S[L,R]\)​ ,满足 \(S[L,R]\) 是 \(2 ...

  4. ABP微服务系列学习-搭建自己的微服务结构(二)

    在解决方案根目录添加common.props,这个文件的作用是可以配置项目文件全局的一些属性,如忽略警告,全局PackageReference,语言版本等. <Project> <P ...

  5. Laravel - 虚拟主机引入静态资源

    一. 注意: 引用的静态文件要放在根目录,不要放在assets目录下 二. 引入方法 1.  模板中引入 css      <link rel="stylesheet" hr ...

  6. Hexo中引入另一个文件内容

    有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 安装插件 npm install hexo-include-m ...

  7. [转帖]十分钟掌握 Vim 编辑器核心功能

    https://juejin.cn/post/6929248764746006535 前言 相信不论是前端还是后台多多少少都需要上到服务器上做一些操作,改改配置文件等,大多数 Linux 服务器默认都 ...

  8. [转帖]JMETER结果分析

    https://www.cnblogs.com/a00ium/p/10462892.html 我相信你同意:有很多方法可以收集和解释JMeter结果,你会感到迷茫. 嗯,看完这篇文章后,您将了解收集和 ...

  9. 多个物理磁盘挂载到同一目录的方法 (lvm 软raid)

    多个物理磁盘挂载到同一目录的方法 (lvm 软raid) 背景 公司里面的一台申威3231的机器 因为这个机器的raid卡没有操作界面. 所以只能够通过命令行方式创建raid 自己这一块比较菜, 想着 ...

  10. [转帖]linux下/proc/sysrq-trigger详解

    /proc/sysrq-trigger详解 这是一组"魔术组合键",只要内核没有被完全锁住,不管内核在做什么事情,使用这些组合键能即时打印出内核的信息. 使用SysRq组合键是了解 ...