├── .gitignore ├── CMakeLists.txt ├── LICENSE.txt ├── Makefile ├── NOTICE.txt ├── README.md ├── configure ├── configure.plugin ├── scripts ├── __load__.zeek ├── __preload__.zeek ├── consts.zeek └── icsnpp │ └── enip │ ├── __load__.zeek │ ├── dpd.sig │ └── main.zeek ├── src ├── ENIP.cc ├── ENIP.h ├── Plugin.cc ├── Plugin.h ├── consts.pac ├── enip-analyzer.pac ├── enip-protocol.pac ├── enip-utilities.pac ├── enip.pac └── events.bif ├── tests ├── .gitignore ├── analyzer │ ├── availability.zeek │ └── basic.zeek ├── baseline │ └── analyzer.basic │ │ ├── cip.log │ │ ├── cip_identity.log │ │ ├── cip_io.log │ │ ├── conn.log │ │ └── enip.log ├── btest.cfg ├── files │ └── random.seed ├── scripts │ ├── diff-remove-timestamps │ └── get-zeek-env └── traces │ └── enip_cip_example.pcap └── zkg.meta /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15 FATAL_ERROR) 2 | 3 | project(Plugin) 4 | 5 | include(ZeekPlugin) 6 | 7 | zeek_plugin_begin(ICSNPP Enip) 8 | zeek_plugin_cc(src/ENIP.cc src/Plugin.cc) 9 | zeek_plugin_bif(src/events.bif) 10 | zeek_plugin_pac(src/enip.pac src/enip-analyzer.pac src/enip-protocol.pac) 11 | zeek_plugin_dist_files(README CHANGES COPYING VERSION) 12 | zeek_plugin_end() -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2023, Battelle Energy Alliance, LLC 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Convenience Makefile providing a few common top-level targets. 3 | # 4 | # Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. 5 | 6 | cmake_build_dir=build 7 | arch=`uname -s | tr A-Z a-z`-`uname -m` 8 | 9 | all: build-it 10 | 11 | build-it: 12 | @test -e $(cmake_build_dir)/config.status || ./configure 13 | -@test -e $(cmake_build_dir)/CMakeCache.txt && \ 14 | test $(cmake_build_dir)/CMakeCache.txt -ot `cat $(cmake_build_dir)/CMakeCache.txt | grep ZEEK_DIST | cut -d '=' -f 2`/build/CMakeCache.txt && \ 15 | echo Updating stale CMake cache && \ 16 | touch $(cmake_build_dir)/CMakeCache.txt 17 | 18 | ( cd $(cmake_build_dir) && make ) 19 | 20 | install: 21 | ( cd $(cmake_build_dir) && make install ) 22 | 23 | clean: 24 | ( cd $(cmake_build_dir) && make clean ) 25 | 26 | distclean: 27 | rm -rf $(cmake_build_dir) 28 | 29 | test: 30 | make -C tests -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | This project contains code from Idaho National Laboratory's ICSNPP Project 2 | Github URL: https://github.com/cisagov/ICSNPP 3 | Licensed under BSD 3-Part License. 4 | 5 | 6 | © 2023 Battelle Energy Alliance, LLC 7 | ALL RIGHTS RESERVED 8 | 9 | Prepared by Battelle Energy Alliance, LLC 10 | Under Contract No. DE-AC07-05ID14517 11 | With the U. S. Department of Energy 12 | 13 | NOTICE: This computer software was prepared by Battelle Energy 14 | Alliance, LLC, hereinafter the Contractor, under Contract 15 | No. AC07-05ID14517 with the United States (U. S.) Department of 16 | Energy (DOE). The Government is granted for itself and others acting on 17 | its behalf a nonexclusive, paid-up, irrevocable worldwide license in this 18 | data to reproduce, prepare derivative works, and perform publicly and 19 | display publicly, by or on behalf of the Government. There is provision for 20 | the possible extension of the term of this license. Subsequent to that 21 | period or any extension granted, the Government is granted for itself and 22 | others acting on its behalf a nonexclusive, paid-up, irrevocable worldwide 23 | license in this data to reproduce, prepare derivative works, distribute 24 | copies to the public, perform publicly and display publicly, and to permit 25 | others to do so. The specific term of the license can be identified by 26 | inquiry made to Contractor or DOE. NEITHER THE UNITED STATES NOR THE UNITED 27 | STATES DEPARTMENT OF ENERGY, NOR CONTRACTOR MAKES ANY WARRANTY, EXPRESS OR 28 | IMPLIED, OR ASSUMES ANY LIABILITY OR RESPONSIBILITY FOR THE USE, ACCURACY, 29 | COMPLETENESS, OR USEFULNESS OR ANY INFORMATION, APPARATUS, PRODUCT, OR 30 | PROCESS DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT INFRINGE PRIVATELY 31 | OWNED RIGHTS. 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ICSNPP-ENIP 2 | 3 | Industrial Control Systems Network Protocol Parsers (ICSNPP) - Ethernet/IP and CIP. 4 | 5 | ## Overview 6 | 7 | ICSNPP-ENIP is a Zeek plugin for parsing and logging fields within the Ethernet/IP protocol. 8 | 9 | This plugin was developed to be fully customizable. To drill down into specific ENIP/CIP packets and log certain variables, users can add the logging functionality to [scripts/icsnpp/enip/main.zeek](scripts/icsnpp/enip/main.zeek). The functions within [scripts/icsnpp/enip/main.zeek](scripts/icsnpp/enip/main.zeek) and [src/events.bif](src/events.bif) are good guides for adding new logging functionality. 10 | 11 | This parser produces four log files. These log files are defined in [scripts/icsnpp/enip/main.zeek](scripts/icsnpp/enip/main.zeek). 12 | * enip.log 13 | * cip.log 14 | * cip_io.log 15 | * cip_identity.log 16 | 17 | For additional information on these log files, see the *Logging Capabilities* section below. 18 | 19 | ## Installation 20 | 21 | ### Package Manager 22 | 23 | This script is available as a package for [Zeek Package Manger](https://docs.zeek.org/projects/package-manager/en/stable/index.html) 24 | 25 | ```bash 26 | zkg refresh 27 | zkg install icsnpp-enip 28 | ``` 29 | 30 | If this package is installed from ZKG, it will be added to the available plugins. This can be tested by running `zeek -N`. If installed correctly, users will see `ICSNPP::ENIP`. 31 | 32 | If ZKG is configured to load packages (see @load packages in quickstart guide), this plugin and these scripts will automatically be loaded and ready to go. 33 | [ZKG Quickstart Guide](https://docs.zeek.org/projects/package-manager/en/stable/quickstart.html) 34 | 35 | If users are not using site/local.zeek or another site installation of Zeek and want to run this package on a packet capture, they can add `icsnpp/enip` to the command to run this plugin's scripts on the packet capture: 36 | 37 | ```bash 38 | git clone https://github.com/cisagov/icsnpp-enip.git 39 | zeek -Cr icsnpp-enip/tests/traces/enip_cip_example.pcap icsnpp/enip 40 | ``` 41 | 42 | ### Manual Install 43 | 44 | To install this package manually, clone this repository and run the configure and make commands as shown below. 45 | 46 | ```bash 47 | git clone https://github.com/cisagov/icsnpp-enip.git 48 | cd icsnpp-enip/ 49 | ./configure 50 | make 51 | ``` 52 | 53 | If these commands succeed, users will end up with a newly created build directory. This contains all the files needed to run/test this plugin. The easiest way to test the parser is to point the ZEEK_PLUGIN_PATH environment variable to this build directory. 54 | 55 | ```bash 56 | export ZEEK_PLUGIN_PATH=$PWD/build/ 57 | zeek -N # Ensure everything compiled correctly and you are able to see ICSNPP::ENIP 58 | ``` 59 | 60 | Once users have tested the functionality locally and it appears to have compiled correctly, they can install it system-wide: 61 | ```bash 62 | sudo make install 63 | unset ZEEK_PLUGIN_PATH 64 | zeek -N # Ensure everything installed correctly and you are able to see ICSNPP::ENIP 65 | ``` 66 | 67 | To run this plugin in a site deployment, users will need to add the line `@load icsnpp/enip` to the `site/local.zeek` file to load this plugin's scripts. 68 | 69 | If users are not using site/local.zeek or another site installation of Zeek and want to run this package on a packet capture, they can add `icsnpp/enip` to the command to run this plugin's scripts on the packet capture: 70 | 71 | ```bash 72 | zeek -Cr icsnpp-enip/tests/traces/enip_cip_example.pcap icsnpp/enip 73 | ``` 74 | 75 | If users want to deploy this on an already existing Zeek implementation and don't want to build the plugin on the machine, they can extract the Zeek_Enip.tgz file to the directory of the established ZEEK_PLUGIN_PATH (default is `${ZEEK_INSTALLATION_DIR}/lib/zeek/plugins/`). 76 | 77 | ```bash 78 | tar xvzf build/Zeek_Enip.tgz -C $ZEEK_PLUGIN_PATH 79 | ``` 80 | 81 | ## Logging Capabilities 82 | 83 | It its default configuration, this parser will only log Ethernet/IP and CIP packets on ports 2222 and 44818. This decision was made due to the false positives generated when a signature-only based detection system was used. 84 | 85 | If users know of Ethernet/IP and CIP traffic that operate on ports other than 2222 or 44818, there are two options: 86 | * Allow signature detection on additional, known ports only: 87 | * In [scripts/icsnpp/enip/dpd.sig](scripts/icsnpp/enip/dpd.sig): add the known Ethernet/IP and CIP port numbers to the lines: `dst-port == 2222, 44818` 88 | * Allow signature detection on all ports (may produce false positive): 89 | * In [scripts/icsnpp/enip/dpd.sig](scripts/icsnpp/enip/dpd.sig): replace the lines: `dst-port == 2222, 44818` with `dst-port >= 1024` 90 | 91 | ### ENIP Header Log (enip.log) 92 | 93 | #### Overview 94 | 95 | This log captures Ethernet/IP header information for every Ethernet/IP packet and logs it to **enip.log**. 96 | 97 | #### Fields Captured 98 | 99 | | Field | Type | Description | 100 | | ----------------------|-----------|-------------------------------------------------------------- | 101 | | ts | time | Timestamp | 102 | | uid | string | Unique ID for this connection | 103 | | id | conn_id | Default Zeek connection info (IP addresses, ports) | 104 | | is_orig | bool | True if the packet is sent from the originator | 105 | | source_h | address | Source IP address (see *Source and Destination Fields*) | 106 | | source_p | port | Source port (see *Source and Destination Fields*) | 107 | | destination_h | address | Destination IP address (see *Source and Destination Fields*) | 108 | | destination_p | port | Destination port (see *Source and Destination Fields*) | 109 | | packet_correlation_id | string | Ties ENIP headers to associated CIP packets | 110 | | enip_command_code | string | Ethernet/IP command code | 111 | | enip_command | string | Ethernet/IP command name | 112 | | length | count | Length of ENIP data following header | 113 | | session_handle | string | Session identifier | 114 | | enip_status | string | Ethernet/IP status code | 115 | | sender_context | string | Sender context | 116 | | options | string | Options flags | 117 | 118 | ### CIP Header Log (cip.log) 119 | 120 | #### Overview 121 | 122 | This log captures CIP header information for every CIP packet and logs it to **cip.log**. 123 | 124 | #### Fields Captured 125 | 126 | | Field | Type | Description | 127 | | ------------------------- |-----------|-------------------------------------------------------------- | 128 | | ts | time | Timestamp | 129 | | uid | string | Unique ID for this connection | 130 | | id | conn_id | Default Zeek connection info (IP addresses, ports) | 131 | | is_orig | bool | True if the packet is sent from the originator | 132 | | source_h | address | Source IP address (see *Source and Destination Fields*) | 133 | | source_p | port | Source port (see *Source and Destination Fields*) | 134 | | destination_h | address | Destination IP address (see *Source and Destination Fields*) | 135 | | destination_p | port | Destination port (see *Source and Destination Fields*) | 136 | | packet_correlation_id | string | Ties ENIP headers to associated CIP packets | 137 | | cip_sequence_count | count | CIP sequence number | 138 | | direction | string | Request or response | 139 | | cip_service_code | string | CIP service code | 140 | | cip_service | string | CIP service name | 141 | | cip_status_code | string | CIP status code | 142 | | cip_status | string | CIP status name | 143 | | cip_extended_status_code | string | CIP extended status code | 144 | | cip_extended_status | string | CIP extended status name | 145 | | class_id | string | CIP request path - class ID | 146 | | class_name | string | CIP request path - class name | 147 | | instance_id | string | CIP request path - instance ID | 148 | | attribute_id | string | CIP request path - attribute ID | 149 | 150 | ### CIP I/O Log (cip_io.log) 151 | 152 | #### Overview 153 | 154 | This log captures CIP I/O (input-output) data for every CIP IO packet and logs it to **cip_io.log**. 155 | 156 | #### Fields Captured 157 | 158 | | Field | Type | Description | 159 | | --------------------- |-----------|-------------------------------------------------------------- | 160 | | ts | time | Timestamp | 161 | | uid | string | Unique ID for this connection | 162 | | id | conn_id | Default Zeek connection info (IP addresses, ports) | 163 | | is_orig | bool | True if the packet is sent from the originator | 164 | | source_h | address | Source IP address (see *Source and Destination Fields*) | 165 | | source_p | port | Source port (see *Source and Destination Fields*) | 166 | | destination_h | address | Destination IP address (see *Source and Destination Fields*) | 167 | | destination_p | port | Destination port (see *Source and Destination Fields*) | 168 | | packet_correlation_id | string | Ties ENIP headers to associated CIP packets | 169 | | connection_id | string | Connection identifier | 170 | | sequence_number | count | Sequence number within connection | 171 | | data_length | count | Length of data in io_data field | 172 | | io_data | string | CIP IO data (in hex) | 173 | 174 | ### CIP Identity Log (cip_identity.log) 175 | 176 | #### Overview 177 | 178 | This log captures important variables for CIP_Identity objects and logs them to **cip_identity.log**. 179 | 180 | #### Fields Captured 181 | 182 | | Field | Type | Description | 183 | | --------------------- |-----------|-------------------------------------------------------------- | 184 | | ts | time | Timestamp | 185 | | uid | string | Unique ID for this connection | 186 | | id | conn_id | Default Zeek connection info (IP addresses, ports) | 187 | | is_orig | bool | True if the packet is sent from the originator | 188 | | source_h | address | Source IP address (see *Source and Destination Fields*) | 189 | | source_p | port | Source Port (see *Source and Destination Fields*) | 190 | | destination_h | address | Destination IP address (see *Source and Destination Fields*) | 191 | | destination_p | port | Destination Port (see *Source and Destination Fields*) | 192 | | packet_correlation_id | string | Ties ENIP headers to associated CIP packets | 193 | | encapsulation_version | count | Encapsulation protocol version supported | 194 | | socket_address | addr | Socket address IP address | 195 | | socket_port | count | Socket address port number | 196 | | vendor_id | count | Vendor ID | 197 | | vendor_name | string | Name of vendor | 198 | | device_type_id | count | Device type ID | 199 | | device_type_name | string | Name of device type | 200 | | product_code | count | Product code assigned to device | 201 | | revision | string | Device revision (major.minor) | 202 | | device_status | string | Current status of device | 203 | | serial_number | string | Serial number of device | 204 | | product_name | string | Human readable description of device | 205 | | device_state | string | Current state of the device | 206 | 207 | ### Source and Destination Fields 208 | 209 | #### Overview 210 | 211 | Zeek's typical behavior is to focus on and log packets from the originator and not log packets from the responder. However, most ICS protocols contain useful information in the responses, so the ICSNPP parsers log both originator and responses packets. Zeek's default behavior, defined in its `id` struct, is to never switch these originator/responder roles which leads to inconsistencies and inaccuracies when looking at ICS traffic that logs responses. 212 | 213 | The default Zeek `id` struct contains the following logged fields: 214 | * id.orig_h (Original Originator/Source Host) 215 | * id.orig_p (Original Originator/Source Port) 216 | * id.resp_h (Original Responder/Destination Host) 217 | * id.resp_p (Original Responder/Destination Port) 218 | 219 | Additionally, the `is_orig` field is a boolean field that is set to T (True) when the id_orig fields are the true originators/source and F (False) when the id_resp fields are the true originators/source. 220 | 221 | To not break existing platforms that utilize the default `id` struct and `is_orig` field functionality, the ICSNPP team has added four new fields to each log file instead of changing Zeek's default behavior. These four new fields provide the accurate information regarding source and destination IP addresses and ports: 222 | * source_h (True Originator/Source Host) 223 | * source_p (True Originator/Source Port) 224 | * destination_h (True Responder/Destination Host) 225 | * destination_p (True Responder/Destination Port) 226 | 227 | The pseudocode below shows the relationship between the `id` struct, `is_orig` field, and the new `source` and `destination` fields. 228 | 229 | ``` 230 | if is_orig == True 231 | source_h == id.orig_h 232 | source_p == id.orig_p 233 | destination_h == id.resp_h 234 | destination_p == id.resp_p 235 | if is_orig == False 236 | source_h == id.resp_h 237 | source_p == id.resp_p 238 | destination_h == id.orig_h 239 | destination_p == id.orig_p 240 | ``` 241 | 242 | #### Example 243 | 244 | The table below shows an example of these fields in the log files. The first log in the table represents a Modbus request from 192.168.1.10 -> 192.168.1.200 and the second log represents a Modbus reply from 192.168.1.200 -> 192.168.1.10. As shown in the table below, the `id` structure lists both packets as having the same originator and responder, but the `source` and `destination` fields reflect the true source and destination of these packets. 245 | 246 | | id.orig_h | id.orig_p | id.resp_h | id.resp_p | is_orig | source_h | source_p | destination_h | destination_p | 247 | | ------------ | --------- |---------------|-----------|---------|---------------|----------|---------------|-------------- | 248 | | 192.168.1.10 | 47785 | 192.168.1.200 | 502 | T | 192.168.1.10 | 47785 | 192.168.1.200 | 502 | 249 | | 192.168.1.10 | 47785 | 192.168.1.200 | 502 | F | 192.168.1.200 | 502 | 192.168.1.10 | 47785 | 250 | 251 | ## Coverage 252 | 253 | See [Logging Capabilities](#logging-capabilities) for detailed information of the parser coverage. 254 | 255 | ### Note 256 | 257 | Ethernet/IP and CIP have a lot of vendor and product specific messages that are not included in this parser. All coverage details in this section include information and statistics based on the basic/default Ethernet/IP and CIP protocols. 258 | 259 | ### General/Header Logging 260 | 261 | The general log files for Ethernet/IP (enip.log) and CIP (cip.log) contain basic header information for all basic/default (~100%) Ethernet/IP and CIP messages. 262 | 263 | ### Detailed Logging 264 | 265 | Detailed logging for 1 Ethernet/IP command is logged in the CIP identity log file (cip_identity.log). The other 9 Ethernet/IP commands do not contain detailed logging, therefore 10% (1/10) of the Ethernet/IP commands contain detailed logging. 266 | 267 | There is currently no (0%) detailed logging for regular CIP services outside of the CIP general/header log file (cip.log). 268 | 269 | ## ICSNPP Packages 270 | 271 | All ICSNPP Packages: 272 | * [ICSNPP](https://github.com/cisagov/icsnpp) 273 | 274 | Full ICS Protocol Parsers: 275 | * [BACnet](https://github.com/cisagov/icsnpp-bacnet) 276 | * Full Zeek protocol parser for BACnet (Building Control and Automation) 277 | * [BSAP](https://github.com/cisagov/icsnpp-bsap) 278 | * Full Zeek protocol parser for BSAP (Bristol Standard Asynchronous Protocol) over IP 279 | * Full Zeek protocol parser for BSAP Serial comm converted using serial tap device 280 | * [Ethercat](https://github.com/cisagov/icsnpp-ethercat) 281 | * Full Zeek protocol parser for Ethercat 282 | * [Ethernet/IP and CIP](https://github.com/cisagov/icsnpp-enip) 283 | * Full Zeek protocol parser for Ethernet/IP and CIP 284 | * [GE SRTP](https://github.com/cisagov/icsnpp-ge-srtp) 285 | * Full Zeek protocol parser for GE SRTP 286 | * [Genisys](https://github.com/cisagov/icsnpp-genisys) 287 | * Full Zeek protocol parser for Genisys 288 | * [OPCUA-Binary](https://github.com/cisagov/icsnpp-opcua-binary) 289 | * Full Zeek protocol parser for OPC UA (OPC Unified Architecture) - Binary 290 | * [S7Comm](https://github.com/cisagov/icsnpp-s7comm) 291 | * Full Zeek protocol parser for S7comm, S7comm-plus, and COTP 292 | * [Synchrophasor](https://github.com/cisagov/icsnpp-synchrophasor) 293 | * Full Zeek protocol parser for Synchrophasor Data Transfer for Power Systems (C37.118) 294 | * [Profinet IO CM](https://github.com/cisagov/icsnpp-profinet-io-cm) 295 | * Full Zeek protocol parser for Profinet I/O Context Manager 296 | 297 | Updates to Zeek ICS Protocol Parsers: 298 | * [DNP3](https://github.com/cisagov/icsnpp-dnp3) 299 | * DNP3 Zeek script extending logging capabilities of Zeek's default DNP3 protocol parser 300 | * [Modbus](https://github.com/cisagov/icsnpp-modbus) 301 | * Modbus Zeek script extending logging capabilities of Zeek's default Modbus protocol parser 302 | 303 | ### License 304 | 305 | Copyright 2023 Battelle Energy Alliance, LLC. Released under the terms of the 3-Clause BSD License (see [`LICENSE.txt`](./LICENSE.txt)). 306 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Wrapper for viewing/setting options that the plugin's CMake 4 | # scripts will recognize. 5 | # 6 | # Don't edit this. Edit configure.plugin to add plugin-specific options. 7 | # 8 | 9 | set -e 10 | command="$0 $*" 11 | 12 | if [ -e `dirname $0`/configure.plugin ]; then 13 | # Include custom additions. 14 | . `dirname $0`/configure.plugin 15 | fi 16 | 17 | # Check for `cmake` command. 18 | type cmake > /dev/null 2>&1 || { 19 | echo "\ 20 | This package requires CMake, please install it first, then you may 21 | use this configure script to access CMake equivalent functionality.\ 22 | " >&2; 23 | exit 1; 24 | } 25 | 26 | usage() { 27 | 28 | cat 1>&2 </dev/null 2>&1; then 41 | plugin_usage 1>&2 42 | fi 43 | 44 | echo 45 | 46 | exit 1 47 | } 48 | 49 | # Function to append a CMake cache entry definition to the 50 | # CMakeCacheEntries variable 51 | # $1 is the cache entry variable name 52 | # $2 is the cache entry variable type 53 | # $3 is the cache entry variable value 54 | append_cache_entry () { 55 | CMakeCacheEntries="$CMakeCacheEntries -D $1:$2=$3" 56 | } 57 | 58 | # set defaults 59 | builddir=build 60 | zeekdist="" 61 | installroot="default" 62 | CMakeCacheEntries="" 63 | 64 | while [ $# -ne 0 ]; do 65 | case "$1" in 66 | -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; 67 | *) optarg= ;; 68 | esac 69 | 70 | case "$1" in 71 | --help|-h) 72 | usage 73 | ;; 74 | 75 | --zeek-dist=*) 76 | zeekdist=`cd $optarg && pwd` 77 | ;; 78 | 79 | --bro-dist=*) # Legacy option for backwards compability 80 | zeekdist=`cd $optarg && pwd` 81 | ;; 82 | 83 | --install-root=*) 84 | installroot=$optarg 85 | ;; 86 | 87 | --with-binpac=*) 88 | append_cache_entry BinPAC_ROOT_DIR PATH $optarg 89 | binpac_root=$optarg 90 | ;; 91 | 92 | --with-broker=*) 93 | append_cache_entry BROKER_ROOT_DIR PATH $optarg 94 | broker_root=$optarg 95 | ;; 96 | 97 | --with-caf=*) 98 | append_cache_entry CAF_ROOT_DIR PATH $optarg 99 | caf_root=$optarg 100 | ;; 101 | 102 | --with-bifcl=*) 103 | append_cache_entry BifCl_EXE PATH $optarg 104 | ;; 105 | 106 | --enable-debug) 107 | append_cache_entry BRO_PLUGIN_ENABLE_DEBUG BOOL true 108 | ;; 109 | 110 | *) 111 | if type plugin_option >/dev/null 2>&1; then 112 | plugin_option $1 && shift && continue; 113 | fi 114 | 115 | echo "Invalid option '$1'. Try $0 --help to see available options." 116 | exit 1 117 | ;; 118 | esac 119 | shift 120 | done 121 | 122 | if [ -z "$zeekdist" ]; then 123 | if type zeek-config >/dev/null 2>&1; then 124 | zeek_config="zeek-config" 125 | elif type bro-config >/dev/null 2>&1; then 126 | zeek_config="bro-config" 127 | fi 128 | 129 | if [ -n "${zeek_config}" ]; then 130 | if ${zeek_config} --cmake_dir >/dev/null 2>&1; then 131 | # Have a newer version of zeek-config that has needed flags 132 | append_cache_entry BRO_CONFIG_PREFIX PATH `${zeek_config} --prefix` 133 | append_cache_entry BRO_CONFIG_INCLUDE_DIR PATH `${zeek_config} --include_dir` 134 | append_cache_entry BRO_CONFIG_PLUGIN_DIR PATH `${zeek_config} --plugin_dir` 135 | append_cache_entry BRO_CONFIG_CMAKE_DIR PATH `${zeek_config} --cmake_dir` 136 | append_cache_entry CMAKE_MODULE_PATH PATH `${zeek_config} --cmake_dir` 137 | 138 | build_type=`${zeek_config} --build_type` 139 | 140 | if [ "$build_type" = "debug" ]; then 141 | append_cache_entry BRO_PLUGIN_ENABLE_DEBUG BOOL true 142 | fi 143 | 144 | if [ -z "$binpac_root" ]; then 145 | append_cache_entry BinPAC_ROOT_DIR PATH `${zeek_config} --binpac_root` 146 | fi 147 | 148 | if [ -z "$broker_root" ]; then 149 | append_cache_entry BROKER_ROOT_DIR PATH `${zeek_config} --broker_root` 150 | fi 151 | 152 | if [ -z "$caf_root" ]; then 153 | append_cache_entry CAF_ROOT_DIR PATH `${zeek_config} --caf_root` 154 | fi 155 | else 156 | # Using legacy bro-config, so we must use the "--bro_dist" option. 157 | zeekdist=`${zeek_config} --bro_dist 2> /dev/null` 158 | 159 | if [ ! -e "$zeekdist/zeek-path-dev.in" ]; then 160 | echo "$zeekdist does not appear to be a valid Zeek source tree." 161 | exit 1 162 | fi 163 | 164 | # BRO_DIST is needed to support legacy Bro plugins 165 | append_cache_entry BRO_DIST PATH $zeekdist 166 | append_cache_entry ZEEK_DIST PATH $zeekdist 167 | append_cache_entry CMAKE_MODULE_PATH PATH $zeekdist/cmake 168 | fi 169 | else 170 | echo "Either 'zeek-config' must be in PATH or '--zeek-dist=' used" 171 | exit 1 172 | fi 173 | else 174 | if [ ! -e "$zeekdist/zeek-path-dev.in" -a ! -e "$zeekdist/bro-path-dev.in" ]; then 175 | echo "$zeekdist does not appear to be a valid Zeek source tree." 176 | exit 1 177 | fi 178 | 179 | # BRO_DIST is needed to support legacy Bro plugins 180 | append_cache_entry BRO_DIST PATH $zeekdist 181 | append_cache_entry ZEEK_DIST PATH $zeekdist 182 | append_cache_entry CMAKE_MODULE_PATH PATH $zeekdist/cmake 183 | fi 184 | 185 | if [ "$installroot" != "default" ]; then 186 | mkdir -p $installroot 187 | append_cache_entry BRO_PLUGIN_INSTALL_ROOT PATH $installroot 188 | fi 189 | 190 | echo "Build Directory : $builddir" 191 | echo "Zeek Source Directory : $zeekdist" 192 | 193 | mkdir -p $builddir 194 | cd $builddir 195 | 196 | cmake $CMakeCacheEntries .. 197 | 198 | echo "# This is the command used to configure this build" > config.status 199 | echo $command >> config.status 200 | chmod u+x config.status -------------------------------------------------------------------------------- /configure.plugin: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Hooks to add custom options to the configure script. 4 | # 5 | 6 | plugin_usage() 7 | { 8 | : # Do nothing 9 | # cat </src/Plugin.cc 5 | # Note: ENIP uses little-endian byte order rather than network byte order 6 | # Header: 7 | # Command (uint16) 8 | # Valid Values (network byte order): 9 | # 0x0000, 0x0004, 0x0063, 0x0064, 0x0065, 0x0066, 0x006F, 10 | # 0x0070, 0x0072, 0x0073 11 | # Length (uint16) 12 | # Session Handle (uint32) 13 | # Status Code (uint32) 14 | # Valid Values (network byte order): 15 | # 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000064, 0x00000069 16 | # Additional Values (not in reference code) 17 | # 0x00000065, 0x0000006a 18 | # Context (uint8) 19 | # Options (uint32) 20 | 21 | signature dpd_enip_tcp { 22 | ip-proto == tcp 23 | src-port >= 1024 24 | dst-port == 2222, 44818 25 | payload /^[\x00\x04\x63\x64\x65\x66\x6f\x70\x72\x73]\x00[\x00-\xff]{6}[\x00\x01\x02\x03\x64\x65\x69\x6a]\x00{3}[\x00-\xff][\x00-\xff]{4}/ 26 | enable "ENIP_TCP" 27 | } 28 | 29 | signature dpd_enip_udp_client_to_server { 30 | ip-proto == udp 31 | src-port >= 1024 32 | dst-port == 2222, 44818 33 | payload /^[\x00\x04\x63\x64\x65\x66\x6f\x70\x72\x73]\x00[\x00-\xff]{6}[\x00\x01\x02\x03\x64\x65\x69\x6a]\x00{3}[\x00-\xff][\x00-\xff]{4}/ 34 | enable "ENIP_UDP" 35 | } 36 | 37 | signature dpd_enip_udp_server_to_client { 38 | ip-proto == udp 39 | src-port == 2222, 44818 40 | dst-port >= 1024 41 | payload /^[\x00\x04\x63\x64\x65\x66\x6f\x70\x72\x73]\x00[\x00-\xff]{6}[\x00\x01\x02\x03\x64\x65\x69\x6a]\x00{3}[\x00-\xff][\x00-\xff]{4}/ 42 | enable "ENIP_UDP" 43 | } -------------------------------------------------------------------------------- /scripts/icsnpp/enip/main.zeek: -------------------------------------------------------------------------------- 1 | ##! main.zeek 2 | ##! 3 | ##! Binpac Ethernet/IP (ENIP) Analyzer - Contains the base script-layer functionality for 4 | ##! processing events emitted from the analyzer. 5 | ##! 6 | ##! Author: Stephen Kleinheider 7 | ##! Contact: stephen.kleinheider@inl.gov 8 | ##! 9 | ##! Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. 10 | 11 | module ENIP; 12 | 13 | export{ 14 | redef enum Log::ID += { LOG_ENIP, 15 | LOG_CIP, 16 | LOG_CIP_IO, 17 | LOG_CIP_IDENTITY }; 18 | 19 | ############################################################################################### 20 | ################################## ENIP_Header -> enip.log ################################## 21 | ############################################################################################### 22 | type ENIP_Header: record { 23 | ts : time &log; # Timestamp of event 24 | uid : string &log; # Zeek unique ID for connection 25 | id : conn_id &log; # Zeek connection struct (addresses and ports) 26 | is_orig : bool &log; # the message came from the originator/client or the responder/server 27 | source_h : addr &log; # Source IP Address 28 | source_p : port &log; # Source Port 29 | destination_h : addr &log; # Destination IP Address 30 | destination_p : port &log; # Destination Port 31 | packet_correlation_id : string &log; # A correlation ID that ties ENIP headers to associated CIP packets (packet rather than connection based) 32 | enip_command_code : string &log; # Ethernet/IP Command Code (in hex) 33 | enip_command : string &log; # Ethernet/IP Command Name (see enip_commands) 34 | length : count &log; # Length of ENIP data following header 35 | session_handle : string &log; # Sesesion identifier 36 | enip_status : string &log; # Status code (see enip_statuses) 37 | sender_context : string &log; # Sender context 38 | options : string &log; # Options flags 39 | }; 40 | global log_enip: event(rec: ENIP_Header); 41 | global log_policy_enip: Log::PolicyHook; 42 | 43 | ############################################################################################### 44 | ################################### CIP_Header -> cip.log ################################### 45 | ############################################################################################### 46 | type CIP_Header: record { 47 | ts : time &log; # Timestamp of event 48 | uid : string &log; # Zeek unique ID for connection 49 | id : conn_id &log; # Zeek connection struct (addresses and ports) 50 | is_orig : bool &log; # the message came from the originator/client or the responder/server 51 | source_h : addr &log; # Source IP Address 52 | source_p : port &log; # Source Port 53 | destination_h : addr &log; # Destination IP Address 54 | destination_p : port &log; # Destination Port 55 | packet_correlation_id : string &log; # A correlation ID that ties ENIP headers to associated CIP packets (packet rather than connection based) 56 | cip_sequence_count : count &log; # CIP sequence number for transport 57 | direction : string &log; # Request or Response 58 | cip_service_code : string &log; # CIP service code (in hex) 59 | cip_service : string &log; # CIP service name (see cip_services) 60 | cip_status_code : string &log; # CIP status code (in hex) 61 | cip_status : string &log; # CIP status description (see cip_statuses) 62 | cip_extended_status_code : string &log; # CIP extended status code (in hex) 63 | cip_extended_status : string &log; # CIP extended status description (see cip_extended_statuses) 64 | class_id : string &log; # CIP Request Path - Class ID 65 | class_name : string &log; # CIP Request Path - Class Name (see cip_classes) 66 | instance_id : string &log; # CIP Request Path - Instance ID 67 | attribute_id : string &log; # CIP Request Path - Attribute ID 68 | }; 69 | global log_cip: event(rec: CIP_Header); 70 | global log_policy_cip: Log::PolicyHook; 71 | 72 | ############################################################################################### 73 | ################################## CIP_IO_Log -> cip_io.log ################################# 74 | ############################################################################################### 75 | type CIP_IO_Log: record { 76 | ts : time &log; # Timestamp of event 77 | uid : string &log; # Zeek unique ID for connection 78 | id : conn_id &log; # Zeek connection struct (addresses and ports) 79 | is_orig : bool &log; # the message came from the originator/client or the responder/server 80 | source_h : addr &log; # Source IP Address 81 | source_p : port &log; # Source Port 82 | destination_h : addr &log; # Destination IP Address 83 | destination_p : port &log; # Destination Port 84 | packet_correlation_id : string &log; # A correlation ID that ties ENIP headers to associated CIP packets (packet rather than connection based) 85 | connection_id : string &log; # CIP Connection Identifier 86 | sequence_number : count &log; # CIP Sequence Number with Connection 87 | data_length : count &log; # Length of io_data field 88 | io_data : string &log; # CIP IO Data 89 | }; 90 | global log_cip_io: event(rec: CIP_IO_Log); 91 | global log_policy_cip_io: Log::PolicyHook; 92 | 93 | ############################################################################################### 94 | ######################### CIP_Identity_Item_Log -> cip_identity.log ######################### 95 | ############################################################################################### 96 | type CIP_Identity_Item_Log: record { 97 | ts : time &log; # Timestamp of event 98 | uid : string &log; # Zeek unique ID for connection 99 | id : conn_id &log; # Zeek connection struct (addresses and ports) 100 | is_orig : bool &log; # the message came from the originator/client or the responder/server 101 | source_h : addr &log; # Source IP Address 102 | source_p : port &log; # Source Port 103 | destination_h : addr &log; # Destination IP Address 104 | destination_p : port &log; # Destination Port 105 | packet_correlation_id : string &log; # A correlation ID that ties ENIP headers to associated CIP packets (packet rather than connection based) 106 | encapsulation_version : count &log; # Encapsulation protocol version supported 107 | socket_address : addr &log; # Socket address IP address 108 | socket_port : count &log; # Socket address port number 109 | vendor_id : count &log; # Vendor ID 110 | vendor_name : string &log; # Name of Vendor (see cip_vendors) 111 | device_type_id : count &log; # Device type ID 112 | device_type_name : string &log; # Name of device type (see cip_device_types) 113 | product_code : count &log; # Product code assigned to device 114 | revision : string &log; # Device revision (major.minor) 115 | device_status : string &log; # Current status of device (see cip_statuses) 116 | serial_number : string &log; # Serial number of device 117 | product_name : string &log; # Human readable description of device 118 | device_state : string &log; # Current state of the device 119 | }; 120 | global log_cip_identity: event(rec: CIP_Identity_Item_Log); 121 | global log_policy_cip_identity: Log::PolicyHook; 122 | } 123 | 124 | # Defines ENIP/CIP ports 125 | const ports = { 126 | 2222/udp, 127 | 44818/tcp, 128 | 44818/udp, 129 | }; 130 | 131 | # Defines ENIP/CIP UDP ports 132 | const udp_ports = { 133 | 2222/udp, 134 | 44818/udp, 135 | }; 136 | 137 | # Defines Implicit UDP ENIP/CIP I/O ports 138 | const udp_implicit_ports = { 139 | 2222/udp, 140 | }; 141 | 142 | # Defines ENIP/CIP TCP ports 143 | const tcp_ports = { 144 | 44818/tcp, 145 | }; 146 | redef likely_server_ports += { ports }; 147 | 148 | ################################################################################################### 149 | ################ Defines Log Streams for enip.log, cip.log, and cip_identity.log ################ 150 | ################################################################################################### 151 | event zeek_init() &priority=5 { 152 | Log::create_stream(ENIP::LOG_ENIP, [$columns=ENIP_Header, 153 | $ev=log_enip, 154 | $path="enip", 155 | $policy=log_policy_enip]); 156 | 157 | Log::create_stream(ENIP::LOG_CIP, [$columns=CIP_Header, 158 | $ev=log_cip, 159 | $path="cip", 160 | $policy=log_policy_cip]); 161 | 162 | Log::create_stream(ENIP::LOG_CIP_IO, [$columns=CIP_IO_Log, 163 | $ev=log_cip_io, 164 | $path="cip_io", 165 | $policy=log_policy_cip_io]); 166 | 167 | Log::create_stream(ENIP::LOG_CIP_IDENTITY, [$columns=CIP_Identity_Item_Log, 168 | $ev=log_cip_identity, 169 | $path="cip_identity", 170 | $policy=log_policy_cip_identity]); 171 | #Analyzer::register_for_ports(Analyzer::ANALYZER_ENIP_TCP, tcp_ports); 172 | #Analyzer::register_for_ports(Analyzer::ANALYZER_ENIP_UDP, udp_ports); 173 | # Monitor only the UDP Port assigned to implicit ENIP/CIP IO Messages 174 | Analyzer::register_for_ports(Analyzer::ANALYZER_ENIP_UDP, udp_implicit_ports); 175 | } 176 | 177 | ################################################################################################### 178 | ####### Ensure that conn.log:service is set if it has not already been ####### 179 | ################################################################################################### 180 | function set_service(c: connection, service: string) { 181 | if ((!c?$service) || (|c$service| == 0)) 182 | add c$service[service]; 183 | } 184 | 185 | ################################################################################################### 186 | ####################### Defines logging of enip_header event -> enip.log ######################## 187 | ################################################################################################### 188 | event enip_header(c: connection, 189 | is_orig: bool, 190 | packet_correlation_id: string, 191 | command: count, 192 | length: count, 193 | session_handle: count, 194 | status: count, 195 | sender_context: string, 196 | options: count) { 197 | 198 | set_service(c, "enip"); 199 | local enip_item: ENIP_Header; 200 | enip_item$ts = network_time(); 201 | enip_item$uid = c$uid; 202 | enip_item$id = c$id; 203 | enip_item$is_orig = is_orig; 204 | 205 | if(is_orig) 206 | { 207 | enip_item$source_h = c$id$orig_h; 208 | enip_item$source_p = c$id$orig_p; 209 | enip_item$destination_h = c$id$resp_h; 210 | enip_item$destination_p = c$id$resp_p; 211 | }else 212 | { 213 | enip_item$source_h = c$id$resp_h; 214 | enip_item$source_p = c$id$resp_p; 215 | enip_item$destination_h = c$id$orig_h; 216 | enip_item$destination_p = c$id$orig_p; 217 | } 218 | 219 | enip_item$packet_correlation_id = packet_correlation_id; 220 | enip_item$enip_command_code = fmt("0x%02x",command); 221 | enip_item$enip_command = enip_commands[command]; 222 | enip_item$length = length; 223 | enip_item$session_handle = fmt("0x%08x", session_handle); 224 | enip_item$enip_status = enip_statuses[status]; 225 | enip_item$sender_context = fmt("0x%s", bytestring_to_hexstr(sender_context)); 226 | enip_item$options = fmt("0x%08x", options); 227 | 228 | Log::write(LOG_ENIP, enip_item); 229 | } 230 | 231 | ################################################################################################### 232 | ######################## Defines logging of cip_header event -> cip.log ######################### 233 | ################################################################################################### 234 | event cip_header(c: connection, 235 | is_orig: bool, 236 | packet_correlation_id: string, 237 | cip_sequence_count: count, 238 | service: count, 239 | response: bool, 240 | status: count, 241 | status_extended: count, 242 | class_id: count, 243 | instance_id: count, 244 | attribute_id: count){ 245 | 246 | set_service(c, "cip"); 247 | local cip_header_item: CIP_Header; 248 | cip_header_item$ts = network_time(); 249 | cip_header_item$uid = c$uid; 250 | cip_header_item$id = c$id; 251 | cip_header_item$is_orig = is_orig; 252 | 253 | if(is_orig) 254 | { 255 | cip_header_item$source_h = c$id$orig_h; 256 | cip_header_item$source_p = c$id$orig_p; 257 | cip_header_item$destination_h = c$id$resp_h; 258 | cip_header_item$destination_p = c$id$resp_p; 259 | }else 260 | { 261 | cip_header_item$source_h = c$id$resp_h; 262 | cip_header_item$source_p = c$id$resp_p; 263 | cip_header_item$destination_h = c$id$orig_h; 264 | cip_header_item$destination_p = c$id$orig_p; 265 | } 266 | 267 | if (cip_sequence_count != 0) 268 | cip_header_item$cip_sequence_count = cip_sequence_count; 269 | 270 | cip_header_item$packet_correlation_id = packet_correlation_id; 271 | cip_header_item$cip_service_code = fmt("0x%02x",service); 272 | cip_header_item$cip_service = cip_services[service]; 273 | 274 | if(response) 275 | { 276 | cip_header_item$direction = "response"; 277 | if (status != UINT32_MAX ) 278 | { 279 | cip_header_item$cip_status_code = fmt("0x%02x", status); 280 | cip_header_item$cip_status = cip_statuses[status]; 281 | } 282 | 283 | if (status_extended != UINT32_MAX ) 284 | { 285 | cip_header_item$cip_extended_status_code = fmt("0x%04x", status_extended); 286 | cip_header_item$cip_extended_status = cip_extended_status[status_extended]; 287 | } 288 | }else 289 | { 290 | cip_header_item$direction = "request"; 291 | 292 | if(class_id != UINT32_MAX){ 293 | cip_header_item$class_id = fmt("0x%02x",class_id); 294 | cip_header_item$class_name = cip_classes[class_id]; 295 | } 296 | 297 | if(instance_id != UINT32_MAX) 298 | cip_header_item$instance_id = fmt("0x%02x",instance_id); 299 | 300 | if(attribute_id != UINT32_MAX) 301 | cip_header_item$attribute_id = fmt("0x%02x",attribute_id); 302 | 303 | } 304 | 305 | Log::write(LOG_CIP, cip_header_item); 306 | } 307 | 308 | ################################################################################################### 309 | ######################### Defines logging of cip_io event -> cip_io.log ######################### 310 | ################################################################################################### 311 | event cip_io(c: connection, 312 | is_orig: bool, 313 | packet_correlation_id: string, 314 | connection_identifier: count, 315 | sequence_number: count, 316 | data_length: count, 317 | data: string){ 318 | 319 | set_service(c, "cip"); 320 | local cip_io_item: CIP_IO_Log; 321 | cip_io_item$ts = network_time(); 322 | cip_io_item$uid = c$uid; 323 | cip_io_item$id = c$id; 324 | cip_io_item$is_orig = is_orig; 325 | 326 | if(is_orig) 327 | { 328 | cip_io_item$source_h = c$id$orig_h; 329 | cip_io_item$source_p = c$id$orig_p; 330 | cip_io_item$destination_h = c$id$resp_h; 331 | cip_io_item$destination_p = c$id$resp_p; 332 | }else 333 | { 334 | cip_io_item$source_h = c$id$resp_h; 335 | cip_io_item$source_p = c$id$resp_p; 336 | cip_io_item$destination_h = c$id$orig_h; 337 | cip_io_item$destination_p = c$id$orig_p; 338 | } 339 | 340 | cip_io_item$packet_correlation_id = packet_correlation_id; 341 | cip_io_item$connection_id = fmt("0x%08x", connection_identifier);; 342 | cip_io_item$sequence_number = sequence_number; 343 | cip_io_item$data_length = data_length; 344 | cip_io_item$io_data = bytestring_to_hexstr(data); 345 | 346 | Log::write(LOG_CIP_IO, cip_io_item); 347 | } 348 | 349 | ################################################################################################### 350 | ################### Defines logging of cip_identity event -> cip_identity.log ################### 351 | ################################################################################################### 352 | event cip_identity(c: connection, 353 | is_orig: bool, 354 | packet_correlation_id: string, 355 | encapsulation_version: count, 356 | socket_address: count, 357 | socket_port: count, 358 | vendor_id: count, 359 | device_type: count, 360 | product_code: count, 361 | revision_major: count, 362 | revision_minor: count, 363 | status: count, 364 | serial_number: count, 365 | product_name: string, 366 | state: count ){ 367 | 368 | set_service(c, "cip"); 369 | local cip_identity_item: CIP_Identity_Item_Log; 370 | cip_identity_item$ts = network_time(); 371 | cip_identity_item$uid = c$uid; 372 | cip_identity_item$id = c$id; 373 | cip_identity_item$is_orig = is_orig; 374 | 375 | if(is_orig) 376 | { 377 | cip_identity_item$source_h = c$id$orig_h; 378 | cip_identity_item$source_p = c$id$orig_p; 379 | cip_identity_item$destination_h = c$id$resp_h; 380 | cip_identity_item$destination_p = c$id$resp_p; 381 | }else 382 | { 383 | cip_identity_item$source_h = c$id$resp_h; 384 | cip_identity_item$source_p = c$id$resp_p; 385 | cip_identity_item$destination_h = c$id$orig_h; 386 | cip_identity_item$destination_p = c$id$orig_p; 387 | } 388 | 389 | cip_identity_item$packet_correlation_id = packet_correlation_id; 390 | 391 | cip_identity_item$encapsulation_version = encapsulation_version; 392 | cip_identity_item$socket_address = count_to_v4_addr(socket_address); 393 | cip_identity_item$socket_port = socket_port; 394 | cip_identity_item$vendor_id = vendor_id; 395 | cip_identity_item$vendor_name = cip_vendors[vendor_id]; 396 | cip_identity_item$device_type_id = device_type; 397 | cip_identity_item$device_type_name = cip_device_types[device_type]; 398 | cip_identity_item$product_code = product_code; 399 | cip_identity_item$revision = fmt("%d.%d", revision_major, revision_minor); 400 | cip_identity_item$device_status = fmt("0x%04x", status); 401 | cip_identity_item$serial_number = fmt("0x%08x", serial_number); 402 | cip_identity_item$product_name = product_name; 403 | cip_identity_item$device_state = fmt("0x%04x", state); 404 | Log::write(LOG_CIP_IDENTITY, cip_identity_item); 405 | } 406 | -------------------------------------------------------------------------------- /src/ENIP.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. 2 | 3 | #include "ENIP.h" 4 | #include 5 | #include 6 | #include "events.bif.h" 7 | 8 | namespace zeek::analyzer::enip { 9 | ENIP_TCP_Analyzer::ENIP_TCP_Analyzer(Connection* c): analyzer::tcp::TCP_ApplicationAnalyzer("ENIP_TCP", c) 10 | { 11 | interp = new binpac::ENIP::ENIP_Conn(this); 12 | had_gap = false; 13 | } 14 | 15 | ENIP_TCP_Analyzer::~ENIP_TCP_Analyzer() 16 | { 17 | delete interp; 18 | } 19 | 20 | void ENIP_TCP_Analyzer::Done() 21 | { 22 | analyzer::tcp::TCP_ApplicationAnalyzer::Done(); 23 | interp->FlowEOF(true); 24 | interp->FlowEOF(false); 25 | } 26 | 27 | void ENIP_TCP_Analyzer::EndpointEOF(bool is_orig) 28 | { 29 | analyzer::tcp::TCP_ApplicationAnalyzer::EndpointEOF(is_orig); 30 | interp->FlowEOF(is_orig); 31 | } 32 | 33 | void ENIP_TCP_Analyzer::DeliverStream(int len, const u_char* data, bool orig) 34 | { 35 | analyzer::tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); 36 | assert(TCP()); 37 | 38 | // Commenting out the two lines below to retain ENIP logging when [TCP ACKed unseen segment] 39 | // or [TCP Retransmission] packets are sent which results in a TCP gap 40 | // if(had_gap) 41 | // return; 42 | 43 | try 44 | { 45 | interp->NewData(orig, data, data + len); 46 | } 47 | catch(const binpac::Exception& e) 48 | { 49 | #if ZEEK_VERSION_NUMBER < 40200 50 | ProtocolViolation(util::fmt("Binpac exception: %s", e.c_msg())); 51 | 52 | #else 53 | AnalyzerViolation(util::fmt("Binpac exception: %s", e.c_msg())); 54 | 55 | #endif 56 | } 57 | } 58 | 59 | void ENIP_TCP_Analyzer::Undelivered(uint64_t seq, int len, bool orig) 60 | { 61 | analyzer::tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); 62 | had_gap = true; 63 | interp->NewGap(orig, len); 64 | } 65 | 66 | ENIP_UDP_Analyzer::ENIP_UDP_Analyzer(Connection* c): analyzer::Analyzer("ENIP_UDP", c) 67 | { 68 | interp = new binpac::ENIP::ENIP_Conn(this); 69 | } 70 | 71 | ENIP_UDP_Analyzer::~ENIP_UDP_Analyzer() 72 | { 73 | delete interp; 74 | } 75 | 76 | void ENIP_UDP_Analyzer::Done() 77 | { 78 | zeek::analyzer::Analyzer::Done(); 79 | } 80 | 81 | void ENIP_UDP_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint64_t seq, const zeek::IP_Hdr* ip, int caplen) 82 | { 83 | zeek::analyzer::Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen); 84 | 85 | try 86 | { 87 | interp->NewData(orig, data, data + len); 88 | } 89 | catch ( const binpac::Exception& e ) 90 | { 91 | #if ZEEK_VERSION_NUMBER < 40200 92 | ProtocolViolation(util::fmt("Binpac exception: %s", e.c_msg())); 93 | 94 | #else 95 | AnalyzerViolation(util::fmt("Binpac exception: %s", e.c_msg())); 96 | 97 | #endif 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /src/ENIP.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #if __has_include() 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | #include 12 | #if ZEEK_VERSION_NUMBER >= 40100 13 | #include 14 | #else 15 | #include 16 | #endif 17 | 18 | #include "enip_pac.h" 19 | 20 | namespace zeek::analyzer::enip { 21 | class ENIP_TCP_Analyzer : public analyzer::tcp::TCP_ApplicationAnalyzer 22 | { 23 | public: 24 | ENIP_TCP_Analyzer(Connection* conn); 25 | virtual ~ENIP_TCP_Analyzer(); 26 | 27 | virtual void Done(); 28 | virtual void DeliverStream(int len, const u_char* data, bool orig); 29 | virtual void Undelivered(uint64_t seq, int len, bool orig); 30 | 31 | virtual void EndpointEOF(bool is_orig); 32 | 33 | static analyzer::Analyzer* Instantiate(Connection* conn) 34 | { 35 | return new ENIP_TCP_Analyzer(conn); 36 | } 37 | 38 | protected: 39 | binpac::ENIP::ENIP_Conn* interp; 40 | bool had_gap; 41 | }; 42 | 43 | class ENIP_UDP_Analyzer : public analyzer::Analyzer 44 | { 45 | 46 | public: 47 | ENIP_UDP_Analyzer(Connection* conn); 48 | virtual ~ENIP_UDP_Analyzer(); 49 | virtual void Done(); 50 | 51 | virtual void DeliverPacket(int len, const u_char* data, bool orig, uint64_t seq, const IP_Hdr* ip, int caplen); 52 | 53 | static analyzer::Analyzer* Instantiate(Connection* conn) 54 | { 55 | return new ENIP_UDP_Analyzer(conn); 56 | } 57 | 58 | protected: 59 | binpac::ENIP::ENIP_Conn* interp; 60 | 61 | }; 62 | } // namespace zeek::analyzer::enip 63 | -------------------------------------------------------------------------------- /src/Plugin.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. 2 | #include "Plugin.h" 3 | #include "zeek/analyzer/Component.h" 4 | 5 | namespace plugin 6 | { 7 | namespace ICSNPP_ENIP 8 | { 9 | Plugin plugin; 10 | } 11 | } 12 | 13 | using namespace plugin::ICSNPP_ENIP; 14 | 15 | zeek::plugin::Configuration Plugin::Configure() 16 | { 17 | AddComponent(new zeek::analyzer::Component("ENIP_TCP",zeek::analyzer::enip::ENIP_TCP_Analyzer::Instantiate)); 18 | AddComponent(new zeek::analyzer::Component("ENIP_UDP",zeek::analyzer::enip::ENIP_UDP_Analyzer::Instantiate)); 19 | 20 | zeek::plugin::Configuration config; 21 | config.name = "ICSNPP::ENIP"; 22 | config.description = "Ethernet/IP and CIP Protocol analyzer for TCP/UDP"; 23 | config.version.major = 1; 24 | config.version.minor = 3; 25 | 26 | return config; 27 | } 28 | -------------------------------------------------------------------------------- /src/Plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | #include "ENIP.h" 6 | 7 | namespace plugin 8 | { 9 | namespace ICSNPP_ENIP 10 | { 11 | class Plugin : public zeek::plugin::Plugin 12 | { 13 | protected: 14 | virtual zeek::plugin::Configuration Configure(); 15 | }; 16 | 17 | extern Plugin plugin; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/consts.pac: -------------------------------------------------------------------------------- 1 | ## consts.pac 2 | ## 3 | ## Binpac Ethernet/IP (ENIP) Analyzer - Contains the constants definitions for Ethernet/IP and CIP 4 | ## 5 | ## Author: Stephen Kleinheider 6 | ## Contact: stephen.kleinheider@inl.gov 7 | ## 8 | ## Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. 9 | 10 | ############################################################ 11 | ############### Ethernet/IP Command Codes ################ 12 | ############################################################ 13 | enum command_codes 14 | { 15 | NOP = 0x0000, 16 | LIST_SERVICES = 0x0004, 17 | LIST_IDENTITY = 0x0063, 18 | LIST_INTERFACES = 0x0064, 19 | REGISTER_SESSION = 0x0065, 20 | UNREGISTER_SESSION = 0x0066, 21 | SEND_RR_DATA = 0x006F, 22 | SEND_UNIT_DATA = 0x0070, 23 | START_DTLS = 0x00C8, 24 | } 25 | 26 | ############################################################ 27 | ###### Ethernet/IP Common Packet Format Item Types ####### 28 | ############################################################ 29 | enum cpf_item_types 30 | { 31 | NULL_ADDRESS = 0x0000, 32 | CIP_IDENTITY = 0x000C, 33 | CIP_SECURITY = 0x0086, 34 | ENIP_CAPABILITY = 0x0087, 35 | CONNECTED_ADDRESS = 0x00A1, 36 | CONNECTED_TRANSPORT_DATA = 0x00B1, 37 | UNCONNECTED_MESSAGE_DATA = 0x00B2, 38 | LIST_SERVICES_RESPONSE = 0x0100, 39 | SOCK_ADDR_DATA_ORIG_TO_TARGET = 0x8000, 40 | SOCK_ADDR_DATA_TARGET_TO_ORIG = 0x8001, 41 | SEQUENCED_ADDRESS_ITEM = 0x8002, 42 | UNCONNECTED_MESSAGE_DTLS = 0x8003, 43 | # 0x0001 - 0x000B -> Reserved for legacy usage 44 | # 0x000D - 0x0085 -> Reserved for legacy usage 45 | # 0x0088 - 0x0090 -> Reserved for future expansion 46 | # 0x0091 - 0x0091 -> Reserved for legacy usage 47 | # 0x0092 - 0x00A0 -> Reserved for future expansion 48 | # 0x00A2 - 0x00A4 -> Reserved for legacy usage 49 | # 0x00A5 - 0x00B0 -> Reserved for future expansion 50 | # 0x00B3 - 0x00FF -> Reserved for future expansion 51 | # 0x0101 - 0x010F -> Reserved for legacy usage 52 | # 0x0110 - 0x07FF -> Reserved for future expansion 53 | # 0x8004 - 0xFFFF -> Reserved for future expansion 54 | } 55 | 56 | ############################################################ 57 | ################## CIP Common Services ################### 58 | ############################################################ 59 | enum cip_common_services 60 | { 61 | GET_ATTRIBUTES_ALL = 0x01, 62 | SET_ATTRIBUTES_ALL = 0x02, 63 | GET_ATTRIBUTE_LIST = 0x03, 64 | SET_ATTRIBUTE_LIST = 0x04, 65 | RESET = 0x05, 66 | START = 0x06, 67 | STOP = 0x07, 68 | CREATE = 0x08, 69 | DELETE = 0x09, 70 | MULTIPLE_SERVICE = 0x0A, 71 | APPLY_ATTRIBUTES = 0x0D, 72 | GET_ATTRIBUTE_SINGLE = 0x0E, 73 | SET_ATTRIBUTE_SINGLE = 0x10, 74 | FIND_NEXT_OBJECT_INSTANCE = 0x11, 75 | RESTORE = 0x15, 76 | SAVE = 0x16, 77 | NO_OPERATION = 0x17, 78 | GET_MEMBER = 0x18, 79 | SET_MEMBER = 0x18, 80 | INSERT_MEMBER = 0x1A, 81 | REMOVE_MEMBER = 0x1B, 82 | GROUP_SYNC = 0x1C, 83 | GET_CONNECTION_POINT_MEMBER_LIST = 0x1D, 84 | GET_ATTRIBUTES_ALL_RESPONSE = 0x81, 85 | GET_ATTRIBUTE_LIST_RESPONSE = 0x83, 86 | SET_ATTRIBUTE_LIST_RESPONSE = 0x84, 87 | MULTIPLE_SERVICE_RESPONSE = 0x8A, 88 | GET_ATTRIBUTE_SINGLE_RESPONSE = 0x8E, 89 | } -------------------------------------------------------------------------------- /src/enip-analyzer.pac: -------------------------------------------------------------------------------- 1 | ## enip-analyzer.pac 2 | ## 3 | ## Binpac Ethernet/IP (ENIP) Analyzer - Adds processing functions to ENIP_Flow to generate events. 4 | ## 5 | ## Author: Stephen Kleinheider 6 | ## Contact: stephen.kleinheider@inl.gov 7 | ## 8 | ## Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. 9 | 10 | %extern{ 11 | #include 12 | #include 13 | %} 14 | %header{ 15 | 16 | typedef struct CIP_Request_Path { 17 | uint32 class_id, instance_id, attribute_id; 18 | 19 | CIP_Request_Path(){ 20 | class_id = UINT32_MAX; 21 | instance_id = UINT32_MAX; 22 | attribute_id = UINT32_MAX; 23 | } 24 | 25 | }CIP_Request_Path; 26 | 27 | 28 | uint32 get_unsigned(const_bytestring data); 29 | uint32 get_number(uint8 size, uint8 x, const_bytestring data); 30 | CIP_Request_Path parse_request_path(const_bytestring data); 31 | CIP_Request_Path parse_request_multiple_service_packet(const_bytestring data, uint16 starting_location); 32 | %} 33 | 34 | %code{ 35 | 36 | // Get uint32 number from status_extended array 37 | uint32 get_unsigned(const_bytestring data) 38 | { 39 | if(data.length() == 0) 40 | { 41 | return UINT32_MAX; 42 | } 43 | uint32 number = 0; 44 | for ( int32 i = 0; i < data.length(); ++i ){ 45 | number <<= 8; 46 | number |= data[i]; 47 | 48 | if ( i == 3 ) 49 | return number; 50 | } 51 | return number; 52 | } 53 | 54 | // Get uint32 number from data in request path 55 | uint32 get_number(uint8 size, uint16 x, const_bytestring data) 56 | { 57 | if(size == 0) 58 | return data[x]; 59 | else if (size == 1) 60 | return (data[x+1] << 8) | data[x]; 61 | else if (size == 2) 62 | return (data[x+3] << 24) | (data[x+2] << 13) | (data[x+1] << 8) | data[x]; 63 | 64 | return UINT32_MAX; 65 | } 66 | 67 | // Parse request path and return CIP_Request_Path struct 68 | CIP_Request_Path parse_request_path(const_bytestring data) 69 | { 70 | CIP_Request_Path request_path; 71 | 72 | uint16 x = 0; 73 | uint16 data_length = data.length(); 74 | 75 | while( (x+1) < data_length ) 76 | { 77 | if ((data[x] >> 5) == 1) 78 | { 79 | uint16 choice = (data[x] & 0x1c) >> 2; 80 | uint16 size = data[x] & 3; 81 | x += 1; 82 | if(size > 0) 83 | x += 1; 84 | 85 | if(choice == 0) 86 | request_path.class_id = get_number(size, x, data); 87 | else if(choice == 1) 88 | request_path.instance_id = get_number(size, x, data); 89 | else if(choice == 4) 90 | request_path.attribute_id = get_number(size, x, data); 91 | 92 | if(size == 0) 93 | x += 1; 94 | else if(size == 1) 95 | x += 2; 96 | else 97 | x += 4; 98 | } 99 | else 100 | { 101 | return request_path; 102 | } 103 | } 104 | return request_path; 105 | } 106 | 107 | // Parse request path from multiple service packet and return CIP_Request_Path struct 108 | CIP_Request_Path parse_request_multiple_service_packet(const_bytestring data, uint16 starting_location) 109 | { 110 | CIP_Request_Path request_path; 111 | 112 | uint16 x = starting_location; 113 | uint16 data_length = starting_location + (data[x] * 2) + 1; 114 | x += 1; 115 | 116 | while( (x + 1) < data_length ) 117 | { 118 | if ((data[x] >> 5) == 1) 119 | { 120 | uint16 choice = (data[x] & 0x1c) >> 2; 121 | uint16 size = data[x] & 3; 122 | x += 1; 123 | if(size > 0) 124 | x += 1; 125 | 126 | if(choice == 0) 127 | request_path.class_id = get_number(size, x, data); 128 | else if(choice == 1) 129 | request_path.instance_id = get_number(size, x, data); 130 | else if(choice == 4) 131 | request_path.attribute_id = get_number(size, x, data); 132 | 133 | if(size == 0) 134 | x += 1; 135 | else if(size == 1) 136 | x += 2; 137 | else 138 | x += 4; 139 | } 140 | else 141 | { 142 | return request_path; 143 | } 144 | 145 | } 146 | return request_path; 147 | } 148 | 149 | %} 150 | 151 | refine flow ENIP_Flow += { 152 | 153 | ############################################################################################### 154 | ############################ Process data for enip_header event ############################# 155 | ############################################################################################### 156 | function process_enip_header(enip_header: ENIP_Header): bool 157 | %{ 158 | if ( ::enip_header ) 159 | { 160 | zeek::BifEvent::enqueue_enip_header(connection()->zeek_analyzer(), 161 | connection()->zeek_analyzer()->Conn(), 162 | ${enip_header.is_originator}, 163 | zeek::make_intrusive(${enip_header.packet_correlation_id}), 164 | ${enip_header.command}, 165 | ${enip_header.length}, 166 | ${enip_header.session_handle}, 167 | ${enip_header.status}, 168 | to_stringval(${enip_header.sender_context}), 169 | ${enip_header.options}); 170 | } 171 | return true; 172 | %} 173 | 174 | ############################################################################################### 175 | ############################# Process data for cip_header event ############################# 176 | ############################################################################################### 177 | function process_cip_header(cip_header: CIP_Header): bool 178 | %{ 179 | if ( ::cip_header ) 180 | { 181 | // MULTIPLE_SERVICE CIP header data is parsed in process_multiple_service_request 182 | // and process_multiple_service_response functions, so no need to duplicate 183 | // parsing here 184 | if(${cip_header.service_code} == MULTIPLE_SERVICE) 185 | return true; 186 | 187 | uint32 status = UINT32_MAX; 188 | uint32 status_extended = UINT32_MAX; 189 | CIP_Request_Path request_path; 190 | 191 | if(${cip_header.request_or_response} == 1) 192 | { 193 | status = ${cip_header.response_packet.status}; 194 | status_extended = get_unsigned(${cip_header.response_packet.status_extended}); 195 | }else 196 | { 197 | request_path = parse_request_path(${cip_header.request_path.request_path}); 198 | } 199 | 200 | zeek::BifEvent::enqueue_cip_header(connection()->zeek_analyzer(), 201 | connection()->zeek_analyzer()->Conn(), 202 | ${cip_header.is_originator}, 203 | zeek::make_intrusive(${cip_header.packet_correlation_id}), 204 | ${cip_header.cip_sequence_count}, 205 | ${cip_header.service_code}, 206 | (${cip_header.request_or_response} == 1), 207 | status, 208 | status_extended, 209 | request_path.class_id, 210 | request_path.instance_id, 211 | request_path.attribute_id); 212 | } 213 | return true; 214 | %} 215 | 216 | ############################################################################################### 217 | ############################### Process data for cip_io event ############################### 218 | ############################################################################################### 219 | function process_cip_io(cip_io_item: CIP_IO): bool 220 | %{ 221 | if ( ::cip_io ) 222 | { 223 | zeek::BifEvent::enqueue_cip_io(connection()->zeek_analyzer(), 224 | connection()->zeek_analyzer()->Conn(), 225 | ${cip_io_item.is_originator}, 226 | zeek::make_intrusive(${cip_io_item.packet_correlation_id}), 227 | ${cip_io_item.sequenced_address_item.connection_identifier}, 228 | ${cip_io_item.sequenced_address_item.encap_sequence_number}, 229 | ${cip_io_item.connected_data_length}, 230 | to_stringval(${cip_io_item.connected_data_item})); 231 | } 232 | return true; 233 | %} 234 | 235 | ############################################################################################### 236 | ############################ Process data for cip_identity event ############################ 237 | ############################################################################################### 238 | function process_cip_identity_item(identity_item: CIP_Identity_Item): bool 239 | %{ 240 | if ( ::cip_identity ) 241 | { 242 | zeek::BifEvent::enqueue_cip_identity(connection()->zeek_analyzer(), 243 | connection()->zeek_analyzer()->Conn(), 244 | ${identity_item.is_originator}, 245 | zeek::make_intrusive(${identity_item.packet_correlation_id}), 246 | ${identity_item.encapsulation_version}, 247 | ${identity_item.socket_address.sin_addr}, 248 | ${identity_item.socket_address.sin_port}, 249 | ${identity_item.vendor_id}, 250 | ${identity_item.device_type}, 251 | ${identity_item.product_code}, 252 | ${identity_item.revision_major}, 253 | ${identity_item.revision_minor}, 254 | ${identity_item.status}, 255 | ${identity_item.serial_number}, 256 | to_stringval(${identity_item.product_name}), 257 | ${identity_item.state}); 258 | } 259 | return true; 260 | %} 261 | 262 | ############################################################################################### 263 | ########################## Process data for register_session event ########################## 264 | ############################################################################################### 265 | function process_register_session(message: Register_Session): bool 266 | %{ 267 | if ( ::register_session ) 268 | { 269 | zeek::BifEvent::enqueue_register_session(connection()->zeek_analyzer(), 270 | connection()->zeek_analyzer()->Conn(), 271 | ${message.is_originator}, 272 | ${message.protocol_version}, 273 | ${message.options_flags}); 274 | } 275 | return true; 276 | %} 277 | 278 | ############################################################################################### 279 | ############################ Process data for cip_security event ############################ 280 | ############################################################################################### 281 | function process_cip_security_item(security_item: CIP_Security_Item): bool 282 | %{ 283 | if ( ::cip_security ) 284 | { 285 | zeek::BifEvent::enqueue_cip_security(connection()->zeek_analyzer(), 286 | connection()->zeek_analyzer()->Conn(), 287 | ${security_item.is_originator}, 288 | ${security_item.security_profile}, 289 | ${security_item.cip_security_state}, 290 | ${security_item.enip_security_state}, 291 | ${security_item.iana_port_state}); 292 | } 293 | return true; 294 | %} 295 | 296 | ############################################################################################### 297 | ########################## Process data for enip_capability event ########################### 298 | ############################################################################################### 299 | function process_enip_capability_item(enip_item: ENIP_Capability_Item): bool 300 | %{ 301 | if ( ::enip_capability ) 302 | { 303 | zeek::BifEvent::enqueue_enip_capability(connection()->zeek_analyzer(), 304 | connection()->zeek_analyzer()->Conn(), 305 | ${enip_item.is_originator}, 306 | ${enip_item.enip_profile}); 307 | } 308 | return true; 309 | %} 310 | 311 | ############################################################################################### 312 | ############################ Process data for enip_service event ############################ 313 | ############################################################################################### 314 | function process_service_item(service_item: Service_Item): bool 315 | %{ 316 | if ( ::enip_service ) 317 | { 318 | zeek::BifEvent::enqueue_enip_service(connection()->zeek_analyzer(), 319 | connection()->zeek_analyzer()->Conn(), 320 | ${service_item.is_originator}, 321 | ${service_item.protocol_version}, 322 | ${service_item.capability_flags}, 323 | to_stringval(${service_item.service_name})); 324 | } 325 | return true; 326 | %} 327 | 328 | ############################################################################################### 329 | ######################### Process data for connected_address event ########################## 330 | ############################################################################################### 331 | function process_connected_address_item(address_item: Connected_Address_Item): bool 332 | %{ 333 | if ( ::connected_address ) 334 | { 335 | zeek::BifEvent::enqueue_connected_address(connection()->zeek_analyzer(), 336 | connection()->zeek_analyzer()->Conn(), 337 | ${address_item.is_originator}, 338 | ${address_item.connection_identifier}); 339 | } 340 | return true; 341 | %} 342 | 343 | ############################################################################################### 344 | ######################### Process data for sequenced_address event ########################## 345 | ############################################################################################### 346 | function process_sequenced_address_item(address_item: Sequenced_Address_Item): bool 347 | %{ 348 | if ( ::sequenced_address ) 349 | { 350 | zeek::BifEvent::enqueue_sequenced_address(connection()->zeek_analyzer(), 351 | connection()->zeek_analyzer()->Conn(), 352 | ${address_item.is_originator}, 353 | ${address_item.connection_identifier}, 354 | ${address_item.encap_sequence_number}); 355 | } 356 | return true; 357 | %} 358 | 359 | ############################################################################################### 360 | ###################### Process data for unconnected_message_dtls event ###################### 361 | ############################################################################################### 362 | function process_unconnected_message_dtls(message: Unconnected_Message_DTLS): bool 363 | %{ 364 | if ( ::unconnected_message_dtls ) 365 | { 366 | zeek::BifEvent::enqueue_unconnected_message_dtls(connection()->zeek_analyzer(), 367 | connection()->zeek_analyzer()->Conn(), 368 | ${message.is_originator}, 369 | ${message.unconn_message_type}, 370 | ${message.transaction_number}, 371 | ${message.status}); 372 | } 373 | return true; 374 | %} 375 | 376 | ############################################################################################### 377 | ######################## Process data for socket_address_info event ######################### 378 | ############################################################################################### 379 | function process_socket_address_info(item: Socket_Address_Info_Item): bool 380 | %{ 381 | if ( ::socket_address_info ) 382 | { 383 | zeek::BifEvent::enqueue_socket_address_info(connection()->zeek_analyzer(), 384 | connection()->zeek_analyzer()->Conn(), 385 | ${item.is_originator}, 386 | ${item.sin_addr}, 387 | ${item.sin_port}); 388 | } 389 | return true; 390 | %} 391 | 392 | ############################################################################################### 393 | ##################### Process data for get_attribute_all_response event ##################### 394 | ############################################################################################### 395 | function process_get_attribute_all_response(data: Get_Attributes_All_Response): bool 396 | %{ 397 | if ( ::get_attribute_all_response ) 398 | { 399 | zeek::BifEvent::enqueue_get_attribute_all_response(connection()->zeek_analyzer(), 400 | connection()->zeek_analyzer()->Conn(), 401 | ${data.is_originator}, 402 | to_stringval(${data.attribute_data})); 403 | } 404 | return true; 405 | %} 406 | 407 | ############################################################################################### 408 | ##################### Process data for set_attribute_all_request event ###################### 409 | ############################################################################################### 410 | function process_set_attribute_all_request(data: Set_Attributes_All_Request): bool 411 | %{ 412 | if ( ::set_attribute_all_request ) 413 | { 414 | zeek::BifEvent::enqueue_set_attribute_all_request(connection()->zeek_analyzer(), 415 | connection()->zeek_analyzer()->Conn(), 416 | ${data.is_originator}, 417 | to_stringval(${data.attribute_data})); 418 | } 419 | return true; 420 | %} 421 | 422 | ############################################################################################### 423 | ##################### Process data for get_attribute_list_request event ##################### 424 | ############################################################################################### 425 | function process_get_attribute_list_request(data: Get_Attribute_List_Request): bool 426 | %{ 427 | if ( ::get_attribute_list_request ) 428 | { 429 | string attribute_ids = zeek::util::fmt("%d",${data.attribute_list[0]}); 430 | 431 | for(uint8 i=1; i<${data.attribute_count};i++) 432 | attribute_ids += zeek::util::fmt(",%d",${data.attribute_list[i]}); 433 | 434 | zeek::BifEvent::enqueue_get_attribute_list_request(connection()->zeek_analyzer(), 435 | connection()->zeek_analyzer()->Conn(), 436 | ${data.is_originator}, 437 | ${data.attribute_count}, 438 | zeek::make_intrusive(attribute_ids)); 439 | } 440 | return true; 441 | %} 442 | 443 | ############################################################################################### 444 | #################### Process data for get_attribute_list_response event ##################### 445 | ############################################################################################### 446 | function process_get_attribute_list_response(data: Get_Attribute_List_Response): bool 447 | %{ 448 | if ( ::get_attribute_list_response ) 449 | { 450 | zeek::BifEvent::enqueue_get_attribute_list_response(connection()->zeek_analyzer(), 451 | connection()->zeek_analyzer()->Conn(), 452 | ${data.is_originator}, 453 | ${data.attribute_count}, 454 | to_stringval(${data.attribute_data})); 455 | } 456 | return true; 457 | %} 458 | 459 | ############################################################################################### 460 | ##################### Process data for set_attribute_list_request event ##################### 461 | ############################################################################################### 462 | function process_set_attribute_list_request(data: Set_Attribute_List_Request): bool 463 | %{ 464 | if ( ::set_attribute_list_request ) 465 | { 466 | zeek::BifEvent::enqueue_set_attribute_list_request(connection()->zeek_analyzer(), 467 | connection()->zeek_analyzer()->Conn(), 468 | ${data.is_originator}, 469 | ${data.attribute_count}, 470 | to_stringval(${data.attribute_data})); 471 | } 472 | return true; 473 | %} 474 | 475 | ############################################################################################### 476 | #################### Process data for set_attribute_list_response event ##################### 477 | ############################################################################################### 478 | function process_set_attribute_list_response(data: Set_Attribute_List_Response): bool 479 | %{ 480 | if ( ::set_attribute_list_response ) 481 | { 482 | zeek::BifEvent::enqueue_set_attribute_list_response(connection()->zeek_analyzer(), 483 | connection()->zeek_analyzer()->Conn(), 484 | ${data.is_originator}, 485 | ${data.attribute_count}, 486 | to_stringval(${data.attribute_data})); 487 | } 488 | return true; 489 | %} 490 | 491 | ############################################################################################### 492 | ###################### Process data for multiple_service_request event ###################### 493 | ############################################################################################### 494 | function process_multiple_service_request(data: Multiple_Service_Packet_Request): bool 495 | %{ 496 | if ( ::cip_header ) 497 | { 498 | uint16 service_packet_location; 499 | 500 | uint8 service_count = ${data.service_count}; 501 | uint16 cip_sequence_count = ${data.cip_sequence_count}; 502 | CIP_Request_Path request_path = parse_request_path(${data.request_path.request_path}); 503 | 504 | // CIP Header event for multiple service packet 505 | zeek::BifEvent::enqueue_cip_header(connection()->zeek_analyzer(), 506 | connection()->zeek_analyzer()->Conn(), 507 | ${data.is_originator}, 508 | zeek::make_intrusive(${data.packet_correlation_id}), 509 | ${data.cip_sequence_count}, 510 | MULTIPLE_SERVICE, 511 | false, 512 | UINT32_MAX, 513 | UINT32_MAX, 514 | request_path.class_id, 515 | request_path.instance_id, 516 | request_path.attribute_id); 517 | 518 | // CIP Header event for each service within multiple service packet 519 | for(uint8 i=0; i < service_count;i++) 520 | { 521 | service_packet_location = ${data.service_offsets[i]} - (2*service_count) - 2; 522 | request_path = parse_request_multiple_service_packet(${data.services},service_packet_location+1); 523 | 524 | zeek::BifEvent::enqueue_cip_header(connection()->zeek_analyzer(), 525 | connection()->zeek_analyzer()->Conn(), 526 | ${data.is_originator}, 527 | zeek::make_intrusive(${data.packet_correlation_id}), 528 | cip_sequence_count, 529 | ${data.services[service_packet_location]} & 0x7f, 530 | false, 531 | UINT32_MAX, 532 | UINT32_MAX, 533 | request_path.class_id, 534 | request_path.instance_id, 535 | request_path.attribute_id); 536 | } 537 | } 538 | 539 | return true; 540 | %} 541 | 542 | ############################################################################################### 543 | ##################### Process data for multiple_service_response event ###################### 544 | ############################################################################################### 545 | function process_multiple_service_response(data: Multiple_Service_Packet_Response): bool 546 | %{ 547 | if ( ::cip_header ) 548 | { 549 | CIP_Request_Path request_path; 550 | uint16 service_packet_location; 551 | 552 | uint8 service_count = ${data.service_count}; 553 | uint16 cip_sequence_count = ${data.cip_sequence_count}; 554 | 555 | // CIP Header event for multiple service packet 556 | zeek::BifEvent::enqueue_cip_header(connection()->zeek_analyzer(), 557 | connection()->zeek_analyzer()->Conn(), 558 | ${data.is_originator}, 559 | zeek::make_intrusive(${data.packet_correlation_id}), 560 | ${data.cip_sequence_count}, 561 | MULTIPLE_SERVICE, 562 | true, 563 | ${data.status}, 564 | get_unsigned(${data.status_extended}), 565 | request_path.class_id, 566 | request_path.instance_id, 567 | request_path.attribute_id); 568 | 569 | // CIP Header event for each service within multiple service packet 570 | for(uint8 i=0; i < service_count;i++) 571 | { 572 | service_packet_location = ${data.service_offsets[i]} - (2*service_count) - 2; 573 | 574 | zeek::BifEvent::enqueue_cip_header(connection()->zeek_analyzer(), 575 | connection()->zeek_analyzer()->Conn(), 576 | ${data.is_originator}, 577 | zeek::make_intrusive(${data.packet_correlation_id}), 578 | cip_sequence_count, 579 | ${data.services[service_packet_location]} & 0x7f, 580 | true, 581 | ${data.services[service_packet_location + 2]}, 582 | UINT32_MAX, 583 | request_path.class_id, 584 | request_path.instance_id, 585 | request_path.attribute_id); 586 | } 587 | } 588 | return true; 589 | %} 590 | 591 | ############################################################################################### 592 | ################### Process data for get_attribute_single_response event #################### 593 | ############################################################################################### 594 | function process_get_attribute_single_response(data: Get_Attribute_Single_Response): bool 595 | %{ 596 | if ( ::get_attribute_single_response ) 597 | { 598 | zeek::BifEvent::enqueue_get_attribute_single_response(connection()->zeek_analyzer(), 599 | connection()->zeek_analyzer()->Conn(), 600 | ${data.is_originator}, 601 | to_stringval(${data.attribute_data})); 602 | } 603 | return true; 604 | %} 605 | 606 | ############################################################################################### 607 | #################### Process data for set_attribute_single_request event #################### 608 | ############################################################################################### 609 | function process_set_attribute_single_request(data: Set_Attribute_Single_Request): bool 610 | %{ 611 | if ( ::set_attribute_single_request ) 612 | { 613 | zeek::BifEvent::enqueue_set_attribute_single_request(connection()->zeek_analyzer(), 614 | connection()->zeek_analyzer()->Conn(), 615 | ${data.is_originator}, 616 | ${data.attribute_id}, 617 | to_stringval(${data.attribute_data})); 618 | } 619 | return true; 620 | %} 621 | }; 622 | -------------------------------------------------------------------------------- /src/enip-protocol.pac: -------------------------------------------------------------------------------- 1 | ## enip-protocol.pac 2 | ## 3 | ## Binpac Ethernet/IP (ENIP) Analyzer - Defines Protocol Message Formats 4 | ## 5 | ## Author: Stephen Kleinheider 6 | ## Contact: stephen.kleinheider@inl.gov 7 | ## 8 | ## Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. 9 | 10 | %include consts.pac 11 | 12 | ################################################################################################### 13 | ##################################### ZEEK CONNECTION DATA ###################################### 14 | ################################################################################################### 15 | 16 | ## --------------------------------------------ENIP-PDU-------------------------------------------- 17 | ## Message Description: 18 | ## Main Ethernet/IP PDU 19 | ## Message Format: 20 | ## - header: ENIP_Header -> See ENIP_Header 21 | ## - body: variable -> ENIP_Originator or ENIP_Target 22 | ## Protocol Parsing: 23 | ## Starts protocol parsing by getting Ethernet/IP header and passes processing to either 24 | ## ENIP_Originator or ENIP_Target depending on is_orig value. 25 | ## ------------------------------------------------------------------------------------------------ 26 | type ENIP_PDU(is_orig: bool) = record { 27 | command: uint16; 28 | proto: case command of { 29 | 2 -> udp_pdu: CIP_IO(is_orig, packet_correlation_id); 30 | default -> tcp_pdu: ENIP_TCP(is_orig, command, packet_correlation_id); 31 | } &requires(packet_correlation_id); 32 | } &let { 33 | packet_correlation_id: string = $context.flow.generate_packet_id(); 34 | } &byteorder=littleendian; 35 | 36 | type ENIP_TCP(is_orig: bool, command: uint16, packet_correlation_id: string) = record { 37 | header : ENIP_Header(is_orig, command, packet_correlation_id); 38 | body : case is_orig of { 39 | true -> originator: ENIP_Originator(command, packet_correlation_id); 40 | false -> target: ENIP_Target(command, packet_correlation_id); 41 | }; 42 | } &byteorder=littleendian; 43 | 44 | ## ---------------------------------------------CIP-IO--------------------------------------------- 45 | ## Message Description: 46 | ## CIP IO uses a different format than other CIP packets 47 | ## Message Format: 48 | ## - sequenced_address_type: uint16 -> Always 0x8002 49 | ## - sequenced_address_length: uint16 -> Always 8 50 | ## - sequenced_address_item: Sequenced_Address_Item -> See Sequenced_Address_Item 51 | ## - connected_data_type: uint16 -> Always 0x00B1 52 | ## - connected_data_length: uint16 -> Length of connected_data 53 | ## - connected_data_item: variable -> CIP IO data 54 | ## Protocol Parsing: 55 | ## Starts protocol parsing by getting Ethernet/IP header and passes processing to either 56 | ## ENIP_Originator or ENIP_Target depending on is_orig value. 57 | ## ------------------------------------------------------------------------------------------------ 58 | type CIP_IO(is_orig: bool, packet_correlation_id: string) = record { 59 | sequenced_address_type: uint16; # Always 0x8002 60 | sequenced_address_length: uint16; # Always 8 61 | sequenced_address_item: Sequenced_Address_Item(is_orig); 62 | connected_data_type: uint16; # Always 0x00B1 63 | connected_data_length: uint16; 64 | connected_data_item: bytestring &length=connected_data_length; 65 | } &let { 66 | is_originator: bool = is_orig; 67 | deliver: bool = $context.flow.process_cip_io(this); 68 | } &byteorder=littleendian; 69 | 70 | ################################################################################################### 71 | ################################## END OF ZEEK CONNECTION DATA ################################## 72 | ################################################################################################### 73 | 74 | 75 | ################################################################################################### 76 | ##################################### ETHERNET/IP COMMANDS ###################################### 77 | ################################################################################################### 78 | 79 | ## ----------------------------------------ENIP-Originator----------------------------------------- 80 | ## Message Description: 81 | ## Ethernet/IP Message sent from the originator to the target. 82 | ## Protocol Parsing: 83 | ## Continue with parsing of Ethernet/IP message depending on ENIP command 84 | ## ------------------------------------------------------------------------------------------------ 85 | type ENIP_Originator(command: uint16, packet_correlation_id: string) = case command of { 86 | NOP -> nop: Nop; 87 | LIST_IDENTITY -> list_identity: empty; 88 | LIST_INTERFACES -> list_interfaces: empty; 89 | REGISTER_SESSION -> register_session: Register_Session(true); 90 | UNREGISTER_SESSION -> unregister_session: empty; 91 | LIST_SERVICES -> list_services: empty; 92 | SEND_RR_DATA -> send_rr_data: Send_RR_Data(true, packet_correlation_id); 93 | SEND_UNIT_DATA -> send_unit_data: Send_Unit_Data(true, packet_correlation_id); 94 | default -> unknown: bytestring &restofdata; 95 | }; 96 | 97 | ## ------------------------------------------ENIP-Target------------------------------------------- 98 | ## Message Description: 99 | ## Ethernet/IP Message sent from the target to the originator. 100 | ## Protocol Parsing: 101 | ## Continue with parsing of Ethernet/IP message depending on ENIP command 102 | ## ------------------------------------------------------------------------------------------------ 103 | type ENIP_Target(command: uint16, packet_correlation_id: string) = case command of { 104 | NOP -> nop: Nop; 105 | LIST_IDENTITY -> list_identity: List_Identity_Response(packet_correlation_id); 106 | LIST_INTERFACES -> list_interfaces: List_Interfaces_Response(packet_correlation_id); 107 | REGISTER_SESSION -> register_session: Register_Session(false); 108 | UNREGISTER_SESSION -> unregister_session: empty; 109 | LIST_SERVICES -> list_services: List_Services_Response(packet_correlation_id); 110 | SEND_RR_DATA -> send_rr_data: Send_RR_Data(false, packet_correlation_id); 111 | SEND_UNIT_DATA -> send_unit_data: Send_Unit_Data(false, packet_correlation_id); 112 | default -> unknown: bytestring &restofdata; 113 | }; 114 | 115 | ## ------------------------------------------ENIP-Header------------------------------------------- 116 | ## Message Description: 117 | ## Ethernet/IP fixed length 24 byte header. 118 | ## Message Format: 119 | ## - Command: uint16 -> Ethernet/IP Command (see command_codes) 120 | ## - Length: uint16 -> Length of ENIP data following header 121 | ## - Session Handle: uint32 -> Session identification 122 | ## - Status: uint32 -> Status code 123 | ## - Sender Context: uint8[8] -> Sender Context 124 | ## - Options: uint32 -> Options Flags 125 | ## Protocol Parsing: 126 | ## Sends header information to the enip_header event. By default this is then logged to the 127 | ## enip.log file as defined in main.zeek. 128 | ## ------------------------------------------------------------------------------------------------ 129 | type ENIP_Header(is_orig: bool, command: uint16, packet_correlation_id: string) = record { 130 | #command : uint16; 131 | length : uint16; 132 | session_handle : uint32; 133 | status : uint32; 134 | sender_context : bytestring &length=8; 135 | options : uint32; 136 | } &let { 137 | is_originator: bool = is_orig; 138 | deliver: bool = $context.flow.process_enip_header(this); 139 | } &byteorder=littleendian; 140 | 141 | ## ----------------------------------------------NOP----------------------------------------------- 142 | ## Message Description: 143 | ## A NOP (No Operation) command can be sent by either an originator or a target. No reply 144 | ## shall be generated by the command and the receiver shall ignore any data contained in the 145 | ## message. 146 | ## Message Format: 147 | ## - Unused Data: uint8[] -> Any value (ignored by target) 148 | ## Protocol Parsing: 149 | ## No event created for NOP command as all data should be ignored by target 150 | ## ------------------------------------------------------------------------------------------------ 151 | type Nop = record { 152 | unused_data : bytestring &restofdata; 153 | } &byteorder=littleendian; 154 | 155 | ## -------------------------------------List-Identity-Response------------------------------------- 156 | ## Message Description: 157 | ## An originator may use the ListIdentity command to locate and identify potential targets. 158 | ## The targets shall respond with the appropriate data items. 159 | ## Message Format: 160 | ## - Item Count: uint16 -> Number of target items to follow 161 | ## - Target Items: CPF_Item[] -> CIP Identity/Security or ENIP Capability 162 | ## Protocol Parsing: 163 | ## Continue with parsing of target items (see CIP_Identity_Item, ENIP_Capability_Item, and 164 | ## CIP_Security_Item) 165 | ## ------------------------------------------------------------------------------------------------ 166 | type List_Identity_Response(packet_correlation_id: string) = record { 167 | item_count : uint16; 168 | target_items : Common_Packet_Format_Item(false, packet_correlation_id)[item_count]; 169 | } &byteorder=littleendian; 170 | 171 | ## ------------------------------------List-Interfaces-Response------------------------------------ 172 | ## Message Description: 173 | ## The optional ListInterfaces command shall be used by an originator to identify non-CIP 174 | ## communication interfaces associated with the target. 175 | ## Message Format: 176 | ## - Item Count: uint16 -> Number of target items to follow 177 | ## - Target Items: CPF_Item[] -> See Common Packet Format Item 178 | ## Protocol Parsing: 179 | ## Continue with parsing of target items (see Common_Packet_Format_Item) 180 | ## ------------------------------------------------------------------------------------------------ 181 | type List_Interfaces_Response(packet_correlation_id: string) = record { 182 | item_count : uint16; 183 | target_items : Common_Packet_Format_Item(false, packet_correlation_id)[item_count]; 184 | } &byteorder=littleendian; 185 | 186 | ## ----------------------------------------Register-Session---------------------------------------- 187 | ## Message Description: 188 | ## An originator shall send a RegisterSession command to a target to initiate a session 189 | ## Message Format: 190 | ## - Protocol Version: uint16 -> Version of Protocol (currently 1) 191 | ## - Options Flag: uint16 -> Options Flag (no public options defined) 192 | ## Protocol Parsing: 193 | ## Sends protocol version and options flag to the register_session event 194 | ## ------------------------------------------------------------------------------------------------ 195 | type Register_Session(is_orig: bool) = record { 196 | protocol_version : uint16; 197 | options_flags : uint16; 198 | } &let { 199 | is_originator: bool = is_orig; 200 | deliver: bool = $context.flow.process_register_session(this); 201 | } &byteorder=littleendian; 202 | 203 | ## -------------------------------------List-Services-Response------------------------------------- 204 | ## Message Description: 205 | ## The ListServices command shall determine which encapsulation service classes the target 206 | ## device supports. 207 | ## Message Format: 208 | ## - Item Count: uint16 -> Number of target items to follow 209 | ## - Target Items: CPF_Item[] -> See Service_Item 210 | ## Protocol Parsing: 211 | ## Continue with parsing of target items (see Service_Item) 212 | ## ------------------------------------------------------------------------------------------------ 213 | type List_Services_Response(packet_correlation_id: string) = record { 214 | item_count : uint16; 215 | target_items : Common_Packet_Format_Item(false, packet_correlation_id)[item_count]; 216 | } &byteorder=littleendian; 217 | 218 | ## ------------------------------------------Send-RR-Data------------------------------------------ 219 | ## Message Description: 220 | ## A SendRRData command shall transfer an encapsulated request/reply packet between the 221 | ## originator and target, where the originator initiates the command 222 | ## Message Format: 223 | ## - Interface Handle: uint32 -> Should be 0 for CIP packets 224 | ## - Timeout: uint16 -> Timout for when request expires 225 | ## - Item Count: uint16 -> Number of target items to follow 226 | ## - Target Items: CPF_Item[] -> See Common Packet Format Item 227 | ## Protocol Parsing: 228 | ## Continue with parsing of target items (see Common_Packet_Format_Item) 229 | ## ------------------------------------------------------------------------------------------------ 230 | type Send_RR_Data(is_orig: bool, packet_correlation_id: string) = record { 231 | interface_handle : uint32; 232 | timeout : uint16; 233 | item_count : uint16; 234 | encap_items : Common_Packet_Format_Item(is_orig, packet_correlation_id)[item_count]; 235 | } &byteorder=littleendian; 236 | 237 | ## -----------------------------------------Send-Unit-Data----------------------------------------- 238 | ## Message Description: 239 | ## The SendUnitData command shall send encapsulated connected messages. A reply shall not be 240 | ## returned. 241 | ## Message Format: 242 | ## - Interface Handle: uint32 -> Should be 0 for CIP packets 243 | ## - Timeout: uint16 -> Should be set to 0 (no reply) 244 | ## - Item Count: uint16 -> Number of target items to follow 245 | ## - Target Items: CPF_Item[] -> See Common Packet Format Item 246 | ## Protocol Parsing: 247 | ## Continue with parsing of target items (see Common_Packet_Format_Item) 248 | ## ------------------------------------------------------------------------------------------------ 249 | type Send_Unit_Data(is_orig: bool, packet_correlation_id: string) = record { 250 | interface_handle : uint32; 251 | timeout : uint16; 252 | item_count : uint16; 253 | encap_items : Common_Packet_Format_Item(is_orig, packet_correlation_id)[item_count]; 254 | } &byteorder=littleendian; 255 | 256 | ################################################################################################### 257 | ################################## END OF ETHERNET/IP COMMANDS ################################## 258 | ################################################################################################### 259 | 260 | 261 | ################################################################################################### 262 | ############################ ETHERNET/IP COMMAND PACKET FORMAT ITEMS ############################ 263 | ################################################################################################### 264 | 265 | ## -----------------------------------Common-Packet-Format-Item------------------------------------ 266 | ## Message Description: 267 | ## The common packet format (CPF) defines a standard format for protocol packets that are 268 | ## transported with the encapsulation protocol. 269 | ## Message Format: 270 | ## - Type ID: uint16 -> Type of item (see cpf_item_types) 271 | ## - Length: uint16 -> Length in bytes of the data field 272 | ## - Data: variable -> Data (if length > 0) 273 | ## Protocol Parsing: 274 | ## Continue with parsing of target items according to Type ID. 275 | ## ------------------------------------------------------------------------------------------------ 276 | type Common_Packet_Format_Item(is_orig: bool, packet_correlation_id: string) = record { 277 | item_type : uint16; 278 | item_length : uint16; 279 | item_data : case item_type of { 280 | NULL_ADDRESS -> null_address: empty; 281 | CIP_IDENTITY -> cip_identity_item: CIP_Identity_Item(is_orig, packet_correlation_id); 282 | CIP_SECURITY -> cip_security_item: CIP_Security_Item(is_orig); 283 | ENIP_CAPABILITY -> enip_capability: ENIP_Capability_Item(is_orig); 284 | CONNECTED_ADDRESS -> connected_address: Connected_Address_Item(is_orig); 285 | CONNECTED_TRANSPORT_DATA -> connected_transport_data: Connected_Data_Item(is_orig, item_length, packet_correlation_id); 286 | UNCONNECTED_MESSAGE_DATA -> unconnected_message_data: Unconnected_Data_Item(is_orig, item_length, packet_correlation_id); 287 | LIST_SERVICES_RESPONSE -> list_services_response: Service_Item(is_orig); 288 | SOCK_ADDR_DATA_ORIG_TO_TARGET -> sock_addr_data_orig_to_target: Socket_Address_Info_Item(is_orig); 289 | SOCK_ADDR_DATA_TARGET_TO_ORIG -> sock_addr_data_target_to_orig: Socket_Address_Info_Item(is_orig); 290 | SEQUENCED_ADDRESS_ITEM -> sequenced_address_item: Sequenced_Address_Item(is_orig); 291 | UNCONNECTED_MESSAGE_DTLS -> unconnected_message_dtls: Unconnected_Message_DTLS(is_orig, item_length, packet_correlation_id); 292 | default -> unknown: bytestring &restofdata; 293 | }; 294 | } &byteorder=littleendian; 295 | 296 | ## ---------------------------------------CIP-Identity-Item---------------------------------------- 297 | ## Message Description: 298 | ## The CIP Identity Item shall be the first item returned in a ListIdentity Response. This 299 | ## item describes data and functionality of CIP object/device. 300 | ## Message Format: 301 | ## - Encapsulation Version: uint16 -> Encapsulation Protocol Version supported 302 | ## - Socket Address Info: struct -> See Socket_Address_Info_Item 303 | ## - Vendor ID: uint16 -> Device manufacturer's Vendor ID 304 | ## - Device Type: uint16 -> Device type of product 305 | ## - Product Code: uint16 -> Product code assigned to device 306 | ## - Revision (Major): uint8 -> Device revision (major) 307 | ## - Revision (Minor): uint8 -> Device revision (minor) 308 | ## - Status: uint16 -> Current status of device 309 | ## - Serial Number: uint32 -> Serial number of device 310 | ## - Product Name Length: uint8 -> Length (in bytes) of Product Name 311 | ## - Product Name: string -> Human readable description of device 312 | ## - State: uint16 -> Current state of device 313 | ## Protocol Parsing: 314 | ## Sends all variables to the cip_identity event. By default this is then logged to the 315 | ## cip_identity.log file as defined in main.zeek. 316 | ## ------------------------------------------------------------------------------------------------ 317 | type CIP_Identity_Item(is_orig: bool, packet_correlation_id: string) = record { 318 | encapsulation_version : uint16; 319 | socket_address : Socket_Address_Info_Item(is_orig); 320 | vendor_id : uint16; 321 | device_type : uint16; 322 | product_code : uint16; 323 | revision_major : uint8; 324 | revision_minor : uint8; 325 | status : uint16; 326 | serial_number : uint32; 327 | product_name_length : uint8; 328 | product_name : bytestring &length=(product_name_length); 329 | state : uint8; 330 | } &let { 331 | is_originator : bool = is_orig; 332 | deliver: bool = $context.flow.process_cip_identity_item(this); 333 | } &byteorder=littleendian; 334 | 335 | ## ---------------------------------------CIP-Security-Item---------------------------------------- 336 | ## Message Description: 337 | ## The CIP Security Item shall be included in a ListIdentity Response for all CIP Security 338 | ## capable devices. It describes the security state and functionality of the device. 339 | ## Message Format: 340 | ## - Security Profiles: uint16 -> CIP Security Profiles supported 341 | ## - CIP Security State: uint8 -> Current state of CIP Security Object 342 | ## - ENIP Security State: uint8 -> Current state of ENIP Security Object 343 | ## - IANA Port State: int8 -> Current state for ENIP related ports 344 | ## + 1 (True) indicates port is open, 0 (False) indicates port is closed 345 | ## + Bit 0: 44818/tcp 346 | ## + Bit 1: 44818/udp 347 | ## + Bit 2: 2222/ucp 348 | ## + Bit 3: 2221/tcp 349 | ## + Bit 4: 2221/udp 350 | ## + Bit 5-7: Reserved 351 | ## Protocol Parsing: 352 | ## Sends all variables to the cip_security event. 353 | ## ------------------------------------------------------------------------------------------------ 354 | type CIP_Security_Item(is_orig: bool) = record { 355 | security_profile : uint16; 356 | cip_security_state : uint8; 357 | enip_security_state : uint8; 358 | iana_port_state : int8; 359 | } &let { 360 | is_originator : bool = is_orig; 361 | deliver: bool = $context.flow.process_cip_security_item(this); 362 | } &byteorder=littleendian; 363 | 364 | ## --------------------------------------ENIP-Capability-Item-------------------------------------- 365 | ## Message Description: 366 | ## The Ethernet/IP Capability Item can be included in a ListIdentity Response and is used to 367 | ## define Ethernet/IP transport capabilities for the various message types for a device. 368 | ## Message Format: 369 | ## - ENIP Profile: uint32 -> Features supported for ENIP transport 370 | ## Protocol Parsing: 371 | ## Sends enip_profile to the enip_capability event. 372 | ## ------------------------------------------------------------------------------------------------ 373 | type ENIP_Capability_Item(is_orig: bool) = record { 374 | enip_profile : uint32; 375 | } &let { 376 | is_originator : bool = is_orig; 377 | deliver: bool = $context.flow.process_enip_capability_item(this); 378 | } &byteorder=littleendian; 379 | 380 | ## ------------------------------------Socket-Address-Info-Item------------------------------------ 381 | ## Message Description: 382 | ## The Sockaddr Info items shall be used to communicate IP address or port information 383 | ## necessary to create Class 0 or Class 1 connections 384 | ## Message Format: 385 | ## - sin_family: int16 -> Shall be AF_INET = 2 386 | ## - sin_port: uint16 -> Socket Address Port Number 387 | ## - sin_addr: uint32 -> Socket Address IP address 388 | ## - sin_zero: uint8[8] -> Length of 8, should be set to all 0 389 | ## Protocol Parsing: 390 | ## Sends sin_addr and sin_port to the socket_address_info event 391 | ## ------------------------------------------------------------------------------------------------ 392 | type Socket_Address_Info_Item(is_orig: bool) = record { 393 | sin_family : int16; 394 | sin_port : uint16; 395 | sin_addr : uint32; 396 | sin_zero : uint8[8]; 397 | } &let { 398 | is_originator : bool = is_orig; 399 | deliver: bool = $context.flow.process_socket_address_info(this); 400 | } &byteorder=bigendian; 401 | 402 | ## ------------------------------------------Service-Item------------------------------------------ 403 | ## Message Description: 404 | ## Shows service classes the target device supports 405 | ## Message Format: 406 | ## - Protocol Version: uint16 -> Version of Protocol (currently 1) 407 | ## - Capability Flags: uint16 -> Capability Flags 408 | ## - Name of Service: uint8[16] -> Name of Service 409 | ## Protocol Parsing: 410 | ## Sends protocol_version, capability_flags, and service_name to enip_service event 411 | ## ------------------------------------------------------------------------------------------------ 412 | type Service_Item(is_orig: bool) = record { 413 | protocol_version : uint16; 414 | capability_flags : uint16; 415 | service_name : bytestring &length=16; 416 | } &let { 417 | is_originator : bool = is_orig; 418 | deliver: bool = $context.flow.process_service_item(this); 419 | } &byteorder=littleendian; 420 | 421 | ## -------------------------------------Connected-Address-Item------------------------------------- 422 | ## Message Description: 423 | ## This address item shall be used when the encapsulated protocol is connection-oriented. The 424 | ## data shall contain a connection identifier. 425 | ## Message Format: 426 | ## - Connection Identifier: uint32 -> Connection Identifier 427 | ## Protocol Parsing: 428 | ## Sends connection_identifier to the connected_address event 429 | ## ------------------------------------------------------------------------------------------------ 430 | type Connected_Address_Item(is_orig: bool) = record { 431 | connection_identifier : uint32; 432 | } &let { 433 | is_originator : bool = is_orig; 434 | deliver: bool = $context.flow.process_connected_address_item(this); 435 | } &byteorder=littleendian; 436 | 437 | ## -------------------------------------Sequenced-Address-Item------------------------------------- 438 | ## Message Description: 439 | ## This address item shall be used for CIP transport class 0 and class 1 connected data. The data 440 | ## shall contain a connection identifier and an Encapsulation Sequence Number. 441 | ## Message Format: 442 | ## - Connection Identifier: uint32 -> Connection Identifier 443 | ## - Encap Sequence Number: uint32 -> Encapsulation Sequence Number 444 | ## Protocol Parsing: 445 | ## Sends connection_identifier and encap_sequence_number to the sequenced_address event 446 | ## ------------------------------------------------------------------------------------------------ 447 | type Sequenced_Address_Item(is_orig: bool) = record { 448 | connection_identifier : uint32; 449 | encap_sequence_number : uint32; 450 | } &let { 451 | is_originator : bool = is_orig; 452 | deliver: bool = $context.flow.process_sequenced_address_item(this); 453 | } &byteorder=littleendian; 454 | 455 | ## -------------------------------------Unconnected-Data-Item-------------------------------------- 456 | ## Message Description: 457 | ## A data item that encapsulates an unconnected message 458 | ## Message Format: 459 | ## - Data: CIP_Header -> Unconnected Message (see CIP_Header) 460 | ## Protocol Parsing: 461 | ## Continue with parsing of CIP Data (see CIP_Header) 462 | ## ------------------------------------------------------------------------------------------------ 463 | type Unconnected_Data_Item(is_orig: bool, message_size: uint16, packet_correlation_id: string) = record { 464 | unconnected_message : CIP_Header(is_orig, 0, packet_correlation_id); 465 | } &byteorder=littleendian; 466 | 467 | ## --------------------------------------Connected-Data-Item--------------------------------------- 468 | ## Message Description: 469 | ## A data item that encapsulates a connected transport packet 470 | ## Message Format: 471 | ## - CIP Sequence Count: uint16 -> CIP sequence number for transport 472 | ## - Data: CIP_Header -> Transport Packet (see CIP_Header) 473 | ## Protocol Parsing: 474 | ## Continue with parsing of CIP Data (see CIP_Header) 475 | ## ------------------------------------------------------------------------------------------------ 476 | type Connected_Data_Item(is_orig: bool, message_size: uint16, packet_correlation_id: string) = record { 477 | cip_sequence_count : uint16; 478 | transport_packet : CIP_Header(is_orig, cip_sequence_count, packet_correlation_id); 479 | } &byteorder=littleendian; 480 | 481 | ## ------------------------------------Unconnected-Message-DTLS------------------------------------ 482 | ## Message Description: 483 | ## A data item that enapsulates an unconnected message via a DTLS session. 484 | ## Message Format: 485 | ## - Unconnected Message Type: uint16 -> Type of unconnected message 486 | ## - Transaction Number: uint32 -> Used for request/reply matching 487 | ## - Status: uint16 -> Status (see enip_status_codes) 488 | ## - Unconnected Message: CIP_Header -> Unconnected Message (see CIP_Header) 489 | ## Protocol Parsing: 490 | ## Sends unconn_message_type, transaction_number, and status to the unconnected_message_dtls 491 | ## event and then continues with parsing of CIP Data (see CIP_Header). 492 | ## ------------------------------------------------------------------------------------------------ 493 | type Unconnected_Message_DTLS(is_orig: bool, message_size: uint16, packet_correlation_id: string) = record { 494 | unconn_message_type : uint16; 495 | transaction_number : uint32; 496 | status : uint16; 497 | unconnected_message : CIP_Header(is_orig, 0, packet_correlation_id); 498 | } &let { 499 | is_originator : bool = is_orig; 500 | deliver: bool = $context.flow.process_unconnected_message_dtls(this); 501 | } &byteorder=littleendian; 502 | 503 | ################################################################################################### 504 | ######################## END OF ETHERNET/IP COMMAND PACKET FORMAT ITEMS ######################### 505 | ################################################################################################### 506 | 507 | 508 | ################################################################################################### 509 | ######################################### CIP COMMANDS ########################################## 510 | ################################################################################################### 511 | 512 | ## -------------------------------------------CIP-Header------------------------------------------- 513 | ## Message Description: 514 | ## CIP header for encapsulated CIP services within Ethernet/IP packets 515 | ## Message Format: 516 | ## - Service: uint8 -> CIP Service (see cip_common_services) 517 | ## - Request Path: Request_Path -> See Request_Path 518 | ## - Status Code: empty/CIP_Status -> See CIP_Status if response packet 519 | ## - Data: variable -> CIP service specific data 520 | ## Protocol Parsing: 521 | ## Sends CIP header information to the cip_header event and continues on with CIP service 522 | ## parsing. By default, CIP header info is logged to the cip.log file as defined in main.zeek. 523 | ## ------------------------------------------------------------------------------------------------ 524 | type CIP_Header(is_orig: bool, cip_sequence_count: uint16, packet_correlation_id: string) = record { 525 | service : uint8; 526 | request_path : Request_Path; 527 | status_code : case (service >> 7) of { 528 | 1 -> response_packet: CIP_Status; 529 | default -> request_packet: empty; 530 | }; 531 | data : case service of { 532 | GET_ATTRIBUTES_ALL -> get_attributes_all_request: empty; 533 | GET_ATTRIBUTES_ALL_RESPONSE -> get_attributes_all_response: Get_Attributes_All_Response(is_orig); 534 | GET_ATTRIBUTE_LIST -> get_attribute_list: Get_Attribute_List_Request(is_orig); 535 | GET_ATTRIBUTE_LIST_RESPONSE -> get_attribute_list_response: Get_Attribute_List_Response(is_orig); 536 | SET_ATTRIBUTE_LIST -> set_attribute_list: Set_Attribute_List_Request(is_orig); 537 | SET_ATTRIBUTE_LIST_RESPONSE -> set_attribute_list_response: Set_Attribute_List_Response(is_orig); 538 | MULTIPLE_SERVICE -> multiple_service_request: Multiple_Service_Packet_Request(is_orig, cip_sequence_count, request_path, packet_correlation_id); 539 | MULTIPLE_SERVICE_RESPONSE -> multiple_service_response: Multiple_Service_Packet_Response(is_orig, cip_sequence_count, response_packet.status, response_packet.status_extended, packet_correlation_id); 540 | GET_ATTRIBUTE_SINGLE_RESPONSE -> get_attribute_single_response: Get_Attribute_Single_Response(is_orig); 541 | SET_ATTRIBUTE_SINGLE -> set_attribute_single_request: Set_Attribute_Single_Request(is_orig); 542 | default -> other: bytestring &restofdata; 543 | }; 544 | } &let { 545 | is_originator : bool = is_orig; 546 | request_or_response : uint8 = (service >> 7); 547 | service_code : uint8 = (service & 0x7f); 548 | deliver: bool = $context.flow.process_cip_header(this); 549 | } &byteorder=littleendian; 550 | 551 | ## -------------------------------------------CIP-Status------------------------------------------- 552 | ## Message Description: 553 | ## Status Code sent in CIP response packets. 554 | ## Message Format: 555 | ## - Status: uint8 -> CIP status code 556 | ## - Status Extra: uint8 -> Size of extended status 557 | ## - Extended Status: variable -> CIP extended status code 558 | ## Protocol Parsing: 559 | ## Continues with parsing of CIP data 560 | ## ------------------------------------------------------------------------------------------------ 561 | type CIP_Status = record { 562 | status : uint8; 563 | status_extra : uint8; 564 | status_extended : bytestring &length = status_extra; 565 | } &byteorder=littleendian; 566 | 567 | ## ------------------------------------------Request-Path------------------------------------------ 568 | ## Message Description: 569 | ## CIP Request path transport information. Additional parsing of the request path is done in 570 | ## enip_analyzer.pac function parse_request_path. 571 | ## Message Format: 572 | ## - Request Path Size: uint8 -> Size of request path 573 | ## - Request Path: uint16[] -> Request Path Data 574 | ## Protocol Parsing: 575 | ## Continues with parsing of CIP data 576 | ## ------------------------------------------------------------------------------------------------ 577 | type Request_Path = record { 578 | request_path_size : uint8; 579 | request_path : bytestring &length=request_path_size*2; 580 | } &byteorder=littleendian; 581 | 582 | ## ----------------------------------Get-Attributes-All-Response----------------------------------- 583 | ## Message Description: 584 | ## Returns the contents of the instance or class attributes defined in the object definition. 585 | ## CIP Service Code 0x01 - Response Only (No Request Data) 586 | ## Message Format: 587 | ## - Attribute Data: variable -> Attribute data based on instance/class 588 | ## Protocol Parsing: 589 | ## Sends attribute_data to the get_attribute_all_response event. Cannot do further processing 590 | ## on attribute data because it is instance/class specific 591 | ## ------------------------------------------------------------------------------------------------ 592 | type Get_Attributes_All_Response(is_orig: bool) = record { 593 | attribute_data : bytestring &restofdata; 594 | } &let { 595 | is_originator: bool = is_orig; 596 | deliver: bool = $context.flow.process_get_attribute_all_response(this); 597 | } &byteorder=littleendian; 598 | 599 | ## -----------------------------------Set-Attributes-All-Request----------------------------------- 600 | ## Message Description: 601 | ## Modifies the contents of the instance or class attributes defined in the object definition. 602 | ## CIP Service Code 0x02 - Request Only (No Response Data) 603 | ## Message Format: 604 | ## - Attribute Data: variable -> Attribute data based on object/class 605 | ## Protocol Parsing: 606 | ## Sends attribute_data to the set_attribute_all_request event. Cannot do further processing 607 | ## on attribute data because it is instance/class specific 608 | ## ------------------------------------------------------------------------------------------------ 609 | type Set_Attributes_All_Request(is_orig: bool) = record { 610 | attribute_data : bytestring &restofdata; 611 | } &let { 612 | is_originator: bool = is_orig; 613 | deliver: bool = $context.flow.process_set_attribute_all_request(this); 614 | } &byteorder=littleendian; 615 | 616 | ## -----------------------------------Get-Attribute-List-Request----------------------------------- 617 | ## Message Description: 618 | ## The Get_Attribute_List service shall return the contents of the selected gettable 619 | ## attributes of the specified object class or instance 620 | ## CIP Service Code 0x03 - Request 621 | ## Message Format: 622 | ## - Attribute Count: uint16 -> Number of attribute IDs in list 623 | ## - Attribute List: uint16[] -> List of attribute IDs 624 | ## Protocol Parsing: 625 | ## Sends attribute_count and attribute_list to the get_attribute_list_request event. 626 | ## ------------------------------------------------------------------------------------------------ 627 | type Get_Attribute_List_Request(is_orig: bool) = record { 628 | attribute_count : uint16; 629 | attribute_list : uint16[attribute_count]; 630 | } &let { 631 | is_originator: bool = is_orig; 632 | deliver: bool = $context.flow.process_get_attribute_list_request(this); 633 | } &byteorder=littleendian; 634 | 635 | ## ----------------------------------Get-Attribute-List-Response----------------------------------- 636 | ## Message Description: 637 | ## The Get_Attribute_List service shall return the contents of the selected gettable 638 | ## attributes of the specified object class or instance 639 | ## CIP Service Code 0x03 - Response 640 | ## Message Format: 641 | ## - Attribute Count: uint16 -> Number of attribute structs 642 | ## - Attribute Data: variable[] -> Struct of attribute responses 643 | ## Protocol Parsing: 644 | ## Sends attribute_count and attribute_data to the get_attribute_list_response event. Cannot 645 | ## do further processing on attribute data because it is instance/class specific 646 | ## ------------------------------------------------------------------------------------------------ 647 | type Get_Attribute_List_Response(is_orig: bool) = record { 648 | attribute_count : uint16; 649 | attribute_data : bytestring &restofdata; 650 | } &let { 651 | is_originator: bool = is_orig; 652 | deliver: bool = $context.flow.process_get_attribute_list_response(this); 653 | } &byteorder=littleendian; 654 | 655 | ## -----------------------------------Set-Attribute-List-Request----------------------------------- 656 | ## Message Description: 657 | ## The Set_Attribute_List service shall set the contents of selected attributes of the 658 | ## specified object class or instance. 659 | ## CIP Service Code 0x04 - Request 660 | ## Message Format: 661 | ## - Attribute Count: uint16 -> Number of attribute structs 662 | ## - Attribute Data: variable[] -> Struct of attribute responses 663 | ## Protocol Parsing: 664 | ## Sends attribute_count and attribute_data to the set_attribute_list_request event. Cannot 665 | ## do further processing on attribute data because it is instance/class specific 666 | ## ------------------------------------------------------------------------------------------------ 667 | type Set_Attribute_List_Request(is_orig: bool) = record { 668 | attribute_count : uint16; 669 | attribute_data : bytestring &restofdata; 670 | } &let { 671 | is_originator: bool = is_orig; 672 | deliver: bool = $context.flow.process_set_attribute_list_request(this); 673 | } &byteorder=littleendian; 674 | 675 | ## ----------------------------------Set-Attribute-List-Response----------------------------------- 676 | ## Message Description: 677 | ## The Set_Attribute_List service shall set the contents of selected attributes of the 678 | ## specified object class or instance. 679 | ## CIP Service Code 0x04 - Response 680 | ## Message Format: 681 | ## - Attribute Count: uint16 -> Number of attribute structs 682 | ## - Attribute Data: variable[] -> Struct of attribute responses 683 | ## Protocol Parsing: 684 | ## Sends attribute_count and attribute_data to the set_attribute_list_response event. Cannot 685 | ## do further processing on attribute data because it is instance/class specific 686 | ## ------------------------------------------------------------------------------------------------ 687 | type Set_Attribute_List_Response(is_orig: bool) = record { 688 | attribute_count : uint16; 689 | attribute_data : bytestring &restofdata; 690 | } &let { 691 | is_originator: bool = is_orig; 692 | deliver: bool = $context.flow.process_set_attribute_list_response(this); 693 | } &byteorder=littleendian; 694 | 695 | ## --------------------------------Multiple-Service-Packet-Request--------------------------------- 696 | ## Message Description: 697 | ## Performs a set of services as an autonomous sequence. 698 | ## CIP Service Code 0x0A - Request 699 | ## Message Format: 700 | ## - Service Count: uint16 -> Number of services 701 | ## - Service Offsets: uint16[] -> List of service offsets 702 | ## - Services: variable -> Services 703 | ## Protocol Parsing: 704 | ## Sends message data to the multiple_service_request event. 705 | ## ------------------------------------------------------------------------------------------------ 706 | type Multiple_Service_Packet_Request(is_orig: bool, cip_sequence_count: uint16, request_path: Request_Path, packet_correlation_id: string) = record { 707 | service_count : uint16; 708 | service_offsets : uint16[service_count]; 709 | services : bytestring &restofdata; 710 | } &let { 711 | is_originator: bool = is_orig; 712 | deliver: bool = $context.flow.process_multiple_service_request(this); 713 | } &byteorder=littleendian; 714 | 715 | ## --------------------------------Multiple-Service-Packet-Response-------------------------------- 716 | ## Message Description: 717 | ## Performs a set of services as an autonomous sequence. 718 | ## CIP Service Code 0x0A - Response 719 | ## Message Format: 720 | ## - Service Count: uint16 -> Number of services 721 | ## - Service Offsets: uint16[] -> List of service offsets 722 | ## - Services: variable -> Services 723 | ## Protocol Parsing: 724 | ## Sends message data to the multiple_service_response event. 725 | ## TODO: edit this function description with updates 726 | ## ------------------------------------------------------------------------------------------------ 727 | type Multiple_Service_Packet_Response(is_orig: bool, cip_sequence_count: uint16, status: uint8, status_extended: bytestring, packet_correlation_id: string) = record { 728 | service_count : uint16; 729 | service_offsets : uint16[service_count]; 730 | services : bytestring &restofdata; 731 | } &let { 732 | is_originator: bool = is_orig; 733 | deliver: bool = $context.flow.process_multiple_service_response(this); 734 | } &byteorder=littleendian; 735 | 736 | ## ---------------------------------Get-Attribute-Single-Response---------------------------------- 737 | ## Message Description: 738 | ## Returns the contents of the specified attribute or other logical elements 739 | ## CIP Service Code 0x0E - Response only (No Request Data) 740 | ## Message Format: 741 | ## - Attribute Data: variable -> Struct of attribute response 742 | ## Protocol Parsing: 743 | ## Sends attribute_data to the get_attribute_single_response event. Cannot do further 744 | ## processing on attribute data because it is instance/class specific 745 | ## ------------------------------------------------------------------------------------------------ 746 | type Get_Attribute_Single_Response(is_orig: bool) = record { 747 | attribute_data : bytestring &restofdata; 748 | } &let { 749 | is_originator: bool = is_orig; 750 | deliver: bool = $context.flow.process_get_attribute_single_response(this); 751 | } &byteorder=littleendian; 752 | 753 | ## ----------------------------------Set-Attribute-Single-Request---------------------------------- 754 | ## Message Description: 755 | ## Modifies an attribute value. 756 | ## CIP Service Code 0x10 - Request only (No Response Data) 757 | ## Message Format: 758 | ## - Attribute ID: uint8 -> Identifies the attribute 759 | ## - Attribute Data: variable -> Value of modified attribute 760 | ## Protocol Parsing: 761 | ## Sends attribute_id and attribute_data to the set_attribute_single_response event. Cannot 762 | ## do further processing on attribute data because it is instance/class specific 763 | ## ------------------------------------------------------------------------------------------------ 764 | type Set_Attribute_Single_Request(is_orig: bool) = record { 765 | attribute_id : uint8; 766 | attribute_data : bytestring &restofdata; 767 | } &let { 768 | is_originator: bool = is_orig; 769 | deliver: bool = $context.flow.process_set_attribute_single_request(this); 770 | } &byteorder=littleendian; 771 | 772 | ################################################################################################### 773 | ###################################### END OF CIP COMMANDS ###################################### 774 | ################################################################################################### 775 | -------------------------------------------------------------------------------- /src/enip-utilities.pac: -------------------------------------------------------------------------------- 1 | ## enip-utilities.pac 2 | ## 3 | ## ENIP/CIP Protocol Analyzer 4 | ## 5 | ## Analyzer utilitiy functions. 6 | ## 7 | ## Author: Melanie Pierce 8 | ## Contact: melanie.pierce@inl.gov 9 | ## 10 | ## Copyright (c) 2024 Battelle Energy Alliance, LLC. All rights reserved. 11 | 12 | 13 | %extern{ 14 | /* 15 | Note: 16 | The binpac compiler generates one header file along with the associated source file so there 17 | isn't a need to bring in additional headers here. We'll just track header files in the 18 | enip-analyzer.pac binpac file. 19 | */ 20 | %} 21 | 22 | %header{ 23 | #define ID_LEN 9 24 | string generateId(); 25 | %} 26 | 27 | %code{ 28 | 29 | // 30 | // Utility function used to generate unique id associated with the ENIP logs. While 31 | // this id is NOT part of the ENIP/CIP documented spec, we use it to tie nested log files 32 | // together - e.g. any nested log files such as the status code detail log will contain 33 | // this id which can be used to reference back to the primary ENIP/CIP log file. 34 | // 35 | // The implemenation was taken from: https://lowrey.me/guid-generation-in-c-11/ 36 | // 37 | std::string generateId() { 38 | std::stringstream ss; 39 | for (auto i = 0; i < ID_LEN; i++) { 40 | // Generate a random char 41 | std::random_device rd; 42 | std::mt19937 gen(rd()); 43 | std::uniform_int_distribution<> dis(0, 255); 44 | const auto rc = dis(gen); 45 | 46 | // Hex representaton of random char 47 | std::stringstream hexstream; 48 | hexstream << std::hex << rc; 49 | auto hex = hexstream.str(); 50 | ss << (hex.length() < 2 ? '0' + hex : hex); 51 | } 52 | return ss.str(); 53 | } 54 | %} 55 | 56 | refine flow ENIP_Flow += { 57 | function generate_packet_id(): string 58 | %{ 59 | return(generateId()); 60 | %} 61 | } 62 | -------------------------------------------------------------------------------- /src/enip.pac: -------------------------------------------------------------------------------- 1 | %include zeek/binpac.pac 2 | %include zeek/zeek.pac 3 | 4 | %extern{ 5 | #include "events.bif.h" 6 | %} 7 | 8 | analyzer ENIP withcontext { 9 | connection: ENIP_Conn; 10 | flow: ENIP_Flow; 11 | }; 12 | 13 | connection ENIP_Conn(zeek_analyzer: ZeekAnalyzer) { 14 | upflow = ENIP_Flow(true); 15 | downflow = ENIP_Flow(false); 16 | }; 17 | 18 | %include enip-protocol.pac 19 | 20 | flow ENIP_Flow(is_orig: bool) { 21 | datagram = ENIP_PDU(is_orig) withcontext(connection, this); 22 | } 23 | 24 | %include enip-utilities.pac 25 | %include enip-analyzer.pac -------------------------------------------------------------------------------- /src/events.bif: -------------------------------------------------------------------------------- 1 | ## events.bif 2 | ## 3 | ## Binpac Ethernet/IP (ENIP) Analyzer - Defines events the analyzer will generate 4 | ## 5 | ## Author: Stephen Kleinheider 6 | ## Contact: stephen.kleinheider@inl.gov 7 | ## 8 | ## Copyright (c) 2023 Battelle Energy Alliance, LLC. All rights reserved. 9 | 10 | ################################################################################################### 11 | ####################################### LOGGED BY DEFAULT ####################################### 12 | ################################################################################################### 13 | 14 | ## ------------------------------------------enip-header------------------------------------------- 15 | ## Event Description: 16 | ## Event is generated for all Ethernet/IP packets and contains relevant ENIP header data 17 | ## Event Data: 18 | ## - c: connection -> Zeek Connection Struct 19 | ## - command: count -> Ethernet/IP Command (see enip_commands in consts.zeek) 20 | ## - length: count -> Length of ENIP data following header 21 | ## - session_handle: count -> Session Identifier (session handle) 22 | ## - status: count -> Status Code (see enip_statuses in consts.zeek) 23 | ## - sender_context string -> Sender Context (used to match request and responses) 24 | ## - options: count -> Options flags 25 | ## Default Output: 26 | ## Writes to log file enip.log 27 | ## ------------------------------------------------------------------------------------------------ 28 | event enip_header%(c: connection, 29 | is_orig: bool, 30 | packet_correlation_id: string, 31 | command: count, 32 | length: count, 33 | session_handle: count, 34 | status: count, 35 | sender_context: string, 36 | options: count%); 37 | 38 | ## -------------------------------------------cip-header------------------------------------------- 39 | ## Event Description: 40 | ## Event is generated for all CIP packets and contains relevant CIP header data 41 | ## Event Data: 42 | ## - c: connection -> Zeek Connection Struct 43 | ## - cip_sequence_count: count -> CIP sequence number for transport (connected data only) 44 | ## - service: count -> CIP Service Type (see cip_services in consts.zeek) 45 | ## - response: bool -> Request or Response boolean 46 | ## - status: count -> CIP Status Code (see cip_statuses in consts.zeek) 47 | ## - status_extended: count -> CIP Status Code (see cip_extended_statuses in consts.zeek) 48 | ## - class_id count -> CIP Request Path - Class ID 49 | ## - instance_id count -> CIP Request Path - Instance ID 50 | ## - attribute_id count -> CIP Request Path - Attribute ID 51 | ## Default Output: 52 | ## Writes to log file cip.log 53 | ## ------------------------------------------------------------------------------------------------ 54 | event cip_header%(c: connection, 55 | is_orig: bool, 56 | packet_correlation_id: string, 57 | cip_sequence_count: count, 58 | service: count, 59 | response: bool, 60 | status: count, 61 | status_extended: count, 62 | class_id: count, 63 | instance_id: count, 64 | attribute_id: count%); 65 | 66 | ## ------------------------------------------cip-identity------------------------------------------ 67 | ## Event Description: 68 | ## Event is generated for packets that include a CIP_Identity in a ListServices response 69 | ## Event Data: 70 | ## - c: connection -> Zeek Connection Struct 71 | ## - encapsulation_version:count -> Encapsulation Protocol Version supported 72 | ## - socket_address: count -> Socket Address IP Address 73 | ## - socket_port: count -> Socket Address Port 74 | ## - vendor_id: count -> Vendor ID (see cip_vendors in consts.zeek) 75 | ## - device_type: count -> Device type (see cip_device_types in consts.zeek) 76 | ## - product_code: count -> Product code assigned to device 77 | ## - revision_major: count -> Device revision (major) 78 | ## - revision_minor: count -> Device revision (minor) 79 | ## - status: count -> Current status of device (see cip_statuses in consts.zeek) 80 | ## - serial_number: count -> Serial number of device 81 | ## - product_name: string -> Human readable description of device 82 | ## - state: count -> Current state of the device 83 | ## Default Output: 84 | ## Writes to log file cip_identity.log 85 | ## ------------------------------------------------------------------------------------------------ 86 | event cip_identity%(c: connection, 87 | is_orig: bool, 88 | packet_correlation_id: string, 89 | encapsulation_version: count, 90 | socket_address: count, 91 | socket_port: count, 92 | vendor_id: count, 93 | device_type: count, 94 | product_code: count, 95 | revision_major: count, 96 | revision_minor: count, 97 | status: count, 98 | serial_number: count, 99 | product_name: string, 100 | state: count%); 101 | 102 | ## ---------------------------------------------cip-io--------------------------------------------- 103 | ## Event Description: 104 | ## Event is generated for all CIP IO packets 105 | ## Event Data: 106 | ## - c: connection -> Zeek Connection Struct 107 | ## - connection_identifier:count -> Connection Identifier 108 | ## - sequence_number: count -> Sequence Number within Connection 109 | ## - data_length: count -> Length of data field 110 | ## - data: count -> CIP IO data 111 | ## Default Output: 112 | ## Writes to log file cip_io.log 113 | ## ------------------------------------------------------------------------------------------------ 114 | event cip_io%(c: connection, 115 | is_orig: bool, 116 | packet_correlation_id: string, 117 | connection_identifier: count, 118 | sequence_number: count, 119 | data_length: count, 120 | data: string%); 121 | 122 | ################################################################################################### 123 | ################################### END OF LOGGED BY DEFAULT #################################### 124 | ################################################################################################### 125 | 126 | 127 | ################################################################################################### 128 | ##################################### NOT LOGGED BY DEFAULT ##################################### 129 | ################################################################################################### 130 | 131 | ## ----------------------------------------register-session---------------------------------------- 132 | ## Event Description: 133 | ## Event is generated for ENIP register_session commands 134 | ## Event Data: 135 | ## - c: connection -> Zeek Connection Struct 136 | ## - protocol_version: count -> Version of Protocol (currently 1) 137 | ## - options_flags: count -> Options Flag (no public options defined) 138 | ## Default Output: 139 | ## No defined log in main.zeek by default 140 | ## ------------------------------------------------------------------------------------------------ 141 | event register_session%(c: connection, 142 | is_orig: bool, 143 | protocol_version: count, 144 | options_flags: count%); 145 | 146 | ## ------------------------------------------cip-security------------------------------------------ 147 | ## Event Description: 148 | ## Event is generated for packets that include a CIP_Security_Item in a ListServices response 149 | ## Event Data: 150 | ## - c: connection -> Zeek Connection Struct 151 | ## - security_profile: count -> CIP Security Profiles supported 152 | ## - cip_security_state: count -> Current state of CIP Security Object 153 | ## - enip_security_state: count -> Current state of ENIP Security Object 154 | ## - iana_port_state: count -> Current state for ENIP related ports 155 | ## Default Output: 156 | ## No defined log in main.zeek by default 157 | ## ------------------------------------------------------------------------------------------------ 158 | event cip_security%(c: connection, 159 | is_orig: bool, 160 | security_profile: count, 161 | cip_security_state: count, 162 | enip_security_state: count, 163 | iana_port_state: count%); 164 | 165 | ## ----------------------------------------enip-capability----------------------------------------- 166 | ## Event Description: 167 | ## Event is generated for packets that include a ENIP_Capability_Item in a ListServices response 168 | ## Event Data: 169 | ## - c: connection -> Zeek Connection Struct 170 | ## - enip_profile: count -> Features supported for ENIP transport 171 | ## Default Output: 172 | ## No defined log in main.zeek by default 173 | ## ------------------------------------------------------------------------------------------------ 174 | event enip_capability%(c: connection, 175 | is_orig: bool, 176 | enip_profile: count%); 177 | 178 | ## ------------------------------------------enip-service------------------------------------------ 179 | ## Event Description: 180 | ## Event is generated for packets that include a Service_Item in a ListServices response 181 | ## Event Data: 182 | ## - c: connection -> Zeek Connection Struct 183 | ## - protocol_version: count -> Version of Protocol (currently 1) 184 | ## - capability_flags: count -> Capability Flags 185 | ## - service_name: string -> Name of Service 186 | ## Default Output: 187 | ## No defined log in main.zeek by default 188 | ## ------------------------------------------------------------------------------------------------ 189 | event enip_service%(c: connection, 190 | is_orig: bool, 191 | protocol_version: count, 192 | capability_flags: count, 193 | service_name: string%); 194 | 195 | ## ---------------------------------------connected-address---------------------------------------- 196 | ## Event Description: 197 | ## Event is generated for packets that include a Connected_Address_Item 198 | ## Event Data: 199 | ## - c: connection -> Zeek Connection Struct 200 | ## - connection_id: count -> Connection Identifier 201 | ## Default Output: 202 | ## No defined log in main.zeek by default 203 | ## ------------------------------------------------------------------------------------------------ 204 | event connected_address%(c: connection, 205 | is_orig: bool, 206 | connection_id: count%); 207 | 208 | ## ---------------------------------------sequenced-address---------------------------------------- 209 | ## Event Description: 210 | ## Event is generated for packets that include a Sequenced_Address_Item 211 | ## Event Data: 212 | ## - c: connection -> Zeek Connection Struct 213 | ## - connection_id: count -> Connection Identifier 214 | ## - encap_sequence_num: count -> Encapsulation Sequence Number 215 | ## Default Output: 216 | ## No defined log in main.zeek by default 217 | ## ------------------------------------------------------------------------------------------------ 218 | event sequenced_address%(c: connection, 219 | is_orig: bool, 220 | connection_id: count, 221 | encap_sequence_num: count%); 222 | 223 | ## ------------------------------------unconnected-message-dtls------------------------------------ 224 | ## Event Description: 225 | ## Event is generated for packets that include a Unconnected_Message_DTLS 226 | ## Event Data: 227 | ## - c: connection -> Zeek Connection Struct 228 | ## - unconn_message_type: count -> Type of unconnected message 229 | ## - transaction_number: count -> Transaction number for for request/reply matching 230 | ## - status: count -> Status (see enip_statuses in consts.zeek) 231 | ## Default Output: 232 | ## No defined log in main.zeek by default 233 | ## ------------------------------------------------------------------------------------------------ 234 | event unconnected_message_dtls%(c: connection, 235 | is_orig: bool, 236 | unconn_message_type: count, 237 | transaction_number: count, 238 | status: count%); 239 | 240 | ## --------------------------------------socket-address-info--------------------------------------- 241 | ## Event Description: 242 | ## Event is generated for packets that include a Socket_Address_Info_Item 243 | ## Event Data: 244 | ## - c: connection -> Zeek Connection Struct 245 | ## - socket_address: count -> Socket Address IP address 246 | ## - socket_port: count -> Socket Address Port Number 247 | ## Default Output: 248 | ## No defined log in main.zeek by default 249 | ## ------------------------------------------------------------------------------------------------ 250 | event socket_address_info%(c: connection, 251 | is_orig: bool, 252 | socket_address: count, 253 | socket_port: count%); 254 | 255 | ## -----------------------------------get-attribute-all-response----------------------------------- 256 | ## Event Description: 257 | ## Event is generated for CIP service Get_Attributes_All_Response 258 | ## Event Data: 259 | ## - c: connection -> Zeek Connection Struct 260 | ## - attribute_data: string -> Attribute data based on instance/class 261 | ## Default Output: 262 | ## No defined log in main.zeek by default 263 | ## ------------------------------------------------------------------------------------------------ 264 | event get_attribute_all_response%(c: connection, 265 | is_orig: bool, 266 | attribute_data: string%); 267 | 268 | ## -----------------------------------set-attribute-all-request------------------------------------ 269 | ## Event Description: 270 | ## Event is generated for CIP service Set_Attributes_All_Request 271 | ## Event Data: 272 | ## - c: connection -> Zeek Connection Struct 273 | ## - attribute_data: string -> Attribute data based on instance/class 274 | ## Default Output: 275 | ## No defined log in main.zeek by default 276 | ## ------------------------------------------------------------------------------------------------ 277 | event set_attribute_all_request%(c: connection, 278 | is_orig: bool, 279 | attribute_data: string%); 280 | 281 | ## -----------------------------------get-attribute-list-request----------------------------------- 282 | ## Event Description: 283 | ## Event is generated for CIP service Get_Attribute_List_Request 284 | ## Event Data: 285 | ## - c: connection -> Zeek Connection Struct 286 | ## - attribute_count: count -> Number of attribute IDs in list 287 | ## - attributes: string -> List of attribute IDs 288 | ## Default Output: 289 | ## No defined log in main.zeek by default 290 | ## ------------------------------------------------------------------------------------------------ 291 | event get_attribute_list_request%(c: connection, 292 | is_orig: bool, 293 | attribute_count: count, 294 | attributes: string%); 295 | 296 | ## ----------------------------------get-attribute-list-response----------------------------------- 297 | ## Event Description: 298 | ## Event is generated for CIP service Get_Attribute_List_Response 299 | ## Event Data: 300 | ## - c: connection -> Zeek Connection Struct 301 | ## - attribute_count: count -> Number of attribute structs 302 | ## - attributes: string -> Struct of attribute responses 303 | ## Default Output: 304 | ## No defined log in main.zeek by default 305 | ## ------------------------------------------------------------------------------------------------ 306 | event get_attribute_list_response%(c: connection, 307 | is_orig: bool, 308 | attribute_count: count, 309 | attributes: string%); 310 | 311 | ## -----------------------------------set-attribute-list-request----------------------------------- 312 | ## Event Description: 313 | ## Event is generated for CIP service Set_Attribute_List_Request 314 | ## Event Data: 315 | ## - c: connection -> Zeek Connection Struct 316 | ## - attribute_count: count -> Number of attribute structs 317 | ## - attributes: string -> Struct of attribute responses 318 | ## Default Output: 319 | ## No defined log in main.zeek by default 320 | ## ------------------------------------------------------------------------------------------------ 321 | event set_attribute_list_request%(c: connection, 322 | is_orig: bool, 323 | attribute_count: count, 324 | attributes: string%); 325 | 326 | ## ----------------------------------set-attribute-list-response----------------------------------- 327 | ## Event Description: 328 | ## Event is generated for CIP service Set_Attribute_List_Response 329 | ## Event Data: 330 | ## - c: connection -> Zeek Connection Struct 331 | ## - attribute_count: count -> Number of attribute structs 332 | ## - attributes: string -> Struct of attribute responses 333 | ## Default Output: 334 | ## No defined log in main.zeek by default 335 | ## ------------------------------------------------------------------------------------------------ 336 | event set_attribute_list_response%(c: connection, 337 | is_orig: bool, 338 | attribute_count: count, 339 | attributes: string%); 340 | 341 | ## ------------------------------------multiple-service-request------------------------------------ 342 | ## Event Description: 343 | ## Event is generated for CIP service Multiple_Service_Packet_Request 344 | ## Event Data: 345 | ## - c: connection -> Zeek Connection Struct 346 | ## - service_count: count -> Number of services included in command 347 | ## - services: string -> Comma delimited list of services included 348 | ## Default Output: 349 | ## No defined log in main.zeek by default 350 | ## ------------------------------------------------------------------------------------------------ 351 | event multiple_service_request%(c: connection, 352 | is_orig: bool, 353 | service_count: count, 354 | services: string%); 355 | 356 | ## -----------------------------------multiple-service-response------------------------------------ 357 | ## Event Description: 358 | ## Event is generated for CIP service Multiple_Service_Packet_Response 359 | ## Event Data: 360 | ## - c: connection -> Zeek Connection Struct 361 | ## - service_count: count -> Number of services included in command 362 | ## - services: string -> Comma delimited list of services included 363 | ## Default Output: 364 | ## No defined log in main.zeek by default 365 | ## ------------------------------------------------------------------------------------------------ 366 | event multiple_service_response%(c: connection, 367 | is_orig: bool, 368 | service_count: count, 369 | services: string%); 370 | 371 | ## ---------------------------------get-attribute-single-response---------------------------------- 372 | ## Event Description: 373 | ## Event is generated for CIP service Get_Attribute_Single_Response 374 | ## Event Data: 375 | ## - c: connection -> Zeek Connection Struct 376 | ## - attribute_value: string -> Attribute data based on instance/class 377 | ## Default Output: 378 | ## No defined log in main.zeek by default 379 | ## ------------------------------------------------------------------------------------------------ 380 | event get_attribute_single_response%(c: connection, 381 | is_orig: bool, 382 | attribute_value: string%); 383 | 384 | ## ----------------------------------set-attribute-single-request---------------------------------- 385 | ## Event Description: 386 | ## Event is generated for CIP service Set_Attribute_Single_Request 387 | ## Event Data: 388 | ## - c: connection -> Zeek Connection Struct 389 | ## - attribute_id: count -> Identifies the attribute 390 | ## - attribute_value: string -> Attribute data based on instance/class 391 | ## Default Output: 392 | ## No defined log in main.zeek by default 393 | ## ------------------------------------------------------------------------------------------------ 394 | event set_attribute_single_request%(c: connection, 395 | is_orig: bool, 396 | attribute_id: count, 397 | attribute_value: string%); 398 | 399 | ################################################################################################### 400 | ################################# END OF NOT LOGGED BY DEFAULT ################################## 401 | ################################################################################################### 402 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | .tmp 2 | .btest.failed.dat 3 | -------------------------------------------------------------------------------- /tests/analyzer/availability.zeek: -------------------------------------------------------------------------------- 1 | # @TEST-EXEC: zeek -NN | grep -i -q ANALYZER_ENIP 2 | # 3 | # @TEST-DOC: Check that ENIP analyzer is available. 4 | -------------------------------------------------------------------------------- /tests/analyzer/basic.zeek: -------------------------------------------------------------------------------- 1 | # @TEST-EXEC: zeek -C -r ${TRACES}/enip_cip_example.pcap %INPUT 2 | # @TEST-EXEC: zeek-cut -n packet_correlation_id < cip.log > cip.tmp && mv cip.tmp cip.log 3 | # @TEST-EXEC: zeek-cut -n packet_correlation_id < cip_identity.log > cip_identity.tmp && mv cip_identity.tmp cip_identity.log 4 | # @TEST-EXEC: zeek-cut -n packet_correlation_id < cip_io.log > cip_io.tmp && mv cip_io.tmp cip_io.log 5 | # @TEST-EXEC: zeek-cut -n packet_correlation_id < enip.log > enip.tmp && mv enip.tmp enip.log 6 | # @TEST-EXEC: btest-diff cip.log 7 | # @TEST-EXEC: btest-diff cip_identity.log 8 | # @TEST-EXEC: btest-diff cip_io.log 9 | # @TEST-EXEC: btest-diff enip.log 10 | # 11 | # @TEST-DOC: Test ENIP analyzer with small trace. 12 | 13 | @load icsnpp/enip 14 | -------------------------------------------------------------------------------- /tests/baseline/analyzer.basic/cip_identity.log: -------------------------------------------------------------------------------- 1 | ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. 2 | XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 10.1.1.167 5262 10.1.1.164 44818 F 10.1.1.164 44818 10.1.1.167 5262 1 10.1.1.164 44818 1 Rockwell Automation/Allen-Bradley 12 Communications Adapter 58 4.3 0x0030 0x00524d8e 1756-ENBT/A 0x0003 3 | -------------------------------------------------------------------------------- /tests/baseline/analyzer.basic/conn.log: -------------------------------------------------------------------------------- 1 | ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. 2 | #separator \x09 3 | #set_separator , 4 | #empty_field (empty) 5 | #unset_field - 6 | #path conn 7 | #open XXXX-XX-XX-XX-XX-XX 8 | #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig local_resp missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents 9 | #types time string addr port addr port enum string interval count count string bool bool count string count count count count set[string] 10 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 tcp enip 20.296440 13826 18040 OTH T T 0 ADad 176 20866 175 25040 - 11 | XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 10.1.1.167 5262 10.1.1.164 44818 tcp enip 0.128716 24 75 RSTR T T 0 ShADdFar 4 196 4 243 - 12 | XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 10.1.1.167 37997 10.1.1.164 44818 tcp - 5.543195 0 0 S1 T T 0 Sh 1 44 2 88 - 13 | XXXXXXXXXX.XXXXXX CtPZjS20MLrsMUOJi2 192.168.1.24 2222 192.168.1.22 2222 udp cip 0.002723 11374 600 SF T T 0 Dd 368 21678 30 1440 - 14 | #close XXXX-XX-XX-XX-XX-XX 15 | -------------------------------------------------------------------------------- /tests/baseline/analyzer.basic/enip.log: -------------------------------------------------------------------------------- 1 | ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. 2 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 3 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 4 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 5 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 6 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 7 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 8 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 9 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 10 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 11 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 12 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 13 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 14 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 15 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 16 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 17 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 18 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 19 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 20 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 21 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 22 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 23 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 24 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 25 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 26 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 27 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 28 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 29 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 30 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 31 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 32 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 33 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 34 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 35 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 36 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 37 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 38 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 39 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 40 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 41 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 42 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 43 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 44 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 45 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 46 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 47 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 48 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 49 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 50 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 51 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 52 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 53 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 54 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 55 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 56 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 57 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 58 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 59 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 60 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 61 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 62 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 63 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 64 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 65 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 66 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 67 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 68 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 69 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 70 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 71 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 72 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 73 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 74 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 75 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 76 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 77 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 78 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 79 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 80 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 81 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 82 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 83 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 84 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 85 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 86 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 87 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 88 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 89 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 90 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 91 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 92 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 93 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 94 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 95 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 96 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 97 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 98 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 99 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 100 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 40 0x11020100 Success 0x0000000000000000 0x00000000 101 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 102 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 103 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 104 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 105 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 106 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 107 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 108 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 109 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 110 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 111 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 112 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 113 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 114 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 115 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 116 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 117 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 118 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 119 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 120 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 121 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 122 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 123 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 124 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 125 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 126 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 127 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 128 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 129 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 130 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 131 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 132 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 133 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 134 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 135 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 136 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 137 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 138 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 139 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 140 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 141 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 142 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 143 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 144 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 145 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 146 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 147 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 148 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 149 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 150 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 151 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 152 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 153 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 154 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 155 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 156 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 157 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 158 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 159 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 160 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 161 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 162 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 163 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 164 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 165 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 166 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 167 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 168 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 169 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 170 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 171 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 172 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 173 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 174 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 175 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 176 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 177 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 178 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 179 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 180 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 181 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 182 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 183 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 184 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 185 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 186 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 187 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 188 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 189 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 190 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 191 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 192 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 193 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 194 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 195 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 196 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 197 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 198 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 199 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 200 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 201 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 202 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 203 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 204 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 205 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 206 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 207 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 208 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 209 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 210 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 211 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 212 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 213 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 214 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 215 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 216 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 217 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 218 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 219 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 220 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 221 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 222 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 223 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 224 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 225 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 226 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 227 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 228 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 229 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 230 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 231 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 232 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 233 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 234 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 235 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 236 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 237 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 238 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 239 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 240 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 241 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 242 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 243 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 244 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 245 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 246 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 247 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 248 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 249 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 250 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 251 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 252 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 253 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 254 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 255 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 256 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 257 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 258 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 259 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 269 0x11020100 Success 0x0000000000000000 0x00000000 260 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 261 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 72 0x11020100 Success 0x0000000000000000 0x00000000 262 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 263 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 34 0x11020100 Success 0x0000000000000000 0x00000000 264 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 265 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 33 0x11020100 Success 0x0000000000000000 0x00000000 266 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 32 0x11020100 Success 0x0000000000000000 0x00000000 267 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 F 192.168.10.120 44818 192.168.10.105 3033 0x70 Send Unit Data 36 0x11020100 Success 0x0000000000000000 0x00000000 268 | XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.10.105 3033 192.168.10.120 44818 T 192.168.10.105 3033 192.168.10.120 44818 0x70 Send Unit Data 186 0x11020100 Success 0x0000000000000000 0x00000000 269 | XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 10.1.1.167 5262 10.1.1.164 44818 T 10.1.1.167 5262 10.1.1.164 44818 0x63 List Identity 0 0x00000000 Success 0x00000000c1debed1 0x00000000 270 | XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 10.1.1.167 5262 10.1.1.164 44818 F 10.1.1.164 44818 10.1.1.167 5262 0x63 List Identity 51 0x00000000 Success 0x00000000c1debed1 0x00000000 271 | -------------------------------------------------------------------------------- /tests/btest.cfg: -------------------------------------------------------------------------------- 1 | [btest] 2 | TestDirs = analyzer 3 | TmpDir = %(testbase)s/.tmp 4 | BaselineDir = %(testbase)s/baseline 5 | IgnoreDirs = .tmp 6 | IgnoreFiles = *.tmp *.swp #* *.trace .DS_Store 7 | 8 | [environment] 9 | ZEEKPATH=`%(testbase)s/scripts/get-zeek-env zeekpath` 10 | ZEEK_PLUGIN_PATH=`%(testbase)s/scripts/get-zeek-env zeek_plugin_path` 11 | ZEEK_SEED_FILE=%(testbase)s/files/random.seed 12 | PATH=`%(testbase)s/scripts/get-zeek-env path` 13 | PACKAGE=%(testbase)s/../scripts 14 | TZ=UTC 15 | LC_ALL=C 16 | TRACES=%(testbase)s/traces 17 | TMPDIR=%(testbase)s/.tmp 18 | TEST_DIFF_CANONIFIER=%(testbase)s/scripts/diff-remove-timestamps 19 | -------------------------------------------------------------------------------- /tests/files/random.seed: -------------------------------------------------------------------------------- 1 | 2983378351 2 | 1299727368 3 | 0 4 | 310447 5 | 0 6 | 1409073626 7 | 3975311262 8 | 34130240 9 | 1450515018 10 | 1466150520 11 | 1342286698 12 | 1193956778 13 | 2188527278 14 | 3361989254 15 | 3912865238 16 | 3596260151 17 | 517973768 18 | 1462428821 19 | 0 20 | 2278350848 21 | 32767 22 | -------------------------------------------------------------------------------- /tests/scripts/diff-remove-timestamps: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | # 3 | # Replace anything which looks like timestamps with XXXs (including the #start/end markers in logs). 4 | 5 | # Get us "modern" regexps with sed. 6 | if [ `uname` == "Linux" ]; then 7 | sed="sed -r" 8 | else 9 | sed="sed -E" 10 | fi 11 | 12 | $sed 's/(0\.000000)|([0-9]{9,10}\.[0-9]{2,8})/XXXXXXXXXX.XXXXXX/g' | \ 13 | $sed 's/^ *#(open|close).(19|20)..-..-..-..-..-..$/#\1 XXXX-XX-XX-XX-XX-XX/g' 14 | -------------------------------------------------------------------------------- /tests/scripts/get-zeek-env: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # BTest helper for getting values for Zeek-related environment variables. 4 | 5 | base=$(dirname $0) 6 | zeek_dist=$(cat ${base}/../../build/CMakeCache.txt 2>/dev/null | grep ZEEK_DIST | cut -d = -f 2) 7 | 8 | if [ -n "${zeek_dist}" ]; then 9 | if [ "$1" = "zeekpath" ]; then 10 | ${zeek_dist}/build/zeek-path-dev 11 | elif [ "$1" = "zeek_plugin_path" ]; then 12 | ( cd ${base}/../.. && pwd ) 13 | elif [ "$1" = "path" ]; then 14 | echo ${zeek_dist}/build/src:${zeek_dist}/aux/btest:${base}/:${zeek_dist}/aux/zeek-cut:$PATH 15 | else 16 | echo "usage: $(basename $0) " >&2 17 | exit 1 18 | fi 19 | else 20 | # Use Zeek installation for testing. In this case zeek-config must be in PATH. 21 | if ! which zeek-config >/dev/null 2>&1; then 22 | echo "zeek-config not found" >&2 23 | exit 1 24 | fi 25 | 26 | if [ "$1" = "zeekpath" ]; then 27 | zeek-config --zeekpath 28 | elif [ "$1" = "zeek_plugin_path" ]; then 29 | # Combine the local tree and the system-wide path. This allows 30 | # us to test on a local build or an installation made via zkg, 31 | # which squirrels away the build. --cpk 32 | echo "$(cd ${base}/../.. && pwd):$(zeek-config --plugin_dir)" 33 | elif [ "$1" = "path" ]; then 34 | echo ${PATH} 35 | else 36 | echo "usage: $(basename $0) " >&2 37 | exit 1 38 | fi 39 | fi 40 | -------------------------------------------------------------------------------- /tests/traces/enip_cip_example.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cisagov/icsnpp-enip/6a62de96fb10ead765edf838f17a8a41c1342988/tests/traces/enip_cip_example.pcap -------------------------------------------------------------------------------- /zkg.meta: -------------------------------------------------------------------------------- 1 | [package] 2 | build_dir = build/ICSNPP_Enip.tgz 3 | script_dir = build/scripts/icsnpp/enip 4 | build_command = ./configure && make 5 | test_command = cd tests && btest -c btest.cfg 6 | description = Ethernet/IP and CIP plugin for parsing and logging of the Ethernet/IP and CIP protocols - CISA ICSNPP 7 | credits = Stephen Kleinheider 8 | tags = enip, ENIP, cip, CIP, ics, ICS, CISA, INL, ICSNPP, icsnpp, zeek plugin, log writer, protocol analyzer 9 | depends = 10 | zkg >=2.0 11 | zeek >=4.0.0 --------------------------------------------------------------------------------