windows驱动开发-内核编程技术汇总(一)

下面是整理过的一系列内核编程技术知识点。

使用本机系统服务例程

Windows 本机操作系统服务 API 作为一组在内核模式下运行的例程实现。 这些例程的名称以前缀 Nt或 Zw开头。 内核模式驱动程序可以直接调用这些例程。 用户模式应用程序可以使用系统调用访问这些例程。

除了少数例外,每个本机系统服务例程都有两个略有不同的版本,它们名称相似,但前缀不同。 例如,对 NtCreateFile 和 ZwCreateFile 的调用执行类似的操作,实际上由同一内核模式系统例程提供服务。 对于来自用户模式的系统调用,例程的 Nt 和 Zw 版本的行为相同。 对于来自内核模式驱动程序的调用,例程的 Nt 和 Zw 版本在处理调用方传递给例程的参数值的方式上有所不同。

内核模式驱动程序调用本机系统服务例程的 Zw 版本,以通知例程参数来自受信任的内核模式源。 在这种情况下,例程假定它可以安全地使用参数,而无需先验证参数。 但是,如果参数可能来自用户模式源或内核模式源,则驱动程序会改为调用例程的 Nt 版本,这将根据调用线程的历史记录确定参数是源自用户模式还是内核模式。

当用户模式应用程序调用本机系统服务例程的 Nt 或 Zw 版本时,例程始终将其接收的参数视为来自不受信任的用户模式源的值。 例程在使用参数之前彻底验证参数值。 具体而言,例程会探测调用方提供的任何缓冲区,以验证缓冲区是否位于有效的用户模式内存中并正确对齐。

本机系统服务例程对接收的参数进行额外的假设。 如果例程收到指向由内核模式驱动程序分配的缓冲区的指针,则例程假定该缓冲区是在系统内存中分配的,而不是在用户模式内存中分配的。 如果例程收到由用户模式应用程序打开的句柄,则例程在用户模式句柄表中查找句柄,而不是在内核模式句柄表中查找句柄。

在少数情况下,参数值的含义在用户模式和内核模式的调用之间差异更大。 例如, ZwNotifyChangeKey 例程 (或其 NtNotifyChangeKey 对应) 具有一对输入参数 ApcRoutine 和 ApcContext,其含义不同,具体取决于参数是来自用户模式还是内核模式源。 对于从用户模式调用, ApcRoutine 指向 APC 例程, ApcContext 指向操作系统在调用 APC 例程时提供的上下文值。 对于从内核模式调用, ApcRoutine 指向 WORK_QUEUE_ITEM 结构, ApcContext 指定 WORK_QUEUE_ITEM 结构描述的工作队列项的类型。

PreviousMode

当用户模式应用程序调用本机系统服务例程的 Nt 或 Zw 版本时,系统调用机制会将调用线程捕获到内核模式。 为了指示参数值源自用户模式,系统调用的陷阱处理程序将调用方线程对象中的 PreviousMode 字段设置为 UserMode。 本机系统服务例程检查调用线程的 PreviousMode 字段,以确定参数是否来自用户模式源。

如果内核模式驱动程序调用本机系统服务例程并将参数值传递给来自内核模式源的例程,则驱动程序必须确保当前线程对象中的 PreviousMode 字段设置为 KernelMode。

内核模式驱动程序可以在任意线程的上下文中运行,并且此线程的 PreviousMode 字段可能设置为 UserMode。 在这种情况下,内核模式驱动程序可以调用本机系统服务例程的 Zw 版本,以通知例程参数值来自受信任的内核模式源。 Zw 调用将转到一个精简包装器函数,该函数替代当前线程对象中的 PreviousMode 值。 包装器函数将 PreviousMode 设置为 KernelMode 并调用例程的 Nt 版本。 从 Nt 版本的例程返回时,包装器函数将还原线程对象的原始 PreviousMode 值并返回 。

