随笔 - 298  文章 - 377  trackbacks - 0
<2017年4月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

常用链接

留言簿(34)

随笔分类

随笔档案

文章档案

相册

收藏夹

搜索

  •  

最新评论

阅读排行榜

评论排行榜

#include <stdio.h>
#include<conio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#include <string>
using namespace std;
#pragma  comment (lib, "ws2_32.lib")
#define SIO_RCVALL      _WSAIOW(IOC_VENDOR,1)
#define MAX_PACK_LEN 65535 // 最大包长度
#define MAX_ADDR_LEN 16 // 最大地址长度
#define MAX_PROTO_TEXT_LEN 16 // 子协议名称最大长度
#define MAX_PROTO_NUM 12 // 子协议数量
#define MAX_HOSTNAME_LEN 255 // 最大主机名长度

// 定义IP首部格式
typedef struct _IPHeader      

    unsigned char h_verlen;    // 版本和首部长度  
    unsigned char tos;         // 服务类型       
    unsigned short total_len;  // 总长度 
    unsigned short ident;      // 标识号     
    unsigned short frag_and_flags;  // 段偏移量
    unsigned char ttl;         // 生存时间       
    unsigned char proto;       // 协议   
    unsigned short checksum;   // 首部校验和
    unsigned int sourceIP;     // 源IP地址  
    unsigned int destIP;       // 目的地址   
}IPHEADER;

// 定义TCP首部格式
typedef struct _TCPHeader 

    unsigned short th_sport;  // 源端口号        
    unsigned short th_dport;  // 目的端口号       
    unsigned int th_seq;  // SEQ序号    
    unsigned int th_ack;  // ACK序号
    unsigned char th_lenres;  //  首部长度    
    unsigned char th_flag;   // 控制位  
    unsigned short th_win;  // 窗口大小        
    unsigned short th_sum;  // 校验和        
    unsigned short th_urp;  // 紧急指针         
}TCPHEADER;

// 定义UDP首部格式
typedef struct _UDPHeader
{
    unsigned short uh_sport; // 16位源端口
    unsigned short uh_dport; // 16位目的端口
    unsigned short uh_len; // 16位长度
    unsigned short uh_sum; // 16位校验和
}UDPHEADER;

// 定义ICMP首部格式
typedef struct _ICMPHeader
{
    BYTE i_type; // 8位类型
    BYTE i_code; // 8位代码
    unsigned short i_cksum; // 16位校验和
    unsigned short i_id; // 识别号
    unsigned short i_seq; // 报文序列号
    unsigned long timestamp; // 时间戳
}ICMPHEADER;
//----------------------------------------------------------------------------------------------
// 定义子协议映射表
typedef struct _protomap 
{
    int ProtoNum;
    char ProtoText[MAX_PROTO_TEXT_LEN];
}PROTOMAP;

// 为子协议映射表赋值
PROTOMAP ProtoMap[MAX_PROTO_NUM]={
    {IPPROTO_IP,"IP"},
    {IPPROTO_ICMP,"ICMP"},
    {IPPROTO_IGMP,"IGMP"},
    {IPPROTO_GGP,"GGP"},
    {IPPROTO_TCP,"TCP"},
    {IPPROTO_PUP,"PUP"},
    {IPPROTO_UDP,"UDP"},
    {IPPROTO_IDP,"IDP"},
    {IPPROTO_ND,"ND"},
    {IPPROTO_RAW,"RAW"},
    {IPPROTO_MAX,"MAX"},
    {NULL,""}
};

SOCKET SockRaw; // 全局套接字
char TcpFlag[6]={'F','S','R','P','A','U'}; // TCP标志位
bool paramAll = false// 嗅探所有的数据包
bool paramTcp = false// 嗅探TCP数据包
bool paramUdp = false// 嗅探UDP数据包
bool paramIcmp = false// 嗅探ICMP数据包

int packet_totallen = 0; // 数据包总长度

char paramHostAddr_A[20]; // 嗅探的主机A
char paramHostAddr_B[20]; // 嗅探的主机B
char keyword[100]; // 嗅探的关键信息

// IP数据包解析函数
int DecodeIpPack(char *);
// TCP数据包解析函数
int DecodeTcpPack(char *);
// UDP数据包解析函数
int DecodeUdpPack(char *);
// ICMP数据包解析函数
int DecodeIcmpPack(char *);
// 显示数据包信息
void ShowPackInfo(char *buf, int iProtocol, char *szSoueceIP, char *szDestIP, char *szProtocol);
// 显示子协议数据包函数
void ShowSubPackInfo(char *, int);
// 错误检测函数
void CheckSockError(intchar*);
// 协议检测函数
char *CheckProtocol(int);
// 设置嗅探器参数函数
bool SetSnifferParam();
//-----------------------------------------------------------------------------------------------------
// SOCK错误处理函数
void CheckSockError(int iErrorCode, char *pErrorMsg)
{
    if(iErrorCode == SOCKET_ERROR)
    {
        printf("%s 出错了: %d",pErrorMsg,GetLastError());
        closesocket(SockRaw);
        exit(0);
    }
}
//------------------------------------------------------------------------------------------------------
// 协议识别函数
char *CheckProtocol(int iProtocol)
{
    for(int i=0; i<MAX_PROTO_NUM;i++)
    {
        // 如果找到对应的子协议,则返回名称
        if(ProtoMap[i].ProtoNum == iProtocol)
        {
            return ProtoMap[i].ProtoText;
        }
    }
    return "";
}
//---------------------------------------------------------------------------------------------------------
// TCP解包函数
int DecodeTcpPack(char *TcpBuf)
{
    TCPHEADER *pTcpHeader;
    char data[MAX_PACK_LEN];
    int i;
    // 转换成TCP首部格式
    pTcpHeader = (TCPHEADER*)TcpBuf;
    // 输出源端口和目的端口
    printf("  端口 : %d-->%d  ",ntohs(pTcpHeader->th_sport),ntohs(pTcpHeader->th_dport));
    unsigned char FlagMask = 1;
    // 输出标志位
    
//printf("标志位:");
    for(i=0;i<6;i++)
    {
        if((pTcpHeader->th_flag) & FlagMask)
        {
            printf("标志位:%c",TcpFlag[i]);
        }
        else
        {
            printf("-");
        }
        FlagMask = FlagMask<<1;
    }
    printf("\n");
    // 求数据段长度
    int totalheadlen = sizeof(IPHEADER)+sizeof(TCPHEADER);
    int tcpheadlen = sizeof(TCPHEADER);
    memcpy(data,TcpBuf+tcpheadlen,packet_totallen-totalheadlen);
    return true;
}
//-------------------------------------------------------------------------------------------------------------
// UDP 解包函数
int DecodeUdpPack(char *UdpBuf)
{
    UDPHEADER *pUdpHeader;
    char data[MAX_PACK_LEN];
    pUdpHeader = (UDPHEADER *)UdpBuf;
    // 输出端口和数据长度
    printf(" 端口号: %d-->%d ",ntohs(pUdpHeader->uh_sport),ntohs(pUdpHeader->uh_dport));
    printf(" 长度: %d\n",ntohs(pUdpHeader->uh_len));
    int totalheadlen = sizeof(IPHEADER)+sizeof(UDPHEADER);
    int udpheadlen = sizeof(UDPHEADER);
    memcpy(data,UdpBuf+udpheadlen,packet_totallen-totalheadlen);
    return true;
}
//---------------------------------------------------------------------------------------------------------------------
// ICMP 解包函数
int DecodeIcmpPack(char *IcmpBuf)
{
    ICMPHEADER *pIcmpHeader;
    pIcmpHeader = (ICMPHEADER *)IcmpBuf;
    // 输出ICMP数据包类型、ID和SEQ
    printf("  Type : %d,%d",pIcmpHeader->i_type,pIcmpHeader->i_code);
    printf("  ID = %d SEQ = %d\n",pIcmpHeader->i_id,pIcmpHeader->i_seq);
    return true;
}

//-----------------------------------------------------------------------------------------------------------------------
// 根据过滤条件显示数据包信息
void ShowPackInfo(char *buf, int iProtocol, char *szSoueceIP, char *szDestIP, char *szProtocol)
{
    // 如果设置了主机B的IP,没有设置主机A的IP
    if((!strcmp(paramHostAddr_A,"all")) && (strcmp(paramHostAddr_B,"all")))
    {
        if((!strcmp(paramHostAddr_B,szSoueceIP)) 
            || (!strcmp(paramHostAddr_B,szDestIP)))
        {
        printf(" -------------------------------------------------------------------------------\n");
        printf("| 协议|    源IP地址     |   目的IP地址   |  ");
        printf("------------------------------------------------------------------------------\n");
        printf("\n| %s | ",szProtocol);
        printf(" %s | %s  |",szSoueceIP,szDestIP);
            // 显示子协议数据包相关信息
            ShowSubPackInfo(buf,iProtocol);
        }
    }
    // 如果设置主机A的IP,没有设置主机B的IP
    else if((strcmp(paramHostAddr_A,"all")) && (!strcmp(paramHostAddr_B,"all")))
    {
        if((!strcmp(paramHostAddr_A,szSoueceIP)) 
            || (!strcmp(paramHostAddr_A,szDestIP)))
        {
        printf(" -------------------------------------------------------------------------------\n");
        printf("| 协议|    源IP地址     |   目的IP地址   |\n  ");
        printf("------------------------------------------------------------------------------");
        printf("\n| %s | ",szProtocol);
        printf(" %s | %s  |",szSoueceIP,szDestIP);
            ShowSubPackInfo(buf,iProtocol);
        }
    }
    // 如果主机A和B的IP都进行了设置
    else if((strcmp(paramHostAddr_A,"all")) && (strcmp(paramHostAddr_B,"all")))
    {
        if((!strcmp(paramHostAddr_A,szSoueceIP) 
            && !strcmp(paramHostAddr_B,szDestIP))
            || (!strcmp(paramHostAddr_B,szSoueceIP) 
            && !strcmp(paramHostAddr_A,szDestIP)))
        {
            
        printf(" -------------------------------------------------------------------------------\n");
        printf("| 协议|    源IP地址     |   目的IP地址   |\n  ");
        printf("------------------------------------------------------------------------------");
        printf("\n| %s | ",szProtocol);
        printf(" %s | %s  |",szSoueceIP,szDestIP);
            ShowSubPackInfo(buf,iProtocol);
        }
    }
    // 如果主机A和B的IP都没有进行设置
    else
    {
        printf(" -------------------------------------------------------------------------------\n");
        printf("| 协议|    源IP地址     |   目的IP地址   |\n  ");
        printf("------------------------------------------------------------------------------");
        printf("\n| %s | ",szProtocol);
        printf(" %s | %s  |",szSoueceIP,szDestIP);
        ShowSubPackInfo(buf,iProtocol);
    }
}
//-----------------------------------------------------------------------------------------------------------------------

