使用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) 收藏 举报 ...
随机推荐
- pycharm永久激活(转载)
转载自CSDN--http://blog.csdn.net/mr_hhh/article/details/79062747 2018-02-2417:30:52 今天再补充一个教程,关于pycharm ...
- Python学习日记之字典深复制与浅复制
Python中通过copy模块有两种复制(深复制与浅复制) copy 浅复制 复制时只会复制父对象,而不会复制对象的内部的子对象. deepcopy 深复制 复制对象及其子对象 因此,复制后对原dic ...
- IDEA 提示Cannot resolve symbol
将Springboot项目,构建为多个模块的时候,idea的有些类中报错Cannot resolve symbol 解决: 1.File->Invalidate Caches/Restart 清 ...
- FTP初始化文件.netrc使用技巧[转发]
FTP初始化文件.netrc使用技巧 FTP(文件传输)和E-mail(电子邮件).Telnet(远程登录)一样,是 Internet的三大主要功能之一.因为使用频繁,用户往往会遇到各种 各样的问题, ...
- git常用命令和github
工作区:就是你的工作目录 暂存区:它像个缓存区域,临时保存你的改动 版本区:就是你的git仓库 HEAD:相当于一个指针,指向你最近一次提交后的结果 git status 查看状态 git add . ...
- POJ_2828_Buy Tickets
题意:插队问题: 2016.5.20,复习这道题. 总结:线段树基础不牢,建树,更新尚不熟悉,注意加强理解记忆. 主要理解:(单点更新,逆序插入) 发生插队时,前面的队伍是连续没有空位的,即pos:2 ...
- R中矩阵运算
# 数据产生 # rnorm(n, mean = 0, sd = 1) 正态分布的随机数(r 代表随机,可以替换成dnorm, pnorm, qnorm 作不同计算.r= random = 随机, d ...
- Vue指令1:v-text及v-html
v-text: //插入一段文本<div id="app"> <p v-text="message"></p></di ...
- JS的filter用法
filter也是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素. 和map()类似,Array的filter()也接收一个函数.和map()不同的是,filter()把传入的函 ...
- JS中的let和var的区别
最近很多前端的朋友去面试被问到let和var的区别,其实阮一峰老师的ES6中已经很详细介绍了let的用法和var的区别.我简单总结一下,以便各位以后面试中使用. ES6 新增了let命令,用来声明局部 ...