内核模式驱动程序可以直接调用本机系统服务例程的 Nt 版本。 当内核模式驱动程序处理可在用户模式或内核模式下发起的 I/O 请求时,驱动程序可以调用例程的 Nt 版本,以便当前线程的 PreviousMode 值在调用期间保持不变。 NtXxx 例程检查调用线程的 PreviousMode 值,以确定参数值是来自用户模式应用程序还是内核模式组件,并相应地处理它们。

如果内核模式驱动程序调用 NtXxx 例程,并且当前线程对象中的 PreviousMode 值未准确指示参数值来自用户模式还是内核模式源,则可能会出现错误。

例如,假设内核模式驱动程序在任意线程的上下文中运行,并且此线程的 PreviousMode 值设置为 UserMode。 如果驱动程序将内核模式文件句柄传递给 NtClose 例程,则此例程会检查 PreviousMode 值,并确定该句柄必须是用户模式句柄。 当 NtClose 在用户模式句柄表中找不到句柄时,它将返回STATUS_INVALID_HANDLE错误代码。 同时,驱动程序会泄漏从未关闭的内核模式句柄。

对于另一个示例,如果 NtXxx 例程的参数包含输入或输出缓冲区,并且 如果 PreviousMode = UserMode,该例程将调用 ProbeForRead 或 ProbeForWrite 例程来验证缓冲区。 如果在系统内存而不是用户模式内存中分配缓冲区, 则 ProbeForXxx 例程将引发异常, NtXxx 例程返回STATUS_ACCESS_VIOLATION错误代码。

如有必要,驱动程序可以调用 ExGetPreviousMode 例程,从当前线程对象获取 PreviousMode 值。 或者,驱动程序可以从描述所请求的 I/O 操作的 IRP 结构中读取 RequestorMode 字段。 RequestorMode 字段包含请求操作的线程的 PreviousMode 值的副本。

库和头文件

内核模式驱动程序通过调用 Ntoskrnl.exe 动态链接库中的 Nt 和 Zw 入口点 (DLL) 来使用本机系统服务例程。 此 DLL 包含这些例程的实际实现。 若要访问这些入口点,驱动程序会静态链接到 Ntoskrnl.lib 库,该库在 Windows 驱动程序工具包 (WDK) 中可用。 在 Ntoskrnl.lib 中实现的例程是动态链接到运行时Ntoskrnl.exe入口点的存根。

WDK 文档介绍了Ntoskrnl.exe中的一些(但不是全部 )Zw 入口点。 大多数记录的 Zw 例程在 WDK 的 Wdm.h 头文件中定义,但有些例程在其他头文件(如 Ntddk.h 和 Ntifs.h)中定义。

通常,用户模式应用程序不调用 Nt 和 Zw 例程。 相反,应用程序可能会调用 Win32 例程(例如 CreateFile),后者随后调用本机系统服务例程(如 NtCreateFile 或 ZwCreateFile)来执行请求的操作。 但是,用户模式应用程序可以直接调用 Nt 或 Zw 例程来执行 Win32 例程不支持的操作。

用户模式应用程序通过调用Ntdll.dll动态链接库中的入口点来使用本机系统服务例程。 这些入口点将对 Nt 和 Zw 例程的调用转换为捕获到内核模式的系统调用。 若要访问这些入口点,用户模式应用程序会静态链接到 WDK 中提供的 Ntdll.lib 库。 在 Ntdll.lib 中实现的例程是可在运行时动态链接到 Ntdll.dll 中的入口点的存根。

Windows SDK 文档介绍了 Ntdll.lib 中的一些(但不是全部) Nt 入口点。 大多数记录的 Nt 例程都在 Windows SDK 的 Winternl.h 头文件中定义。 本文档很少提及 Zw 入口点,Windows SDK 中没有头文件包含 Zw 例程的定义。

