首页
社区
课程
招聘
[原创]刚开始学习windows驱动,分享自己做的一个小东西的理解
发表于: 2015-4-18 00:36 17101

[原创]刚开始学习windows驱动,分享自己做的一个小东西的理解

2015-4-18 00:36
17101
标题:初试 windows 驱动编写之 --- TDI层实现特定TCP/UDP端口的数据加密

前言:此文章中相应叙述,很多是根据自己的理解而写出,如有不准确或者错误之处,希望各位前辈们不吝指出。

一 、windows 网络体系结构及 TDI 简介 :

  根据前辈们对MSDN的研究,找到一张相对完整的windows网络体系结构图(出自http://bbs.pediy.com/showthread.php?t=101794):


从图中可以看出,windows的网络结构大致分为五层:
  1. 网络应用层 , 提供供用户态程序调用的网络API(包括winsock , rpc 等 )。
  2. TDI 客户端层,内核模式的设备驱动程序,用于将上层的API请求转换成IRP,并发送给下层。
  3.TDI Transport Provider ,TDI传送者,这部分包含协议驱动程序,即,某个协议(TCP / UDP / IP 等)的具体实现。为上层 TDI Client 提供了5个设备对象,从而使用这些协议 。
  4. NDIS (Network Driver Interface Specification ),向上提供接口,供TDI 传输者和网卡驱动调用 。
  5. HAL , 硬件抽象层 。

  其中,TDI客户端以及TDI传送者之间,通过TDI接口,将上层的请求封装成IRP之后进行通信。

二、TDI层数据加密原理解析 :
TDI层加密,即将一个驱动程序挂接到TDI传输驱动程序Tcpip.sys所创建的三个设备对象之上,截获TDI客户和传输驱动程序之间的IRP通信。解析获取主功能码和次功能码,在对应的Dispatch例程中,可获取通信双方的IP地址,端口号,协议等五元组信息,对这些信息进行验证及筛选,将期望中的数据加密完成后,再将此IRP传递给所挂接的设备 。

  具体做法是,在IRP从TDI客户端传送到TDI传送者的过程中,通过HOOK技术,改变程序流程,使IRP先经过HOOK程序,经过处理后,再继续向下传送。TDI HOOK前后程序执行及IRP流动过程如下图(图片出自《基于TDI-HOOK和NDIS-HOOK的主机防火墙研究与实现 ----徐胜 》):


  那么,接下来的重点就在于,如何编写并加载自定义的TDI HOOK 驱动,并截取IRP ,从IRP中解析数据,解析数据并重新发送至TDI传输者(特定的协议设备对象)。

三、Windows NT 系列内核程序设计、编译、加载及运行:

  在《寒江独钓---windows内核安全编程》一书中,简单地将windows驱动程序模型分为两种 : 将一切能够在windows 2000到vista 上运行的,未调用WDF相关的内核API函数的驱动都称为传统型驱动(包括NT式和WDM),如果调用了WDF(Windows Driver Framework)相关的内核API则称为WDF驱动。
  而本文中所涉及到的TDI驱动,属于传统型驱动中的NT式驱动 。
  
  如果应用程序开发时需要使用SDK一样,内核程序开发则使用WDK(Windows Driver Kit),各个版本的wdk都可在msdn上下载得到。
  安装过程及环境变量等配置在此不再赘述。
  与win32程序的winmain()以及console程序的 main()函数类似,驱动程序为入口为DriverEntry(),NT驱动的hello world版本如下 :
#include <ntddk.h>
VOID DriverUnload(PDRIVER_OBJECT driver)
{
  DbgPrint(“driver unloading...”) ;
}
NTSTATUS DrivereEntry( PDRIVER_OBJECT  driver , PUNICODE_STRING reg_path )
{
  DbgPrint(“hello world”) ;  

  //卸载函数
  driver->DriverUnload = DriverUnload ;
  return STATUS_SUCCESS ; 
}


驱动程序的编译 :
  wdk提供用于编译驱动源码的build工具。然而除程序员编写的源程序外,编译一个驱动工程还需要两个额外的文件,即makefile与SOURCES文件,其中,makefile对于所有的工程都是通用的,而SOURCES文件需要手动指定要编译的文件列表以及生成的目标文件。例如,以下是一个典型的SOURCES文件内容 :
TARGETNAME=hello
TARGETTYPE=DRIVER
SOURCES=hello.c
  编写完这些文件后,便可进入命令行,利用wdk的build工具对其进行编译。注:编译过程中,注意目标机选项应与当前平台相符合。

  驱动程序的运行环境、装载及调试信息打印查看:
  为避免给正在使用的操作系统造成不必要的伤害,驱动程序编写及测试时通常在虚拟机中运行。Vmware或VirtualBox搭载官方发布的windows镜像一般为首选。
  驱动的装载可以使用DriverInstaller类似的小软件进行。通常此类软件的界面形式以及提供的简单功能如下图 :


  调试信息的打印可通过debugview查看,此软件在msdn上也提供下载。(通常print大法用以调试可以解决大部分问题)

四、TDI HOOK 驱动编写
  核心函数解释及编写思路 :
  1.头文件引用 :
  #include <ntddk.h>
  #include <tdikrnl.h>

  2.入口函数 DriverEntry  
  NTSTATUS DriverEntry( …param list... ),此函数需要做以下事情
  生成设备,并绑定已知名字的设备。(TCP设备\\Device\\Tcp,UDP设备\\Device\\Udp等)
  设备生成以后,需要设置处理windows发送给这些设备的请求的dispatch函数,为简单处理,统一设置为DeviceDispatch函数。具体代码如下:
  for ( I = 0 ; I < IRP_MJ_MAXIMUM_FUNCTION ; I++ )
    driver->MajorFunction[I] = DeviceDispatch ; 
  
  3.DeviceDispach函数:
  经过入口函数指定dispatch函数后,所有的IRP请求包都会在此函数中进行处理,因此,此函数需要判断IRP的类型,并决定是否进行处理,如何进行处理,以及处理后将数据发送给原设备等问题。
  IRP的主功能号有如下几种 : IRP_MJ_CREATE , IRP_MJ_DEVICE_CONTROL , IRP_MJ_INTERNAL_DEVICE_CONTROL , IRP_MJ_CLOSE , IRP_MJ_CLEANUP 。
  其中,主功能号为IRP_MJ_CREATE的IRP的IRP中,可以获取发送此irp的pid以及EA,其中,通过一些特定的技巧设置回调函数,可以从EA中获取目的地址的ip和port,这两者可以作为识别某个服务程序的标识,也可作为是否加密发送到此ip以及port的数据的凭证。
  IRP_MJ_DEVICE_CONTROL与IRP_MJ_INTERNAL_DEVICE_CONTROL两者的功能基本相似。区别在于,INTERNEL_DEVICE_CONTROL处理的是从本地发送出去的数据。主功能号为这两者的IRP,次功能号可以为以下几种 :
a.TDI_ASSOCIATE_ADDRESS
b.TDI_DISASSOCIATE_ADDRESS
c.TDI_CONNECT
d.TDI_SEND
e.TDI_RECEIVE
f.TDI_SEND_DATAGRAM
g.TDI_RECEIVE_DATAGRAM

  从次功能号的命名规则中可以看出,后四种分别用于TCP协议、UDP协议的发送与接收数据。因此,当识别到这些次功能号时,可以对其操作的数据进行相应的加密或解密处理,其中,获取发送或接收的数据的实现如下(获取数据后对其加密的部分省略) :
unsigned char * pSendData = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority);

  在将IRP进行处理后(无论是经过数据段加密或未经过数据段加密的IRP),最后都需要将其发送给原设备,以保证正常运作,此功能的代码段如下所示 :
old_dev_obj = get_original_dev_obj()
IoCallLocalDriver(old_dev_obj , irp )
  
至此, TDI HOOK驱动的工作便完成了。

五、当前代码成果、难点问题,及后续发展空间:
  为避免重复造轮子的活动,项目的代码主要参考自现有代码《寒江独钓 windows 内核安全编程》中的两个案例 tdi_fw及 tdifw_smpl 。
  具体做法为,将tdi_fw文件编译成一个通用的lib文件(关于tdi过滤驱动的编写基本一样,编成库文件可以便于不同需求时调用此通用的lib,减小代码重复编写的工作),从tdifw_smpl项目中调用此lib。
  而在本应用中,为了使数据加密正常进行,我们需要在tdi_send , tdi_receive , tdi_datagram_send , tdi_datagram_receive四个函数中作相应操作,即增加判定逻辑以及加密或解密算法的编写。
  由于四个函数基本写法类似,以下就以tdi_send函数中增加的代码为例说明此工作过程:



        难点问题及后续发展空间 :
  1.由于此项目是基于特定端口,从而识别服务程序,并据此决定是否进行数据加密,因此,不能够被广泛应用于普遍应用层的应用程序之间的通信。
  对此可提出如下需求:通过指定某一特定的应用程序(通过程序名或者进程id)后,即可对此应用下的所有对等层通信进行加密收发。进一步将之配备上相应GUI,可作为产品发布。
  2.如果属于C/S架构当中的两个client之间进行通信,那么,在TCP/UDP数据包的数据帧中,应当对另外一个对象进行相应标识,若将此数据包加密后发送至server端,将导致server端无法理解,从而无法找到另外的client,通信无法正常进行.
  3.通信双方的加密协商,以及双方通信时询问对方是否处理加密环境的协商问题:为加强加密强度和灵活性,应允许通信双方进行加密方式的协商以及会话密钥的商定。并且,由于加解密为双向过程,因此,在某一端加密发送或接收之前,需要确定通信的另一端也同时属于此环境中,因此,应该提供查询机制,并根据查询结构返回反馈信息并进一步决定是否进行加密发送或接收。
  4.多平台的兼容性问题,如32位,64位操作系统,以及windows不同版本的操作系统的兼容问题,由于最新版本的windows如win10,win8.1等,对内核层的驱动保护状态加深,因此tdi hook的实现变得不再适用,因此需要考虑其替代方案。
  5.如果应用程序作了驱动级保护、动态端口或者其它的保护措施,那么,此项目同样不能正常运行,因此,如果需要,应该运作在更底层作相关操作。

六、 替代方案
  TDI 的相应机制在windows vista之后,逐渐被wfp(windows filter platform )所替代,并且后者是当前网络架构相关驱动的主流趋势,因此,对于本文中所描述的相关hook操作及信息获取,均可在后者中,以一种更优雅的方式编写出来。
  WFP及callout驱动相关的描述可参考MSDN,以下列出几篇WFP应用的具体实例以及前辈们分享出的文章,供以后有精力时可继续向下深入学习:
http://blog.csdn.net/z18_28_19/article/details/12586523
http://blog.csdn.net/z18_28_19/article/details/12716273
http://bbs.pediy.com/showthread.php?t=173871
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366510(v=vs.85).aspx

[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 3
支持
分享
最新回复 (9)
雪    币: 2664
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
2
支持一下,加油...
2015-4-18 01:06
0
雪    币: 160
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
顶楼主!继续努力!!!!
2015-4-18 08:33
0
雪    币: 49
活跃值: (43)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
感谢支持 ~
2015-4-18 09:45
0
雪    币: 49
活跃值: (43)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
2015-4-18 09:47
0
雪    币: 8188
活跃值: (2772)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
6
strlen。。。。。。。。。这种代码
2015-4-18 11:13
0
雪    币: 199
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
顶楼主!继续努力!!!!
2015-4-18 13:23
0
雪    币: 106
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
浅尝辄止
2015-4-27 12:05
0
雪    币: 27
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
还有个严重的问题要考虑吧,按数据流加密还是按数据块加密,按流的话效率怎么办?按块的话,解密时候怎么保证数据块完整性?
2015-4-27 13:19
0
雪    币: 49
活跃值: (43)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
不好意思,见笑了
2015-4-27 21:56
0
游客
登录 | 注册 方可回帖
返回
//