Building a packet from scratch (under Windows) lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- role_33 · 2024-11-04 04:08 Hello all, I need to communicate (from Windows) with a networked device, and unfortunately this is not something I have dealt with before (not from the programming perspective, anyway). This means that, besides not knowing exactly how to implement the communications, I'm not sure what to look for. Using Wireshark it looks like they are just sending a packet containing an IP header, a TCP header, and the raw bytes (something similar to https://inc0x0.com/tcp-ip-packets-introduction/tcp-ip- packets-3-manually-create-and-send-raw-tcp-ip-packets/ , but with ~20 data bytes at the end). The actual captures are on my work computer :/ So... apparently it's just a matter of populating a custom packet with the correct information. However, from what I have found, it looks like this is not easy to do from Windows. Here's the catch: I used ChatGPT to generate some sample code, and -although it starts by warning it requires some Linux features- the code compiles happily under windows with minimal changes. But it doesn't send anything (Wireshark doesn't see anything on that network interface) - and I don't know if the problem is the code, or if it's a Windows limitation. On a few posts I saw people indicating NPCAP was necessary to create custom packets, but don't explain much more. Wireshark does install NPCAP, for that matter. My question is: is it possible to use Sockets under windows to create (and send) custom packets? If Sockets won't do the trick, is there a package (or something) I can use to it? I know of the existence of Synapse, but I'm not sure it allows to do this low-level packet crafting. Thanks! J The code from the AI thingie is as follows (with a couple changes - from memory): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program SendRawTCPPacket; {$mode objfpc}{$H+} uses  SysUtils, Sockets, ctypes; //BaseUnix; // J: Commenting out Linux stuff type  TIpHeader = packed record    ver_len: Byte;              // Version and header length    tos: Byte;                  // Type of service    total_len: Word;          // Total length    id: Word;                   // Identification    frag_offset: Word;          // Fragment offset and flags    ttl: Byte;                  // Time to live    proto: Byte;              // Protocol (TCP = 6)    checksum: Word;             // Header checksum    src_addr: LongWord;         // Source IP address  dest_addr: LongWord;        // Destination IP address  end;   TTcpHeader = packed record    src_port: Word;             // Source port    dest_port: Word;            // Destination port    seq_num: LongWord;          // Sequence number    ack_num: LongWord;          // Acknowledgment number    offset_res: Byte;           // Data offset and reserved bits    flags: Byte;                // Flags    window: Word;               // Window size    checksum: Word;           // Checksum    urgent_ptr: Word;           // Urgent pointer  end; var  sock: cint;  destAddr: sockaddr_in;  packet: array[0..39] of Byte;  ipHeader: TIpHeader;  tcpHeader: TTcpHeader;  destIp: string;  destPort: Word; function CalculateChecksum(buffer: PWord; size: Integer): Word;var  sum: LongWord;  i: Integer;begin  sum := 0;  for i := 0 to (size div 2) - 1 do    Inc(sum, buffer[i]);   // Add carry bits  while (sum shr 16) > 0 do    sum := (sum and $FFFF) + (sum shr 16);   Result := not Word(sum);end; begin  // Set destination IP and port  destIp := '192.168.1.1';      // Replace with the target IP  destPort := 80;               // Replace with the target port (HTTP)   // Create a raw socket  sock := fpSocket(AF_INET, SOCK_RAW, IPPROTO_TCP);  if sock < 0 then  begin    writeln('Failed to create raw socket. Root privileges are required.');    halt(1);  end;   // Set up destination address  FillChar(destAddr, SizeOf(destAddr), 0);  destAddr.sin_family := AF_INET;  destAddr.sin_port := htons(destPort);  destAddr.sin_addr.s_addr := StrToHostAddr(destIp).s_addr;   // Create IP header  FillChar(ipHeader, SizeOf(ipHeader), 0);  ipHeader.ver_len := (4 shl 4) or (SizeOf(ipHeader) div 4); // IPv4 and header length  ipHeader.ttl := 64;  ipHeader.proto := IPPROTO_TCP;  ipHeader.src_addr := StrToHostAddr('192.168.1.100').s_addr; // Replace with your IP  ipHeader.dest_addr := destAddr.sin_addr.s_addr;  ipHeader.total_len := htons(SizeOf(ipHeader) + SizeOf(tcpHeader));  ipHeader.checksum := CalculateChecksum(@ipHeader, SizeOf(ipHeader));   // Create TCP header  FillChar(tcpHeader, SizeOf(tcpHeader), 0);  tcpHeader.src_port := htons(12345);      // Arbitrary source port  tcpHeader.dest_port := htons(destPort);  tcpHeader.seq_num := htonl(1);  tcpHeader.ack_num := 0;  tcpHeader.offset_res := (SizeOf(tcpHeader) div 4) shl 4;  tcpHeader.flags := $02;                  // SYN flag  tcpHeader.window := htons(1024);  tcpHeader.checksum := CalculateChecksum(@tcpHeader, SizeOf(tcpHeader));   // Combine headers into packet  Move(ipHeader, packet, SizeOf(ipHeader));  Move(tcpHeader, packet[SizeOf(ipHeader)], SizeOf(tcpHeader));   // Send packet  if fpSendTo(sock, @packet, SizeOf(packet), 0, @destAddr, SizeOf(destAddr)) < 0 then    writeln('Failed to send packet.')  else    writeln('Packet sent successfully.');   // Close socket  //fpClose(sock); // J: Not available in Sockets under Windows  CloseSocket(sock)end. ---------------------------------------------------------------------- DonAlfredo · 2024-11-04 07:23 The mORmot2 has a nice OS-independent socket implementation. https://github.com/synopse/mORMot2/blob/master/src/net/mormot.net.sock .pas Works very well on many OS, including Windows. ---------------------------------------------------------------------- MarkMLl · 2024-11-04 08:59 Quote from: role_33 on November 04, 2024, 05:08:08 amThe code from the AI thingie is as follows (with a couple changes - from memory): Please do not quote AI-generated code, since the next time an AI walks this forum it will reinforce its belief that it is a viable solution: even if in fact it is utter rubbish. I think we need to know more about what you're trying to do and the device at the far end. Specifically, are you absolutely sure that you're using TCP- which is not normally packet-based- or are you using TCP/IP as a generic term? MarkMLl ---------------------------------------------------------------------- Warfley · 2024-11-04 12:00 TCP is a stream based protocol. You can't just simply send TCP packets and expect anything to work. TCP maintains an internal state (sequence number, acknowledge number, congestion window and a whole bunch more). So if you don't want to intercept an existing stream, you need to establish your own TCP connection to the device and then communicate with whatever application layer protocol the device is using. A simple TCP stream you can easily open up with TSocketStream from the unit ssockets. It follows roughly the Berkley Sockets API which you should get familiar with anyway if you want to do anything with regards to networking. But the more interesting thing is of course what the application layer protocol is, if there is TLS encryption, etc. Without that knowledge you won't be able to do anything ---------------------------------------------------------------------- MarkMLl · 2024-11-04 12:50 Quote from: Warfley on November 04, 2024, 01:00:21 pmTCP is a stream based protocol. You can't just simply send TCP packets and expect anything to work. TCP maintains an internal state (sequence number, acknowledge number, congestion window and a whole bunch more). It is of course common to build ICMP and UDP packets from scratch (ping, WOL etc.), which is why I think we might possibly have a terminology problem here. It is of course common to send a brief TCP stream to a remote port. But the only time I've had consider building TCP packets from scratch- particularly with customised header information- was when doing a bit of hacking against a local-but-undocumented device... and even there a simple fpConnect() with careful examination of the response might have been adequate. (I'd have to work through my code in more detail to check that... looking at my notes suggests that I had to do it that way because I wanted to look very carefully at application-level checksums etc... but that my code's brute-force performance was still a long way behind Nmap etc.) MarkMLl ---------------------------------------------------------------------- role_33 · 2024-11-04 19:23 Quote from: MarkMLl on November 04, 2024, 09:59:35 amQuote from: role_33 on November 04, 2024, 05:08:08 amThe code from the AI thingie is as follows (with a couple changes - from memory): Please do not quote AI-generated code, since the next time an AI walks this forum it will reinforce its belief that it is a viable solution: even if in fact it is utter rubbish. I think we need to know more about what you're trying to do and the device at the far end. Specifically, are you absolutely sure that you're using TCP- which is not normally packet-based- or are you using TCP/IP as a generic term? MarkMLl Point taken. Unfortunately, my actual code resides at a company computer, and the moment I take *anything* out of it I'll be answering questions for the next 3 months, so I just posted the original code spitted out by the mightly overlord :/ Which -surprisingly- compiles just fine And you are correct: I'm using TCP/IP as a generic term. The device I'm working with is a piece of automotive hardware, and I'm afraid I can't say much more without getting myself in trouble. This piece of hardware runs a daemon that responds to the data sent to it, but there's no mention on the spec about HOW to send that data, so I'm relying on my observations of what Wireshark reports. Namely, the packet contains: - Destination MAC Address | Source MAC addresses | 0x0800 (IPv4, StreamIndex 0) - A standard IPV4 header. It reports the protocol to be TCP (6) - A standard TCP header - Some data bytes <-- This is the only thing contained in the specs I received The IPv4 and TCP headers look just like the ones on the website I linked (except the flags set are different) Wireshark reports the "Protocols in frame" as eth:ethertype:ip:tcp:data The (redacted) packet looks like this: Code: [Select]Frame 10: 73 bytes on wire (584 bits), 73 bytes captured (584 bits) on interface \Device\NPF_{xxxxxxxxxxx-xxxx-xxxx-xxxx- xxxxxxxxxxxx}, id 0     Section number: 1     Interface id: 0 (\Device\NPF_{xxxxxxxxxxx-xxxx-xxxx-xxxx- xxxxxxxxxxxx})     Encapsulation type: Ethernet (1)     Arrival Time: Oct 30, 2024 21:14:34.307664000 Eastern Daylight Time     UTC Arrival Time: Oct 31, 2024 01:14:34.307664000 UTC     Epoch Arrival Time: 1730337274.307664000     [Time shift for this packet: 0.000000000 seconds]     [Time delta from previous captured frame: 1.801229000 seconds]     [Time delta from previous displayed frame: 1.801229000 seconds]     [Time since reference or first frame: 6.935502000 seconds]     Frame Number: 10     Frame Length: 73 bytes (584 bits)     Capture Length: 73 bytes (584 bits)     [Frame is marked: False]     [Frame is ignored: False]     [Protocols in frame: eth:ethertype:ip:tcp:data]     [Coloring Rule Name: TCP]     [Coloring Rule String: tcp] Ethernet II, Src: (xx:xx:xx:xx:xx:xx), Dst: (xx:xx:xx:xx:xx:xx)     Destination: AsixElectron_dc:02:fd (00:0e:c6:dc:02:fd)     Type: IPv4 (0x0800)     [Stream index: 0] Internet Protocol Version 4, Src: 192.168.xxx.xxx, Dst: 192.168.xxx.xxx     0100 .... = Version: 4     .... 0101 = Header Length: 20 bytes (5)     Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)     Total Length: 59     Identification: 0x694d (26957)     010. .... = Flags: 0x2, Don't fragment     ...0 0000 0000 0000 = Fragment Offset: 0     Time to Live: 128     Protocol: TCP (6)     Header Checksum: 0x0000 [validation disabled]     [Header checksum status: Unverified]     Source Address: 192.168.xxx.xxx     Destination Address: 192.168.xxx.xxx     [Stream index: 0] Transmission Control Protocol, Src Port: xxxxx, Dst Port: xxxxx, Seq: 14, Ack: 17, Len: 19     Source Port: xxxxx     Destination Port: xxxxx     [Stream index: 0]     [Stream Packet Number: 4]     [Conversation completeness: Incomplete (12)]     [TCP Segment Len: 19]     Sequence Number: 14    (relative sequence number)     Sequence Number (raw): 3481193771     [Next Sequence Number: 33    (relative sequence number)]     Acknowledgment Number: 17    (relative ack number)     Acknowledgment number (raw): 769143398     0101 .... = Header Length: 20 bytes (5)     Flags: 0x018 (PSH, ACK)         000. .... .... = Reserved: Not set         ...0 .... .... = Accurate ECN: Not set         .... 0... .... = Congestion Window Reduced: Not set         .... .0.. .... = ECN-Echo: Not set         .... ..0. .... = Urgent: Not set         .... ...1 .... = Acknowledgment: Set         .... .... 1... = Push: Set         .... .... .0.. = Reset: Not set         .... .... ..0. = Syn: Not set         .... .... ...0 = Fin: Not set         [TCP Flags: ·······AP···]     Window: 512     [Calculated window size: 512]     [Window size scaling factor: -1 (unknown)]     Checksum: 0x5448 [unverified]     [Checksum Status: Unverified]     Urgent Pointer: 0     [Timestamps]     [SEQ/ACK analysis]     TCP payload (19 bytes) Data (19 bytes)     Data: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX     [Length: 19] Finally, yes, I'm aware there's a lot more to the communication with any device. I just want to make sure I manage to put something out on the NIC (i.e. making sure I'm using the correct method) before investing a lot of time on this approach. I was expecting the device I'm trying to communicate with to reject the packet, but I think it's failing before anything is put out there. J ---------------------------------------------------------------------- MarkMLl · 2024-11-04 20:24 OK, so establish the TCP connection (behind the scenes several handshake packets are exchanged) then send byte sequence as required and either wait or close the connection. For something like this you should find the standard sockets unit entirely adequate. Strictly speaking, you don't know whether your byte sequence goes as one or multiple packets: that detail's handled by the TCP protocol stack. In practical terms I'd expect it to be a single packet up to ~1Kbytes, but TCP handles byte streams rather than datagrams/packets which are the province of UDP. If you were in the UK and you needed confidential help I'd suggest we did it via a one-penny order/invoice (i.e. enough to establish a contractual relationship) but it sounds like you're getting to grips with things fairly nicely :-) MarkMLl ---------------------------------------------------------------------- BSaidus · 2024-11-04 20:34 Hello, I remember somedays (years) ago, I used libnet for building a custom packets see : https://github.com/libnet/libnet ---------------------------------------------------------------------- MarkMLl · 2024-11-04 21:10 Quote from: BSaidus on November 04, 2024, 09:34:52 pmI remember somedays (years) ago, I used libnet for building a custom packets see : https://github.com/libnet/libnet Yes, but (checking the link) I think that's more oriented towards Nmap-style port-scanning etc. Broadly speaking I think we've managed to get past that, to the stage where we're just crafting a sequence of bytes to be sent (i.e. the sort of thing netcat or echo>netpipes could do). My professional curiosity is reined in, but I remember a colleague whose PhD was based on automotive networking and was sponsored by Ripaults. MarkMLl ---------------------------------------------------------------------- Warfley · 2024-11-04 22:10 Quote from: role_33 on November 04, 2024, 08:23:06 pmThe device I'm working with is a piece of automotive hardware, and I'm afraid I can't say much more without getting myself in trouble. This piece of hardware runs a daemon that responds to the data sent to it, but there's no mention on the spec about HOW to send that data, so I'm relying on my observations of what Wireshark reports. Again, it's TCP, think in connections and streams. What do you want to do? Do you want to intercept an existing stream or do you want (to replay) your own stream? If you don't know, look at the communication of the real software you are capturing. Is the communication in short connections, e.g. a request response scheme where each request has its own connection? Easiest way to check is to check the port numbers of the client, if they change regularly, it's probably a new connection. But port numbers can be fixed so alternatively check for TCP handshakes and fin packages (Wireshark can filter those) If this is the case take all the packets that belong to one connection (i.e. from syn to fin) concat the data sent and just put it into a TCP stream socket and see what happens. If there is one connection that you want to intercept, it's gonna be much harder, because as I said already, TCP has internal state, meaning you need to read out the state from the communications, and then craft your own custom TCP packets using IP RAW sockets: https://learn.microsoft.com/en-us/windows/win32/winsock/tcp-ip-raw- sockets-2 The problem then is that any packets you intercept will mess up the state at your actual client and it will probably crash whatever application it is you are running. Instead you should just provide your application as proxy service which can intercept messages in between. This way a consistent state is maintained at the real client, preventing it from crashing ---------------------------------------------------------------------- Remy Lebeau · 2024-11-05 10:09 Quote from: role_33 on November 04, 2024, 08:23:06 pmNamely, the packet contains: - Destination MAC Address | Source MAC addresses | 0x0800 (IPv4, StreamIndex 0) - A standard IPV4 header. It reports the protocol to be TCP (6) - A standard TCP header - Some data bytes <-- This is the only thing contained in the specs I received Then there is no reason you shouldn't be able to use a standard TCP socket via the Winsock API on Windows to establish a TCP connection and send packets. You don't need to concern yourself with the Ethernet, IP, and TCP headers, Winsock will handle those for you. Focus only on the data stream, per the specs. ---------------------------------------------------------------------- role_33 · 2024-11-06 17:36 Hello peeps, @Warfley: the device I'm talking to just responds to commands being sent on the data portion of the packet (and sends an acknowledgment packet back). There isn't a "stream" per se (besides the package sequence numbering) and no need to intercept packages from other devices. The ports are well defined (always the same). I have one piece of software right now that can communicate with this device, but it's closed source, support is *bad*, doesn't have an API, and it has a million options I don't need. This software crashing is the main reason I'm looking into developing an alternative. @Remy: can you point me to an example that does something similar - under Windows? I haven't tried recently, but I recall that when I first attempted to send the data packets, those resulted on something different (and much larger) than what the packets I can see on Wireshark from the (bad, but somewhat working) existing program. J ---------------------------------------------------------------------- MarkMLl · 2024-11-06 18:22 Quote from: role_33 on November 06, 2024, 06:36:03 pmThere isn't a "stream" per se (besides the package sequence numbering) Oh yes there is. /By/ /definition/ TCP is a stream protocol, and neither end knows- or should care- whether the other is handling it in largish chunks, byte-by-byte and so on. The sequence numbers (unless you're adding some at the application level) are outside your control. In particular they change arbitrarily if the TCP passes through something that isn't IP at some intermediate routing stage, if it's rewritten by NAT, or if a long TCP message is broken into multiple shorter ones (or vice versa). MarkMLl ---------------------------------------------------------------------- Warfley · 2024-11-06 18:41 Ok, just lets make it very simple, you have this packet with the data that is sent to the device, just try to open a connection and send the data manually: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program Project1; {$mode objfpc}{$H+} uses  ssockets; const  {Put in the data you read out of wireshark }  DataToSend: Array[0..18] of Byte = ($00,$ 00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 );var  s: TInetSocket;  buff: array[0..1023] of Byte;begin  s:=TInetSocket.Create('IP of your device', Port of your Device);  try    s.Connect;    s.write(DataToSend,Length(DataToSend)));    s.Read(buff,SizeOf(buff));  finally    s.Free;  end;end. And look what happens. If it works (in that the connection is at least accepted, what happens afterwards I can't tell), you know the device is kind of using one-shot request response schemes. Then it is rather easy. ---------------------------------------------------------------------- role_33 · 2024-11-06 18:46 Ok... let's reword that The only packets on that NIC going to/from the device I'm communicating with are the ones generated when the control software sends a user-initiated command (and that's exactly one packet per command, unless the DF flag on the IPv4 allows fragmentation somehow), and the acknowledgement from the device (one packet). From time to time you see the computer trying to find something there using UDP, but I know for a fact the device ignores those. There isn't any kind of handshaking going on between the computer and the device on a regular basis. I intend to replace the piece of cr_p software that is currently being used completely, so I don't risk any conflicts. J ---------------------------------------------------------------------- role_33 · 2024-11-06 19:37 Quote from: Warfley on November 06, 2024, 07:41:22 pmOk, just lets make it very simple, you have this packet with the data that is sent to the device, just try to open a connection and send the data manually: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program Project1; {$mode objfpc}{$H+} uses  ssockets; const  {Put in the data you read out of wireshark }  DataToSend: Array[0..18] of Byte = ($00,$ 00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 );var  s: TInetSocket;  buff: array[0..1023] of Byte;begin  s:=TInetSocket.Create('IP of your device', Port of your Device);  try    s.Connect;    s.write(DataToSend,Length(DataToSend)));    s.Read(buff,SizeOf(buff));  finally    s.Free;  end;end. And look what happens. If it works (in that the connection is at least accepted, what happens afterwards I can't tell), you know the device is kind of using one-shot request response schemes. Then it is rather easy. And we have traffic! Thanks! No response, but traffic, which is progress. When I try to run this, the s.connect fails. It raises an exception (ESocketError / "Connect to failed") From inspecting the packet with Wireshark, the main thing I can see right now is that the packet from the original software has: Code: [Select]    [Protocols in frame: eth:ethertype:ip:tcp:data]     [Coloring Rule Name: TCP]     [Coloring Rule String: tcp] as opposed tothe one from your code: Code: [Select]    [Protocols in frame: eth:ethertype:ip:tcp]     [Coloring Rule Name: TCP SYN/FIN]     [Coloring Rule String: tcp.flags & 0x02 || tcp.flags.fin == 1] Where can I control the flags passed? J ---------------------------------------------------------------------- Warfley · 2024-11-06 20:19 You can't, as was said multiple times in this thread, TCP is a stream based protocol. Syn packets are used to setup the stream. The problem seems to be that your device can only ever hold one stream at a time, meaning when the other, original software is running and has that stream setup, you cannot connect from a different application. This is why it is failing on the connect. So you have two options, either disconnect the other software (temporarily) and while it's down establish your own stream, or you must intercept the existing stream. ---------------------------------------------------------------------- MarkMLl · 2024-11-06 20:55 Quote from: Warfley on November 06, 2024, 09:19:31 pmYou can't, as was said multiple times in this thread, TCP is a stream based protocol. Syn packets are used to setup the stream. I resisted the temptation to point that out before you did :-) There's been tomes written on the innards of TCP, and the significance of the packet flags (SYN etc.), connection parameters (DF etc.) and RFC-recognised options (window size etc.). However by and large THE APPLICATION PROGRAMMER DOES NOT NEED TO GET INVOLVED WITH THAT STUFF. QuoteThe problem seems to be that your device can only ever hold one stream at a time, meaning when the other, original software is running and has that stream setup, you cannot connect from a different application. This is why it is failing on the connect. Makes sense. IOW, either the device is using a fairly low-end embedded OS with absolutely minimal multitasking capability, or it's running e.g. Linux but the backlog parameter passed to the listen() function is 1. Again, there's nothing the programmer at the client end can do to change this. MarkMLl ---------------------------------------------------------------------- role_33 · 2024-11-06 21:40 Thank you, gents! @Warfley: the only software running on the computer attached to the device was my Lazarus test program. The other software had not been run on either my computer nor the device after I powered it up this morning - meaning the only stream was the one I created by using your code. Now knowing what to look for, I checked the logs again. - I started the other piece of software and established the connection (literally, press "Connect"). - I can see a SYN package being sent. Specifically: Code: [Select]  [C] -> [Broadcast] ARP packet   [H] -> [C] ARP packet   [C] -> [H] ping   [H] -> [C] ping   [C] -> [H] ping   [H] -> [C] ping   [H] -> [C] ARP packet   [C] -> [H] ARP packet   [C] -> [H] SYN packet   [H] -> [C] SYN, ACK packet   .   .   . Where  [C]: client/PC, and [H]: host/device I just tested something, though: just creating the TInetSocket and freeing it immediately after: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Test;var  s: TInetSocket;begin  s:=TInetSocket.Create('192.168.xxx.xxx', );  s.Free;end; ... and this generates more traffic than just establishing the connection on the original software. Perhaps the device is expecting those pings? I dunno... Anyway: I'll do some more tests before I bug you guys again. I appreciate your help, a lot! Thanks! J ---------------------------------------------------------------------- MarkMLl · 2024-11-06 22:42 SYN and SYN/ACK are part of the "three-way handshake" which establishes a TCP connection. There's always the possibility that the supplier-provided client and server were "being clever", but by and large I'd expect you to only need to look at the data messages. I almost wrote "packets" there, but again must emphasise that TCP is not a packet-oriented protocol. MarkMLl ---------------------------------------------------------------------- Warfley · 2024-11-06 23:38 Quote from: role_33 on November 06, 2024, 10:40:38 pmSpecifically: Code: [Select]  [C] -> [Broadcast] ARP packet   [H] -> [C] ARP packet   [C] -> [H] ping   [H] -> [C] ping   [C] -> [H] ping   [H] -> [C] ping   [H] -> [C] ARP packet   [C] -> [H] ARP packet   [C] -> [H] SYN packet   [H] -> [C] SYN, ACK packet   .   .   . Where  [C]: client/PC, and [H]: host/device Just as a quick explaination. ARP is the protocol thats used to figure out which machine has which local IP address. Basically whenever you try to connect to some device with a certain IP address your computer starts with broadcasting onto the network "Hey who'se got the IP for XXX", and the device with that IP then answers. Basically screaming into the void and hoping someone responds. This is exactly what you see before the first ping. Then before setting up the TCP connection, the same happens again, just instead of a broadcast, because the PC already knows the target, they just ask directly: "Hey do you still have that IP" and get a response. So just consider these as noise. Quote from: role_33 on November 06, 2024, 10:40:38 pm... and this generates more traffic than just establishing the connection on the original software. Perhaps the device is expecting those pings? I dunno... I mean it wouldn't be something I would generally call a good practice (ICMP packets are often by many routers, active switches and so on, depriorized or completely dropped) so relying on ICMP communication is really wonky, that said, you are talking about specialized embedded hardware, and I have seen all kinds of stuff where the engineers have tried to "be smart". Maybe look into the Ping packages, maybe they do some special stuff in there. ICMP messages can have additional data, which is not part of the protocol itself, but maybe the device does some special stuff there. Doing ICMP is not that trivial, as it requires to work with IP_RAW sockets, and I don't think the fcl has a native implementation. I think indy supports ICMP sockets, so you may look into that direction. ---------------------------------------------------------------------- MarkMLl · 2024-11-07 07:48 Quote from: Warfley on November 07, 2024, 12:38:19 amMaybe look into the Ping packages, maybe they do some special stuff in there. ICMP messages can have additional data, which is not part of the protocol itself, but maybe the device does some special stuff there. Doing ICMP is not that trivial, as it requires to work with IP_RAW sockets, and I don't think the fcl has a native implementation. I think indy supports ICMP sockets, so you may look into that direction. Also: Does Wireshark explicitly describe those as pings (i.e. ICMP echos), or are you mistakenly assuming that anything ICMP is a ping? There's several commands other than ping, and some of those are potentially important. I think I've used a DLL which gave me fairly painless ping access back in my Windows days. It's more of a problem on unix (i.e. including Linux) since a program that wants to send an ICMP message (of any type) generally needs elevated capabilities. MarkMLl ---------------------------------------------------------------------- role_33 · 2024-11-07 17:05 Hello Gents, Thank you for the suggestion to look into the PING packets. Wireshark does identify them as ping echo, request/reply ("eth.ethertype.ip.icmp.data"). I sent a PING command from the command prompt, and from what I can see the packets do look slightly different, but I'm not sure how significant that is: - the TTL on the ping from my windows machine is 128, but the one from the old software is 255 - the 32 byte data on the ping from CMD is the typical alphabet sequence, but from the old software it's all zeros Besides these two differences, everything else looks the same (minus the timestamps, sequence numbers, etc.) Just because it's not Friday yet (i.e. there's still some weekly pain to be inflicted) , shall I assume that customizing the PING command (using e.g. Synapse) is not an option? Thx! J ---------------------------------------------------------------------- MarkMLl · 2024-11-07 17:16 The TTL limits the number of network hops so is unlikely to be relevant. The payload is simply cruft and is also unlikely to be relevant. Having said that a ping could /potentially/ be used for a wakeup/knocking sequence, but it's not very likely. MarkMLl ---------------------------------------------------------------------- Warfley · 2024-11-07 17:25 What you can try is very simply the following: use the windows ping util to send two pings and then try to connect and look what happens: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  s:TInetSocket;  outp:string;begin  { Send two pings }  RunCommand('ping', ['-n', '2', DeviceIP], outp);  { Try to connect }  s:=TInetSocket.Create(DeviceIP,DevicePort);  s.connect;  s.Free;end. ---------------------------------------------------------------------- MarkMLl · 2024-11-07 17:43 Quote from: Warfley on November 07, 2024, 06:25:06 pmWhat you can try is very simply the following: use the windows ping util to send two pings and then try to connect and look what happens: Noting of course your earlier comment about the possibility that the server might only be prepared to handle one connection at a time, and noting also that it might require a "rest" of a minute or two between connections. It would also be worth having Wireshark active while doing this, and looking at the server's response when the connection is attempted: this might either be a TCP negotiation packet or an ICMP packet (one of the other roles of ICMP is error reporting). MarkMLl ---------------------------------------------------------------------- role_33 · 2024-11-08 22:48 Hello people, I hope this is not as stoopid as I feel right now, but: I went through Warfley's code step by step, looking at Wiresharks at each point, and I noticed that after creating the TInetSocket I already had the packets the old program (the one I want to get rid of) was sending at that point in time. So, I just removed the "Connect" command... and this thing is working. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  s: TInetSocket;  buff: array[0..1023] of Byte;begin  s:=TInetSocket.Create('IP of your device', Port of your Device);  try    //s.Connect; // -> Commenting this line out does the trick    s.write(DataToSend,Length(DataToSend)));    s.Read(buff,SizeOf(buff));  finally    s.Free;  end;end. I still need to do a bunch of things (one of the commands I need to implement is "send me a lot of data", so I need to implement receiving that data). But IT WORKS. Thank you, Thank you, Thank you!!! J ---------------------------------------------------------------------- MarkMLl · 2024-11-09 07:13 Quote from: role_33 on November 08, 2024, 11:48:47 pmI still need to do a bunch of things (one of the commands I need to implement is "send me a lot of data", so I need to implement receiving that data). But IT WORKS. The important thing to appreciate is that TCP data is just a stream... a sequence of bytes, not a TStream etc. but without any protocol- defined delimiters. MarkMLl ---------------------------------------------------------------------- Remy Lebeau · 2024-11-10 01:40 I feel like this discussion is going around in circles. Either the device/software is using standard TCP, or it is not. Rather than speculating any further, can you post the actual Wireshark capture of a working communication with the device? Then someone can give you a definitive answer as to how to replicate that session with your own code. ---------------------------------------------------------------------- role_33 · 2024-11-11 21:59 Hello Remy, The data coming out of these devices -and the communication protocol- is considered sensitive by my company, so I'm not free to post it. If I were to ask, I would bring unwanted unnecessary attention to my testing. However, it looks like the device is using standard TCP, but with some specific constraints (e.g. no fragmentation). As someone said somewhere, the main problem is between the chair and the keyboard. But with Mark and Wharfley's help, things are moving forward. I now need to capture the packets sent back by the device, to complete a proof-of-concept. J ---------------------------------------------------------------------- MarkMLl · 2024-11-12 07:51 I know that you've seen the DF flag but it's not relevant to local operation particularly if application-level messages already fit inside the lower-level MTU. Working from memory for example sizes, it would be relevant if you were sending 1 MByte messages over Ethernet with the standard 1K-ish MTU, or 64K messages over ATM with frame size 48 bytes. Apart from that, and I can assure you that we are all getting sick of trying to hammer this home, TCP is stream-based and neither end of the link should be making assumptions about fragmentation. If the equipment with which you are trying to communicate is assuming that just because it sees the first byte of an application-level message it can recover the final one as part of the same operation then it's broken, what's more that design flaw could potentially result in a security vulnerability. MarkMLl