如果出现几个次要异常, Nt 例程Ntdll.dll中的每个入口点都有 Zw 例程的匹配入口点。 WDK 和 Windows SDK 的文档建议应用程序开发人员避免调用未记录的 Nt 入口点,并警告 Zw 入口点可能会在将来的 Windows 版本中从Ntdll.dll消失。 从用户模式调用 Zw 例程的应用程序开发人员应为此做好准备。

有关可由应用程序调用的 Nt 例程的说明,请参阅 Winternl、 winternl.h 标头和 杂项Low-Level客户端支持。 Windows SDK 文档中 Nt 例程的一些参考页将例程标记为“已弃用”,并建议读者使用等效的 Win32 例程,而不是已弃用的 Nt 例程。

用户模式应用程序无法调用 Ntoskrnl.exe 中的入口点,内核模式驱动程序无法调用 Ntdll.dll 中的入口点。

内核全局变量
Mm64BitPhysicalAddress

在 Wdm.h 中声明Mm64BitPhysicalAddress,声明如下:

PBOOLEAN Mm64BitPhysicalAddress
// Wdm.h

指定硬件和操作系统是否支持 64 位物理地址。 如果硬件和操作系统支持 64 位物理地址,则指向值为 TRUE ,否则为 FALSE 。

用法如下:

向驱动程序添加 64 位寻址支持可以显著提高整体系统性能。 对于 (DMA) 执行直接内存访问的设备驱动程序来说,这一点尤其重要。 在 64 位 Microsoft Windows 中,执行 DMA 但不支持 64 位寻址的设备驱动程序是双缓冲的,这会导致相对性能降低。

尽管双缓冲通常 (8 GB 系统上) 单个百分点的影响相对较小,但这足以影响 I/O 密集型任务,例如数据库活动。 随着物理内存量的增加,这种负面的性能影响也会增加。

若要支持 64 位 DMA,驱动程序应遵循以下准则:

  • 使用 PHYSICAL_ADDRESS 结构进行物理地址计算;
  • 将整个 64 位地址视为有效的物理地址。 例如,驱动程序不应在锁定的缓冲区上调用 MmGetPhysicalAddress 、放弃高 32 位,并将截断的地址传递给 32 位组件适配器。 这会导致内存损坏、I/O 丢失和系统故障;
  • 添加 GetScatterGatherList 和 PutScatterGatherList的高性能散点/收集例程;
  • 检查 Mm64BitPhysicalAddress 全局系统变量的值。 如果为 TRUE,则系统支持 64 位物理寻址;
  • 将 DEVICE_DESCRIPTION 结构的 Dma64BitAddresses 成员设置为 TRUE 以指示驱动程序支持 64 位 DMA 地址;
  • 32 位 Windows 中的 DMA 例程是 64 位就绪的。 如果设备驱动程序正确使用这些例程,则 DMA 代码应在 64 位 Windows 上无需修改即可正常工作;
MmBadPointer    

声明如下:

PVOID MmBadPointer;
// Wdm.h 中声明

它指向保证无效的内存位置的指针,注意从 Windows 8.1 开始,MmBadPointer 已弃用。 驱动程序应改用 MM_BAD_POINTER 宏。如果访问由 MmBadPointer 变量指定的内存地址,操作系统将生成一个 bug 检查。

可以使用 MmBadPointer 调试驱动程序代码。 将任何未初始化的指针变量设置为 MmBadPointer ,以查找代码首次尝试取消引用无效指针的时间。

MmBadPointer PAGE_SIZE中的所有地址都保证无效。 例如,如果 Address 是指针,并且 MmBadPointer<= Address<MmBadPointer + PAGE_SIZE,则尝试访问 *Address 会导致操作系统检查生成 bug,MmBadPointer + PAGE_SIZE不保证无效。

MM_BAD_POINTER

驱动程序可以使用 MM_BAD_POINTER 宏作为要分配给未初始化或不再有效的指针变量的错误指针值,尝试访问此无效指针变量指向的内存位置将导致 bug 检查。

