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

驱动篇的开端

准备

在做之后的动作前,因为win7及其以上的版本默认是不支持DbgPrint(大家暂时理解为内核版的printf)的打印,所以,为了方便我们的调试,我们先要修改一下注册表

创建一个reg文件然后运行

Windows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Debug Print Filter]
"DEFAULT"=dword:0000000f

之后我们要去网上找一下能够直接加载驱动的工具,比如我这个在52破解上找的

在这里插入图片描述

在做好这些之后,我们打开我们的驱动开发环境,之前专栏里面的文章应该是说过了

装好了的环境应该是能够看见这些东西

在这里插入图片描述

我们的驱动依次有NT(不支持即插即用功能),WDM(支持即插即用功能),WDF(以WDM为基础的框架,为了简化我们开发的流程),以及UMDF,KMDF(用户,内核)。为了理解底层原理,我们后续的demo会围绕前两个来进行

创建一个新的Empty WDM Driver文件

首先看右边,我红圈标出来的地方默认会有inf文件,里面会标记我们驱动的信息,如果不填编译器会报错,这里我们暂时不需要,因为我们现阶段还是只是在不验证驱动签名的Win7上进行开发,等到后续介绍到Win10之后,我们会重新介绍inf,这里删掉就行了

在这里插入图片描述

右键打开ntifs.h头文件,可以看见里面包含了很多头文件,所以我们引用这个就足够了

在这里插入图片描述

随便写一个小demo作为我们驱动开发的开端

#include<ntifs.h>NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) {DbgPrint("Hello My Driver!");return STATUS_SUCCESS;
}

还要注意,由于vs2015的原因,我们默认的目标平台是win10,这里得改下,改成win7

在这里插入图片描述

然后我们的驱动为了方便编译,把视警告为错误关掉

在这里插入图片描述

这样我们就可以编译出一个sys文件了,把它移到我们目标win7上去,打开DbgView(微软官方工具),打开驱动加载工具,注意这两个都要管理员权限,加载驱动,最后的结果应该是我们可以在DbgView里面看见我们目标的字符串

在这里插入图片描述

这时候如果我们按下卸载驱动,会发现我们是卸载不掉的,这是因为我们在之前的代码中没有留下卸载驱动的函数,把它补上

#include<ntifs.h>VOID DriverUnload(PDRIVER_OBJECT DriverObject) {DbgPrint("Driver has benn Unloaded");}NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) {DbgPrint("Hello My Driver!");DbgBreakPoint();pDriver->DriverUnload = DriverUnload;return STATUS_SUCCESS;
}

这里除了为我们卸载驱动做出了示范之外,还有一个函数DbgBreakPoint,它等价于int3,方便我们调试

编译后运行,结果应该是这样,可以看见有字符串打出来了,同时系统也进入了int3 断点

在这里插入图片描述

驱动里面的字符串

我们使用驱动可以像在C中一样,使用char,驱动开发本身给了我们更加安全的方法,因为它不像传统字符串以’\0’结尾,就很容易在读取的时候越界,而驱动里面提供了PUNICODE_STRING这种结构

它就规定了字符串的长度和buffer指针
在这里插入图片描述

在这里插入图片描述

但是它是Unicode宽字符,我们可以在DbgPrint中打印DriverEntry中的Reg这个参数来作为示例,反正待会我们也会介绍这个参数

在这里插入图片描述

我们看看打印了什么,除了我们自己的字符串外,pReg里面装的就是一个注册表的值,这个值的最后一段正是我们驱动的名字

在这里插入图片描述

注册表

在这里插入图片描述

我们跟着之前被打印出来的字符找到了这个注册表项,里面有几个值,我们来一一介绍

首先是Type,毫无疑问,我们属于1

Type值为1:表示该驱动程序是一个标准的驱动程序,通常用于设备驱动程序。
Type值为2:表示该驱动程序是一个文件系统驱动程序(File System Driver, FSD)。
Type值为3:表示该驱动程序是一个网络驱动程序(Network Driver)。
Type值为4:表示该驱动程序是一个显示驱动程序(Display Driver)或视频驱动程序。
Type值为5:表示该驱动程序是一个多媒体驱动程序(Multimedia Device Driver)。
Type值为6:表示该驱动程序是一个非设备驱动程序,可能是一个服务或内核模式的过滤器驱动程序。

然后是这个Start值,这里我们的值为3,也就是我们需要手动加载

Start的值设置为0,则驱动由启动引导器加载,应该跟“随着开机,最先启动”是同一回事;
Start的值设置为1,则驱动由操作系统的I/O子系统加载,即在系统内核初始化时加载;
Start的值设置为2,则驱动/服务在启动后自动加载;
Start的值设置为3,则驱动/服务就是按需手动加载;
Start的值设置为4,驱动/服务就是被禁用的状态

Error Control指的是当驱动加载失败时返回的值,这里暂时不细说

Image Path实际上就是我们驱动的路径

在这里插入图片描述

动态调试一下

借着之前在代码中下的DbgBreakPoint,我们来具体看看代码运行,打开我们的windbg,在加载PDB符号文件之后,打开pDriver

