About IEC 60870-5-104

IEC 104 is the European cousin of DNP3. It is more complex than Modbus, but a good bit simpler than DNP3. It consists of two layers:

  • APCI - Application Protocol Control Information used to denote frame types for 104's network mode.
  • ASDU - Application Service Data Unit that contains application layer frames. This is the same for 101 and 104.

The application layer defines a number of Type Ids which can be thought of as function codes. They define the format of the data that follows. Unlike in DNP3, 104 ASDUs can only contain one type of data.

Functions supported

The 104 fuzzer provides support for every TypeId defined in the standard. This doesn't guarantee that all possible bugs will be found, but it does mean there that a significant portion of the application layer is stressed by the fuzzer.

Health checks

The fuzzer queries the device under test (DUT) by sending a U-format frame with TESTFR ACT and expects to receive TESTFR CON in response.

Conformance and parameters

Some parameters in IEC 104 have configurable sizes that both sides must agree upon. Aegis uses the following values:

  • A two-octet Cause of Transmission field is used where the one-byte sender address sub-field is utilized.
  • A two-octet Common Address field is used.
  • A three-octet Information Object Address field is used.

There are the defaults for almost all systems, and the only settings that work with Wireshark.


  • The fuzzer automatically advances and increments the Transmit and Receive Sequence Numbers in the APCI.
  • The fuzzer will send (outstation) or receive (master) START_DT automatically.
  • The fuzzer always answers TESTFR ACT with TESTFR CON.


  • sender-addr - Sender (Originator) address - The address placed in all 1-octet cause of transmission sender address fields.

  • common-addr - Common address (sector) - The common address, or sector, of the DUT.

  • retries - Number of health-check retries - The number of attempts the fuzzer will make to query the target with a health check before deciding it has failed.

  • timeout - Health-check timeout - The timeout (in milliseconds) for reading a link layer frame from the target during a health-check.

Procedures (outstation)

  • app-request - Fuzzes the server's application layer with mutated forms of request TypeIds.
  • rand-app-request - Fuzzes the server's application layer with random semi-random requests.

Procedures (master)

  • app-response - Fuzzes the client's application layer with mutated forms of response TypeIds
  • rand-app-response - Fuzzes the client's application layer with random semi-random responses.

Procedures (either master or outstation)

The following procedures send frames with malformed APCI. You will almost certainly need to run each test case in its own TCP session (i.e. tests-per-session == 1).

  • apci - Sends malformed I, U, or S frames with disallowed lengths and a configurable random payload length.
  • random-frame - Sends a completely random frame prepended with the 0x68 start characters.

Test Plans

Your Aegis installation of contains recommended test plans for both outstations and masters.

  • plans\iec104-outstation.xml
  • plans\iec104-master.xml

In most cases, the only parameter you need to adjust will be the common address.

The recommended test plan repeats some of the procedures with different fill or random seeds. It is recommended that you follow the plan for maximum efficacy, but on slow implementations, this could take a long time. Some implementations can handle hundreds of test cases per second, while others only seem to handle a couple dozen. It may be worth figuring out why the implementation is slow to respond to health checks or requests. You might consider running additional random seeds besides zero if your have enough time.

The last test case in each plan generates random application layer data within appropriate encapsulation. It is arbitrarily set to 250,000 iterations. Run as many iterations as you can tolerate with the speed of your device.