在许多硬件平台上,地址 0,往往表示为命名常量 NULL是无效地址,但驱动程序开发人员不应假设地址 0 在所有平台中均无效。 将未初始化或无效的指针变量设置为地址 0 不一定总能保证可以检测到通过这些指针进行的不当访问。

相反,可以保证 MM_BAD_POINTER 值是运行驱动程序的每个平台上的无效地址。

在地址 0 是无效地址的平台上,访问 IRQL < DISPATCH_LEVEL 地址 0 的驱动程序会导致异常 (访问冲突) ,该异常会被try/except 语句无意中捕获 。 因此,驱动程序的异常处理代码可能会屏蔽无效访问,并在调试过程中阻止检测这种访问。 但是,可以保证对 MM_BAD_POINTER 地址的访问会导致 bug 检查,异常处理程序无法对此进行屏蔽。

下面的代码示例演示如何将 MM_BAD_POINTER 值分配给名为 ptr 的指针变量。 Ntdef.h 标头文件将 PUCHAR 类型定义为指向 unsigned char 的指针。

PUCHAR ptr = (PUCHAR)MM_BAD_POINTER; // Now ptr is guaranteed to fault.

将 ptr 设置为 MM_BAD_POINTER 后,尝试访问 ptr 指向的内存位置会导致 bug 检查。

事实上,MM_BAD_POINTER 是无效地址的整个页面的基址。 因此,对 MM_BAD_POINTER 至 (MM_BAD_POINTER + PAGE_SIZE - 1) 范围内的地址进行任何访问都会导致 bug 检查。

从 Windows 8.1 开始,MM_BAD_POINTER 宏在 Wdm.h 标头文件中定义。 但是,使用此宏定义的驱动程序代码可以在 Windows Vista 及更低版本的 Windows 中运行。

PsInitialSystemProcess    

定义为:

PEPROCESS PsInitialSystemProcess;
// 在 Ntddk.h 中声明

指向系统进程的 EPROCESS 结构,该结构是一个不透明结构,后续会详细介绍。

注意: 在这里解释一下为什么很少去明确介绍一些内核内部使用的数据结构,对于驱动开发人员,逆向出某个内核布局和结构,并不难!但是,作为驱动开发工程师,需要知道不应该去假定内核使用的数据结构是什么样的,用于正式驱动发布的代码不应依赖于一些未公开的结构,这些结构可能在不同版本之间存在差异,这会导致驱动的可移植性和稳定性下降。

NLS_MB_CODE_PAGE_TAG    

声明为:

extern BOOLEAN NLS_MB_CODE_PAGE_TAG;	

 指定代码页是单字节代码页还是多字节代码页。

对于多字节代码页,NLS_MB_CODE_PAGE_TAG为 TRUE;对于单字节代码页为 FALSE。

保留NLS_MB_CODE_PAGE_TAG供系统使用。 在用户模式下,请改为调用 GetCPInfoEx 。如果可能,应用程序应使用 Unicode 而不是代码页。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/831619.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【知识加油站】——机电产品数字孪生机理模型构建

明确一种多领域、多层次、参数化、一致性的机电一体化装备数字孪生机理模型构建准则&#xff01; 关键词英文简称&#xff1a; 数字孪生&#xff1a;DT物联网&#xff1a;IoT网络物理系统&#xff1a;CPS高级架构&#xff1a;HLA统一建模语言&#xff1a;UML数控机床&#xf…

webpack打包工具

目录 1. yarn包管理器 1.1 yarn 是什么, 有什么用? 1.2 yarn的使用 ​​​​​​2. webpack基本概述 2.1 webpack是什么&#xff1f; 2.2 什么是打包&#xff1f; 2.3 webpack能做什么&#xff1f; 3. webpack基本使用步骤 3.1 webpack基本使用步骤 3.2 package.jso…

