精华内容
下载资源
问答
  • rawsocket
    2021-06-27 23:43:55

    测试代码

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<netinet/ip_icmp.h>
    #include<netinet/tcp.h>
    #include<netinet/udp.h>
    #include<netinet/if_ether.h>
    #include<net/if.h>
    #include <net/ethernet.h>
    #include<arpa/inet.h>
    #include<sys/socket.h>
    #include<sys/types.h>
    #include<sys/ioctl.h>
    #include <linux/if_packet.h>
    #include <unistd.h>
    
    
    #define BUFFSIZE 1024
    
    const char* device = "enx00e04c680125";
    const unsigned char dst_mac[6] = {0x00,0x0c,0x29,0x87,0x16, 0x37};
    
    struct ker_arphdr
      {
        unsigned short int ar_hrd;          /* Format of hardware address.  */
        unsigned short int ar_pro;          /* Format of protocol address.  */
        unsigned char ar_hln;               /* Length of hardware address.  */
        unsigned char ar_pln;               /* Length of protocol address.  */
        unsigned short int ar_op;           /* ARP opcode (command).  */
    #if 1
        /* Ethernet looks like this : This bit is variable sized
           however...  */
        unsigned char __ar_sha[ETH_ALEN];   /* Sender hardware address.  */
        unsigned char __ar_sip[4];          /* Sender IP address.  */
        unsigned char __ar_tha[ETH_ALEN];   /* Target hardware address.  */
        unsigned char __ar_tip[4];          /* Target IP address.  */
    #endif
      };
    typedef struct {
        /* Source/destination address. */
        unsigned char dst_address[6];
        unsigned char src_address[6];
    
        /* Ethernet type. */
        unsigned short type;
    } eth_header_t;
    
    
    int main(){
    
        int rawsock;
        //char wbuf[BUFFSIZE];
        //int ret;
        char rbuf[BUFFSIZE];
        int n, count = 0;
        eth_header_t* eth;
        
            rawsock = socket(AF_PACKET, SOCK_RAW, ntohs(ETH_P_ARP));
            if(rawsock < 0){
                    printf("raw socket error!\n");
                    exit(1);
            }
    
        struct ifreq ifr_re;
        strncpy(ifr_re.ifr_name, device, IFNAMSIZ);
    
        // 获取接口index
        if(ioctl(rawsock, SIOCGIFINDEX, (char*)&ifr_re))
        {
            return -1;
        }
    
        // 赋值socket属性
        struct sockaddr_ll hwaddr;
        memset(&hwaddr, 0, sizeof(hwaddr));
        hwaddr.sll_ifindex   = ifr_re.ifr_ifindex;
        hwaddr.sll_family    = AF_PACKET;
        hwaddr.sll_protocol  = htons(ETH_P_ARP);
        hwaddr.sll_hatype    = 0;
        hwaddr.sll_pkttype   = PACKET_HOST;
        hwaddr.sll_halen     = ETH_ALEN;
    
        // 绑定socket至接口
        if(bind(rawsock, (struct sockaddr*)&hwaddr, sizeof(hwaddr)))
        {
            printf("raw socket bind error!\n");
            return -1;
        }
        // 获取接口MAC地址
        if(ioctl(rawsock, SIOCGIFHWADDR, (char*)&ifr_re))
        {
            printf("raw socket get mac address failed!\n");
            return -2;
        }
        printf("Local mac: %02x:%02x:%02x:%02x:%02x:%02x\n", 
                        ifr_re.ifr_hwaddr.sa_data[0], 
                        ifr_re.ifr_hwaddr.sa_data[1], 
                        ifr_re.ifr_hwaddr.sa_data[2],
                        ifr_re.ifr_hwaddr.sa_data[3],
                        ifr_re.ifr_hwaddr.sa_data[4],
                        ifr_re.ifr_hwaddr.sa_data[5]);
        // send pkt
        //write(rawsock, wbuf,  12);
    
        while (1) {
            n = recvfrom(rawsock,rbuf,BUFFSIZE,0,NULL,NULL);
            if(n<0){
                printf("receive error!\n");
                exit(1);
            }
            count++;
            eth = (eth_header_t*)rbuf;
             if (eth->type == htons(ETH_P_IP)){
                printf("Recved IP  pkt dst mac: %02x:%02x:%02x:%02x:%02x:%02x  ", eth->dst_address[0]
                    , eth->dst_address[1]
                    , eth->dst_address[2]
                    , eth->dst_address[3]
                    , eth->dst_address[4]
                    , eth->dst_address[5]);
                    struct ip *ip = (struct ip*)(eth + 1);
                    printf("%3d     %15s",count,inet_ntoa(ip->ip_src));
                    printf("%15s    %5d     %5d\n",inet_ntoa(ip->ip_dst),ip->ip_p,ntohs(ip->ip_len));
            }
            else if (eth->type == htons(ETH_P_ARP)) {
                    printf("Recved ARP pkt src mac: %02x:%02x:%02x:%02x:%02x:%02x  ", eth->src_address[0]
                                    , eth->src_address[1]
                                    , eth->src_address[2]
                                    , eth->src_address[3]
                                    , eth->src_address[4]
                                    , eth->src_address[5]);
                    struct ker_arphdr* ah =  (struct ker_arphdr*)(eth + 1);
                    printf("%3d          %u.%u.%u.%u\n",count, ah->__ar_sip[3],ah->__ar_sip[2],ah->__ar_sip[1],ah->__ar_sip[0]);
    
            }
            memset(rbuf, 0, sizeof(rbuf));
        }
        return 0;
    }

    测试收获

    1. Rawsocket收到的包,并不是截获。数据包后续该怎么处理还怎么处理,Rawsocket这里只是复制了一份而已。

    2. Rawsocket收包是双向的,比如主机收到的一个icmp echo request包和主机发出去的一个icmp echo reply包,这两个包Rawsocket都是能Get到。

    3. sll_protocol  参数可以是指定三层协议的,协议号在/include/linux/if_ether.h中。也可以指定未收录在if_ether.h中的私有三层协议。

    更多相关内容
  • mina-transport-rawsocket

    2021-06-21 06:29:48
    Apache Mina 传输原始套接字Apache mina Rawsocket 传输使用本机库 jnetpcap 1.4.r1425 来自: ://jnetpcap.com/download 请参阅: : 用于 NIC(网络接口卡)的 IoAcceptor //10.10.10.1 is one of nic's ip ...
  • RawSocket-master.zip,RawSocket-master,test.cpp,PacketSniffer.cpp,CheckSum.cpp,PacketSniffer.h,CheckSum.h,PacketSender.cpp,PacketSender.h,.gitignore,Makefile,README.md
  • 利用rawsocket实现本机网络报文监控解析,支持TCP、UDP、Raw报文的解析,关键字提取。测试成功的代码。
  • 主要介绍了python 使用raw socket进行TCP SYN扫描实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • linux下使用RAW SOCKET接收LLDP报文并解析,纯C代码,可使用GCC直接编译,测试通过。
  • Linux环境下基于Raw socket技术的多线程追击抓包法.pdf
  • rawsocket_udp.c

    2021-06-07 11:19:48
    实现发送自定义以往帧,以及raw_socket实现UDP发送,伪装IP头,大包IP分片与重组,checksum计算和大包分片时偏移值计算,编译直接可用。
  • rawsocket抓包侦听

    2020-10-10 17:39:38
    rawsocket抓包侦听,只有简单的基本功能,VC6工程,在Win7环境下测试OK rawsocket抓包侦听,只有简单的基本功能,VC6工程,在Win7环境下测试OK
  • RawSocket在链路层的收发,arp,多线程指定网守发示例
  • 如何自己封装IP头用raw socket来实现ip报文的发送
  • RawSocket基于MAC地址发送以太网数据帧例子。C++实现。
  • 通过rawsocket实行报文侦听拦截,分析报文内容特征,获取关键信息。可以作为实现嗅探软件的基础框架。
  • raw socket

    2015-01-14 11:10:01
    raw socket exmaples, 包括各种协议,源代码来自github
  • 使用 RawSocket 捕获网卡/指定程序/指定端口/指定IP 数据包
  • 基于raw socket的UDP数据的发送和接收,自定义IP头,UDP头,数据
  • VC下基于winsock2的原始套接子发送程序,含有详细的注释说明,是学习网络编程的很好的例子
  • Linux socket raw loop test
  • This is a UDP Socket created with raw_socket.
  • 在Windows下实现基于Raw Socket的无连接通信,并且采用多线程方式。
  • RAW socket使用

    千次阅读 2021-06-09 14:12:55
    type type定义了套接字类型,如下的值在中进行了定义: 常量 描述 SOCK_STREAM Stream (connection) socket(TCP) SOCK_DGRAM Datagram (connection-less) socket(UDP) SOCK_RAW RAW socket SOCK_RDM Reliably-...

    一、通用

    首先讨论在使用以下任何API进行开发时必须考虑的一些一般性问题。除了这里引出的问题外,编程者还必须注意他想要使用的网络协议的特殊性。如果没有注意到这种特殊性,例如交换信息的正确顺序,就不能确保我们能够与另一个主机通信。

    1.1 字节顺序

    在网络通信中,字节顺序(也称为endianness)对于正确设置和解释字段至关重要。每当一个值需要超过1字节的存储空间时,我们就必须在网络字节顺序和主机字节顺序之间进行转换。根据所使用的协议和操作系统,网络字节顺序和主机字节顺序可能不同。对于IP协议,网络字节顺序是大端编址,因此每当主机的字节顺序不是大端编址时,我们就必须进行转换[5]。

    对于用于IP协议的转换,Berkeley套接字API提供了一组标准函数,这些函数在头文件<arpa/inet.h>:

    FunctionDescription
    uint32_t htonl(uint32_t hostlong)host-to-network
    uint16_t htons(uint16_t hostshort)host-to-network
    uint32_t ntohl(uint32_t netlong)network-to-host
    uint16_t ntohs(uint16_t netshort)network-to-host

    Linux环境下通过套接字接收/发送的数据总是按网络字节顺序[5]。

    1.2 checksum

    许多用于网络通信的协议使用校验和来检测传输错误。有不同的方法来计算校验和。如果我们选择完全由自己生成首部,我们必须手动计算和设置适用的头字段。如果我们这样做,有几点需要考虑:

    • 使用哪种算法来计算校验和
    • 首部的哪些字段(有时甚至是多个首部的字段)必须包含在校验和的计算中[5]。当然,用户数据可能也被包含在计算中
    • 如果我们想计算校验和,所有的头信息需要已经经过了正确的设置
    • 我们是否必须计算校验和,或者可以通过网络驱动程序/硬件(例如以太网校验和)、操作系统或预定义函数调用自动计算校验和[5]。

    作为计算校验和的一个可能的代码示例,附录中给出了用于计算因特网校验和的listling,这个listing随RFC 1071一起提供的。

    1.3 Type-Casting

    C语言的一个基本功能是支持类型转换。将二进制数据转换为C中的数据结构的能力对于程序员更容易地处理头数据是至关重要的。要执行类型转换,只需创建指向所需结构的指针:

    struct header* protocolHeader;
    

    Then we do need a pointer to the memory space where the binary data of the packet is stored, in our examples mostly a char-Array with a fixed SIZE[5]:

    char buffer[SIZE];
    

    Finally we can cast the binary data to our struct and afterwards are able to access the header fields[5]:

    protocolHeader = (struct header*) buffer;
    

    在访问header字段时,我们仍然需要处理前面提到的字节顺序。对于大多数众所周知的协议,库中包含的头文件中都有预定义的结构。下表显示了一些可用的头,但它只显示了可用头结构的一部分。根据操作系统和库的不同,可能会提供更多的头文件:

    Header-FileDescription
    <netinet/ip.h>Defines macros, variables, and structures for IP.
    <netinet/ip_icmp.h>Defines macros, variables, and structures for ICMP.
    <netinet/udp.h>Defines macros, variables, and structures for UDP.
    <netinet/tcp.h>Defines macros, variables, and structures for TCP
    <netns/idp.h>Defines IPX packet headers.
    <netns/sp.h>Defines SPX packet header.
    <ssl.h>Defines SSL prototypes, macros, variables, and structures.

    1.4 Header-Positions

    另一个必须考虑的问题是首部在二进制数据中的位置。必须考虑以下因素:

    • 较低层的头总是封装较高层的头和数据
    • 最低层的首部总是可以在二进制数据包的开头找到。可能不是所有字段都存在,例如数据链路层中的以太网协议就是这种情况。对于以太网协议,前导码、帧起始分隔符和帧校验和由网络驱动程序删除,因为它们更属于物理层(OSI层1)[5]。
    • 如果我们将二进制数据类型转化为结构体,我们必须将最后一个头的长度添加到数据指针中,以获得下一个头的开始[5]
      `next_header = (struct header*) (buffer + sizeof(struct header));
    • 如果最后一个报头具有可变长度和可选字段(例如IP报头或TCP报头),则要找到正确的起始位置可能比上面所示的简单加操作要困难一些。在这种情况下,我们必须首先得到报头的固定部分,然后访问长度字段,最后计算可选报头的长度。只有这样做之后,我们才能找到下一个首部的开始。如果我们对可选字段的内容感兴趣,我们还必须访问包含可选字段类型的标题字段,并相应地将其转换为正确的类型。

    二、RAW-sockets

    RAW-socket允许访问传输层(OSI第4层)和网络层(OSI第3层)[5]。它的使用仅限于有效用户ID为0或具有CAP_NET_RAW功能的进程,因为它需要root访问权限[1]。

    2.1 socket()

    对RAW-socket的读写都需要首先创建套接字。创建套接字使用与普通套接字相同的函数。可在<netinet/in.h>中找到,其形式如下[8]

    int socket(int family, int type, int protocol)
    

    其中参数如下:


    family

    family是一个描述所用地址族的常量值,常量在<sys/socket.h>中进行了定义:

    ConstantDescription
    AF_LOCALLocal communication
    AF_UNIXUnix domain sockets
    AF_INETIP version 4
    AF_INET6IP version 6
    AF_IPXNovell IPX
    AF_NETLINKKernel user interface device
    AF_X25Reserved for X.25 project
    AF_AX25Amateur Radio AX.25
    AF_APPLETALKAppletalk DDP
    AF_PACKETLow level packet interface
    AF_ALGInterface to kernel crypto API

    该函数仅在套接字已经建立连接后将源自网络的错误传递给用户。在这种情况下,只传递EMSGSIZE和EPROTO以实现兼容性。如果启用了IP_RECVERR标志位,则所有网络错误都将保存在错误队列中。如果套接字创建成功,则返回非负的套接字描述符;如果在创建套接字期间发生错误,则返回-1。此外<errno.h>中定义的变量errno可以具有以下值[8]:
    在这里插入图片描述
    使用者必须意识到,设置family会影响以后可以选择哪个协议。与RAW-socket一起使用的通常选项是用于发送和接收IPv4数据包的AF_INET。


    type

    type定义了套接字类型,如下的值在<sys/socket.h>中进行了定义:

    常量描述
    SOCK_STREAMStream (connection) socket(TCP)
    SOCK_DGRAMDatagram (connection-less) socket(UDP)
    SOCK_RAWRAW socket
    SOCK_RDMReliably-delivered message
    SOCK_SEQPACKETSequential packet socket
    SOCK_PACKETLinux specific way of getting packets at the dev level.

    在这里插入图片描述


    protocol

    protocol定义了套接字发送和接收数据包所使用的协议[8]。协议编号由IANA(互联网分配编号管理局)定义,完整列表可在其网站上找到。<netinet/in.h>中定义了一些协议常量:

    常量描述
    IPPROTO_IPDummy protocol.
    IPPROTO_HOPOPTSIPv6 Hop-by-Hop options.
    IPPROTO_ICMPInternet Control Message Protocol.
    IPPROTO_IGMPInternet Group Management Protocol.
    IPPROTO_IPIPIPIP tunnels (older KA9Q tunnels use 94).
    IPPROTO_TCPTransmission Control Protocol
    IPPROTO_EGPExterior Gateway Protocol.
    IPPROTO_PUPPUP protocol.
    IPPROTO_UDPUser Datagram Protocol.
    IPPROTO_IDPXNS IDP protocol.
    IPPROTO_TPSO Transport Protocol Class 4.
    IPPROTO_IPV6IPv6 header.
    IPPROTO_ROUTINGIPv6 routing header.
    IPPROTO_FRAGMENTIPv6 fragmentation header.
    IPPROTO_RSVPReservation Protocol.
    IPPROTO_GREGeneral Routing Encapsulation.
    IPPROTO_ESPEncapsulating security payload.
    IPPROTO_AHAuthentication header.
    IPPROTO_ICMPV6ICMPv6.
    IPPROTO_NONEIPv6 no next header.
    IPPROTO_DSTOPTSIPv6 destination options.
    IPPROTO_MTPMulticast Transport Protocol.
    IPPROTO_ENCAPEncapsulation Header.
    IPPROTO_PIMProtocol Independent Multicast.
    IPPROTO_COMPCompression Header Protocol.
    IPPROTO_SCTPStream Control Transmission Protocol.
    IPPROTO_RAWRaw IP packets.
    IPPROTO_MAXNo description.

    这里protocol的选择受到第一个选项family的影响,只有该family的协议可以选择为protocol。因此,如果选择了我们AF_INET选项,我们只能使用基于IP的协议[8]。

    此外,这里应该注意到,大多数操作系统(取决于Linux/Unix发行版)的IPPROTO_RAW意味着套接字还希望用户手动创建IP首部[8]。如果我们选择这个常数,我们就有第3层写入权限。通常的方法是使用另一个常量,然后使用setsockopt()更改套接字选项

    In addition to these constants we could also use constants that are defined for layer 2 (PACKET-sockets) to access their protocol information. These constants are operating system dependent and therefore code that uses them cannot be ported as easy as the general constants from the previous table. As an example, table 48 in the appendix shows the constants in Linux for Ethernet protocols which are defined in the <linux/if_ether.h> header.

    2.2 setsockopt()

    setsockopt()函数可用于更改套接字的options。在不同网络层次军存在options(例如TCP、IP),they are always present at the uppermost socket level.。函数体在<sys/socket.h>头中定义,如下所示:

    int setsockopt(int sockfd, int level, int optname, const void * optval, socklen_t optlen)
    

    其中可以设置如下的参数:

    • sockfd - 指定需要设定哪个socket的选项
    • level - The protocol level of the option we want to set.
    • optname - 我们想要设定的选项名,它与optval和optlen一起被未经解释地传递给协议模块进行处理
    • optval - 我们要设置的选项值所在的缓冲区,通常是一个整数。It should then be non-zero to enable a Boolean option and zero to disable it.
    • optlen - 用字节衡量的optval的缓冲区长度

    当修改socket option时,option所在的网络层次及option名需要进行指定。当修改socket API层次的option时,level需要被被设定为SOL_SOCKET。当修改在其他任意层次的option时,the protocol number of the appropriate protocol controlling the option is supplied.例如,为了指明某一个option是被TCP协议使用的,level需要被设定为TCP 的protocol number。

    对于以IPPROTO_IP作为参数指定的level,下表显示了<netinet/IP.h>头文件支持并已包含的以下optname:

    optname描述
    IP_ADD_MEMBERSHIPJoin a multicast group. Argument is an ip_mreqn structure
    IP_ADD_SOURCE_MEMBERSHIPJoin a multicast group and allow receiving data only from a specified source
    IP_BLOCK_SOURCEStop receiving multicast data from a specific source in a given group
    IP_DROP_MEMBERSHIPLeave a multicast group
    IP_DROP_SOURCE_MEMBERSHIPLeave a source-specific group-that
    IP_FREEBINDIf enabled, this boolean option allows binding to an IP address that is non-local/does not exist
    IP_HDRINCLIf enabled, the user supplies an IP header in front of the user data. Only valid for SOCK_RAW sockets
    IP_MSFILTERThis option provides access to the advanced full-state filtering API
    IP_MTU_DISCOVERSet or receive the Path MTU Discovery setting for a socket
    IP_MULTICAST_IFSet the local device for a multicast socket
    IP_MULTICAST_LOOPSet or read an argument that determines if multicast packets should be looped back to the local sockets
    IP_MULTICAST_TTLSet or read the time-to-live value of outgoing multicast packets for this socket
    IP_NODEFRAGIf enabled (nonzero), the reassembly of outgoing packets is disabled in the netfilter layer
    IP_OPTIONSSet or get the IP options to be sent with every packet from this socket
    IP_PKTINFOPass an IP_PKTINFO ancillary message that supplies information about the incoming packet
    IP_RECVERREnable extended reliable error message passing. On a datagram socket, all generated errors are stored in a per-socket error queue
    IP_RECVTOSIf enabled the IP_TOS ancillary message is passed with incoming packets
    IP_RECVTTLIf set, pass a IP_TTL control message with the received packets TTL. Not supported for SOCK_STREAM sockets
    IP_RETOPTSIdentical to IP_RECVOPTS, but returns raw unprocessed options with timestamp and route record options not filled in for this hop
    IP_ROUTER_ALERTPass all to-be forwarded packets with the IP Router Alert option set to this socket. Only valid for raw sockets.
    IP_TOSSet or get the TOS field that is sent with every IP packet originating from this socket.
    IP_TRANSPARENTSetting this boolean option enables transparent proxying on this socket.
    IP_TTLSet or get the current time-to-live field that is used in every packet sent from this socket.
    IP_UNBLOCK_SOURCEUnblock previously blocked multicast source.

    函数执行成功时返回0,如果发生错误返回-1。

    2.3 getsockopt

    2.4 bind

    在创建了一个socket后,我们就可以将创建的socket和一个特定的address绑定到一起。通常来讲这个过程叫做assigning a name to a socket。对于RAW-socket和PACKET-socket来讲这个过程是可选的,但是我们通常使用它来定义我们包的source address,同时也用它来定义我们想要从哪个network-interface来读取包。其他类型的socket可能要求在使用前绑定到一个特定的address。具体地,我们使用<sys/socket.h>中定义的bind()函数来将socket绑定到一个特定的IP地址。

    函数体如下:

    int bind(int sockfd,const struct sockaddr * addr, socklen_t addrlen);
    

    其中参数如下:

    • sockfd:指定需要设定地址的socket
    • addr:需要设定其中地址信息的地址数据结构
    • addrlen:地址数据结构的字节大小

    当函数成功执行时返回0,执行失败时返回-1。

    2.5 getsockname

    2.6 connect

    这个函数用于初始化一个有具体目的地址的连接,write、send、read以及recv函数都需要这个函数。

    对于connection based的协议,例如SOCK_STREAM这个函数同样会尝试从另一端建立连接。对于datagram based的协议,only the default destination is defined with this function。函数在<sys/socket.h>中进行了定义,函数体如下:

    int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen);
    

    其中参数如下:

    • sockfd:指定进行连接的socket的文件描述符
    • addr:sockaddr*结构体指针,指定了连接的另一方
    • addrlen:addr的长度

    注意如果socket sockfd是SOCK_DGRAM类型,那么addr是datagram默认发送的地址,也是接收datagram的唯一地址。如果socket是SOCK_STREAM或SOCK_SEQPACKET类型,那么调用这个函数会尝试和addr指定的地址绑定的socket进行连接。
    在这里插入图片描述

    当函数成功执行时返回0,失败时返回-1。

    参考

    2.7 read

    2.8 write

    我们可以用三种不同的方式通过套接字发送数据。write()和send()函数都需要先定义目标地址,这可以通过使用connect()函数实现。sendto()具有定义目标地址的选项,但也可以使用connect()函数设置。对于以上三种方式,我们都必须考虑缓冲区约束,否则在所有数据传输完全之前,写入连接将关闭。

    2.8.1 write

    2.8.2 send

    2.8.3 sendto

    sendto()函数允许我们定义一个数据应该发送到的特定地址,而不必首先调用connect()来设置目标地址[8]。需要注意的是,如果在连接模式(connection-mode)套接字上使用sendto()函数,则会忽略额外的地址信息,并在errno中返回EISCONN错误(如果未分别设置为NULL和零)[8]。这是因为对于这样的套接字,连接类型已经指定了目标。要使用此函数,必须包含<sys/types.h>(对于数据类型)和<sys/socket.h>(对于函数)。函数的调用方式如下[8]:

    ssize_t sendto(int sockfd, void * buf, size_t len, int flags, struct sockaddr * dest_addr, socklen_t addrlen)
    

    需要设置的参数如下:

    • sockfd - 指定我们通过哪个socket将数据发送出去
    • buf - 指定了我们想要通过socket发送的二进制数据所在的内存空间
    • len - 指定了从给定的内存空间中应当读取多少数据用于传输
    • dest_addr - 该函数使用此参数定义一个结构sockaddr*,其中包含套接字地址族和该族的协议地址。参数可以设置为空,这时不填写
    • addrlen - 提供给socket的dest_addr的长度
    • flags - 可以为这个方程设置的flag如下表所示
    Flag描述
    MSG_CONFIRMOnly valid on SOCK_DGRAM and SOCK_RAW. Tell the layer 2 that you got a successful reply from the other side
    MSG_DONTROUTEDon’t use a gateway to send out the packet, only send to hosts on directly connected networks.
    MSG_DONTWAITEnables non-blocking operation, if the operation would block EAGAIN or EWOULDBLOCK is returned.
    MSG_EORTerminates a record (when this notion is supported).
    MSG_MOREThe caller has more data to send. This flag is used with UDP/TCP sockets.
    MSG_NOSIGNALRequests not to send SIGPIPE on errors on stream oriented sockets when the other end breaks the connection. The EPIPE error is still returned.
    MSG_OOBSends out-of-band data on sockets that support this notion, the underlying protocol must also support out-of-band data.

    2.9 close

    2.10 inet_ntop

    2.11 inet_pton

    2.12

    展开全文
  • python raw socket 介绍

    2020-12-21 20:41:19
    因为要使用 python 底层发包模块,也就是 raw socket 发包模式,所以在此深入了解一下 python socket 通信。涉及到的函数:import socketsocket()setsockopt()sendto()recvfrom()因为使用的是原始套接字,所以我们不...

    因为要使用 python 底层发包模块,也就是 raw socket 发包模式,所以在此深入了解一下 python socket 通信。

    涉及到的函数:

    import socket

    socket()

    setsockopt()

    sendto()

    recvfrom()

    因为使用的是原始套接字,所以我们不使用bind/connect函数,参照《unix 网络编程》

    bind 函数仅仅设置本地地址。就输出而言,调用bind函数设置的是将用于从这个原始套接字发送的所有数据报的源IP地址。如果不调用bind,内核就吧源IP地址设置为外出接口的主IP地址。

    connect函数仅仅设置外地地址,同样因为原始套接字不存在端口号的概念。就输出而言,调用connect之后我们可以把sendto调用改为write或者send调用,因为目的IP地址已经指定了。

    顺便说一句,connect函数也是三次握手的发生过程,参见链接

    套接字参数

    官网介绍:

    socket.socket([family[, type[, proto]]])

    参数说明:

    family:协议簇/地址簇。

    最常用的就是 socket.AF_INET 了,TCP/UDP 通信均属于此类型。

    PS:有时我们看到的协议常量名为 AF_xxx,有时又是 PF_xxx,可以理解为 address family 和 protocol family,实际使用中是没有区别的。一般在区分协议的时候习惯使用 PF ,而在区分地址的时候习惯使用AF。可以参照这个链接的解释:

    Yes. AF_foo means address family foo, and PF_foo means protocol family foo. In Linux, they are always been the same values, I believe.

    Traditionally, the PF_foo constants were used for socket(), but AF_foo in the struct sockaddr structure.

    According to man 2 socket, even the (historical) BSD 4.x man page states that "The protocol family generally is the same as the address family", and subsequent standards use AF_* everywhere.

    Thus, today, there really should be no difference between AF_foo and PF_foo.

    除此之外常用的还有 AF_UNIX/AF_LOCAL ,代表UNIX域协议,属于IPC(进程间通信)的一种方式;AF_INET6 ,IPv6 通信。

    socket.AF_UNIX 只能够用于单一的Unix系统进程间通信

    socket.AF_INET 服务器之间网络通信

    socket.AF_INET6 IPv6

    type:socket的类型

    官网给出的列表如下:

    socket.SOCK_STREAM

    socket.SOCK_DGRAM

    socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。

    还有两种就是 socket.SOCK_RDM 与 socket.SOCK_SEQPACKET,基本没见过用

    前两种分别代表 面向流(TCP)和面向数据报(UDP)的socket通信。

    (我的理解是:SOCK_RAW = 协议头部我也自己发)

    proto: 协议类型

    常见的为

    IPPROTO_ICMP = 1

    IPPROTO_IP = 0

    IPPROTO_RAW = 255

    IPPROTO_TCP = 6

    IPPROTO_UDP = 17

    设置套接字选项

    setsockopt:设置套接字选项

    socket.setsockopt(level, optname, value)

    具体参数查看链接

    level:参数作用范围,常见的包括:

    SOL_SOCKET SOL应该是指的 SOck Level ,意为套接字层选项,常见的有 SO_REUSEADDR ,可以服用处于 Time_wait 状态的端口。

    IPPROTO_IP IP数据包选项,一个将要用到的是 IP_HDRINCL ,如果是TRUE,IP头就会随即将发送的数据一起提交,并从读取的数据中返回。

    还有 IPPROTO_TCP 等,此处不多做介绍。

    SOCKET通信例子

    TCP/UDP 通信

    先放两个简单的例子

    UDP Server:

    import socket

    address = ('127.0.0.1', 31500)

    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    s.bind(address)

    while True:

    data, addr = s.recvfrom(2048)

    if not data:

    print "client has exist"

    break

    print "received:", data, "from", addr

    s.close()

    UDP Client:

    import socket

    address = ('127.0.0.1', 31500)

    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    while True:

    msg = raw_input()

    if not msg:

    break

    s.sendto(msg, address)

    s.close()

    TCP Server:

    import socket

    address = ('127.0.0.1', 31500)

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # s = socket.socket()

    s.bind(address)

    s.listen(5)

    ss, addr = s.accept()

    print 'got connected from',addr

    ss.send('byebye')

    ra = ss.recv(512)

    print ra

    ss.close()

    s.close()

    TCP Client:

    import socket

    address = ('127.0.0.1', 31500)

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    s.connect(address)

    data = s.recv(512)

    print 'the data received is',data

    s.send('hihi')

    s.close()

    RAW SOCKET 通信

    接下来我们看一个raw socket通信的例子

    import sys

    import socket

    from impacket import ImpactDecoder, ImpactPacket

    def main():

    if len(sys.argv) < 3:

    print "Use: %s " % sys.argv[0]

    print "Use: %s " % sys.argv[0]

    sys.exit(1)

    elif len(sys.argv) == 3:

    src = sys.argv[1]

    dst = sys.argv[2]

    cnt = 1

    elif len(sys.argv) ==4:

    src = sys.argv[1]

    dst = sys.argv[2]

    cnt = sys.argv[3]

    else:

    print "Input error!"

    sys.exit(1)

    #print src, dst

    ip = ImpactPacket.IP()

    ip.set_ip_src(src)

    ip.set_ip_dst(dst)

    tcp = ImpactPacket.TCP()

    tcp.set_th_sport(55968)

    tcp.set_th_dport(80)

    tcp.set_th_seq(1)

    tcp.set_th_ack(1)

    tcp.set_th_flags(0x18)

    tcp.set_th_win(64)

    tcp.contains( ImpactPacket.Data("GET /att/DIYLife/41264/528 HTTP/1.1\r\nHost: 192.168.111.1\r\nAccept-Encoding: identity\r\n\r\n"))

    ip.contains(tcp)

    # Open a raw socket. Special permissions are usually required.

    s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)

    s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) // 此选项设置使用我们自己构造的IP头部

    seq_id = 0

    while cnt >= 1:

    # Calculate its checksum.

    seq_id = seq_id + 1

    tcp.set_th_seq(seq_id)

    tcp.calculate_checksum()

    # Send it to the target host.

    s.sendto(ip.get_packet(), (dst,80))

    cnt= cnt -1

    if __name__ == '__main__':

    main()

    看完这几个例子之后,说一下我的看法。

    Socket 的作用就是封装了各种不同的底层协议,为我们提供一个统一的操作接口。使用socket通信的时候,我们只需要根据协议类型来初始化相应的socket,然后将我们需要写入的数据传入该socket即可。

    因此,在初始化之后,socket为我们做了这么几件事情:

    对于面向流的连接如TCP,可以帮助我们自动完成三次握手(connect函数)和四次挥手(close函数)的过程

    在我们每次发送数据的时候,将我们要发送的数据根据默认或者你设置的选项包裹好包头,将其交给网卡的发送缓冲区

    接受数据的时候,帮助我们去掉包头

    由于不同协议都可以使用同样的接口进行发送和接受数据,因此,区分不同包头的过程都是在socket()函数中完成的。

    总结

    包结构图

    创建四层以上的套接字

    直接使用 socket.socket(socket.AF_INET,socket.SOCK_STREAM/socket.SOCK_DGRAM , socket.IPPROTO_TCP)即可,proto 可以自动推断(等价于IPPROTO_IP),也可以直接简写为s = socket.socket()

    意味着我们需要填充的内容仅仅是包结构图中的 [ 数据 ] 部分的内容

    创建三层套接字

    自行填充TCP头/UDP头,IP头部交给内核填充

    意味着我们需要填充的是包结构图中的 [ TCP包头 | 数据 ]

    此时由于四层协议头部需要由我们自己填充,就有一个问题:如果是四层以上套接字的话,我们是不用告诉socket协议名的,程序会自动根据你的端口号来区分应用层协议。但是如果你填充四层协议头的话,socket就必须提前知道是什么协议,用来填充IP头部的协议字段,也就是说协议字段不能为IPPROTO_IP。

    因此,我们就需要传入 socket 函数的第三个参数。例如我们要自己构造TCP包,可以用 socket.socket(socket.AF_INET,socket.SOCK_RAW , socket.IPPROTO_TCP )

    自行填充 四层协议头部和IP头部(限定是IP协议)

    意味着我们需要填充的是包结构图中的 [ IP包头 | TCP包头 | 数据 ] 的内容。

    这个和上面那个差不多,只不过我们可以修改IP头部,一种方式是:

    s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)

    s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) # 设置 IP 头部自己发送

    另外一种方式是:

    s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)

    这两种方式应该都是仅仅限于发送IP协议,所以 Ethernet 头部的协议字段不用我们填充~

    创建二层套接字

    方式1:

    socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))

    自行填充 以太网包头

    意味着我们需要填充的是上图中的 [ MAC包头 | IP包头 | TCP包头 | 数据 ] 的内容。

    方式2:

    socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))

    使用SOCK_RAW发送的数据必须包含链路层的协议头,接受得到的数据包,包含链路层协议头。而使用SOCK_DGRAM则都不含链路层的协议头。

    也即是说,需要填充的是上图中的 [ IP包头 | TCP包头 | 数据 ] 的内容。

    展开全文
  • 原始套接字-raw socket 最近在研究高并发下扫描存活主机,基本想法是通过socket来模拟ICMP报文,然后就发现了socket的一片新天地----原始套接字(raw socket)。 raw socket,即原始套接字,可以接收本机网卡上的...

    原始套接字-raw socket

    最近在研究高并发下扫描存活主机,基本想法是通过socket来模拟ICMP报文,然后就发现了socket的一片新天地----原始套接字(raw socket)。

    raw socket,即原始套接字,可以接收本机网卡上的数据帧或者数据包,对于监听网络的流量和分析是很有作用的,一共可以有4种方式创建这种socket。
    1.socket(PF_INET, SOCK_RAW, IPPROTO_TCP|IPPROTO_UDP|IPPROTO_ICMP)发送接收ip数据包
    2.socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))发送接收以太网数据帧
    3.socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))发送接收以太网数据帧(不包括以太网头部) [1]
    4.socket(PF_INET, SOCK_PACKET, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))过时了,不要用啊

    我们可看到通过原始套接字,我们可以拿到2层和3层的全部信息,也可以模拟二层和三层的各种协议,是不是很厉害了
    在这里插入图片描述

    所以如果要模拟ping,需要用第一种方法,
    socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)。
    我们可以通过socket函数第三个参数,可以模拟创建各种三层的协议。后面一期将模拟TCP协议的时候,还会用到其他类型。

    下面是封装之后的创建ICMP函数

    /* create a socke to icmp */
    int icmp_socket(char *ipv4)
    {
        int sockfd;
        int size = ICMP_RECVBUF_SIZE;
        
        if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
        {
           	usleep(1000);
    		if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
    	    {
    	        ICMP_LOG_ERR("创建socket失败");
    	        return -1;
    	    }
        }
    
    	//
    	//要过滤响应来源地址,需要这里绑定来源IP
        {
    		struct sockaddr_in serv_addr;
    		unsigned long ul = 1;
    		
    		ioctl(sockfd, FIONBIO, &ul); //设置为非阻塞模式
    		
    		memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
    		serv_addr.sin_family = AF_INET;  //使用IPv4地址
    		serv_addr.sin_addr.s_addr = inet_addr(ipv4);  //具体的IP地址
    		serv_addr.sin_port = htons(1234);  //端口随意填写,
    
    		//将套接字和IP、端口绑定
    		if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
            {
            	struct timeval tm;
    			fd_set set;
                int error=-1, len;
    			
                len = sizeof(int);
                tm.tv_sec = 1;
                tm.tv_usec = 0;
                FD_ZERO(&set);
                FD_SET(sockfd, &set);
                if( select(sockfd+1, NULL, &set, NULL, &tm) > 0)
                {
                    getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len);
                    if(error == 0)
                    {
    					//ret = true;
    				}
                    else
                    {
    					ICMP_LOG_ERR("connect[%s] socket失败1",ipv4);
    					close(sockfd);
    					return -1;
    				}
                } 
    			else
    			{
    				ICMP_LOG_ERR("connect[%s] socket失败2",ipv4);
    				close(sockfd);
    				return -1;
    			}
            }
            else
            {
    			//ret = true;
    		}
            ul = 0;
            ioctl(sockfd, FIONBIO, &ul); //设置为阻塞模式
    	}
    	//设置接收buf大小
        if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size))!=0)
        {
            ICMP_LOG_ERR("setsockopt SO_RCVBUF error.\n\r");
            close(sockfd);
            return -1;
        }
    
    	//设置超时时间,影响后面revform函数,让其不会一直阻塞
        if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&icmp_wait_timeout, sizeof(struct timeval))!=0)
        {
            ICMP_LOG_ERR("setsockopt SO_RCVTIMEO error.\n\r");
            close(sockfd);
            return -1;
        }
       
        return sockfd;
    }
    

    这个函数中比较重要的点,在于要过滤响应来源地址,需要这里绑定来源IP,这句话的含义就是我们创建的Raw socket,是比较松散的过滤,如果不绑定来源IP,那么所有的ICMP报文我们都收到,如果网络环境比较干净,倒是无所谓,但是如果是复杂的环境,里面有其他ICMP报文的话,会干扰到我们分析响应结果。
    下面这段话,是对于Raw Socket的一段非常重要的话

    当内核有一个需要传递到原始套接字的IP数据报时,它将检查所有进程上的原始套接字,以寻找所有匹配的套接字。每个匹配懂得套接字将被递送以该iP数据报的一个副本。(事实证明,如果进程过多,匹配的套接字过多,内核会忙于数据报的软过滤和分发,而实际的套接字却空闲,导致性能下降)
    内核对每个原始套接字均执行如下3个测试,只有这三个测试为真,内核才把接收到的数据报递送到这个套接字。
    【1】如果创建这个套接字时制订了非0的协议参数(socket的第三个参数),那么接受到的数据报的协议字段必须匹配该值,否则数据报不递送到这个套接字
    【2】如果这个原始套接字已由bind调用绑定了某个本地IP地址,那么接受到的数据报的目的IP地址必须匹配这个绑定的地址,否则该数据报不递送到这个套接字。
    【3】如果这个原始套接字已由connect调用指定了某个外地IP地址,那么接受到的数据报的源IP地址必须匹配这个已连接地址,否则该数据报不递送到这个套接字。

    bind和connect用的不恰当的话,直接影响你接收数据,处理不好,要么收的多,要么收不到。
    在这里插入图片描述

    下面是各个模块的功能函数。
    计算校验码函数

    unsigned short icmp_gen_chksum(unsigned short * data, int len)
    {
        int             nleft   = len;
        int             sum     = 0;
        unsigned short  *w      = data;
        unsigned short  answer  = 0;
     
        while (nleft > 1)
        {
            sum += *w++;
            nleft -= 2;
        }
     
        if (nleft == 1)
        {
            * (unsigned char *) (&answer) = *(unsigned char *)w;
            sum += answer;
        }
     
        sum     = (sum >> 16) + (sum & 0xffff);
        sum     += (sum >> 16);
        answer  = ~sum;
        
        return answer;
    }
    

    生成ICMP报文函数,这里注意如果前面没有绑定IP地址,那么也可以通过在此处配置icmp_id的方式来进行区分,这个ID是每一次操作会往返传递与两地之间,所以可以作为身份验证用。
    在这里插入图片描述

    int icmp_pkg_pack(void *buffer,const void *data, int data_size)
    {
        int  packsize = 0;
        struct icmp * icmp  = malloc(sizeof(struct icmp));
        icmp->icmp_type     = ICMP_ECHO;
        icmp->icmp_code     = 0;
        icmp->icmp_cksum    = 0;
        icmp->icmp_seq      = htons(0);
        icmp->icmp_id       = 0xff00;
    
        gettimeofday((struct timeval *) &icmp->icmp_data, NULL);
     
        memcpy(buffer, icmp, sizeof(struct icmp));
        packsize += sizeof(struct icmp);
     
        if(data && data_size)
        {
            memcpy(buffer+packsize, data, data_size);
            packsize += data_size;
        }
     
        return packsize;
    }
     
    

    发送ICMP报文函数,这个校验和的函数经过测试,没有任何问题

     
    /* send icmp package */
    int icmp_send_pkg(char* ipv4,int socket, const void *data, int size)
    {
        int             packetsize;
        unsigned short  checksum = 0;
        int             n = 0;
      	struct sockaddr_in dst_addr;
         
        char pkg_buffer[ICMP_BUF_SIZE];
        
        packetsize  = icmp_pkg_pack(pkg_buffer, data, size);
        checksum    = icmp_gen_chksum((unsigned short *)pkg_buffer, packetsize);
        
         icmp_dst_addr(ipv4, &dst_addr);
    
        memcpy(pkg_buffer + ICMP_PKG_CHKSUM_OFFSET, &checksum, ICMP_PKG_CHKSUM_SIZE);
     
        if ((n = sendto(socket, pkg_buffer, packetsize, 0, (struct sockaddr *) &dst_addr, sizeof(struct sockaddr_in)))< 0)
        {
    	        ICMP_LOG_ERR("发送ICMP失败n = %d", n);
    	        return 0;
        }
                           
        return n;
    }
    

    接收ICMP报文函数,Revice函数在前面的socket定义的超时时间之后会自动返回,保证用户进程不会一直阻塞。
    在这里插入图片描述

    int icmp_recv_pkg(int socket, void *recvbuf, int size)
    {
        int n;
    	socklen_t fromlen;
    	struct sockaddr_in from_addr; 
    	 
        fromlen = sizeof(struct sockaddr_in);
     
        if((n = recvfrom(socket, recvbuf, size, 0, (struct sockaddr *) &from_addr, &fromlen)) < 0)
        {
            ICMP_LOG_ERR("recvfrom error.n = %d\n\r", n);
            return 0;
        }
        return n;
    }
    

    解析ICMP报文函数,这里主要是判断了有没有收到响应,还可以通过时间戳,计算经过了多少时间到达
    (这里没写)在这里插入图片描述

    int icmp_pkg_unpack(char * buf, int len)
    {
        int		iphdrlen;
        struct  ip * ip = NULL;
        struct  icmp * icmp = NULL;
     
        ip          = (struct ip *)buf;
        iphdrlen    = ip->ip_hl << 2;
        icmp        = (struct icmp *) (buf + iphdrlen);
        len        -= iphdrlen;
     
        if (len < 8)
        {
            ICMP_LOG_ERR("ICMP packet\'s length is less than 8\n\r");
            return - 1;
        }
        if (icmp->icmp_type != ICMP_ECHOREPLY) 
        {
            return - 1;
        }
        return 0;
    }
    

    主函数测试ping函数和一些定义,还有一些核心头文件,基础头文件请自己添加
    在这里插入图片描述

    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/ip_icmp.h>
    #ifndef offsetof
    #define offsetof(type, member)    ((int) & ((type*)0) -> member )
    #endif
     
    #define ICMP_BUF_SIZE           256
    #define ICMP_RECVBUF_SIZE       (50 * 1024)
    
    #define ICMP_PROTO_NAME         "icmp"
    #define ICMP_DATA               "my ICMP Ping"
     
    #define ICMP_PING_SUCC          __ICMP_PING_SUCC
    #define ICMP_PING_FAIL          __ICMP_PING_FAIL
     
    #define ICMP_LOG(fmt...)        printf(fmt);
     
    #define ICMP_LOG_ERR(fmt...)   	printf(fmt);
    
    #define ICMP_PKG_CHKSUM_OFFSET  offsetof(struct icmp, icmp_cksum)
    #define ICMP_PKG_CHKSUM_SIZE    2
    
    typedef enum 
    {
        __ICMP_PING_FAIL = 0,
        __ICMP_PING_SUCC,
    }icmp_ping_rlst_t;
    
    static struct timeval icmp_wait_timeout = {0,100000}; //sec
    
    int icmp_ping_fun(char *ipv4)
    {
    	int res=__ICMP_PING_FAIL;
        char pkg_buffer[ICMP_BUF_SIZE];
        int ping_socket = 0;
    	
    	ping_socket =icmp_socket(ipv4);
    
    	if(ping_socket ==NULL)
    	{
    		return __ICMP_PING_FAIL;
    	}
    	else
    	{
    		int n=0;
    		n = icmp_send_pkg(ipv4,ping_socket, ICMP_DATA, sizeof(ICMP_DATA));
    		if(n < 8) 
    		{
    			close(ping_socket );
    			return __ICMP_PING_FAIL;
    		}
    		else
    		{
    			n = icmp_recv_pkg(ping_socket, pkg_buffer, ICMP_BUF_SIZE);
    			if(n<8) 
    			{
    				close(ping_socket );
    				return __ICMP_PING_FAIL;
    			}
    			else
    			{
    				if(icmp_pkg_unpack(pkg_buffer, n)==0)
    				{
        				close(ping_socket );
       					return __ICMP_PING_SUCC;
        				}
    				else
    				{
    					close(ping_socket );
    					return __ICMP_PING_FAIL;
    				}
    			}
    		}
    	}
    }
    

    这种写法,配合上多线程,同时ping65535个IP,3秒就能得到全部结果。
    在这里插入图片描述

    最后感谢这些人的奉献,参考了人家的代码,进行了一些改动。

    C语言实现ICMP协议,并进行PING测试
    raw_socket(原始套接字)以及普通socket使用终极总结

    下一章会再次介绍一下利用原始套接字模拟tcp通讯,来进行远端端口扫描。
    前一阵为了给孩子提供一个可以玩土的地方,和邻居合租的大棚,小孩子看到土的想法就是
    在这里插入图片描述
    结果发现还是我们这些农村出身的大人更喜欢这种种地的感觉。
    在这里插入图片描述
    从旁边大棚的废土里面捡到了几个草莓植株,居然开花了
    在这里插入图片描述
    希望大家以后能像这株草莓一样,被喜欢你的人发现。

    展开全文
  • RawSocket-master.zip,RawSocket-master,README.md,manifest.mf,src,rawsocket,RawSocket.java,jpcapListener.java,build.xml,nbproject,build-impl.xml,project.properties,project.xml,genfiles.properties
  • socket
  • RAW SOCKET实现ICMP重定向攻击

    千次阅读 2022-04-06 15:29:38
    RAW SOCKET SOCK_STREAM和SOCK_DGRAM都只能处理运输层往上的数据,而为了实现这个攻击,需要自己处理网络层的数据,所以需要用到SOCK_RAW。 使用RAW SOCKET处理网络层数据时,内核会自动帮我们处理ip头部信息,但是...
  • Java实现Ping功能(采用JNI技术),有源码和例子
  • 1. Raw Socket基础提供了一种方法来绕过整个网络堆栈遍历和直接将以太网帧输送到一个应用程序。有很多种方法来创建raw sockets,例如AF_PACKET,PF_PACKET。这里使用PF_PACKET,它是linux系统上才有的选项,如果是...
  • raw socket 量产的产品

    2022-07-14 14:51:37
    使用raw socket 不走tcp/ip实现数字可视对讲系统

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 59,144
精华内容 23,657
关键字:

rawsocket