使用NDIS驱动监測以太网络活动
本论文不是帮助程序猿开发网络驱动而是帮助他使用这种驱动。
此外。特定的应用与特定种类的驱动相相应。随着Internet的到来,编写网络驱动成为驱动开发的核心。为帮助开发网络设备驱动。微软为Windows
 NT操作系统开发了网络设备接口规范(NDIS)库。
比如。以太网中称为以太网接口卡,令牌环网中称为令牌环网接口卡,等等。
对全部外部功能来说。NIC驱动都依赖于NDIS。这些功能包含与协议驱动的通信。注冊,截获NIC硬件中断。与下层的NIC的通信。
全然NIC驱动必须保持接收数据的绑定信息。
对于上层传输驱动程序来书,中间驱动看起来像是微port驱动。对微port驱动来说,看起来像是协议驱动。使用中间协议驱动的主要是为了传输媒质,存在于对于传输驱动未知和微port管理之间的新的媒质类型。
它也在它的底层提供协议接口,来接收下层驱动发送来的包。
驱动中其他的函数是通过DriverEntry函数声明的。应用程序调用函数如CreateFile。ReadFile等。会由NT I/O管理器生成对应IRP(输入/输出请求包)。
每一个I/O操作由工作顺序来描写叙述,工作顺序告诉驱动做什么和通过I/O子系统追踪请求的过程。
这些工作顺序通过一个称为I/O请求包(IRP)的数据结构的形式给出。
这个IRP为完毕特定操作按顺序调用驱动中的进入点。
NT 设备开发工具(DDK)。
应用能够利用PACKET.SYS将网卡设置为混杂模式,以便于捕获网络中传输的全部数据包。
这个驱动能够将网卡设置为不论什么期望的模式,而且同意应用程序通过网络发送和接收数据包。除驱动程序的sys文件之外。还提供了一个DLL(PACKET32.DLL),通过此DLL应用程序能够和驱动程序通信。
- typedef struct _ADAPTER
 - {
 - HANDLE hFile; // 保存由CreateFile方法返回的句柄
 - TCHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; // 保存驱动的符号链接名
 - } ADAPTER, *LPADAPTER;
 
- typedef struct _PACKET
 - {
 - HANDLE hEvent; // 保存和适配器对象对应的事件句柄
 - OVERLAPPED OverLapped;// 包括异步输入输出信息的OVERLAPPED结构
 - PVOID Buffer; // 包括发送和接收数据的缓冲区
 - UINT Length; // 缓冲区长度
 - } PACKET, *LPPACKET;
 
- typedef struct _CONTROL_BLOCK
 - {
 - LPADAPTER hFile; // 指向适配器对象的指针
 - HANDLE hEvent; // 保存事件句柄
 - // Name of the driver as registered in the registry.
 - TCHAR AdapterName[64]; // 注冊表中注冊的驱动名
 - HANDLE hMem; // 保存接收数据包的缓冲区
 - LPBYTE lpMem;
 - HGLOBAL hMem2; // 保存发送数据包的缓冲区
 - LPBYTE lpMem2;
 - ULONG PacketLength; // 包长度
 - ULONG LastReadSize; // 最后读取的包大小
 - UINT BufferSize; // 缓冲区长度
 - } CONTROL_BLOCK, *PCONTROL_BLOCK;
 
应用程序開始
- CONTROL_BLOCK cbAdapter;
 - ULONG NameLength=64;
 - // 得到驱动在注冊表中注冊的名字
 - PacketGetAdapterNames(CbAdapter.AdapterName,&NameLength);
 - CbAdapter.BufferSize=1514; // 保留1514字节,最大帧长度
 - // 分配并锁定内存缓冲区用于发送和接收数据包
 - CbAdapter.hMem=GlobalAlloc(GPTR, 1514);
 - CbAdapter.lpMem=(LPBYTE)GlobalLock(CbAdapter.hMem);
 - CbAdapter.hMem2=GlobalAlloc(GPTR,1514);
 - CbAdapter.lpMem2=(LPBYTE)GlobalLock(CbAdapter.hMem2);
 - // 打开优先的适配器用于接收数据,
 - // 函数依次调用CreateFile方法。调用驱动程序中对应的进入点。
