抓取网络数据包

抓取网络数据包

当用户在局域网内传递数据时,处于同一网段的所有计算机的网卡都会收到这些数据,尽管它不是传递数据的目的地。利用这一特点,我们就可以截获局域网中传递的数据。为了能够获取通过网卡上的数据,需要创建原始套接字。用户可以将socket函数的第二个参数设置为SOCK_RAW来创建原始套接字。例如:

m_Socket=socket(AF_INET,SOCK_RAW,IPPROTO_IP);

由原始套接字获得的数据是IP数据报,而不仅仅是一个用户数据。它还包含IP数据头和相应协议的数据头,最后才是用户数据。为了获得用户数据,需要逐一去掉IP数据头及各个协议的数据头。

//创建套接字,开始监听网络
void CSniffAppDlg::OnBeginlistn()
{
    //创建套接字
    m_Sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP);
    char name[128];
    memset(name,0,128);

    hostent* phostent;
    phostent=gethostbyname(name);

    DWORD ip;

    ip=inet_addr(inet_ntoa(*(int_addr)phostent->h_addr_list[0]));
    int timeout=4000; //超时4秒
    //设置接受数据的超时时间
    setsockopt(m_Sock,SOL_SOCKET.SO_RCVTIMEO.(const char *)&timeou.sizeof(timeout));
    sockadd_in_skaddr;
    skaddr.sin_family=AF_INET;
    skaddr.sin_port=htons(700);
    skaddr.sin_addr.S_un.S_addr=ip;
    //绑定地址
    if(bind(m_Sock,(sockaddr*)$skaddr,sizeof(skaddr))==SOCKET_ERROR)
    {
    MessageBox("地址绑定错误");
    return;
    }
    DWORD inBuffer=1;
    DWORD outBuffer[10];
    DWORD reValue=0;
    if(WSAIoctl(m_Sock,SIO_RCVAL,&inBuffer,sizeof(inBuffer),&outBuffer,sizeof(outBuffer),&reValue,NULL)==SOCKET_ERROR)
    {
    MessageBox("设置缓冲区错误。");
    closesocket(m_Sock);
    return;
    }
    else
     m_pThread=AfxBeginThread(ThreadFun.(void*)this);

}
UINT ThreadFun(LPVOID pFaram) //去除数据头
{
    CSniffAppDlg* pDlg=static_cast<CSniffAppDlg*>(pParam);
    MSG msg;
    char buffer[1000],sourceip[32],*tempbuf;
    char *ptemp;

    BYTE* pData=NULL; //实际数据包中的数据
    UINT sourceport;
    CString str;
    HEADIP* pHeadIP;
    HEADICMP* pHeadICMP;
    HEADUDP* pHeadUDP;
    HEADTCP* pHeadTCP;
    in_addr addr;
    int ret;
    while(TRUE)
    {
        pData=NULL;
        if(PeekMessage(&msg.pDlg->m_hWnd,WM_CLOSE,WM_CLOSE,PM_NOREMOVE))
        {
            closesocket(pDlg->m_Sock);
            break;
        }
        memst(buffer,0,1000);
        ret=recv(pDlg->m_Sock,buffer,1000,0);
        if(ret==SOCKET_ERROR)
            {
             continue;
            }
            else    //接收到的数据
            {
                tempbuf=buffer;
                pHeadIP=(HEADIP*)tempbuf;
                WORD len=ntohs(pHeadIP->totallen); //获取数据报总长度
                //获取源IP
                pDlg->m_List.InsertItem(pDlg->m_List.GetItemCount()."");
                addr.S_un.S_addr=pHeadIP->sourceIP;
                ptemp=inet_ntoa(addr);

                pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,1,ptemp);
                //获取目的IP
                addr.S_un.S_addr=pHeadIP->destIP;
                ptemp=inet_ntoa(addr);
                pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,2,ptemp);

                //获取协议名称
                ptem=get_protoname(pHeadIP->proto);
                strcpy(sourceip,ptemp);
                pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,0,sourceip);

                //获取IP数据报总长度
                WORD ipSunLen=ntohs(pHeadIP->totallen);

                //IP数据报头总长度
                int netlen=ipSumLen-ipHeadLen;

                //根据不同的协议获得不同协议的数据
                switch(pHeadIP-proto)
                {
                    case IPPROTO_ICMP:
                    {
                        pHeadICMP=(HEADICMP*)(tempbuf+20);
                        pData=(BYTE*)(pHeadICMP)+4;//ICMP数据报头功4个字节

                        //获取数据的长度
                        netlen-=4;
                        break;
                    }

                    case IPPROTO_UDP:
                    {
                        pHeadUDP=(HEADUDP*)(tempbuf+20);
                        pData=(BYTE*)(pHeadUDP)+8;//UDP数据报头共8个字节
                        sourceport=ntohs(pHeadUDP->SourcePort);
                        str.Format("%d",sourceport);
                        //设置源端口
                        pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,3,str);
                        str.Empty();
                        netlen-=8;
                        break;
                    }

                    case IPPROTO_TCP:
                    {
                        pHeadTCP=(HEADTCP*)(tempbuf+20);
                        sourceport=ntohs(pHeadTCP->SourcePort);
                        pData=(BYTE*)(pHeadTCP)+20;//TCP数据报头共20个字节
                        str.Format("%d",sourceport);
                        //设置源端口
                        pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,3,str);
                        str.Empty();
                        netlen-=20;
                        break;
                    }
                }
                //设置数据大小
                str.Format("%d",netlen);
                pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,4,str);
                str.Empty();
                //设置数据
                if(pData!=NULL)
                {
                    str.Format("%s",pData);
                    pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,5,str);

                }
                str.Empty();

            }
    }
    return  0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值