antiarpsniffer:用ARP伪装广播探测网络中的Sniffer

嗅探器(Snfer)直以来都是种让人恼火黑客工具它是种静态攻击软件Software存在不会留下任何痕迹因此人们很难将它揪出来可是危害性却又是相当大(它就像个监视器动”都在它监视的下你说危害大不大)所以我们不能不要想个办法出来检查网络中是否存在Snfer这是非常必要 1. Snfer原理 所谓知己知彼方能百战不殆要了解探测Snfer思路方法就先得了解Snfer原理首先让我们来看看局域网中是怎样传输数据个数据包地是局域网内某台计算机时此数据包将以广播形式被发送到网内每台计算机上而每台计算机网卡将分析数据包中Mac地址(即以太网地址)如果此地址为本计算机Mac地址或为广播地址(FF-FF-FF-FF-FF-FF)那么数据包将被接收而如果不是网卡将直接将其丢弃但是这里有个前提就是接收端计算机网卡是在正常模式下工作而如果网卡被设置为混杂模式那么它就可以接收所有经过数据包了(当然也包括目地不是本机数据包)就是说只要是发送到局域网内数据包都会被设置成混杂模式网卡所接收!这也就是Snfer基本原理了至于Snfer具体实现和些细节这里就不多讲了大家有兴趣可以参考相关资料 2. 以太网中传输ARP数据报 知道了Snfer基本原理现在我们就要想想如何才能将局域网中隐藏Snfer揪出来这才是本篇文章主题这里我们需要自己构造ARP数据包所以就先简单介绍下ARP请求和应答数据报结构: typedef struct _et_header //以太网头部 { unsigned char eh_dst[6]; unsigned char eh_src[6]; unsigned eh_type; }ET_HEADER; typedef struct _arp_header //ARP头部 { unsigned arp_hdr; unsigned arp_pro; unsigned char arp_hln; unsigned char arp_pln; unsigned arp_opt; unsigned char arp_sha[6]; unsigned long arp_spa; unsigned char arp_tha[6]; unsigned long arp_tpa; }ARP_HEADER;    以上就是网络中传输ARP数据包结构了至于结构中每个字段所表示具体含义以及如何超出了本文章讨论范围大家有兴趣可以参看TCP-IP协议详解 3. 探测局域网中Snfer 终于进入主题了既然Snfer是种静态黑软不会留下任何日志那么我们就要主动去探测它鉴于Snfer原理是设置网卡为混杂模式那么我们就可以想办法探测网络中被设置为混杂模式网卡以此来判断是否存在Snfer 这里让我们再来看看计算机接收数据包规则前面已经讲过在正常模式下首先由网卡判断数据包Mac地址如果为本机Mac地址或为广播地址那么数据包将被接收进入系统核心否则将被丢弃而如果网卡被设置为混杂模式那么所有数据包都将直接进入系统核心数据包到达系统核心后系统还将进步对数据包进行筛选:系统只会对目Mac地址为本机Mac地址或广播地址数据包做出响应――如果接收到是ARP请求报文那么系统将回馈个ARP应答报文但是区别系统核心和网卡对广播地址判断有些不样:以Windows系统为例网卡会判断Mac地址所有 6位而系统核心只判断Mac地址前两位(Win98甚至只判断前位)也就是说对于系统核心而言正确广播地址FF-FF-FF-FF-FF-FF和广播地址FF-FF-FF-FF-FF-FE是都被认为是广播地址甚至FF-FF-00-00-00-00也会被系统核心认为是广播地址! 写到这里聪明读者大概已经知道该如何做了如果我们构造个目Mac地址为FF-FF-FF-FF-FF-FEARP请求报文那么对于在正常工作模式下网卡数据包将被丢弃当然也就不会回馈任何报文;而对于在混杂模式下网卡数据包将被接收进入系统核心而系统核心会认为这个Mac地址是广播地址因此就会回馈个ARP应答报文这样我们就可以判断出这台机器上存在Snfer了 4. 主要源码分析 由以上分析可知大概分为两个模块个是发送伪装广播地址ARP请求报文个是接收回馈ARP应答报文并做出分析我们就分别用两个线程来实现主线程负责发送监听线程负责接收

首先是创建以太网头部和ARP头部结构: ★ typedef struct _et_header //以太网头部 { unsigned char eh_dst[6]; unsigned char eh_src[6]; unsigned eh_type; }ET_HEADER; typedef struct _arp_header //ARP头部 { unsigned arp_hdr; unsigned arp_pro; unsigned char arp_hln; unsigned char arp_pln; unsigned arp_opt; unsigned char arp_sha[6]; unsigned long arp_spa; unsigned char arp_tha[6]; unsigned long arp_tpa; }ARP_HEADER; ★ 然后是发送ARP请求报文主线程取得所有适配器名字其中“adapter_name”表示个用于存放适配器名字缓冲区而这些适配器名字将以UNICODE编码方式存入此缓冲区中UNICODE编码方式就是用个字空间(两个字节)来存放这样每个间自然会出现个'\0'而两个适配器名字的间将会有个字为'\0'作为间隔adapter_length:这个缓冲区大小: ★ (PacketGetAdapterNames((char*)adapter_name, &adapter_length)FALSE) { prf("PacketGetAdapterNames error:%d\n",GetLastError); 0; } ★ 打开适配器此处我默认打开第块适配器: ★ lpAdapter=(LPADAPTER)PacketOpenAdapter((LPTSTR)adapter_list[0]); (!lpAdapter||(lpAdapter->hFileINVALID_HANDLE_VALUE)) { prf("Unable to open the driver, Error Code : %lx\n", GetLastError); 0; } ★ 以太网头部和ARP头部结构赋值StrToMac是笔者自定义串转换为Mac地址: ★ StrToMac("00E06E41508F",s_Mac); //"00E06E41508F"是笔者测试所用本地机网卡地址,测试者应将其改为测试机网卡地址 memcpy(et_header.eh_src,s_Mac,6); StrToMac("FFFFFFFFFFFE",d_Mac); //目物理地址设置为FFFFFFFFFFFE memcpy(et_header.eh_dst,d_Mac,6); et_header.eh_type=htons(0x0806); //类型为0x0806表示这是ARP包 arp_header.arp_hdr=htons(0x0001); //硬件地址类型以太网地址 arp_header.arp_pro=htons(0x0800); //协议地址类型为IP协议 arp_header.arp_hln=6; //硬件地址长度为6 arp_header.arp_pln=4; //协议地址长度为4 arp_header.arp_opt=htons(0x0001); //标识为ARP请求 arp_header.arp_spa=inet_addr("172.24.21.10"); //"172.24.21.10"是我测试所用本地机IP,测试者应将其改为测试机IP memcpy(arp_header.arp_sha,et_header.eh_src,6); arp_header.arp_tpa=inet_addr(argv[1]); memcpy(arp_header.arp_tha,et_header.eh_dst,6); ★ 发送数据包: ★ lpPacket=PacketAllocatePacket; //给PACKET结构指针分配内存 PacketInitPacket(lpPacket,buffer,512); //化PACKET结构指针 PacketSetNumWrites(lpAdapter,5); //设置发送次数 PacketSendPacket(lpAdapter,lpPacket,TRUE);//发送ARP请求包 ★ 最后别忘了扫尾工作: ★ PacketFreePacket(lpPacket); //释放PACKET结构指针 PacketCloseAdapter(lpAdapter); //关闭适配器 ★ 最后是监听线程: 设置接收数据包系列参数: ★ PacketSetHwFilter(lpAdapter, NDIS_PACKET_TYPE_DIRECTED); //设置网卡为直接模式 PacketSetBuff(lpAdapter,1024); //设置网卡接收数据包缓冲区大小 PacketSetReadTimeout(lpAdapter,2); //设置接收到个包后“休息”时间 ★ 接收数据包: ★PacketReceivePacket(lpAdapter, lpPacket, TRUE); //接收数据包★ 对数据包进行分析以得出结论: ★ char *buf; bpf_hdr *lpBpfhdr; ET_HEADER *lpEthdr; in_addr addr={0}; buf=(char *)lpPacket->Buffer; lpBpfhdr=(bpf_hdr *)buf; lpEthdr=(ET_HEADER *)(buf+lpBpfhdr->bh_hdrlen); (lpEthdr->eh_typehtons(0x0806)) //判断是否为ARP包 { ARP_HEADER *lpArphdr=(ARP_HEADER*)(buf+lpBpfhdr->bh_hdrlen+(ET_HEADER)); char source_ip[20]={0},dest_ip[20]={0}; addr.S_un.S_addr=lpArphdr->arp_spa; memcpy(source_ip,inet_ntoa(addr),strlen(inet_ntoa(addr))); mem(&addr,0,(in_addr)); addr.S_un.S_addr=lpArphdr->arp_tpa; memcpy(dest_ip,inet_ntoa(addr),strlen(inet_ntoa(addr))); (!strcmp(source_ip,ip) && !strcmp(dest_ip,"172.24.21.10")) //判断接收到源IP和目IP是否正确(串变量ip是从主线程传递过来被探测机ip) { (lpArphdr->arp_opthtons(0x0002)) //判断是否为ARP应答 { prf("There is a Snfer!\n"); } } }



  • 篇文章: 鸽子内网上线详细教程

  • 篇文章: 世界顶级防火墙LooknStop配置详解
  • Tags:  sniffer snifferproarp arpsniffer antiarpsniffer

    延伸阅读

    最新评论

    发表评论