围观网络之二 —— TDI~

TDI 过滤~
一、与TDI过滤有关的东西。。收发数据那块先从略了。。

TCP怎么填充头部,怎么保证发送的成功和顺序正确,那都是协议的东西了。。详见《TCP-IP详解》(17章开始是TCP)。协议的东西有空再看看~

TDI 过滤没什么难度,WDK详尽到罗嗦的程度,教程也很多了,简单mark一下

上文看到Winsock库函数和afd.sys几乎是一一对应的,有时是一对多。但afd并不是将所有的请求都下发。

Afd是功能辅助模块,面向的对象是endpoint。TCP/UDP 是传输层,负责给两端的两个应用程序传输数据,面向的对象是一个传输控制块 TCB。

FsContext统一是TCP_CONTEXT结构,FsContext2 表示这个文件对象具体代表什么(地址、连接、或者一个控制)

到了tcp层,提供的服务有(其中有一些可过滤的地方):

绑定

afd!AfdBind -> tcpip!TCPCreate 

当EA中是TdiTransportAddress 时,表示是打开一个本地的地址对象,调用TdiOpenAddress。
TdiOpenAddress将分配一个正确的本地地址和端口,并创建一个地址对象(AddrObj),存放于tcpContext->Handle.AddressHandle。
为FileObject->FsContext填充一个 _TCP_CONTEXT结构,FsContext2设置为TDI_TRANSPORT_ADDRESS_FILE(代表这是一个地址对象)
过滤这里可以得到绑定的本地ip地址和端口号(在irp完成之后)。

连接

afd!AfdCreateConnection -> tcpip!TCPCreate

EA名字是TdiConnectionContext,表示是打开一个连接对象,调用TdiOpenConnection,

将创建一个TCPConn结构并分配一个connectID存放于tcpContext->Handle.ConnectionContext,FsContext2设置为TDI_CONNECTION_FILE(代表这是一个连接对象)
在楚狂人的教程中,这里的过滤操作是自己建表将文件对象和ConnectionContext相关联,毕竟TCP_CONTEXT结构不公开。

TDI_ASSOCIATE_ADDRESS
TdiAssociateAddress将地址对象AO存到连接对象中。
在这里可以得到链接地址。

TDI_CONNECT
正式建立连接了。得到链接地址很容易。
TdiConnect
这里开始出现一个传输层的重要结构 传输控制块TCB 记录了一个传输的所有信息 地位相当于进程管理器中的EPROCESS 。这里调用了InsertTCB将TCB放入了全局链表TCBTable。
这里初始化这个结构并且填充各种信息,最终调用SendSYN,即握手的第一步。返回TDI_PENDING。
监听和接受连接

TDI_SET_EVENT_HANDLER 中的 TDI_EVENT_CONNECT

设置一个回调来接受连接,替换之 可得到连接本机的事件

接受数据
TDI_EVENT_RECEIVE
TDI_EVENT_RECEIVE_DATAGRAM
TDI_EVENT_RECEIVE_EXPEDITED
拦截三个事件回调,回调是从中断一层一层解析并递交上来的。

TDI_ RECEIVE
TdiReceive来缓冲数据

发送数据
TDI_SEND 
最终调用TdiSend 填充协议头部,调用LocalNetInfo.ipi_xmit发送数据了
还有UDP的TDI_SEND_DATAGRAM 和 TDI_RECEIVE_DATAGRAM

收发数据 可以做的工作 拒绝接受/过滤数据/统计流量 等等

360netmon 是一个很简单的TDI过滤驱动,实现的就是 实时统计了每个进程收发的数据流量,提供禁止某个进程收发数据的功能。不过里面有5、6个自定义结构,搞得我花了一点时间去猜都是什么。。。

附上IDB和 其DeviceIoCtrlInternal 的 还原代码(因为这个f5看起来不太方便~)IDB是5.5的,在localtype里定义了那些自定义结构~  IDB下载

二、连接的枚举
顺便说一下枚举系统内建立的连接,正常的就是用IPHELP API(netstat用的),
底层一点不过是用IOCTL_TCP_QUERY_INFORMATION_EX 曾经rootkits那本书中写过irp hook这里隐藏链接

XT也是发送了这个irp,至于更底层,其实没太大必要。定位TCBTable就比较麻烦,不过TCB这个结构。有了NT4的参考还是很好逆出来的。

