2014-01-13 52 views
3

我試圖創建一個有效的TCP連接到我的測試服務器以模擬GET請求。希望我非常接近解決方案。在Pcap.NET中創建一個有效的TCP連接

從一個真實的請求,利用Wireshark的數據,我已經成功發送使用PacketCommunicator.SendPacket()一個包時,爲了獲得SYN & SYN-ACK

enter image description here

不過,我似乎無法使ACK出現。

第一分組使用EthernetLayerIpV4LayerTcpLayer構成,而後者(當前非工作)使用剛剛提到+一個HttpRequestLayer的那些。

最後的數據包TcpLayerControlBits設置爲TcpControlBits.Acknowledgment。儘管如此,WireShark並沒有出現在我的「真正」GET請求中。

希望我已經發布了代碼的相關部分。如果沒有 - 請讓我知道。

回答

6

這是一個有效的草案(我檢查過)。

請將構建HttpGetSender實例時使用的值更改爲任何需要的值。

棘手的部分是讓序列和確認號碼正確。

using System; 
using System.Collections.Generic; 
using PcapDotNet.Core; 
using PcapDotNet.Packets; 
using PcapDotNet.Packets.Ethernet; 
using PcapDotNet.Packets.Http; 
using PcapDotNet.Packets.IpV4; 
using PcapDotNet.Packets.Transport; 

namespace SendingHttpGet 
{ 
    internal class HttpGetSender 
    { 
     public HttpGetSender() 
     { 
     } 

     public MacAddress SourceMac { get; set; } 
     public MacAddress DestinationMac { get; set; } 
     public IpV4Address SourceIpV4 { get; set; } 
     public IpV4Address DestinationIpV4 { get; set; } 
     public string Host { get; set; } 

     public void Run(PacketDevice device) 
     { 
      using (PacketCommunicator communicator = device.Open(100, // name of the device 
                   PacketDeviceOpenAttributes.Promiscuous, 
                   // promiscuous mode 
                   100)) // read timeout 
      { 
       SendSyn(communicator); 
       WaitForAck(communicator); 
      } 
     } 

     private void WaitForAck(PacketCommunicator communicator) 
     { 
      communicator.SetFilter("tcp and src " + DestinationIpV4 + " and dst " + SourceIpV4 + " and src port " + _destinationPort + " and dst port " + _sourcePort); 
      Packet packet; 
      while (true) 
      { 
       if (communicator.ReceivePacket(out packet) == PacketCommunicatorReceiveResult.Ok) 
       { 
        if (packet.Ethernet.IpV4.Tcp.AcknowledgmentNumber == _expectedAckNumber) 
        { 
         _seqNumber = _expectedAckNumber; 
         _ackNumber = packet.Ethernet.IpV4.Tcp.SequenceNumber + 1; 
         SendGet(communicator); 
         break; 
        } 

       } 
       SendSyn(communicator); 
      } 
      WaitForResponse(communicator); 
     } 

     private void WaitForResponse(PacketCommunicator communicator) 
     { 
      communicator.SetFilter("tcp and src " + DestinationIpV4 + " and dst " + SourceIpV4 + " and src port " + _destinationPort + " and dst port " + _sourcePort); 
      Packet packet; 
      while (true) 
      { 
       if (communicator.ReceivePacket(out packet) == PacketCommunicatorReceiveResult.Ok) 
       { 
        Console.WriteLine("Expected ack number: " + _expectedAckNumber); 
        Console.WriteLine("Received ack number: " + packet.Ethernet.IpV4.Tcp.AcknowledgmentNumber); 
        if (packet.Ethernet.IpV4.Tcp.AcknowledgmentNumber == _expectedAckNumber) 
        { 
         break; 
        } 

       } 
       SendGet(communicator); 
      } 
     } 

     private void SendSyn(PacketCommunicator communicator) 
     { 
      // Ethernet Layer 
      EthernetLayer ethernetLayer = new EthernetLayer 
               { 
                Source = SourceMac, 
                Destination = DestinationMac, 
               }; 

      // IPv4 Layer 
      IpV4Layer ipV4Layer = new IpV4Layer 
             { 
              Source = SourceIpV4, 
              CurrentDestination = DestinationIpV4, 
              Ttl = 128, 
              Fragmentation = 
               new IpV4Fragmentation(IpV4FragmentationOptions.DoNotFragment, 0), 
              Identification = 1234, 
             }; 

      // TCP Layer 
      TcpLayer tcpLayer = new TcpLayer 
            { 
             SourcePort = _sourcePort, 
             DestinationPort = _destinationPort, 
             SequenceNumber = _seqNumber, 
             ControlBits = TcpControlBits.Synchronize, 
             Window = _windowSize, 
            }; 

      communicator.SendPacket(PacketBuilder.Build(DateTime.Now, ethernetLayer, ipV4Layer, tcpLayer)); 
      _expectedAckNumber = _seqNumber + 1; 
     } 