// 显示子协议数据包信息
void ShowSubPackInfo(char *buf, int iProtocol)
{
    switch(iProtocol)
    {
    case IPPROTO_TCP: // TCP数据包
        DecodeTcpPack(buf);
        break;
    case IPPROTO_UDP: // UDP数据包
        DecodeUdpPack(buf);
        break;
    case IPPROTO_ICMP: // ICMP数据包
        DecodeIcmpPack(buf);
        break;
    default:
        break;
    }
}
// IP 解包函数
int DecodeIpPack(char *buf)
{

    //cout<<"发送的buffer:"<<buf<<endl<<endl; 郁闷,这是个结构体,打印的时候都显示E
    IPHEADER *pIpHeader;
    int iProtocol;
    // 定义协议
    char szProtocol[MAX_PROTO_TEXT_LEN];
    char szSourceIP[MAX_ADDR_LEN];
    char szDestIP[MAX_ADDR_LEN];
    SOCKADDR_IN saSource,saDest;
    pIpHeader = (IPHEADER *)buf;
    // 检测协议是哪种类型
    iProtocol = pIpHeader->proto;
    strncpy(szProtocol,CheckProtocol(iProtocol),MAX_PROTO_TEXT_LEN);
    // 检测源地址
    saSource.sin_addr.s_addr = pIpHeader->sourceIP;
    strncpy(szSourceIP,inet_ntoa(saSource.sin_addr),MAX_ADDR_LEN);
    // 检测目的地址
    saDest.sin_addr.s_addr = pIpHeader->destIP;
    strncpy(szDestIP,inet_ntoa(saDest.sin_addr),MAX_ADDR_LEN);

    int iIpLen = sizeof(unsigned long)*(pIpHeader->h_verlen & 0xf);
    packet_totallen = ntohs(pIpHeader->total_len);

    // 下面显示过滤信息
    if(paramAll) // 显示所有协议类型数据包
    {
        ShowPackInfo(buf+iIpLen,iProtocol,szSourceIP,szDestIP,szProtocol);
    }
    // 显示TCP类型数据包
    else if(paramTcp && (iProtocol == IPPROTO_TCP))
    { 
        ShowPackInfo(buf+iIpLen,iProtocol,szSourceIP,szDestIP,szProtocol);
    }
    // 显示UDP类型数据包
    else if(paramUdp && (iProtocol == IPPROTO_UDP))
    {
        ShowPackInfo(buf+iIpLen,iProtocol,szSourceIP,szDestIP,szProtocol);
    }
    // 显示ICMP类型数据包
    else if(paramIcmp && (iProtocol == IPPROTO_ICMP))
    {
        ShowPackInfo(buf+iIpLen,iProtocol,szSourceIP,szDestIP,szProtocol);
    }
    return true;
}
//------------------------------------------------------------------------------------------------------------
// 设置嗅探器参数
bool SetSnifferParam()
{
    int ret;
    bool check_input = false;
    while(!check_input)
    {
                printf("*************************基于原始套接字的网络嗅探器*****************************\n\n");
                printf("   学号:3109005953   姓名:卫海鹏   专业班级:2009级计算机科学与技术(2)班 \n\n");
                printf("==>>请选择要嗅探的数据包类型: 0. 全部  1. TCP  2. UDP  3. ICMP : ");
        scanf("%d",&ret);
        switch(ret)
        {
        case 0:
            paramAll = true;
            check_input = true;
            break;
        case 1:
            paramTcp = true;
            check_input = true;
            break;
        case 2:
            paramUdp = true;
            check_input = true;
            break;
        case 3:
            paramIcmp = true;
            check_input = true;
            break;
        default:
            printf("==>>o(︶︿︶)o唉,输入错误!!!\n");
            check_input = false;
            break;
        }
    }

    printf("\n==>>请输入嗅探的主机A的IP地址(输入all即为全部主机):");
    scanf("%s",paramHostAddr_A);
    printf("\n==>>请输入嗅探的主机B的IP地址(输入all即为全部主机):");
    scanf("%s",paramHostAddr_B);
      
    return true;
}
//----------------------------------------------------------------------------------------------------------------------
void main(int argc, char **argv)
{
    int i,temp;
    int iErrorCode;
    char RecvBuf[MAX_PACK_LEN] = {0};
    SetSnifferParam();
    WSADATA wsaData;
    // 初始化Winsock库
    iErrorCode = WSAStartup(MAKEWORD(2,1),&wsaData);
    CheckSockError(iErrorCode, "WSAStartup");
    SockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
    CheckSockError(SockRaw, "socket");
    // 获取本机IP地址,并且判断Socket版本,建立原始套接字
    char FAR name[MAX_HOSTNAME_LEN];
    iErrorCode = gethostname(name, MAX_HOSTNAME_LEN);
    CheckSockError(iErrorCode, "gethostname");

    printf("%s\n",name);

    struct hostent FAR *pHostent;
    pHostent = (struct hostent *)malloc(sizeof(struct hostent));

    pHostent = gethostbyname(name);
    
    cout<<"pHostent->h_name:"<<pHostent->h_name<<endl;
    cout<<"pHostent->h_aliases:"<<pHostent->h_aliases<<endl;
    cout<<"pHostent->h_addrtype:"<<pHostent->h_addrtype<<endl;
    cout<<"pHostent->h_length:"<<pHostent->h_length<<endl;
    cout<<"pHostent->h_addr_list:"<<pHostent->h_addr_list<<endl;
    



    // 设置地址结构,端口为本地的6000
    SOCKADDR_IN sa;
    sa.sin_family = AF_INET;
    sa.sin_port = htons(6000);

    memcpy(&sa.sin_addr.S_un.S_addr,pHostent->h_addr_list[0],pHostent->h_length);

    // 绑定地址结构
    iErrorCode = bind(SockRaw, (PSOCKADDR)&sa, sizeof(sa));
    CheckSockError(iErrorCode, "bind");
    // 设置套接字为SIO_RCVALL,以便接收所有的IP包
    DWORD dwBufferLen[10];
    DWORD dwBufferInLen = 1;
    DWORD dwBytesReturned = 0;

    //为什么要有下面这一行,还不是很清楚
    iErrorCode = WSAIoctl(SockRaw, SIO_RCVALL , &dwBufferInLen, sizeof(dwBufferInLen),
        &dwBufferLen, sizeof(dwBufferLen), &dwBytesReturned, NULL, NULL);

    CheckSockError(iErrorCode, "Ioctl");
    // 监听IP报文
   L1:  printf("\n==>>请输入要嗅探数据包的个数:");
                scanf("%d",&temp);
                i=temp;

        while(i)
    {

        // 每次将接收缓冲区清零
        memset(RecvBuf, 0, sizeof(RecvBuf));
        // 开始接收缓冲区的数据
        iErrorCode = recv(SockRaw, RecvBuf, sizeof(RecvBuf),0);
        CheckSockError(iErrorCode, "recv");
        // 对接收到的数据包进行解析
        iErrorCode = DecodeIpPack(RecvBuf);
        CheckSockError(iErrorCode, "Decode");
        Sleep(100);
        i--;
    }
     if(i % 10 == 0) {
       system("pause");
       goto L1;
     } //等待输入一个字符(不回显)后继续输出.

}
posted on 2017-04-04 02:44 聂文龙 阅读(224) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理