局域网截包程序设计

  刚才收到了一个留言,第一次有人给我留言,很感动,给了我很大的信心,原来我写的东西还有点价值,只有当作业交上去的价值吧,现在把一年多前的在学校的一个作业程序贴上,希望有人把它当成作业。

 

实验目的
目前的局域网基本上都采用以广播为技术基础的以太网,任何两个节点之间的通信数据包,不仅为这两个节点的网卡所接收,也同时为处在同一以太网上的任何一个节点的网卡所截取。因此,黑客只要接入以太网上的任一节点进行侦听,就可以捕获发生在这个以太网上的所有数据包,对其进行解包分析,从而窃取关键信息,这就是以太网所固有的安全隐患。网上主要的免费黑客攻击工具如SATAN、ISS、NETCAT等均将以太网侦听作为基本的手段。
本实验实现一个局域网截包程序,目的在于使学生能更好地理解网络的工作机制(包括封包机制、协议分析等),该实验是对《计算机网络》课程一个有益的补充。
实验内容
在一个局域网环境中,用C 语言实现下面的基本功能:
(1)确定截包的方法:包括RAW 模式SOCKET、PACKET32以及直接作为驱动程序挂在NDIS上
(2)要求截获以下包的类型并分析:以太网帧格式、IP包、ICMP包、TCP报文段、UDP报文等相关字段进行描述。
实验步骤和注意事项
实验按下述步骤进行:
(1)       熟悉RAW模式的SOCKET编程
(2)       熟悉PACKET32的工作机制
(3)       熟悉WINDOWS 2000环境下NDIS驱动程序的编写方法
(4)       编写基于上述某一机制的局域网截包的实现程序;
(5)       在模拟实现环境下调试并运行自己编写的协议实现程序;
(6)       如出现异常情况,在实验报告中记录并分析可能的原因
#define RCVALL_ON 1
#define MAX_ADDR_LEN 16 //点分十进制地址的最大长度
#define MAX_PROTO_TEXT_LEN 16 //子协议名称(如"TCP")最大长度
#define WINSOCK_VERSION MAKEWORD(2, 2)
#pragma comment(lib, "Ws2_32.lib")
#include
#include
#include
#include
typedef struct iphdr          //定义IP首部
{
    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地址
}IPHeader;
typedef struct _tcphdr    //定义TCP首部
{
 USHORT th_sport; //16位源端口
 USHORT th_dport; //16位目的端口
 unsigned int  th_seq; //32位序列号
 unsigned int  th_ack; //32位确认号
 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; //16位源端口
    unsigned short uh_dport; //16位目的端口
    unsigned short uh_len; //16位长度
    unsigned short uh_sum; //16位校验和
}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;

int  iTTL,iLEN,iBYTES;
char szSourceIP[MAX_ADDR_LEN], szDestIP[MAX_ADDR_LEN];
int  iSourcePort,iDestPort;
int  fflag=0;//file flag
#define PACKAGE_SIZE sizeof(IPHeader)+1000
void HandleError(char *func);
//functions
int DecodeTcpPack(char *, int,FILE *); //TCP解包函数
int DecodeUdpPack(char *, int,FILE *); //UDP解包函数
int DecodeIcmpPack(char *, int,FILE *); //ICMP解包函数
//MAIN
int main(int argc, char *argv[])
{
 sockaddr_in saSource,saDest;
 WSAData wsaData;
 char buf[PACKAGE_SIZE];
    WSAStartup(WINSOCK_VERSION, &wsaData);
    SOCKET sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
    if(sock == SOCKET_ERROR)
    {
        HandleError("socket");
        WSACleanup();
        return -1;
    }
    //获取本机IP地址
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    //addr.sin_addr.S_un.S_addr = inet_addr("192.168.1.101");
char name[256];
 PHOSTENT hostinfo;
 if( gethostname ( name, sizeof(name)) == 0)
 {
  if((hostinfo = gethostbyname(name)) != NULL)
  {
   memcpy(&(addr.sin_addr.S_un.S_addr) , (struct in_addr *)*hostinfo->h_addr_list , sizeof((struct in_addr *)*hostinfo->h_addr_list ));
  }
 }
    addr.sin_family = AF_INET;
    if(bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)//bind
    {
        HandleError("bind");
    }
 //设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包
    int on = RCVALL_ON;
    DWORD num;
    if(WSAIoctl(sock, SIO_RCVALL, &on, sizeof(on), NULL, 0, &num, NULL, NULL) == SOCKET_ERROR)
    {
        HandleError("wsaIoctl set");
    }
    struct sockaddr_in from;
    int fromlen;
    int size;
 FILE *fp;
 if((fp=fopen("log.txt","w+"))==NULL)
 {
  printf("open file errer,can't save list to file");
  fflag=1;
 }
 //侦听IP报文
    while(!kbhit())
    {
        memset(buf, 0, sizeof(num));
        memset(&from, 0, sizeof(from));
        fromlen = sizeof(from);
  size=recvfrom(sock, buf, PACKAGE_SIZE, 0, (struct sockaddr*)&from, &fromlen);
        if(size == SOCKET_ERROR)
  {
   if(WSAGetLastError() == WSAEMSGSIZE)
            {
                HandleError("recvfrom");
                continue;
            }
        }
  IPHeader *iph=(IPHeader *)buf;
  /**/
  //源地址
   saSource.sin_addr.s_addr = iph->sourceIP;
   strncpy(szSourceIP, inet_ntoa(saSource.sin_addr), MAX_ADDR_LEN);
  //目的地址
   saDest.sin_addr.s_addr = iph->destIP;
   strncpy(szDestIP, inet_ntoa(saDest.sin_addr), MAX_ADDR_LEN);
  iTTL = iph->ttl;
  //计算IP首部的长度
  int IpHeadLen = 4 * (iph->h_lenver & 0xf);
  //根据协议类型分别调用相应的函数
  
        switch(iph->proto)
        {
        case IPPROTO_ICMP:
   DecodeIcmpPack(buf+IpHeadLen, size,fp);
            break;
        case IPPROTO_IGMP:
            printf("IGMP ");
   printf("%15s:      ->%15s:       ", szSourceIP, szDestIP);
            printf("%d",size);
            printf("%s/n", buf);
            break;
        case IPPROTO_TCP:
   DecodeTcpPack((buf+IpHeadLen),size,fp);
            break;
        case IPPROTO_UDP:
   DecodeUdpPack(buf+IpHeadLen, size,fp);
            break;
        default:
            printf("unknown datagram from %s/n", inet_ntoa(from.sin_addr));
            printf("%s/n", buf);
   break;
        }//end switch
  
        Sleep(200);
    }//end while
 fclose(fp);
    closesocket(sock);
    WSACleanup();
    printf("Stopped!/n");
 getch();
    return 0;
}//end of main