0: kd> dt pDriver
Local var @ 0x905209e0 Type _DRIVER_OBJECT*
0x8834a148 +0x000 Type             : 0n4+0x002 Size             : 0n168+0x004 DeviceObject     : (null) +0x008 Flags            : 2+0x00c DriverStart      : 0x9d08c000 Void+0x010 DriverSize       : 0x6000+0x014 DriverSection    : 0x88d09008 Void+0x018 DriverExtension  : 0x8834a1f0 _DRIVER_EXTENSION+0x01c DriverName       : _UNICODE_STRING "\Driver\2"+0x024 HardwareDatabase : 0x841af250 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"+0x028 FastIoDispatch   : (null) +0x02c DriverInit       : 0x9d090000     long  2!GsDriverEntry+0+0x030 DriverStartIo    : (null) +0x034 DriverUnload     : (null) +0x038 MajorFunction    : [28] 0x83ef8da3     long  nt!CcSetFileSizesEx+0

里面这个DriverStart就是我们二进制文件的首地址

0: kd> db 0x9d08c000
ReadVirtual: 9d08c000 not properly sign extended
9d08c000  4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00  MZ..............
9d08c010  b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00  ........@.......
9d08c020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
9d08c030  00 00 00 00 00 00 00 00-00 00 00 00 d8 00 00 00  ................
9d08c040  0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68  ........!..L.!Th
9d08c050  69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f  is program canno
9d08c060  74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20  t be run in DOS 
9d08c070  6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00  mode....$.......

现在我们暂时需要注意的还有一个DriverInit,它指示我们GsDriverEntry+0这个位置才驱动的真正入口点,而不是我们驱动里面写的DriverEntry

再打开一个结构DriverExtension,这里我们注意到一个有意思的事情,那就是我们驱动的服务名叫做2

0: kd> dt _DRIVER_EXTENSION 0x8834a1f0
2!_DRIVER_EXTENSION+0x000 DriverObject     : 0x8834a148 _DRIVER_OBJECT+0x004 AddDevice        : (null) +0x008 Count            : 0+0x00c ServiceKeyName   : _UNICODE_STRING "2"

让我们再回顾一下驱动的加载卸载流程,注册(在注册表里面写值)->启动(按照服务来启动)->停止(按照服务来停止)->卸载(删除注册表里的值)

所以,当我们的驱动注册了之后,我们完全可以将驱动当作服务进行启动和停止

在这里插入图片描述

细节

我们用CFF 来打开我们的sys文件,有一项的名字叫做Debug Directory RVA,它在.rdata里面

在这里插入图片描述

我们再打开.rdata的描述,可以看见0x2000对应0x600,所以我们的Debug 信息从0x610开始

在这里插入图片描述

通过上图我们也知道了为什么要专门注意这段信息的原因,这里存储的是我们pdb的路径,由于我们开发环境路径可能会带着自己的名字之类的信息,所以这里我们是必须要抹除的

http://www.lryc.cn/news/496462.html

相关文章:

  • OpenSSL 自建CA 以及颁发证书(网站部署https双向认证)
  • 吾杯网络安全技能大赛WP(部分)
  • 按vue组件实例类型实现非侵入式国际化多语言翻译
  • Java入门:22.集合的特点,List,Set和Map集合的使用
  • 重生之我在异世界学编程之C语言:深入指针篇(下)
  • 理解Parquet文件和Arrow格式:从Hugging Face数据集的角度出发
  • 下载 M3U8 格式的视频
  • Tomcat使用教程
  • LabVIEW氢气纯化控制系统
  • 现在的电商风口已经很明显了
  • Uniapp触底刷新
  • 开源项目 - face parsing 人脸区域分割 人像区域分割 人脸分割 人像区域分割 BiSeNet
  • python游戏设计---飞机大战
  • 13TB的StarRocks大数据库迁移过程
  • HTTP代理有那些常见的安全协议?
  • Kylin Server V10 下基于Kraft模式搭建Kafka集群
  • tauri使用github action打包编译多个平台arm架构和inter架构包踩坑记录
  • Python爬虫与窗口实现翻译小工具(仅限学习交流)
  • 紫光展锐联合上汽海外发布量产车型,赋能汽车智能化
  • Maven 打包出现问题解决方案
  • 第四话:JS中的eval函数
  • 歇一歇,写写段子
  • TypeScript (一)运行环境配置,数据类型,可选类型,联合类型,type与interface,交叉类型,断言as,字面量类型,类型缩小
  • Linux Find 命令详情解释
  • 2024年认证杯SPSSPRO杯数学建模A题(第一阶段)保暖纤维的保暖能力全过程文档及程序
  • Milvus python库 pymilvus 常用操作详解之Collection(下)
  • 李飞飞:Agent AI 多模态交互的前沿探索
  • [October 2019]Twice SQL Injection
  • Python爬虫——城市数据分析与市场潜能计算(Pandas库)
  • 如何搭建JMeter分布式集群环境来进行性能测试