     private void SendGet(PacketCommunicator communicator) 
     { 
      // Ethernet Layer 
      EthernetLayer ethernetLayer = new EthernetLayer 
      { 
       Source = SourceMac, 
       Destination = DestinationMac, 
      }; 

      // IPv4 Layer 
      IpV4Layer ipV4Layer = new IpV4Layer 
      { 
       Source = SourceIpV4, 
       CurrentDestination = DestinationIpV4, 
       Ttl = 128, 
       Fragmentation = 
        new IpV4Fragmentation(IpV4FragmentationOptions.DoNotFragment, 0), 
       Identification = 1235, 
      }; 

      // TCP Layer 
      TcpLayer tcpLayer = new TcpLayer 
      { 
       SourcePort = _sourcePort, 
       DestinationPort = _destinationPort, 
       SequenceNumber = _seqNumber, 
       AcknowledgmentNumber = _ackNumber, 
       ControlBits = TcpControlBits.Acknowledgment, 
       Window = _windowSize, 
      }; 

      // HTTP Layer 
      HttpLayer httpLayer = new HttpRequestLayer 
      { 
       Uri = "/", 
       Header = new HttpHeader(HttpField.CreateField("Host", Host)), 
       Method = new HttpRequestMethod(HttpRequestKnownMethod.Get), 
       Version = HttpVersion.Version11, 
      }; 

      Packet packet = PacketBuilder.Build(DateTime.Now, ethernetLayer, ipV4Layer, tcpLayer, httpLayer); 
      communicator.SendPacket(packet); 
      _expectedAckNumber = (uint) (_seqNumber + packet.Ethernet.IpV4.Tcp.PayloadLength); 
     } 

     private ushort _sourcePort = (ushort) (4123 + new Random().Next() % 1000); 
     private ushort _destinationPort = 80; 
     private uint _seqNumber = (uint) new Random().Next(); 
     private uint _expectedAckNumber; 
     private ushort _windowSize = 8192; 
     private uint _ackNumber; 
    } 

    internal class Program 
    { 
     private static void Main(string[] args) 
     { 
      // Retrieve the device list from the local machine 
      IList<LivePacketDevice> allDevices = LivePacketDevice.AllLocalMachine; 

      if (allDevices.Count == 0) 
      { 
       Console.WriteLine("No interfaces found! Make sure WinPcap is installed."); 
       return; 
      } 

      // Print the list 
      for (int i = 0; i != allDevices.Count; ++i) 
      { 
       LivePacketDevice device = allDevices[i]; 
       Console.Write((i + 1) + ". " + device.Name); 
       if (device.Description != null) 
        Console.WriteLine(" (" + device.Description + ")"); 
       else 
        Console.WriteLine(" (No description available)"); 
      } 

      int deviceIndex = 0; 
      do 
      { 
       Console.WriteLine("Enter the interface number (1-" + allDevices.Count + "):"); 
       string deviceIndexString = Console.ReadLine(); 
       if (!int.TryParse(deviceIndexString, out deviceIndex) || 
        deviceIndex < 1 || deviceIndex > allDevices.Count) 
       { 
        deviceIndex = 0; 
       } 
      } while (deviceIndex == 0); 

      // Take the selected adapter 
      PacketDevice selectedDevice = allDevices[deviceIndex - 1]; 

      HttpGetSender sender = new HttpGetSender 
             { 
              SourceMac = new MacAddress("your:host:mac:address:1:2"), 
              DestinationMac = new MacAddress("gateway:mac:address:1:2:3"), 
              SourceIpV4 = new IpV4Address("your.host.ip.address"), 
              DestinationIpV4 = new IpV4Address("target.host.ip.address"), 
              Host = "targethost.com", 
             }; 

      sender.Run(selectedDevice); 
     } 
    } 
} 
+0

非常感謝您抽出時間。 WireShark現在看起來好多了。但是,服務器似乎沒有拿起它。除了需要修改的'sender'屬性外,還有什麼?例如,如果'HttpLayer'中的'Uri'被設置爲'/'? – Johan

+0

那麼,如果你用來發送這個數據包的主機是活動的,它可能會看到它沒有發送的TCP連接的響應,並且會發送一個RST數據包來終止服務器中的連接。是的,你應該看到通常在一個正常的HTTP GET數據包併發送類似的東西。 – brickner

相關問題