简单的网络数据包分析小程序

对MAC、IP、TCP等的数据包进行抓取分析其结构,使用了pcap库

1.mac.h

#include <string>
#include <iostream>
#include <cstdio>

class PMacHeader
{
private:
    const unsigned char *m;
    std::string dst, src, type, tpname;
public:
    PMacHeader(const unsigned char *p = 0){m = p;}
    ~PMacHeader(){m = 0;}
    void ResetPt(const unsigned char * p){m = p;}
    unsigned short GetProtocol();
    std::string& GetDstStr();
    std::string& GetSrcStr();
};

2.mac.cpp

#include "stdafx.h"
#include "mac.h"

unsigned short PMacHeader::GetProtocol()
{
    unsigned short thetype;
    thetype = (unsigned short)m[12] << 8;
    thetype += (unsigned short)m[12+1];
    return thetype;
}
std::string& PMacHeader::GetDstStr()
{
    char dstBuf[6*3+1];
    std::sprintf(dstBuf, "%.2x %.2x %.2x %.2x %.2x %.2x ", m[0], m[1], m[2], m[3], m[4], m[5]);
    dst = dstBuf;
    return dst;
}
std::string& PMacHeader::GetSrcStr()
{
    char srcBuf[6*3+1];
    std::sprintf(srcBuf,"%.2x %.2x %.2x %.2x %.2x %.2x ", m[6], m[7], m[8], m[9], m[10], m[11]);
    src = srcBuf;
    return src;
}
3.ip.h

#include <string>
#include <iostream>
#include <cstdio>

class PIpHeader
{
private:
    const unsigned char *p;
    std::string src, dst;
public:
    PIpHeader(const unsigned char *pt = 0):p(pt){}
    ~PIpHeader(){p = 0;}
    void Reset(const unsigned char *pt){ p = pt;}
    short GetVesion();//取IP的版本
    short GetHeaderLen();//取IP报头的长度 (1单位/4字节)
    short GetServer();//服务
    unsigned short GetTotalLen();//总长度
    unsigned short GetID();//标识
    short GetFlag();
    short GetEx();//偏移量
    short GetTTL();
    unsigned short GetProtocol();
    unsigned short GetCheck();//校验码
    std::string& GetSrcStr();//源IP的字符串形式
    std::string& GetDstStr();//目标IP的字符串形式
};
4.ip.cpp

#include "stdafx.h"
#include "IP.h"

short PIpHeader::GetVesion()
{ return p[0] >> 4;}

short PIpHeader::GetHeaderLen()
{ return p[0] & 0x0f;}

short PIpHeader::GetServer()
{ return p[1];}

unsigned short PIpHeader::GetTotalLen()
{
    unsigned short length = (unsigned short)p[2] << 8;
    length += (unsigned short)p[3];
    return length;
}
unsigned short PIpHeader::GetID()
{
    unsigned short id = (unsigned short)p[4] << 8;
    id += (unsigned short)p[5];
    return id;
}
short PIpHeader::GetFlag()
{
    return p[6] >> 5;
}
short PIpHeader::GetEx()
{
    unsigned short ex = ((unsigned short)p[6] & 0x1f) << 8;
    ex += (unsigned short)p[7];
    return ex;
}
short PIpHeader::GetTTL()
{
    return (unsigned short)p[8];
}
unsigned short PIpHeader::GetProtocol()
{
    return (unsigned short)p[9];
}
unsigned short PIpHeader::GetCheck()
{
    unsigned short check = (unsigned short)p[10] << 8;
    check += (unsigned short)p[11];
    return check;
}
std::string& PIpHeader::GetSrcStr()
{
    char srcbuf[16+1];
    std::sprintf(srcbuf, "%d.%d.%d.%d", p[12], p[13], p[14], p[15]);
    src = srcbuf;
    return src;
}
std::string& PIpHeader::GetDstStr()
{
    char dstbuf[16+1];
    std::sprintf(dstbuf, "%d.%d.%d.%d", p[16], p[17], p[18], p[19]);
    dst = dstbuf;
    return dst;
}

5.ProtocolType.cpp
#include "stdafx.h"
#include "ProtocolType.h"