阿里低代码引擎学习记录

官网 一、关于设计器 1、从设计器入手进行低代码开发 设计器就是我们用拖拉拽的方法&#xff0c;配合少量代码进行页面或者应用开发的在线工具。 阿里官方提供了以下八个不同类型的设计器Demo&#xff1a; 综合场景Demo&#xff08;各项能力相对完整&#xff0c;使用Fusion…

转速和频率转换功能块(CODESYS ST源代码)

1、转速/频率常用转换关系 转速/频率/线速度/角速度计算FC_200 plc计算角速度-CSDN博客文章浏览阅读3.2k次。里工业控制张力控制无处不在,也衍生出很多张力控制专用控制器,磁粉制动器等,本篇博客主要讨论PLC的张力控制相关应用和算法,关于绕线机的绕线算法,大家可以参看专…

手写一个uart协议——rs232

先了解一下关于uart和rs232的基础知识 文章目录 一、RS232的回环测试1.1模块整体架构1.2 rx模块设计1.2.1 波形设计1.2.2代码实现与tb1.2.4 仿真 1.3 tx模块设计1.3.1 波形设计1.3.2 代码实现与tb1.3.4 顶层设计1.3.3 仿真 本篇内容&#xff1a; 一、RS232的回环测试 上位机…

Leaflet在WGS84 Web墨卡托投影与WGS84经纬度投影下空间信息变形问题及修正-以圆为例

目录 前言 一、投影的相关知识 1、经纬度投影 2、Web墨卡托投影 二、经纬度投影下的空间信息展示 1、空间信息展示 2、效果展示 3、经纬度投影下的圆修正 三、Web墨卡托投影下空间信息展示 1、底图引用 2、自定义生成圆 总结 前言 在GIS的知识海洋中&#xff0c;对…

记一次从登录框到前台rce

接口未授权挖掘 在网站未登录的情况下&#xff0c;由于不知道后台接口。唯一办法通过js文件、路径扫描。通过这种收集方式使用burp进行批量扫描&#xff0c;分别探测GET/POST请求。观察响应包跟状态码。判断响应包&#xff0c;确定存在未授权后&#xff0c;再构造数据包。 2 突…

【JVM】Java工具(Arthas,APM,Java Agent,JMX)

Java工具 常见的Java工具有以下几类&#xff1a; 1、诊断类工具&#xff0c;如Arthas、VisualVM等。 2、开发类工具&#xff0c;如Idea、Eclipse。 3、APM应用性能监测工具&#xff0c;如Skywalking、Zipkin等。 4、热部署工具&#xff0c;如Jrebel等。 Arthas中 Java Ag…

【kettle006】kettle访问华为openGauss高斯数据库并处理数据至execl文件(已更新)

1.一直以来想写下基于kettle的系列文章&#xff0c;作为较火的数据ETL工具&#xff0c;也是日常项目开发中常用的一款工具&#xff0c;最近刚好挤时间梳理、总结下这块儿的知识体系。 2.熟悉、梳理、总结下华为openGauss高斯数据库相关知识体系 3.欢迎批评指正&#xff0c;跪谢…

zookeeper 都有哪些使用场景?(最全 zookeeper 用法介绍)

目录 一、面试官心理分析 二、面试题剖析 1.分布式协调 2.分布式锁 3.元数据/配置信息管理 4.HA高可用性 一、面试官心理分析 现在聊的是分布式系统&#xff0c;面试官跟你聊完了 dubbo 相关的一些问题之后&#xff0c;已经确认你对分布式服务框架/RPC框架基本都有一些认…

windows驱动开发-PNP管理器

PNP技术是由Microsoft提出的&#xff0c;英文Plug and play的缩写&#xff0c;中译即插即用&#xff0c;意思是系统自动侦测周边设备和板卡并自动安装设备驱动程序&#xff0c;做到插上就能用&#xff0c;无须人工干预&#xff0c;是Windows自带的一项技术。所谓即插即用是指将…

