Windows驱动开发(9)——双机调试
今天具体学习一下双机调试。
前言肯定主要就是这个调试器怎么去用了,这里我贴一下 VirtualKD 的项目地址——(https://github.com/4d61726b/VirtualKD-Redux)。也由衷地感谢这些开发者给我们开发了这么好用的工具,让我们环境搭建这一步走了很大的捷径,上一篇博客中遇到的问题,当时因为比较急直接去提了 issue,而作者也给出了很耐心的解释,应该是照顾我这个萌新吧。
真的是非常感谢。
Windbg的使用我是实在用不来那个纯命令行的调试器,因为根本不知道跑起来之后怎么加断点,所以我使用了 Windbg preview,这个据说是要在微软商店下载的,如果停用了 windows 更新的话,好像就直接用不了了,为了这个我重新打开了我 windows 的更新。
初始布局大概是这样:
当提示 Debuggee is running 的时候,是没办法在 KD 命令行输入指令的,断点也打不了。
最开始的情况应该是:这里根本就不知道在哪的,左边的反汇编窗口应该也不是指向了自己想要的位置,此时不知道在哪里断就可以先放着,然后点 break 暂停,这个暂停是 ...
Windows驱动开发(8)——双机调试
今天还有学习一下双机调试。
环境准备先添加一个串行端口,使用命名管道。
然后开启虚拟机,运行命令
1bcdedit /copy {current} /d "win10 x64 debug for windbg"
这个命令的意思是把当前启动项复制一份命名为 win10 x64 debug for windbg
然后再运行 msconfig,选择刚复制的一份启动项,打开高级选项,勾选调试,选择 COM1。
然后重启之后就完事了,选择第三个选项即可。
这里用一下 VirtualDK 这个软件,非常好用,直接在虚拟机运行 target64 的 exe 文件,然后注意,最重要的一点:
F8 选择禁用驱动签名
F8 选择禁用驱动签名
F8 选择禁用驱动签名
重要的事情说三遍,不然根本连不上,后面 Windbg 再慢慢学吧,今天因为这个环境搞了很久。
Windows驱动开发(7)——句柄回调
今天学习驱动保护进程。
实现原理我们在驱动层注册一个进程回调,当调用 OpenProcess 的时候,会触发这个回调,我们在这里取消掉进程结束的权限就可以达到防止进程被结束的目的。
回调函数先写一下回调函数:
1234567891011121314151617181920212223242526OB_PREOP_CALLBACK_STATUS MyProtect( PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation){ if (OperationInformation->KernelHandle) { } else { ACCESS_MASK AccessBitsToClear = PROCESS_TERMINATE; PEPROCESS process = (PEPROCESS)OperationInformation->Object; PUCHAR p ...
Windows驱动开发(6)——加载驱动过程
今天顺便再解决一下应用层加载卸载驱动的方式。
加载驱动加载驱动过程
用OpenSCManager打开服务控制管理器
用CreateService创建对应服务
如果驱动服务已经创建过,则用OpenService打开服务
用StartService加载启动驱动服务
清理工作,用CloseServiceHandle关闭释放句柄
一个一个介绍一下每一步的详细步骤吧
打开服务控制管理器使用如下代码获得一个SCM管理器的句柄。
1SC_HANDLE hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
第一个参数是目标计算机的名称。 如果指针为 NULL 或指向空字符串,则该函数将连接到本地计算机上的服务控制管理器。
第二个参数是服务控制管理器数据库的名称。 此参数应设置为SERVICES_ACTIVE_DATABASE。 如果为 NULL,则默认打开SERVICES_ACTIVE_DATABASE数据库。
第三个参数是我们获得句柄的权限,SC_MANAGER_ALL_ACCESS 表示获得所有权限。
创建服务 ...
Windows驱动开发(5)——设备通信
今顺便再来搞搞这个 IRP_MJ_READ 和 IRP_MJ_WRITE 等事件。
应用层读写设备文件写文件同样在函数的 SWITCH 分发中添加 case,然后在 DriverEntry 中注册回调,我们先了解三个指针,这里后面有大用,这三个指针是传参的三种方式。
1234567case IRP_MJ_WRITE: { char *ptr1 = pirp->UserBuffer; char *ptr2 = pirp->MdlAddress; char *ptr3 = pirp->AssociatedIrp.SystemBuffer; kprintf(("Line %d:xia0ji233: ring3 calls ReadFile ptr1=%p ptr2=%p ptr3=%p\n"), __LINE__, ptr1, ptr2, ptr3); break;}
WriteFile 是 ring3 向 ring0 写入数据的一个过程,因此我们在 ring0 层要拷贝 UserBuffer 里面 ...
Windows驱动开发(4)——设备通信
今天来了解一下 R3 与 R0 通信。
应用程序与内核交互打开设备事件也是解决了昨天 3 环应用程序与内核通信的问题,我们应该用以下代码创建设备:
12345678910#include <iostream>#include <Windows.h>#define SYMBOL L"\\??\\xia0ji2333"int main(){ HANDLE DriverHandle = CreateFile(SYMBOL, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); printf("error=%x\n", GetLastError()); printf("handle=%x\n", DriverHandle); getchar();}
驱动加载成功之后,直接运行:
发 ...
Windows驱动开发(3)——创建设备
今天来了解一下IRP模块。
IRPIRP是输入输出请求包(I/O Request Package)的简称
常见的事件有以下几种:
IRP_MJ_CREATE:请求一个句柄 CreateFile
IRP_MJ_CLOSE:关闭句柄 CloseHandle
IRP_MJ_READ:从设备得到数据ReadFile
IRP_MJ_WRITE:传送数据到设备 WriteFile
IRP_MJ_DEVICE_CONTROL:控制操作利用IOCTL宏 DeviceIOControl
代码基本框架这里注册这个 IRP 事件跟注册卸载驱动函数差不多,代码如下:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849#include<ntifs.h>#define kprintf(format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, format, ##__VA_ARGS__)N ...
数据结构复习(1)
开始复习复习数据结构。
数据结构的基本概念术语
数据:是信息的载体,计算机程序加工的原料。
数据元素:是数据的基本单位,一个数据元素可由若干个数据项组成,数据项是最小不可分割的单位。
数据对象:具有相同性质的数据元素的集合。最简单的就是一个结构体的数组,就是一个数据对象。比如学生结构体,有名字,年龄等信息。
数据类型:基本有以下几种类型:
原子类型:用C语言来说的话,就是属于那种 int,char 这些的数据类型。
结构类型:那就是C语言的结构体呗。
抽象数据类型:抽象数据阻止及相关操作。因为 C 没有抽象的概念,所以硬要说应该就是定义了一系列规则的集合,或者说拿 C++ 的泛型来理解也可以吧。
数据结构:是相互之间存在一种或多种特定关系的数据元素的集合,数据结构包括三个方面的内容:逻辑结构,存储结构和数据运算。一个算法的设计取决于逻辑结构,一个算法的实现取决于存储结构。【也很简单,比如深搜。对于图这种抽象结构,大概算法的设计是取决于它是图这样的抽象逻辑结构(从一个点开始,找到与之相连的点,然后分别递归这些点)。但是具体实现就要看你是怎么存图,比如图可以用邻接矩阵或者是链式前向 ...
高等数学复习(7)
高等数学复习(7)——零点问题和微分不等式
零点问题零点问题经常转换为求根或者两个曲线的交点问题。
定理1:零点定理,在连续函数的一个区间内,如果端点值异号,那么至少有一个根。
定理2:单调性,一个单调区间内,至多有一个根(也可能没有,但是有只能有一个)。
定理3:罗尔原话——$f^{(n)}(x)=0$ 有 k 个根,那么 $f(x)$ 最多有 k+n 个根(最多指的是最理想的情况,一个根都没有也是可能的,这个定理只用不证明)。
奇次的多项式至少有一个实数根,很简单,因为仅看最高项,它趋于正无穷和负无穷的时候,肯定是异号的,所以至少有一个实数根。
证明常用思路证明不等关系,通常需要研究一个函数的导数,如果直接求导难以解决,思考以下思路:
可以尝试作变量代换,代换的时候需要注意,把自变量的范围跟着变化一下。
对导数研究正负性,如果导数还是不能直接看出来,再次求导又特别麻烦,如果有分式,那么建议直接把分子或者分母推到一个恒正或恒负,对分子或分母研究导数,看正负性。
对于常数证明,通常对常数变量化,如果有多个常数,那就把其中一个当成常数,另一个当成变量去研究,或者有办 ...
Windows驱动开发(2)——hello world
今天写一个驱动的hello world。
打印一下基本的信息吧就是,创建一个空项目,写一个驱动入口和一个卸载例程。
这里给一下用到的工具,其中 VirtualKD-Redux 是github上下载的,用于关闭windows驱动签名验证的,这里建议直接再虚拟机里搞就好了。
code代码:
123456789101112131415#include<ntifs.h>#define kprintf(format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, format, ##__VA_ARGS__)void DriverUnload(PDRIVER_OBJECT pDriver) { kprintf(("Line %d:xia0ji233: unload success\n"),__LINE__);}NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING Registr ...