网络抓包,协议分析,流量统计程序


// YQPackageCaptureDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "YQPackageCapture.h"
#include "YQPackageCaptureDlg.h"
#include "afxdialogex.h"
#include <pcap.h>
#include <vector>
#include <afxwin.h>
using namespace std;
#pragma warning(disable:4996)
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

/*_____________________________________________结构体_________________________________________*/
/* 4字节的IP地址 */
typedef struct ip_address
{
    u_char byte1;
    u_char byte2;
    u_char byte3;
    u_char byte4;
} ip_address;

/* IPv4 首部 */   //Internet Protocol version 4
typedef struct ip_header
{
    u_char  ver_ihl;        // 版本 (4 bits) + 首部长度 (4 bits)
    u_char  tos;            // 服务类型(Type of service)
    u_short tlen;           // 总长(Total length)
    u_short identification; // 标识(Identification)
    u_short flags_fo;       // 标志位(Flags) (3 bits) + 段偏移量(Fragment offset) (13 bits)
    u_char  ttl;            // 存活时间(Time to live)
    u_char  proto;          // 协议(Protocol)
    u_short crc;            // 首部校验和(Header checksum)
    ip_address  saddr;      // 源地址(Source address)
    ip_address  daddr;      // 目的地址(Destination address)
    u_int   op_pad;         // 选项与填充(Option + Padding)
} ip_header;

/* UDP 首部*/
/*UDP 是User Datagram Protocol的简称,
中文名是用户数据报协议,
是OSI(Open System Interconnection,开放式系统互联)参考模型中一种无连接的传输层协议*/
typedef struct udp_header
{
    u_short sport;          // 源端口(Source port)
    u_short dport;          // 目的端口(Destination port)
    u_short len;            // UDP数据包长度(Datagram length)
    u_short crc;            // 校验和(Checksum)
} udp_header;

/*TCP头部*/
typedef struct tcp_header
{
    short m_sSourPort;                // 源端口号16bit
    short m_sDestPort;      // 目的端口号16bit
    unsigned int m_uiSequNum;      // 序列号32bit
    unsigned int m_uiAcknowledgeNum;  // 确认号32bit
    short m_sHeaderLenAndFlag;     // 前4位:TCP头长度;中6位:保留;后6位:标志位
    short m_sWindowSize;    // 窗口大小16bit
    short m_sCheckSum;       // 检验和16bit
    short m_surgentPointer;     // 紧急数据偏移量16bit
}tcp_header;

typedef struct ip_flow
{
    ip_address  ipaddr;      // 源地址(Source address)
    float flow;             //该源地址的流量
}ip_flow;

typedef struct package_info
{
    u_char *package;      // 源地址(Source address)
    short len;             //该源地址的流量
}package_info;

/*_____________________________________________全局变量_________________________________________*/

int no = 0;
LARGE_INTEGER m_nFreq;         //内部计时器的时钟周期,用于计时
LARGE_INTEGER m_nBeginTime;    //开始捕获时,计时器的值,用于计时
vector<package_info> package_vec;
vector<ip_flow>ip_flow_vec;
CListCtrl CYQPackageCaptureDlg::list_package;
CListCtrl CYQPackageCaptureDlg::list_flow;
pcap_t *adhandle; //网卡句柄
pcap_if_t *alldevs;
pcap_if_t *d;
int stopNow=0;  //是否现在要停止捕获

/*______________________________ 回调函数原型 ______________________________________________*/
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);

// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
    CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_ABOUTBOX };
#endif

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
    DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()

// CYQPackageCaptureDlg 对话框

CYQPackageCaptureDlg::CYQPackageCaptureDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_YQPACKAGECAPTURE_DIALOG, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CYQPackageCaptureDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_COMBO_ADAPTER, com_adapter);
    DDX_Control(pDX, IDC_LIST_PACKAGES, list_package);
    DDX_Control(pDX, IDC_LIST_FLOW, list_flow);
}

BEGIN_MESSAGE_MAP(CYQPackageCaptureDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_BUTTON_START_CAP, &CYQPackageCaptureDlg::OnBnClickedButtonStartCap)
    ON_CBN_SELCHANGE(IDC_COMBO_ADAPTER, &CYQPackageCaptureDlg::OnCbnSelchangeComboAdapter)
    ON_EN_CHANGE(IDC_EDIT_DESCRIPTION, &CYQPackageCaptureDlg::OnEnChangeEditDescription)
    ON_BN_CLICKED(IDC_BUTTON_STOP_CAP, &CYQPackageCaptureDlg::OnBnClickedButtonStopCap)
    ON_EN_CHANGE(IDC_EDIT_ASCII, &CYQPackageCaptureDlg::OnEnChangeEditAscii)
    ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_PACKAGES, &CYQPackageCaptureDlg::OnLvnItemchangedListPackages)
END_MESSAGE_MAP()

// CYQPackageCaptureDlg 消息处理程序

BOOL CYQPackageCaptureDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // 将“关于...”菜单项添加到系统菜单中。

    // IDM_ABOUTBOX 必须在系统命令范围内。
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        BOOL bNameValid;
        CString strAboutMenu;
        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
        ASSERT(bNameValid);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
    //  执行此操作
    SetIcon(m_hIcon, TRUE);         // 设置大图标
    SetIcon(m_hIcon, FALSE);        // 设置小图标

    // TODO: 在此添加额外的初始化代码
    /***________________________显示可选的网卡__________________________***/
    //pcap_if_t *alldevs;
    //pcap_if_t *d;
    int inum;
    int adapter_counter = 0;           //网卡数目
    //pcap_t *adhandle; //网卡句柄
    char errbuf[PCAP_ERRBUF_SIZE];
    u_int netmask;
    char packet_filter[] = "ip and tcp or udp";   //程序最终可以得到IPV4,udp和tcp的数据包,并把它们复制给应用程序
    struct bpf_program fcode;   //伯克利封包过滤器(Berkeley Packet Filter,缩写 BPF)
                                //printf("%d\n", sizeof(u_char));
                                /* 获得设备列表 */
    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
    {
        fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
        exit(1);
    }

    /* 显示网卡 */
     //为组合框控件的列表框添加列表项
    for (d = alldevs; d; d = d->next)
    {
        CString name(d->name);
        com_adapter.InsertString(adapter_counter++, name);
        //adapter_counter++;
    }

    if (adapter_counter == 0)
    {
        AfxMessageBox(L"\nNo interfaces found! Make sure WinPcap is installed.\n");
        return -1;
    }
    // 默认选择第一项
    com_adapter.SetCurSel(0);

    /* 跳转到已选设备 */
    inum = com_adapter.GetCurSel();
    int i;
    for (d = alldevs, i = 0; i< inum - 1; d = d->next, i++);
    //显示网卡描述
    CString description_str(d->description);
    SetDlgItemText(IDC_EDIT_DESCRIPTION, description_str);
    ///* 释放设备列表 */
    //pcap_freealldevs(alldevs);

    /*____________显示control list package 的基本信息_______________________*/
    CRect rect;
    list_package.GetClientRect(&rect);   //获得客户区
    list_package.SetExtendedStyle(list_package.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);         //设置风格,LVS_EX_FULLROWSELECT是有线条,后面那个是充满
                                                                                                          //插入列:
    list_package.InsertColumn(0, _T("NO."), LVCFMT_CENTER, rect.Width() /14, 0);
    list_package.InsertColumn(1, _T("Time"), LVCFMT_CENTER, rect.Width() / 7, 1);
    list_package.InsertColumn(2, _T("Source"), LVCFMT_CENTER, rect.Width() / 7, 2);
    list_package.InsertColumn(3, _T("Destination"), LVCFMT_CENTER, rect.Width() / 7, 3);
    list_package.InsertColumn(4, _T("Protocol"), LVCFMT_CENTER, rect.Width() /14, 4);
    list_package.InsertColumn(5, _T("Length"), LVCFMT_CENTER, rect.Width() / 14, 5);
    list_package.InsertColumn(6, _T("Info"), LVCFMT_CENTER, 5*rect.Width() /14, 6);

    list_flow.GetClientRect(&rect);   //获得客户区
    list_flow.SetExtendedStyle(list_package.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);         //设置风格,LVS_EX_FULLROWSELECT是有线条,后面那个是充满
                                                                                                                      //插入列:
    list_flow.InsertColumn(0, _T("源IP地址"), LVCFMT_CENTER, rect.Width() / 2, 0);
    list_flow.InsertColumn(1, _T("流量"), LVCFMT_CENTER, rect.Width() / 2, 1);

    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CYQPackageCaptureDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialogEx::OnSysCommand(nID, lParam);
    }
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CYQPackageCaptureDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // 用于绘制的设备上下文

        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // 使图标在工作区矩形中居中
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // 绘制图标
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialogEx::OnPaint();
    }
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CYQPackageCaptureDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}

