使用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) 收藏 举报 ...
随机推荐
- 程序员必知的LinuxShell命令
程序员必知的LinuxShell命令 grep (Globle Regular Expression Print全局正则表达式) 命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的 ...
- Android 五种方式实现Android底部导航栏
https://segmentfault.com/a/1190000007697941
- MySQL与MongoDB的操作对比
MySQL与MongoDB都是开源的常用数据库,但是MySQL是传统的关系型数据库,MongoDB则是非关系型数据库,也叫文档型数据库,是一种NoSQL的数据库.它们各有各的优点,关键是看用在什么地方 ...
- ubuntu16.04安装teamviewer12
安装teamviewer下载地址:http://www.teamviewer.com/en/download/linux/ 下载的是:teamviewer_12.0.76279_i386.deb ...
- UML实例教程 解析UML建模分析与设计
UML统一建模语言在软件开发过程中非常实用,UMl建模的分析与设计你是否熟悉,这里就通过实例向大家介绍,希望通过本文的学习,你对UML建模的分析与设计方法有一定的了解. 本节向大家介绍一下图书管理系统 ...
- 网络编程基础_4.1TCP_服务端
TCP_服务端 #include <stdio.h> // 1. 包含必要的头文件和库, 必须位于 windows之前 #include <WinSock2.h> #pragm ...
- java学习_5_23
Collection接口中定义的方法如下,所有继承自Collection接口的接口(List,Set)的实现类均实现了这些方法. List容器是有序.可重复的,常用的实现类:ArrayList,Lin ...
- acm相关(纯转载)
我觉得很好的文章,之所以放随笔是为了让大家看到这些优秀的博文 acm如何起步 acm重点题型 动态规划题目总结 背包九讲阅读网站
- pressure coeffcient of a wing/blade
software: CFD POST ANSYS menu bar, select Tools > Macro Calculator. \ correction: Ref pressure is ...
- 百练4152:最佳加法表达式(dp+高精度)
描述 给定n个1到9的数字,要求在数字之间摆放m个加号(加号两边必须有数字),使得所得到的加法表达式的值最小,并输出该值.例如,在1234中摆放1个加号,最好的摆法就是12+34,和为36 输入有不超 ...