小巧的网络抓包

#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报文
    while1 )
    
{
        
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];
    
forint i=0; i<iBufSize; i++ )
    
{
        printf( 
"%02X ", (unsigned char)buf[i] );

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

        
if15 == i%16 )
        
{
            ascii[ col ] 
= 0;
            printf( 
"%s ", ascii );
            col 
= 0;
        }

        
else if7 == i%8 )    printf( "" );
    }

    
if( col )
    
{
        
forint i=col; i<16; i++ )
        
{
            printf( 
"   " );
            
if15 == i%16 )
            
{
                ascii[ col ] 
= 0;
                printf( 
"%s ", ascii );
            }

            
else if7 == 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;
}
 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值