zoukankan      html  css  js  c++  java
  • 自定义RAW头

    TRawSocket = class(TObject)
    private
        buf: array[0..BUFLEN - 1] of char;
        FdwNotifyWnd: Cardinal;
        hsocket: Cardinal;
        str: string;
    public
        constructor Create;
        destructor Destroy; override;
        function createSocket: Integer;
        procedure destroySocket;
        function IsOk: Boolean;
        //function sendTcpData(srcIP, dstIP: string; srcPort, dstPort: word; data:
          //pchar; dataLen: integer): Integer;
        function sendUdpData(srcIP, dstIP: string; srcPort, dstPort: word; data:
          pchar; dataLen: integer): Integer;
        function sendUdpDataFrag(srcIP, dstIP: string; srcPort, dstPort: word;
          data: pchar; dataLen: integer): Integer;
    published
        property dwNotifyWnd: Cardinal read FdwNotifyWnd write FdwNotifyWnd;
    end;
    constructor TRawSocket.Create;
    begin
    inherited Create;
    hsocket := INVALID_SOCKET;
    end;destructor TRawSocket.Destroy;
    begin
    if IsOk then destroySocket;
    inherited Destroy;
    end;function TRawSocket.createSocket: Integer;
    var
    flag: Integer;
    ret: Integer;
    begin
    // 创建raw socket,自己构造ip包头
    result := -1; // Create socket
    // IPPROTO_RAW 只能用来发送IP包,而不能接收任何数据.
    //*发送的数据需要自己填充IP包头,TCP/UDP头并且自己计算校验和
    hsocket := Socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    if (hsocket = INVALID_SOCKET) then begin
        str := 'Socket() failed: ' + IntToStr(WSAGetLastError);
        SendMessage(FdwNotifyWnd, WM_STRINFO, integer(str), 0);
        exit;
    end;flag := 1; // Option: Header Include
    ret := SetSockOpt(hsocket, IPPROTO_IP, IP_HDRINCL, @flag, SizeOf(flag));
    if ret = SOCKET_ERROR then begin
        str := 'setsockopt IP_HDRINCL failed: ' + IntToStr(WSAGetLastError);
        SendMessage(FdwNotifyWnd, WM_STRINFO, integer(str), 0);
        exit;
    end;flag := 5000; // Option: Send OverTime;
    ret := SetSockOpt(hsocket, SOL_SOCKET, SO_SNDTIMEO, @flag, SizeOf(flag));
    if ret = SOCKET_ERROR then begin
        str := 'setsockopt SO_SNDTIMEO failed: ' + IntToStr(WSAGetLastError);
        SendMessage(FdwNotifyWnd, WM_STRINFO, integer(str), 0);
        exit;
    end;
    result := 1;
    end;procedure TRawSocket.destroySocket;
    begin
    shutdown(hsocket, SD_BOTH);
    CloseSocket(hsocket);
    hsocket := INVALID_SOCKET;
    end;function TRawSocket.IsOk: Boolean;
    begin
    result := not (hsocket = INVALID_SOCKET);
    end;
    function TRawSocket.sendUdpData(srcIP, dstIP: string; srcPort, dstPort: word;
    data: pchar; dataLen: integer): Integer;
    var
    ipHdr: _ipHead;
    udpHdr: _udpHead;
    pseudoHdr: _pseudoHead;
    ipSize, udpSize: Word;
    iphdrlen, pseudohdrlen, udphdrlen: Word;
    lpipHdr: pipHead;
    lpudpHdr: pudpHead;
    p, p0: PChar;
    Local: TSockAddrIn;
    Remote: TSockAddrIn;
    begin
    // 功能:打包发送UDP包
    Local.sin_family := AF_INET;
    Local.sin_addr.S_addr := inet_Addr(PChar(srcIP));
    Local.sin_port := htons(srcPort);Remote.sin_family := AF_INET;
    Remote.sin_addr.S_addr := inet_Addr(PChar(dstIP));
    Remote.sin_port := htons(dstPort);iphdrlen := sizeof(_ipHead);
    udphdrlen := sizeof(_udpHead);
    pseudohdrlen := sizeof(pseudoHdr);
    ipSize := iphdrlen + udphdrlen + datalen;
    udpSize := ipSize - iphdrlen;
    inc(idt); // test
    // 初始化 IP 头
    ipHdr.ver_IHL := (4 shl 4) or (sizeof(ipHdr) div 4);
    ipHdr.serverType := 0; // IP type of service
    ipHdr.totalLen := htons(ipSize); // Total packet len
    ipHdr.ident := htons(idt); // Unique identifier: set to 0
    ipHdr.flags_off := 0; // Fragment offset field
    ipHdr.ttl := 128; // Time to live
    ipHdr.protocol := 17; // Protocol(UDP)
    ipHdr.ipchksum := 0; // IP checksum
    ipHdr.srcAddr := Local.sin_addr.S_addr; // Source address
    ipHdr.dstAddr := Remote.sin_addr.S_addr; // Destination address// 初始化 UDP 头
    udpHdr.srcPort := Local.sin_port;
    udpHdr.dstPort := Remote.sin_port;
    udpHdr.Length := htons(udpSize);
    udpHdr.checksum := 0;// 初始化 伪ip 头
    pseudoHdr.srcAddr := ipHdr.srcAddr;
    pseudoHdr.dstAddr := ipHdr.dstAddr;
    pseudoHdr.unused := 0;
    pseudoHdr.protocol := ipHdr.protocol;
    pseudoHdr.Length := udpHdr.Length;p := buf + iphdrlen - pseudohdrlen;
    p0 := P; // 备份伪ip头指针p0,checksum 运算用
    move(pseudoHdr, p^, pseudohdrlen);
    inc(p, pseudohdrlen);
    lpudpHdr := pudpHead(p);
    move(udpHdr, p^, udphdrlen);
    inc(p, udphdrlen);
    move(data^, p^, datalen);
    inc(p, datalen);
    lpudpHdr^.checksum := checksum(p0, p - p0);
    // copy ip头;覆盖伪ip头
    p := buf;
    lpipHdr := pipHead(p);
    move(ipHdr, p^, iphdrlen);
    lpipHdr^.ipchksum := checksum(buf, iphdrlen); // ip头// Send the raw socket packet
    result := sendto(hsocket, buf, ipSize, 0, @Remote, SizeOf(Remote));
    if result = SOCKET_ERROR then
    begin
        str := 'sendto() failed: ' + IntToStr(WSAGetLastError);
        SendMessage(FdwNotifyWnd, WM_STRINFO, integer(str), 0);
        exit;
    end;
    end;
    function TRawSocket.sendUdpDataFrag(srcIP, dstIP: string; srcPort, dstPort:
    word; data: pchar; dataLen: integer): Integer;
    const
    fraglen = 1472; // 分片的数据长度 1500(以太网MTU)-20(IP头长)-8(UDP头长)
    var
    ipHdr: _ipHead;
    udpHdr: _udpHead;
    pseudoHdr: _pseudoHead;
    ipSize, udpSize: Word;
    iphdrlen, pseudohdrlen, udphdrlen: Word;
    lpipHdr: pipHead;
    lpudpHdr: pudpHead;
    p, p0: PChar;
    Local: TSockAddrIn;
    Remote: TSockAddrIn;
    i, j, k: integer;
    begin
    inc(idt); // test
    // 功能:分片发送ip 分片包UDP协议
    Local.sin_family := AF_INET;
    Local.sin_addr.S_addr := inet_Addr(PChar(srcIP));
    Local.sin_port := htons(srcPort);Remote.sin_family := AF_INET;
    Remote.sin_addr.S_addr := inet_Addr(PChar(dstIP));
    Remote.sin_port := htons(dstPort);iphdrlen := sizeof(_ipHead);
    udphdrlen := sizeof(_udpHead);
    pseudohdrlen := sizeof(pseudoHdr);j := datalen div fraglen;
    if (datalen mod fraglen) = 0 then j := j - 1;
    for i := 0 to j do
    begin
        if datalen > (i + 1) * fraglen then k := fraglen + udpHdrLen
        else k := datalen - i * fraglen;
        ipSize := iphdrlen + udphdrlen + k;
        udpSize := ipSize - iphdrlen;
    // 初始化 IP 头
        ipHdr.ver_IHL := (4 shl 4) or (sizeof(ipHdr) div 4);
        ipHdr.serverType := 0; // IP type of service
        ipHdr.totalLen := htons(ipSize); // Total packet len
        ipHdr.ident := htons(idt); // Unique identifier: set to 0
        // Fragment offset field
        if i = 0 then ipHdr.flags_off := htons($2000) // 第一片
        else if i < j then ipHdr.flags_off := htons($2000 or (fraglen + udpHdrLen) * i) // 中间片
        else ipHdr.flags_off := htons((fraglen + udpHdrLen) * i); // 最后一片
        ipHdr.ttl := 128; // Time to live
        ipHdr.protocol := 17; // Protocol(UDP)
        ipHdr.ipchksum := 0; // IP checksum
        ipHdr.srcAddr := Local.sin_addr.S_addr; // Source address
        ipHdr.dstAddr := Remote.sin_addr.S_addr; // Destination address// 初始化 UDP 头
        udpHdr.srcPort := Local.sin_port;
        udpHdr.dstPort := Remote.sin_port;
        udpHdr.Length := htons(udpSize);
        udpHdr.checksum := 0;// 初始化 伪ip 头
        pseudoHdr.srcAddr := ipHdr.srcAddr;
        pseudoHdr.dstAddr := ipHdr.dstAddr;
        pseudoHdr.unused := 0;
        pseudoHdr.protocol := ipHdr.protocol;
        pseudoHdr.Length := udpHdr.Length;    p := buf + iphdrlen - pseudohdrlen;
        p0 := P; // 备份伪ip头指针p0,checksum 运算用
        move(pseudoHdr, p^, pseudohdrlen);
        inc(p, pseudohdrlen);
        lpudpHdr := pudpHead(p);
        move(udpHdr, p^, udphdrlen);
        inc(p, udphdrlen);
        move(data^, p^, k);
        inc(p, k);
        lpudpHdr^.checksum := checksum(p0, p - p0);
    // copy ip头;覆盖伪ip头
        p := buf;
        lpipHdr := pipHead(p);
        move(ipHdr, p^, iphdrlen);
        lpipHdr^.ipchksum := checksum(buf, iphdrlen); // ip头// Send the raw socket packet
        result := sendto(hsocket, buf, ipSize, 0, @Remote, SizeOf(Remote));
        if result = SOCKET_ERROR then
        begin
          str := 'sendto() failed: ' + IntToStr(WSAGetLastError);
          SendMessage(FdwNotifyWnd, WM_STRINFO, integer(str), 0);
          exit;
        end;end;
    result := datalen;
    end;
  • 相关阅读:
    Scrapy 概览笔记
    Python 依赖版本控制 (requirements.txt 文件生成和使用)
    Python 虚拟空间的使用
    macOS 所有版本 JDK 安装指南 (with Homebrew)
    鉴权那些事
    Java 位运算符和 int 类型的实现
    ASP.NET Core 入门教程 5、ASP.NET Core MVC 视图传值入门
    如何做好一次知识或技术分享
    ASP.NET Core 入门教程 4、ASP.NET Core MVC控制器入门
    ASP.NET Core 入门教程 3、ASP.NET Core MVC路由入门
  • 原文地址:https://www.cnblogs.com/moonwind/p/4450647.html
Copyright © 2011-2022 走看看