本工程是驱动vpcknt的一个封闭层而已,比较简单。

一、导出的API接口分析

1、Start

(1)加载驱动vpcknt.sys。

vpcknt.sys是从工程的资源文件中通过CreateDriverFileFromAppResources加载的。(所以启动NDIS时金山杀毒软件会警告)

得到驱动文件后调用StartVersionedDeviceDriver把驱动.sys加载。 (加载过程中还通过驱动读取了版本)

(驱动加载方法通过服务的方式,与前面文章<<虚拟桌面:一个简单的桌面管理工具>>是一样的)

(2)初始化PINITIALIZE_HOOK_INPUT的两个变量pihiHookInput 、pihoHookOutput;

且通过调用驱动的IOCTL_VPCKNT_INITIALIZE_HOOK初始化pihoHookOutput数据和PNT_PROTOCOL_LIST指针(即协议列表);

2、Stop

卸载驱动

3、Listen

OALIST_ITEM类型的数据指针作为入参数,驱动IO码为IOCTL_VPCKNT_SUBMIT_OALIST的调用,目的是提交OALIST数据。

4、WaitForPacket

这里先去判断上一个包状态中的bArePacketsRemaining标志,如果它为TRUE,表还有数据,那么直接去读;

否则调用WaitForMultipleObjects等待内核事件;

[cpp] view plaincopy
  1. HANDLE      vhHandles[] = { g_hKernelEvent, g_hExitFromThread };
  2. DWORD       dwWaitRes = g_hsPrevStats.bArePacketsRemaining ? WAIT_OBJECT_0 :
  3. ::WaitForMultipleObjects( 2, vhHandles, FALSE, INFINITE );

获得包和数据包的状态

[cpp] view plaincopy
  1. DWORD       dwBytesReturned = 0;
  2. BOOL        bIoctlRes = ::DeviceIoControl( g_hDevice, IOCTL_VPCKNT_GET_NEXT_PACKET,
  3. NULL, 0,
  4. g_pbStorage, MACRO_STORAGE_BUFFER_SIZE,
  5. & dwBytesReturned, NULL );
  6. if ( bIoctlRes != FALSE && dwBytesReturned != 0 )
  7. {
  8. // allocate the packet memory.
  9. BYTE*           pb = (BYTE*) ::malloc( dwBytesReturned );
  10. if ( pb == NULL )
  11. return FALSE;
  12. else
  13. ::memcpy( pb, g_pbStorage, dwBytesReturned );
  14. // return.
  15. g_hsPrevStats = * (HOOK_STATS*) pb;
  16. if ( psStats )
  17. * psStats = * (HOOK_STATS*) pb;
  18. * pppPacketPtr = (PNEXT_PACKET) ( pb + sizeof( HOOK_STATS ) );

二、总结:

1、原子操作

通过原子操作能保证在多线程时保证得调用完Start,才能使用Listen和Stop,起到的作用与关键代码类似。

(1)在Start开始时:

EHS_INITIALIZING为1;

EHS_NOT_INITIALIZED为0;

[plain] view plaincopy
  1. LONG            prev = ::InterlockedCompareExchange( & g_lHooked, EHS_INITIALIZING, EHS_NOT_INITIALIZED );
  2. if ( prev != EHS_NOT_INITIALIZED )
  3. return FALSE;

g_lHooked最开始为0,上面的代码后g_lHooked为  1  ;

(2)在Start结束时:

[cpp] view plaincopy
  1. g_lHooked = EHS_FUNCTIONING;

EHS_FUNCTIONING为 2 ;

(3)在Stop里:

EHS_FUNCTIONING 为 2;

EHS_STOPPING 为 3 ;

[cpp] view plaincopy
  1. LONG            prev = ::InterlockedCompareExchange( & g_lHooked, EHS_STOPPING, EHS_FUNCTIONING );
  2. if ( prev != EHS_FUNCTIONING )
  3. return;

因为经过了Start 的结束后g_lHooked为 2 ; 所以经过上面的代码后g_lHooked 为  3 ;

1、InterlockedCompareExchange

InterlockedCompareExchange属于Interlocked系列互锁函数之一,常用于多线程编程。

类似的还有下面的几个:

//增减

(1) LONG InterlockedIncrement(IN OUT LONG volatile *lpAddend);

  lpAddend为长整型变量的地址,返回值为原始值。这个函数的主要作用是原子性自增(相当于++操作)。

(2) LONG InterlockedDecrement(IN OUT LONG volatile *lpAddend);

  lpAddend为长整型变量的地址,返回值为原始值。这个函数的主要作用是原子性自减(相当于--操作)。

(3) LONG InterlockedExchangeAdd ( LPLONG Addend, LONG Increment );

  Addend为长整型变量的地址,Increment为想要在Addend指向的长整型变量上增加的数值(可以是负数)。这个函数的主要作用是保证这个加操作为一个原子访问。

  //交换

(4) LONG InterlockedExchange( LPLONG Target, LONG Value );

  用第二个参数的值取代第一个参数指向的值。函数返回值为原始值。

(5) PVOID InterlockedExchangePointer( PVOID *Target, PVOID Value );

  用第二个参数的值取代第一个参数指向的值。函数返回值为原始值。

//比较交换

(6) LONG InterlockedCompareExchange( LPLONG Destination, LONG Exchange, LONG Comperand );

  如果第三个参数与第一个参数指向的值相同,那么用第二个参数取代第一个参数指向的值。函数返回值为原始值。

(7) PVOID InterlockedCompareExchangePointer ( PVOID *Destination, PVOID Exchange, PVOID Comperand );

  如果第三个参数与第一个参数指向的值相同,那么用第二个参数取代第一个参数指向的值。函数返回值为原始值。

NDIS网络数据监控程序NDISMonitor(2)-----驱动与应用的中间层NdisHook相关推荐

  1. 网络数据包拦截通用技术(协议驱动hook)

    网络数据包拦截通用技术 作者:甘嘉平 (gjp) 看到很多仁兄提供的数据包的拦截技术,其中最多的是编写IM DRIVER在NDIS中间层 对MINIPORT(网卡驱动程序)和协议驱动程序之间的数据包进 ...

  2. Linux内核网络数据发送(六)——网络设备驱动

    Linux内核网络数据发送(六)--网络设备驱动 1. 前言 2. 驱动回调函数注册 3. `ndo_start_xmit` 发送数据 4. `igb_tx_map` 1. 前言 本文主要介绍设备通过 ...

  3. NDIS网络驱动程序-----

    from:http://blog.sina.com.cn/s/blog_61d65e360100waop.html NDIS网络驱动程序-----学习(一) (2011-08-15 21:48:14) ...

  4. 网络数据包拦截通用技术

    网络数据包拦截通用技术 作者:甘嘉平 (gjp) 看到很多仁兄提供的数据包的拦截技术,其中最多的是编写IM DRIVER在NDIS中间层 对MINIPORT(网卡驱动程序)和协议驱动程序之间的数据包进 ...

  5. COPY FROM 文章标题 网络数据包拦截通用技术

    COPY FROM 文章标题 网络数据包拦截通用技术 看到很多仁兄提供的数据包的拦截技术,其中最多的是编写IM DRIVER在NDIS中间层 对MINIPORT(网卡驱动程序)和协议驱动程序之间的数据 ...

  6. 《数据科学:R语言实现》——2.7 爬取网络数据

    本节书摘来自华章计算机<数据科学:R语言实现>一书中的第2章,第2.7节,作者 丘祐玮(David Chiu),更多章节内容可以访问云栖社区"华章计算机"公众号查看. ...

  7. linux receive函数,Linux网络 - 数据包的接收过程

    的方式写入到指定的内存地址,该地址由网卡驱动分配并初始化.注: 老的网卡可能不支持DMA,不过新的网卡一般都支持. 3: 网卡通过硬件中断(IRQ)通知CPU,告诉它有数据来了 4: CPU根据中断表 ...

  8. 网络数据包收发流程(三):e1000网卡和DMA

    早就想整理网络数据包收发流程了,一直太懒没动笔.今天下决心写了 一.硬件环境 intel82546:PHY与MAC集成在一起的PCI网卡芯片,很强大 bcm5461:   PHY芯片,与之对应的MAC ...

  9. Linux内核网络数据发送(五)——排队规则

    Linux内核网络数据发送(五)--排队规则 1. 前言 2. `qdisc_run_begin()` and `qdisc_run_end()`:仅设置 qdisc 状态位 3. `__qdisc_ ...

最新文章

  1. 菜鸟学习Spring——60s利用JoinPoint获取參数的值和方法名称
  2. java sqlite mybatis_Spring boot + Mybatis + SQLite 搭建blog API
  3. fat32 linux 打包工具_一个方便的用于创建树莓派 SD 卡镜像的程序 | Linux 中国
  4. C++多线程基础笔记
  5. 快讯:阿里巴巴加入JCP执行委员会
  6. 3140: [Hnoi2013]消毒
  7. geoserver三维_集团公司自主研发三维GIS平台产品——GeniusWorld 2.0 C版本发布
  8. php 环信easyui_环信easeui集成:坑总结2018
  9. 剑指offer面试题32 - III. 从上到下打印二叉树 III(二叉树)(BFS)
  10. 2017百度之星初赛:A-1001. 小C的倍数问题
  11. Java 登录拦截器
  12. 网易云Android高级,网易云音乐Android新版 一键升本地音质
  13. 羊年祝福语(羊年祝福大全)
  14. 【离散数学】一阶/谓词逻辑思维导图
  15. vscode 经常弹出:尝试在目标目录创建文件时发生一个错误 重试 跳过这个文件 关闭安装程序
  16. 2022-2027年中国肺炎疫苗行业市场运行现状及投资战略研究报告
  17. java文件读取报(文件名、目录名或卷标语法不正确。)
  18. 黑马程序员_Java_异常
  19. 包载信使mRNA的多西环素纳米脂质体|雷公藤红素纳米脂质体RNA核糖核酸(实验原理)
  20. 5G行业专网赋能!《5G垂直行业专网设计及部署白皮书》正式发布!

热门文章

  1. php+mysql 员工管理系统 学生课设源码
  2. 测量block size 为8K ,自动分配的本地管理表空间的位图block一位能管理多少空间
  3. Resource Path Location Type Project configuration is not up-to-date with pom.xml. Run Ma
  4. Java之数组的定义格式,【默认值规则】,Java内存划分5大区,面向对象类的基本定义和对象的使用,private和this关键字,类的构造方法,标准类的组成部分。
  5. 亚阈值区MOSFET阈值电压Vth随温度变化曲线仿真【Cadence】
  6. SLAM数学篇:问题表述
  7. 15_细菌的繁殖与扩散
  8. 毕节计算机考试准考证打印,2016年9月毕节计算机三级四级准考证打印入口,计算机等级考试时间查询...
  9. Aruba7010 默认密码_【对讲机的那点事】如何为您的数字对讲机热点配置安全密码...
  10. Ansys Speos | 联合 optiSLang 背光板设计优化方案