/*开始捕获按钮*/
void CYQPackageCaptureDlg::OnBnClickedButtonStartCap()
{
    // TODO: 在此添加控件通知处理程序代码
    //pcap_if_t *alldevs;
    //pcap_if_t *d;
    int inum;
    int adapter_counter = 0;

    char errbuf[PCAP_ERRBUF_SIZE];
    u_int netmask;
    char packet_filter[] = "ip and tcp or udp";   //程序最终可以得到IPV4,udp和tcp的数据包,并把它们复制给应用程序
    struct bpf_program fcode;   //伯克利封包过滤器(Berkeley Packet Filter,缩写 BPF)
                                //printf("%d\n", sizeof(u_char));

    /* 跳转到已选设备 */
    inum= com_adapter.GetCurSel();
    int i;
    for (d = alldevs, i = 0; i< inum - 1; d = d->next, i++);

    /* 打开适配器 */
    if ((adhandle = pcap_open(d->name,  // 设备名
        65536,     // 要捕捉的数据包的部分
                   // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容
        PCAP_OPENFLAG_PROMISCUOUS,         // 混杂模式
        1000,      // 读取超时时间
        NULL,      // 远程机器验证
        errbuf     // 错误缓冲池
        )) == NULL)
    {
        AfxMessageBox(L"\nUnable to open the adapter. %s is not supported by WinPcap\n");
        fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
        return ;
    }

    /* 检查数据链路层,为了简单,我们只考虑以太网 */
    /*返回链路层的类型,链路层的类型包括:
    DLT_NULL: BSD回路封装;链路层协议头是一个4字节的域,……
    DLT_EN10MB: 以太网(10Mb, 100Mb, 1000Mb, 或者更高)。
    DLT_IEEE802: IEEE802.5令牌环网。
    ……
    */
    if (pcap_datalink(adhandle) != DLT_EN10MB) //如果不是以太网就不处理了
    {
        AfxMessageBox(L"\nThis program works only on Ethernet networks.\n");
        fprintf(stderr, "\nThis program works only on Ethernet networks.\n");
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
        return ;
    }

    /*类型        格式          默认子网掩码
         A   网络 节点 节点 节点  255.0.0.0
              B   网络 网络 节点 节点  255.255.0.0
                   C   网络 网络 网络 节点  255.255.255.0*/
    if (d->addresses != NULL)
        /* 获得接口第一个地址的掩码 */
        netmask = ((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
    else
        /* 如果接口没有地址,那么我们假设一个C类的掩码 */
        netmask = 0xffffff;

    //编译过滤器pcap_compile
    if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0)
    {
        AfxMessageBox(L"\nUnable to compile the packet filter. Check the syntax.\n");
        fprintf(stderr, "\nUnable to compile the packet filter. Check the syntax.\n");
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
        getchar();
        return ;
    }

    //设置过滤器pcap_setfilter
    if (pcap_setfilter(adhandle, &fcode)<0)
    {
        AfxMessageBox(L"\nError setting the filter.\n");
        fprintf(stderr, "\nError setting the filter.\n");
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
        getchar();
        return ;
    }

    printf("\nlistening on %s...\n", d->description);

    /* 释放设备列表 */
    pcap_freealldevs(alldevs);

    /* 开始捕捉并计时 */
    QueryPerformanceFrequency(&m_nFreq); // 获取时钟周期
    QueryPerformanceCounter(&m_nBeginTime);//获取开始捕获时,计时器的值

    pcap_loop(adhandle, 0, packet_handler, NULL);

}

void CYQPackageCaptureDlg::OnCbnSelchangeComboAdapter()
{
    // TODO: 在此添加控件通知处理程序代码
    /* 跳转到已选设备 */
    int inum = com_adapter.GetCurSel();
    int i;
    for (d = alldevs, i = 0; i< inum - 1; d = d->next, i++);
    //显示网卡描述
    CString description_str(d->description);
    SetDlgItemText(IDC_EDIT_DESCRIPTION, description_str);
    //SetDlgItemText(IDC_EDIT_DESCRIPTION, L"change my friend!!");

}

/****************************回调函数***********************************/
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
    //NO.   Time   Source   Destination     Protocol     Length     Info   十六进制   ASCII码   流量统计
    //AfxMessageBox(L"抓到包了!");
    struct tm ltime;
    char timestr[16];
    ip_header *ih;
    udp_header *uh;
    tcp_header *th;
    u_int ip_len;
    time_t local_tv_sec;
    struct timeval tv_capPackage;

    /* 获得IP数据包头部的位置 */
    /*因为我们需要解析IP数据包,
    从IP数据包的首部解析到源IP地址和目的IP地址,
    而IP数据包的首部位于MAC首部的后面,所以我们需要跳过MAC首部。
    对于以太网而言MAC首部长度为14位*/

    ih = (ip_header *)(pkt_data +
        14); //以太网头部长度 固定14位
    ip_len = (ih->ver_ihl & 0xf) * 4;   //ip首部有多少字节(取低四位,得到首部有多少个双字;乘4得到字节数)

    /***************           显示每个包的PCI   ****************************************/
    CString noStr;
    noStr.Format(_T("%d"), no+1);

    ////插入该包数据,第0列(no)内容为1
    CYQPackageCaptureDlg::list_package.InsertItem(no, noStr);

    //Time
    LARGE_INTEGER m_nTime;
    QueryPerformanceCounter(&m_nTime);//获取当前时间
    long long sec, next, time;   //从开始捕获,到捕获到当前包,时间差的秒,及其剩下的0.1秒;整个以微妙表示
    time = (m_nTime.QuadPart - m_nBeginTime.QuadPart) * 1000000 / m_nFreq.QuadPart;
    sec = time / 1000000;
    next = time - time / 1000000 * 1000000;
    //printf("Time:%lld.%.6lld \n", sec, next);
    CString timeStr;
    timeStr.Format(_T("%lld.%.6lld \n"), sec, next);
    //设置该包第1列(time)内容
    CYQPackageCaptureDlg::list_package.SetItemText(no , 1,timeStr);

    //Source

    CString sourceStr;
    sourceStr.Format(_T("%d.%d.%d.%d\n"),
        ih->saddr.byte1,
        ih->saddr.byte2,
        ih->saddr.byte3,
        ih->saddr.byte4);
    //设置该包第2列(source)内容
    CYQPackageCaptureDlg::list_package.SetItemText(no, 2,sourceStr);

    //Destination

    CString desStr;
    desStr.Format(_T("%d.%d.%d.%d\n"),
        ih->daddr.byte1,
        ih->daddr.byte2,
        ih->daddr.byte3,
        ih->daddr.byte4);
    //设置该包第3列(Destination)内容
    CYQPackageCaptureDlg::list_package.SetItemText(no, 3, desStr);

    //Protocol
    /*协议字段:占8比特。指明IP层所封装的上层协议类型,
    如ICMP(1)、IGMP(2) 、TCP(6)、UDP(17)、EIGRP(88)、OSPF(89)等。*/
    CString protocolStr = NULL;
    CString Str;

    switch (ih->proto)
    {
    case 1:protocolStr = "ICMP";  break;
    case 2:protocolStr = "IGMP";  break;
    case 6:protocolStr = "TCP";  break;
    case 17:protocolStr = "UDP"; break;
    case 20:protocolStr = "HMP";  break;
    case 88:protocolStr = "EIGRP";  break;
    case 89:protocolStr = "OSPF";  break;
    default: protocolStr.Format(_T("%d", ih->proto));
    }
    CYQPackageCaptureDlg::list_package.SetItemText(no, 4,protocolStr);
    //printf("Protocol:%s\n", protocol);

    //Length
    CString lenStr;
    int wholeLen = ntohs(ih->tlen) + 14;  //将网络字节序列转换成主机字节序列,加上以太网包头的长度
    lenStr.Format(_T("%d"), wholeLen);
    CYQPackageCaptureDlg::list_package.SetItemText(no, 5, lenStr);

    //Info
    CString infoStr;
    //UDP
    //printf("Info:\n");
    if (protocolStr == "UDP")
    {
        /* 获得UDP首部的位置 */

        uh = (udp_header *)((u_char*)ih + ip_len);
        infoStr.Format(_T("%d -> %d, Len=%d\n\n"), ntohs(uh->sport), ntohs(uh->dport), ntohs(uh->len));
    }
    else if (protocolStr == "TCP")
    {
        /* 获得TCP首部的位置 */
        th = (tcp_header *)((u_char*)ih + ip_len);
        infoStr.Format(_T("%d -> %d, Seq=%u, Ack=%u, Win=%d "),
            ntohs(th->m_sSourPort),
            ntohs(th->m_sDestPort),
            ntohl(th->m_uiSequNum),
            ntohl(th->m_uiAcknowledgeNum),
            ntohs(th->m_sWindowSize)
            );
    }
    CYQPackageCaptureDlg::list_package.SetItemText(no, 6, infoStr);

    int list_item_count = CYQPackageCaptureDlg::list_package.GetItemCount();
    if (list_item_count   >   0)
        CYQPackageCaptureDlg::list_package.EnsureVisible(list_item_count - 1, FALSE);

    //十六进制
    CString hexStr,tempStr;
    u_char *temp = (u_char *)pkt_data;
    for (int i = 0; i < wholeLen; i++)
    {
        tempStr.Format(_T("%x "), *(temp++));
        hexStr += tempStr;
    }
    SetDlgItemText(AfxGetMainWnd()->m_hWnd,IDC_EDIT_HEX,hexStr);

    //ASCII码
    CString asciiStr;
    temp = (u_char *)pkt_data;
    for (int i = 0; i < wholeLen; i++)
    {
        tempStr.Format(_T("%c "), *(temp++));
        asciiStr += tempStr;
    }
    SetDlgItemText(AfxGetMainWnd()->m_hWnd, IDC_EDIT_ASCII, asciiStr);

    //统计流量:
    int ip_count = size(ip_flow_vec);   //已经统计过的ip源地址
    int isNew = 1;    //之前没出现过该ip源地址
    ip_flow new_ip_flow;
    CString flowStr;
    for (int i = 0; i < ip_count; i++)
    {
        //如果该ip地址已经出现过
        if (ih->saddr.byte1 == ip_flow_vec[i].ipaddr.byte1
            &&ih->saddr.byte2 == ip_flow_vec[i].ipaddr.byte2
            &&ih->saddr.byte3 == ip_flow_vec[i].ipaddr.byte3
            &&ih->saddr.byte4 == ip_flow_vec[i].ipaddr.byte4)
        {
            ip_flow_vec[i].flow += (double)wholeLen / 1024;  //单位为KB
            isNew = 0;

            flowStr.Format(_T("%.2f KB"), ip_flow_vec[i].flow);
            CYQPackageCaptureDlg::list_flow.SetItemText(i, 1, flowStr);
            break;
        }
    }
    //如果该ip地址此前没有出现过
    if (isNew == 1)
    {
        new_ip_flow.ipaddr = ih->saddr;
        new_ip_flow.flow = (double)wholeLen / 1024;

        ip_flow_vec.push_back(new_ip_flow);
        flowStr.Format(_T("%.2f KB"),new_ip_flow.flow);
        //插入该IP地址,显示ip地址
        CYQPackageCaptureDlg::list_flow.InsertItem(ip_count, sourceStr);
        //显示流量
        CYQPackageCaptureDlg::list_flow.SetItemText(ip_count, 1, flowStr);
    }
    list_item_count = CYQPackageCaptureDlg::list_flow.GetItemCount();
    if (list_item_count   >   0)
        CYQPackageCaptureDlg::list_flow.EnsureVisible(list_item_count - 1, FALSE);

    /*把包的内容存入package_vec*/
    temp = (u_char *)pkt_data;
    package_info new_package_info;
    new_package_info.package = temp;
    new_package_info.len = wholeLen;
    package_vec.push_back(new_package_info);

    //包的个数+1
    no++;
    //实时显示
    UpdateWindow(AfxGetMainWnd()->m_hWnd);
    //CString mess;
    //mess.Format(_T("%d"), adhandle);
    //AfxMessageBox(mess);

    //判断是否停止
    AfxGetApp()->PumpMessage();
    if (stopNow == 1)
    {
        pcap_breakloop(adhandle);  ///right here ahandle turned into 0
    }
}

void CYQPackageCaptureDlg::OnEnChangeEditDescription()
{
    // TODO:  如果该控件是 RICHEDIT 控件,它将不
    // 发送此通知,除非重写 CDialogEx::OnInitDialog()
    // 函数并调用 CRichEditCtrl().SetEventMask(),
    // 同时将 ENM_CHANGE 标志“或”运算到掩码中。

    // TODO:  在此添加控件通知处理程序代码
}

void CYQPackageCaptureDlg::OnBnClickedButtonStopCap()
{
    // TODO: 在此添加控件通知处理程序代码
    stopNow = 1;

}

void CYQPackageCaptureDlg::OnEnChangeEditAscii()
{
    // TODO:  如果该控件是 RICHEDIT 控件,它将不
    // 发送此通知,除非重写 CDialogEx::OnInitDialog()
    // 函数并调用 CRichEditCtrl().SetEventMask(),
    // 同时将 ENM_CHANGE 标志“或”运算到掩码中。

    // TODO:  在此添加控件通知处理程序代码
}

void CYQPackageCaptureDlg::OnLvnItemchangedListPackages(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    NMLISTVIEW *pnml = (NMLISTVIEW*)pNMHDR;//新建一个指针
    if (-1 != pnml->iItem)//如果指针无误
    {
        CString pac_no_str;
        int pac_no;
        pac_no_str = list_package.GetItemText(pnml->iItem, 0);//如果鼠标选中了某行,将选中的行的第0列赋给str
        pac_no = _ttoi(pac_no_str)-1;

        CString hexStr, tempStr;
        u_char *temp = (u_char *)package_vec[pac_no].package;
        for (int i = 0; i < package_vec[pac_no].len; i++)
        {
            tempStr.Format(_T("%x "), *(temp++));
            hexStr += tempStr;
        }
        //CString len;
        //len.Format(_T("%d"), wholeLen);
        //AfxMessageBox(len);
        //SetDlgItemText(IDC_EDIT_HEX, L"exm");
        SetDlgItemText(IDC_EDIT_HEX, hexStr);

        //ASCII码
        CString asciiStr;
        temp = (u_char *)package_vec[pac_no].package;
        for (int i = 0; i < package_vec[pac_no].len; i++)
        {
            tempStr.Format(_T("%c "), *(temp++));
            asciiStr += tempStr;
        }
        //SetDlgItemText(IDC_EDIT_ASCII, L"exm");
        SetDlgItemText(IDC_EDIT_ASCII, asciiStr);

    }

    *pResult = 0;
}

原文地址:https://www.cnblogs.com/YuQiao0303/p/8886172.html

时间: 2024-10-13 17:23:26

网络抓包,协议分析,流量统计程序的相关文章

shell脚本实现网络扫描 自动抓包 协议分析 nmap

此文章提供思想基础用法:关于自动检测功能,各个端口和抓包功能,项目中使用的为nmap软件,Linux操作系统,首先我们要安装nmap的软件 项目中使用的为nmap-6.40-7.el7.x86_64版本, 命令格式为:  #nmap  [扫描类型]  [选项]  <目标主机> 扫描类型: -sS (TCP  SYN扫描半开) -sT(TCP 连接扫描全开) -sU  (UDP扫描) -sP    (ICMP扫描) -A     //对目标主机做全面分析 选项       : -n     //

WinPcap网络抓包分析程序--总结

应付大作业写的一个程序,先给出程序的运行界面 程序的核心内容是抓包然后分析数据,我做的最多的也是协议分析这块内容.上面首先给出的是当前网络的上传下载速度,这块内容我是参考Windows性能计数器来写的,就是PDH,直接获取相应的接口, 获取数据,这块内容直接放出代码 1 #include <Pdh.h> 2 #include <list> 3 #pragma comment(lib, "Pdh.lib") 4 5 class NetWorkSpeed 6 { 7

python编写网络抓包分析脚本

python编写网络抓包分析脚本 写网络抓包分析脚本,一个称手的sniffer工具是必不可少的,我习惯用Ethereal,简单,易用,基于winpcap的一个开源的软件 Ethereal自带许多协议的 decoder,但是它的架构并不灵活,如果你要加入一个自己定义的的解码器,得去修改Ethereal的代码,再重新编译,相当的烦琐 对于一般的明文协议,没有什么问题,但是对于加密协议,比如网络游戏,客户端程序一般会在刚连接上的时候,发送一个随机密钥,而后的报文都会用这个密钥进 行加密,诸如此类.要想

浅谈使用tcpdump、wireshark对Android应用程序进行抓包并分析

本文主要介绍如何使用tcpdump和wireshark对Android应用程序进行抓包并分析,需要说明的是在抓包之前,你的Android设备必须root过了,另外你的电脑必须有Android SDK环境. 下载并安装tcpdump tcpdump链接:http://www.ijiami.cn/ 选择一个版本下载并解压提取出其中呃tcpdump文件,然后push到你的手机上去: adb push c:\tcpdump /data/local/tcpdump 进一步操作: adb shell su

工欲善其事,必先利其器 – 网络抓包

抓包(packet capture)就是将网络传输发送与接收的数据包进行截获.分析,甚至可以用来转发,重传等等,抓包可使用的场景很多,排错.验证.测试.核对等,我就举几个例子来说明吧. 场景一.在一台存储上启用了SNMP服务,随后想通过验证UDP161/162的侦听状态来确认服务是否确实启动了. 详情:最简单的方式就是用进入存储的OS运行类似netstat –anop查看UDP端口状态,还有些同学会条件反射的说telnet一下呗或者用nmap的工具做端口扫描,但是最后发现结果是Open | Fi