const unsigned char* GetMacPointer(const unsigned char *p)
{
    return p;
}
const unsigned char* GetArpPointer(const unsigned char *p)
{
    return p+14;
}
const unsigned char* GetIpPointer(const unsigned char *p)
{
    return p+14;
}
const unsigned char* GetTcpPointer(const unsigned char *p)
{
   return GetIpPointer(p)+(((unsigned short)(GetIpPointer(p)[0]) & 0x0f)*4);
}

6.使用mfc库,其中的主要内容如下,使用了pcap

bool CPCDlgDlg::InitAdapter(void)
{
    CString adapter;
    char errBuf[PCAP_ERRBUF_SIZE];
    TCHAR t_errBuf[PCAP_ERRBUF_SIZE];
    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errBuf) == -1)
    {
        MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, errBuf, sizeof(errBuf), t_errBuf, sizeof(t_errBuf));
        adapter.Format(_T("Error in pcap_findalldevs:%s\n"), t_errBuf);
        ((CListBox*)GetDlgItem(IDC_LIST_ADAPTER))->AddString(adapter);
        return false;
    }
    else
    {
        for (dev = alldevs; dev; dev = dev->next)
        {
            DWORD dwNameNum = MultiByteToWideChar (CP_ACP, 0, dev->name, -1, NULL, 0);
            DWORD dwDesNum = MultiByteToWideChar (CP_ACP, 0, dev->description, -1, NULL, 0);
            TCHAR* dev_name = new TCHAR[dwNameNum];
            TCHAR* dev_des = new TCHAR[dwDesNum];
            MultiByteToWideChar(CP_ACP, 0, dev->name, -1, dev_name, dwNameNum);
            MultiByteToWideChar(CP_ACP, 0, dev->description, -1, dev_des, dwDesNum);
            
            adapter.Format(_T("%s(%s)"),dev_name, dev_des);
            delete [] dev_name;
            delete [] dev_des;
            ((CListBox*)GetDlgItem(IDC_LIST_ADAPTER))->AddString(adapter);
        }
    }
    return true;
}


CPCDlgDlg::~CPCDlgDlg(void)
{
     pcap_freealldevs(alldevs);
}


void CPCDlgDlg::OnBnClickedButtonCatch()
{
    int select = 0;
    select = ((CListBox*)GetDlgItem(IDC_LIST_ADAPTER))->GetCurSel();
    dev = alldevs;
    for (int i = 0; i < select; dev = dev->next, ++i);

    char errBuf[PCAP_ERRBUF_SIZE];
    TCHAR t_errBuf[PCAP_ERRBUF_SIZE];
    pcap_t *adhandle;
    if ((adhandle = pcap_open(dev->name,
        65536,
        PCAP_OPENFLAG_PROMISCUOUS,
        1000,
        NULL,
        errBuf
        )) == NULL)
    {
        CString errStr;
        MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, errBuf, sizeof(errBuf), t_errBuf, sizeof(t_errBuf));
        errStr.Format(_T("Error in pcap_findalldevs:%s\n"), t_errBuf);
        ((CListBox*)GetDlgItem(IDC_LIST_ADAPTER))->AddString(errStr);
        return;
    }

    if (!isCatch)
    {
        isCatch = true;
        HCatchThread = AfxBeginThread(CatchPacket, adhandle);
    }
}


