P欺诈,使用Winpcap对数据包进行拦截 |
您所在的位置:网站首页 › 如何拦截数据包的短信 › P欺诈,使用Winpcap对数据包进行拦截 |
上一篇讲到了对所有的网络数据包进行侦听,并过滤,得到自己想要分析的数据包。数据包被侦听到了,但仍旧发送给了远程的服务器,若我们希望截获这些数据包,但不希望把这些数据被发送给远程服务器,那该如何解决呢?防火墙!对,我也想到了使用防火墙。windows下的防火墙,大多使用NIDS(Network Driver Interface Specification)对中间层驱动(Intermediate drivers)进行操作。NIDS就是把IP包拦截在中间驱动层,使这些不能通过网卡发送。但是这样做的话,上一篇的模拟sniffer程序也侦听不到被NIDS所拦截的IP包。因此,防火墙行不通。 使用网卡的混杂模式,通过伪造TCP握手信号,赶在本机与远程端握手连通之前,把本机的手牵到自己这里来,不是也可以实现吗?这正是我所要讲的重点。没错,我的实现思路也是这样的。sendto 函数只在windows server 2003 下支持,在windows XP系统下,为了保证网络安全,已经不再被支持。有网友说可以用Wsasend()可以替代sendto,为了节约时间,我没有尝试去用Wsasend()函数。 使用Winpcap(windows packet capture)可以完成所需要的功能。winpcap独立于主机协议(如TCP-IP)而发送和接收原始数据包。Winpcap为数据包捕获提供了windows下的一个平台,它是由伯克利分组捕获库派生而来的分组捕获库,它是在Windows操作平台上来实现对底层包的截取过滤,它的体系结构是由一个核心的包过滤驱动程序,一个底层的动态连接库packet.dll和一个高层的独立于系统的函数库libpcap组成。 调用winpcap函数的程序,需要安装winpcap程序,使之能与驱动挂上钩。还需要下载winpcap的头文件和相应的库文件。这样程序才能够跑得起来。
首先先来介绍一下包头。除了上一篇介绍的IP头,TCP、UDP、ICMP头外,这里还有两个头:以太网地址包头和计算校验码的包头。 typedef struct _ethhdr { unsigned char eh_dst[6]; unsigned char eh_src[6]; unsigned short eh_type; }ETH_HEADER;
typedef struct _psdhdr { unsigned long saddr; unsigned long daddr; char mbz; //保留,置0 char ptcl; //协议,如IPPROTO_TCP unsigned short tcpl; //TCP报头长度 }PSD_HEADER;
写一个对数据进行处理的类。 class CTod { public: CTod(void); ~CTod(void); public: pcap* m_pCap; //PCAP句柄 public: int CTod::SendRaw(BYTE *_dmac,BYTE *_smac, USHORT _ident, ULONG _saddr,USHORT _sport, ULONG _daddr,USHORT _dport, ULONG _seq, ULONG _ack); USHORT checksum(USHORT *buffer, int size); BOOL OpenPcap(ULONG _laddr); //打开本地网口 static DWORD WINAPI WorkSniffer(LPVOID _lp); //抓包线程 };
CTod::CTod(void) {} CTod::~CTod(void) {} int CTod::SendRaw(BYTE *_dmac,BYTE *_smac, //目的MAC,源MAC,网络顺序 USHORT _ident, //IP包标识号 ULONG _saddr,USHORT _sport, //源IP,PORT,网络顺序 ULONG _daddr,USHORT _dport, //目的IP,PORT,网络顺序 ULONG _seq, ULONG _ack) //32位序列号,应答号,网络顺序 { if(m_pCap==NULL){ return -1; } //构造以太网头 ETH_HEADER eth; memcpy(eth.eh_dst,_dmac,6); memcpy(eth.eh_src,_smac,6); eth.eh_type=htons(ETH_IP); //构造IP头 IP_HEADER ip; ip.h_verlen= 4 bytes_out=len; } return bytes_out; } //计算校验和 USHORT CTod::checksum(USHORT *buffer, int size) { unsigned long cksum=0; while(size>1){ cksum+=*buffer++; size-=sizeof(USHORT); } if(size) cksum+=*(UCHAR*)buffer; cksum=(cksum>>16)+(cksum&0xffff); cksum+=(cksum>>16); return (USHORT)(~cksum); }
未完,见下一篇。。。
接上一篇。。。
//打开一个网卡 BOOL CTod::OpenPcap(ULONG _laddr) { pcap_if_t *alldevs; //打开适配器时使用 pcap_if_t *d; char errbuf[PCAP_ERRBUF_SIZE]; if(pcap_findalldevs(&alldevs,errbuf)==-1){ //获取网卡的列表 return FALSE; } BOOL bfind=FALSE; for(d=alldevs; d; d=d->next){ for(pcap_addr_t *a=d->addresses; a; a=a->next){ struct sockaddr_in *psin=(struct sockaddr_in*)a->addr; if( psin->sin_family==AF_INET ){ if( psin->sin_addr.s_addr==_laddr ){ bfind=TRUE; break; } } } if(bfind) break; } if(!bfind){ pcap_freealldevs(alldevs); return FALSE; } //打开选择的网卡 if((m_pCap=pcap_open_live(d->name, // 设备名称 65535, // portion of the packet to capture 1, // 混杂模式 100, // 读超时为0.1秒 errbuf // error buffer ))==NULL) { fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf); pcap_freealldevs(alldevs); //释放设备列表 return FALSE; } pcap_setbuff(m_pCap,1024*1024); //设置内核缓冲区,pcap默认是1M缓冲 struct bpf_program fcode; //指向BPF指令所在空间 char filter[4]="tcp"; ULONG netmask=0x00ffffff; ULONG mask=*(ULONG*)&(((struct sockaddr_in*)d->addresses->netmask)->sin_addr); netmask=mask; pcap_compile(m_pCap, &fcode,filter,1,netmask); //编译 tcpdump 表达式为BPF程序 pcap_setfilter(m_pCap, &fcode); //设置BPF内核过滤器 pcap_freecode(&fcode); //释放指令空间 pcap_freealldevs(alldevs); //释放设备列表 return TRUE; }
//抓包子线程 DWORD WINAPI CTod::WorkSniffer(LPVOID _lp) { CTod *ptod=(CTod*)_lp; struct pcap_pkthdr *header; u_char *pkt_data; char szSourceIP[MAX_ADDR_LEN]; char szDestIP[MAX_ADDR_LEN]; int ret=0; while(TRUE) { //捕获数据包 ret=pcap_next_ex(ptod->m_pCap, &header, //内核过滤器每输出一个包,将在输出的数据前加了20字节的数据 (const u_char**)&pkt_data); if(retsaddr; if( IsAlexaDes(szSourIP) ){ } unsigned long szDestIP = pip->daddr; if( !IsAlexaDes(szDestIP) ){ //目的IP都与Alexa无关 continue; } //除掉IP头和TCP头后的数据长度 int predatalen=ntohs(pip->total_len)-40;
正向发RST包 //ptod->SendRaw(peth->eh_dst,peth->eh_src, // htons(ntohs(pip->ident)+1), // pip->saddr,ptcp->th_sport, // pip->daddr,ptcp->th_dport, // htonl( ntohl(ptcp->th_seq)+predatalen ), // ptcp->th_ack); //反向发RST包 ptod->SendRaw(peth->eh_src,peth->eh_dst, htons(0), pip->daddr,ptcp->th_dport, pip->saddr,ptcp->th_sport, ptcp->th_ack, htonl( ntohl(ptcp->th_seq)+1 )); } return 0; }
程序是通过侦听到TCP连接的握手信号,然后对TCP包进行分析后,发送一个握手应答信号给连接的发起端。当连接的发起端接收到连接应答信号后,会再发送一个应答信号,此时,连接发起端认为TCP连接己经建立,就开始发送数据。再用上一篇讲的办法来侦听数据,即可得到所需的IP包。因此,通过这种IP欺诈的办法,可以骗得所需的TCP数据包。 http://blog.sina.com.cn/s/blog_613e4fea0100l5tj.html |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |