小巧玲珑的网络抓包

2023-10-18 10:48
文章标签 网络 抓包 小巧玲珑

本文主要是介绍小巧玲珑的网络抓包,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

#include <Winsock2.h>
#include <mstcpip.h>

#pragma comment(lib,"WS2_32.lib")

typedef struct _iphdr
{
    unsigned char h_lenver;        //4位首部长度+4位IP版本号
    unsigned char tos;            //8位服务类型TOS
    unsigned short total_len;    //16位总长度(字节)
    unsigned short ident;        //16位标识
    unsigned short frag_and_flags; //3位标志位
    unsigned char ttl;            //8位生存时间 TTL
    unsigned char proto;        //8位协议 (TCP, UDP 或其他)
    unsigned short checksum;    //16位IP首部校验和
    unsigned int sourceIP;        //32位源IP地址
    unsigned int destIP;        //32位目的IP地址
}IP_HEADER; 

typedef struct _tcphdr        //定义TCP首部
{
    USHORT th_sport;        //16位源端口
    USHORT th_dport;        //16位目的端口
    unsigned int th_seq;
    unsigned int th_ack;
    unsigned char th_lenres;//4位首部长度/6位保留字
    unsigned char th_flag;    //6位标志位
    USHORT th_win;            //16位窗口大小
    USHORT th_sum;            //16位校验和
    USHORT th_urp;            //16位紧急数据偏移量
}TCP_HEADER;

typedef struct _udphdr        //定义UDP首部

    unsigned short uh_sport;
    unsigned short uh_dport;
    unsigned short uh_len;
    unsigned short uh_sum;
} UDP_HEADER; 

typedef struct _icmphdr        //定义ICMP首部

    BYTE i_type;            //8位类型
    BYTE i_code;            //8位代码
    USHORT i_cksum;            //16位校验和
    USHORT i_id;            //识别号(一般用进程号作为识别号)
    USHORT i_seq;            //报文序列号
    ULONG timestamp;        //时间戳
}ICMP_HEADER;

bool DecodeIpPack(const char *,int);    // IP 解包
bool DecodeTcpPack(const char *);        // TCP 解包
bool DecodeUdpPack(const char *);        // UDP 解包
bool DecodeIcmpPack(const char *);        // ICMP 解包
const char * CheckProtocol(int);// 查询协议

int _tmain(int argc, _TCHAR* argv[])
{
    // 初始化SOCKET
    WSADATA wsaData;
    int iErrorCode = ::WSAStartup( MAKEWORD(2,1), &wsaData );
    if( SOCKET_ERROR == iErrorCode )
    {
        printf( "WSAStartup() error. " );
        return -1;
    }
   
    SOCKET sock = ::socket( AF_INET, SOCK_RAW, IPPROTO_IP );
    if( INVALID_SOCKET == sock )
    {
        printf( "socket() error. " );
        return -1;
    }

    //获取本机IP地址
    char szHostName[200];
    iErrorCode = ::gethostname( szHostName, sizeof(szHostName) );
    if( SOCKET_ERROR == iErrorCode )
    {
        printf( "gethostname() error. " );
        return -1;
    }

    PHOSTENT pHostent = ::gethostbyname( szHostName );
    if( NULL == pHostent )
    {
        printf( "gethostbyname() error. " );
        return -1;
    }

    SOCKADDR_IN sa;
    sa.sin_family = AF_INET;
    memcpy( &sa.sin_addr.S_un.S_addr, pHostent->h_addr_list[0], pHostent->h_length );
    sa.sin_port = htons( 60000 );

    iErrorCode = ::bind( sock, (PSOCKADDR)&sa, sizeof(sa) );
    if( SOCKET_ERROR == iErrorCode )
    {
        printf( "bind() error. " );
        return -1;
    }

    // 设置 SOCK_RAW 为 SIO_RCVALL,接收所有的 IP 包
    DWORD dwBufferLen[10];
    DWORD dwBufferInLen = 1;
    DWORD dwBytesReturned = 0;
    iErrorCode = ::WSAIoctl( sock, SIO_RCVALL, &dwBufferInLen, sizeof(dwBufferInLen), &dwBufferLen,
        sizeof( dwBufferLen ), &dwBytesReturned, NULL, NULL );
    if( SOCKET_ERROR == iErrorCode )
    {
        printf( "Ioctl() error. " );
        return -1;
    }

    //侦听IP报文
    while( 1 )
    {
        char package[8 * 1024] = { 0 };    // 数据缓冲区
        iErrorCode = ::recv( sock, package, sizeof(package), 0 );
        if( SOCKET_ERROR == iErrorCode )
                printf( "recv() error. " );
        else if( !DecodeIpPack( package, iErrorCode ) )    // 解析 IP 包
                printf( "DecodeIpPack() error. " );
    }

    // ::Closesocket( sock );
    // ::WSACleanup();
    return 0;

// 解析 IP 包
bool DecodeIpPack(const char *buf, int iBufSize)
{
    IP_HEADER *pIpheader;
    int iProtocol, iTTL;
    char szProtocol[12];
    char szSourceIP[16];
    char szDestIP[16];
    SOCKADDR_IN saSource, saDest;
    pIpheader = (IP_HEADER *)buf;

    //Check Proto 
    iProtocol = pIpheader->proto;
    ::strcpy( szProtocol, CheckProtocol(iProtocol) );

    //Check Source IP
    saSource.sin_addr.s_addr = pIpheader->sourceIP;
    ::strcpy( szSourceIP, inet_ntoa(saSource.sin_addr) );

    //Check Dest IP
    saDest.sin_addr.s_addr = pIpheader->destIP;
    ::strcpy( szDestIP, inet_ntoa(saDest.sin_addr) );
    iTTL = pIpheader->ttl;

    //Output 
    printf( "%s ", szProtocol );
    printf( "%s->%s ", szSourceIP, szDestIP );
    printf( "bytes=%d TTL=%d ",iBufSize,iTTL );

    //Calculate IP Header Length
    int iIphLen = sizeof(unsigned long) * ( pIpheader->h_lenver & 0x0f );

    //Decode Sub Protocol:TCP, UDP, ICMP, etc
    switch( iProtocol )
    { 
    case IPPROTO_TCP:    DecodeTcpPack( buf + iIphLen );        break;
    case IPPROTO_UDP:    DecodeUdpPack( buf + iIphLen );        break;
    case IPPROTO_ICMP:    DecodeIcmpPack( buf + iIphLen );    break;
    default:    break;
    }
    printf( " " );

    int col = 0;
    char ascii[17];
    for( int i=0; i<iBufSize; i++ )
    {
        printf( "%02X ", (unsigned char)buf[i] );

        ascii[ col++ ] = ( unsigned char )buf[i] < 0x20 ? '.' : buf[i];

        if( 15 == i%16 )
        {
            ascii[ col ] = 0;
            printf( "%s ", ascii );
            col = 0;
        }
        else if( 7 == i%8 )    printf( "- " );
    }
    if( col )
    {
        for( int i=col; i<16; i++ )
        {
            printf( "   " );
            if( 15 == i%16 )
            {
                ascii[ col ] = 0;
                printf( "%s ", ascii );
            }
            else if( 7 == i%8 )    printf( "- " );
        }
    }

    return true; 

//协议识别程序
const char * CheckProtocol(int iProtocol)

    typedef struct _protomap    //定义子协议映射表 
    { 
        int ProtoNum;
        char ProtoText[12];
    }PROTOMAP;

    static PROTOMAP ProtoMap[]={    //为子协议映射表赋值 
    { IPPROTO_IP,    "IP"    },
    { IPPROTO_ICMP,    "ICMP"    },
    { IPPROTO_IGMP,    "IGMP"    },
    { IPPROTO_GGP,    "GGP"    },
    { IPPROTO_IPV4,    "IPV4"    },
    { IPPROTO_TCP,    "TCP"    },
    { IPPROTO_PUP,    "PUP"    },
    { IPPROTO_UDP,    "UDP"    },
    { IPPROTO_IDP,    "IDP"    },
    { IPPROTO_IPV6, "IPV6"    },
    { IPPROTO_ROUTING,    "ROUTING"    },
    { IPPROTO_FRAGMENT,    "FRAGMENT"    },
    { IPPROTO_ESP,    "ESP"    },
    { IPPROTO_AH,    "AH"    },
    { IPPROTO_ICMPV6,    "ICMPV6"    },
    { IPPROTO_NONE,    "NONE"    },
    { IPPROTO_DSTOPTS,    "DSTOPTS"    },
    { IPPROTO_ND,    "ND"    },
    { IPPROTO_ICLFXBM,    "ICLFXBM"    },
    { IPPROTO_RAW,    "RAW"    },
    { IPPROTO_MAX,    "MAX"    },
    };
   
    const int nProtoCount = sizeof(ProtoMap)/sizeof(PROTOMAP);

    for(int i=0; i<nProtoCount; i++)
    {
        if(ProtoMap[i].ProtoNum==iProtocol)
            return ProtoMap[i].ProtoText;
    }
    return ""; 

//TCP解包程序 
bool DecodeTcpPack(const char * TcpBuf)

    TCP_HEADER * pTcpHeader;
    int i;
    pTcpHeader = (TCP_HEADER * )TcpBuf;
    printf("Port:%d->%d ", ntohs(pTcpHeader->th_sport),ntohs(pTcpHeader->th_dport));
    unsigned char FlagMask = 1;
    for( i=0; i<6; i++ )
    {
        static char * TcpFlag = "FSRPAU";     //定义TCP标志位 
        if( ( pTcpHeader->th_flag ) & FlagMask )
                printf( "%c", TcpFlag[i] );
        else    printf( "-" );

        FlagMask = FlagMask << 1;
    } 
    return true; 

//UDP解包程序 
bool DecodeUdpPack(const char * UdpBuf)

    UDP_HEADER *pUdpHeader;
    pUdpHeader = (UDP_HEADER * )UdpBuf;
    printf("Port:%d->%d ", ntohs(pUdpHeader->uh_sport), ntohs(pUdpHeader->uh_dport));
    printf("Len=%d", ntohs(pUdpHeader->uh_len));
    return true;

//ICMP解包程序 
bool DecodeIcmpPack(const char * IcmpBuf)

    ICMP_HEADER *pIcmpHeader;
    pIcmpHeader = (ICMP_HEADER * )IcmpBuf;
    printf("Type:%d,%d ", pIcmpHeader->i_type,pIcmpHeader->i_code);
    printf("ID=%d SEQ=%d", pIcmpHeader->i_id, pIcmpHeader->i_seq);
    return true;
}

评论
# re: 小巧玲珑的网络抓包
周星星
Posted @ 2006-11-01 13:42
60000端口是什么呀?
假如我想抓所有端口的原始数据包该怎么做?
# **,60000是自己的端口,但RAW下,它能抓任意端口的数据包
老梆菜
Posted @ 2006-11-01 13:45
你运行看看啦
# re: 小巧玲珑的网络抓包
周星星
Posted @ 2006-11-01 15:41
由于格式转化的原因,有部分空格没能粘贴出来,导致界面混乱,这是blog的问题。

8 * 1024 不是固定的,可否直接获得?

我有一点疑惑,既然这些数据被你截获了,为什么却不影响正常通讯?
# to **
老梆菜
Posted @ 2006-11-01 20:27
8*1024是随便定的,当然可以先读IP头,从IP头中的 total_len 得到真实的长度,raw socket 是内部方法,它直接读写网卡,因此不影响正常程序的正常通讯
# re: 小巧玲珑的网络抓包
周星星
Posted @ 2006-11-02 08:58
:) 老杨无秘密了
# re: 小巧玲珑的网络抓包
showgt
Posted @ 2006-11-08 23:47
老师怎么直接复制到VC++怎么运行不了的啊?

错误:atal error C1083: Cannot open include file: 'mstcpip.h': No such file or directory
Error executing cl.exe.
# to showgt

Posted @ 2006-11-10 00:00
我使用 vc.net 编写,不知道 vc6 下的效果:)
# re: 小巧玲珑的网络抓包
向陽樹
Posted @ 2006-12-08 11:47
    // ::Closesocket( sock );
    // ::WSACleanup();
上面兩句為什麼要注釋掉呢?
# re: 小巧玲珑的网络抓包
玻璃小屋
Posted @ 2007-01-25 12:35

截到包,能破坏这个包,不让上层程序接受不???
# re: 小巧玲珑的网络抓包
困惑
Posted @ 2007-02-27 22:27
:P,梆菜,你的另一个身份是不是shotgun?

这篇关于小巧玲珑的网络抓包的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/232059

相关文章

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

SpringBoot使用OkHttp完成高效网络请求详解

《SpringBoot使用OkHttp完成高效网络请求详解》OkHttp是一个高效的HTTP客户端,支持同步和异步请求,且具备自动处理cookie、缓存和连接池等高级功能,下面我们来看看SpringB... 目录一、OkHttp 简介二、在 Spring Boot 中集成 OkHttp三、封装 OkHttp

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用

使用Python高效获取网络数据的操作指南

《使用Python高效获取网络数据的操作指南》网络爬虫是一种自动化程序,用于访问和提取网站上的数据,Python是进行网络爬虫开发的理想语言,拥有丰富的库和工具,使得编写和维护爬虫变得简单高效,本文将... 目录网络爬虫的基本概念常用库介绍安装库Requests和BeautifulSoup爬虫开发发送请求解

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

SSID究竟是什么? WiFi网络名称及工作方式解析

《SSID究竟是什么?WiFi网络名称及工作方式解析》SID可以看作是无线网络的名称,类似于有线网络中的网络名称或者路由器的名称,在无线网络中,设备通过SSID来识别和连接到特定的无线网络... 当提到 Wi-Fi 网络时,就避不开「SSID」这个术语。简单来说,SSID 就是 Wi-Fi 网络的名称。比如

Java实现任务管理器性能网络监控数据的方法详解

《Java实现任务管理器性能网络监控数据的方法详解》在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率、内存占用等,对于开发者和系统管理员来说,了解这些... 目录引言一、背景知识二、准备工作1. Maven依赖2. Gradle依赖三、代码实现四、代码详解五

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor