您的位置:首页 > 其它

<读书笔记> windows内核安全 --- 串口过滤(1)

2014-03-02 14:00 585 查看
一直从事windows驱动相关的工作,不过没有怎么梳理过整体的知识系统,最近又把这本寒江独钓拿出来看了一遍,将从中得到的相关知识放在这篇文章里,仅供参考。

串口是啥?串口就是串口呗,嘿嘿。随着PC机的更新换代,很多的电脑已经没有串口的身影,尤其是笔记本电脑,很少看见有带串口的电脑,搭建调试环境的时候总是因为没有串口让人很郁闷。

串口没有归没有,但是用处还是挺大的,很多开发板都是通过串口将调试信息反馈到PC,给开发人员多了一种调试方法,还有驱动的内核调试,双机调试在win7之前,最容易实现的方法就是通过串口来实现,USB口调试需要调试电缆,价格比较贵;1394接口在现代电脑上基本看不见。不过最近发现在WIN8平台之后加入的网络双机调试很给力,而且很方便,额,貌似写偏了。还是继续梳理串口过滤这篇的学习心得。

这个梳理过程就直接从代码切入,顺便理解一下相关的概念。

过滤驱动就是在windows内核中加入新的层,从而加入新的功能,计算机行业不是有一句话叫“加入一个中间件,没有解决不了的问题”,过滤驱动就是这样一个中间件。

好了,驱动从DriverEntry开始,咱开始就写写这个filter,当然这个代码看着肯定很眼熟,没错,这就是网上down下来的本书源码,只不过一点点小小的改动。

DriverEntry(
__in PDRIVER_OBJECT  DriverObject,
__in PUNICODE_STRING RegistryPath
)
{
ULONG    ulIndex;

//设置分发函数
for(ulIndex=0; ulIndex<IRP_MJ_MAXIMUM_FUNCTION; ulIndex++)
{
DriverObject->MajorFunction[ulIndex] = ComfltDispatch;
}

//卸载函数分发
DriverObject->DriverUnload = ComfltUnload;

//绑定串口
ComfltAttachComs(DriverObject);

return STATUS_SUCCESS;
}


这个咱真的没得说的,设置一下分发函数、卸载函数,绑定串口,系统就根据我们设置的相应函数,去执行对应的位置代码,以后的学习笔记就不再写DriverEntry中的内容了,都大同小异。

下一步,看一下这个绑定串口是怎么处理的,既然是绑定串口,自然就需要知道该绑定到哪个设备上,所以先要获取这样的设备,我们的目标是串口,串口在系统中是有固定名字的,例如COM1就对应“\\Device\\Serial0”,COM2就对应“\\Device\\Serial1”,依次类推。windows内核提供一个函数可以通过设备名称获得该名称对应的栈顶设备对象。前提是访问的权限是在特定范围之内,对于串口来说,可以直接使用FILE_ALL_ACCESS。

NTSTATUS
IoGetDeviceObjectPointer(
IN PUNICODE_STRING  ObjectName,
IN ACCESS_MASK  DesiredAccess,
OUT PFILE_OBJECT  *FileObject,
OUT PDEVICE_OBJECT  *DeviceObject
);
所以对于这个函数我们需要知道的是ObjectName,DesiredAccess直接设置成FILE_ALL_ACCESS,而这里面DeviceObject就是我们需要的绑定对象。这里面会获取一个文件对象,这个对于串口是没有用处的,需要调用ObDereferenceObject将其解除引用,否则,嘿嘿,将会有不好的事情发生了。

通过上面的分析,咱已经得到了待绑定的对象了,接下来就需要生成一个绑定对象(Filter Object),使用函数IoCreateDevice去创建这个对象,这个对象不是一个随随便便的对象,如果太随便,待绑定的那位肯定会有意见了。所以这边要创建一个对应的FILE_DEVICE_SERIAL_PORT设备,这个类型我们可以直接从待绑定对象获取。所以我们得到这样的一个函数实现。

status = IoCreateDevice(DriverObject,
0,
NULL,
DeviceObject->DeviceType,
0,
FALSE,
FltDevice);

创建完这个与过滤设备之后,需要将相关的标志位设置一下,如POWERPAGE属性,数据传输方式等。

完成了上述的这些操作之后,我们要开始绑了,所谓的绑就是调用一个函数将过滤设备与被绑定设备连接在一起,这样会生成一个新的设备。

// Create filter device
status = IoCreateDevice(DriverObject, 0, NULL, DeviceObject->DeviceType, 0, FALSE, FltDevice);

if ( !NT_SUCCESS(STATUS_SUCCESS) )
{
KdPrint(("Create filter deivce error, status =%d ", status ));
return status;
}

// Copy Flags
if(DeviceObject->Flags & DO_BUFFERED_IO)
(*FltDevice)->Flags |= DO_BUFFERED_IO;
if(DeviceObject->Flags & DO_DIRECT_IO)
(*FltDevice)->Flags |= DO_DIRECT_IO;
if(DeviceObject->Characteristics & FILE_DEVICE_SECURE_OPEN)
(*FltDevice)->Characteristics |= FILE_DEVICE_SECURE_OPEN;
(*FltDevice)->Flags |= DO_POWER_PAGABLE;

// Attach the filter device to Com device
NewDevice = IoAttachDeviceToDeviceStack(*FltDevice, DeviceObject);
if (NewDevice == NULL)
{
IoDeleteDevice(*FltDevice);
*FltDevice = NULL;
status = STATUS_UNSUCCESSFUL;
return status;
}
*AttachedDevice = NewDevice;

// Start this filter device object
(*FltDevice)->Flags = (*FltDevice)->Flags & ~DO_DEVICE_INITIALIZING;
Ok了,这样整个的过滤设备绑定过程就结束了。我们创建了过滤设备不是用来玩的,既然是要过滤,那我们就可以通过这样一个设备区“截取”串口的一些信息,整个截取过程就需要在Dispatch中去处理。

Dispatch函数中需要处理的就是一个叫IRP的东西,这玩意在驱动层就想一个包一样,上层有了就一步一步的往下层送,知道送给系统内核处理完,再返回,过滤驱动截取的就是这样的IRP,从IRP中可以看见相关的信息,如上面传送的是啥数据,对应的CTL_CODE是啥,等等。。。。。

这个代码我就不贴出来了,在这篇串口过滤里面需要知道的就是怎么将过滤设备与对应的设备进行绑定,了解了这个的流程,那串口方面的过滤就没啥问题了。

这篇文章介绍的方法是书中使用的方法,下一篇串口过滤(2),依然是串口过滤驱动,但是使用的方法是WDK的sample中介绍的方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: