DEV Community

Cover image for I Stripped Away the Vendor Software and Hand-Crafted 5 Industrial Handshakes From Scratch
404Saint
404Saint

Posted on

I Stripped Away the Vendor Software and Hand-Crafted 5 Industrial Handshakes From Scratch

By RUGERO Tesla (@404Saint).

A few weeks back, I wrote an article about how easy it is to take control of an unauthenticated PLC if you have network access. But pointing a script at a port and watching a variable change is only step one. It doesn’t tell you how the communication actually functions when it hits the wire.

If you read standard OT security textbooks, they give you high-level theoretical overviews. If you look at vendor documentation, they hide everything inside closed-source graphical interfaces.

I got tired of the abstraction. I wanted to see the raw bytes.

So, I built a lab environment called raw-industrial-protocols using nothing but lightweight Python socket twins running over a local Linux loopback interface. No heavy simulators. No proprietary vendor suites. Just standard network sockets injecting raw hex streams directly onto the wire to mimic, capture, and dissect the exact binary handshakes used by the critical infrastructure powering our world.

This is Layer Zero. And it's the trailer for a massive new standalone series where we will deeply study discovery, exploitation, defensive analysis, and protocol hardening for every major industrial suite.

Here is what happens when you drop beneath the software layer and look at the raw bytes.


The Industrial Wire Protocol Matrix

Before diving into the payloads, we have to look at how these stacks align. Most IT engineers assume industrial traffic is completely alien. In reality, it's just structured payloads riding on top of standard OSI transport models:

Protocol Default Port Transport Layer Framing Envelope Baseline Security
Modbus/TCP 502 TCP MBAP Header (7 Bytes) Explicitly None
DNP3 20000 TCP / UDP Custom EPA Link/Transport Layer Cleartext / Optional Auth
EtherNet/IP 44818 TCP / UDP Encapsulation Header (24 Bytes) Cleartext Session Tracking
S7Comm 102 TCP TPKT (RFC 1006) $\rightarrow$ COTP (ISO 8073) Cleartext by Design
OPC UA 4840 TCP Native Binary Layer Configurable (None to Sign/Encrypt)

Phase 1: Modbus/TCP — The Defacto Standard

Modbus/TCP is the grandfather of industrial automation. Engineered in the late 70s for serial links and later wrapped in a TCP envelope, it strips away old serial CRC checksums and introduces a 7-byte MBAP (Modbus Application Protocol) header.

When a client queries a PLC to read 10 holding registers starting at memory offset 0, it pushes this exact 12-byte payload into the raw TCP stream:

00 01 00 00 00 06 01 03 00 00 00 0A

Enter fullscreen mode Exit fullscreen mode
  • 00 01 (Transaction ID): Sequential identifier to pair requests and responses.
  • 00 00 (Protocol ID): Fixed zero-value reserved strictly for Modbus/TCP.
  • 00 06 (Length): A 16-bit integer confirming 6 bytes follow.
  • 01 (Unit ID): Routing drop index to cross hardware gateways.
  • 03 (Function Code): The explicit instruction mapping to Read Holding Registers.
  • 00 00 (Starting Address): Memory offset register zero.
  • 00 0A (Quantity): Requests exactly 10 contiguous registers.

Modbus TCP Live Packet Capture Verification


Phase 2: DNP3 — The Grid Anchor

The Distributed Network Protocol (DNP3) runs our electrical grids and water systems. Because it was designed to maintain reliable telemetry over unstable radio links, it implements a highly complex, rugged EPA (Enhanced Performance Architecture) stack. This structure maps out an explicit custom Data Link and pseudo-Transport layer directly over standard TCP packets.

A primary master node checking the basic Link Status of an outstation drops this precise 10-byte structure onto the wire:

05 64 05 C9 00 00 01 00 4D 50

Enter fullscreen mode Exit fullscreen mode
  • 05 64 (Start Bytes): Fixed magic hex header marking the start of a valid DNP3 frame.
  • 05 (Length): Identifies that 5 user data bytes follow (excluding the trailing CRC block).
  • C9 (Control Byte): Bitmask declaring frame parameters; 0xC9 triggers a primary link status request.
  • 00 00 / 01 00 (Addresses): 16-bit Little-Endian addresses mapping the Destination RTU ($0$) and Source Master ($1$).
  • 4D 50 (Data Link CRC): Crucial algebraic checksum validating the header before processing continues.

DNP3 Live Packet Capture Verification

Phase 3: EtherNet/IP & CIP — The Session Hijack Surface

EtherNet/IP takes the Common Industrial Protocol (CIP) and adapts it for modern industrial enterprise routing. To handle communication safely, it uses a fixed 24-byte Encapsulation Header that sits on top of all commands to manage sessions.

Default implementations pass tracking numbers and session handles in completely unauthenticated cleartext. If you are on-path, you can sniff these registration handles out of the air and hijack the connection entirely.

Before any industrial tag parsing can occur, the engineering client must run a Register Session routine, sending a 28-byte layout:

65 00 04 00 00 00 00 00 00 00 00 00 41 41 41 41 41 41 41 41 00 00 00 00 01 00 00 00

Enter fullscreen mode Exit fullscreen mode
  • 65 00 (Command ID): Maps explicitly to the Register Session instruction primitive.
  • 04 00 (Length): Indicates 4 trailing data bytes follow the header layout.
  • 00 00 00 00 (Session Handle): Empty tracking block. The physical controller generates this unique token and populates it in the response.
  • 41 41 41 41 41 41 41 41 (Sender Context): Fixed 8-byte diagnostic tracking phrase that the receiving PLC must echo back completely unchanged.

Ethernet/IP Live Packet Capture Verification

Phase 4: S7Comm — Proprietary Transport Nesting

S7Comm is the core protocol powering Siemens S7-300 and S7-400 programmatic lines. It communicates through a nested ISO transport layout to enforce safety boundaries. It doesn't write directly to raw TCP. Instead, it embeds your data inside a TPKT (RFC 1006) frame acting as a packetizer, which then wraps around a COTP (ISO 8073) connection management block.

The absolute baseline initialization frame requests a COTP Connection Request (CR). The 22-byte string looks like this:

03 00 00 16 11 E0 00 00 00 01 00 C0 01 0A C1 02 01 00 C2 02 02 00

Enter fullscreen mode Exit fullscreen mode
  • 03 00 00 16 (TPKT Header): Preloads Version 3 and maps a total upcoming envelope volume of 22 bytes ($0x0016 = 22$).
  • 11 (COTP Length): Confirms 17 parameter description bytes follow.
  • E0 (PDU Type): Declares this frame as an explicit Connection Request.
  • C2 02 02 00 (Destination TSAP): The crucial structural target variable mapping the targeted PLC rack and slot placement configuration directly.

S7Comm Live Packet Capture Verification

Phase 5: OPC UA — The Plaintext Backdoor

OPC UA (Open Platform Communications Unified Architecture) is the modern IT/OT cryptographic bridge. It discards legacy layouts, register boundaries, and old Windows-bound DCOM dependencies to offer an advanced, object-oriented information model. It brings robust security concepts into industrial environments, including X.509 certificate exchanges and strict cryptographic signing algorithms.

But here is the field reality: During commissioning, active troubleshooting, or in older brownfield updates, engineers often configure the security policy parameter profile to None.

When this happens, the entire secure object-oriented stream falls back to completely unencrypted plaintext, exposing raw session tokens and node structural definitions to anyone sniffing the wire.

Before any secure channel configuration occurs, the client fires a native binary Hello (HEL) string spanning a standard 32-byte layout:

48 45 4C 46 20 00 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 00 00

Enter fullscreen mode Exit fullscreen mode
  • 48 45 4C (Message Type): ASCII text indicators translating to HEL.
  • 46 (Chunk Type): ASCII character F (Final chunk), signaling a self-contained transmission window.
  • 20 00 00 00 (Message Size): Little-Endian unsigned integer establishing an explicit 32-byte frame layout boundary ($0x20 = 32$).
  • 00 00 01 00 (Buffer Sizes): Standard 32-bit little-endian capacity properties negotiating buffer windows up to $65,536\text{ bytes}$.

OPC UA Live Packet Capture Verification

The Troubleshooting Hell: The Alignment Check Mismatch

When you hand-craft low-level injection scripts using raw hex strings, you don't get the luxury of automated libraries handling data formatting for you. You hit the real friction points.

During development, I spent hours staring at tshark capturing frames completely cleanly, but refusing to render the application-layer dissection tree for OPC UA. It would drop the protocol mapping entirely and fall back to displaying a generic, raw TCP Data payload block.

The Lesson:

Network protocol analysis engines use strict validation rules. In my initial script configuration, I manually declared an internal size field block of 32 bytes (\x20\x00\x00\x00), but physically only appended 28 bytes of parameters to the raw socket array.

The engine's protocol parser calculates lengths rigidly. When it detected an alignment mismatch between the stated header length and the actual wire byte count, it flagged the packet as malformed and dropped the deep application tree to preserve data integrity.

Knowing how to troubleshoot alignment errors down to the physical byte level is a critical skill for deep protocol fuzzing and industrial vulnerability research.


What's Next?

This laboratory establishes the absolute foundation of our protocol analysis roadmap. Now that we can communicate with these stacks natively at Layer Zero without relying on heavy vendor software wrappers, we can start moving higher up the chain.

If you want the full step-by-step setup guides, the functional Python server/client twins, and the complete low-level reference manual, the entire project is open-source and ready to clone:

👉 Get the Code and Lab Manuals: github.com/404saint/raw-industrial-protocols

In the upcoming installments of this series, we will take each of these five protocols individually and run comprehensive deep dives exploring active network discovery, technical exploitation paths, deep packet defensive monitoring, and production protocol hardening.

Top comments (0)