zoukankan      html  css  js  c++  java
  • 29网络偷包

    偷包,就是在网络传输过程中,截取某一数据包,进行解析获取其发送的数据。

    原理与TCP通信类似。只需在创建套接字时,参数不同。

    fd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);

    PF_INET                      IPV4协议

    SOCK_RAW            对原始网络协议访问

    IPPROTO_TCP:   TCP 协议

    注意:第三参数必须指定协议的类型,不可以是0,只能接受某一种协议的数据,不可以是所有IP数据包。

    注意:

    char szBuf[1024];

    iRet = read(fd, szBuf, sizeof(szBuf));

    此时szBuf接受的包是数据,不是字符串,可能是乱码或其他乱七八的东东。

    因此,对数据包进行解析:

    IP数据报的格式:

    (1)一个 IP 数据报由首部和数据两部分组成。

    (2)首部的前一部分是固定长度,共 20 字节,是所有 IP 数据报必须具有的。

    (3)在首部的固定部分的后面是一些可选字段,其长度是可变的。

    定义IP数据包格式的一个结构体:

    typedef struct tagIpHeader

    {

          unsigned char ucHeadLen:4;

          unsigned char ucVer:4;

          unsigned char ucTos;

          unsigned short usLen;

          unsigned short usIdent;

          unsigned short usOffset:13;

          unsigned short usFlag:3;

          unsigned char ucTTL;

          unsigned char ucProtocol;

          unsigned short usChkSum;

          unsigned int uiSrcIp;

          unsigned int uiDstIp;

         

          char data[0];

    }IPHEAD_S;

    再将接收到的szBuf,转换,再将结构体的信息输出

    IPHEAD_S *pIpHead = (IPHEAD_S*)szBuf;

    TCP 报文段首部的前 20 个字节是固定的,后面有 4n 字节是根据需要而增加的选项 (n 是整数)。

    注意:TCP 首部的最小长度是 20 字节。而UDP是28字节。

    定义TIP报文段格式的一个结构体:

    typedef struct tagTcpHeader

    {

          unsigned short srcPort;

          unsigned short dstPort;

          unsigned int   uiSeq;

          unsigned int   uiSeqQ;

          unsigned short fin:1;

          unsigned short syn:1;

          unsigned short rst:1;

          unsigned short psh:1;

          unsigned short ack:1;

          unsigned short urg:1;

          unsigned short res:6;

          unsigned short usHeadLen:4;

          unsigned short usWinLen;

          unsigned short usChkSum;

          unsigned short usUrgPtr;

          unsigned char  data[0];

    }TCPHEAD_S;

    例子:

    #include<stdio.h>

    #include<stdlib.h>

    #include<unistd.h>

    #include<sys/socket.h>

    #include<netinet/in.h>

    #include<arpa/inet.h>

    #include<string.h>

    #define RAW_PORT  8888

    //IP数据包格式

    typedef struct tagIpHeader

    {

          unsigned char ucHeadLen:4;

          unsigned char ucVer:4;

          unsigned char ucTos;

          unsigned short usLen;

          unsigned short usIdent;

          unsigned short usOffset:13;

          unsigned short usFlag:3;

          unsigned char ucTTL;

          unsigned char ucProtocol;

          unsigned short usChkSum;

          unsigned int uiSrcIp;

          unsigned int uiDstIp;

         

          char data[0];

    }IPHEAD_S;

    //TCP数据报格式

    typedef struct tagTcpHeader

    {

          unsigned short srcPort;

          unsigned short dstPort;

          unsigned int   uiSeq;

          unsigned int   uiSeqQ;

          unsigned short fin:1;

          unsigned short syn:1;

          unsigned short rst:1;

          unsigned short psh:1;

          unsigned short ack:1;

          unsigned short urg:1;

          unsigned short res:6;

          unsigned short usHeadLen:4;

          unsigned short usWinLen;

          unsigned short usChkSum;

          unsigned short usUrgPtr;

          unsigned char  data[0];

    }TCPHEAD_S;

    //IP信息

    void PrintIpHead(IPHEAD_S *pIpHead)

    {

          printf(" --------------- IP_HEAD ------------- ");

          printf("srcPort : %d ", pIpHead->ucVer);

          printf("HeadLen : %d ", pIpHead->ucHeadLen);

          printf("TOS     : %d ", pIpHead->ucTos);

          printf("DataLen : %d ", ntohs(pIpHead->usLen));

          printf("Ident   : %d ", ntohs(pIpHead->usIdent));

          printf("Flag    : %d ", pIpHead->usFlag);

          printf("Offset  : %d ", pIpHead->usOffset);

          printf("TTL     : %d ", pIpHead->ucTTL);

          printf("Protocol: %d ", pIpHead->ucProtocol);

          printf("ChkSum  : %d ", ntohs(pIpHead->usChkSum));

          struct sockaddr_in addr;

          addr.sin_addr.s_addr = pIpHead->uiSrcIp; //s_addr is network-endian

          printf("Src IP  : %s ", inet_ntoa(addr.sin_addr));

         

          addr.sin_addr.s_addr = pIpHead->uiDstIp;

          printf("Dst IP  : %s ", inet_ntoa(addr.sin_addr));

         

          printf(" ------------------------------------- ");

    }

    //TCP信息

    void PrintTcpHead(TCPHEAD_S *pTcpHead)

    {

          printf(" --------------- TCP_HEAD ------------- ");

          printf("srcPort : %d ", htons(pTcpHead->srcPort));

          printf("dstPort : %d ", pTcpHead->dstPort);

          printf("uiSeq   : %d ", pTcpHead->uiSeq);

          printf("uiSeqQ : %d ",  htons(pTcpHead->uiSeqQ));

          printf("fin:%d syn:%d tst:%d psh:%d ack:%d urg:%d res:%d:%d ",

                     pTcpHead->fin,pTcpHead->syn,pTcpHead->rst,

                     pTcpHead->psh,pTcpHead->ack,pTcpHead->urg,pTcpHead->res);

          printf("usHeadLen: %d ", pTcpHead->usHeadLen);

          printf("usWinLen  : %d ", htons(pTcpHead->usWinLen));

          printf("usChkSum  : %d ", htons(pTcpHead->usChkSum));

          printf("usUrgPtr: %d ", htons(pTcpHead->usUrgPtr));

          printf("ChkSum  : %d ", htons(pTcpHead->usChkSum));

          printf(" ------------------------------------- ");

    }

    void CaptureData()

    {

          int fd;

          int iRet;

          struct sockaddr_in addr;

          socklen_t  addrlen = sizeof(addr);

         

          fd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP); //capture TCP data-packet

          //fd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); //capture TCP data-packet

          if (fd < 0)

          {

               perror("Fail to socket!");

               return;

          }

         

          addr.sin_family = AF_INET;

          addr.sin_port   = htonl(RAW_PORT);

          addr.sin_addr.s_addr = htonl(INADDR_ANY);

          iRet = bind(fd, (struct sockaddr*)&addr, addrlen);

          if (iRet)

          {

               perror("Fail to bind!");

               close(fd);

               return;

          }

          char szBuf[1024];

          while(1)

          {

               memset(szBuf, 0, sizeof(szBuf));

               iRet = read(fd, szBuf, sizeof(szBuf));

               if (iRet < 0)

               {

                     perror("Fail to read!");

                     break;

               }

               //解析数据包

               IPHEAD_S *pIpHead = (IPHEAD_S*)szBuf;

               PrintIpHead(pIpHead);

               //解析TCP报文的数据

               TCPHEAD_S *pTcpHead=(TCPHEAD_S *)pIpHead;

               printf("data: %s ", pTcpHead->data);

               //printf("Recv:%s ", szBuf);

              

          }

          close(fd);

          return; 

    }

    int main()

    {

          CaptureData();

          return 0;

    }

    大小序问题:

    在数据包格式中看到,版本在前,首部长度在后。但是在结构体中,首部长度在前,版本在后。

    解析:因此char是一个字节,而在数据包中,版本+首部长度=1字节。并且是大字节序,接受到后在内存中是小字节序。此时首部长度将被放在高位,版本被放在地位。因此进行调换。

    DataLen和 Ident   的转换也是如此。

          printf("DataLen : %d ", ntohs(pIpHead->usLen));

          printf("Ident   : %d ", ntohs(pIpHead->usIdent));

  • 相关阅读:
    Could not find file '..inhibernate.cfg.xml'解决方法:
    图片轮播插件-carouFredSel
    C语言数组
    C语言字符串
    C语言指针基础
    python 多线程
    Andriod之Activity
    Java面向对象的编程
    C++模板编程
    关于思考
  • 原文地址:https://www.cnblogs.com/gd-luojialin/p/9216041.html
Copyright © 2011-2022 走看看