为随后的读写操作打开适配器
 - CbAdapter.hFile=(ADAPTER*)PacketOpenAdapter(CbAdapter.AdapterName);
 - // 打开适配器域
 - if (CbAdapter.hFile = = NULL)
 - {
 - AfxMessageBox("Open Adapter failed");
 - }
 - // 此Packet对象用于从网络上接收全部数据的包
 - PVOID Packet;
 - // 设置过滤条件为混杂(非选择)模式
 - // 此函数依次呼叫DeviceIoControl方法。用来设置网卡工作于期望的模式。
 - Filter = NDIS_PACKET_TYPE_PROMISCUOUS;
 - // 设置网卡为混杂模式
 - PacketSetFilter(CbAdapter.hFile, Filter);
 - // 分配缓冲区用于接收数据包
 - Packet=PacketAllocatePacket(CbAdapter.hFile);
 - // 初始化接收数据包缓冲区
 - if(Packet != NULL)
 - {
 - PacketInitPacket((PACKET *)Packet,(char *)pdData[nCurrentWriteLocation].pData,1514);
 - // 从驱动中读取数据包
 - // 此函数依次调用ReadFile方法来读取通过EIC从网络上收到的数据
 - PacketReceivePacket(CbAdapter.hFile,(PACKET *)Packet,TRUE,&pdData[nCurrentWriteLocation].nPacketLength );
 
- ULONG
 - PacketGetAdapterNames(
 - PTSTR pStr,
 - PULONG BufferSize
 - )
 - {
 - HKEY SystemKey;
 - HKEY ControlSetKey;
 - HKEY ServicesKey;
 - HKEY NdisPerfKey;
 - HKEY LinkageKey;
 - LONG Status;
 - DWORD RegType;
 - // Open the Key HKEY_LOCAL_MACHINE,打开HKEY_LOCAL_MACHINE键值
 - Status=RegOpenKeyEx(
 - HKEY_LOCAL_MACHINE,
 - TEXT("SYSTEM"),
 - 0,
 - KEY_READ,
 - &SystemKey
 - );
 - if (Status == ERROR_SUCCESS) {
 - // Open the key currentcontrolset 打开currentcontrolset键值
 - Status=RegOpenKeyEx(
 - SystemKey,
 - TEXT("CurrentControlSet"),
 - 0,
 - KEY_READ,
 - &ControlSetKey
 - );
 - if (Status == ERROR_SUCCESS) {
 - // Open the key Services打开Services键值
 - Status=RegOpenKeyEx(
 - ControlSetKey,
 - TEXT("Services"),
 - 0,
 - KEY_READ,
 - &ServicesKey
 - );
 - if (Status == ERROR_SUCCESS) {
 - // Open the key Packet. 打开Packet键值
 - Status=RegOpenKeyEx(
 - ServicesKey,
 - TEXT("Packet"),
 - 0,
 - KEY_READ,
 - &NdisPerfKey
 - );
 - if (Status == ERROR_SUCCESS) {
 - // Open the key Linkage.打开Linkage键值
 - Status=RegOpenKeyEx(
 - NdisPerfKey,
 - TEXT("Linkage"),
 - 0,
 - KEY_READ,
 - &LinkageKey
 - );
 - if (Status == ERROR_SUCCESS) {
 - // Open the key Export.
 - Status=RegQueryValueEx(
 - LinkageKey,
 - TEXT("Export"),
 - NULL,
 - &RegType,
 - (LPBYTE)pStr,
 - BufferSize
 - );
 - // Close all the keys that have been opened so far.关闭已打开的全部键值
 - RegCloseKey(LinkageKey);
 - }
 - RegCloseKey(NdisPerfKey);
 - }
 - RegCloseKey(ServicesKey);
 - }
 - RegCloseKey(ControlSetKey);
 - }
 - RegCloseKey(SystemKey);
 - }
 - return Status;
 - }
 
- PVOID PacketOpenAdapter(LPTSTR AdapterName)
 - {
 - LPADAPTER lpAdapter;
 - BOOLEAN Result;
 - ODS("Packet32: PacketOpenAdapter/n");
 - // 为适配器对象分配全局内存
 - lpAdapter=(LPADAPTER)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(ADAPTER));
 - if (lpAdapter==NULL)
 - {
 - ODS("Packet32: PacketOpenAdapter GlobalAlloc Failed/n");
 - return NULL;
 - }
 - // 将名字复制到符号链接名
 - wsprintf(lpAdapter->SymbolicLink, TEXT("////.//%s%s"), DOSNAMEPREFIX, &AdapterName[8] );
 - // Defines an MS-DOS name for the device.
 - Result=DefineDosDevice(DDD_RAW_TARGET_PATH,&lpAdapter->SymbolicLink[4], AdapterName);
 - if (Result)
 - {
 - // Creates and returns a file handle for the specified device. 为特定设备创建并返回文件句柄
 - lpAdapter->hFile=CreateFile(lpAdapter->SymbolicLink,GENERIC_WRITE | GENERIC_READ,0,NULL,CREATE_ALWAYS,FILE_FLAG_OVERLAPPED,0);
 - if (lpAdapter->hFile != INVALID_HANDLE_VALUE)
 - {
 - return lpAdapter;
 - }
 - }
 - ODS("Packet32: PacketOpenAdapter Could not open adapter /n");
 - GlobalFreePtr(lpAdapter );
 - return NULL;
 - }
 