对几款网络抓包工具的评测

对几款网络抓包工具的评测 by 拉登哥哥 最近在写个CMD远控 写着写着 想在服务端上做点手脚 都知道杀软误报 特别是黑软大部分都报毒 但实际上是正常的 对此可能部分人并不装杀软 基本上靠自己分析软件是否安全 1 低级点的 用相关工具 检测不能真的完全保证程序无毒  也没啥技术含量 原因是 可能你正在检测时 后门没激活(比如 我设置晚上12点才向外连接等) 你在白天或其它时间检测我的工具 可能没发现任何异常 晚上你开工具做事的时候 后门也跟着激活了 哈哈 这方法 实际中还真有人这么看 以前某个木

网络抓包wireshark(转)

转自 网络抓包wireshark 抓包应该是每个技术人员掌握的基础知识,无论是技术支持运维人员或者是研发,多少都会遇到要抓包的情况,用过的抓包工具有fiddle.wireshark,作为一个不是经常要抓包的人员,学会用Wireshark就够了,毕竟它是功能最全面使用者最多的抓包工具. Wireshark(前称Ethereal)是一个网络封包分析软件.网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料.Wireshark使用WinPCAP作为接口,直接与网卡进行数据报文交换

CatchPacket网络抓包软件

CatchPacket网络抓包软件  qq  22945088431.技术特点:基于WinPcap库,c# winform2.实现获取机器所有网卡,可任意选择监听3.可以捕获常见网络协议arp dns http icmp igmp ftp pop3 smtp telnet udp tcp dhcp4.抓取数据包的信息内容,安装网络层,结构化展现数据信息5.16进制数据内容解析6.数据保存,方便下次分析7.网络数据统计,方便分析8.提供一些常见的网络协议测试工具 技术特点:基于WinPcap库,c

网络抓包工具-Wireshark学习资料

wireshark一个非常牛逼的网络抓包工具.转载一系列博文 一站式学习Wireshark(一):Wireshark基本用法 一站式学习Wireshark(二):应用Wireshark观察基本网络协议 一站式学习Wireshark(三):应用Wireshark IO图形工具分析数据流 一站式学习Wireshark(四):网络性能排查之TCP重传与重复ACK 一站式学习Wireshark(五):TCP窗口与拥塞处理 一站式学习Wireshark(六):狙击网络高延时点 一站式学习Wireshark

iOS系统设备网络抓包工具介绍:越狱和不越狱的办法

对终端进行抓包是客户端测试中的一种重要手段.本文主要介绍了ios设备(iphone.ipad和ipodtouch)的几种常用的抓包方法. 一.准备条件 需要进行抓包的设备必须经过root,俗称越狱,主要利用redsn0w和各种iOSFirmwares进行,如越狱不用更换固件版本,只需使用 redsn0w安装Cydia即可,网上有详细教程,此处省略.安装完毕,在3G或WiFi环境下启动Cydia,确认身份为“开发者”,如下图. 通过Cydia源,用户可以下载和安装比appstore更高权限的软件,