void CPCDlgDlg::InsertPacketToList(pcap_t *adhandle, pcap_pkthdr *header, const u_char *pkt_data)
{
    static CString strPacketInfo;
    std::string total_info_ascii_str;    
    //
    using std::cout;
    using std::endl;
    //总体信息
    static struct tm ltime;
    static time_t local_tv_sec;
    static char timestr[16];
    local_tv_sec = header->ts.tv_sec;
    localtime_s(<ime, &local_tv_sec);
    strftime(timestr, sizeof(timestr), "%H:%M:%S", <ime);

    static char Buffer[150];
    sprintf(Buffer, "时间:%s,%.6d 总长度:%d\n", timestr, header->ts.tv_usec, header->len);
    total_info_ascii_str = Buffer;
    

    //输出MAC首部主要内容
    
    static PMacHeader pmac;
    pmac.ResetPt(GetMacPointer(pkt_data));
    total_info_ascii_str += "      MAC首部---";
    total_info_ascii_str += "目的地址:" + pmac.GetDstStr() + "源地址:"+pmac.GetSrcStr();

    unsigned short protocol_type = pmac.GetProtocol();
    //输出ARP首部主要内容
    if (protocol_type == PROTOCOL_ARP)
    {
        static PArpHeader parp;
        parp.Reset(GetArpPointer(pkt_data));
        total_info_ascii_str += "      ARP首部---";
        total_info_ascii_str += "谁是:" + parp.GetDstIPStr() + "请告诉:" + parp.GetSrcIPStr();

        DWORD dwNum = MultiByteToWideChar (CP_ACP, 0, total_info_ascii_str.c_str(), -1, NULL, 0);
        TCHAR* packet_info = new TCHAR[dwNum];
        MultiByteToWideChar(CP_ACP, 0, total_info_ascii_str.c_str(), -1, packet_info, dwNum);
        strPacketInfo.Format(_T("%s"), packet_info);
        delete [] packet_info;
        ((CListBox*)GetDlgItem(IDC_LIST_PACKET))->AddString(strPacketInfo);
        return;
    }
    //输出IP首部主要内容
    if (protocol_type == PROTOCOL_IP)
    {
        static PIpHeader pip;
        pip.Reset(GetIpPointer(pkt_data));
        sprintf(Buffer, "      IP首部---版本号:%d 首部长度:%d IP数据报总长度:%d TTL:%d目的IP:%s 源IP:%s ",
                        pip.GetVesion(),pip.GetHeaderLen(),pip.GetTotalLen(), pip.GetTTL(),
                        pip.GetDstStr().c_str(),pip.GetSrcStr().c_str());
        total_info_ascii_str += Buffer;
        protocol_type = pip.GetProtocol();
        //输出TCP首部主要内容
        if (protocol_type == PROTOCOL_TCP)
        {
            static PTcpHeader ptcp;
            ptcp.Reset(GetTcpPointer(pkt_data));
            sprintf(Buffer, "      TCP首部---目的端口:%d 源端口:%d 确认号:%ud 序号:%ud SYN:%d ACK:%d 窗口大小:%d" ,
                            ptcp.GetDstPort(), ptcp.GetSrcPort(), ptcp.GetACKNum(),
                            ptcp.GetNum(), ptcp.GetSYN(), ptcp.GetACK(), ptcp.GetWinSize());
            total_info_ascii_str += Buffer;
        }
    }

    total_info_ascii_str += "      未知协议";
    DWORD dwNum = MultiByteToWideChar (CP_ACP, 0, total_info_ascii_str.c_str(), -1, NULL, 0);
    TCHAR* packet_info = new TCHAR[dwNum];
    MultiByteToWideChar(CP_ACP, 0, total_info_ascii_str.c_str(), -1, packet_info, dwNum);
    strPacketInfo.Format(_T("%s"), packet_info);
    delete [] packet_info;
    ((CListBox*)GetDlgItem(IDC_LIST_PACKET))->AddString(strPacketInfo);
    return;
}


UINT CPCDlgDlg::CatchPacket(LPVOID pParam)
{
    struct pcap_pkthdr *header;
    const u_char *pkt_data;
    int res;
    while ((res = pcap_next_ex((pcap_t*)pParam, &header, &pkt_data)) >= 0)
    {
        if (res == 0)
        {
            continue;
        }
        pDlgDlg->InsertPacketToList((pcap_t*)pParam, header, pkt_data);
        if (!pDlgDlg->isCatch)
        {
            AfxEndThread(1);
        }
    }
    if (res == -1)
    {

        return 1;
    }
    return 0;
}


void CPCDlgDlg::OnBnClickedButtonStop()
{
    // TODO: 在此添加控件通知处理程序代码
    if(isCatch)
    {
        isCatch = false;
    }   
}


void CPCDlgDlg::OnBnClickedButtonClean()
{
    // TODO: 在此添加控件通知处理程序代码
    ((CListBox*)GetDlgItem(IDC_LIST_PACKET))->ResetContent();
}

还有一些TCP,ARP的头文件分析,基本和mac ip的内容类似

你可能感兴趣的:(简单的网络数据包分析小程序)