filter.c
上传用户:jencksen
上传日期:2016-04-08
资源大小:66k
文件大小:13k
源码类别:

ICQ弱点检测代码

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////
  2. // filter.c文件
  3. // 这个文件包含了驱动程序中过滤相关的代码  过滤部分
  4. #include "precomp.h"
  5. #pragma hdrstop
  6. #include "iocommon.h"
  7. #include "protoinfo.h"
  8. // 过滤规则列表
  9. typedef struct _PassthruFilterList
  10. {
  11. PassthruFilter filter;
  12. struct _PassthruFilterList *pNext;
  13. } PassthruFilterList, *PPassthruFilterList;
  14. // ADAPT结构中FilterReserved部分
  15. typedef struct _ADAPT_FILTER_RSVD
  16. {
  17. BOOLEAN     bFilterInitDone;
  18. //  Per-Adapter过滤相关成员
  19. PassthruStatistics Statistics; // 记录网络状态,如传输了多少封包,丢弃了多少等等
  20. PPassthruFilterList pFilterList; // 指向过滤列表
  21. }ADAPT_FILTER_RSVD, *PADAPT_FILTER_RSVD;
  22. C_ASSERT(sizeof(ADAPT_FILTER_RSVD) <= sizeof(((PADAPT)0)->FilterReserved));
  23. // OPEN_CONTEXT结构中FilterReserved部分.
  24. typedef struct _OPEN_CONTEXT_FILTER_RSVD
  25. {
  26. BOOLEAN     bFilterInitDone;
  27. // 更多的Per-Open-Handle过滤相关成员
  28. }OPEN_FILTER_RSVD, *POPEN_FILTER_RSVD;
  29. C_ASSERT(sizeof(OPEN_FILTER_RSVD) <= sizeof(((POPEN_CONTEXT)0)->FilterReserved));
  30. VOID FltOnInitAdapter(PADAPT pAdapt)
  31. {
  32. PADAPT_FILTER_RSVD   pFilterContext;
  33. //
  34. // 初始化ADAPT结构中的FilterReserved域
  35. //
  36. pFilterContext = (PADAPT_FILTER_RSVD )&pAdapt->FilterReserved;
  37. }
  38. VOID FltOnDeinitAdapter(PADAPT pAdapt)
  39. {
  40. PADAPT_FILTER_RSVD   pFilterContext;
  41. //
  42. // 反初始化ADAPT结构中的FilterReserved域
  43. //
  44. pFilterContext = (PADAPT_FILTER_RSVD)&pAdapt->FilterReserved;
  45. ClearFilterList(pFilterContext);
  46. }
  47. /////////////////////////////////////////////////////
  48. // 向适配器过滤列表中添加一个过滤规则
  49. NTSTATUS AddFilterToAdapter(PADAPT_FILTER_RSVD pFilterContext, PPassthruFilter pFilter)
  50. {
  51. PPassthruFilterList pNew;
  52. // 为新的过滤规则申请内存空间
  53. if(NdisAllocateMemoryWithTag(&pNew, sizeof(PassthruFilterList), TAG) != NDIS_STATUS_SUCCESS)
  54. return STATUS_INSUFFICIENT_RESOURCES;
  55. // 填充这块内存
  56. NdisMoveMemory(&pNew->filter, pFilter, sizeof(PassthruFilter));
  57. // 连接到过滤列表中
  58. pNew->pNext = pFilterContext->pFilterList;
  59. pFilterContext->pFilterList = pNew;
  60. return STATUS_SUCCESS;
  61. }
  62. // 删除适配器过滤列表中的规则
  63. void ClearFilterList(PADAPT_FILTER_RSVD pFilterContext)
  64. {
  65. PPassthruFilterList pList = pFilterContext->pFilterList;
  66. PPassthruFilterList pNext;
  67. // 释放过滤列表占用的内存
  68. while(pList != NULL)
  69. {
  70. pNext = pList->pNext;
  71. NdisFreeMemory(pList, 0, 0); 
  72. pList = pNext;
  73. }
  74. pFilterContext->pFilterList = NULL;
  75. }
  76. // 对那些不能识别的IOCTL,PassThru从主要的DevIoControl例程调用此例程
  77. NTSTATUS FltDevIoControl(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
  78. {
  79. // 假设失败
  80. NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
  81. // 取得此IRP(pIrp)的I/O堆栈指针
  82. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  83. // 取得I/O控制代码
  84. ULONG uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
  85. // 取得I/O缓冲区指针和它的长度
  86. PVOID pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
  87. ULONG uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
  88. ULONG uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  89. ULONG uTransLen = 0;
  90. PADAPT              pAdapt = NULL;
  91.     PADAPT_FILTER_RSVD  pFilterContext = NULL;
  92.     POPEN_CONTEXT       pOpenContext = pIrpStack->FileObject->FsContext;
  93. if(pOpenContext == NULL || (pAdapt = pOpenContext->pAdapt) == NULL)
  94. {
  95. status = STATUS_INVALID_HANDLE;
  96. goto CompleteTheIRP;
  97. }
  98. pFilterContext = (PADAPT_FILTER_RSVD)&pAdapt->FilterReserved;
  99. //
  100. // Fail IOCTL If Unbind Is In Progress   Fail IOCTL If Adapter Is Powering Down
  101. //
  102. NdisAcquireSpinLock(&pAdapt->Lock);
  103. if( pAdapt->UnbindingInProcess || pAdapt->StandingBy == TRUE)
  104. {
  105. NdisReleaseSpinLock(&pAdapt->Lock);
  106. status = STATUS_INVALID_DEVICE_STATE;
  107. goto CompleteTheIRP;
  108. }
  109. // 当改变数据时,要拥有SpinLock
  110. // 最后,处理IO控制代码
  111. switch(uIoControlCode)
  112. {
  113. case IOCTL_PTUSERIO_QUERY_STATISTICS: // 获取网络活动状态
  114. {
  115. uTransLen = sizeof(PassthruStatistics);
  116. if(uOutSize < uTransLen)
  117. {
  118. status =  STATUS_BUFFER_TOO_SMALL;
  119. break;
  120. }
  121. NdisMoveMemory(pIoBuffer, &pFilterContext->Statistics, uTransLen);
  122. status = STATUS_SUCCESS;
  123. }
  124. break;
  125. case IOCTL_PTUSERIO_RESET_STATISTICS: // 重设网络活动状态
  126. {
  127. NdisZeroMemory(&pFilterContext->Statistics, sizeof(PassthruStatistics));
  128. status = STATUS_SUCCESS;
  129. }
  130. break;
  131. case IOCTL_PTUSERIO_ADD_FILTER: // 添加一个过滤规则
  132. {
  133. if(uInSize >= sizeof(PassthruFilter))
  134. {
  135. DBGPRINT((" 添加一个过滤规则"));
  136. status = AddFilterToAdapter(pFilterContext, (PPassthruFilter)pIoBuffer);
  137. }
  138. else
  139. {
  140. status = STATUS_INVALID_DEVICE_REQUEST;
  141. }
  142. }
  143. break;
  144. case IOCTL_PTUSERIO_CLEAR_FILTER: // 清除过滤规则
  145. {
  146. DBGPRINT((" 清除过滤规则"));
  147. ClearFilterList(pFilterContext);
  148. status = STATUS_SUCCESS;
  149. }
  150. break;
  151. }
  152. NdisReleaseSpinLock(&pAdapt->Lock);
  153. CompleteTheIRP:
  154. if(status == STATUS_SUCCESS)
  155. pIrp->IoStatus.Information = uTransLen;
  156. else
  157. pIrp->IoStatus.Information = 0;
  158. pIrp->IoStatus.Status = status;
  159. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  160. return status;
  161. }
  162. ////////////////////////////////////////////////////
  163. // 读取封包中的数据
  164. void FltReadPacketData(PNDIS_PACKET pPacket, 
  165.    PUCHAR lpBufferIn, ULONG nNumberToRead, PUINT lpNumberOfRead)
  166. {
  167. PUCHAR pBuf;
  168. ULONG nBufferSize;
  169. PNDIS_BUFFER pBufferDes = NULL;
  170. // 检查参数
  171. if(pPacket == NULL || lpBufferIn == NULL || nNumberToRead == 0)
  172. {
  173. if(lpNumberOfRead != NULL)
  174. {
  175. *lpNumberOfRead = 0;
  176. return ;
  177. }
  178. }
  179. // 设置返回数据
  180. *lpNumberOfRead = 0;
  181. // 遍历封包中的缓冲区描述表,将数据复制到用户缓冲区
  182. pBufferDes = pPacket->Private.Head;
  183. while(pBufferDes != pPacket->Private.Tail && pBufferDes != NULL)
  184. {
  185. // 获取此缓冲区描述表的缓冲区信息
  186. NdisQueryBufferSafe(pBufferDes, &pBuf, &nBufferSize, NormalPagePriority);
  187. if(pBuf == NULL)
  188. return;
  189. if(nNumberToRead > nBufferSize) // 复制整个缓冲区
  190. {
  191. NdisMoveMemory(lpBufferIn + *lpNumberOfRead, pBuf, nBufferSize);
  192. nNumberToRead -= nBufferSize;
  193. *lpNumberOfRead += nBufferSize;
  194. }
  195. else // 仅复制剩下的部分
  196. {
  197. NdisMoveMemory(lpBufferIn + *lpNumberOfRead, pBuf, nNumberToRead);
  198. *lpNumberOfRead += nNumberToRead;
  199. return;
  200. }
  201. // 下一个缓冲区描述表
  202. pBufferDes = pBufferDes->Next;
  203. }
  204. }
  205. /////////////////////////////////////////////
  206. // 检查过滤规则
  207. BOOLEAN FltCheckFilterRules(PPassthruFilterList pFilterList, PUCHAR pPacketData, ULONG nDataLen, BOOLEAN bIncludeETHdr)
  208. {
  209. int nLeavingLen = nDataLen;
  210. PETHeader pEtherHdr;
  211. PIPHeader pIpHdr;
  212. PTCPHeader pTcpHdr;
  213. PUDPHeader pUdpHdr;
  214. // 从缓冲区中萃取出IP头
  215. // 如果包含以太头,就要先检查以太头
  216. if(bIncludeETHdr)
  217. {
  218. if(nLeavingLen < sizeof(ETHeader))
  219. {
  220. return TRUE;
  221. }
  222. nLeavingLen -= sizeof(ETHeader);
  223. pEtherHdr = (PETHeader)pPacketData;
  224. if(pEtherHdr->type != 0x8) // 如果不是IP协议,则不处理
  225. return TRUE;
  226. pIpHdr = (PIPHeader)(pEtherHdr + 1);
  227. }
  228. else
  229. {
  230. pIpHdr = (PIPHeader)pPacketData;
  231. }
  232. // 验证剩余数据长度,防止发生内核非法访问
  233. if(nLeavingLen < sizeof(IPHeader))
  234. return TRUE;
  235. nLeavingLen -= sizeof(IPHeader);
  236. // 检查版本信息,我们仅处理IPv4
  237. if(((pIpHdr->iphVerLen >> 4) & 0x0f) == 6)
  238. {
  239. return TRUE;
  240. }
  241. if(pIpHdr->ipProtocol == 6 && nLeavingLen >= sizeof(TCPHeader))  // 是TCP协议?
  242. {
  243. // 提取TCP头
  244. pTcpHdr = (PTCPHeader)(pIpHdr + 1);
  245. // 我们接受所有已经建立连接的TCP封包
  246. if(!(pTcpHdr->flags & 0x02))
  247. {
  248. return TRUE;
  249. }
  250. }
  251. // 与过滤规则比较,决定采取的行动
  252. while(pFilterList != NULL)
  253. {
  254. // 查看封包使用的协议是否和过滤规则相同
  255. if(pFilterList->filter.protocol == 0 || pFilterList->filter.protocol == pIpHdr->ipProtocol)
  256. {
  257. // 如果协议相同,再查看源IP地址
  258. if(pFilterList->filter.sourceIP != 0 &&
  259. pFilterList->filter.sourceIP != (pFilterList->filter.sourceMask & pIpHdr->ipSource))
  260. {
  261. pFilterList = pFilterList->pNext;
  262. continue;
  263. }
  264. // 再查看目的IP地址
  265. if(pFilterList->filter.destinationIP != 0 &&
  266. pFilterList->filter.destinationIP != (pFilterList->filter.destinationMask & pIpHdr->ipDestination))
  267. {
  268. pFilterList = pFilterList->pNext;
  269. continue;
  270. }
  271. // 如果是TCP封包,接着查看TCP端口号
  272. if(pIpHdr->ipProtocol == 6)
  273. {
  274. if(nLeavingLen < 4)
  275. {
  276. return TRUE;
  277. }
  278. pTcpHdr = (PTCPHeader)(pIpHdr + 1);
  279. // 如果源端口号和目的端口号都与规则中的一样,则按照规则的记录处理这个封包
  280. if(pFilterList->filter.sourcePort == 0 || pFilterList->filter.sourcePort == pTcpHdr->sourcePort)
  281. {
  282. if(pFilterList->filter.destinationPort == 0 ||
  283. pFilterList->filter.destinationPort == pTcpHdr->destinationPort)
  284. {
  285. DBGPRINT((" 按照规则处理一个TCP封包 n "));
  286. return !pFilterList->filter.bDrop; 
  287. }
  288. }
  289. }
  290. // 如果是UDP封包,接着查看UDP端口号
  291. else if(pIpHdr->ipProtocol == 17)
  292. {
  293. if(nLeavingLen < 4)
  294. {
  295. return !pFilterList->filter.bDrop;
  296. }
  297. pUdpHdr = (PUDPHeader)(pIpHdr + 1);
  298. if(pFilterList->filter.sourcePort == 0 || 
  299. pFilterList->filter.sourcePort == pUdpHdr->sourcePort)
  300. {
  301. if(pFilterList->filter.destinationPort == 0 ||
  302. pFilterList->filter.destinationPort == pUdpHdr->destinationPort)
  303. {
  304. DBGPRINT((" 按照规则处理一个UDP封包 n "));
  305. return !pFilterList->filter.bDrop; 
  306. }
  307. }
  308. }
  309. else
  310. {
  311. // 对于其它封包,我们直接处理
  312. return !pFilterList->filter.bDrop; 
  313. }
  314. }
  315. // 比较下一个封包
  316. pFilterList = pFilterList->pNext;
  317. }
  318. // 默认情况下接收所有封包
  319. return TRUE;
  320. }
  321. // 过滤向外发送的数据,从MPSendPackets或者MPSend函数调用
  322. // 如果从MPSendPackets调用就运行在IRQL <= DISPATCH_LEVEL级别
  323. // 如果从MPSend调用,就运行在IRQL == DISPATCH_LEVEL级别
  324. BOOLEAN FltFilterSendPacket(
  325. IN PADAPT          pAdapt,
  326. IN PNDIS_PACKET   pSendPacket,
  327. IN BOOLEAN         bDispatchLevel  // TRUE -> IRQL == DISPATCH_LEVEL
  328. )
  329. {
  330. BOOLEAN bPass = TRUE;
  331. PADAPT_FILTER_RSVD pFilterContext = (PADAPT_FILTER_RSVD)&pAdapt->FilterReserved;
  332. UCHAR buffer[MAX_PACKET_HEADER_LEN];
  333. ULONG nReadBytes;
  334. // 当使用过滤数据时,要获取旋转锁
  335. if(bDispatchLevel)
  336. {
  337. NdisDprAcquireSpinLock(&pAdapt->Lock);
  338. }
  339. else
  340. {
  341. NdisAcquireSpinLock(&pAdapt->Lock);
  342. }
  343. // 设置统计数字
  344. pFilterContext->Statistics.nMPSendPktsCt ++;
  345. // 如果没有设置过滤规则,则放行所有封包
  346. if(pFilterContext->pFilterList == NULL)
  347. goto ExitTheFilter;
  348. ////////////////////////////////////////////////////
  349. // 读取封包中的数据,这里仅读取封包头即可
  350. FltReadPacketData(pSendPacket, buffer, MAX_PACKET_HEADER_LEN, &nReadBytes);
  351. // 检查过滤规则,看看是否允许这个封包通过
  352. bPass = FltCheckFilterRules(pFilterContext->pFilterList, buffer, nReadBytes, TRUE);
  353. if(!bPass)
  354. {
  355. // 拒绝了一个封包
  356. pFilterContext->Statistics.nMPSendPktsDropped ++;
  357. }
  358. ExitTheFilter:
  359. // 过滤之后要释放旋转锁
  360. if(bDispatchLevel)
  361. NdisDprReleaseSpinLock(&pAdapt->Lock);
  362. else
  363. NdisReleaseSpinLock(&pAdapt->Lock);
  364. return bPass;
  365. }
  366. // 过滤接收到的数据,从PtReceivePacket函数调用,运行在DISPATCH_LEVEL IRQL级别
  367. BOOLEAN FltFilterReceivePacket(
  368. IN PADAPT         pAdapt,
  369. IN PNDIS_PACKET   pReceivedPacket
  370. )
  371. {
  372. BOOLEAN bPass = TRUE;
  373. PADAPT_FILTER_RSVD pFilterContext = (PADAPT_FILTER_RSVD)&pAdapt->FilterReserved;
  374. UCHAR buffer[MAX_PACKET_HEADER_LEN];
  375. ULONG nReadBytes;
  376. // 当使用过滤数据时,要获取旋转锁
  377. NdisDprAcquireSpinLock(&pAdapt->Lock);
  378. // 设置统计数字
  379. pFilterContext->Statistics.nPTRcvPktCt ++;
  380. // 如果没有设置过滤规则,则放行所有封包
  381. if(pFilterContext->pFilterList == NULL)
  382. goto ExitTheFilter;
  383. ////////////////////////////////////////////////////
  384. // 读取封包中的数据,这里仅读取封包头即可
  385. FltReadPacketData(pReceivedPacket, buffer, MAX_PACKET_HEADER_LEN, &nReadBytes);
  386. if(nReadBytes != MAX_PACKET_HEADER_LEN)
  387. {
  388. DBGPRINT(("  FltFilterReceivePacket:  nReadBytes != MAX_PACKET_HEADER_LEN"));
  389. }
  390. // 检查过滤规则,看看是否允许这个封包通过
  391. bPass = FltCheckFilterRules(pFilterContext->pFilterList,buffer, nReadBytes, TRUE);
  392. if(!bPass)
  393. {
  394. // 拒绝了一个封包
  395. pFilterContext->Statistics.nPTRcvPktDropped ++;
  396. }
  397. ExitTheFilter:
  398. // 过滤之后要释放旋转锁
  399. NdisDprReleaseSpinLock(&pAdapt->Lock);
  400. return bPass;
  401. }
  402. // 过滤接收到的数据,从PtReceivePacket函数调用,运行在DISPATCH_LEVEL IRQL级别
  403. BOOLEAN FltFilterReceive(
  404. IN PADAPT         pAdapt,
  405. IN NDIS_HANDLE    MacReceiveContext,
  406. IN PVOID          HeaderBuffer,
  407. IN UINT           HeaderBufferSize,
  408. IN PVOID          LookAheadBuffer,
  409. IN UINT           LookAheadBufferSize,
  410. IN UINT           PacketSize
  411. )
  412. {
  413. BOOLEAN bPass = TRUE;
  414. PADAPT_FILTER_RSVD pFilterContext = (PADAPT_FILTER_RSVD)&pAdapt->FilterReserved;
  415. PETHeader pEtherHdr = (PETHeader)HeaderBuffer;
  416. // 当使用过滤数据时,要获取旋转锁
  417. NdisDprAcquireSpinLock(&pAdapt->Lock);
  418. // 设置统计数字
  419. pFilterContext->Statistics.nPTRcvCt ++;
  420. // 如果没有设置过滤规则,则放行所有封包
  421. if(pFilterContext->pFilterList == NULL)
  422. goto ExitTheFilter;
  423. // 如果不是IP协议,则放行
  424. if(pEtherHdr->type != 0x8)  
  425. goto ExitTheFilter;
  426. // 检查过滤规则,看看是否允许这个封包通过
  427. bPass = FltCheckFilterRules(pFilterContext->pFilterList,LookAheadBuffer, LookAheadBufferSize, FALSE);
  428. if(!bPass)
  429. {
  430. // 拒绝了一个封包
  431. pFilterContext->Statistics.nPTRcvDropped ++;
  432. }
  433. ExitTheFilter:
  434. // 过滤之后要释放旋转锁
  435.     NdisDprReleaseSpinLock(&pAdapt->Lock);
  436. return bPass;
  437. }