//TCP解包程序
int DecodeTcpPack(char * TcpBuf, int iBufSize,FILE *fp)
{
 unsigned char FlagMask;FlagMask = 1;
 int i;
 TCP_HEADER *tcph;
 
 tcph = (TCP_HEADER*)TcpBuf;
 //计算TCP首部长度
 int TcpHeadLen = tcph->th_lenres>>4;
 TcpHeadLen *= sizeof(unsigned long);
 char *TcpData=TcpBuf+TcpHeadLen; 
 iSourcePort = ntohs(tcph->th_sport);
 iDestPort   = ntohs(tcph->th_dport);
 
 //输出
 printf("TCP  ");
 printf("%15s:%5d ->%15s:%5d  ", szSourceIP, iSourcePort, szDestIP, iDestPort);
 printf("TTL=%3d  ", iTTL);
 if(fflag==1)
 
 //判断TCP标志位
 for( i=0; i<6; i++ )
 {
  if((tcph->th_flag) & FlagMask)
   printf("1");
  else printf("0");
  FlagMask=FlagMask<<1;
 }
 printf("  bytes=%4d", iBufSize);
 printf("/n");
 if(fflag=1)//写入文件
 fprintf(fp,"TCP  %15s:%5d ->%15s:%5d  TTL=%3d  ------  bytes=%4d/n"
  ,szSourceIP, iSourcePort, szDestIP, iDestPort, iTTL,iBufSize);
 return 0;
}
//UDP解包程序
int DecodeUdpPack(char * UdpBuf, int iBufSize,FILE *fp)
{
 UDP_HEADER *udph;
 udph = (UDP_HEADER*)UdpBuf;
 iSourcePort = ntohs(udph->uh_sport);
 iDestPort   = ntohs(udph->uh_dport);
 //输出
 printf("UDP  ");
 printf("%15s:%5d ->%15s:%5d  ", szSourceIP, iSourcePort, szDestIP, iDestPort);
 printf("TTL=%3d ", iTTL);
 printf("Len=%4d ", ntohs(udph->uh_len));
 printf("bytes=%4d", iBufSize);
 printf("/n");
 if(fflag=1)//写入文件
 fprintf(fp,"UDP  %15s:%5d ->%15s:%5d  TTL=%3d Len=%4d bytes=%4d/n"
  ,szSourceIP, iSourcePort, szDestIP, iDestPort, iTTL, ntohs(udph->uh_len), iBufSize);
 return 0;
}
//ICMP解包程序
int DecodeIcmpPack(char * IcmpBuf, int iBufSize,FILE *fp)
{
 ICMP_HEADER * icmph;
 icmph = (ICMP_HEADER * )IcmpBuf;
 int iIcmpType = icmph->i_type;
 int iIcmpCode = icmph->i_code;
 //输出
 printf("ICMP ");
 printf("%15s       ->%15s        ", szSourceIP, szDestIP);
 printf("TTL=%3d ", iTTL);
 printf("Type%2d,%d ",iIcmpType,iIcmpCode);
 printf("bytes=%4d", iBufSize);
 printf("/n"); 
 if(fflag=1)//写入文件
 fprintf(fp,"ICMP %15s       ->%15s        TTL=%3d Type%2d,%d bytes=%4d"
  , szSourceIP, szDestIP, iTTL,iIcmpType,iIcmpCode, iBufSize);
 return 0;
}
void HandleError(char *func)
{
    char info[65]= {0};
    _snprintf(info, 64, "%s: %d/n", func, WSAGetLastError());
    printf(info);
}

你可能感兴趣的:(网络编程,struct,header,socket,tcp,fp,file)