- PVOID PacketAllocatePacket(LPADAPTER AdapterObject)
 - {
 - LPPACKET lpPacket;
 - // 为Packet对象分配内存
 - lpPacket=(LPPACKET)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(PACKET));
 - if (lpPacket==NULL)
 - {
 - ODS("Packet32: PacketAllocateSendPacket: GlobalAlloc Failed/n");
 - return NULL;
 - }
 - // 操作结束时建立事件对象
 - lpPacket->OverLapped.hEvent=CreateEvent( NULL,FALSE,FALSE, NULL);
 - if (lpPacket->OverLapped.hEvent==NULL)
 - {
 - ODS("Packet32: PacketAllocateSendPacket: CreateEvent Failed/n");
 - GlobalFreePtr(lpPacket);
 - return NULL;
 - }
 - return lpPacket;
 - }
 
PacketInitPacket函数设置packet对象缓冲区
- VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length)
 - {
 - // 设置packet对象缓冲区到缓冲区
 - lpPacket->Buffer=Buffer;
 - // 设置packet对象缓冲区长度到缓冲区长度
 - lpPacket->Length=Length;
 - }
 
- BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync,PULONG BytesReceived)
 - {
 - BOOLEAN Result;
 - // 设置偏移量为0
 - lpPacket->OverLapped.Offset=0;
 - lpPacket->OverLapped.OffsetHigh=0;
 - if (!ResetEvent(lpPacket->OverLapped.hEvent))
 - {
 - return FALSE;
 - }
 - // 调用ReadFile来读取数据包
 - Result=ReadFile(AdapterObject->hFile,lpPacket->Buffer, lpPacket->Length, BytesReceived, &lpPacket->OverLapped);
 - if (Sync)
 - {
 - // They want to wait
 - Result=GetOverlappedResult(AdapterObject->hFile,&lpPacket->OverLapped,BytesReceived, TRUE );
 - }
 - else
 - {
 - // They don't want to wait, they will call PacketWaitPacket to get
 - // The real result
 - //不等待,调用PacketWaitPacket得到真实值
 - Result = TRUE;
 - }
 - return Result;
 - }
 
在数据穿越每一层协议的同一时候,协议栈上对应协议为了栈中下一层协议,将数据封装起来。
因此。封装就是一个将数据存储成协议栈中更低层协议要求的格式的过程。
| 
 Protocol 
 | 
 Value(Decimal) 
 | 
| 
 TCP 
 | 
 6 
 | 
| 
 UDP 
 | 
 17 
 | 
| 
 ICMP 
 | 
 1 
 | 
| 
 IGMP 
 | 
 2 
 | 
因此,依靠分析数据包就能够得到URL。URL出项在数据包中的通用格式为:
这必须考虑在内。驱动中使用的是NDIS版本号是3.0。
驱动在Windows NT下工作良好,但不能在Windows95下工作。由于Windows95只支持的是NDIS是2.1版本号和NDIS 3.1版本号。
并且,CE不支持内建的DMA和分配连续的内存块。
更进一步,为CE编写NDIS驱动。程序猿必须考虑到电源管理的问题。
这就是说。必须提供附加的电源管理代码。
使用NDIS驱动监測以太网络活动的更多相关文章
- Windows网络驱动、NDIS驱动(微端口驱动、中间层驱动、协议驱动)、TDI驱动(网络传输层过滤)、WFP(Windows Filtering Platform)
		
catalog . 引言 . Windows 2000网络结构和OSI模型 . NDIS驱动 . NDIS微端口驱动编程实例 . NDIS中间层驱动编程实例 . NDIS协议层驱动编程实例 . TDI ...
 - 网络状态监測之 Reachability的使用
		
先下载 Reachability开源库地址: (一)git hub: https://github.com/tonymillion/Reachability (二)我自己改动的:http://down ...
 - Android实践--监測网络状态
		
Android 监測网络状态 我们在使用Android手机时候,一些APP须要网络环境才干执行,所以手机须要可用的网络,无论是2G.3G或者WIFI.甚至有一些比較耗流量的APP仅仅能在WI ...
 - 广播小案例-监听系统网络状态 --Android开发
		
本例通过广播实现简单的监听系统网络状态改变的小案例. 1.案例效果演示 当手机连网后,系统提示“已连接网络”, 当手机断网后,系统提示“当前网络不可用”. 2.案例实现 在主活动中动态注册广播,然后写 ...
 - Atitit.软件仪表盘(7)--温度监測子系统--电脑重要部件温度与监控and警报
		
Atitit.软件仪表盘(7)--温度监測子系统--电脑重要部件温度与监控and警报 Cpu温度.风扇转速 主板温度 显卡温度 硬盘温度 电池温度 鲁大师 硬盘温度 Cpu温度 core temp ...
 - 使用HTML5监測站点性能
		
在这个信息爆炸的互联网时代,越来越多的人缺少了等待的耐心.站点性能对于一个站点来说越来越重要.下面为监控到的站点打开时间对跳出率的影响: 当站点打开时间在0-1秒时,跳出率为12% 当站点打开时间在1 ...
 - Android监听WIFI网络的变化并且获得当前信号强度
		
MainActivity如下: package cc.testwifi; import android.os.Bundle; import android.app.Activity; /** * De ...
 - Atitit.软件仪表盘(2)--vm子系统--资源占用监測
		
Atitit.软件仪表盘(2)--vm子系统--资源占用监測 1. Jvisualvm.exe 2. jprofile 3. Heap //permgen monitor 作者::老哇的爪子At ...
 - 用BroadcastReceiver监听手机网络状态变化
		
android--解决方案--用BroadcastReceiver监听手机网络状态变化 标签: android网络状态监听方案 2015-01-20 15:23 1294人阅读 评论(3) 收藏 举报 ...
 
随机推荐
- CF811C Vladik and Memorable Trip
			
思路: 令dp[i]表示前i个的最大舒适度.则如果区间[j, i](1 < j <= i)满足条件,有如下转移:dp[i] = max(dp[i], dp[j - 1] + cur).其中 ...
 - LockDemo 锁对象
			
class Resource { private boolean flag = false; private String name; private int count; //资源锁 Lock lo ...
 - 安卓app测试之启动时间和电量监控
			
一.启动时间监控 通过adb命令获取 adb shell am start -W /<packageName> /<activityName> 案例: adb shell am ...
 - 梦想CAD控件安卓文字样式
			
增加文字样式 用户可以增加文字样式到数据库,并设置其字体等属性,具体实现代码如下: // 增加文字样式 //getCurrentDatabase()返回当前数据库对象 //getTextstyle() ...
 - SpringBoot开源项目学习总结
			
一.实现日期格式数据类型的转换 首先,定义DateConverter实现Converter<String, Date>接口: package com.stevlu.common; impo ...
 - datetimebox赋值或取值
			
datetimebox赋值或取值 $('#j_dateStart').datebox('setValue', ""); //赋予空值 $("#j_dateStart&qu ...
 - /etc/updatedb.conf配置文件
			
[root@localhost ~]# vi /etc/updatedb.conf PRUNE_BIND_MOUNTS = "yes" PRUNEFS = "9p afs ...
 - 在MONO Design中使用Flex3D
			
在项目开发组的努力下,HTML5 3D 的开发包变得越来越优秀,越来越健壮:基于HTML5 3D技术的MONO Design建模平台功能也变得越来越强大和完善,这个方便了很多使用我们HTML5 3D的 ...
 - 打造完美的ImageLoader——LruCache+DiskLruCache
			
做android应用少不了要和网络打交道,在我刚开始学android的时候总是处理不好网络图片的加载,尤其是图片乱跳的问题,后来发现了各种缓存图片的方法:本地缓存.软引用.LruCache.... 我 ...
 - Gym - 101670C Chessboard Dancing(CTU Open Contest 2017 找规律)
			
题目:链接 思路: 多画出几个情况就可以找出规律来了 Knight (当大于2的时候只要两种颜色相间出现就可以了) King(当大于等于3的时候,总可以用四种形式来补色,具体如下) Bishop(斜 ...