zoukankan      html  css  js  c++  java
  • 【VS开发】raw socket 的例子

    raw socket 的例子

    一. 摘要 
      Raw Socket: 原始套接字 
      可以用它来发送和接收 IP 层以上的原始数据包, 如 ICMP, TCP, UDP...

        int sockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);

      这样我们就创建了一个 Raw Socket

      Sniffer: 嗅探器 
      关于嗅探器的原理我想大多数人可能都知道 
      1. 把网卡置于混杂模式; 
      2. 捕获数据包; 
      3. 分析数据包.

      但具体的实现知道的人恐怕就不是那么多了. 好, 现在让我们用 Raw Socket 的做一个自已的 Sniffer.

    二. 把网卡置于混杂模式 
      在正常的情况下,一个网络接口应该只响应两种数据帧: 
      一种是与自己硬件地址相匹配的数据帧 
      一种是发向所有机器的广播数据帧 
      如果要网卡接收所有通过它的数据, 而不管是不是发给它的, 那么必须把网卡置于混杂模式. 也就是说让它的思维混乱, 不按正常的方式工作. 用 Raw Socket 实现代码如下:

        setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag); //设置 IP 头操作选项 
        bind(sockRaw, (PSOCKADDR)&addrLocal, sizeof(addrLocal); //把 sockRaw 绑定到本地网卡上 
        ioctlsocket(sockRaw, SIO_RCVALL, &dwValue);       //让 sockRaw 接受所有的数据

      flag 标志是用来设置 IP 头操作的, 也就是说要亲自处理 IP 头: bool flag = ture; 
      addrLocal 为本地地址: SOCKADDR_IN addrLocal; 
      dwValue 为输入输出参数, 为 1 时执行, 0 时取消: DWORD dwValue = 1; 
      没想到这么简单吧?

    三. 捕获数据包 
      你的 sockRaw 现在已经在工作了, 可以在局域网内其它的电脑上用 Sniffer 检测工具检测一下, 看你的网卡是否处于混杂模式(比如 DigitalBrain 的 ARPKiller). 
      不能让他白白的浪费资源啊, 抓包!

        recv(sockRaw, RecvBuf, BUFFER_SIZE, 0); //接受任意数据包

      #define BUFFER_SIZE 65535 
      char RecvBuf[BUFFER_SIZE]; 
      越来越发现 Sniffer 原来如此的简单了, 这么一个函数就已经完成抓取数据包的任务了.

    四. 分析数据包 
      这回抓来的包和平常用 Socket 接受的包可就不是一回事儿了, 里面包含 IP, TCP 等原始信息. 要分析它首先得知道这些结构. 
      数据包的总体结构: 
      ---------------------------------------------- 
      | ip header | tcp header(or x header) | data | 
      ----------------------------------------------

      IP header structure: 
           4    8    16                    32 bit 
      |--------|--------|----------------|--------------------------------| 
      | Ver  | IHL  |Type of service |     Total length     | 
      |--------|--------|----------------|--------------------------------| 
      | Identification |   Flags   |     Fragment offset    | 
      |--------|--------|----------------|--------------------------------| 
      | Time to live  |  Protocol  |     Header checksum    | 
      |--------|--------|----------------|--------------------------------| 
      |             Source address              | 
      |--------|--------|----------------|--------------------------------| 
      |            Destination address             | 
      |--------|--------|----------------|--------------------------------| 
      |            Option + Padding              | 
      |--------|--------|----------------|--------------------------------| 
      |                Data                | 
      |--------|--------|----------------|--------------------------------|

      TCP header structure: 
                      16                32 bit 
      |--------------------------------|--------------------------------| 
      |     Source port      |    Destination port    | 
      |--------------------------------|--------------------------------| 
      |             Sequence number             | 
      |--------------------------------|--------------------------------| 
      |           Acknowledgement number           | 
      |--------------------------------|--------------------------------| 
      | Offset | Resrvd |U|A|P|R|S|F|      Window       | 
      |--------------------------------|--------------------------------| 
      |      Checksum       |    Urgent pointer     | 
      |--------------------------------|--------------------------------| 
      |             Option + Padding            | 
      |--------------------------------|--------------------------------| 
      |               Data                | 
      |--------------------------------|--------------------------------|

    五. 实现 Sniffer 
      OK! 
      现在都清楚了, 还等什么. 
      下面是我用 BCB6 写的一个 Simple Sniffer 的代码, 仅供参考. 
      (需要在工程文件里加入WS2_32.LIB这个文件) 
    // 
    // 
    #include <vcl.h> 
    #pragma hdrstop

    #include <winsock2.h> 
    #include <ws2tcpip.h> 
    #include <mstcpip.h> 
    #include <netmon.h> 
    #include "WMain.h" 
    //--------------------------------------------------------------------------- 
    #pragma package(smart_init) 
    #pragma resource "*.dfm" 
    TMainForm *MainForm; 
    //--------------------------------------------------------------------------- 
    __fastcall TMainForm::TMainForm(TComponent* Owner) 
      : TForm(Owner) 

    WSADATA WSAData; 
      BOOL  flag  = true; 
      int   nTimeout = 1000; 
      char  LocalName[16]; 
      struct hostent *pHost;

      //检查 Winsock 版本号 
      if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0) 
        throw Exception("WSAStartup error!");

      //初始化 Raw Socket 
      if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == INVALID_SOCKET) 
        throw Exception("socket setup error!");

      //设置IP头操作选项 
      if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag)) == SOCKET_ERROR) 
        throw Exception("setsockopt IP_HDRINCL error!");

      //获取本机名 
      if (gethostname((char*)LocalName, sizeof(LocalName)-1) == SOCKET_ERROR) 
        throw Exception("gethostname error!");

      //获取本地 IP 地址 
      if ((pHost = gethostbyname((char*)LocalName)) == NULL) 
        throw Exception("gethostbyname error!");

      addr_in.sin_addr  = *(in_addr *)pHost->h_addr_list[0]; //IP 
      addr_in.sin_family = AF_INET; 
      addr_in.sin_port  = htons(57274);

      //把 sock 绑定到本地地址上 
      if (bind(sock, (PSOCKADDR)&addr_in, sizeof(addr_in)) == SOCKET_ERROR) 
        throw Exception("bind error!");

      iSortDirection = 1; 

    //--------------------------------------------------------------------------- 
    __fastcall TMainForm::~TMainForm() 

      WSACleanup(); 

    //---------------------------------------------------------------------------

    void __fastcall TMainForm::btnCtrlClick(TObject *Sender) 

      TListItem *Item; 
      DWORD dwValue; 
      int nIndex = 0;

      if (btnCtrl->Caption == "&Start") 
      { 
        dwValue = 1; 
        //设置 SOCK_RAW 为SIO_RCVALL,以便接收所有的IP包 
        if (ioctlsocket(sock, SIO_RCVALL, &dwValue) != 0) 
          throw Exception("ioctlsocket SIO_RCVALL error!"); 
        bStop = false; 
        btnCtrl->Caption = "&Stop"; 
        lsvPacket->Items->Clear(); 
      } 
      else 
      { 
        dwValue = 0; 
        bStop = true; 
        btnCtrl->Caption = "&Start"; 
        //设置SOCK_RAW为SIO_RCVALL,停止接收 
        if (ioctlsocket(sock, SIO_RCVALL, &dwValue) != 0) 
          throw Exception("WSAIoctl SIO_RCVALL error!"); 
      }

      while (!bStop) 
      { 
        if (recv(sock, RecvBuf, BUFFER_SIZE, 0) > 0) 
        { 
          nIndex++; 
          ip = *(IP*)RecvBuf; 
          tcp = *(TCP*)(RecvBuf + (ip.HdrLen & IP_HDRLEN_MASK));

          Item = lsvPacket->Items->Add(); 
          Item->Caption = nIndex; 
          Item->SubItems->Add(GetProtocolTxt(ip.Protocol)); 
          Item->SubItems->Add(inet_ntoa(*(in_addr*)&ip.SrcAddr)); 
          Item->SubItems->Add(inet_ntoa(*(in_addr*)&ip.DstAddr)); 
          Item->SubItems->Add(tcp.SrcPort); 
          Item->SubItems->Add(tcp.DstPort); 
          Item->SubItems->Add(ntohs(ip.TotalLen)); 
        } 
        Application->ProcessMessages(); 
      }   

    //---------------------------------------------------------------------------

    AnsiString __fastcall TMainForm::GetProtocolTxt(int Protocol) 

      switch (Protocol) 
      { 
        case IPPROTO_ICMP :      //1        
          return PROTOCOL_STRING_ICMP_TXT; 
        case IPPROTO_TCP :      //6        
          return PROTOCOL_STRING_TCP_TXT; 
        case IPPROTO_UDP :      //17       
          return PROTOCOL_STRING_UDP_TXT; 
        default : 
          return PROTOCOL_STRING_UNKNOWN_TXT; 
      } 

    //---------------------------------------------------------------------------

    // 
    // 
    //---------------------------------------------------------------------------

    #ifndef WMainH 
    #define WMainH 
    //--------------------------------------------------------------------------- 
    #define BUFFER_SIZE 65535

    #include <Classes.hpp> 
    #include <Controls.hpp> 
    #include <StdCtrls.hpp> 
    #include <Forms.hpp> 
    #include <ComCtrls.hpp> 
    #include <ExtCtrls.hpp> 
    #include <winsock2.h> 
    #include "netmon.h"

    //--------------------------------------------------------------------------- 
    class TMainForm : public TForm 

    __published: // IDE-managed Components 
      TPanel *Panel1; 
      TButton *btnCtrl; 
      TListView *lsvPacket; 
      TLabel *Label1; 
      void __fastcall btnCtrlClick(TObject *Sender); 
      void __fastcall lsvPacketColumnClick(TObject *Sender, 
         TListColumn *Column); 
      void __fastcall lsvPacketCompare(TObject *Sender, TListItem *Item1, 
         TListItem *Item2, int Data, int &Compare); 
      void __fastcall Label1Click(TObject *Sender); 
    private: // User declarations 
      AnsiString __fastcall GetProtocolTxt(int Protocol); 
    public: // User declarations 
      SOCKET   sock; 
      SOCKADDR_IN addr_in; 
      IP     ip; 
      TCP     tcp; 
      PSUHDR   psdHeader; 
      char    RecvBuf[BUFFER_SIZE]; 
      bool    bStop;

      int iSortDirection; 
      int iColumnToSort; 
      __fastcall TMainForm(TComponent* Owner); 
      __fastcall ~TMainForm(); 
    }; 
    //--------------------------------------------------------------------------- 
    extern PACKAGE TMainForm *MainForm; 
    //--------------------------------------------------------------------------- 
    #endif

      偷了个懒, IP, TCP 头及一些宏定义用了 netmon.h 的头, 这个文件在 BCB6 的 include 目录下可以找得到, 其中与本程序相关内容如下:

    // 
    // 
    // 
    // IP Packet Structure 
    // 
    typedef struct _IP 

      union 
      { 
        BYTE  Version; 
        BYTE  HdrLen; 
      }; 
      BYTE ServiceType; 
      WORD TotalLen; 
      WORD ID; 
      union 
      { 
        WORD  Flags; 
        WORD  FragOff; 
      }; 
      BYTE TimeToLive; 
      BYTE Protocol; 
      WORD HdrChksum; 
      DWORD  SrcAddr; 
      DWORD  DstAddr; 
      BYTE Options[0]; 
    } IP;

    typedef IP * LPIP; 
    typedef IP UNALIGNED * ULPIP;

    // 
    // TCP Packet Structure 
    // 
    typedef struct _TCP 
      { 
      WORD SrcPort; 
      WORD DstPort; 
      DWORD SeqNum; 
      DWORD AckNum; 
      BYTE DataOff; 
      BYTE Flags; 
      WORD Window; 
      WORD Chksum; 
      WORD UrgPtr; 
      } TCP;

    typedef TCP *LPTCP; 
    typedef TCP UNALIGNED * ULPTCP;

    // upper protocols 
    #define PROTOCOL_STRING_ICMP_TXT    "ICMP" 
    #define PROTOCOL_STRING_TCP_TXT    "TCP" 
    #define PROTOCOL_STRING_UDP_TXT    "UDP" 
    #define PROTOCOL_STRING_SPX_TXT    "SPX" 
    #define PROTOCOL_STRING_NCP_TXT    "NCP"

    #define PROTOCOL_STRING_UNKNOW_TXT   "UNKNOW"

      这个文件也有人声称没有. 
    // 
    // 
    // Copyright (c) Microsoft Corporation. All rights reserved. 
    #if _MSC_VER > 1000 
    #pragma once 
    #endif

    struct tcp_keepalive { 
      u_long onoff; 
      u_long keepalivetime; 
      u_long keepaliveinterval; 
    };

    // New WSAIoctl Options

    #define SIO_RCVALL      _WSAIOW(IOC_VENDOR,1) 
    #define SIO_RCVALL_MCAST   _WSAIOW(IOC_VENDOR,2) 
    #define SIO_RCVALL_IGMPMCAST _WSAIOW(IOC_VENDOR,3) 
    #define SIO_KEEPALIVE_VALS  _WSAIOW(IOC_VENDOR,4) 
    #define SIO_ABSORB_RTRALERT  _WSAIOW(IOC_VENDOR,5) 
    #define SIO_UCAST_IF     _WSAIOW(IOC_VENDOR,6) 
    #define SIO_LIMIT_BROADCASTS _WSAIOW(IOC_VENDOR,7) 
    #define SIO_INDEX_BIND    _WSAIOW(IOC_VENDOR,8) 
    #define SIO_INDEX_MCASTIF   _WSAIOW(IOC_VENDOR,9) 
    #define SIO_INDEX_ADD_MCAST  _WSAIOW(IOC_VENDOR,10) 
    #define SIO_INDEX_DEL_MCAST  _WSAIOW(IOC_VENDOR,11)

    // Values for use with SIO_RCVALL* options 
    #define RCVALL_OFF       0 
    #define RCVALL_ON       1 
    #define RCVALL_SOCKETLEVELONLY 2

      现在我们自已的 Sniffer 就做好了, Run, Start......哇, 这么多数据包, 都是从这一台机器上发出的, 它在干什么? 原来 Adminstrator 密码为空, 中了尼姆达病毒!

    六. 小结 
      优点: 实现简单, 不需要做驱动程序就可实现抓包. 
      缺点: 数据包头不含帧信息, 不能接收到与 IP 同层的其它数据包, 如 ARP, RARP... 
      这里提供的程序仅仅是一个 Sniffer 的例子, 没有对数据包进行进一步的分析. 写此文的目的在于熟悉Raw Socket 编程方法, 了解 TCP/IP 协议结构原理以及各协议之间的关系.

    posted @ 2009-05-07 22:16 WindFly 阅读(354) 评论(0) 编辑

    基于套接字发送伪造IP包

    这 里介绍Windows Sockets的一些关于原始套接字(Raw Socket)的编程。同Winsock1相比,最明显的就是支持了Raw Socket套接字类型,通过原始套接字,我们可以更加自如地控制Windows下的多种协议,而且能够对网络底层的传输机制进行控制。 
    1、创建一个原始套接字,并设置IP头选项。 
    SOCKET sock; 
    sock = socket(AF_INET,SOCK_RAW,IPPROTO_IP); 
    或者: 
    s = WSASoccket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED); 
    这 里,我们设置了SOCK_RAW标志,表示我们声明的是一个原始套接字类型。创建原始套接字后,IP头就会包含在接收的数据中,如果我们设定 IP_HDRINCL 选项,那么,就需要自己来构造IP头。注意,如果设置IP_HDRINCL 选项,那么必须具有 administrator权限,要不就必须修改注册表: 
    HKEY_LOCAL_MACHINESystemCurrentControlSetServicesAfdParameter 
    修改键:DisableRawSecurity(类型为DWORD),把值修改为 1。如果没有,就添加。 
    BOOL blnFlag=TRUE; 
    setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&blnFlag, sizeof(blnFlag); 
    对于原始套接字在接收数据报的时候,要注意这么几点: 
    1、如果接收的数据报中协议类型和定义的原始套接字匹配,那么,接收的所有数据就拷贝到套接字中。 
    2、如果绑定了本地地址,那么只有接收数据IP头中对应的远端地址匹配,接收的数据就拷贝到套接字中。 
    3、如果定义的是外部地址,比如使用connect(),那么,只有接收数据IP头中对应的源地址匹配,接收的数据就拷贝到套接字中。 
    2、构造IP头和TCP头 
    这里,提供IP头和TCP头的结构: 
    // Standard TCP flags 
    #define URG 0x20 
    #define ACK 0x10 
    #define PSH 0x08 
    #define RST 0x04 
    #define SYN 0x02 
    #define FIN 0x01 
    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地址 
    }IP_HEADER; 
    typedef struct psd_hdr //定义TCP伪首部 

    unsigned long saddr; //源地址 
    unsigned long daddr; //目的地址 
    char mbz; 
    char ptcl; //协议类型 
    unsigned short tcpl; //TCP长度 
    }PSD_HEADER; 
    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; 
    TCP伪首部并不是真正存在的,只是用于计算检验和。校验和函数: 
    USHORT checksum(USHORT *buffer, int size) 

    unsigned long cksum=0; 
    while (size > 1) 

    cksum += *buffer++; 
    size -= sizeof(USHORT); 

    if (size) 

    cksum += *(UCHAR*)buffer; 

    cksum = (cksum >> 16) + (cksum & 0xffff); 
    cksum += (cksum >>16); 
    return (USHORT)(~cksum); 

    当需要自己填充IP头部和TCP头部的时候,就同时需要自己计算他们的检验和。 
    3、发送原始套接字数据报 
    填充这些头部稍微麻烦点,发送就相对简单多了。只需要使用sendto()就OK。 
    sendto(sock, (char*)&tcpHeader, sizeof(tcpHeader), 0, (sockaddr*)&addr_in,sizeof(addr_in)); 
    下面是一个示例程序,可以作为SYN扫描的一部分。 
    #include <stdio.h> 
    #include <winsock2.h> 
    #include <ws2tcpip.h> 
    #define SOURCE_PORT 7234 
    #define MAX_RECEIVEBYTE 255 
    typedef struct ip_hdr //定义IP首部 

    unsigned char h_verlen; //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 tsd_hdr //定义TCP伪首部 

    unsigned long saddr; //源地址 
    unsigned long daddr; //目的地址 
    char mbz; 
    char ptcl; //协议类型 
    unsigned short tcpl; //TCP长度 
    }PSDHEADER; 
    typedef struct tcp_hdr //定义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位紧急数据偏移量 
    }TCPHEADER; 
    //CheckSum:计算校验和的子函数 
    USHORT checksum(USHORT *buffer, int size) 

    unsigned long cksum=0; 
    while(size >1) 

    cksum+=*buffer++; 
    size -=sizeof(USHORT); 

    if(size ) 

    cksum += *(UCHAR*)buffer; 

    cksum = (cksum >> 16) + (cksum & 0xffff); 
    cksum += (cksum >>16); 
    return (USHORT)(~cksum); 

    void useage() 

    printf("****************************************** "); 
    printf("TCPPing "); 
    printf(" Written by Refdom "); 
    printf(" Email: refdom@263.net "); 
    printf("Useage: TCPPing.exe Target_ip Target_port "); 
    printf("******************************************* "); 

    int main(int argc, char* argv[]) 

    WSADATA WSAData; 
    SOCKET sock; 
    SOCKADDR_IN addr_in; 
    IPHEADER ipHeader; 
    TCPHEADER tcpHeader; 
    PSDHEADER psdHeader; 
    char szSendBuf[60]={0}; 
    BOOL flag; 
    int rect,nTimeOver; 
    useage(); 
    if (argc!= 3) 
    { return false; } 
    if (WSAStartup(MAKEWORD(2,2), &WSAData)!=0) 

    printf("WSAStartup Error! "); 
    return false; 

    if ((sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET) 

    printf("Socket Setup Error! "); 
    return false; 

    flag=true; 
    if (setsockopt(sock,IPPROTO_IP, IP_HDRINCL,(char *)&flag,sizeof(flag))==SOCKET_ERROR) 

    printf("setsockopt IP_HDRINCL error! "); 
    return false; 

    nTimeOver=1000; 
    if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOver, sizeof(nTimeOver))==SOCKET_ERROR) 

    printf("setsockopt SO_SNDTIMEO error! "); 
    return false; 

    addr_in.sin_family=AF_INET; 
    addr_in.sin_port=htons(atoi(argv[2])); 
    addr_in.sin_addr.S_un.S_addr=inet_addr(argv[1]); 
    // 
    // 
    //填充IP首部 
    ipHeader.h_verlen=(4<<4 | sizeof(ipHeader)/sizeof(unsigned long)); 
    // ipHeader.tos=0; 
    ipHeader.total_len=htons(sizeof(ipHeader)+sizeof(tcpHeader)); 
    ipHeader.ident=1; 
    ipHeader.frag_and_flags=0; 
    ipHeader.ttl=128; 
    ipHeader.proto=IPPROTO_TCP; 
    ipHeader.checksum=0; 
    ipHeader.sourceIP=inet_addr("本地地址"); 
    ipHeader.destIP=inet_addr(argv[1]); 
    //填充TCP首部 
    tcpHeader.th_dport=htons(atoi(argv[2])); 
    tcpHeader.th_sport=htons(SOURCE_PORT); //源端口号 
    tcpHeader.th_seq=htonl(0x12345678); 
    tcpHeader.th_ack=0; 
    tcpHeader.th_lenres=(sizeof(tcpHeader)/4<<4|0); 
    tcpHeader.th_flag=2; //修改这里来实现不同的标志位探测,2是SYN,1是FIN,16是ACK探测 等等 
    tcpHeader.th_win=htons(512); 
    tcpHeader.th_urp=0; 
    tcpHeader.th_sum=0; 
    psdHeader.saddr=ipHeader.sourceIP; 
    psdHeader.daddr=ipHeader.destIP; 
    psdHeader.mbz=0; 
    psdHeader.ptcl=IPPROTO_TCP; 
    psdHeader.tcpl=htons(sizeof(tcpHeader)); 
    //计算校验和 
    memcpy(szSendBuf, &psdHeader, sizeof(psdHeader)); 
    memcpy(szSendBuf+sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader)); 
    tcpHeader.th_sum=checksum((USHORT *)szSendBuf,sizeof(psdHeader)+sizeof(tcpHeader)); 
    memcpy(szSendBuf, &ipHeader, sizeof(ipHeader)); 
    memcpy(szSendBuf+sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader)); 
    memset(szSendBuf+sizeof(ipHeader)+sizeof(tcpHeader), 0, 4); 
    ipHeader.checksum=checksum((USHORT *)szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader)); 
    memcpy(szSendBuf, &ipHeader, sizeof(ipHeader)); 
    rect=sendto(sock, szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader), 
    0, (struct sockaddr*)&addr_in, sizeof(addr_in)); 
    if (rect==SOCKET_ERROR) 

    printf("send error!:%d ",WSAGetLastError()); 
    return false; 

    else 
    printf("send ok! "); 
    closesocket(sock); 
    WSACleanup(); 
    return 0; 

    4、接收数据 
    和 发送原始套接字数据相比,接收就比较麻烦了。因为在WIN我们不能用recv()来接收raw socket上的数据,这是因为,所有的IP包都是先递交给系统核心,然后再传输到用户程序,当发送一个raws socket包的时候(比如syn),核心并不知道,也没有这个数据被发送或者连接建立的记录,因此,当远端主机回应的时候,系统核心就把这些包都全部丢 掉,从而到不了应用程序上。所以,就不能简单地使用接收函数来接收这些数据报。 
    要达到接收数据的目的,就必须采用嗅探,接收所有通过的数据包,然后进行筛选,留下符合我们需要的。可以再定义一个原始套接字,用来完成接收数据的任务,需要设置SIO_RCVALL,表示接收所有的数据。 
    SOCKET sniffersock; 
    sniffsock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED); 
    DWORD lpvBuffer = 1; 
    DWORD lpcbBytesReturned = 0 ; 
    WSAIoctl(sniffersock, SIO_RCVALL, &lpvBuffer, sizeof(lpvBuffer), NULL, 0, & lpcbBytesReturned, NULL, NULL); 
    创建一个用于接收数据的原始套接字,我们可以用接收函数来接收数据包了。然后在使用一个过滤函数达到筛选的目的,接收我们需要的数据包。

  • 相关阅读:
    vue-element-admin 权限的添加
    vue 图标通过组件的方式引用步骤
    linux系统环境下配置vue项目运行环境
    5.5 卷积神经网络(LeNet)
    5.4 池化层
    5.3 多输入通道和多输出通道
    5.2 填充和步幅
    html && CSS
    P2827 [NOIP2016 提高组] 蚯蚓
    5.1 二维卷积层
  • 原文地址:https://www.cnblogs.com/huty/p/8518346.html
Copyright © 2011-2022 走看看