XP下
#pragma pack(push, 1)
struct TCB
{
_BYTE f0[8];
_DWORD dword8;
_DWORD tcb_daddr;
_DWORD tcb_saddr;
_WORD tcb_dport;
_WORD tcb_sport;
_DWORD pid;
…….略去


NT4查连接属于哪个进程比较麻烦,TCB中好像不存储pid,但xp的版本就有这么一句:

TdiConnect:   
TCB->pid = PsGetCurrentProcessId();

PS:迅雷的智能限速竟然都NDSI小端口了,真和谐啊,暂时还看不了。。。
PPS:利用第三方带签名的驱动的bug挺和谐。。。一些非安全厂商的驱动相当不安全。。
基于TDITCP数据传输 1.上位机 上位机包括tcptcp.cpp 1.1 对外函数说明 HANDLE TdiTcpOpen(); TdiTcpOpen用于打开设备,成功返回有效的句柄,失败返回INVALID_HANDLE_VALUE. BOOL TdiTcpClose(HANDLE hDevice); TdiTcpClose用于关闭设备,成功返回TRUE,失败返回FALSE; hDevice为TdiTcpOpen返回的句柄 BOOL TdiTcpConnect(HANDLE hDevice,const PCHAR pIpAddres,USHORT uPort); TdiTcpConnect用于与服务器建链,pIpAddres为服务器IP地址,uPort为服务器端口地址。 hDevice为TdiTcpOpen返回的句柄 pIpAddres为IP地址,如”10.0.0.20” uPort为端口地址 BOOL TdiTcpSend(HANDLE hDevice,PVOID pBuff,ULONG nLen,PULONG pRtn); TdiTcpSend用于给服务器发送数据. hDevice为TdiTcpOpen返回的句柄 pBuff接向发送数据的指针 nLen发送数据长度 pRtn发送成功长度 BOOL TdiTcpRcv(HANDLE hDevice,PVOID pBuff,ULONG nLen,PULONG pRtn); TdiTcpRcv用于从服务器接收数据 hDevice为TdiTcpOpen返回的句柄 pBuff接收数据缓冲区 nLen接收数据缓冲区长度 pRtn实际接收数据长度指针 BOOL TdiTcpSetRcvTimeOut(HANDLE hDevice,ULONG ulSecond); TdiTcpSetRcvTimeOut用于设置接收数据超时时间,默认为3秒。 hDevice为TdiTcpOpen返回的句柄 ulSecond为超时时间 2.下位机 下位机包括D1603.h D1603.cpp和Tdifun.cpp TdiFun.h 2.1 关键数据结构 驱动与应用连接服务器结构体 typedef struct _CONNECT_STRUCT { ULONG ip; //服务器IP地址 USHORT port; //服务器端口 }CONNECT_STRUCT,*PCONNECT_STRUCT; //设备展结构体 typedef struct _DEVICE_EXTENSION { PDEVICE_OBJECT pDeviceObject; //设备指针 UNICODE_STRING wstrDeviceName ; //设备名 UNICODE_STRING wstrSymbolicLinkName;//设备链接名 }DEVICE_EXTENSION,*PDEVICE_EXTENSION; 读数据链接 typedef struct _RCV_IPR_LIST { PIRP pIrp; //指向读IPR LIST_ENTRY ListEntry; //链表 }RCV_IPR_LIST,*PRCV_IPR_LIST; 当前链接上下文 typedef struct _SOCKET_CONTEXT { HANDLE TransportAddressHandle; //传输地址句柄 FILE_OBJECT* pTrasnportAddressFile;//传输地址指针 HANDLE ConnectionHandle;//连接地址句柄 FILE_OBJECT* pConnectionFile;//连接地址指针 LIST_ENTRY RcvHead; //接收IRP链表头 KEVENT event; //接收数据同步事件 ULONG uTimeOut; // 接收数据超时 }SOCKET_CONTEXT,*PSOCKET_CONTEXT; 2.2 外函数说明 驱动装载主入口函数 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath); 驱动卸载函数 VOID D1603Unload(PDRIVER_OBJECT DriverObject); 默认IRP回调函数 NTSTATUS D1603Dispatch(PDEVICE_OBJECT DeviceObject,PIRP Irp); TdiTcpOpen对应的IPR函数 NTSTATUS D1603Create(PDEVICE_OBJECT
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值