当前位置: 首页 > news >正文

windows内核研究(驱动开发之内核编程)

驱动开发


内核编程

windows内核驱动WDK在线文档

在我们之前写3环应用程序时,可以使用windows为我们提供的各种API函数,只要导入头文件<windows.h>就可以了,但是在内核编程的时候,我们需要使用微软为内核程序提供的专用的API,如ntddk.h(前提是你有安装好对应版本的WDK)

WDK帮助文档中只包含了内核模块导出的函数,对于未导出的函数,则不能直接使用,如要使用就要自己定义一个函数指针,并且为该函数指针提供正确的函数地址(1.特征码搜索,2解析内核PDB文件)

返回值

大部分内核函数的返回值都是NTSTATUS类型(宏定义):

NTSTATUS PsCreateSystemThread();
NTSTATUS ZwOpenProcess();
NTSTATUS ZwOpenEvent();

这个值能说明执行的结果:

STATUS_SUCCESS 0x00000000 // 成功
STATUS_INVALID_PARAMETER 0xC000000D // 参数无效
STATUS_BUFFER_OVERFLOw 0x80000005 // 缓冲区长度不够

NTSTATUS的返回值是一个宏定义他的返回值还有很多很多,如果返回的是一个我们不清楚的宏定义,那么可以去ntstatus.h中查看

内核中的异常处理

在内核中,往往一个很小的错误就可能导致蓝屏,为了让自己的程序更加健壮,可以使用windows为我们提供的结构化异常处理机制

__try{// 可能出错的代码
}__except(filter_value){// 出错时要执行的代码
}

出现异常时,可以根据filter_value的值来决定程序该如何执行

  • 为EXCEPTION_EXECUTE_HANDLER(1) // 代码进入except块
  • 为EXCEPTION_CONTINUE_SEARCH(0) // 不处理异常,由上一层调用函数处理
  • 为EXCEPTION_CONTINUE_EXECUTION(-1) // 回去继续执行错误的代码

常用的内核内存函数

c语言内核
mallocExAllocatePool
memsetRtIFillMemory
memcpyRtlMoveMemory
freeExFreePool

内核下的字符串种类

ANSI_STRING/UNICODE_STRING

// ANSI_STRING字符串
typedef struct _STRING{USHORT Length;			// 字符串的长度USHORT MaximumLength;	// 字符串的最大长度PCHAR Buffer;			// 字符串从什么地方开始
}STRING;// UNICODE_STRING字符串
typedef struct _UNICODE_STRING{USHORT Length;USHORT MaxmumLength;PWSTR Buffer;			
}UNICODE_STRING;

内核中常用的字符串操作函数

ANSI_STRING字符串UNICODE_STRING字符串
RtlInitAnsiStringRtlInitUnicodeString
RtlCopyStringRtlCopyUnicodeString
RtlCompareStringRtlCompareUnicodeString
RtAnsiStringToUnicodeStringRtlUnicodeStringToAnsiString

内核空间与内核模块

由于进程的内核空间都是共享的,所以我们在内核空间做的改动将影响到所有的进程

在这里插入图片描述

我们来做一个小实验

#include<ntddk.h>// 定义一个全局变量
ULONG num = 0x12345678;// 卸载函数
VOID DrvUnload(PDRIVER_OBJECT DriverObject) {DbgPrint("我被卸载了\n");
}// 驱动入口函数,相当于main函数
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) {// 打印全局变量的地址DbgPrint("%X\n", &num);// 设置卸载函数DriverObject->DriverUnload = DrvUnload;return STATUS_SUCCESS;
}

可以看到这个地址打印出是FFFFF8043E1F3000

在这里插入图片描述

我们先在内核状态下查看这个地址看是什么

在这里插入图片描述

发现正是我们定义的全局变量值

我们在windbg中再打开一个程序(直接就看dbgview),看它这个进程的0x72433000这个地址里面存储的值是什么

 .process 地址 // 用来切换当前进程的上下文

在这里插入图片描述
查看在dbgview下的FFFFF8043E1F3000地址

在这里插入图片描述

发现我们也同样读取到了这个地上的值并且是一样的

内核模块

DRIVER_OBJCET(驱动对象)结构体

在这里插入图片描述

  • DriverStart // 在内核模块开始的位置
  • DriverSize // 在内核模块的大小(结束的位置)
  • DriverName // 在内核模块中的名称

斜体样式打印DRIVER_OBJECT结构体的地址信息

#include<ntddk.h>// 卸载函数
VOID DrvUnload(PDRIVER_OBJECT DriverObject) {DbgPrint("我被卸载了\n");
}// 驱动入口函数,相当于main函数
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) {// 打印DriverObject结构体的地址DbgPrint("%llX\n", &DriverObject);// 设置卸载函数DriverObject->DriverUnload = DrvUnload;return STATUS_SUCCESS;
}

输入的内核地址为:FFFFE6053C522B20

在这里插入图片描述

查看解析后的结构体

dt _DRIVER_OBJECT FFFFE6053C522B20 // 解析FFFFE6053C522B20 地址对应的_DRIVER_OBJECT

在这里插入图片描述

在_DRIVER_OBJECT结构体中的DriverSection成员他是一个指针,指向的是一个结构体对象(_LDR_DATA_TABLE_ENTRY 是一个链表把内核中所有的模块都链在了一起)

dt _LDR_DATA_TABLE_ENTRY
2: kd> dt _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY+0x000 InLoadOrderLinks : _LIST_ENTRY+0x010 InMemoryOrderLinks : _LIST_ENTRY+0x020 InInitializationOrderLinks : _LIST_ENTRY+0x030 DllBase          : Ptr64 Void+0x038 EntryPoint       : Ptr64 Void+0x040 SizeOfImage      : Uint4B+0x048 FullDllName      : _UNICODE_STRING+0x058 BaseDllName      : _UNICODE_STRING+0x068 FlagGroup        : [4] UChar+0x068 Flags            : Uint4B+0x068 PackagedBinary   : Pos 0, 1 Bit+0x068 MarkedForRemoval : Pos 1, 1 Bit+0x068 ImageDll         : Pos 2, 1 Bit+0x068 LoadNotificationsSent : Pos 3, 1 Bit+0x068 TelemetryEntryProcessed : Pos 4, 1 Bit+0x068 ProcessStaticImport : Pos 5, 1 Bit+0x068 InLegacyLists    : Pos 6, 1 Bit+0x068 InIndexes        : Pos 7, 1 Bit+0x068 ShimDll          : Pos 8, 1 Bit+0x068 InExceptionTable : Pos 9, 1 Bit+0x068 ReservedFlags1   : Pos 10, 2 Bits+0x068 LoadInProgress   : Pos 12, 1 Bit+0x068 LoadConfigProcessed : Pos 13, 1 Bit+0x068 EntryProcessed   : Pos 14, 1 Bit+0x068 ProtectDelayLoad : Pos 15, 1 Bit+0x068 ReservedFlags3   : Pos 16, 2 Bits+0x068 DontCallForThreads : Pos 18, 1 Bit+0x068 ProcessAttachCalled : Pos 19, 1 Bit+0x068 ProcessAttachFailed : Pos 20, 1 Bit+0x068 CorDeferredValidate : Pos 21, 1 Bit+0x068 CorImage         : Pos 22, 1 Bit+0x068 DontRelocate     : Pos 23, 1 Bit+0x068 CorILOnly        : Pos 24, 1 Bit+0x068 ChpeImage        : Pos 25, 1 Bit+0x068 ReservedFlags5   : Pos 26, 2 Bits+0x068 Redirected       : Pos 28, 1 Bit+0x068 ReservedFlags6   : Pos 29, 2 Bits+0x068 CompatDatabaseProcessed : Pos 31, 1 Bit+0x06c ObsoleteLoadCount : Uint2B+0x06e TlsIndex         : Uint2B+0x070 HashLinks        : _LIST_ENTRY+0x080 TimeDateStamp    : Uint4B+0x088 EntryPointActivationContext : Ptr64 _ACTIVATION_CONTEXT+0x090 Lock             : Ptr64 Void+0x098 DdagNode         : Ptr64 _LDR_DDAG_NODE+0x0a0 NodeModuleLink   : _LIST_ENTRY+0x0b0 LoadContext      : Ptr64 _LDRP_LOAD_CONTEXT+0x0b8 ParentDllBase    : Ptr64 Void+0x0c0 SwitchBackContext : Ptr64 Void+0x0c8 BaseAddressIndexNode : _RTL_BALANCED_NODE+0x0e0 MappingInfoIndexNode : _RTL_BALANCED_NODE+0x0f8 OriginalBase     : Uint8B+0x100 LoadTime         : _LARGE_INTEGER+0x108 BaseNameHashValue : Uint4B+0x10c LoadReason       : _LDR_DLL_LOAD_REASON+0x110 ImplicitPathOptions : Uint4B+0x114 ReferenceCount   : Uint4B+0x118 DependentLoadFlags : Uint4B+0x11c SigningLevel     : UChar
dt _LDR_DATA_TABLE_ENTRY ffffe605`3d51e500 // 解析地址对应的结构体
2: kd> dt _LDR_DATA_TABLE_ENTRY ffffe605`3d51e500
ntdll!_LDR_DATA_TABLE_ENTRY+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0xfffff804`36e48210 - 0xffffe605`3c4fd4d0 ]+0x010 InMemoryOrderLinks : _LIST_ENTRY [ 0xfffff804`3e214000 - 0x00000000`0000003c ]+0x020 InInitializationOrderLinks : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ]+0x030 DllBase          : 0xfffff804`3e210000 Void+0x038 EntryPoint       : 0xfffff804`3e215000 Void+0x040 SizeOfImage      : 0x7000+0x048 FullDllName      : _UNICODE_STRING "\??\C:\Users\ygxdks\Desktop\MyDriver2.sys"+0x058 BaseDllName      : _UNICODE_STRING "MyDriver2.sys"+0x068 FlagGroup        : [4]  ""+0x068 Flags            : 0x49104000+0x068 PackagedBinary   : 0y0+0x068 MarkedForRemoval : 0y0+0x068 ImageDll         : 0y0+0x068 LoadNotificationsSent : 0y0+0x068 TelemetryEntryProcessed : 0y0+0x068 ProcessStaticImport : 0y0+0x068 InLegacyLists    : 0y0+0x068 InIndexes        : 0y0+0x068 ShimDll          : 0y0+0x068 InExceptionTable : 0y0+0x068 ReservedFlags1   : 0y00+0x068 LoadInProgress   : 0y0+0x068 LoadConfigProcessed : 0y0+0x068 EntryProcessed   : 0y1+0x068 ProtectDelayLoad : 0y0+0x068 ReservedFlags3   : 0y00+0x068 DontCallForThreads : 0y0+0x068 ProcessAttachCalled : 0y0+0x068 ProcessAttachFailed : 0y1+0x068 CorDeferredValidate : 0y0+0x068 CorImage         : 0y0+0x068 DontRelocate     : 0y0+0x068 CorILOnly        : 0y1+0x068 ChpeImage        : 0y0+0x068 ReservedFlags5   : 0y10+0x068 Redirected       : 0y0+0x068 ReservedFlags6   : 0y10+0x068 CompatDatabaseProcessed : 0y0+0x06c ObsoleteLoadCount : 1+0x06e TlsIndex         : 0x14+0x070 HashLinks        : _LIST_ENTRY [ 0xffff838d`03726e40 - 0x00000000`0000273b ]+0x080 TimeDateStamp    : 0+0x088 EntryPointActivationContext : 0xffffe605`36a47791 _ACTIVATION_CONTEXT+0x090 Lock             : (null) +0x098 DdagNode         : 0x687af49a`00007000 _LDR_DDAG_NODE+0x0a0 NodeModuleLink   : _LIST_ENTRY [ 0xffffe605`3b848c08 - 0xffffe605`3b848c08 ]+0x0b0 LoadContext      : 0xfffff804`3e210003 _LDRP_LOAD_CONTEXT+0x0b8 ParentDllBase    : 0xfffff804`3e216fff Void+0x0c0 SwitchBackContext : 0x00000000`fffffffe Void+0x0c8 BaseAddressIndexNode : _RTL_BALANCED_NODE+0x0e0 MappingInfoIndexNode : _RTL_BALANCED_NODE+0x0f8 OriginalBase     : 0xffffe605`3c4fd5b8+0x100 LoadTime         : _LARGE_INTEGER 0xffffe605`3d51e638+0x108 BaseNameHashValue : 0+0x10c LoadReason       : 0 ( LoadReasonStaticDependency )+0x110 ImplicitPathOptions : 0x3d51e620+0x114 ReferenceCount   : 0xffffe605+0x118 DependentLoadFlags : 0+0x11c SigningLevel     : 0 ''

主要看四个成员

  1. +0x000 InLoadOrderLinks // 这个内核模块的下一个模块地址
  2. +0x030 DllBase // 这个内核模块从什么位置开始
  3. +0x040 SizeOfImage // 这个内核模块的大小
  4. +0x048 FullDllName // 这个内核模块完整的路径名
http://www.lryc.cn/news/593190.html

相关文章:

  • Java无服务架构新范式:Spring Native与AWS Lambda冷启动深度优化
  • 【小沐学GIS】基于Rust绘制三维数字地球Earth(Rust、OpenGL、GIS)
  • C++STL系列之概述
  • OpenCV 官翻5 - 机器学习
  • 【web安全】万能密码
  • 物联网系统中的可视化大屏定义
  • UGUI 性能优化系列:第三篇——渲染与像素填充率优化
  • 小明记账簿焕新记:从单色到多彩的主题进化之路
  • 【Android】ListView与RecyclerView的基础使用
  • 安全隔离新选择:SiLM5768L系列 - 集成互锁功能的高速六通道数字隔离器
  • 从随机数值到特征检测器的学习与更新
  • 【Linux驱动-快速回顾】简单了解一下PinCtrl子系统:设备树如何被接解析与匹配
  • 大模型 Function Call 的实现步骤及示例详解
  • SpringBoot 3.0 挥别 spring.factories,拥抱云原生新纪元
  • Java机考题:815. 公交路线 图论BFS
  • 猎板:在 5G 与 AI 时代,印制线路板如何满足高性能需求
  • SQL Server和PostgreSQL填充因子
  • 数据结构与算法之美:拓扑排序
  • 小谈相机的学习过程
  • ROS2 通过相机确定物品坐标位置
  • MySQL数据丢失救援办法
  • 异步解决一切问题 |消息队列 |减少嵌套 |hadoop |rabbitmq |postsql
  • 智能体之变:深度解析OpenAI ChatGPT Agent如何重塑人机协作的未来
  • 【Qt开发】Qt的背景介绍(三)-> 认识Qt Creator
  • 论文略读:Are Large Language Models In-Context Graph Learners?
  • 高可用架构设计与实践综述
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 基于wordcloud库实现词云图
  • 暑假训练七
  • 进阶向:基于Python的智能客服系统设计与实现
  • 安装单机版本Redis