计算机网络chapter2——应用层

文章目录 第2章 应用层章节引出—— 2.1应用层协议原理2.1.1 网络应用程序体系结构&#xff08;1&#xff09;客户-服务器体系结构&#xff08;2&#xff09;对等(P2P)体系结构2.1.2 进程通信1.客户和服务器进程2.进程与计算机网络之间的接口3. 进程寻址 2.1.3 可供应用程序使用…

STM32数字示波器+详细注释+上位机程序+硬件

目录 1、设计指标&#xff1a; 2、功能&#xff1a; 3、上位机的程序 ​4、测试的照片 5、PCB 6、模拟电路板 7、程序 资料下载地址&#xff1a;STM32数字示波器详细注释上位机程序硬件 1、设计指标&#xff1a; 主控: STM32…

中华科技控股集团:人工智能标准化引领者与数字化服务新航程的启航者

4月30日, 矗立于时代科技潮头的中华科技控股集团&#xff0c;自2010年在香港这片国际金融沃土上诞生以来&#xff0c;便以其独特的国资背景与全球化视野&#xff0c;肩负起推动中国科技进步与产业升级的重任。作为国资委麾下的重要一员&#xff0c;中华科技始终坚持创新驱动发展…

MLP手写数字识别(2)-模型构建、训练与识别(tensorflow)

查看tensorflow版本 import tensorflow as tfprint(Tensorflow Version:{}.format(tf.__version__)) print(tf.config.list_physical_devices())1.MNIST的数据集下载与预处理 import tensorflow as tf from keras.datasets import mnist from keras.utils import to_categori…

Adobe 更新 Firefly Image 3 图像生成模型

一个工具或者模型&#xff0c;对于初次使用的人来说&#xff0c;易用性和超出预期的效果很能吸引使用者&#xff0c;suno和mj在这方面我感觉确实不错&#xff0c;第一次使用感觉很惊艳。 Adobe 更新 Firefly Image 3 图像生成模型&#xff0c;我用了mj的提示词&#xff0c;最后…

【Cpp】类和对象#拷贝构造 赋值重载

标题&#xff1a;【Cpp】类和对象#拷贝构造 赋值重载 水墨不写bug 目录 &#xff08;一&#xff09;拷贝构造 &#xff08;二&#xff09;赋值重载 &#xff08;三&#xff09;浅拷贝与深拷贝 正文开始&#xff1a; &#xff08;一&#xff09;拷贝构造 拷贝构造函数&…

UG NX二次开发(C#)-获取Part中对象创建时的序号(*)

文章目录 1、前言2、UG NX的对象序号讲解3、采用UG NX二次开发或者建模序号4、注意事项1、前言 在UG NX中,我们创建任意一个对象,都会在模型历史中添加一个创建对象的编号,即是对象序号,这个是递增的,当删除中间产生的对象时,其序号会重新按照建模顺序重新排布。今天一个…

MLP实现fashion_mnist数据集分类(2)-函数式API构建模型(tensorflow)

使用函数式API构建模型&#xff0c;使得模型可以处理多输入多输出。 1、查看tensorflow版本 import tensorflow as tfprint(Tensorflow Version:{}.format(tf.__version__)) print(tf.config.list_physical_devices())2、fashion_mnist数据集分类模型 2.1 使用Sequential构建…

内网安全-代理Socks协议路由不出网后渗透通讯CS-MSF控制上线简单总结

我这里只记录原理&#xff0c;具体操作看文章后半段或者这篇文章内网渗透—代理Socks协议、路由不出网、后渗透通讯、CS-MSF控制上线_内网渗透 代理-CSDN博客 注意这里是解决后渗透通讯问题&#xff0c;之后怎么提权&#xff0c;控制后面再说 背景 只有win7有网&#xff0c;其…