├── DhaeyerWolf
├── AMS.zip
├── DNP3.zip
├── NTP.zip
├── BACNet.zip
├── OPCUA.zip
├── S7Comm.zip
├── ModbusTCP.zip
├── Profinet.zip
├── CIP (Ethernet-IP).zip
├── DNS - @DhaeyerWolf.zip
├── SMB - @DhaeyerWolf.zip
├── plugins
│ └── lua
│ │ ├── CiscoNexus_dissector.lua
│ │ ├── README.md
│ │ ├── UMAS_dissector.lua
│ │ ├── siemens_ruggedcom(RCDP)_dissector.lua
│ │ └── melsoft_dissector.lua
├── notes
│ ├── opcua.md
│ ├── modbus.md
│ ├── dnp3.md
│ ├── EthernetIP(CIP).md
│ └── IEC104.md
└── LICENSE
├── .gitmodules
└── README.md
/DhaeyerWolf/AMS.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DhaeyerWolf/ICS-OT_wireshark_profiles/HEAD/DhaeyerWolf/AMS.zip
--------------------------------------------------------------------------------
/DhaeyerWolf/DNP3.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DhaeyerWolf/ICS-OT_wireshark_profiles/HEAD/DhaeyerWolf/DNP3.zip
--------------------------------------------------------------------------------
/DhaeyerWolf/NTP.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DhaeyerWolf/ICS-OT_wireshark_profiles/HEAD/DhaeyerWolf/NTP.zip
--------------------------------------------------------------------------------
/DhaeyerWolf/BACNet.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DhaeyerWolf/ICS-OT_wireshark_profiles/HEAD/DhaeyerWolf/BACNet.zip
--------------------------------------------------------------------------------
/DhaeyerWolf/OPCUA.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DhaeyerWolf/ICS-OT_wireshark_profiles/HEAD/DhaeyerWolf/OPCUA.zip
--------------------------------------------------------------------------------
/DhaeyerWolf/S7Comm.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DhaeyerWolf/ICS-OT_wireshark_profiles/HEAD/DhaeyerWolf/S7Comm.zip
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "amwalding"]
2 | path = amwalding
3 | url = https://github.com/amwalding/wireshark_profiles
4 |
--------------------------------------------------------------------------------
/DhaeyerWolf/ModbusTCP.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DhaeyerWolf/ICS-OT_wireshark_profiles/HEAD/DhaeyerWolf/ModbusTCP.zip
--------------------------------------------------------------------------------
/DhaeyerWolf/Profinet.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DhaeyerWolf/ICS-OT_wireshark_profiles/HEAD/DhaeyerWolf/Profinet.zip
--------------------------------------------------------------------------------
/DhaeyerWolf/CIP (Ethernet-IP).zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DhaeyerWolf/ICS-OT_wireshark_profiles/HEAD/DhaeyerWolf/CIP (Ethernet-IP).zip
--------------------------------------------------------------------------------
/DhaeyerWolf/DNS - @DhaeyerWolf.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DhaeyerWolf/ICS-OT_wireshark_profiles/HEAD/DhaeyerWolf/DNS - @DhaeyerWolf.zip
--------------------------------------------------------------------------------
/DhaeyerWolf/SMB - @DhaeyerWolf.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DhaeyerWolf/ICS-OT_wireshark_profiles/HEAD/DhaeyerWolf/SMB - @DhaeyerWolf.zip
--------------------------------------------------------------------------------
/DhaeyerWolf/plugins/lua/CiscoNexus_dissector.lua:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------------
2 | --
3 | -- Cisco Nexus Protocol Plug-in for Wireshark
4 | --
5 | -- date : April, 16th 2019
6 | -- author : Younes Dragoni (@ydragoni)
7 | -- contact : secresearch [ @ ] nozominetworks [ . ] com
8 | --
9 | --------------------------------------------------------------------------
10 |
11 | -- initialize wrapper fields
12 | cisco_nexus = Proto ("CiscoNexus_vlan","Cisco Nexus")
13 |
14 | -- load 802.1Q Virtual LAN dissector
15 | original_vlan_dissector = DissectorTable.get("ethertype"):get_dissector(0x8100)
16 |
17 | -- wrapper main function
18 | function cisco_nexus.dissector (buf, pkt, root)
19 | -- validate packet length is adequate, otherwise quit
20 | if buf:len() == 0 then return end
21 | pkt.cols.protocol = cisco_nexus.name
22 |
23 | -- create subtree for Cisco Nexus
24 | subtree = root:add(cisco_nexus, buf(4))
25 |
26 | -- subscribes ECAT dissector
27 | original_vlan_dissector:call(buf:range(4,buf:len()-4):tvb(), pkt, subtree)
28 |
29 | end
30 |
31 | -- Initialization routine
32 | function cisco_nexus.init()
33 | end
34 |
35 | -- subscribe for Ethernet packets on type 0x8905.
36 | local eth_table = DissectorTable.get("ethertype")
37 | eth_table:add(0x8905, cisco_nexus)
--------------------------------------------------------------------------------
/DhaeyerWolf/notes/opcua.md:
--------------------------------------------------------------------------------
1 | # OPCUA
2 | ## NodeId Identifier Numeric:
3 | #### Session Services
4 | ##### CreateSession
5 | - Request: opcua.servicenodeid.numeric == 461
6 | - Response: opcua.servicenodeid.numeric == 464
7 |
8 | ##### ActivateSession
9 | - Request: opcua.servicenodeid.numeric == 467
10 | - Response: opcua.servicenodeid.numeric == 470
11 |
12 | ##### CloseSecureChannel
13 | - Request: opcua.servicenodeid.numeric == 452
14 |
15 | ### Secure Channel Services
16 | ##### OpenSecureChannel
17 | - Request: opcua.servicenodeid.numeric == 446
18 | - Response: opcua.servicenodeid.numeric == 449
19 |
20 | ### Node Management Services
21 | ##### Browse
22 | - Request: opcua.servicenodeid.numeric == 527
23 | - Response: opcua.servicenodeid.numeric == 530
24 |
25 | ##### BrowseNext
26 | - Request: opcua.servicenodeid.numeric == 533
27 | - Response: opcua.servicenodeid.numeric == 536
28 |
29 | ### Attribute Services
30 | ##### Read
31 | - Request: opcua.servicenodeid.numeric == 631
32 | - Response: opcua.servicenodeid.numeric == 634
33 |
34 | ##### Write
35 | - Request: opcua.servicenodeid.numeric == 673
36 | - Response: opcua.servicenodeid.numeric == 676
37 |
38 | ### Subscription Services
39 | ##### Publish
40 | - Request: opcua.servicenodeid.numeric == 826
41 | - Response: opcua.servicenodeid.numeric == 829
42 |
43 | ### Discovery Services
44 | ##### GetEndpoints
45 | - Request: opcua.servicenodeid.numeric == 428
46 | - Response: opcua.servicenodeid.numeric == 431
47 |
48 |
49 | ## MSG types
50 | - OPN - OpenSecureChannel message
51 | - MSG - UA Secure Conversation Message
52 | - HEL - Hello message
53 | - ACK - Acknowledge message
54 | - CLO - CloseSecureChannel message
55 |
56 | **Typical flow of a conversation:**
57 | - Client HEL -> # hello message
58 | - Server ACK <- # Acknowledge hello message
59 | - Client OPN -> # request security poicy (?)
60 | - Server OPN <- # confirms request
61 | - Client MSG -> # requests opc.tcp server (uri)
62 | - Server MSG <- # replies with information
63 | - MSG repeat
--------------------------------------------------------------------------------
/DhaeyerWolf/plugins/lua/README.md:
--------------------------------------------------------------------------------
1 | #
2 | # Plugins folder
3 | There it is possible that there is a "plugins" folder in some of the repositories. This contains plugins (e.g. additional dissectors) for wireshark. The files in this folder should be placed in the wireshark plugins folder
4 |
5 | On Windows:
6 | - For Wireshark portable: `[Install location]/App/Wireshark/plugins`. (for easy use you can just put the whole plugins folder in the `/App/Wireshark/` folder, it will automatically merge the plugins folder.
7 | - The personal plugin folder is %APPDATA%\Wireshark\plugins. (source: https://www.wireshark.org/docs/wsug_html_chunked/ChPluginFolders.html)
8 | - The global plugin folder is WIRESHARK\plugins. (source: https://www.wireshark.org/docs/wsug_html_chunked/ChPluginFolders.html)
9 |
10 | On Unix-like systems:
11 | - The personal plugin folder is ~/.local/lib/wireshark/plugins. (source: https://www.wireshark.org/docs/wsug_html_chunked/ChPluginFolders.html)
12 | If you are running on macOS and Wireshark is installed as an application bundle, the global plugin folder is %APPDIR%/Contents/PlugIns/wireshark, otherwise it’s INSTALLDIR/lib/wireshark/plugins. (source: https://www.wireshark.org/docs/wsug_html_chunked/ChPluginFolders.html)
13 |
14 | An example of this folder structure can be:
15 | ```
16 | plugins
17 | └── lua
18 | └── script1.lua
19 | ```
20 |
21 | # Plugins
22 | - `UMAS_dissector.lua`: Please be aware that this may break the normal Modbus traffic you see in wireshark to disable this you can either remove it from the plugins folder or rename the file to `UMAS_dissector.lua.off` (renaming the file is the recommended way). Credits: Erwan Cordier
23 | - `melsoft_dissector.lua`: A dissector to handle the traffic of the "Mitsubishi Electric MELSOFT" protocol used to communicate with Safety PLCs. Credits: Nozomi Networks - Andrea Palanca, Ivan Speziale
24 | - `CiscoNexus_dissector.lua`: Cisco Nexus Protocol Plug-in for Wireshark. Credits: Nozomi Networks - Younes Dragoni (@ydragoni)
25 | - `siemens_ruggedcom(RCDP)_dissector.lua`: Siemens Ruggedcom (RCDP) Protocol Plug-in for Wireshark. Credits: Nozomi Networks - Luca Cremona (linkedin: luca--cremona)
26 |
27 | # Credits
28 | - @DhaeyerWolf
29 | - https://github.com/biero-el-corridor/Wireshark-UMAS-Modicon-M340-protocol/blob/main/modbus-umas-schneider.lua
30 | - https://github.com/NozomiNetworks/blackhat23-melsoft
31 | - https://github.com/NozomiNetworks/dissectors
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NOTICE
2 | THIS IS A FORK OF THE WONDERFUL REPOSITORY: https://github.com/amwalding/wireshark_profiles and other Open-Source profiles. However, it does not contain ICS/OT-specific Wireshark profiles, which I create when the need arises for me. The reason for the fork is to organize it easily for myself.
3 |
4 | # Wireshark Profiles Repository
5 | Check out this video on the power of Wireshark Profiles:
6 | https://youtu.be/tSzgcEB9f54
7 |
8 | # Structure of the Repository
9 | Every contributor has a main folder; in this folder, the profiles are listed as .ZIP files (this makes it easy to download if you only want one specific profile).
10 |
11 | Example:
12 | ```
13 | root
14 | ├── DhaeyerWolf
15 | │ └── Profile1.zip
16 | │ └── Profile2.zip
17 | │ └── Profile3.zip
18 | │ └── Profile4.zip
19 | └── amwalding
20 | └── Profile1.zip
21 | └── Profile2.zip
22 | └── Profile3.zip
23 | └── Profile4.zip
24 | ```
25 |
26 | # Downloading the Repository
27 | To ensure that submodule folders are included when downloading this repository, avoid using the "Download Zip" feature from GitHub, as it will result in empty submodule folders. Similarly, a standard "git clone" will not include these submodules. Instead, use the following command:
28 |
29 | ```bash
30 | git clone --recurse-submodules https://github.com/DhaeyerWolf/ICS-OT_wireshark_profiles.git
31 | ```
32 |
33 | # How to Use the Profiles
34 | 1. Simply download the profile you want (they are all zipped).
35 | 2. Then, from your Wireshark GUI, right-click in the lower-right corner of the Wireshark GUI - in the Profile box.
36 | 3. Then, simply select: Import> from zip file, and pick the file from your downloads' directory. Now you can select the newly imported profile!!
37 |
38 | # Plugins folder
39 | There may be a “plugins” folder in some repositories. This contains plugins (e.g. additional dissectors) for Wireshark. The files in this folder should be placed in the Wireshark plugins folder
40 |
41 | On Windows:
42 | - For Wireshark portable: `[Install location]/App/Wireshark/plugins`. (for easy use you can just put the whole plugins folder in the `/App/Wireshark/` folder, it will automatically merge the plugins folder.
43 | - The personal plugin folder is %APPDATA%\Wireshark\plugins. (source: https://www.wireshark.org/docs/wsug_html_chunked/ChPluginFolders.html)
44 | - The global plugin folder is WIRESHARK\plugins. (source: https://www.wireshark.org/docs/wsug_html_chunked/ChPluginFolders.html)
45 |
46 | On Unix-like systems:
47 | - The personal plugin folder is ~/.local/lib/wireshark/plugins. (source: https://www.wireshark.org/docs/wsug_html_chunked/ChPluginFolders.html)
48 | If you are running on macOS and Wireshark is installed as an application bundle, the global plugin folder is %APPDIR%/Contents/PlugIns/wireshark, otherwise it’s INSTALLDIR/lib/wireshark/plugins. (source: https://www.wireshark.org/docs/wsug_html_chunked/ChPluginFolders.html)
49 |
50 | An example of this folder structure can be:
51 | ```
52 | plugins
53 | └── lua
54 | └── script1.lua
55 | ```
56 |
57 | # Contribute
58 | Create a pull request with a ZIP file containing your profile. If possible, create a profile specific to the protocol; if not possible, please clearly state the use case of the profile in the name of the profile's name.
59 |
60 | # Credits
61 | - https://github.com/amwalding/wireshark_profiles
62 | - https://www.cellstream.com/wireshark-profiles-repository/
63 | - @DhaeyerWolf
64 | - https://github.com/biero-el-corridor/Wireshark-UMAS-Modicon-M340-protocol/blob/main/modbus-umas-schneider.lua
65 |
66 | # Protocols
67 | The following is a list of the protocols I want to create Wireshark profiles for. Some of them may already be implemented; others are still in a "Work In Progress (WIP)" phase.
68 | - [x] S7Comm
69 | - [x] Profinet
70 | - [x] Modbus TCP/UDP
71 | - [x] OPC-UA
72 | - [x] BACnet
73 | - [x] Ethernet/IP: Common Industrial Protocol (CIP™)
74 | - [x] DNP3
75 | - [ ] MQTT
76 | - [ ] IEC 104
--------------------------------------------------------------------------------
/DhaeyerWolf/notes/modbus.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | # UMAS
5 | ## Protocol dissection
6 |
7 | ### Overview
8 | The basic and normal structure of the protocol. Depending on the UMAS function code the data part can be split up even more.
9 | ```
10 | [Modbus Data + Modbus code 90] | [1 byte - UMAS session/pairing key] | [1 byte - UMAS Function code] | [? bytes - Data]
11 | ```
12 | From here on out, the modbus data is not displayed as the UMAS protocol is applied after the modbus data & modbus code 90.
13 |
14 | ### PLC Program Upload (0x31)
15 | ```
16 | [1 byte - UMAS session/pairing key] | [1 byte - UMAS Function code] | [2 bytes - 00 01 / 00 10] | [2 bytes - block ID - little Endian] | [2 bytes - block length - little Endian] | [? bytes - Data]
17 | ```
18 | - the 3rd part of the protocol, is supposed to always be `00 01`, test however have showed that this can also be `00 10`. It is yet unclear what this means
19 | - The data should be the length fo the defined date in the previous part of the protocol. Everything more than this should be dropped (This has not been verified).
20 |
21 | **Other Notes**
22 | - although it is yet unkown what exactly gets uploaded, it may be a `.stu` file or a `.apx` file.
23 | - observation shows that the filepath to a `.stu` file is send in one packet (the 4th packet)
24 |
25 | Online unofficial documentation discribes the following:
26 | ```
27 | The upload (computer to PLC) process is quite tricky. The first blocks sent to the PLC must have a specific length:
28 |
29 | Block 1 → 64 bytes (with the first 64 bytes of the APX file)
30 | Block 2 → 264 bytes (with bytes 65 to 328 of the APX file)
31 | Block 3 → 64 bytes (with bytes 329 to 373 of the APX file)
32 | Block 4 → 1014 bytes (if possible)
33 | Block 5 → 998 bytes (if possible)
34 | Block 6 → 1008 bytes (if possible)
35 | Block 7 → 1014 bytes (if possible)
36 |
37 | After the 7th block, all blocks are 1022 bytes long (if possible, it depends on negotiation performed during connection. Have a look to sections I and VI for more information). In blocks 4 to 7, if the max packet size is lower than 998, they will be sent with the max packet size.
38 | ```
39 | This is not the same as what I have observed; all my packets were 1012 bytes execpt for the last one (presumably because of the data cutoff)
40 |
41 |
42 | ## Function codes
43 | | Enabled | Protocol | Filter | Description |
44 | |---------|----------|--------|-------------|
45 | | TRUE | Schneider//Program//INIT_COMM | modbus.data[1:2] contains 01 | Initialize a UMAS communication |
46 | | TRUE | Schneider//Program//READ_ID | modbus.data[1:2] contains 02 | Request a PLC ID |
47 | | TRUE | Schneider//Program//READ_PROJECT_INFO | modbus.data[1:2] contains 03 | Read Project Information |
48 | | TRUE | Schneider//Program//READ_PLC_INFO | modbus.data[1:2] contains 04 | Get internal PLC Info |
49 | | TRUE | Schneider//Program//READ_CARD_INFO | modbus.data[1:2] contains 06 | Get internal PLC SD-Card Info |
50 | | TRUE | Schneider//Program//REPEAT | modbus.data[1:2] contains 0A | Sends back data sent to the PLC (used for synchronization) |
51 | | TRUE | Schneider//Program//TAKE_PLC_RESERVATION | modbus.data[1:2] contains 10 | Assign an 'owner' to the PLC |
52 | | TRUE | Schneider//Program//RELEASE_PLC_RESERVATION | modbus.data[1:2] contains 11 | Release the reservation of a PLC |
53 | | TRUE | Schneider//Program//KEEP_ALIVE | modbus.data[1:2] contains 12 | Keep alive message |
54 | | TRUE | Schneider//Program//READ_MEMORY_BLOCK | modbus.data[1:2] contains 20 | Read a memory block of the PLC |
55 | | TRUE | Schneider//Program//READ_VARIABLES | modbus.data[1:2] contains 22 | Read System bits, System Words and Strategy variables |
56 | | TRUE | Schneider//Program//WRITE_VARIABLES | modbus.data[1:2] contains 23 | Write System bits, System Words and Strategy variables |
57 | | TRUE | Schneider//Program//READ_COILS_REGISTERS | modbus.data[1:2] contains 24 | Read coils and holding registers from PLC |
58 | | TRUE | Schneider//Program//WRITE_COILS_REGISTERS | modbus.data[1:2] contains 25 | Write coils and holding registers into PLC |
59 | | TRUE | Schneider//Program//INITIALIZE_UPLOAD | modbus.data[1:2] contains 30 | Initialize Strategy upload (copy from engineering PC to PLC) |
60 | | TRUE | Schneider//Program//UPLOAD_BLOCK | modbus.data[1:2] contains 31 | Upload (copy from engineering PC to PLC) a strategy block to the PLC |
61 | | TRUE | Schneider//Program//END_STRATEGY_UPLOAD | modbus.data[1:2] contains 32 | Finish strategy Upload (copy from engineering PC to PLC) |
62 | | TRUE | Schneider//Program//INITIALIZE_UPLOAD | modbus.data[1:2] contains 33 | Initialize Strategy download (copy from PLC to engineering PC) |
63 | | TRUE | Schneider//Program//DOWNLOAD_BLOCK | modbus.data[1:2] contains 34 | Download (copy from PLC to engineering PC) a strategy block |
64 | | TRUE | Schneider//Program//END_STRATEGY_DOWNLOAD | modbus.data[1:2] contains 35 | Finish strategy Download (copy from PLC to engineering PC) |
65 | | TRUE | Schneider//Program//READ_ETH_MASTER_DATA | modbus.data[1:2] contains 39 | Read Ethernet Master Data |
66 | | TRUE | Schneider//Program//START_PLC | modbus.data[1:2] contains 40 | Starts the PLC |
67 | | TRUE | Schneider//Program//STOP_PLC | modbus.data[1:2] contains 41 | Stops the PLC |
68 | | TRUE | Schneider//Program//MONITOR_PLC | modbus.data[1:2] contains 50 | Monitors variables, Systems bits and words |
69 | | TRUE | Schneider//Program//CHECK_PLC | modbus.data[1:2] contains 58 | Check PLC Connection status |
70 | | TRUE | Schneider//Program//READ_IO_OBJECT | modbus.data[1:2] contains 70 | Read IO Object |
71 | | TRUE | Schneider//Program//WRITE_IO_OBJECT | modbus.data[1:2] contains 71 | Write IO Object |
72 | | TRUE | Schneider//Program//GET_STATUS_MODULE | modbus.data[1:2] contains 73 | Get Status Module |
73 |
74 |
75 | # sources
76 | ## UMAS protocol
77 | - https://lirasenlared.blogspot.com/2017/08/the-unity-umas-protocol-part-i.html
78 | - https://lirasenlared.blogspot.com/2017/08/the-unity-umas-protocol-part-ii.html
79 | - https://lirasenlared.blogspot.com/2017/08/the-unity-umas-protocol-part-iii.html
80 | - https://lirasenlared.blogspot.com/2017/08/the-unity-umas-protocol-part-iv.html
81 |
--------------------------------------------------------------------------------
/DhaeyerWolf/plugins/lua/UMAS_dissector.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | lua wireshark addon for the UMAS embeded modbus protocol
3 | made by biero-el-corridor
4 | --]]
5 |
6 | -- functions that made the concordance of the umas_code -> funtions meaning
7 | function get_umas_function_name(code)
8 | local code_name = "Unknow"
9 | -- source: http://lirasenlared.blogspot.com/2017/08/the-unity-umas-protocol-part-i.html
10 | if code == 1 then code_name = "0x01 - INIT_COMM: Initialize a UMAS communication"
11 | elseif code == 2 then code_name = "0x02 - READ_ID: Request a PLC ID"
12 | elseif code == 3 then code_name = "0x03 - READ_PROJECT_INFO: Read Project Information"
13 | elseif code == 4 then code_name = "0x04 - READ_PLC_INFO: Get internal PLC Info"
14 | elseif code == 6 then code_name = "0x06 - READ_CARD_INFO: Get internal PLC SD-Card Info"
15 | elseif code == 10 then code_name = "0x0A - REPEAT: Sends back data sent to the PLC (used for synchronization)"
16 | elseif code == 16 then code_name = "0x10 - TAKE_PLC_RESERVATION: Assign an owner to the PLC"
17 | elseif code == 17 then code_name = "0x11 - RELEASE_PLC_RESERVATION: Release the reservation of a PLC"
18 | elseif code == 18 then code_name = "0x12 - KEEP_ALIVE: Keep alive message (???)"
19 | elseif code == 32 then code_name = "0x20 - READ_MEMORY_BLOCK: Read a memory block of the PLC"
20 | elseif code == 34 then code_name = "0x22 - READ_VARIABLES: Read System bits, System Words and Strategy variables"
21 | elseif code == 35 then code_name = "0x23 - WRITE_VARIABLES: Write System bits, System Words and Strategy variables"
22 | elseif code == 36 then code_name = "0x24 - READ_COILS_REGISTERS: Read coils and holding registers from PLC"
23 | elseif code == 37 then code_name = "0x25 - WRITE_COILS_REGISTERS: Write coils and holding registers into PLC"
24 | elseif code == 48 then code_name = "0x30 - INITIALIZE_UPLOAD: Initialize Strategy upload (copy from engineering PC to PLC)"
25 | elseif code == 49 then code_name = "0x31 - UPLOAD_BLOCK: Upload (copy from engineering PC to PLC) a strategy block to the PLC"
26 | elseif code == 50 then code_name = "0x32 - END_STRATEGY_UPLOAD: Finish strategy Upload (copy from engineering PC to PLC)"
27 | elseif code == 51 then code_name = "0x33 - INITIALIZE_UPLOAD: Initialize Strategy download (copy from PLC to engineering PC)"
28 | elseif code == 52 then code_name = "0x34 - DOWNLOAD_BLOCK: Download (copy from PLC to engineering PC) a strategy block"
29 | elseif code == 53 then code_name = "0x35 - END_STRATEGY_DOWNLOAD: Finish strategy Download (copy from PLC to engineering PC)"
30 | elseif code == 57 then code_name = "0x39 - READ_ETH_MASTER_DATA: Read Ethernet Master Data"
31 | elseif code == 58 then code_name = "0x40 - START_PLC: Starts the PLC"
32 | elseif code == 59 then code_name = "0x41 - STOP_PLC: Stops the PLC"
33 | elseif code == 80 then code_name = "0x50 - MONITOR_PLC: Monitors variables, Systems bits and words"
34 | elseif code == 88 then code_name = "0x58 - CHECK_PLC: Check PLC Connection status"
35 | elseif code == 112 then code_name = "0x70 - READ_IO_OBJECT: Read IO Object"
36 | elseif code == 113 then code_name = "0x71 - WRITE_IO_OBJECT: WriteIO Object"
37 | elseif code == 115 then code_name = "0x73 - GET_STATUS_MODULE: Get Status Module"
38 | elseif code == 254 then code_name = "0xfe - Response Meaning OK"
39 | elseif code == 253 then code_name = "0xfd - Response Meaning Error" end
40 | return code_name
41 | end
42 |
43 | modbus1_protocol = Proto("Modbus1", "Modbus .")
44 | umas_protocol = Proto("UMAS", "UMAS .")
45 |
46 | -- ressourc that worth your time https://www.wireshark.org/docs/wsdg_html_chunked/lua_module_Proto.html
47 | ----------- part of the modbus protocol ---------------
48 | Transaction_Identifier = ProtoField.uint16("Modbus1.Transaction_Identifier" , "Transaction_Identifier" , base.DEC)
49 | Protocol_Identifier = ProtoField.uint16("Modbus1.Protocol_Identifier" , "Protocol_Identifier" , base.DEC)
50 | Length = ProtoField.uint16("Modbus1.Length" , "Length" , base.DEC)
51 | Unit_Identifier = ProtoField.int8("Modbus1.Unit_Identifier" , "Unit_Identifier" , base.DEC)
52 | modbus1_protocol.fields = { Transaction_Identifier, Protocol_Identifier, Length, Unit_Identifier }
53 | -------------------------------------------------------
54 |
55 | ----------- part of the UMAS protocol -----------------
56 | Function_Code = ProtoField.uint8("UMAS.Function_Code" , "Function_Code" , base.HEX_DEC)
57 | Pairing_Key = ProtoField.uint8("UMAS.Pairing_Key" , "Pairing_Key" , base.HEX)
58 | Umas_Functions_Code = ProtoField.uint8("UMAS.Umas_Functions_Code" , "Umas_Functions_Code" , base.DEC)
59 | Umas_Data = ProtoField.string("UMAS.Umas_Data" , "Umas_Data" , base.ASCII )
60 | umas_protocol.fields = { Function_Code, Pairing_Key, Functions_Code , Umas_Functions_Code ,Umas_Data }
61 | -------------------------------------------------------
62 |
63 | function modbus1_protocol.dissector(buffer,pinfo,tree)
64 | -- get the size of the packet sections
65 | length = buffer:len()
66 |
67 | ------------------------------------------
68 | -- BEGIN OF THE MODBUS SECTIONS ----------
69 | ------------------------------------------
70 |
71 | -- if the sections is empty , terminate the process
72 | if length == 0 then return end
73 |
74 | -- apply the name in the column if the protocol is detected
75 | pinfo.cols.protocol = modbus1_protocol.name
76 |
77 | -- add the layer umas in the list of potential layer
78 | local subtree = tree:add(modbus1_protocol, buffer() , "Modbus Protocol Data")
79 | local modbusSubtree = subtree:add(modbus1_protocol, buffer() ,"modbus header")
80 |
81 | modbusSubtree:add(Transaction_Identifier ,buffer(0,2))
82 | modbusSubtree:add(Protocol_Identifier ,buffer(2,2))
83 | modbusSubtree:add(Length ,buffer(4,2))
84 | modbusSubtree:add(Unit_Identifier ,buffer(6,1))
85 | ------------------------------------------
86 | -- END OF THE MODBUS SECTIONS ------------
87 | ------------------------------------------
88 |
89 | ------------------------------------------
90 | -- BEGIN OF THE UMAS SECTIONS ------------
91 | ------------------------------------------
92 |
93 | local umas_identifier = buffer(7,1):le_uint()
94 | local umas_code = buffer(9,1):le_uint()
95 | local umas_code_name = get_umas_function_name(umas_code)
96 |
97 | local getData = buffer(10)
98 | local data = getData:le_ustring()
99 |
100 | if(umas_identifier == 90)
101 | then
102 | local data_length = length - 10
103 | local umasSubtree = subtree:add(modbus1_protocol ,buffer() ,"umas")
104 | umasSubtree:add(Function_Code, buffer(7,1))
105 | umasSubtree:add(Pairing_Key, buffer(8,1))
106 | umasSubtree:add(Umas_Functions_Code,buffer(9,1)):append_text(" (" .. umas_code_name .. ")")
107 | umasSubtree:add(Umas_Data, getData, data)
108 | end
109 | ------------------------------------------
110 | -- END OF THE UMAS SECTIONS ------------
111 | ------------------------------------------
112 | end
113 |
114 | -- subtree for the definitions of the UMAS protocol.
115 | function umas_protocol.dissector(buffer,pinfo,tree)
116 | length = buffer:len()
117 | if length == 0 then return end
118 | pinfo.cols.protocol = umas_protocol.name
119 |
120 | local subtree = tree:add(umas_protocol, buffer, "UMAS")
121 | subtree:add_le(Function_Code, buffer(7,1))
122 | end
123 |
124 | local modbus = DissectorTable.get("tcp.port")
125 | modbus:add(502, modbus1_protocol)
126 |
--------------------------------------------------------------------------------
/DhaeyerWolf/plugins/lua/siemens_ruggedcom(RCDP)_dissector.lua:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------------
2 | --
3 | -- Siemens Ruggedcom (RCDP) Protocol Plug-in for Wireshark
4 | --
5 | -- date : May, 7th 2021
6 | -- author : Luca Cremona (linkedin: luca--cremona)
7 | -- contact : secresearch [ @ ] nozominetworks [ . ] com
8 | --
9 | --------------------------------------------------------------------------
10 |
11 | rcdp_proto = Proto("RCDP", "Siemens RCDP")
12 |
13 | -- GENERAL DEFINES
14 | local HEADER_SEPARATOR = 513
15 | local TMP_SEPARATOR = 130
16 | local TMP_SEPARATOR_2 = 129
17 | local FIELD_SEPARATOR = 48
18 | local FIELD_TYPE_1 = 1548
19 | local FIELD_TYPE_2 = 1544
20 |
21 | -- RCDP PROTOCOL ID
22 | local RCDP_PID = 0x01e6
23 |
24 | -- BYTE INDEXES
25 | local LEN_2ND_POS = 0
26 | local SEQUENCE_N_POS = 4
27 |
28 | -- FIELDS LENGTH
29 | local L_LEN_2ND = 2
30 | local L_SEQUENCE_N = 1
31 |
32 | -- INIT. FIELDS
33 | local data_data = Field.new("data.data")
34 | local llc_pid = Field.new("llc.pid")
35 |
36 |
37 | seq_number = ProtoField.uint8("rcdp.seq_number", "Sync Number", base.HEX)
38 | direction = ProtoField.uint8("Direction", "Direction", base.HEX)
39 | command = ProtoField.uint8("Command", "Command", base.HEX)
40 | sequence_n = ProtoField.int32("rcdp.sequence_n", "Sequence", base.DEC)
41 | fields_length = ProtoField.int32("rcdp.fields_length", "All Fields Length", base.DEC)
42 | content_length = ProtoField.int32("rcdp.content_length", "Content Length", base.DEC)
43 | len_2nd = ProtoField.int32("rcdp.len_2nd", "Information length", base.DEC)
44 |
45 | os_version = ProtoField.string("rcdp.os_version", "OS Version", base.ASCII)
46 | boot_version = ProtoField.string("rcdp.boot_version", "Boot Version", base.ASCII)
47 | serial_num = ProtoField.string("rcdp.serial_num", "Serial Number", base.ASCII)
48 | order_code = ProtoField.string("rcdp.order_code", "Order Code", base.ASCII)
49 | location = ProtoField.string("rcdp.location", "Location", base.ASCII)
50 | contact = ProtoField.string("rcdp.contact", "Contact", base.ASCII)
51 | device_name = ProtoField.string("rcdp.device_name", "Device Name", base.ASCII)
52 | ip_addr = ProtoField.ipv4("rcdp.ip_addr", "IP Address")
53 | gateway = ProtoField.ipv4("rcdp.gateway", "Gateway")
54 | mask = ProtoField.ipv4("rcdp.mask", "Subnet Mask")
55 | blink_led = ProtoField.int32("rcdp.led", "Blink Led", base.DEC)
56 |
57 | rcdp_proto.fields = {
58 | seq_number,
59 | len_2nd,
60 | direction,
61 | content_length,
62 | sequence_n,
63 | fields_length,
64 | command,
65 | sys_name,
66 | os_version,
67 | boot_version,
68 | serial_num,
69 | order_code,
70 | location,
71 | contact,
72 | device_name,
73 | ip_addr,
74 | gateway,
75 | mask,
76 | blink_led
77 | }
78 |
79 |
80 | function rcdp_proto.dissector(buffer, pinfo, tree)
81 | length=buffer:len()
82 |
83 | if length == 0 then return end
84 |
85 | local llc_pid_ex = llc_pid()
86 |
87 | if llc_pid_ex == nil or llc_pid_ex.value ~= RCDP_PID
88 | then return
89 | end
90 |
91 | pinfo.cols.protocol = rcdp_proto.name
92 |
93 | local buf = data_data().range()
94 | local buf_len = buf:len()
95 | local subtree = tree:add(rcdp_proto, buf(0, buf:len()), "RCDP Protocol Data")
96 | len_2nd_val = buf(LEN_2ND_POS , L_LEN_2ND)
97 |
98 | if len_2nd_val:uint() ~= 0 then
99 | subtree:add(len_2nd, len_2nd_val)
100 | else
101 | subtree:add(len_2nd, len_2nd_val):append_text(" -> Autodiscovery - ping ACK")
102 | end
103 |
104 | subtree:add(seq_number, buf(SEQUENCE_N_POS , L_SEQUENCE_N))
105 |
106 | if(len_2nd_val:uint() > 0) then
107 | local second_part_start = buf_len - len_2nd_val:uint()
108 | local iterator = second_part_start
109 | local dir = buf(iterator,1)
110 |
111 | subtree:add(direction, dir):append_text(" [" .. get_direction(dir:uint()) .. "]")
112 | iterator = iterator + 1
113 | local tmp = buf(iterator,1)
114 |
115 | if (tmp:uint() == TMP_SEPARATOR) then
116 | subtree:add(command, tmp):append_text(" -> Autodiscovery - Senda Data")
117 | f_autodiscovery(buf, pinfo, subtree, iterator+1, buf_len)
118 | elseif (tmp:uint() == TMP_SEPARATOR_2) then
119 | subtree:add(command, tmp):append_text(" -> Autodiscovery - Request Data")
120 | f_autodiscovery_req(buf, pinfo, subtree, iterator+1, buf_len)
121 | else
122 | f_set_value(buf, pinfo, subtree, iterator, buf_len)
123 | end
124 | end
125 | end
126 |
127 |
128 | function get_direction(value)
129 | local direction = "UNKNOWN"
130 |
131 | if value == 162 then direction = "RUGGEDCOM -> PC"
132 | elseif value == 163 then direction = "PC -> RUGGEDCOM"
133 | elseif value == 160 then direction = "BROADCAST"
134 | end
135 |
136 | return direction
137 | end
138 |
139 | function f_autodiscovery_req (buf, pinfo, subtree, iterator, buf_len)
140 | local num_bytes = 0
141 | local tmp_len = 0
142 | local tmp_id
143 |
144 | while buf(iterator,2):uint() ~= HEADER_SEPARATOR do
145 | iterator = iterator + 1
146 | num_bytes = num_bytes + 1
147 | end
148 |
149 | local content_len = buf(iterator-num_bytes, num_bytes)
150 |
151 | if content_len:uint() > 0 then
152 | subtree:add(content_length, content_len:uint())
153 | end
154 |
155 | iterator = iterator + 2
156 | num_bytes = 0
157 |
158 | while buf(iterator,2):uint() ~= HEADER_SEPARATOR do
159 | iterator = iterator + 1
160 | num_bytes = num_bytes + 1
161 | end
162 |
163 | local sequence = buf(iterator-num_bytes,num_bytes)
164 |
165 | subtree:add(sequence_n, sequence)
166 | iterator = iterator + 2
167 |
168 | while buf(iterator,1):uint() ~= TMP_SEPARATOR_2 do
169 | iterator = iterator + 1
170 | end
171 |
172 | iterator = iterator + 1
173 | num_bytes = 0
174 |
175 | while buf(iterator,1):uint() ~= FIELD_SEPARATOR do
176 | iterator = iterator + 1
177 | num_bytes = num_bytes + 1
178 | end
179 |
180 | local fields_len = buf(iterator-num_bytes, num_bytes)
181 |
182 | if fields_len:int() < 0 then
183 | subtree:add(fields_length, fields_len:uint())
184 | end
185 | end
186 |
187 |
188 | function f_autodiscovery (buf, pinfo, subtree, iterator, buf_len)
189 | local num_bytes = 0
190 | local tmp_len = 0
191 | local tmp_id
192 |
193 | while buf(iterator,2):uint() ~= HEADER_SEPARATOR do
194 | iterator = iterator + 1
195 | num_bytes = num_bytes + 1
196 | end
197 |
198 | local content_len = buf(iterator-num_bytes, num_bytes)
199 |
200 | if content_len:uint() > 0 then
201 | subtree:add(content_length, content_len)
202 | end
203 |
204 | iterator = iterator + 2
205 | num_bytes = 0
206 |
207 | while buf(iterator,2):uint() ~= HEADER_SEPARATOR do
208 | iterator = iterator + 1
209 | num_bytes = num_bytes + 1
210 | end
211 |
212 | local sequence = buf(iterator-num_bytes,num_bytes)
213 |
214 | subtree:add(sequence_n, sequence)
215 | iterator = iterator + 2
216 |
217 | while buf(iterator,1):uint() ~= TMP_SEPARATOR do
218 | iterator = iterator + 1
219 | end
220 |
221 | iterator = iterator + 1
222 | num_bytes = 0
223 |
224 | while buf(iterator,1):uint() ~= FIELD_SEPARATOR do
225 | iterator = iterator + 1
226 | num_bytes = num_bytes + 1
227 | end
228 |
229 | local fields_len = buf(iterator-num_bytes, num_bytes)
230 |
231 | if fields_len:int() < 0 then
232 | subtree:add(fields_length, fields_len)
233 | end
234 |
235 | iterator = iterator + 1
236 |
237 | while (iterator < buf_len) do
238 | local field_len = buf(iterator, 1)
239 | iterator = iterator + 1
240 |
241 | if(buf(iterator, 2):uint() == FIELD_TYPE_2) then
242 | add_field_0608(buf, subtree, iterator)
243 | else
244 | add_field_060c(buf, subtree, iterator)
245 | end
246 |
247 | iterator = iterator + field_len:uint() + 1
248 | end
249 | end
250 |
251 | function f_set_value (buf, pinfo, subtree, iterator, buf_len)
252 | local num_bytes = 0
253 | local tmp_len = 0
254 | local tmp_id
255 |
256 | while buf(iterator,2):uint() ~= HEADER_SEPARATOR do
257 | iterator = iterator + 1
258 | num_bytes = num_bytes + 1
259 | end
260 |
261 | local content_len = buf(iterator-num_bytes, num_bytes)
262 | subtree:add(content_length, content_len)
263 | iterator = iterator + 2
264 | num_bytes = 0
265 |
266 | while buf(iterator,2):uint() ~= HEADER_SEPARATOR do
267 | iterator = iterator + 1
268 | num_bytes = num_bytes + 1
269 | end
270 |
271 | local sequence = buf(iterator-num_bytes,num_bytes)
272 |
273 | subtree:add(sequence_n, sequence)
274 | iterator = iterator + 2
275 |
276 | while buf(iterator,1):uint() ~= FIELD_SEPARATOR do
277 | iterator = iterator + 1
278 | end
279 |
280 | iterator = iterator + 1
281 | num_bytes = 0
282 |
283 | while buf(iterator,1):uint() ~= FIELD_SEPARATOR do
284 | iterator = iterator + 1
285 | num_bytes = num_bytes + 1
286 | end
287 |
288 | local fields_len = buf(iterator-num_bytes, num_bytes)
289 | subtree:add(fields_length, fields_len)
290 |
291 | iterator = iterator + 1
292 |
293 | while (iterator < buf_len) do
294 | local field_len = buf(iterator, 1)
295 | iterator = iterator + 1
296 |
297 | if(buf(iterator, 2):uint() == FIELD_TYPE_2) then
298 | add_field_0608(buf, subtree, iterator)
299 | else
300 | add_field_060c(buf, subtree, iterator)
301 | end
302 | iterator = iterator + field_len:uint() + 1
303 | end
304 |
305 | end
306 |
307 | function add_field_060c (buf, subtree, iterator, buf_len)
308 | iterator = iterator + 11
309 | local field_id = buf(iterator,2)
310 | iterator = iterator + 4
311 | local field_len = buf(iterator,1)
312 | iterator = iterator + 1
313 |
314 | if field_id:uint() == 257 then
315 | if field_len:uint() ~= 0 then
316 | subtree:add(ip_addr, buf(iterator, field_len:uint()))
317 | end
318 | elseif field_id:uint() == 258 then
319 | if field_len:uint() ~= 0 then
320 | subtree:add(mask, buf(iterator, field_len:uint()))
321 | end
322 | elseif field_id:uint() == 259 then
323 | if field_len:uint() ~= 0 then
324 | subtree:add(gateway, buf(iterator, field_len:uint()))
325 | end
326 | elseif field_id:uint() == 1030 then
327 | if field_len:uint() ~= 0 then
328 | if buf(iterator, field_len:uint()):uint() == 0 then
329 | subtree:add(blink_led, buf(iterator, field_len:uint())):append_text(" (Not Blinking)")
330 | else
331 | subtree:add(blink_led, buf(iterator, field_len:uint())):append_text(" (Blinking)")
332 | end
333 | end
334 | elseif field_id:uint() == 769 then
335 | subtree:add(serial_num, buf(iterator, field_len:uint()))
336 | elseif field_id:uint() == 770 then
337 | subtree:add(boot_version, buf(iterator, field_len:uint()))
338 | elseif field_id:uint() == 771 then
339 | subtree:add(os_version, buf(iterator, field_len:uint()))
340 | end
341 | end
342 |
343 | function add_field_0608 (buf, subtree, iterator)
344 | iterator = iterator + 7
345 | local field_id = buf(iterator,2)
346 | iterator = iterator + 4
347 | local field_len = buf(iterator,1)
348 | iterator = iterator + 1
349 | if field_id:uint() == 257 then
350 | subtree:add(order_code, buf(iterator, field_len:uint()))
351 | elseif field_id:uint() == 260 then
352 | subtree:add(contact, buf(iterator, field_len:uint()))
353 | elseif field_id:uint() == 261 then
354 | subtree:add(device_name, buf(iterator, field_len:uint()))
355 | elseif field_id:uint() == 262 then
356 | subtree:add(location, buf(iterator, field_len:uint()))
357 | end
358 | end
359 |
360 | -- Register Postdissector
361 | register_postdissector(rcdp_proto)
362 |
--------------------------------------------------------------------------------
/DhaeyerWolf/notes/dnp3.md:
--------------------------------------------------------------------------------
1 | # DNP3
2 |
3 |
4 | # Application Layer Function Code
5 | | Hex Value | Name | Description | Security Implications |
6 | |-----------|------------------------|-----------------------------------------------------|----------------------------------------------------------------------------------------------------------|
7 | | 0x00 | Confirm | Acknowledge receipt of application data | Ensures reliable communication; lack of confirmation may indicate communication issues or replay attacks. |
8 | | 0x01 | Read | Request data objects from outstation | Unauthorized reads may leak sensitive information. |
9 | | 0x02 | Write | Write data objects to outstation | Unauthorized writes can alter configuration or operational data, potentially causing system misbehavior. |
10 | | 0x03 | Select | Prepare a control point for operation | Select before operate ensures a two-step control process, reducing risk of accidental operations. |
11 | | 0x04 | Operate | Execute operation on selected control point | Must be protected to prevent unauthorized control of equipment. |
12 | | 0x05 | Direct Operate | Directly operate a control point, bypassing select | Increases risk as it omits the select step, should be secured to prevent misuse. |
13 | | 0x06 | Direct Operate No Ack | Operate a control point directly, no acknowledgment | No response required; high risk if used maliciously, as it might not be logged or noticed immediately. |
14 | | 0x07 | Immediate Freeze | Freeze counters without altering values | Can be used to capture system state for analysis, but unauthorized use could disrupt operational monitoring. |
15 | | 0x08 | Immediate Freeze No Ack| Freeze counters without acknowledgment or altering values | Can be used to capture system state for analysis, but unauthorized use could disrupt operational monitoring. |
16 | | 0x09 | Freeze and Clear | Freeze counters and reset them | Could be used to erase historical data, hindering incident analysis and system monitoring. |
17 | | 0x0A | Freeze and Clear No Ack| Freeze counters, reset them, no acknowledgment | Could be used to erase historical data, hindering incident analysis and system monitoring. |
18 | | 0x0B | Freeze With Time | Freeze counters with a timestamp | Useful for synchronized measurements; unauthorized use could be a prelude to coordinated attacks. |
19 | | 0x0C | Freeze With Time No Ack| Freeze counters with timestamp, no acknowledgment | Useful for synchronized measurements; unauthorized use could be a prelude to coordinated attacks. |
20 | | 0x0D | Cold Restart | Restart outstation, re-initializing all hardware and software | Unauthorized restarts can cause service interruptions and loss of volatile data. |
21 | | 0x0E | Warm Restart | Restart outstation without re-initializing hardware | Less disruptive than a cold restart, but still can be used to interrupt service. |
22 | | 0x0F | Initialize Data | Initialize application data on the outstation | Can alter operational parameters, potentially leading to unsafe conditions if misused. |
23 | | 0x10 | Initialize Application | Initialize application-specific configurations | Misuse can lead to misconfiguration and system vulnerabilities. |
24 | | 0x11 | Start Application | Start application-specific functions | Could initiate unauthorized processes or enable malicious applications. |
25 | | 0x12 | Stop Application | Stop application-specific functions | Can be used to halt critical monitoring or control functions, potentially leading to unsafe conditions. |
26 | | 0x13 | Save Configuration | Save current configuration settings | Unauthorized saving of configurations can lock in malicious settings, making them persistent. |
27 | | 0x14 | Enable Unsolicited | Enable unsolicited responses from outstation | If misconfigured, could lead to denial-of-service through response flooding. |
28 | | 0x15 | Disable Unsolicited | Disable unsolicited responses from outstation | Could be used to prevent alarms or other important notifications from being reported. |
29 | | 0x16 | Assign Class | Assign data objects to a class for reporting | Misassignment can lead to missed alarms or excessive traffic, depending on the class. |
30 | | 0x17 | Delay Measurement | Measure communication delay | Important for timing analysis, but could be used to map network performance for targeted attacks. |
31 | | 0x18 | Record Current Time | Record the current time in outstation | Ensures time synchronization, but incorrect time settings could affect timestamped data and event logging. |
32 | | 0x19 | Open File | Open a file for reading or writing | Unauthorized access could lead to data leakage or alteration. |
33 | | 0x1A | Close File | Close a file | Proper file handling is crucial for data integrity; unauthorized closure could disrupt legitimate operations. |
34 | | 0x1B | Delete File | Delete a file | Could be used to remove critical firmware or configuration files, potentially causing outstation malfunction. |
35 | | 0x1C | Get File Information | Retrieve file attributes | Unauthorized access could reveal sensitive information about file contents and system configuration. |
36 | | 0x1D | Authenticate File | Authenticate a file's integrity | Ensuring file authenticity is critical for preventing the execution of tampered or malicious code. |
37 | | 0x1E | Abort File | Abort ongoing file operations | Could disrupt legitimate updates or data transfers, potentially leaving the system in an inconsistent state. |
38 | | 0x1F | Activate Configuration | Activate a configuration object | Unauthorized activation could implement malicious configurations, affecting system operation. |
39 | | 0x20 | Authenticate Request | Request authentication challenge | Ensures secure communication; failure to authenticate could indicate an attempted security breach. |
40 | | 0x21 | Authenticate Error | Report an authentication error | Critical for detecting and responding to authentication failures, which may signify attempted unauthorized access. |
41 | | 0x22 | Response | Response for solicited messages | Responses must be verified to ensure data integrity and to detect replay attacks. |
42 | | 0x23 | Unsolicited Response | Unsolicited response for Class 1/2/3 data | Must be monitored for unexpected traffic, which could indicate a compromised outstation. |
43 | | 0x24 | Unknown | Unknown function code | Unknown codes could be indicative of a malfunctioning or compromised device and should be investigated. |
44 | | | | Additional proprietary or future standard function codes | Proprietary codes require vendor-specific knowledge to assess security implications. |
45 |
46 |
47 | # Internal Indications
48 | | Filter | Name | Description | Cyber Security Implications |
49 | |-------------------|------------------------------|-----------------------------------------------------------|------------------------------------------------------------------------------------------------------------------|
50 | | dnp3.al.iin.rst | Device Reset | Indicates that the device has been reset. | If unexpected, may indicate potential cyber-attack or device malfunction. |
51 | | dnp3.al.iin.dt | Device trouble. | General indication that there is a problem with the device. | Could be indicative of a cyber-attack or hardware issue that needs attention. |
52 | | dnp3.al.iin.dol | Digital Outputs in Local. | Digital outputs are being controlled locally and not remotely. | May reduce the risk of unauthorized remote operations but indicates loss of remote control. |
53 | | dnp3.al.iin.tsr | Time sync Required. | The device requires time synchronization. | If frequent, may suggest a coordinated attack on time sources or device malfunctions. |
54 | | dnp3.al.iin.cls3d | Class 3 data available. | Class 3 data is available to be retrieved by the master. | Sudden or unexpected availability might need investigation for unauthorized access. |
55 | | dnp3.al.iin.cls2d | Class 2 data available. | Class 2 data is available to be retrieved by the master. | Sudden or unexpected availability might need investigation for unauthorized access. |
56 | | dnp3.al.iin.cls1d | Class 1 data available. | Class 1 data is available to be retrieved by the master. | Sudden or unexpected availability might need investigation for unauthorized access. |
57 | | dnp3.al.iin.bmsg | Broadcast Msg Rx. | A broadcast message has been received. | May be a sign of an attempt to send commands to multiple devices simultaneously. |
58 | | dnp3.al.iin.cc | Configuration corrupt. | The device's configuration is corrupt and needs to be checked. | Could indicate a cyber-attack aimed at disrupting operations by corrupting configuration files. |
59 | | dnp3.al.iin.oae | Operation Already Executing. | An operation is already in progress on the device. | Multiple operations may indicate a denial-of-service attack. |
60 | | dnp3.al.iin.ebo | Event buffer overflow. | The event buffer has overflowed, and some events may have been lost. | Could be caused by an attack designed to trigger numerous events and overwhelm the system. |
61 | | dnp3.al.iin.pioor | Parameters Invalid or Out of Range. | Parameters received are invalid or out of range. | May be due to misconfiguration or an attempt to cause the device to operate outside safe parameters. |
62 | | dnp3.al.iin.obju | Requested Objects Unknown. | The requested data objects are unknown to the device. | Could indicate an attempt to probe the device for information or capabilities. |
63 | | dnp3.al.iin.fcni | Function code not implemented. | The requested function code is not implemented in the device. | Repeated attempts could be seen as probing for device capabilities or could cause unnecessary processing. |
64 |
65 |
--------------------------------------------------------------------------------
/DhaeyerWolf/notes/EthernetIP(CIP).md:
--------------------------------------------------------------------------------
1 | # Rockwell specific
2 | - source: enet-at002_-en-p.pdf (Rockwell Automation Publication ENET-AT002E-EN-P - January 2023)
3 | - source: Various personal observations in pcaps
4 |
5 | ## Terminology
6 | - Download: Send a program from Workstation to a PLC Workstation -> PLC
7 | - Upload: Grab a program from a PLC onto the Workstation PLC -> Workstation
8 |
9 | ## Wireshark notes
10 | | service code | Name | notes |
11 | | ------------ | ------------------------------------------ | ----------------------------------------------------------------------------------------------- |
12 | | 0x36 | unkown | unkown |
13 | | 0x37 | I/O Force Activation request | observetions showed enable I/O request; Force I/O request |
14 | | 0x38 | unkown | unkown |
15 | | 0x4C | Read Tag | not yet observed, but potentially used during program upload |
16 | | 0x4D | Write Tag | Has been observed during program Download, add "enip.timeout == 1" to get only the requests |
17 | | 0x4E | Read Modify Write | Read Modify Write |
18 | | 0x50 | unkown | Unkown data that contains (port), configuration data |
19 | | 0x52 | Read Tag Fragmented | Read Tag Fragmented |
20 | | 0x53 | Write Tag Fragmented | Write Tag Fragmented |
21 | | 0x54 | unkown | Not yet encountered, however 0x53 & 0x55 exists so probably 0x54 as well |
22 | | 0x55 | Get Instance Attribute List | Get Instance Attribute List |
23 |
24 |
25 | ## Protocol structure
26 | | Name | Description | Wireshark filter |
27 | |--------------|-------------------------------------------------------------|------------------|
28 | | Service Code | Specifies the operation (e.g., read, write) | cip.sc |
29 | | Class | Identifies the group of objects targeted by the operation. | cip.class |
30 | | Instance | Specifies the particular object within the class. | cip.instance |
31 | | Attribute | Indicates the specific property or data point to be accessed or modified. | cip.attribute |
32 |
33 | - **Service Code:** The service code is a part of the CIP message that specifies the type of operation to be performed. It defines the action that the client (e.g., a PLC or HMI) is requesting the server (e.g., a sensor or actuator) to execute. Common service codes include read, write, reset, start, stop, etc.
34 | - **Class:** In CIP, a class is a collection of objects that share common characteristics and behaviors. Each class represents a specific type of device or function within the network. For instance, there might be a class for analog input modules, another for digital output modules, and so on. Each class is identified by a unique class ID.
35 | - **Instance:** An instance is a specific occurrence of a class. While a class defines the general characteristics and behaviors, an instance represents a particular object within that class. For example, if you have a class for analog input modules, each individual analog input module on the network would be an instance of that class. Instances are identified by instance IDs.
36 | - **Attribute:** Attributes are specific properties or data points associated with a class or instance. They represent the actual data that can be read or written, such as the current value of a sensor, configuration parameters, or status information. Each attribute is identified by an attribute ID.
37 |
38 | ### Set Attribute Single
39 | | Field | value |
40 | | ----- | ----- |
41 | | Service Code | 0x10 |
42 |
43 | ### DisableSocket
44 | | Field | value |
45 | | ----- | ----- |
46 | | Service Code | 0x10 |
47 | | Class | 0x342 |
48 | | instance | 0 |
49 | | Attribute | 0x9 |
50 |
51 | ### CreateSocket
52 | | Field | value |
53 | | ----- | ----- |
54 | | Service Code | 0x4b |
55 | | Class | 0x342 |
56 | | instance | 0 |
57 | | Attribute | 0x0 |
58 |
59 | MSG source length: Specify the size of the user-defined structure for the source element. In this example, CreateParams is 12 bytes.
60 |
61 | ### OpenConnection
62 | | Field | value |
63 | | ----- | ----- |
64 | | Service Code | 0x4c |
65 | | Class | 0x342 |
66 | | instance | from Socket Create |
67 | | Attribute | 0x0 |
68 |
69 | MSG source length: specify 8 bytes (timeout + AddrLen) + number of characters in destination address
70 |
71 | ### AcceptConnection
72 | | Field | value |
73 | | ----- | ----- |
74 | | Service Code | 0x50 |
75 | | Class | 0x342 |
76 | | instance | from Socket Create |
77 | | Attribute | 0x0 |
78 |
79 | MSG source length: Specify 4 bytes (Timeout).
80 |
81 | ### ReadSocket
82 | | Field | value |
83 | | ----- | ----- |
84 | | Service Code | 0x4d |
85 | | Class | 0x342 |
86 | | instance | see instance ??? |
87 | | Attribute | 0x0 |
88 |
89 | This service uses the instance that is returned from the CreateConnection service. However, when accepting a connection via the
90 | AcceptConnection service, use the instance that is returned from this AcceptConnection service as the ReadSocket instance
91 |
92 | MSG source length: Specify 8 bytes (Timeout + BufLen).
93 |
94 | ### WriteSocket
95 | | Field | value |
96 | | ----- | ----- |
97 | | Service Code | 0x4e |
98 | | Class | 0x342 |
99 | | instance | see instance ??? |
100 | | Attribute | 0x0 |
101 |
102 | This service uses the instance that is returned from the CreateConnection service. However, when accepting a connection via the
103 | AcceptConnection service, use the instance that is returned from this AcceptConnection service as the WriteSocket instance.
104 |
105 | MSG source length: Specify 16 bytes (Timeout + Addr + BufLen) + number of bytes to write.
106 |
107 | ### DeleteSocket
108 | | Field | value |
109 | | ----- | ----- |
110 | | Service Code | 0x4f |
111 | | Class | 0x342 |
112 | | instance | from Socket Create|
113 | | Attribute | 0x0 |
114 |
115 | MSG source length: Specify 0 bytes
116 |
117 | ### DeleteAllSockets
118 | | Field | value |
119 | | ----- | ----- |
120 | | Service Code | 0x51 |
121 | | Class | 0x342 |
122 | | instance | 0 |
123 | | Attribute | 0x0 |
124 |
125 | MSG source length: Specify 0 bytes
126 |
127 | ### ClearLog
128 | | Field | value |
129 | | ----- | ----- |
130 | | Service Code | 0x52 |
131 | | Class | 0x342 |
132 | | instance | 0 |
133 | | Attribute | 0x0 |
134 |
135 | MSG source length: Specify 0 bytes
136 |
137 | ### JoinMulticastAddress
138 | | Field | value |
139 | | ----- | ----- |
140 | | Service Code | 0x53 |
141 | | Class | 0x342 |
142 | | instance | from Socket Create |
143 | | Attribute | 0x0 |
144 |
145 | MSG source length: Specify 8 bytes
146 |
147 | ### DropMulticastAddress
148 | | Field | value |
149 | | ----- | ----- |
150 | | Service Code | 0x54 |
151 | | Class | 0x342 |
152 | | instance | from Socket Create |
153 | | Attribute | 0x0 |
154 |
155 | MSG source length: Specify 8 bytes
156 |
157 | ## Publication
158 | - [source](https://www.rockwellautomation.com/en-us/support/documentation/overview/publication-types.html)
159 | **Publication Types**
160 | Select a publication type to match your information needs.
161 |
162 | These are our most common publication types and the typical information you can find in each. To narrow your Literature Library search results, use the Publication Type filter to show only the publications most relevant to your information needs.
163 |
164 | **Features, Benefits, and Applications**
165 |
166 | - **Application Profile/Customer Success Story (AP)**
167 | - Demonstrates how our products and services can optimize your industrial operations. Some describe how we helped a specific customer solve an application need.
168 | - **Brochure/Magazine (BR)**
169 | - Features and benefits for a family of products, group of services, or industry. Best for finding overview information.
170 | - **Profile (PP)**
171 | - Features and benefits for a single product or service. May include high-level specification and product catalog number information. Best for finding overview information.
172 | - **Sales Promotion (SP)**
173 | - Includes infographics and eBooks. An infographic provides high-level information in a visual format. An eBook examines topics and challenges that companies may face when working with a specific application.
174 | - **White Paper (WP)**
175 | - An objective overview or in-depth technical assessment that addresses an architecture, capability, or product technology.
176 |
177 | **Technical Specifications and Product Certifications**
178 |
179 | - **Certifications (CT)**
180 | - Product certifications to help you verify that the ratings meet the needs of your application.
181 | - **Selection Guide (SG)**
182 | - Selection steps and criteria to help you choose among different products to build a system.
183 | - **Technical Data (TD)**
184 | - Complete specifications of a product family or platform.
185 |
186 | **Program**
187 |
188 | - **Application Technique (AT)**
189 | - Programming techniques and configuration recommendations for a specific combination of products or a specific feature or function. Intended for the experienced user.
190 | - **Getting Results (GR)**
191 | - Describes how to install, navigate, troubleshoot, and effectively use a software product. This publication supplements a comprehensive online help system.
192 | - **Programming Manual (PM)**
193 | - Guides the developer on how to design, write, and test an application.
194 |
195 | **Install and Operate**
196 |
197 | - **Dimension Sheet (DS)**
198 | - Shows product dimensions or mounting templates.
199 | - **Installation Instructions (IN)**
200 | - Information on how to install, configure (if applicable), and troubleshoot a product.
201 | - **Quick Start (QS)**
202 | - Basic, task-oriented information on how to install, configure, and operate a set of products or components.
203 | - **Reference Data (RD)**
204 | - Descriptions of fault codes, alarm codes, parameters, or other highly structured data presented in a spreadsheet format to enable sort and filter capabilities.
205 | - **Reference Manual (RM)**
206 | - Highly structured and detailed information on product designs, functions, ratings, instructions, or other application requirements. Intended for the experienced user.
207 | - **User Manual (UM)**
208 | - Instructions for product configuration and use. Can also include installation and troubleshooting information.
209 | - **Wiring Diagram (WD)**
210 | - Wiring diagrams and connection guidelines. Generally used when the product does not have Installation Instructions or User Manual.
211 |
212 | **Publication Number 101**
213 |
214 | Do you ever wonder what the characters in our publication numbers mean? These characters provide an at-a-glance view of the type of content in a publication.
215 |
216 | 
--------------------------------------------------------------------------------
/DhaeyerWolf/notes/IEC104.md:
--------------------------------------------------------------------------------
1 | # Type IDs
2 |
3 | | Name | Full Name | TypeId | Description | Cyber Security Analysis |
4 | |---------------|-----------------------------------------------------|--------|-------------|------------------------|
5 | | M_SP_NA_1 | single-point information | 1 | Single-point information: Represents the status of a single digital input, used to monitor discrete events. | In cybersecurity, it's important for detecting unauthorized state changes or inconsistencies. |
6 | | M_SP_TA_1 | single-point information with time tag | 2 | Single-point information with time tag: Similar to single-point information, but includes a timestamp for precise event logging. | Critical for time-based analysis of security incidents. |
7 | | M_DP_NA_1 | double-point information | 3 | Double-point information: Conveys the status of a digital input with more states than a single-point, such as intermediate states. | Essential for detailed monitoring of system behavior in security audits. |
8 | | M_DP_TA_1 | double-point information with time tag | 4 | Double-point information with time tag: Provides detailed state changes with time accuracy, enabling forensic analysis of security breaches. | Necessary for tracing events in a security investigation. |
9 | | M_ST_NA_1 | step position information | 5 | Step position information: Indicates the position of a step controller, useful for tracking if a device is being manipulated beyond normal operation parameters. | Useful for identifying unauthorized device manipulation. |
10 | | M_ST_TA_1 | step position information with time tag | 6 | Step position information with time tag: Adds time information to step position, allowing for correlation with other timed events during an investigation. | Helps in correlating events when investigating security incidents. |
11 | | M_BO_NA_1 | bitstring of 32 bits | 7 | Bitstring of 32 bits: A 32-bit status or command sequence that can be used to detect unauthorized commands or state manipulations in control systems. | Important for detecting unauthorized commands or state manipulations. |
12 | | M_BO_TA_1 | bitstring of 32 bits with time tag | 8 | Bitstring of 32 bits with time tag: The timestamped version of the 32-bit string, which is vital for tracing the exact moment of a potential cyber attack. | Critical for tracing the timing of potential cyber attacks. |
13 | | M_ME_NA_1 | measured value, normalized value | 9 | Measured value, normalized value: Used for analog measurements, normalized to a set range. | Monitoring these can reveal data trends that indicate cyber-physical system tampering. |
14 | | M_ME_TA_1 | measured value, normalized value with time tag | 10 | Measured value, normalized value with time tag: Time-stamped analog measurements to detect anomalies at specific times, which could signify a security event. | Useful for detecting anomalies that could signify security events. |
15 | | M_ME_NB_1 | measured value, scaled value | 11 | Measured value, scaled value: Represents analog measurements in a scaled format. | Sudden changes may suggest unauthorized system interactions. |
16 | | M_ME_TB_1 | measured value, scaled value with time tag | 12 | Measured value, scaled value with time tag: Timestamped scaled values can help pinpoint the timing of unusual system readings during a cyber event. | Helps in pinpointing unusual system readings during a cyber event. |
17 | | M_ME_NC_1 | measured value, short floating point number | 13 | Measured value, short floating point number: Floating-point precision for analog values, which can indicate the precision manipulation of readings. | Indicates precision manipulation of readings, which could be malicious. |
18 | | M_ME_TC_1 | measured value, short floating point number with time tag | 14 | Measured value, short floating point number with time tag: High precision timed measurements for detailed analysis of system changes during security incidents. | Essential for detailed analysis of system changes during security incidents. |
19 | | M_IT_NA_1 | integrated totals | 15 | Integrated totals: Accumulated values over time, such as energy consumption. | Unexplained deviations could be indicative of system compromise. |
20 | | M_IT_TA_1 | integrated totals with time tag | 16 | Integrated totals with time tag: Time-bound accumulated measurements are crucial for identifying periods of unusual activity that may signal a cyber attack. | Crucial for identifying periods of unusual activity that may signal a cyber attack. |
21 | | M_PS_NA_1 | packed single-point information with status change detection | 20 | Packed single-point information with status change detection: Aggregated status information that can reveal patterns of system behavior changes in response to a cyber threat. | Useful for revealing patterns of system behavior changes in response to a cyber threat. |
22 | | M_ME_ND_1 | measured value, normalized value without quality descriptor | 21 | Measured value, normalized value without quality descriptor: Pure measurement data that can be baseline referenced for detecting anomalies. | Pure measurement data is essential for baseline referencing and detecting anomalies. |
23 | | M_SP_TB_1 | single-point information with time tag CP56Time2a | 30 | Single-point information with time tag CP56Time2a: Provides precise timing for single-point events, enhancing the accuracy of security event logging. | Enhances the accuracy of security event logging with precise timing. |
24 | | M_DP_TB_1 | double-point information with time tag CP56Time2a | 31 | Double-point information with time tag CP56Time2a: Detailed state information with precise timing, crucial for forensic analysis in cybersecurity. | Crucial for forensic analysis in cybersecurity with precise timing. |
25 | | M_ST_TB_1 | step position information with time tag CP56Time2a | 32 | Step position information with time tag CP56Time2a: Precisely timed step position data for detecting unauthorized manipulations in real time. | Allows for real-time detection of unauthorized manipulations. |
26 | | M_BO_TB_1 | bitstring of 32 bit with time tag CP56Time2a | 33 | Bitstring of 32 bit with time tag CP56Time2a: A detailed bitstring with accurate timing, useful for tracking exact sequences of control commands during an attack. | Useful for tracking exact sequences of control commands during an attack. |
27 | | M_ME_TD_1 | measured value, normalized value with time tag CP56Time2a | 34 | Measured value, normalized value with time tag CP56Time2a: Time-stamped normalized measurements for immediate detection of out-of-bounds values indicating potential system breaches. | Allows for immediate detection of out-of-bounds values indicating potential system breaches. |
28 | | M_ME_TE_1 | measured value, scaled value with time tag CP56Time2a | 35 | Measured value, scaled value with time tag CP56Time2a: Scaled analog data with precise time tags, aiding in the quick identification of timing and scaling anomalies due to cyber events. | Aids in the quick identification of timing and scaling anomalies due to cyber events. |
29 | | M_ME_TF_1 | measured value, short floating point number with time tag CP56Time2a | 36 | Measured value, short floating point number with time tag CP56Time2a: High-resolution measurements with timestamps, essential for detailed monitoring of system integrity. | Essential for detailed monitoring of system integrity with high-resolution measurements. |
30 | | M_IT_TB_1 | integrated totals with time tag CP56Time2a | 37 | Integrated totals with time tag CP56Time2a: Cumulative values with precise timing, which can be analyzed for signs of data falsification or theft. | Can be analyzed for signs of data falsification or theft with precise timing. |
31 | | M_EP_TD_1 | event of protection equipment with time tag CP56Time2a | 38 | Event of protection equipment with time tag CP56Time2a: Timed events from protective devices that, if altered, could indicate tampering or malicious activity. | Timed events from protective devices are critical for detecting tampering or malicious activity. |
32 | | M_EP_TE_1 | packed start events of protection equipment with time tag CP56Time2a | 39 | Packed start events of protection equipment with time tag CP56Time2a: A collection of start events from protection equipment, which should be scrutinized for unauthorized actions. | Should be scrutinized for unauthorized actions in protection equipment. |
33 | | M_EP_TF_1 | packed output circuit information of protection equipment with time tag CP56Time2a | 40 | Packed output circuit information of protection equipment with time tag CP56Time2a: Detailed protective circuit actions with timing, useful for identifying malicious circuit manipulations. | Useful for identifying malicious circuit manipulations with detailed timing. |
34 | | S_IT_TC_1 | integrated totals containing time tagged security statistics | 41 | Integrated totals containing time tagged security statistics: Security-relevant cumulative values with timestamps, key for identifying trends in security data. | Key for identifying trends in security data with security-relevant cumulative values. |
35 | | C_SC_NA_1 | single command | 45 | Single command: A control command that can be monitored for unauthorized operations that could compromise system security. | Can be monitored for unauthorized operations that could compromise system security. |
36 | | C_DC_NA_1 | double command | 46 | Double command: A more complex control command where unexpected changes could suggest security breaches. | Unexpected changes in double commands could suggest security breaches. |
37 | | C_RC_NA_1 | regulating step command | 47 | Regulating step command: Commands for incremental adjustments, where unauthorized changes could lead to system instability or indicate a cyber attack. | Unauthorized changes in regulating step commands could indicate a cyber attack. |
38 | | C_SE_NA_1 | set point command, normalized value | 48 | Set point command, normalized value: Control commands for setting a normalized value, which should be monitored for integrity to prevent unauthorized system control. | Should be monitored for integrity to prevent unauthorized system control. |
39 | | C_SE_NB_1 | set point command, scaled value | 49 | Set point command, scaled value: Commands that set scaled values, which need to be protected against tampering to maintain system security. | Need to be protected against tampering to maintain system security. |
40 | | C_SE_NC_1 | set point command, short floating point number | 50 | Set point command, short floating point number: Precise control commands that are critical to safeguard to prevent precision attacks on system operations. | Critical to safeguard to prevent precision attacks on system operations. |
41 | | C_BO_NA_1 | bitstring of 32 bits | 51 | Bitstring of 32 bits: A sequence of control or status bits that can be analyzed for patterns indicating cyber intrusion. | Can be analyzed for patterns indicating cyber intrusion. |
42 | | C_SC_TA_1 | single command with time tag CP56Time2a | 58 | Single command with time tag CP56Time2a: Timed control commands for single operations, where the timing can be critical in investigating security incidents. | Timing can be critical in investigating security incidents. |
43 | | C_DC_TA_1 | double command with time tag CP56Time2a | 59 | Double command with time tag CP56Time2a: Timed double commands that, if altered, can have significant implications for system security. | If altered, can have significant implications for system security. |
44 | | C_RC_TA_1 | regulating step command with time tag CP56Time2a | 60 | Regulating step command with time tag CP56Time2a: Timed incremental control commands, where unauthorized timing changes could signify a coordinated attack. | Unauthorized timing changes could signify a coordinated attack. |
45 | | C_SE_TA_1 | set point command, normalized value with time tag CP56Time2a | 61 | Set point command, normalized value with time tag CP56Time2a: Timed commands for setting normalized values, crucial for detecting unauthorized control attempts. | Crucial for detecting unauthorized control attempts. |
46 | | C_SE_TB_1 | set point command, scaled value with time tag CP56Time2a | 62 | Set point command, scaled value with time tag CP56Time2a: Commands with timing information for setting scaled values, important for identifying unauthorized access. | Important for identifying unauthorized access. |
47 | | C_SE_TC_1 | set point command, short floating-point number with time tag CP56Time2a | 63 | Set point command, short floating-point number with time tag CP56Time2a: High-precision timed commands, where accuracy is essential for system security. | Accuracy is essential for system security. |
48 | | C_BO_TA_1 | bitstring of 32 bits with time tag CP56Time2a | 64 | Bitstring of 32 bits with time tag CP56Time2a: A timestamped bitstring, which is vital for tracing the exact moment of a potential cyber attack. | Vital for tracing the exact moment of a potential cyber attack. |
49 | | M_EI_NA_1 | end of initialization | 70 | End of initialization: Marks the completion of a startup sequence, which if unexpected, could indicate a system reboot due to a cyber attack. | If unexpected, could indicate a system reboot due to a cyber attack. |
50 | | S_CH_NA_1 | authentication challenge | 81 | Authentication challenge: Part of a security handshake that can be monitored for signs of spoofing or replay attacks. | Can be monitored for signs of spoofing or replay attacks. |
51 | | S_RP_NA_1 | authentication reply | 82 | Authentication reply: The response in an authentication exchange, which should be verified for authenticity to prevent security breaches. | Should be verified for authenticity to prevent security breaches. |
52 | | S_AR_NA_1 | aggressive mode authentication request session key status request | 83 | Aggressive mode authentication request session key status request: A security protocol step that, if compromised, could lead to unauthorized access. | If compromised, could lead to unauthorized access. |
53 | | S_KR_NA_1 | session key status request | 84 | Session key status request: Requests for session key information that need to be secure to maintain communication integrity. | Need to be secure to maintain communication integrity. |
54 | | S_KS_NA_1 | session key status | 85 | Session key status: Provides the status of a session key, where unexpected changes could indicate key compromise or interception. | Unexpected changes could indicate key compromise or interception. |
55 | | S_KC_NA_1 | session key change | 86 | Session key change: Indicates a change in session keys, which should be monitored for unauthorized updates that could lead to data breaches. | Should be monitored for unauthorized updates that could lead to data breaches. |
56 | | S_ER_NA_1 | authentication error | 87 | Authentication error: Signals an authentication failure, which can be an indicator of attempted unauthorized access. | Can be an indicator of attempted unauthorized access. |
57 | | S_US_NA_1 | user status change | 90 | User status change: Reflects changes in user permissions or status, which should be scrutinized for unauthorized privilege escalation. | Should be scrutinized for unauthorized privilege escalation. |
58 | | S_UQ_NA_1 | update key change request | 91 | Update key change request: A request to change update keys, which must be protected against to prevent malware or unauthorized software updates. | Must be protected against to prevent malware or unauthorized software updates. |
59 | | S_UR_NA_1 | update key change reply | 92 | Update key change reply: The response to an update key change request, which should be confirmed as legitimate to prevent security compromises. | Should be confirmed as legitimate to prevent security compromises. |
60 | | S_UK_NA_1 | update key change symmetric | 93 | Update key change symmetric: Involves symmetric key changes, where unauthorized changes could lead to data interception or manipulation. | Unauthorized changes could lead to data interception or manipulation. |
61 | | S_UA_NA_1 | update key change asymmetric | 94 | Update key change asymmetric: Involves asymmetric key changes, critical for maintaining secure communications and preventing man-in-the-middle attacks. | Critical for preventing man-in-the-middle attacks. |
62 | | S_UC_NA_1 | update key change confirmation | 95 | Update key change confirmation: Confirms a key change, which should be validated to ensure that it's part of a legitimate security protocol. | Should be validated to ensure it's part of a legitimate security protocol. |
63 | | C_IC_NA_1 | interrogation command | 100 | Interrogation command: A request for device or system data, which if unauthorized, could be used for reconnaissance by an attacker. | If unauthorized, could be used for reconnaissance by an attacker. |
64 | | C_CI_NA_1 | counter interrogation command | 101 | Counter interrogation command: A command to query counter values, which should be monitored for unauthorized data collection. | Should be monitored for unauthorized data collection. |
65 | | C_RD_NA_1 | read command | 102 | Read command: Requests data from devices, and should be analyzed for unauthorized attempts to gain system information. | Should be analyzed for unauthorized attempts to gain system information. |
66 | | C_CS_NA_1 | clock synchronization command | 103 | Clock synchronization command: Ensures all devices are time-synchronized, which is crucial for maintaining the integrity of timed operations and logs. | Crucial for maintaining the integrity of timed operations and logs. |
67 | | C_RP_NA_1 | reset process command | 105 | Reset process command: Commands a process reset, which should be monitored to prevent malicious system restarts or disruptions. | Should be monitored to prevent malicious system restarts or disruptions. |
68 | | C_TS_TA_1 | test command with time tag CP56Time2a | 107 | Test command with time tag CP56Time2a: A timed test command, which if not part of regular maintenance, could indicate system probing by an attacker. | Could indicate system probing by an attacker if not part of regular maintenance. |
69 | | P_ME_NA_1 | parameter of measured value, normalized value | 110 | Parameter of measured value, normalized value: Sets a normalized measurement parameter, which should be secured against unauthorized adjustments. | Should be secured against unauthorized adjustments. |
70 | | P_ME_NB_1 | parameter of measured value, scaled value | 111 | Parameter of measured value, scaled value: Sets a scaled measurement parameter, where unexpected changes could indicate tampering. | Unexpected changes could indicate tampering. |
71 | | P_ME_NC_1 | parameter of measured value, short floating-point number | 112 | Parameter of measured value, short floating-point number: Sets a high-precision measurement parameter, which requires protection to maintain system accuracy. | Requires protection to maintain system accuracy. |
72 | | P_AC_NA_1 | parameter activation | 113 | Parameter activation: Activates a parameter setting, which should be monitored for unauthorized activations that could alter system behavior. | Unauthorized activations could alter system behavior and must be monitored. |
73 | | F_FR_NA_1 | file ready | 120 | File ready: Indicates a file is ready for transfer or processing, which should be verified for legitimacy to prevent the spread of malware. | Verification is necessary to prevent the spread of malware. |
74 | | F_SR_NA_1 | section ready | 121 | Section ready: Signals that a file section is ready, which needs to be secure to ensure the integrity of data transfers. | Security is needed to ensure the integrity of data transfers. |
75 | | F_SC_NA_1 | call directory, select file, call file, call section | 122 | Call directory, select file, call file, call section: Commands for file and directory operations, which if unauthorized, could lead to data leakage or manipulation. | Unauthorized commands could lead to data leakage or manipulation. |
76 | | F_LS_NA_1 | last section, last segment | 123 | Last section, last segment: Marks the end of a file or segment transfer, which should be checked for completion to prevent data corruption or interception. | Should be checked for completion to prevent data corruption or interception. |
77 | | F_AF_NA_1 | ack file, ack section | 124 | Ack file, ack section: Acknowledgment of file or section receipt, which should be verified to ensure data transfer integrity. | Verification is necessary to ensure data transfer integrity. |
78 | | F_SG_NA_1 | segment | 125 | Segment: Represents a file segment, where security is needed to prevent segment manipulation or unauthorized segment insertion. | Security is needed to prevent segment manipulation or unauthorized insertion. |
79 | | F_DR_TA_1 | directory | 126 | Directory: Provides directory listings, which should be protected to prevent unauthorized directory traversal or reconnaissance. | Should be protected to prevent unauthorized directory traversal or reconnaissance. |
80 | | F_SC_NB_1 | Query Log - Request archive file | 127 | Query Log - Request archive file: Requests for archived logs, which must be secured to prevent access to historical data that could be used in further attacks. | Must be secured to prevent access to historical data that could be used in further attacks. |
81 |
--------------------------------------------------------------------------------
/DhaeyerWolf/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | GNU GENERAL PUBLIC LICENSE
3 |
4 | Version 3, 29 June 2007
5 |
6 | Copyright © 2007 Free Software Foundation, Inc.
7 |
8 | Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
9 | Preamble
10 |
11 | The GNU General Public License is a free, copyleft license for software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.
14 |
15 | When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.
16 |
17 | To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.
18 |
19 | For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
20 |
21 | Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.
22 |
23 | For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.
24 |
25 | Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.
26 |
27 | Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.
28 |
29 | The precise terms and conditions for copying, distribution and modification follow.
30 | TERMS AND CONDITIONS
31 | 0. Definitions.
32 |
33 | “This License” refers to version 3 of the GNU General Public License.
34 |
35 | “Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
36 |
37 | “The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.
38 |
39 | To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.
40 |
41 | A “covered work” means either the unmodified Program or a work based on the Program.
42 |
43 | To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
44 |
45 | To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
46 |
47 | An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
48 | 1. Source Code.
49 |
50 | The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.
51 |
52 | A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
53 |
54 | The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.
55 |
56 | The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.
57 |
58 | The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
59 |
60 | The Corresponding Source for a work in source code form is that same work.
61 | 2. Basic Permissions.
62 |
63 | All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
64 |
65 | You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.
66 |
67 | Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
68 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
69 |
70 | No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
71 |
72 | When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.
73 | 4. Conveying Verbatim Copies.
74 |
75 | You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
76 |
77 | You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
78 | 5. Conveying Modified Source Versions.
79 |
80 | You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
81 |
82 | a) The work must carry prominent notices stating that you modified it, and giving a relevant date.
83 | b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”.
84 | c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.
85 | d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.
86 |
87 | A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.
88 | 6. Conveying Non-Source Forms.
89 |
90 | You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
91 |
92 | a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
93 | b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.
94 | c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.
95 | d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.
96 | e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.
97 |
98 | A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
99 |
100 | A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.
101 |
102 | “Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
103 |
104 | If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).
105 |
106 | The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
107 |
108 | Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
109 | 7. Additional Terms.
110 |
111 | “Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.
112 |
113 | When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
114 |
115 | Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
116 |
117 | a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
118 | b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or
119 | c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or
120 | d) Limiting the use for publicity purposes of names of licensors or authors of the material; or
121 | e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
122 | f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.
123 |
124 | All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.
125 |
126 | If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
127 |
128 | Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
129 | 8. Termination.
130 |
131 | You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
132 |
133 | However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
134 |
135 | Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
136 |
137 | Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
138 | 9. Acceptance Not Required for Having Copies.
139 |
140 | You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
141 | 10. Automatic Licensing of Downstream Recipients.
142 |
143 | Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
144 |
145 | An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.
146 |
147 | You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
148 | 11. Patents.
149 |
150 | A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”.
151 |
152 | A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.
153 |
154 | Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
155 |
156 | In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
157 |
158 | If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.
159 |
160 | If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
161 |
162 | A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
163 |
164 | Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
165 | 12. No Surrender of Others' Freedom.
166 |
167 | If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
168 | 13. Use with the GNU Affero General Public License.
169 |
170 | Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.
171 | 14. Revised Versions of this License.
172 |
173 | The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
174 |
175 | Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.
176 |
177 | If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
178 |
179 | Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
180 | 15. Disclaimer of Warranty.
181 |
182 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
183 | 16. Limitation of Liability.
184 |
185 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
186 | 17. Interpretation of Sections 15 and 16.
187 |
188 | If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
189 |
190 | END OF TERMS AND CONDITIONS
191 | How to Apply These Terms to Your New Programs
192 |
193 | If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
194 |
195 | To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
196 |
197 |
198 | Copyright (C)
199 |
200 | This program is free software: you can redistribute it and/or modify
201 | it under the terms of the GNU General Public License as published by
202 | the Free Software Foundation, either version 3 of the License, or
203 | (at your option) any later version.
204 |
205 | This program is distributed in the hope that it will be useful,
206 | but WITHOUT ANY WARRANTY; without even the implied warranty of
207 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
208 | GNU General Public License for more details.
209 |
210 | You should have received a copy of the GNU General Public License
211 | along with this program. If not, see .
212 |
213 | Also add information on how to contact you by electronic and paper mail.
214 |
215 | If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
216 |
217 | Copyright (C)
218 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
219 | This is free software, and you are welcome to redistribute it
220 | under certain conditions; type `show c' for details.
221 |
222 | The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”.
223 |
224 | You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see .
225 |
226 | The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read .
227 |
--------------------------------------------------------------------------------
/DhaeyerWolf/plugins/lua/melsoft_dissector.lua:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------------
2 | --
3 | -- Mitsubishi Electric MELSOFT Protocol Plug-in for Wireshark
4 | -- Specifically designed for the detection of CVE-2021-20594, CVE-2021-20597, CVE-2021-20598, CVE-2021-20599, NN-2021-0019
5 | --
6 | -- date : November, 15th 2023
7 | -- author : Andrea Palanca, Ivan Speziale
8 | -- contact : labs [ @ ] nozominetworks [ . ] com
9 | --
10 | --------------------------------------------------------------------------
11 |
12 | -- Helper functions
13 |
14 | function setDefault(t, d) -- Sets default value of table
15 | local mt = {__index = function () return d end}
16 | setmetatable(t, mt)
17 | end
18 |
19 | -- Base dissector
20 |
21 | proto_melsoft = Proto("melsoft","Mitsubishi Electric MELSOFT Protocol")
22 |
23 | base_protofields =
24 | {
25 | other_magic_bytes = ProtoField.uint16("melsoft.other.magic_bytes", "Magic Bytes", base.HEX)
26 | }
27 |
28 | proto_melsoft.fields = base_protofields
29 |
30 | req_resp_table = DissectorTable.new("melsoft.req_resp_table", "melsoft.req_resp_table", ftypes.UINT16, base.HEX, melsoft) -- Main children table containing only the relevant request and response protocols
31 |
32 | function proto_melsoft.dissector(buffer, pinfo, tree)
33 | if buffer:len() < 2 then
34 | return false
35 | end
36 | pinfo.cols.protocol = proto_melsoft.name
37 | local early_magic_bytes_value = buffer(0, 2):uint()
38 | local child = req_resp_table:get_dissector(early_magic_bytes_value)
39 | if child ~= nil then
40 | child(buffer, pinfo, tree)
41 | else
42 | local root = tree:add(proto_melsoft, buffer(), "Mitsubishi Electric MELSOFT Protocol")
43 | local subtree = root:add(proto_melsoft, buffer(), "Other MELSOFT Packet")
44 | pinfo.cols.info = "Other MELSOFT Packet"
45 | end
46 | end
47 |
48 | local tcp_port = DissectorTable.get("tcp.port")
49 | tcp_port:add(5007, proto_melsoft)
50 |
51 | -- Known magic bytes
52 |
53 | magic_bytes = {
54 | [0x5701] = "MELSOFT Request",
55 | [0xd700] = "MELSOFT Response"
56 | }
57 |
58 | -- Known command codes
59 |
60 | command_codes = {
61 | [0x0121] = "Open Initial",
62 | [0x0131] = "Username Login",
63 | [0x0132] = "Password Login",
64 | [0x0133] = "Read User Information from PLC A",
65 | [0x0134] = "Read User Information from PLC B",
66 | [0x0150] = "Safety Run Mode Read",
67 | [0x0410] = "Modify Value",
68 | [0x1001] = "Remote Control Run",
69 | [0x1002] = "Remote Control Stop",
70 | [0x1003] = "Remote Control Pause",
71 | [0x1006] = "Remote Reset Ex",
72 | [0x1120] = "Safety Run Mode Change",
73 | [0x1133] = "User Information Registration",
74 | [0x1859] = "File List Read",
75 | [0x1868] = "File Read",
76 | [0x1869] = "File Write"
77 | }
78 | setDefault(command_codes, "")
79 |
80 | -- Known Ethernet footer parameter types
81 |
82 | ethftr_parameter_types = {
83 | [0x42] = "Authorization Token",
84 | [0x81] = "Command Data CRC32",
85 | [0x82] = "Command Header Type + Command Data + Ethernet Footer CRC32"
86 | }
87 |
88 | -- Known access levels
89 |
90 | access_levels = {
91 | [0x0001] = "Administrators",
92 | [0x1000] = "Developers",
93 | [0x0800] = "Assistant Developers",
94 | [0x0100] = "Users"
95 | }
96 |
97 | -- Request dissector
98 |
99 | proto_melsoft_req = Proto("melsoft.req","Mitsubishi Electric MELSOFT Protocol - " .. magic_bytes[0x5701])
100 |
101 | req_protofields =
102 | {
103 | magic_bytes = ProtoField.uint16("melsoft.req.magic_bytes", "Magic Bytes", base.HEX, magic_bytes),
104 | sequence_number = ProtoField.uint8("melsoft.req.sequence_number", "Sequence Number", base.HEX),
105 | network_number = ProtoField.uint8("melsoft.req.network_number", "Network Number", base.HEX),
106 | unit_number = ProtoField.uint8("melsoft.req.unit_number", "Unit Number", base.HEX),
107 | io_number = ProtoField.uint16("melsoft.req.io_number", "I/O Number", base.HEX),
108 | cmdhdr_cmddata_ethftr_size = ProtoField.uint16("melsoft.req.cmdhdr_cmddata_ethftr_size", "Command Header + Command Data + Ethernet Footer Size", base.DEC),
109 | cmdhdr_type = ProtoField.uint8("melsoft.req.cmdhdr_type", "Command Header Type", base.HEX),
110 | cmdhdr_remaining_size = ProtoField.uint8("melsoft.req.cmdhdr_remaining_size", "Command Header Remaining Size", base.DEC),
111 | command_code = ProtoField.uint16("melsoft.req.command_code", "Command Code", base.HEX, command_codes),
112 | packet_reference = ProtoField.uint16("melsoft.req.packet_reference", "Packet Reference", base.HEX),
113 | cmddata_remaining_size = ProtoField.uint16("melsoft.req.cmddata_remaining_size", "Command Data Remaining Size", base.DEC),
114 | cmddata_payload = ProtoField.bytes("melsoft.req.cmddata_payload", "Payload"),
115 | ethftr_size = ProtoField.uint16("melsoft.req.ethftr_size", "Ethernet Footer Size", base.DEC),
116 | ethftr_no_of_parameters = ProtoField.uint8("melsoft.req.ethftr_no_of_parameters", "Number of Parameters", base.DEC),
117 | ethftr_parameter_type = ProtoField.uint8("melsoft.req.ethftr_parameter_type", "Parameter Type", base.HEX, ethftr_parameter_types),
118 | ethftr_parameter_size = ProtoField.uint8("melsoft.req.ethftr_parameter_size", "Parameter Size", base.DEC),
119 | ethftr_parameter_value = ProtoField.bytes("melsoft.req.ethftr_parameter_value", "Parameter Value")
120 | }
121 |
122 | proto_melsoft_req.fields = req_protofields
123 |
124 | req_fields =
125 | {
126 | command_code_field = Field.new("melsoft.req.command_code"),
127 | ethftr_no_of_parameters_field = Field.new("melsoft.req.ethftr_no_of_parameters")
128 | }
129 |
130 | req_experts =
131 | {
132 | request_with_authorization_token = ProtoExpert.new("melsoft.req.request_with_authorization_token.expert", "Request with authorization token - May be abused to exploit CVE-2021-20599", expert.group.SECURITY, expert.severity.NOTE)
133 | }
134 |
135 | proto_melsoft_req.experts = req_experts
136 |
137 | req_commands_table = DissectorTable.new("melsoft.req.req_commands_table", "melsoft.req.req_commands_table", ftypes.UINT16, base.HEX, melsoft_req) -- Children table for dissecting the various command codes in requests
138 |
139 | function proto_melsoft_req.dissector(buffer, pinfo, tree)
140 | local root = tree:add(proto_melsoft, buffer(), "Mitsubishi Electric MELSOFT Protocol")
141 | local req = root:add(proto_melsoft_req, buffer(), magic_bytes[0x5701])
142 | pinfo.cols.info = magic_bytes[0x5701]
143 | -- Ethernet header
144 | local ethernet_header = req:add(proto_melsoft_req, buffer(0, 0x15), "Ethernet Header")
145 | ethernet_header:add(req_protofields["magic_bytes"], buffer(0, 2))
146 | ethernet_header:add(req_protofields["sequence_number"], buffer(2, 1))
147 | ethernet_header:add(req_protofields["network_number"], buffer(9, 1))
148 | ethernet_header:add(req_protofields["unit_number"], buffer(0xa, 1))
149 | ethernet_header:add(req_protofields["io_number"], buffer(0xb, 2))
150 | ethernet_header:add_le(req_protofields["cmdhdr_cmddata_ethftr_size"], buffer(0x13, 2))
151 | -- Command header
152 | local command_header_starting_byte = 0x15
153 | local command_header = req:add(proto_melsoft_req, buffer(command_header_starting_byte, 0x18), "Command Header")
154 | command_header:add(req_protofields["cmdhdr_type"], buffer(command_header_starting_byte+0, 1))
155 | command_header:add(req_protofields["cmdhdr_remaining_size"], buffer(command_header_starting_byte+2, 1))
156 | -- Command data
157 | local cmddata_starting_byte = 0x15+0x18
158 | local early_cmddata_remaining_size_value = buffer(cmddata_starting_byte+4, 2):le_uint()
159 | local command_data = req:add(proto_melsoft_req, buffer(cmddata_starting_byte, 6+early_cmddata_remaining_size_value), "Command Data")
160 | command_data:add(req_protofields["command_code"], buffer(cmddata_starting_byte, 2))
161 | command_data:add_le(req_protofields["packet_reference"], buffer(cmddata_starting_byte+2, 2))
162 | command_data:add_le(req_protofields["cmddata_remaining_size"], buffer(cmddata_starting_byte+4, 2))
163 | local command_code_value = req_fields["command_code_field"]()()
164 | pinfo.cols.info = magic_bytes[0x5701] .. " - 0x" .. string.format("%X", command_code_value) .. " " .. command_codes[command_code_value]
165 | local child = req_commands_table:get_dissector(command_code_value)
166 | if child ~= nil then
167 | child(buffer, pinfo, command_data)
168 | else
169 | command_data:add(req_protofields["cmddata_payload"], buffer(cmddata_starting_byte+6, early_cmddata_remaining_size_value))
170 | end
171 | -- Ethernet Footer
172 | local ethernet_footer_starting_byte = 0x15+0x18+6+early_cmddata_remaining_size_value
173 | local ethernet_footer = req:add(proto_melsoft_req, buffer(ethernet_footer_starting_byte), "Ethernet Footer")
174 | ethernet_footer:add_le(req_protofields["ethftr_size"], buffer(ethernet_footer_starting_byte, 2))
175 | ethernet_footer:add(req_protofields["ethftr_no_of_parameters"], buffer(ethernet_footer_starting_byte+2, 1))
176 | local ethftr_no_of_parameters_value = req_fields["ethftr_no_of_parameters_field"]()()
177 | local parameter_sizes = {}
178 | for i=0,ethftr_no_of_parameters_value-1
179 | do
180 | ethernet_footer:add(req_protofields["ethftr_parameter_type"], buffer(ethernet_footer_starting_byte+3+i*2, 1))
181 | if buffer(ethernet_footer_starting_byte+3+i*2, 1):uint() == 0x42 then
182 | ethernet_footer:add_proto_expert_info(req_experts["request_with_authorization_token"])
183 | end
184 | ethernet_footer:add(req_protofields["ethftr_parameter_size"], buffer(ethernet_footer_starting_byte+3+i*2+1, 1))
185 | table.insert(parameter_sizes, buffer(ethernet_footer_starting_byte+3+i*2+1, 1):uint())
186 | end
187 | for i=1,ethftr_no_of_parameters_value -- Index starts at 1 to correctly access table values (in Lua, first element in a table has index 1)
188 | do
189 | local bytes_read = 0
190 | for j=1,i-1
191 | do
192 | bytes_read = bytes_read + parameter_sizes[j]
193 | end
194 | ethernet_footer:add(req_protofields["ethftr_parameter_value"], buffer(ethernet_footer_starting_byte+3+ethftr_no_of_parameters_value*2+bytes_read, parameter_sizes[i]))
195 | end
196 | end
197 |
198 | DissectorTable.get("melsoft.req_resp_table"):add(0x5701, proto_melsoft_req)
199 |
200 | -- Response dissector
201 |
202 | proto_melsoft_resp = Proto("melsoft.resp","Mitsubishi Electric MELSOFT Protocol - " .. magic_bytes[0xd700])
203 |
204 | resp_protofields =
205 | {
206 | magic_bytes = ProtoField.uint16("melsoft.resp.magic_bytes", "Magic Bytes", base.HEX, magic_bytes),
207 | sequence_number = ProtoField.uint8("melsoft.resp.sequence_number", "Sequence Number", base.HEX),
208 | cmdhdr_cmddata_ethftr_size = ProtoField.uint16("melsoft.resp.cmdhdr_cmddata_ethftr_size", "Command Header + Command Data + Ethernet Footer Size", base.DEC),
209 | cmdhdr_type = ProtoField.uint8("melsoft.resp.cmdhdr_type", "Command Header Type", base.HEX),
210 | cmdhdr_remaining_size = ProtoField.uint8("melsoft.resp.cmdhdr_remaining_size", "Command Header Remaining Size", base.DEC),
211 | status = ProtoField.uint16("melsoft.resp.status", "Status", base.HEX),
212 | command_code = ProtoField.uint16("melsoft.resp.command_code", "Command Code", base.HEX, command_codes),
213 | packet_reference = ProtoField.uint16("melsoft.resp.packet_reference", "Packet Reference", base.HEX),
214 | cmddata_remaining_size = ProtoField.uint16("melsoft.resp.cmddata_remaining_size", "Command Data Remaining Size", base.DEC),
215 | cmddata_payload = ProtoField.bytes("melsoft.resp.cmddata_payload", "Payload"),
216 | ethftr_size = ProtoField.uint16("melsoft.resp.ethftr_size", "Ethernet Footer Size", base.DEC),
217 | ethftr_no_of_parameters = ProtoField.uint8("melsoft.resp.ethftr_no_of_parameters", "Number of Parameters", base.DEC),
218 | ethftr_parameter_type = ProtoField.uint8("melsoft.resp.ethftr_parameter_type", "Parameter Type", base.HEX, ethftr_parameter_types),
219 | ethftr_parameter_size = ProtoField.uint8("melsoft.resp.ethftr_parameter_size", "Parameter Size", base.DEC),
220 | ethftr_parameter_value = ProtoField.bytes("melsoft.resp.ethftr_parameter_value", "Parameter Value")
221 | }
222 |
223 | proto_melsoft_resp.fields = resp_protofields
224 |
225 | resp_fields =
226 | {
227 | command_code_field = Field.new("melsoft.resp.command_code"),
228 | ethftr_no_of_parameters_field = Field.new("melsoft.resp.ethftr_no_of_parameters")
229 | }
230 |
231 | resp_commands_table = DissectorTable.new("melsoft.resp.resp_commands_table", "melsoft.resp.resp_commands_table", ftypes.UINT16, base.HEX, melsoft_resp) -- Children table for dissecting the various command codes in responses
232 |
233 | function proto_melsoft_resp.dissector(buffer, pinfo, tree)
234 | local root = tree:add(proto_melsoft, buffer(), "Mitsubishi Electric MELSOFT Protocol")
235 | local resp = root:add(proto_melsoft_resp, buffer(), magic_bytes[0xd700])
236 | pinfo.cols.info = magic_bytes[0xd700]
237 | -- Ethernet header
238 | local ethernet_header = resp:add(proto_melsoft_resp, buffer(0, 0x15), "Ethernet Header")
239 | ethernet_header:add(resp_protofields["magic_bytes"], buffer(0, 2))
240 | ethernet_header:add(resp_protofields["sequence_number"], buffer(2, 1))
241 | ethernet_header:add_le(resp_protofields["cmdhdr_cmddata_ethftr_size"], buffer(0x13, 2))
242 | -- Command header
243 | local command_header_starting_byte = 0x15
244 | local command_header = resp:add(proto_melsoft_resp, buffer(command_header_starting_byte, 0x1a), "Command Header")
245 | command_header:add(resp_protofields["cmdhdr_type"], buffer(command_header_starting_byte+0, 1))
246 | command_header:add(resp_protofields["cmdhdr_remaining_size"], buffer(command_header_starting_byte+2, 1))
247 | command_header:add(resp_protofields["status"], buffer(command_header_starting_byte+4, 2))
248 | -- Command data
249 | local cmddata_starting_byte = 0x15+0x1a
250 | local early_cmddata_remaining_size_value = buffer(cmddata_starting_byte+4, 2):le_uint()
251 | local command_data = resp:add(proto_melsoft_resp, buffer(cmddata_starting_byte, 6+early_cmddata_remaining_size_value), "Command Data")
252 | command_data:add(resp_protofields["command_code"], buffer(cmddata_starting_byte, 2))
253 | command_data:add_le(resp_protofields["packet_reference"], buffer(cmddata_starting_byte+2, 2))
254 | command_data:add_le(resp_protofields["cmddata_remaining_size"], buffer(cmddata_starting_byte+4, 2))
255 | local command_code_value = resp_fields["command_code_field"]()()
256 | pinfo.cols.info = magic_bytes[0xd700] .. " - 0x" .. string.format("%X", command_code_value) .. " " .. command_codes[command_code_value]
257 | local child = resp_commands_table:get_dissector(command_code_value)
258 | if child ~= nil then
259 | child(buffer, pinfo, command_data)
260 | else
261 | command_data:add(resp_protofields["cmddata_payload"], buffer(cmddata_starting_byte+6, early_cmddata_remaining_size_value))
262 | end
263 | -- Ethernet Footer
264 | local ethernet_footer_starting_byte = 0x15+0x1a+6+early_cmddata_remaining_size_value
265 | local ethernet_footer = resp:add(proto_melsoft_resp, buffer(ethernet_footer_starting_byte), "Ethernet Footer")
266 | ethernet_footer:add_le(resp_protofields["ethftr_size"], buffer(ethernet_footer_starting_byte, 2))
267 | ethernet_footer:add(resp_protofields["ethftr_no_of_parameters"], buffer(ethernet_footer_starting_byte+2, 1))
268 | local ethftr_no_of_parameters_value = resp_fields["ethftr_no_of_parameters_field"]()()
269 | local parameter_sizes = {}
270 | for i=0,ethftr_no_of_parameters_value-1
271 | do
272 | ethernet_footer:add(resp_protofields["ethftr_parameter_type"], buffer(ethernet_footer_starting_byte+3+i*2, 1))
273 | ethernet_footer:add(resp_protofields["ethftr_parameter_size"], buffer(ethernet_footer_starting_byte+3+i*2+1, 1))
274 | table.insert(parameter_sizes, buffer(ethernet_footer_starting_byte+3+i*2+1, 1):uint())
275 | end
276 | for i=1,ethftr_no_of_parameters_value -- Index starts at 1 to correctly access table values (in Lua, first element in a table has index 1)
277 | do
278 | local bytes_read = 0
279 | for j=1,i-1
280 | do
281 | bytes_read = bytes_read + parameter_sizes[j]
282 | end
283 | ethernet_footer:add(resp_protofields["ethftr_parameter_value"], buffer(ethernet_footer_starting_byte+3+ethftr_no_of_parameters_value*2+bytes_read, parameter_sizes[i]))
284 | end
285 | end
286 |
287 | DissectorTable.get("melsoft.req_resp_table"):add(0xd700, proto_melsoft_resp)
288 |
289 | -- Command data dissectors. Currently, only dissectors relevant for the detection of CVE-2021-20594, CVE-2021-20597, CVE-2021-20598, NN-2021-0019 are supported
290 |
291 | -- Username login
292 |
293 | proto_melsoft_req_username_login = Proto("melsoft.req.username_login","Mitsubishi Electric MELSOFT Protocol - " .. magic_bytes[0x5701] .. " - Username Login")
294 |
295 | req_username_login_protofields =
296 | {
297 | username = ProtoField.string("melsoft.req.username_login.username", "Username", base.UNICODE),
298 | }
299 |
300 | proto_melsoft_req_username_login.fields = req_username_login_protofields
301 |
302 | req_username_login_experts =
303 | {
304 | username_login_request = ProtoExpert.new("melsoft.req.username_login.username_login_request.expert", "Username Login request - May be legitimate or an attempt to exploit CVE-2021-20594", expert.group.SECURITY, expert.severity.NOTE)
305 | }
306 |
307 | proto_melsoft_req_username_login.experts = req_username_login_experts
308 |
309 | function proto_melsoft_req_username_login.dissector(buffer, pinfo, tree)
310 | local cmddata_starting_byte = 0x15+0x18
311 | local cmddata_remaining_size_value = buffer(cmddata_starting_byte+4, 2):le_uint()
312 | local username_login_request = tree:add(proto_melsoft_req_username_login, buffer(cmddata_starting_byte+6, cmddata_remaining_size_value), "Username Login Request")
313 | username_login_request:add(req_username_login_protofields["username"], buffer(cmddata_starting_byte+6, 0x28), buffer(cmddata_starting_byte+6, 0x28):le_ustring())
314 | username_login_request:add_proto_expert_info(req_username_login_experts["username_login_request"])
315 | end
316 |
317 | DissectorTable.get("melsoft.req.req_commands_table"):add(0x0131, proto_melsoft_req_username_login)
318 |
319 | proto_melsoft_resp_username_login = Proto("melsoft.resp.username_login","Mitsubishi Electric MELSOFT Protocol - " .. magic_bytes[0xd700] .. " - Username Login")
320 |
321 | resp_username_login_protofields =
322 | {
323 | username_token = ProtoField.bytes("melsoft.resp.username_login.username_token", "Username Token"),
324 | payload = ProtoField.bytes("melsoft.resp.username_login.payload", "Payload")
325 | }
326 |
327 | proto_melsoft_resp_username_login.fields = resp_username_login_protofields
328 |
329 | resp_username_login_experts =
330 | {
331 | username_login_correct_response = ProtoExpert.new("melsoft.resp.username_login.username_login_correct_response.expert", "Username Login response (correct username) - May be legitimate or an attempt to exploit CVE-2021-20594", expert.group.SECURITY, expert.severity.NOTE),
332 | username_login_wrong_response = ProtoExpert.new("melsoft.resp.username_login.username_login_wrong_response.expert", "Username Login response (wrong username) - May be an attempt to exploit CVE-2021-20594", expert.group.SECURITY, expert.severity.WARN)
333 | }
334 |
335 | proto_melsoft_resp_username_login.experts = resp_username_login_experts
336 |
337 | function proto_melsoft_resp_username_login.dissector(buffer, pinfo, tree)
338 | local command_header_starting_byte = 0x15
339 | local status_value = buffer(command_header_starting_byte+4, 2):uint()
340 | local cmddata_starting_byte = 0x15+0x1a
341 | local cmddata_remaining_size_value = buffer(cmddata_starting_byte+4, 2):le_uint()
342 | local username_login_response = tree:add(proto_melsoft_resp_username_login, buffer(cmddata_starting_byte+6, cmddata_remaining_size_value), "Username Login Response")
343 | if status_value == 0 then
344 | username_login_response:add(resp_username_login_protofields["username_token"], buffer(cmddata_starting_byte+6, 0x10))
345 | username_login_response:add_proto_expert_info(resp_username_login_experts["username_login_correct_response"])
346 | else
347 | username_login_response:add(resp_username_login_protofields["payload"], buffer(cmddata_starting_byte+6, cmddata_remaining_size_value))
348 | username_login_response:add_proto_expert_info(resp_username_login_experts["username_login_wrong_response"])
349 | end
350 | end
351 |
352 | DissectorTable.get("melsoft.resp.resp_commands_table"):add(0x0131, proto_melsoft_resp_username_login)
353 |
354 | -- Password login
355 |
356 | proto_melsoft_req_password_login = Proto("melsoft.req.password_login","Mitsubishi Electric MELSOFT Protocol - " .. magic_bytes[0x5701] .. " - Password Login")
357 |
358 | req_password_login_protofields =
359 | {
360 | username_token = ProtoField.bytes("melsoft.req.password_login.username_token", "Username Token"),
361 | password = ProtoField.bytes("melsoft.req.password_login.password", "SHA256(Username Token + SHA256(Password))")
362 | }
363 |
364 | proto_melsoft_req_password_login.fields = req_password_login_protofields
365 |
366 | req_password_login_experts =
367 | {
368 | password_login_request = ProtoExpert.new("melsoft.req.password_login.password_login_request.expert", "Password Login request - May be legitimate or an attempt to exploit CVE-2021-20598", expert.group.SECURITY, expert.severity.NOTE)
369 | }
370 |
371 | proto_melsoft_req_password_login.experts = req_password_login_experts
372 |
373 | function proto_melsoft_req_password_login.dissector(buffer, pinfo, tree)
374 | local cmddata_starting_byte = 0x15+0x18
375 | local cmddata_remaining_size_value = buffer(cmddata_starting_byte+4, 2):le_uint()
376 | local password_login_request = tree:add(proto_melsoft_req_password_login, buffer(cmddata_starting_byte+6, cmddata_remaining_size_value), "Password Login Request")
377 | password_login_request:add(req_password_login_protofields["username_token"], buffer(cmddata_starting_byte+6, 0x10))
378 | password_login_request:add(req_password_login_protofields["password"], buffer(cmddata_starting_byte+0x16, 0x20))
379 | password_login_request:add_proto_expert_info(req_password_login_experts["password_login_request"])
380 | end
381 |
382 | DissectorTable.get("melsoft.req.req_commands_table"):add(0x0132, proto_melsoft_req_password_login)
383 |
384 | proto_melsoft_resp_password_login = Proto("melsoft.resp.password_login","Mitsubishi Electric MELSOFT Protocol - " .. magic_bytes[0xd700] .. " - Password Login")
385 |
386 | resp_password_login_protofields =
387 | {
388 | password_token = ProtoField.bytes("melsoft.resp.password_login.password_token", "Password Token"),
389 | sessionid_prefix = ProtoField.uint16("melsoft.resp.password_login.sessionid_prefix", "SessionID Prefix", base.HEX),
390 | payload = ProtoField.bytes("melsoft.resp.password_login.payload", "Payload")
391 | }
392 |
393 | proto_melsoft_resp_password_login.fields = resp_password_login_protofields
394 |
395 | resp_password_login_experts =
396 | {
397 | password_login_correct_response = ProtoExpert.new("melsoft.resp.password_login.password_login_correct_response.expert", "Password Login response (correct password) - May be legitimate or an attempt to exploit CVE-2021-20598", expert.group.SECURITY, expert.severity.NOTE),
398 | password_login_wrong_response = ProtoExpert.new("melsoft.resp.password_login.password_login_wrong_response.expert", "Password Login response (wrong password) - May be an attempt to exploit CVE-2021-20598", expert.group.SECURITY, expert.severity.WARN),
399 | password_login_wrong_response_plc_locked = ProtoExpert.new("melsoft.resp.password_login.password_login_wrong_response_plc_locked.expert", "Password Login response (wrong password and PLC locked) - Likely an attempt to exploit CVE-2021-20598", expert.group.SECURITY, expert.severity.ERROR)
400 | }
401 |
402 | proto_melsoft_resp_password_login.experts = resp_password_login_experts
403 |
404 | function proto_melsoft_resp_password_login.dissector(buffer, pinfo, tree)
405 | local command_header_starting_byte = 0x15
406 | local status_value = buffer(command_header_starting_byte+4, 2):uint()
407 | local cmddata_starting_byte = 0x15+0x1a
408 | local cmddata_remaining_size_value = buffer(cmddata_starting_byte+4, 2):le_uint()
409 | local password_login_response = tree:add(proto_melsoft_resp_password_login, buffer(cmddata_starting_byte+6, cmddata_remaining_size_value), "Password Login Response")
410 | if status_value == 0 then
411 | password_login_response:add(resp_password_login_protofields["password_token"], buffer(cmddata_starting_byte+6, 0x10))
412 | password_login_response:add_le(resp_password_login_protofields["sessionid_prefix"], buffer(cmddata_starting_byte+0x26, 2))
413 | password_login_response:add_proto_expert_info(resp_password_login_experts["password_login_correct_response"])
414 | elseif (status_value == 0x844 or status_value == 0x944 or status_value == 0xa44) then
415 | password_login_response:add(resp_password_login_protofields["payload"], buffer(cmddata_starting_byte+6, cmddata_remaining_size_value))
416 | password_login_response:add_proto_expert_info(resp_password_login_experts["password_login_wrong_response"])
417 | else
418 | password_login_response:add(resp_password_login_protofields["payload"], buffer(cmddata_starting_byte+6, cmddata_remaining_size_value))
419 | password_login_response:add_proto_expert_info(resp_password_login_experts["password_login_wrong_response_plc_locked"])
420 | end
421 | end
422 |
423 | DissectorTable.get("melsoft.resp.resp_commands_table"):add(0x0132, proto_melsoft_resp_password_login)
424 |
425 | -- Read User Information from PLC B
426 |
427 | proto_melsoft_req_read_user_information_from_plc_b = Proto("melsoft.req.read_user_information_from_plc_b","Mitsubishi Electric MELSOFT Protocol - " .. magic_bytes[0x5701] .. " - Read User Information from PLC B")
428 |
429 | req_read_user_information_from_plc_b_protofields =
430 | {
431 | payload = ProtoField.bytes("melsoft.req.read_user_information_from_plc_b.payload", "Payload"),
432 | }
433 |
434 | proto_melsoft_req_read_user_information_from_plc_b.fields = req_read_user_information_from_plc_b_protofields
435 |
436 | req_read_user_information_from_plc_b_experts =
437 | {
438 | read_user_information_from_plc_b_request = ProtoExpert.new("melsoft.req.read_user_information_from_plc_b.read_user_information_from_plc_b_request.expert", "Read User Information from PLC B request - May be legitimate or an attempt to exploit NN-2021-0019", expert.group.SECURITY, expert.severity.NOTE)
439 | }
440 |
441 | proto_melsoft_req_read_user_information_from_plc_b.experts = req_read_user_information_from_plc_b_experts
442 |
443 | function proto_melsoft_req_read_user_information_from_plc_b.dissector(buffer, pinfo, tree)
444 | local cmddata_starting_byte = 0x15+0x18
445 | local cmddata_remaining_size_value = buffer(cmddata_starting_byte+4, 2):le_uint()
446 | local read_user_information_from_plc_b_request = tree:add(proto_melsoft_req_read_user_information_from_plc_b, buffer(cmddata_starting_byte+6, cmddata_remaining_size_value), "Read User Information from PLC B Request")
447 | read_user_information_from_plc_b_request:add(req_read_user_information_from_plc_b_protofields["payload"], buffer(cmddata_starting_byte+6, cmddata_remaining_size_value))
448 | read_user_information_from_plc_b_request:add_proto_expert_info(req_read_user_information_from_plc_b_experts["read_user_information_from_plc_b_request"])
449 | end
450 |
451 | DissectorTable.get("melsoft.req.req_commands_table"):add(0x0134, proto_melsoft_req_read_user_information_from_plc_b)
452 |
453 | proto_melsoft_resp_read_user_information_from_plc_b = Proto("melsoft.resp.read_user_information_from_plc_b","Mitsubishi Electric MELSOFT Protocol - " .. magic_bytes[0xd700] .. " - Read User Information from PLC B")
454 |
455 | resp_read_user_information_from_plc_b_protofields =
456 | {
457 | username = ProtoField.string("melsoft.resp.read_user_information_from_plc_b.username", "Username", base.UNICODE),
458 | password = ProtoField.bytes("melsoft.resp.read_user_information_from_plc_b.password", "SHA256(Password)"),
459 | access_level = ProtoField.uint16("melsoft.resp.read_user_information_from_plc_b.access_level", "Access Level", base.HEX, access_levels),
460 | payload = ProtoField.bytes("melsoft.resp.read_user_information_from_plc_b.payload", "Payload")
461 | }
462 |
463 | proto_melsoft_resp_read_user_information_from_plc_b.fields = resp_read_user_information_from_plc_b_protofields
464 |
465 | resp_read_user_information_from_plc_b_experts =
466 | {
467 | read_user_information_from_plc_b_correct_response = ProtoExpert.new("melsoft.resp.read_user_information_from_plc_b.read_user_information_from_plc_b_correct_response.expert", "Read User Information from PLC B response - May be legitimate or an attempt to exploit NN-2021-0019", expert.group.SECURITY, expert.severity.NOTE)
468 | }
469 |
470 | proto_melsoft_resp_read_user_information_from_plc_b.experts = resp_read_user_information_from_plc_b_experts
471 |
472 | function proto_melsoft_resp_read_user_information_from_plc_b.dissector(buffer, pinfo, tree)
473 | local command_header_starting_byte = 0x15
474 | local status_value = buffer(command_header_starting_byte+4, 2):uint()
475 | local cmddata_starting_byte = 0x15+0x1a
476 | local cmddata_remaining_size_value = buffer(cmddata_starting_byte+4, 2):le_uint()
477 | local read_user_information_from_plc_b_response = tree:add(proto_melsoft_resp_read_user_information_from_plc_b, buffer(cmddata_starting_byte+6, cmddata_remaining_size_value), "Read User Information from PLC B Response")
478 | if status_value == 0 then
479 | local i=0
480 | while i < cmddata_remaining_size_value-0x4A do
481 | read_user_information_from_plc_b_response:add(resp_read_user_information_from_plc_b_protofields["username"], buffer(cmddata_starting_byte+6+i, 0x28), buffer(cmddata_starting_byte+6+i, 0x28):le_ustring())
482 | read_user_information_from_plc_b_response:add(resp_read_user_information_from_plc_b_protofields["password"], buffer(cmddata_starting_byte+0x2E+i, 0x20))
483 | read_user_information_from_plc_b_response:add(resp_read_user_information_from_plc_b_protofields["access_level"], buffer(cmddata_starting_byte+0x4E+i, 2))
484 | i = i+0x4A
485 | end
486 | read_user_information_from_plc_b_response:add_proto_expert_info(resp_read_user_information_from_plc_b_experts["read_user_information_from_plc_b_correct_response"])
487 | else
488 | read_user_information_from_plc_b_response:add(resp_read_user_information_from_plc_b_protofields["payload"], buffer(cmddata_starting_byte+6, cmddata_remaining_size_value))
489 | end
490 | end
491 |
492 | DissectorTable.get("melsoft.resp.resp_commands_table"):add(0x0134, proto_melsoft_resp_read_user_information_from_plc_b)
493 |
494 | -- User Information Registration
495 |
496 | proto_melsoft_req_user_information_registration = Proto("melsoft.req.user_information_registration","Mitsubishi Electric MELSOFT Protocol - " .. magic_bytes[0x5701] .. " - User Information Registration")
497 |
498 | req_user_information_registration_protofields =
499 | {
500 | no_of_users = ProtoField.uint16("melsoft.req.user_information_registration.no_of_users", "Number of Users", base.DEC),
501 | username = ProtoField.string("melsoft.req.user_information_registration.username", "Username", base.UNICODE),
502 | password = ProtoField.bytes("melsoft.req.user_information_registration.password", "SHA256(Password)"),
503 | access_level = ProtoField.uint16("melsoft.req.user_information_registration.access_level", "Access Level", base.HEX, access_levels)
504 | }
505 |
506 | proto_melsoft_req_user_information_registration.fields = req_user_information_registration_protofields
507 |
508 | req_user_information_registration_fields =
509 | {
510 | no_of_users_field = Field.new("melsoft.req.user_information_registration.no_of_users")
511 | }
512 |
513 | req_user_information_registration_experts =
514 | {
515 | user_information_registration_request = ProtoExpert.new("melsoft.req.user_information_registration.user_information_registration_request.expert", "User Information Registration request - May be abused to exploit CVE-2021-20597", expert.group.SECURITY, expert.severity.NOTE)
516 | }
517 |
518 | proto_melsoft_req_user_information_registration.experts = req_user_information_registration_experts
519 |
520 | function proto_melsoft_req_user_information_registration.dissector(buffer, pinfo, tree)
521 | local cmddata_starting_byte = 0x15+0x18
522 | local cmddata_remaining_size_value = buffer(cmddata_starting_byte+4, 2):le_uint()
523 | local user_information_registration_request = tree:add(proto_melsoft_req_user_information_registration, buffer(cmddata_starting_byte+6, cmddata_remaining_size_value), "User Information Registration Request")
524 | user_information_registration_request:add_le(req_user_information_registration_protofields["no_of_users"], buffer(cmddata_starting_byte+8, 2))
525 | local no_of_users_value = req_user_information_registration_fields["no_of_users_field"]()()
526 | for i=0,no_of_users_value-1
527 | do
528 | user_information_registration_request:add(req_user_information_registration_protofields["username"], buffer(cmddata_starting_byte+0xA+i*0x4A, 0x28), buffer(cmddata_starting_byte+0xA+i*0x4A, 0x28):le_ustring())
529 | user_information_registration_request:add(req_user_information_registration_protofields["password"], buffer(cmddata_starting_byte+0x32+i*0x4A, 0x20))
530 | user_information_registration_request:add(req_user_information_registration_protofields["access_level"], buffer(cmddata_starting_byte+0x52+i*0x4A, 2))
531 | end
532 | user_information_registration_request:add_proto_expert_info(req_user_information_registration_experts["user_information_registration_request"])
533 | end
534 |
535 | DissectorTable.get("melsoft.req.req_commands_table"):add(0x1133, proto_melsoft_req_user_information_registration)
536 |
537 | proto_melsoft_resp_user_information_registration = Proto("melsoft.resp.user_information_registration","Mitsubishi Electric MELSOFT Protocol - " .. magic_bytes[0xd700] .. " - User Information Registration")
538 |
539 | resp_user_information_registration_protofields =
540 | {
541 | payload = ProtoField.bytes("melsoft.resp.user_information_registration.payload", "Payload")
542 | }
543 |
544 | proto_melsoft_resp_user_information_registration.fields = resp_user_information_registration_protofields
545 |
546 | function proto_melsoft_resp_user_information_registration.dissector(buffer, pinfo, tree)
547 | local command_header_starting_byte = 0x15
548 | local status_value = buffer(command_header_starting_byte+4, 2):uint()
549 | local cmddata_starting_byte = 0x15+0x1a
550 | local cmddata_remaining_size_value = buffer(cmddata_starting_byte+4, 2):le_uint()
551 | local user_information_registration_response = tree:add(proto_melsoft_resp_user_information_registration, buffer(cmddata_starting_byte+6, cmddata_remaining_size_value), "User Information Registration Response")
552 | user_information_registration_response:add(resp_user_information_registration_protofields["payload"], buffer(cmddata_starting_byte+6, cmddata_remaining_size_value))
553 | end
554 |
555 | DissectorTable.get("melsoft.resp.resp_commands_table"):add(0x1133, proto_melsoft_resp_user_information_registration)
--------------------------------------------------------------------------------