├── README.md ├── cr3-fingerprint.nse ├── melsecq-discover.nse ├── melsecq-discover-udp.nse ├── cspv4-info.nse ├── proconos-info.nse ├── codesys-v2-discover.nse ├── atg-info.nse ├── pcworx-info.nse ├── iec-identify.nse ├── omronudp-info.nse ├── omrontcp-info.nse ├── dnp3-info.nse ├── fox-info.nse ├── s7-enumerate.nse ├── modicon-info.nse ├── BACnet-discover-enumerate.nse └── enip-enumerate.nse /README.md: -------------------------------------------------------------------------------- 1 | # ICS-Protocal-Detect-Nmap-Script 2 | Some nmap scripts to detetct the infomations of the different ICS 3 | 4 | Here are 16 main ics protocal scan-scripts include Modbus, S7 and so on. 5 | 6 | 1. s7-enumerate.nse Simatic S7 102 7 | 2. modicon-info.nse Schneider Electric Modicon(Modbus) 502 8 | 3. cr3-fingerprint.nse Crimson V3 789 9 | 4. codesys-v2-discover.nse 3S-Smart Software 1200 or 2455 10 | 5. fox-info.nse Niagara Fox 1911 11 | 6. pcworx-info.nse Pcworx 1962 12 | 7. cspv4-info.nse CSPV4 on AB PLC5 systems 2222 13 | 8. iec-identify.nse IEC 60870-5-104 2404 14 | 9. melsecq-discover.ns MELSEC-Q 5007 15 | 10. omronudp-info.nse Omron 9600 16 | 11. atg-info.nse Guardian AST Automatic Tank Gauge 10001 17 | 12. dnp3-info.nse DNP3 20000 18 | 13. procoos-info.nse ProConOs 20547 19 | 14. enip-enumerate.nse Rockwell Automation EtherNet/IP 44818 20 | 15. BACnet-discover-enumerate.nse BACnet 47808 21 | 16. melsecq-discover-udp.nse MELSEC-Q(UDP) 5007 22 | 17. modbus-discover.nse Modbus 502 23 | -------------------------------------------------------------------------------- /cr3-fingerprint.nse: -------------------------------------------------------------------------------- 1 | description = "Fingerprints Red Lion HMI devices" 2 | author = "Thought Leader" 3 | email_address = "thoughtleader@internetofallthethings.com" 4 | license = "TO-ILL" 5 | categories = {"version","discovery"} 6 | 7 | stdnse = require "stdnse" 8 | 9 | -- Perform discovery using Red Lion Crimson V3 Protocol 10 | 11 | -- this method should expose a user configuration 12 | portrule = function(host, port) 13 | return port.number == 789 14 | end 15 | 16 | action = function(host, port) 17 | local client = nmap.new_socket() 18 | local catch = function() 19 | client:close() 20 | end 21 | 22 | local try = nmap.new_try(catch) 23 | 24 | -- first fingerprint gets the manufacturer info 25 | try(client:connect(host.ip, 789)) 26 | 27 | local localip, loaclport, remoteip, remoteport = 28 | try(client:get_info()) 29 | 30 | local probe_manufacturer = string.char(0x00,0x04,0x01,0x2b,0x1b,0x00) 31 | try(client:send(probe_manufacturer)) 32 | resp = try(client:receive()) 33 | 34 | if string.len(resp) > 2 then 35 | -- return the result, skipping the CR3 header and omitting the trailing null 36 | resp_string = "\nManufacturer: " .. string.sub(resp, 7, -2) 37 | end 38 | 39 | try(client:close()) 40 | 41 | -- second fingerprint gets the model information 42 | try(client:connect(host.ip, 789)) 43 | 44 | local localip, loaclport, remoteip, remoteport = 45 | try(client:get_info()) 46 | 47 | local probe_manufacturer = string.char(0x00,0x04,0x01,0x2a,0x1a,0x00) 48 | try(client:send(probe_manufacturer)) 49 | resp = try(client:receive()) 50 | 51 | if string.len(resp) > 2 then 52 | -- return the result, skipping the CR3 header and omitting the trailing null 53 | resp_string = resp_string .. "\nModel: " .. string.sub(resp, 7, -2) .. "\n" 54 | end 55 | 56 | try(client:close()) 57 | 58 | return resp_string 59 | 60 | end 61 | -------------------------------------------------------------------------------- /melsecq-discover.nse: -------------------------------------------------------------------------------- 1 | -- Nmap Scripting Engine 2 | -- required packages for this script 3 | -- 4 | -- ICS Security Workspace(plcscan.org) 5 | -- ICS Discovery Tools Releases 6 | --- 7 | 8 | local bin = require "bin" 9 | local nmap = require "nmap" 10 | local shortport = require "shortport" 11 | local stdnse = require "stdnse" 12 | local string = require "string" 13 | local table = require "table" 14 | 15 | --Usage: 16 | --Identify MELSEC-Q Series PLC CPUINFO 17 | --nmap -script melsecq-discover -sT -p 5007 18 | 19 | 20 | --Output Example: 21 | --PORT STATE SERVICE REASON 22 | --5007/tcp open MelsoftTCP syn-ack 23 | --| melsecq-discover: 24 | --|_ CPUINFO: Q03UDECPU 25 | 26 | 27 | description = [[ 28 | discovery Mitsubishi Electric Q Series PLC 29 | GET CPUINFO 30 | ]] 31 | 32 | author = "ICS Security Workspace(plcscan.org)" 33 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 34 | categories = {"discovery","intrusive"} 35 | 36 | function set_nmap(host, port) 37 | port.state = "open" 38 | port.version.name = "MelsoftTCP" 39 | port.version.product = "Mitsubishi Q PLC" 40 | nmap.set_port_version(host, port) 41 | nmap.set_port_state(host, port, "open") 42 | 43 | end 44 | 45 | function send_receive(socket, query) 46 | local sendstatus, senderr = socket:send(query) 47 | if(sendstatus == false) then 48 | return "Error Sending getcpuinfopack" 49 | end 50 | local rcvstatus,response = socket:receive() 51 | if(rcvstatus == false) then 52 | return "Error Reading getcpuinfopack" 53 | end 54 | return response 55 | end 56 | 57 | portrule = shortport.port_or_service(5007, "MelsoftTCP", "tcp") 58 | action = function(host,port) 59 | local getcpuinfopack = bin.pack("H","57000000001111070000ffff030000fe03000014001c080a080000000000000004" .. "0101" .. "010000000001") 60 | local response 61 | local output = stdnse.output_table() 62 | local sock = nmap.new_socket() 63 | local constatus,conerr = sock:connect(host,port) 64 | if not constatus then 65 | stdnse.print_debug(1, 66 | 'Error establishing connection for %s - %s', host,conerr 67 | ) 68 | return nil 69 | end 70 | response = send_receive(sock, getcpuinfopack) 71 | local mel, pack_head = bin.unpack("C", response, 1) 72 | -- local mel, space_id = bin.unpack("C", response, 55) 73 | local offset = 0 74 | if ( pack_head == 0xd7) then 75 | -- if ( space_id == 0x20) then 76 | local mel 77 | local mel, cpuinfo = bin.unpack("z", response, 42 + offset) 78 | output["CPUINFO"] = string.sub(cpuinfo, 1, 16) 79 | set_nmap(host, port) 80 | sock:close() 81 | return output 82 | -- end 83 | else 84 | sock:close() 85 | return nil 86 | 87 | end 88 | 89 | 90 | end 91 | -------------------------------------------------------------------------------- /melsecq-discover-udp.nse: -------------------------------------------------------------------------------- 1 | -- Nmap Scripting Engine 2 | -- required packages for this script 3 | -- 4 | -- ICS Security Workspace(plcscan.org) 5 | -- ICS Discovery Tools Releases 6 | --- 7 | 8 | local bin = require "bin" 9 | local nmap = require "nmap" 10 | local shortport = require "shortport" 11 | local stdnse = require "stdnse" 12 | local string = require "string" 13 | local table = require "table" 14 | 15 | --Usage: 16 | --Identify MELSEC-Q Series PLC CPUINFO 17 | --nmap -script melsecq-discover-udp.nse -sU -p 5006 18 | 19 | --Output Example: 20 | --PORT STATE SERVICE REASON 21 | --5006/udp open Mitsubishi/Melsoft udp syn-ack 22 | --| melsecq-discover: 23 | --|_ CPUINFO: Q03UDECPU 24 | 25 | 26 | description = [[ 27 | discovery Mitsubishi Electric Q Series PLC 28 | GET CPUINFO 29 | ]] 30 | 31 | 32 | author = "ICS Security Workspace(plcscan.org)" 33 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 34 | categories = {"discovery","intrusive"} 35 | 36 | function set_nmap(host, port) 37 | port.state = "open" 38 | port.version.name = "MelsoftUdp" 39 | port.version.product = "Mitsubishi Q PLC" 40 | nmap.set_port_version(host, port) 41 | nmap.set_port_state(host, port, "open") 42 | 43 | end 44 | 45 | function send_receive(socket, query) 46 | local sendstatus, senderr = socket:send(query) 47 | if(sendstatus == false) then 48 | return "Error Sending getcpuinfopack" 49 | end 50 | local rcvstatus,response = socket:receive() 51 | if(rcvstatus == false) then 52 | return "Error Reading getcpuinfopack" 53 | end 54 | return response 55 | end 56 | 57 | portrule = shortport.port_or_service(5006, "MelsoftUdp", "udp") 58 | action = function(host,port) 59 | local getcpuinfopack = bin.pack("H","57000000001111070000ffff030000fe03000014001c080a080000000000000004" .. "0101" .. "010000000001") 60 | local response 61 | local output = stdnse.output_table() 62 | local sock = nmap.new_socket() 63 | local constatus,conerr = sock:connect(host,port) 64 | if not constatus then 65 | stdnse.print_debug(1, 66 | 'Error establishing connection for %s - %s', host,conerr 67 | ) 68 | return nil 69 | end 70 | response = send_receive(sock, getcpuinfopack) 71 | local mel, pack_head = bin.unpack("C", response, 1) 72 | -- local mel, space_id = bin.unpack("C", response, 55) 73 | local offset = 0 74 | if ( pack_head == 0xd7) then 75 | -- if ( space_id == 0x20) then 76 | local mel 77 | local mel, cpuinfo = bin.unpack("z", response, 42 + offset) 78 | output["CPUINFO"] = string.sub(cpuinfo, 1, 16) 79 | set_nmap(host, port) 80 | sock:close() 81 | return output 82 | -- end 83 | else 84 | sock:close() 85 | return nil 86 | 87 | end 88 | 89 | 90 | end 91 | -------------------------------------------------------------------------------- /cspv4-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local string = require "string" 6 | local table = require "table" 7 | 8 | description = [[ 9 | This NSE script is used to send a CSPV4 packet to a remote device that has TCP 2222 open. This is a port used via CIP 10 | and used by CSPV4 on AB PLC5 systems. This will determine the Session ID of the remote device to verify it as a CSPV4 11 | compliant device. CSPV4 or AB/Ethernet is used by Allen Bradley inside of its software products such as RSLinx to 12 | communicate to the PLCs. This will help ideitify some Allen Bradley PLCs that do not communicate via Ethernet/IP. 13 | Example: PLC5, SLC 500 14 | 15 | ]] 16 | --- 17 | -- @usage 18 | -- nmap --script cspv4-info -p 2222 19 | -- 20 | -- 21 | -- @output 22 | --PORT STATE SERVICE 23 | --2222/tcp open CSPV4 24 | --| cspv4-info: 25 | --|_ Session ID: 65792 26 | 27 | author = "Stephen Hilt" 28 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 29 | categories = {"discovery", "intrusive"} 30 | 31 | -- 32 | -- Function to define the portrule as per nmap standards 33 | -- 34 | -- 35 | -- 36 | portrule = shortport.portnumber(2222, "tcp") 37 | 38 | --- 39 | -- Function to set the nmap output for the host, if a valid CSPV4 packet 40 | -- is received then the output will show that the port as CSPV4 instead of 41 | -- unknown 42 | -- 43 | -- @param host Host that was passed in via nmap 44 | -- @param port port that CSPV4 is running on (Default TCP/2222) 45 | function set_nmap(host, port) 46 | 47 | --set port Open 48 | port.state = "open" 49 | -- set version name to cspv4 50 | port.version.name = "CSPV4" 51 | nmap.set_port_version(host, port) 52 | nmap.set_port_state(host, port, "open") 53 | 54 | end 55 | --- 56 | -- Action Function that is used to run the NSE. 57 | -- 58 | -- @param host Host that was scanned via nmap 59 | -- @param port port that was scanned via nmap 60 | action = function(host,port) 61 | -- pack the inital communications to the PLC5 62 | local init_coms = bin.pack("H","01010000000000000000000000040005000000000000000000000000") 63 | -- create table for output 64 | local output = stdnse.output_table() 65 | -- create local vars for socket handling 66 | local socket, try, catch 67 | -- create new socket 68 | socket = nmap.new_socket() 69 | -- define the catch of the try statement 70 | catch = function() 71 | socket:close() 72 | end 73 | -- create new try 74 | try = nmap.new_try(catch) 75 | 76 | -- connect to port on host 77 | try(socket:connect(host, port)) 78 | -- send Req Identity packet 79 | try(socket:send(init_coms)) 80 | -- receive response 81 | local rcvstatus, response = socket:receive() 82 | if(rcvstatus == false) then 83 | return false, response 84 | end 85 | -- unpack the response first byte 86 | local pos, first_check = bin.unpack("C", response, 1) 87 | -- Validate the response is the response we expected 88 | if(first_check == 0x02) then 89 | -- store Session ID in output table 90 | pos, output["Session ID"] = bin.unpack("i", response, 5) 91 | -- set Nmap output 92 | set_nmap(host, port) 93 | -- close socket 94 | socket:close() 95 | -- return output table to Nmap 96 | return output 97 | -- If response is not what expcted then close connection and return nothing 98 | else 99 | socket:close() 100 | return nil 101 | end 102 | end 103 | -------------------------------------------------------------------------------- /proconos-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local table = require "table" 6 | 7 | description = [[ 8 | This NSE script will query and parse ProConOs protocol to a remote PLC. 9 | The script will send a initial request packet and once a 10 | response is received, it validates that it was a proper response to the command 11 | that was sent, and then will parse out the data. 12 | 13 | http://digitalbond.com 14 | 15 | ]] 16 | --- 17 | -- @usage 18 | -- nmap --script proconos-info -p 20547 19 | -- 20 | -- 21 | -- @output 22 | --| proconos-info: 23 | --| Ladder Logic Runtime: ProConOS V3.0.1040 Oct 29 2002 24 | --| PLC Type: ADAM5510KW 1.24 Build 005 25 | --| Project Name: 510-projec 26 | --| Boot Project: 510-projec 27 | --|_ Project Source Code: Exist 28 | -- 29 | -- 30 | -- @xmloutput 31 | --ProConOS V3.0.1040 Oct 29 2002 32 | --ADAM5510KW 1.24 Build 005 33 | --510-projec 34 | --510-project 35 | --Exist 36 | author = "Stephen Hilt (Digital Bond)" 37 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 38 | categories = {"discovery", "version"} 39 | 40 | -- 41 | -- Function to define the portrule as per nmap standards 42 | -- 43 | -- 44 | portrule = shortport.portnumber(20547, "tcp") 45 | 46 | --- 47 | -- Function to set the nmap output for the host, if a valid PCPROTOCOL packet 48 | -- is received then the output will show that the port is open instead of 49 | -- open|filtered 50 | -- 51 | -- @param host Host that was passed in via nmap 52 | -- @param port port that PCPROTOCOL is running on (Default TCP/1962) 53 | function set_nmap(host, port) 54 | 55 | --set port Open 56 | port.state = "open" 57 | -- set version name to PCPROTOCOL 58 | port.version.name = "ProConOS" 59 | nmap.set_port_version(host, port) 60 | nmap.set_port_state(host, port, "open") 61 | 62 | end 63 | 64 | --- 65 | -- Action Function that is used to run the NSE. This function will send the initial query to the 66 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 67 | -- is a PCPROTOCOL device. If it is then more actions are taken to gather extra information. 68 | -- 69 | -- @param host Host that was scanned via nmap 70 | -- @param port port that was scanned via nmap 71 | action = function(host,port) 72 | local req_info = bin.pack("H","cc01000b4002000047ee") 73 | -- create table for output 74 | local output = stdnse.output_table() 75 | -- create local vars for socket handling 76 | local socket, try, catch 77 | -- create new socket 78 | socket = nmap.new_socket() 79 | -- define the catch of the try statement 80 | catch = function() 81 | socket:close() 82 | end 83 | -- create new try 84 | try = nmap.new_try(catch) 85 | try(socket:connect(host, port)) 86 | -- connect to port on host 87 | try(socket:send(req_info)) 88 | -- receive response 89 | local rcvstatus, response = socket:receive() 90 | if(rcvstatus == false) then 91 | return false, response 92 | end local pos, check1 = bin.unpack("C",response,1) 93 | -- if the fist byte is 0xcc 94 | if(check1 == 0xcc) then 95 | set_nmap(host, port) 96 | -- create output table with proper data 97 | pos, output["Ladder Logic Runtime"] = bin.unpack("z",response,13) 98 | pos, output["PLC Type"] = bin.unpack("z",response, 45) 99 | pos, output["Project Name"] = bin.unpack("z", response, 78) 100 | pos, output["Boot Project"] = bin.unpack("z", response, pos) 101 | pos, output["Project Source Code"] = bin.unpack("z", response, pos) 102 | -- close socket and return output table 103 | socket:close() 104 | return output 105 | end 106 | -- close socket 107 | socket:close() 108 | -- return nil 109 | return nil 110 | end 111 | -------------------------------------------------------------------------------- /codesys-v2-discover.nse: -------------------------------------------------------------------------------- 1 | local nmap = require "nmap" 2 | local comm = require "comm" 3 | local stdnse = require "stdnse" 4 | local strbuf = require "strbuf" 5 | local nsedebug = require "nsedebug" 6 | 7 | description = [[ 8 | 9 | http://digitalbond.com 10 | 11 | ]] 12 | 13 | author = "Stephen Hilt (Digital Bond)" 14 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 15 | categories = {"discovery", "safe"} 16 | 17 | --- 18 | -- Script is executed for any TCP port. 19 | portrule = function( host, port ) 20 | return port.protocol == "tcp" 21 | end 22 | 23 | --- 24 | -- Function to set the nmap output for the host, if a valid CoDeSyS packet 25 | -- is received then the output will show that the port as CoDeSyS 26 | -- 27 | -- @param host Host that was passed in via nmap 28 | -- @param port port that CoDeSyS may be running on TCP/1200 or TCP/2455 29 | function set_nmap(host, port) 30 | 31 | --set port Open 32 | port.state = "open" 33 | -- set version name to CoDeSyS 34 | port.version.name = "CoDeSyS" 35 | nmap.set_port_version(host, port) 36 | nmap.set_port_state(host, port, "open") 37 | 38 | end 39 | 40 | --- 41 | -- Remove extra whitespace from the beginning and end the string 42 | -- 43 | -- @param s string to remove extra white space 44 | 45 | function trim(s) 46 | -- remove white spaces from beginning and ending of the string 47 | return (s:gsub("^%s*(.-)%s*$", "%1")) 48 | end 49 | 50 | --- 51 | -- Action Function that is used to run the NSE. This function will send the initial query to the 52 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 53 | -- is a CoDeSys device. If it is then more actions are taken to gather extra information. 54 | -- 55 | -- @param host Host that was scanned via nmap 56 | -- @param port port that was scanned via nmap 57 | action = function( host, port ) 58 | -- little endian query 59 | lile_query = bin.pack("H", "bbbb0100000001") 60 | -- big endian query 61 | bige_query = bin.pack("H", "bbbb0100000101") 62 | -- set up table for output 63 | local output = stdnse.output_table() 64 | -- create socket 65 | local sock = nmap.new_socket() 66 | -- connect to remote host 67 | local constatus, conerr = sock:connect(host, port) 68 | -- if not successful debug error message and return nil 69 | if not constatus then 70 | stdnse.print_debug(1, 71 | 'Error establishing a TCP connection for %s - %s', host, conerr 72 | ) 73 | return nil 74 | end 75 | -- send little endian query 76 | local sendstatus, senderr = sock:send(lile_query) 77 | if not sendstatus then 78 | stdnse.print_debug(1, 79 | 'Error sending CoDeSyS request to %s:%d - %s', 80 | host.ip, port.number, senderr 81 | ) 82 | return nil 83 | end 84 | -- recieve response 85 | local rcvstatus, response = sock:receive() 86 | if(rcvstatus == false) then 87 | stdnse.print_debug(1, "Receive error: %s", response) 88 | return nil 89 | end 90 | -- if there was no response, try big endian 91 | if(response == "EOF" or response == "TIMEOUT") then 92 | -- try sending big endian query 93 | local sendstatus, senderr = sock:send(bige_query) 94 | if not sendstatus then 95 | stdnse.print_debug(1, 96 | 'Error sending CoDeSyS request to %s:%d - %s', 97 | host.ip, port.number, senderr 98 | ) 99 | return nil 100 | end 101 | -- receive response 102 | local rcvstatus, response = sock:receive() 103 | if(rcvstatus == false) then 104 | stdnse.print_debug(1, "Receive error: %s", response) 105 | return nil 106 | end 107 | end 108 | -- unpack first byte to see if it is 0xbb 109 | local pos, codesys_check = bin.unpack("C", response, 1) 110 | -- is first byte 0xbb? 111 | if (codesys_check ~= 0xbb) then 112 | sock:close() 113 | return nil 114 | end 115 | 116 | local pos, os_name = bin.unpack("z", response, 65) 117 | local pos , os_type = bin.unpack("z", response, 97) 118 | local pos, product_type = bin.unpack("z", response, 129) 119 | -- close socket 120 | sock:close() 121 | -- set nmap port 122 | set_nmap(host, port) 123 | -- set output table (for future growth of information) 124 | output["OS Name"] = os_name .. " " .. os_type 125 | output["Product Type"] = product_type 126 | -- return output table to nmap 127 | return output 128 | end 129 | -------------------------------------------------------------------------------- /atg-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local string = require "string" 6 | local table = require "table" 7 | 8 | description = [[ This Script is designed to query the I20100 command on Guardian AST Automatic Tank Gauge 9 | products. This script sends a single query and parses the response. This response is the Tank Inventory 10 | of the ATG. Using --script-args command=I20200 you will be able to pull a diffrent report than the I20100. 11 | 12 | Based off of www.veeder.com/gold/download.cfm?doc_id=3668 13 | 14 | ]] 15 | 16 | --- 17 | -- @usage 18 | -- nmap --script atg-info -p 10001 19 | -- 20 | -- @args command If set to another command, It will do that command instead of I20100 21 | -- 22 | -- @output 23 | --10001/tcp open Guardian AST reset 24 | --| atg-info: 25 | --| I20100 26 | --| SEP 19, 2015 5:33 PM 27 | --| 28 | --| Fuel Company 29 | --| 12 Fake St 30 | --| Anytown, USA 12345 31 | --| 32 | --| 33 | --| IN-TANK INVENTORY 34 | --| 35 | --| TANK PRODUCT VOLUME TC VOLUME ULLAGE HEIGHT WATER TEMP 36 | --| 1 UNLEADED 5135 0 6647 42.71 0.00 72.01 37 | --| 2 UNLEADED 5135 0 6647 42.70 0.00 71.55 38 | --| 3 PREMIUM UNLEADED 5135 0 5350 19.27 0.00 72.52 39 | --|_ 40 | 41 | 42 | author = "Stephen J. Hilt" 43 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 44 | categories = {"discovery"} 45 | 46 | 47 | -- 48 | -- Function to define the portrule as per nmap standards 49 | portrule = shortport.port_or_service(10001, "atg") 50 | --- 51 | -- Function to set the nmap output for the host, if a valid ATG packet 52 | -- is received then the output will show that the port as ATG instead of 53 | -- tcpwrapped 54 | -- 55 | -- @param host Host that was passed in via nmap 56 | -- @param port port that ATG is running on (Default TCP/10001) 57 | function set_nmap(host, port) 58 | 59 | --set port Open 60 | port.state = "open" 61 | -- set version name to Guardian AST 62 | port.version.name = " Guardian AST" 63 | nmap.set_port_version(host, port) 64 | nmap.set_port_state(host, port, "open") 65 | 66 | end 67 | 68 | 69 | --- 70 | -- Action Function that is used to run the NSE. This function will send the initial query to the 71 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 72 | -- is a ATG device. If it is then more actions are taken to gather extra information. 73 | -- 74 | -- @param host Host that was scanned via nmap 75 | -- @param port port that was scanned via nmap 76 | action = function(host, port) 77 | local command = "I20100" 78 | local arguments = stdnse.get_script_args('command') 79 | if ( arguments ~= "I20100" and arguments ~= nil) then 80 | command = arguments 81 | end 82 | -- create new socket 83 | local sock = nmap.new_socket() 84 | -- set timeout low in case we don't get a response 85 | sock:set_timeout(1000) 86 | -- query to pull the tank inventory 87 | local tank_command = "\x01" .. command .. "\n" 88 | -- Connect to the remote host 89 | local constatus, conerr = sock:connect(host, port) 90 | if not constatus then 91 | stdnse.debug1( 92 | 'Error establishing a TCP connection for %s - %s', host, conerr 93 | ) 94 | return nil 95 | end 96 | -- send query to inventory the tanks 97 | local sendstatus, senderr = sock:send(tank_command) 98 | if not sendstatus then 99 | stdnse.debug1( 100 | 'Error sending ATG request to %s:%d - %s', 101 | host.ip, port.number, senderr 102 | ) 103 | return nil 104 | end 105 | -- receive the response for parseing 106 | local rcvstatus, response = sock:receive_bytes(1024) 107 | if(rcvstatus == false) then 108 | stdnse.debug1( "Receive error: %s", response) 109 | return nil 110 | end 111 | -- if the response was timeout, then we will return that we had a timeout 112 | --(for now add more addresses later) 113 | if (response == "TIMEOUT" or response == "EOF") then 114 | sock:close() 115 | return "TIMEOUT: No response from query" 116 | end 117 | -- if the first byte is 0x01, or 0x0a then likely the response is an ATG 118 | if(string.byte(response,1) == 0x01 or string.byte(response,1) == 0x0a) then 119 | local inventory_output = string.sub(response,2,-2) 120 | set_nmap(host, port) 121 | sock:close() 122 | return inventory_output 123 | end 124 | end 125 | 126 | -------------------------------------------------------------------------------- /pcworx-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local table = require "table" 6 | 7 | description = [[ 8 | This NSE script will query and parse pcworx protocol to a remote PLC. 9 | The script will send a initial request packets and once a response is received, 10 | it validates that it was a proper response to the command that was sent, and then 11 | will parse out the data. PCWorx is a protocol and Program by Phoenix Contact. 12 | 13 | 14 | http://digitalbond.com 15 | 16 | ]] 17 | --- 18 | -- @usage 19 | -- nmap --script pcworx-info -p 1962 20 | -- 21 | -- 22 | -- @output 23 | --| pcworx-info: 24 | --1962/tcp open pcworx 25 | --| pcworx-info: 26 | --| PLC Type: ILC 330 ETH 27 | --| Model Number: 2737193 28 | --| Firmware Version: 3.95T 29 | --| Firmware Date: Mar 2 2012 30 | --|_ Firmware Time: 09:39:02 31 | 32 | -- 33 | -- 34 | -- @xmloutput 35 | --ILC 330 ETH 36 | --2737193 37 | --3.95T 38 | --Mar 2 2012 39 | --09:39:02 40 | author = "Stephen Hilt (Digital Bond)" 41 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 42 | categories = {"discovery", "version"} 43 | 44 | -- 45 | -- Function to define the portrule as per nmap standards 46 | -- 47 | -- 48 | portrule = shortport.portnumber(1962, "tcp") 49 | 50 | --- 51 | -- Function to set the nmap output for the host, if a valid pcworx Protocol packet 52 | -- is received then the output will show that the port is open instead of 53 | -- 54 | -- @param host Host that was passed in via nmap 55 | -- @param port port that pcworx Protocol is running on (Default TCP/1962) 56 | function set_nmap(host, port) 57 | 58 | --set port Open 59 | port.state = "open" 60 | -- set version name to pcworx Protocol 61 | port.version.name = "pcworx" 62 | nmap.set_port_version(host, port) 63 | nmap.set_port_state(host, port, "open") 64 | 65 | end 66 | 67 | --- 68 | -- Action Function that is used to run the NSE. This function will send the initial query to the 69 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 70 | -- is a pcworx Protocol device. If it is then more actions are taken to gather extra information. 71 | -- 72 | -- @param host Host that was scanned via nmap 73 | -- @param port port that was scanned via nmap 74 | action = function(host,port) 75 | local init_comms = bin.pack("H","0101001a0000000078800003000c494245544830314e305f4d00") 76 | 77 | -- create table for output 78 | local output = stdnse.output_table() 79 | -- create local vars for socket handling 80 | local socket, try, catch 81 | -- create new socket 82 | socket = nmap.new_socket() 83 | -- define the catch of the try statement 84 | catch = function() 85 | socket:close() 86 | end 87 | -- create new try 88 | try = nmap.new_try(catch) 89 | try(socket:connect(host, port)) 90 | try(socket:send(init_comms)) 91 | -- receive response 92 | local rcvstatus, response = socket:receive() 93 | if(rcvstatus == false) then 94 | return false, response 95 | end 96 | -- pcworx has a session ID that is generated by the PLC 97 | -- This will pull the SID so we can communicate further to the PLC 98 | local pos, sid = bin.unpack("C", response, 18) 99 | local init_comms2 = bin.pack("HCH","0105001600010000788000", sid, "00000006000402950000") 100 | try(socket:send(init_comms2)) 101 | -- receive response 102 | local rcvstatus, response = socket:receive() 103 | if(rcvstatus == false) then 104 | return false, response 105 | end 106 | -- this is the request that will pull all the information from the PLC 107 | local req_info = bin.pack("HCH","0106000e00020000000000",sid,"0400") 108 | try(socket:send(req_info)) 109 | -- receive response 110 | local rcvstatus, response = socket:receive() 111 | if(rcvstatus == false) then 112 | return false, response 113 | end 114 | local pos, check1 = bin.unpack("C",response,1) 115 | -- if the response starts with 0x81 then we will continue 116 | if(check1 == 0x81) then 117 | -- set the port information via nmap output 118 | set_nmap(host, port) 119 | -- create output table with proper data 120 | pos, output["PLC Type"] = bin.unpack("z",response,31) 121 | pos, output["Model Number"] = bin.unpack("z", response, 153) 122 | pos, output["Firmware Version"] = bin.unpack("z",response, 67) 123 | pos, output["Firmware Date"] = bin.unpack("z", response, 80) 124 | pos, output["Firmware Time"] = bin.unpack("z", response, 92) 125 | 126 | -- close socket and return output table 127 | socket:close() 128 | return output 129 | end 130 | -- close socket 131 | socket:close() 132 | -- return nil 133 | return nil 134 | end 135 | -------------------------------------------------------------------------------- /iec-identify.nse: -------------------------------------------------------------------------------- 1 | local shortport = require "shortport" 2 | local comm = require "comm" 3 | local stdnse = require "stdnse" 4 | local string = require "string" 5 | local match = require "match" 6 | 7 | description = [[ 8 | Attempts to identify IEC 60870-5-104 ICS protocol. 9 | After probing with a TESTFR (test frame) message, a STARTDT (start data 10 | transfer) message is sent and general interrogation is used to gather the list 11 | of information object addresses stored. 12 | ]] 13 | 14 | --- 15 | -- @output 16 | -- | iec-identify: 17 | -- | ASDU address: 105 18 | -- |_ Information objects: 30 19 | -- 20 | 21 | author = {"Aleksandr Timorin", "Daniel Miller"} 22 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 23 | categories = {"discovery", "intrusive"} 24 | 25 | portrule = shortport.port_or_service(2404, "iec-104", "tcp") 26 | 27 | local function get_asdu(socket) 28 | local status, data = socket:receive_buf(match.numbytes(2), true) 29 | if not status then 30 | return nil, data 31 | end 32 | if data:byte(1) ~= 0x68 then 33 | return nil, "Not IEC-104" 34 | end 35 | local len = data:byte(2) 36 | status, data = socket:receive_buf(match.numbytes(len), true) 37 | if not status then 38 | return nil, data 39 | end 40 | local apcitype = data:byte(1) 41 | return apcitype, data 42 | end 43 | 44 | action = function(host, port) 45 | 46 | local output = stdnse.output_table() 47 | local socket, err = comm.opencon(host, port) 48 | if not socket then 49 | stdnse.debug1("Connect error: %s", err) 50 | return nil 51 | end 52 | 53 | -- send TESTFR ACT command 54 | -- Test frame, like "ping" 55 | local TESTFR = "\x68\x04\x43\0\0\0" 56 | local status, err = socket:send( TESTFR ) 57 | if not status then 58 | stdnse.debug1("Failed to send: %s", err) 59 | return nil 60 | end 61 | 62 | -- receive TESTFR answer 63 | local apcitype, recv = get_asdu(socket) 64 | if not apcitype then 65 | stdnse.debug1("protocol error: %s", recv) 66 | return nil 67 | end 68 | if apcitype ~= 0x83 then 69 | stdnse.print_debug(1, "Not IEC-104. TESTFR response: %#x", apcitype) 70 | return nil 71 | end 72 | 73 | -- send STARTDT ACT command 74 | local STARTDT = "\x68\x04\x07\0\0\0" 75 | status, err = socket:send( STARTDT ) 76 | if not status then 77 | stdnse.debug1("Failed to send: %s", err) 78 | return nil 79 | end 80 | 81 | -- receive STARTDT answer 82 | apcitype, recv = get_asdu(socket) 83 | if not apcitype then 84 | stdnse.debug1("protocol error: %s", recv) 85 | return nil 86 | end 87 | if apcitype ~= 0x0b then 88 | stdnse.debug1("STARTDT ACT did not receive STARTDT CON: %#x", apcitype) 89 | return nil 90 | end 91 | 92 | -- May also receive ME_EI_NA_1 (End of initialization), so check for that in the buffer after sending the next part 93 | 94 | -- send C_IC_NA_1 command 95 | -- type: 0x64, C_IC_NA_1, 96 | -- numix: 1 97 | -- TNCause: 6, Act 98 | -- Originator address; 0 99 | -- ASDU address: 0xffff 100 | -- Information object address: 0 101 | -- QOI: 0x14 (20), Station interrogation (global) 102 | local C_IC_NA_1_broadcast = "\x68\x0e\0\0\0\0\x64\x01\x06\0\xff\xff\0\0\0\x14" 103 | status, err = socket:send( C_IC_NA_1_broadcast ) 104 | if not status then 105 | stdnse.debug1("Failed to send: %s", err) 106 | return nil 107 | end 108 | 109 | local asdu_address 110 | local ioas = 0 111 | -- Have to draw the line somewhere. 112 | local limit = 10 113 | while limit > 0 do 114 | limit = limit - 1 115 | apcitype, recv = get_asdu(socket) 116 | if not apcitype then 117 | stdnse.debug1("Error in C_IC_NA_1: %s", recv) 118 | break 119 | end 120 | if apcitype & 0x01 == 0 then -- Type I, numbered information transfer 121 | -- skip 2 bytes Tx, 2 bytes Rx 122 | local typeid = recv:byte(5) 123 | if typeid == 70 then 124 | -- ME_EI_NA_1, End of Initialization. Skip. 125 | else 126 | local numix = recv:byte(6) & 0x7f 127 | local cause = recv:byte(7) & 0x3f 128 | asdu_address = string.unpack("= 20 and cause <= 36 then 142 | -- Inrogen, response to general interrogation 143 | ioas = ioas + numix 144 | end 145 | end 146 | end 147 | end 148 | end 149 | 150 | socket:close() 151 | 152 | if asdu_address then 153 | output["ASDU address"] = asdu_address 154 | output["Information objects"] = ioas 155 | else 156 | output = "IEC-104 endpoint did not respond to C_IC_NA_1 request" 157 | end 158 | 159 | return output 160 | end 161 | -------------------------------------------------------------------------------- /omronudp-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local table = require "table" 6 | 7 | description = [[ 8 | This NSE script is used to send a FINS packet to a remote device that 9 | has UDP 9600 open. The script will send a Controller Data Read Command and once a 10 | response is received, it validates that it was a proper response to the command 11 | that was sent, and then will parse out the data. 12 | 13 | http://digitalbond.com 14 | 15 | ]] 16 | --- 17 | -- @usage 18 | -- nmap --script ormonudp-info -sU -p 9600 19 | -- 20 | -- 21 | -- 22 | -- @output 23 | --9600/tcp open OMRON FINS 24 | --| omrontcp-info: 25 | --| Controller Model: CJ2M-CPU32 02.01 26 | --| Controller Version: 02.01 27 | --| For System Use: 28 | --| Program Area Size: 20 29 | --| IOM size: 23 30 | --| No. DM Words: 32768 31 | --| Timer/Counter: 8 32 | --| Expansion DM Size: 1 33 | --| No. of steps/transitions: 0 34 | --| Kind of Memory Card: 0 35 | --|_ Memory Card Size: 0 36 | 37 | -- @xmloutput 38 | --CS1G_CPU44H 03.00 39 | --03.00 40 | -- 41 | --20 42 | --23 43 | --32768 44 | --8 45 | --1 46 | --0 47 | --0 48 | --0 49 | 50 | 51 | author = "Stephen Hilt (Digital Bond)" 52 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 53 | categories = {"discovery", "version"} 54 | 55 | -- 56 | -- Function to define the portrule as per nmap standards 57 | -- 58 | -- 59 | portrule = shortport.portnumber(9600, "udp") 60 | 61 | --- 62 | -- Function to set the nmap output for the host, if a valid OMRON FINS packet 63 | -- is received then the output will show that the port is open instead of 64 | -- open|filtered 65 | -- 66 | -- @param host Host that was passed in via nmap 67 | -- @param port port that FINS is running on (Default UDP/9600) 68 | function set_nmap(host, port) 69 | 70 | --set port Open 71 | port.state = "open" 72 | -- set version name to OMRON FINS 73 | port.version.name = "OMRON FINS" 74 | nmap.set_port_version(host, port) 75 | nmap.set_port_state(host, port, "open") 76 | 77 | end 78 | 79 | local memcard = { 80 | [0] = "No Memory Card", 81 | [1] = "SPRAM", 82 | [2] = "EPROM", 83 | [3] = "EEPROM" 84 | } 85 | 86 | function memory_card(value) 87 | local mem_card = memcard[value] or "Unknown Memory Card Type" 88 | return mem_card 89 | end 90 | 91 | --- 92 | -- Action Function that is used to run the NSE. This function will send the initial query to the 93 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 94 | -- is a FINS supported device. 95 | -- 96 | -- @param host Host that was scanned via nmap 97 | -- @param port port that was scanned via nmap 98 | action = function(host,port) 99 | -- 0501 is the command to read the Controller Data 100 | -- This command via UDP will result 101 | local controller_data_read = bin.pack("H", "800002000000006300ef050100") 102 | 103 | -- create table for output 104 | local output = stdnse.output_table() 105 | -- create local vars for socket handling 106 | local socket, try, catch 107 | -- create new socket 108 | socket = nmap.new_socket() 109 | -- define the catch of the try statement 110 | catch = function() 111 | socket:close() 112 | end 113 | -- create new try 114 | try = nmap.new_try(catch) 115 | -- connect to port on host 116 | try(socket:connect(host, port)) 117 | -- send Request Information Packet 118 | try(socket:send(controller_data_read)) 119 | local rcvstatus, response = socket:receive() 120 | if(rcvstatus == false) then 121 | return false, response 122 | end 123 | local pos, header = bin.unpack("C", response, 1) 124 | if(header == 0xc0 or header == 0xc1) then 125 | set_nmap(host, port) 126 | local response_code 127 | pos, response_code = bin.unpack("S", response, 95) 141 | pos, output["IOM size"] = bin.unpack("C", response, pos) 142 | pos, output["No. DM Words"] = bin.unpack(">S", response, pos) 143 | pos, output["Timer/Counter"] = bin.unpack("C", response, pos) 144 | pos, output["Expansion DM Size"] = bin.unpack("C", response, pos) 145 | pos, output["No. of steps/transitions"] = bin.unpack(">S", response, pos) 146 | local mem_card_type 147 | pos, mem_card_type = bin.unpack("C", response, pos) 148 | output["Kind of Memory Card"] = memory_card(mem_card_type) 149 | pos, output["Memory Card Size"] = bin.unpack(">S", response, pos) 150 | 151 | else 152 | output["Response Code"] = "Unknown Response Code" 153 | end 154 | socket:close() 155 | return output 156 | 157 | else 158 | socket:close() 159 | return nil 160 | end 161 | 162 | end 163 | -------------------------------------------------------------------------------- /omrontcp-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local table = require "table" 6 | 7 | description = [[ 8 | This NSE script is used to send two FINS packets to a remote device that 9 | has TCP 9600 open. The script will send a Controller Data Read Command and once a 10 | response is received, it validates that it was a proper response to the command 11 | that was sent, and then will parse out the data. 12 | 13 | http://digitalbond.com 14 | 15 | ]] 16 | --- 17 | -- @usage 18 | -- nmap --script ormontcp-info -p 9600 19 | -- 20 | -- 21 | -- @output 22 | --9600/tcp open OMRON FINS 23 | --| omrontcp-info: 24 | --| Controller Model: CJ2M-CPU32 02.01 25 | --| Controller Version: 02.01 26 | --| For System Use: 27 | --| Program Area Size: 20 28 | --| IOM size: 23 29 | --| No. DM Words: 32768 30 | --| Timer/Counter: 8 31 | --| Expansion DM Size: 1 32 | --| No. of steps/transitions: 0 33 | --| Kind of Memory Card: 0 34 | --|_ Memory Card Size: 0 35 | 36 | -- @xmloutput 37 | --CS1G_CPU44H 03.00 38 | --03.00 39 | -- 40 | --20 41 | --23 42 | --32768 43 | --8 44 | --1 45 | --0 46 | --0 47 | --0 48 | 49 | 50 | 51 | author = "Stephen Hilt (Digital Bond)" 52 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 53 | categories = {"discovery", "version"} 54 | 55 | -- 56 | -- Function to define the portrule as per nmap standards 57 | -- 58 | -- 59 | portrule = shortport.portnumber(9600, "tcp") 60 | 61 | --- 62 | -- Function to set the nmap output for the host, if a valid OMRON FINS packet 63 | -- is received then the output will show that the port is open. 64 | -- 65 | -- @param host Host that was passed in via nmap 66 | -- @param port port that FINS is running on (Default TCP/9600) 67 | function set_nmap(host, port) 68 | 69 | --set port Open 70 | port.state = "open" 71 | -- set version name to OMRON FINS 72 | port.version.name = "OMRON FINS" 73 | nmap.set_port_version(host, port) 74 | nmap.set_port_state(host, port, "open") 75 | 76 | end 77 | 78 | local memcard = { 79 | [0] = "No Memory Card", 80 | [1] = "SPRAM", 81 | [2] = "EPROM", 82 | [3] = "EEPROM" 83 | } 84 | 85 | function memory_card(value) 86 | local mem_card = memcard[value] or "Unknown Memory Card Type" 87 | return mem_card 88 | end 89 | 90 | 91 | --- 92 | -- Action Function that is used to run the NSE. This function will send the initial query to the 93 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 94 | -- is a FINS supported device. 95 | -- 96 | -- @param host Host that was scanned via nmap 97 | -- @param port port that was scanned via nmap 98 | action = function(host,port) 99 | -- this is the request address command 100 | local req_addr = bin.pack("H", "46494e530000000c000000000000000000000000") 101 | -- TCP requres a network address that is recived from the first request, 102 | -- The read contoller data these two strings will be joined with the address 103 | local controller_data_read = "46494e5300000015000000020000000080000200" 104 | local controller_data_read2 = "000000ef050501" 105 | 106 | -- create table for output 107 | local output = stdnse.output_table() 108 | -- create local vars for socket handling 109 | local socket, try, catch 110 | -- create new socket 111 | socket = nmap.new_socket() 112 | -- define the catch of the try statement 113 | catch = function() 114 | socket:close() 115 | end 116 | -- create new try 117 | try = nmap.new_try(catch) 118 | -- connect to port on host 119 | try(socket:connect(host, port)) 120 | -- send Request Information Packet 121 | try(socket:send(req_addr)) 122 | local rcvstatus, response = socket:receive() 123 | if(rcvstatus == false) then 124 | return false, response 125 | end 126 | local pos, header = bin.unpack("C", response, 1) 127 | if(header == 0x46) then 128 | set_nmap(host, port) 129 | local pos, address = bin.unpack("C",response,24) 130 | local controller_data = bin.pack("HCHC", controller_data_read, address, controller_data_read2, 0x00) 131 | -- send the read controller data request 132 | try(socket:send(controller_data)) 133 | local rcvstatus, response = socket:receive() 134 | if(rcvstatus == false) then 135 | return false, response 136 | end 137 | 138 | local response_code 139 | pos, response_code = bin.unpack("S", response, 111) 152 | pos, output["IOM size"] = bin.unpack("C", response, pos) 153 | pos, output["No. DM Words"] = bin.unpack(">S", response, pos) 154 | pos, output["Timer/Counter"] = bin.unpack("C", response, pos) 155 | pos, output["Expansion DM Size"] = bin.unpack("C", response, pos) 156 | pos, output["No. of steps/transitions"] = bin.unpack(">S", response, pos) 157 | local mem_card_type 158 | pos, mem_card_type = bin.unpack("C", response, pos) 159 | output["Kind of Memory Card"] = memory_card(mem_card_type) 160 | pos, output["Memory Card Size"] = bin.unpack(">S", response, pos) 161 | else 162 | output["Response Code"] = "Unknown Response Code" 163 | end 164 | -- close socket, return output 165 | socket:close() 166 | return output 167 | 168 | else 169 | -- close socket and return nil 170 | socket:close() 171 | return nil 172 | end 173 | 174 | end 175 | -------------------------------------------------------------------------------- /dnp3-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local string = require "string" 6 | local table = require "table" 7 | 8 | description = [[ 9 | 10 | This nmap NSE will send a command to query through the first 100 addresses of 11 | DNP3 to see if a valid response is given. If a valid response is given it will 12 | then parse the results based on function ID and other data. 13 | 14 | ]] 15 | 16 | --- 17 | -- @usage 18 | -- nmap --script dnp3-info -p 20000 19 | 20 | author = "Stephen J. Hilt" 21 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 22 | categories = {"discovery", "intrusive"} 23 | 24 | 25 | -- 26 | -- Function to define the portrule as per nmap standards 27 | portrule = shortport.port_or_service(20000, "dnp", "tcp") 28 | 29 | -- Datalink Function Codes PRM=0 30 | local function_id = { 31 | [0] = "ACK", 32 | [1] = "NACK", 33 | [11] = "Link Status", 34 | [15] = "User Data" 35 | } 36 | -- Data Link Function Codes PRM=1 37 | local alt_function_id = { 38 | [0] = "RESET Link", 39 | [1] = "Reset User Process", 40 | [2] = "TEST link", 41 | [3] = "User Data", 42 | [4] = "User Data", 43 | [9] = "Request Link Status" 44 | } 45 | -- lookup function codes based off the PRM (byte 2) 46 | function funct_lookup(id) 47 | local funct_id 48 | -- if the string is 4 bytes then was 0x0 49 | if (string.len(id) < 5) then 50 | -- look up function id in the table, if doesn't exist then its unknown 51 | funct_id = function_id[tonumber(id,2)] or "Unknown Function ID" 52 | id = tonumber(id,2) 53 | -- else byte was 0x?? 54 | else 55 | local first_value = string.byte(id, 2) % 0x10 56 | local second_value = tonumber(string.byte(id,5) % 0x10 .. string.byte(id,6) % 0x10 .. string.byte(id,7) %0x10 .. 57 | string.byte(id,8) % 0x10,2) 58 | if( first_value == 0) then 59 | -- look up function id in the table, if doesn't exist then its unknown 60 | funct_id = function_id[second_value] or "Unknown Function ID" 61 | else 62 | -- look up function id in the table, if doesn't exist then its unknown 63 | funct_id = alt_function_id[second_value] or "Unknown Function ID" 64 | end 65 | -- overwrite id to output what the value for if it was 0x?? 66 | id = second_value 67 | end 68 | return string.format("%s (%d)", funct_id, id) 69 | end 70 | --- 71 | -- Function to set the nmap output for the host, if a valid DNP3 packet 72 | -- is received then the output will show that the port as DNP3 instead of 73 | -- dnp 74 | -- 75 | -- @param host Host that was passed in via nmap 76 | -- @param port port that DNP3 is running on (Default TCP/20000) 77 | function set_nmap(host, port) 78 | 79 | --set port Open 80 | port.state = "open" 81 | -- set version name to DNP3 82 | port.version.name = "DNP3" 83 | nmap.set_port_version(host, port) 84 | nmap.set_port_state(host, port, "open") 85 | 86 | end 87 | 88 | 89 | --- 90 | -- Action Function that is used to run the NSE. This function will send the initial query to the 91 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 92 | -- is a DNP3 device. If it is then more actions are taken to gather extra information. 93 | -- 94 | -- @param host Host that was scanned via nmap 95 | -- @param port port that was scanned via nmap 96 | action = function(host, port) 97 | 98 | 99 | -- create new socket 100 | local sock = nmap.new_socket() 101 | -- set timeout low in case we don't get a response 102 | sock:set_timeout(1000) 103 | -- create output table 104 | local output = stdnse.output_table() 105 | -- query to pull the fist 100 address 106 | local first100 = bin.pack("H", "056405C900000000364C056405C901000000DE8E056405C" .. 107 | "9020000009F84056405C9030000007746056405C9040000" .. 108 | "001D90056405C905000000F552056405C906000000B4580" .. 109 | "56405C9070000005C9A056405C90800000019B9056405C9" .. 110 | "09000000F17B056405C90A000000B071056405C90B00000" .. 111 | "058B3056405C90C0000003265056405C90D000000DAA705" .. 112 | "6405C90E0000009BAD056405C90F000000736F056405C91" .. 113 | "000000011EB056405C911000000F929056405C912000000" .. 114 | "B823056405C91300000050E1056405C9140000003A37056" .. 115 | "405C915000000D2F5056405C91600000093FF056405C917" .. 116 | "0000007B3D056405C9180000003E1E056405C919000000D" .. 117 | "6DC056405C91A00000097D6056405C91B0000007F140564" .. 118 | "05C91C00000015C2056405C91D000000FD00056405C91E00" .. 119 | "0000BC0A056405C91F00000054C8056405C920000000014" .. 120 | "F056405C921000000E98D056405C922000000A887056405" .. 121 | "C9230000004045056405C9240000002A93056405C925000" .. 122 | "000C251056405C926000000835B056405C9270000006B99" .. 123 | "056405C9280000002EBA056405C929000000C678056405C" .. 124 | "92A0000008772056405C92B0000006FB0056405C92C0000" .. 125 | "000566056405C92D000000EDA4056405C92E000000ACAE0" .. 126 | "56405C92F000000446C056405C93000000026E8056405C9" .. 127 | "31000000CE2A056405C9320000008F20056405C93300000" .. 128 | "067E2056405C9340000000D34056405C935000000E5F605" .. 129 | "6405C936000000A4FC056405C9370000004C3E056405C93" .. 130 | "8000000091D056405C939000000E1DF056405C93A000000" .. 131 | "A0D5056405C93B0000004817056405C93C00000022C1056" .. 132 | "05C93D000000CA03056405C93E0000008B09056405C93F0" .. 133 | "0000063CB056405C940000000584A056405C941000000B0" .. 134 | "88056405C942000000F182056405C943000000194005640" .. 135 | "5C9440000007396056405C9450000009B54056405C94600" .. 136 | "0000DA5E056405C947000000329C056405C94800000077B" .. 137 | "F056405C9490000009F7D056405C94A000000DE77056405" .. 138 | "C94B00000036B5056405C94C0000005C63056405C94D000" .. 139 | "000B4A1056405C94E000000F5AB056405C94F0000001D69" .. 140 | "056405C9500000007FED056405C951000000972F056405C" .. 141 | "952000000D625056405C9530000003EE7056405C9540000" .. 142 | "005431056405C955000000BCF3056405C956000000FDF90" .. 143 | "56405C957000000153B056405C9580000005018056405C9" .. 144 | "59000000B8DA056405C95A000000F9D0056405C95B00000" .. 145 | "01112056405C95C0000007BC4056405C95D000000930605" .. 146 | "6405C95E000000D20C056405C95F0000003ACE056405C96" .. 147 | "00000006F49056405C961000000878B056405C962000000" .. 148 | "C681056405C9630000002E43056405C9640000004495") 149 | -- Connect to the remote host 150 | local constatus, conerr = sock:connect(host, port) 151 | if not constatus then 152 | stdnse.debug1( 153 | 'Error establishing a TCP connection for %s - %s', host, conerr 154 | ) 155 | return nil 156 | end 157 | -- send query for the first 100 addresses 158 | local sendstatus, senderr = sock:send(first100) 159 | if not sendstatus then 160 | stdnse.debug1( 161 | 'Error sending dnp3 request to %s:%d - %s', 162 | host.ip, port.number, senderr 163 | ) 164 | return nil 165 | end 166 | -- receive the response for parseing 167 | local rcvstatus, response = sock:receive() 168 | if(rcvstatus == false) then 169 | stdnse.debug1( "Receive error: %s", response) 170 | return nil 171 | end 172 | -- if the response was timeout, then we will return that we had a timeout 173 | --(for now add more addresses later) 174 | if (response == "TIMEOUT" or response == "EOF") then 175 | sock:close() 176 | return "TIMEOUT: No response from query" 177 | end 178 | -- unpack first two bytes 179 | local pos, byte1, byte2 = bin.unpack("CC", response, 1) 180 | -- check to see if it is 0x0564 181 | if( byte1 == 0x05 and byte2 == 0x64) then 182 | -- close socket 183 | sock:close() 184 | -- set nmap to reflect open DNP3 185 | set_nmap(host,port) 186 | -- unpack bit string for PRM checking as well as function codes 187 | local pos, ctrl = bin.unpack("B", response, 4) 188 | -- destination address 189 | local pos, dstadd = bin.unpack("S", response, 5) 190 | -- source address 191 | local pos, srceadd = bin.unpack("S", response, pos) 192 | -- set up output table with values 193 | output["Source Address"] = srceadd 194 | output["Destination Address"] = dstadd 195 | output["Control"] = funct_lookup(ctrl) 196 | -- return output 197 | return output 198 | -- if non 0x0564 response, then this is not a valid packet. 199 | else 200 | sock:close() 201 | return "ERROR: Non Valid DNP3 Packet Response\n\t" .. stdnse.tohex(response) 202 | end 203 | 204 | end 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /fox-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local string = require "string" 6 | local table = require "table" 7 | 8 | description = [[ 9 | 10 | Tridium Niagara Fox is a protocol used within Building Automation Systems. Based 11 | off Billy Rios and Terry McCorkle's work this Nmap NSE will collect information 12 | from A Tridium Niagara system. The information is collected via TCP/1911, 13 | the default Tridium Niagara Fox Port. 14 | 15 | http://digitalbond.com 16 | 17 | ]] 18 | 19 | --- 20 | -- @usage 21 | -- nmap --script fox-info.nse -p 1911 22 | -- 23 | -- @args aggressive - boolean value defines find all or just first sid 24 | -- 25 | -- @output 26 | -- 1911/tcp open Niagara Fox 27 | -- | fox-info: 28 | -- | Fox Version: 1.0.1 29 | -- | Host Name: xpvm-0omdc01xmy 30 | -- | Host Address: 192.168.1.1 31 | -- | Application Name: Workbench 32 | -- | Application Version: 3.7.44 33 | -- | VM Name: Java HotSpot(TM) Server VM 34 | -- | VM Version: 20.4-b02 35 | -- | OS Name: Windows XP 36 | -- | Time Zone: America/Chicago 37 | -- | Host ID: Win-99CB-D49D-5442-07BB 38 | -- | VM UUID: 8b530bc8-76c5-4139-a2ea-0fabd394d305 39 | -- |_ Brand ID: vykon 40 | -- 41 | -- @xmloutput 42 | --1.0.1 43 | --xpvm-0omdc01xmy 44 | --192.168.1.1 45 | --Workbench 46 | --3.7.44 47 | --Java HotSpot(TM) Server VM 48 | --20.4-b02 49 | --Windows XP 50 | --America/Chicago 51 | --Win-99CB-D49D-5442-07BB 52 | --8b530bc8-76c5-4139-a2ea-0fabd394d305 53 | --vykon 54 | 55 | author = "Stephen Hilt (Digital Bond)" 56 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 57 | categories = {"discovery", "intrusive"} 58 | 59 | 60 | -- 61 | -- Function to define the portrule as per nmap standards 62 | -- 63 | -- 64 | -- 65 | 66 | portrule = shortport.port_or_service(1911, "mtp", "tcp") 67 | 68 | -- 69 | -- Function to split a string based on a separator 70 | -- 71 | -- @param sep A separator to split the string upon 72 | function string:split(sep) 73 | local sep, fields = sep or ":", {} 74 | local pattern = string.format("([^%s]+)", sep) 75 | self:gsub(pattern, function(c) fields[#fields+1] = c end) 76 | return fields 77 | end 78 | 79 | --- 80 | -- Function to set the Nmap output for the host, if a valid Niagara Fox packet 81 | -- is received then the output will show that the port is open instead of 82 | -- open|filtered 83 | -- 84 | -- @param host Host that was passed in via nmap 85 | -- @param port port that Niagara Fox is running on (Default UDP/47808) 86 | function set_nmap(host, port) 87 | 88 | --set port Open 89 | port.state = "open" 90 | -- set version name to Niagara Fox 91 | port.version.name = "Niagara Fox" 92 | nmap.set_port_version(host, port) 93 | nmap.set_port_state(host, port, "open") 94 | 95 | end 96 | 97 | -- 98 | -- Function to term the length of a table/array 99 | -- 100 | -- @param t a table that is passed in 101 | function len(t) 102 | count = 0 103 | for k,v in pairs(t) do 104 | count = count + 1 105 | end 106 | return count 107 | end 108 | 109 | --- 110 | -- Action Function that is used to run the NSE. This function will send the 111 | -- initial query to the host and port that were passed in via nmap. The 112 | -- initial response is parsed to determine if host is a Niagara Fox device. If it 113 | -- is then more actions are taken to gather extra information. 114 | -- 115 | -- @param host Host that was scanned via nmap 116 | -- @param port port that was scanned via nmap 117 | action = function(host, port) 118 | --set the first query data for sending 119 | local orig_query = bin.pack( "H","666f7820612031202d3120666f782068656c6c6f0a7b0a" .. 120 | "666f782e76657273696f6e3d733a312e300a69643d693a310a686f73744e" .. 121 | "616d653d733a7870766d2d306f6d64633031786d790a686f737441646472" .. 122 | "6573733d733a3139322e3136382e312e3132350a6170702e6e616d653d73" .. 123 | "3a576f726b62656e63680a6170702e76657273696f6e3d733a332e372e34" .. 124 | "340a766d2e6e616d653d733a4a61766120486f7453706f7428544d292053" .. 125 | "657276657220564d0a766d2e76657273696f6e3d733a32302e342d623032" .. 126 | "0a6f732e6e616d653d733a57696e646f77732058500a6f732e7665727369" .. 127 | "6f6e3d733a352e310a6c616e673d733a656e0a74696d655a6f6e653d733a" .. 128 | "416d65726963612f4c6f735f416e67656c65733b2d32383830303030303b" .. 129 | "333630303030303b30323a30303a30302e3030302c77616c6c2c6d617263" .. 130 | "682c382c6f6e206f722061667465722c73756e6461792c756e646566696e" .. 131 | "65643b30323a30303a30302e3030302c77616c6c2c6e6f76656d6265722c" .. 132 | "312c6f6e206f722061667465722c73756e6461792c756e646566696e6564" .. 133 | "0a686f737449643d733a57696e2d393943422d443439442d353434322d30" .. 134 | "3742420a766d557569643d733a38623533306263382d373663352d343133" .. 135 | "392d613265612d3066616264333934643330350a6272616e6449643d733a" .. 136 | "76796b6f6e0a7d3b3b0a" ) 137 | -- output table that will be returned to nmap 138 | local to_return = stdnse.output_table() 139 | 140 | -- create new socket 141 | local sock = nmap.new_socket() 142 | -- connect to the remote host 143 | local constatus, conerr = sock:connect(host, port) 144 | if not constatus then 145 | stdnse.debug1( 146 | 'Error establishing a UDP connection for %s - %s', host, conerr 147 | ) 148 | return nil 149 | end 150 | -- send the original query to see if it is a valid Niagara Fox Device 151 | local sendstatus, senderr = sock:send(orig_query) 152 | if not sendstatus then 153 | stdnse.debug1( 154 | 'Error sending Niagara Fox request to %s:%d - %s', 155 | host.ip, port.number, senderr 156 | ) 157 | return nil 158 | end 159 | 160 | -- receive response 161 | local rcvstatus, response = sock:receive() 162 | if(rcvstatus == false) then 163 | stdnse.debug1( "Receive error: %s", response) 164 | return nil 165 | end 166 | -- split the response on 0x0a (NL char) 167 | local output = response:split("\x0a") 168 | -- for each value in side of the created array 169 | for keys,value in pairs(output) do 170 | -- if string contains hostName 171 | if ( string.match(value, "hostName") ) then 172 | local temp = value:split(":") 173 | to_return["Host Name"] = temp[2] 174 | -- if response contains hostAddress 175 | elseif (string.match(value, "hostAddress") ) then 176 | local temp = value:split(":") 177 | to_return["Host Address"] = temp[2] 178 | -- if response contains fox.version 179 | elseif ( string.match(value, "fox.version") ) then 180 | local temp = value:split(":") 181 | to_return["Fox Version"] = temp[2] 182 | -- if response contains app.name 183 | elseif ( string.match(value, "app.name") ) then 184 | local temp = value:split(":") 185 | to_return["Application Name"] = temp[2] 186 | -- if response contains app.version 187 | elseif ( string.match(value,"app.version") ) then 188 | local temp = value:split(":") 189 | to_return["Application Version"] = temp[2] 190 | -- if response contains vm.name 191 | elseif ( string.match(value, "vm.name") ) then 192 | local temp = value:split(":") 193 | to_return["VM Name"] = temp[2] 194 | -- if response contains vm.version 195 | elseif ( string.match(value, "vm.version") ) then 196 | local temp = value:split(":") 197 | to_return["VM Version"] = temp[2] 198 | --if response contains os.name 199 | elseif ( string.match(value,"os.name") ) then 200 | local temp = value:split(":") 201 | to_return["OS Name"] = temp[2] 202 | -- if response contains timeZone 203 | elseif (string.match(value,"timeZone") ) then 204 | local temp = value:split(":") 205 | -- split again just for the timezone name 206 | local temp2 = temp[2]:split(";") 207 | -- if response contains hostId 208 | elseif ( string.match(value,"hostId") ) then 209 | local temp = value:split(":") 210 | to_return["Host ID"] = temp[2] 211 | -- if response contains vmUuid 212 | elseif ( string.match(value,"vmUuid") ) then 213 | local temp = value:split(":") 214 | to_return["VM UUID"] = temp[2] 215 | -- if response contains brandId 216 | elseif ( string.match(value, "brandId") ) then 217 | local temp = value:split(":") 218 | to_return["Brand ID"] = temp[2] 219 | end 220 | -- if the length of the table is 0, then we didn't parse anything 221 | if( len(to_return) ~= 0 ) then 222 | -- set nmap output if we did parse information 223 | set_nmap(host,port) 224 | end 225 | end 226 | -- return output table to nmap 227 | return to_return 228 | end 229 | 230 | -------------------------------------------------------------------------------- /s7-enumerate.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local string = require "string" 6 | local table = require "table" 7 | 8 | 9 | description = [[ 10 | Enumerates Siemens S7 PLC Devices and collects their device information. This 11 | script is based off PLCScan that was developed by Positive Research and 12 | Scadastrangelove (https://code.google.com/p/plcscan/). This script is meant to 13 | provide the same functionality as PLCScan inside of Nmap. Some of the 14 | information that is collected by PLCScan was not ported over; this 15 | information can be parsed out of the packets that are received. 16 | 17 | Thanks to Positive Research, and Dmitry Efanov for creating PLCScan 18 | ]] 19 | 20 | author = "Stephen Hilt (Digital Bond)" 21 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 22 | categories = {"discovery", "intrusive"} 23 | 24 | --- 25 | -- @usage 26 | -- nmap --script s7-info.nse -p 102 27 | -- 28 | -- @output 29 | --102/tcp open Siemens S7 PLC 30 | --| s7-info: 31 | --| Basic Hardware: 6ES7 315-2AG10-0AB0 32 | --| System Name: SIMATIC 300(1) 33 | --| Copyright: Original Siemens Equipment 34 | --| Version: 2.6.9 35 | --| Module Type: CPU 315-2 DP 36 | --| Module: 6ES7 315-2AG10-0AB0 37 | --|_ Serial Number: S C-X4U421302009 38 | -- 39 | -- 40 | -- @xmloutput 41 | --6ES7 315-2AG10-0AB0 42 | --SIMATIC 300(1) 43 | --Original Siemens Equipment 44 | --2.6.9 45 | --SimpleServer 46 | --CPU 315-2 DP 47 | --6ES7 315-2AG10-0AB0 48 | --S C-X4U421302009 49 | -- 50 | 51 | 52 | -- port rule for devices running on TCP/102 53 | portrule = shortport.port_or_service(102, "iso-tsap", "tcp") 54 | 55 | --- 56 | -- Function to send and receive the S7COMM Packet 57 | -- 58 | -- First argument is the socket that was created inside of the main Action 59 | -- this will be utilized to send and receive the packets from the host. 60 | -- the second argument is the query to be sent, this is passed in and is created 61 | -- inside of the main action. 62 | -- @param socket the socket that was created in Action. 63 | -- @param query the specific query that you want to send/receive on. 64 | local function send_receive(socket, query) 65 | local sendstatus, senderr = socket:send(query) 66 | if(sendstatus == false) then 67 | return "Error Sending S7COMM" 68 | end 69 | -- receive response 70 | local rcvstatus, response = socket:receive() 71 | if(rcvstatus == false) then 72 | return "Error Reading S7COMM" 73 | end 74 | return response 75 | end 76 | 77 | --- 78 | -- Function to parse the first SZL Request response that was received from the S7 PLCC 79 | -- 80 | -- First argument is the socket that was created inside of the main Action 81 | -- this will be utilized to send and receive the packets from the host. 82 | -- the second argument is the query to be sent, this is passed in and is created 83 | -- inside of the main action. 84 | -- @param response Packet response that was received from S7 host. 85 | -- @param host The host hat was passed in via Nmap, this is to change output of host/port 86 | -- @param port The port that was passed in via Nmap, this is to change output of host/port 87 | -- @param output Table used for output for return to Nmap 88 | local function parse_response(response, host, port, output) 89 | -- unpack the protocol ID 90 | local pos, value = bin.unpack("C", response, 8) 91 | -- unpack the second byte of the SZL-ID 92 | local pos, szl_id = bin.unpack("C", response, 31) 93 | -- set the offset to 0 94 | local offset = 0 95 | -- if the protocol ID is 0x32 96 | if (value == 0x32) then 97 | local pos 98 | -- unpack the module information 99 | pos, output["Module"] = bin.unpack("z", response, 44) 100 | -- unpack the basic hardware information 101 | pos, output["Basic Hardware"] = bin.unpack("z", response, 72) 102 | -- set version number to 0 103 | local version = 0 104 | -- parse version number 105 | local pos, char1, char2, char3 = bin.unpack("CCC", response, 123) 106 | -- concatenate string, or if string is nil make version number 0.0 107 | output["Version"] = table.concat({char1 or "0.0", char2, char3}, ".") 108 | -- return the output table 109 | return output 110 | else 111 | return nil 112 | end 113 | end 114 | 115 | --- 116 | -- Function to parse the second SZL Request response that was received from the S7 PLC 117 | -- 118 | -- First argument is the socket that was created inside of the main Action 119 | -- this will be utilized to send and receive the packets from the host. 120 | -- the second argument is the query to be sent, this is passed in and is created 121 | -- inside of the main action. 122 | -- @param response Packet response that was received from S7 host. 123 | -- @param output Table used for output for return to Nmap 124 | local function second_parse_response(response, output) 125 | local offset = 0 126 | -- unpack the protocol ID 127 | local pos, value = bin.unpack("C", response, 8) 128 | -- unpack the second byte of the SZL-ID 129 | local pos, szl_id = bin.unpack("C", response, 31) 130 | -- if the protocol ID is 0x32 131 | if (value == 0x32) then 132 | -- if the szl-ID is not 0x1c 133 | if( szl_id ~= 0x1c ) then 134 | -- change offset to 4, this is where most of valid PLCs will fall 135 | offset = 4 136 | end 137 | -- parse system name 138 | pos, output["System Name"] = bin.unpack("z", response, 40 + offset) 139 | -- parse module type 140 | pos, output["Module Type"] = bin.unpack("z", response, 74 + offset) 141 | -- parse serial number 142 | pos, output["Serial Number"] = bin.unpack("z", response, 176 + offset) 143 | -- parse plant identification 144 | pos, output["Plant Identification"] = bin.unpack("z", response, 108 + offset) 145 | -- parse copyright 146 | pos, output["Copyright"] = bin.unpack("z", response, 142 + offset) 147 | 148 | -- for each element in the table, if it is nil, then remove the information from the table 149 | for key, value in pairs(output) do 150 | if(string.len(output[key]) == 0) then 151 | output[key] = nil 152 | end 153 | end 154 | -- return output 155 | return output 156 | else 157 | return nil 158 | end 159 | end 160 | --- 161 | -- Function to set the nmap output for the host, if a valid S7COMM packet 162 | -- is received then the output will show that the port is open 163 | -- and change the output to reflect an S7 PLC 164 | -- 165 | -- @param host Host that was passed in via nmap 166 | -- @param port port that S7COMM is running on 167 | local function set_nmap(host, port) 168 | --set port Open 169 | port.state = "open" 170 | -- set that detected an Siemens S7 171 | port.version.name = "iso-tsap" 172 | port.version.devicetype = "specialized" 173 | port.version.product = "Siemens S7 PLC" 174 | nmap.set_port_version(host, port) 175 | nmap.set_port_state(host, port, "open") 176 | 177 | end 178 | --- 179 | -- Action Function that is used to run the NSE. This function will send the initial query to the 180 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 181 | -- is a S7COMM device. If it is then more actions are taken to gather extra information. 182 | -- 183 | -- @param host Host that was scanned via nmap 184 | -- @param port port that was scanned via nmap 185 | action = function(host, port) 186 | -- COTP packet with a dst of 102 187 | local COTP = bin.pack("H", "0300001611e00000001400c1020100c2020" .. "102" .. "c0010a") 188 | -- COTP packet with a dst of 200 189 | local alt_COTP = bin.pack("H", "0300001611e00000000500c1020100c2020" .. "200" .. "c0010a") 190 | -- setup the ROSCTR Packet 191 | local ROSCTR_Setup = bin.pack("H", "0300001902f08032010000000000080000f0000001000101e0") 192 | -- setup the Read SZL information packet 193 | local Read_SZL = bin.pack("H", "0300002102f080320700000000000800080001120411440100ff09000400110001") 194 | -- setup the first SZL request (gather the basic hardware and version number) 195 | local first_SZL_Request = bin.pack("H", "0300002102f080320700000000000800080001120411440100ff09000400110001") 196 | -- setup the second SZL request 197 | local second_SZL_Request = bin.pack("H", "0300002102f080320700000000000800080001120411440100ff090004001c0001") 198 | -- response is used to collect the packet responses 199 | local response 200 | -- output table for Nmap 201 | local output = stdnse.output_table() 202 | -- create socket for communications 203 | local sock = nmap.new_socket() 204 | -- connect to host 205 | local constatus, conerr = sock:connect(host, port) 206 | if not constatus then 207 | stdnse.debug1('Error establishing connection for %s - %s', host, conerr) 208 | return nil 209 | end 210 | -- send and receive the COTP Packet 211 | response = send_receive(sock, COTP) 212 | -- unpack the PDU Type 213 | local pos, CC_connect_confirm = bin.unpack("C", response, 6) 214 | -- if PDU type is not 0xd0, then not a successful COTP connection 215 | if ( CC_connect_confirm ~= 0xd0) then 216 | sock:close() 217 | -- create socket for communications 218 | stdnse.debug1('S7INFO:: CREATING NEW SOCKET') 219 | sock = nmap.new_socket() 220 | -- connect to host 221 | local constatus, conerr = sock:connect(host, port) 222 | if not constatus then 223 | stdnse.debug1('Error establishing connection for %s - %s', host, conerr) 224 | return nil 225 | end 226 | response = send_receive(sock, alt_COTP) 227 | local pos, CC_connect_confirm = bin.unpack("C", response, 6) 228 | if ( CC_connect_confirm ~= 0xd0) then 229 | stdnse.debug1('S7 INFO:: Could not negotiate COTP') 230 | return nil 231 | end 232 | end 233 | -- send and receive the ROSCTR Setup Packet 234 | response = send_receive(sock, ROSCTR_Setup) 235 | -- unpack the protocol ID 236 | local pos, protocol_id = bin.unpack("C", response, 8) 237 | -- if protocol ID is not 0x32 then return nil 238 | if ( protocol_id ~= 0x32) then 239 | return nil 240 | end 241 | -- send and receive the READ_SZL packet 242 | response = send_receive(sock, Read_SZL) 243 | local pos, protocol_id = bin.unpack("C", response, 8) 244 | -- if protocol ID is not 0x32 then return nil 245 | if ( protocol_id ~= 0x32) then 246 | return nil 247 | end 248 | -- send and receive the first SZL Request packet 249 | response = send_receive(sock, first_SZL_Request) 250 | -- parse the response for basic hardware information 251 | output = parse_response(response, host, port, output) 252 | -- send and receive the second SZL Request packet 253 | response = send_receive(sock, second_SZL_Request) 254 | -- parse the response for more information 255 | output = second_parse_response(response, output) 256 | -- close the socket 257 | sock:close() 258 | 259 | -- If we parsed anything, then set the version info for Nmap 260 | if #output > 0 then 261 | set_nmap(host, port) 262 | end 263 | -- return output to Nmap 264 | return output 265 | 266 | end 267 | -------------------------------------------------------------------------------- /modicon-info.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local nmap = require "nmap" 3 | local shortport = require "shortport" 4 | local stdnse = require "stdnse" 5 | local string = require "string" 6 | local table = require "table" 7 | 8 | description = [[ 9 | Modicon is a brand of Programmable Logic Controller (PLC) that is put out by 10 | Schneider Electric. This NSE is designed to use Modbus to communicate to the 11 | PLC via Normal queries that are performed via engineering software. The information 12 | that is collected via Modbus is done in two separate function codes. First, Function 13 | Code 43 is utilized to pull the Vendor Name, Network Module, and the Firmware Version. 14 | Second, Schneider uses function code 90 for communications as well. Via Function Code 90 15 | it is possible to pull information such as the CPU Module, Memory Card Model, and some 16 | information about the project that is loaded into the PLC. 17 | 18 | 19 | http://digitalbond.com 20 | ]] 21 | --- 22 | -- @usage 23 | -- nmap --script modicon-info -p 502 24 | -- 25 | -- 26 | -- @output 27 | --502/tcp open Modbus 28 | --| modicon-info: 29 | --| Vendor Name: Schneider Electric 30 | --| Network Module: BMX NOE 0100 31 | --| CPU Module: BMX P34 2000 32 | --| Firmware: V2.60 33 | --| Memory Card: BMXRMS008MP 34 | --| Project Information: Project - V4.0 35 | --| Project File Name: Project.STU 36 | --| Project Revision: 0.0.9 37 | --|_ Project Last Modified: 7/11/2013 5:55:33 38 | -- @xmloutput 39 | --Schneider Electric 40 | --BMX NOE 0100 41 | --BMX P34 2000 42 | --V2.60 43 | --BMXRMS008MP 44 | --Project - V4.0 45 | --Project.STU 46 | --0.0.9 47 | --7/11/2013 5:55:33 48 | 49 | author = "Stephen Hilt (Digital Bond)" 50 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 51 | categories = {"discovery", "intrusive","digitalbond"} 52 | 53 | -- 54 | -- Function to define the portrule as per nmap standards 55 | -- 56 | -- 57 | -- 58 | portrule = shortport.portnumber(502, "tcp") 59 | 60 | --- 61 | -- Function to trim white space off the beginning and ending of a string 62 | -- 63 | -- @param s a string passed in that needs white space trimmed off 64 | function trim(s) 65 | -- remove white spaces from beginning and ending of the string 66 | return (s:gsub("^%s*(.-)%s*$", "%1")) 67 | end 68 | --- 69 | -- Function to set the nmap output for the host, if a valid Modbus packet 70 | -- is received then the output will show that the port as Modbus. 71 | -- 72 | -- @param host Host that was passed in via nmap 73 | -- @param port port that Modbus is running on (Default TCP/502) 74 | function set_nmap(host, port) 75 | 76 | --set port Open 77 | port.state = "open" 78 | -- set version name to Modbus 79 | port.version.name = "Modbus" 80 | nmap.set_port_version(host, port) 81 | nmap.set_port_state(host, port, "open") 82 | 83 | end 84 | --- 85 | -- Function to setup the communications to the Modicon. This is where alot 86 | -- of the function code 90 information is sent and parsed for information 87 | -- about the Modicon itself. 88 | -- 89 | -- @param socket Socket passed in via Action to communicate to remote device 90 | -- @param output The output table to add information that is collected 91 | --- 92 | function init_comms(socket, output) 93 | 94 | -- decelerations 95 | local pos 96 | local payload = bin.pack("H","000100000004005a0002") 97 | socket:send(payload) 98 | -- recv packet, however not going to do anything with it 99 | local rcvstatus, response = socket:receive() 100 | -- send and receive, not going to do anything with this packet. 101 | payload = bin.pack("H","000200000005005a000100") 102 | socket:send(payload) 103 | local rcvstatus, response = socket:receive() 104 | -- create a string with 249 T (0x54) 105 | local count = 0 106 | local ice = "54" 107 | while (count < 248) do 108 | ice = ice .. "54" 109 | count = count + 1 110 | end 111 | -- send packet with 249 T's (0x54), recv packet and do nothing as well 112 | payload = bin.pack("H","0003000000fe005a00fe00" .. ice) 113 | socket:send(payload) 114 | local rcvstatus, response = socket:receive() 115 | -- send packet that request the project information 116 | payload = bin.pack("H","000400000005005a000300") 117 | socket:send(payload) 118 | local rcvstatus, response = socket:receive() 119 | -- unpack the Project Name, this is configured by the engineers 120 | local pos, project_name = bin.unpack("z", response, 50) 121 | -- unpack the year that the project was last modified 122 | -- define the next sections we are going to unpack 123 | -- Each one is to support time stamp 124 | local project_hour 125 | local project_min 126 | local project_sec 127 | local project_month 128 | local project_day 129 | -- define the 3 vars for the project revision number 130 | local project_rev_1 131 | local project_rev_2 132 | local project_rev_3 133 | -- unpack the time stamp, as well as the revision numbers 134 | -- unpack the seconds 135 | pos, project_sec = bin.unpack("C", response, 38) 136 | -- unpack the min 137 | pos, project_min = bin.unpack("C", response, pos) 138 | -- unpack the hour 139 | pos, project_hour = bin.unpack("C", response, pos) 140 | -- unpack the day 141 | pos, project_day = bin.unpack("C", response, pos) 142 | -- unpack the month 143 | pos, project_month = bin.unpack("C", response, pos) 144 | pos, project_year = bin.unpack(" 38 | -- 39 | -- @args full If set yes the script will run the FDT and BBMD Checks 40 | -- 41 | -- @output 42 | --47808/udp open BACNet -- Building Automation and Control Networks 43 | --| BACnet-discover-enumerate.nse: 44 | --| Vendor ID: BACnet Stack at SourceForge (260) 45 | --| Instance Number: 260001 46 | --| Firmware: 0.8.2 47 | --| Application Software: 1.0 48 | --| Object Name: SimpleServer 49 | --| Model Name: GNU 50 | --| Description: server 51 | --| Location: USA 52 | --| BACnet Broadcast Management Device (BBMD): 53 | --| 192.168.0.100:47808 54 | --| Foreign Device Table (FDT): 55 | --|_ 192.168.1.101:47809:ttl=60:timeout=37 56 | 57 | -- 58 | -- @xmloutput 59 | --BACnet Stack at SourceForge (260) 60 | --260001 61 | --0.8.2 62 | --1.0 63 | --SimpleServer 64 | --GNU 65 | --server 66 | --USA 67 | --192.168.0.100:47808 68 | --192.168.1.101:47809:ttl=60:timeout=37 69 | 70 | author = "Stephen Hilt(Digital Bond)" 71 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 72 | categories = {"discovery", "intrusive"} 73 | 74 | -- 75 | -- Function to define the portrule as per nmap standards 76 | -- 77 | -- 78 | -- 79 | 80 | portrule = shortport.port_or_service(47808, "bacnet", "udp") 81 | 82 | --- 83 | -- Function to determine if a string starts with the parameter that is passed in 84 | -- 85 | -- First argument is the string to be evaluated, the second argument is 86 | -- the character(s) to be tested if the string starts with this argument. Uses Lua 87 | -- string.sub and string.len 88 | -- @param String String to be passed in. 89 | -- @param Start The char you want to test to see the string starts with. 90 | function string.starts(String,Start) 91 | return string.sub(String,1,string.len(Start))==Start 92 | end 93 | 94 | --- 95 | -- Table to look up the Vendor Name based on Vendor ID 96 | -- Table data from http://www.bacnet.org/VendorID/BACnet%20Vendor%20IDs.htm 97 | -- Fetched on 3/18/2014 98 | -- 99 | -- @key vennum Vendor number parsed out of the BACNet packet 100 | local vendor_id = { 101 | [0] = "ASHRAE", 102 | [1] = "NIST", 103 | [2] = "The Trane Company", 104 | [3] = "McQuay International", 105 | [4] = "PolarSoft", 106 | [5] = "Johnson Controls Inc.", 107 | [6] = "American Auto-Matrix", 108 | [7] = "Siemens Schweiz AG (Formerly: Landis & Staefa Division Europe)", 109 | [8] = "Delta Controls", 110 | [9] = "Siemens Schweiz AG", 111 | [10] = "Schneider Electric", 112 | [11] = "TAC", 113 | [12] = "Orion Analysis Corporation", 114 | [13] = "Teletrol Systems Inc.", 115 | [14] = "Cimetrics Technology", 116 | [15] = "Cornell University", 117 | [16] = "United Technologies Carrier", 118 | [17] = "Honeywell Inc.", 119 | [18] = "Alerton / Honeywell", 120 | [19] = "TAC AB", 121 | [20] = "Hewlett-Packard Company", 122 | [21] = "Dorsette.s Inc.", 123 | [22] = "Siemens Schweiz AG (Formerly: Cerberus AG)", 124 | [23] = "York Controls Group", 125 | [24] = "Automated Logic Corporation", 126 | [25] = "CSI Control Systems International", 127 | [26] = "Phoenix Controls Corporation", 128 | [27] = "Innovex Technologies Inc.", 129 | [28] = "KMC Controls Inc.", 130 | [29] = "Xn Technologies Inc.", 131 | [30] = "Hyundai Information Technology Co. Ltd.", 132 | [31] = "Tokimec Inc.", 133 | [32] = "Simplex", 134 | [33] = "North Building Technologies Limited", 135 | [34] = "Notifier", 136 | [35] = "Reliable Controls Corporation", 137 | [36] = "Tridium Inc.", 138 | [37] = "Sierra Monitor Corporation/FieldServer Technologies", 139 | [38] = "Silicon Energy", 140 | [39] = "Kieback & Peter GmbH & Co KG", 141 | [40] = "Anacon Systems Inc.", 142 | [41] = "Systems Controls & Instruments LLC", 143 | [42] = "Lithonia Lighting", 144 | [43] = "Micropower Manufacturing", 145 | [44] = "Matrix Controls", 146 | [45] = "METALAIRE", 147 | [46] = "ESS Engineering", 148 | [47] = "Sphere Systems Pty Ltd.", 149 | [48] = "Walker Technologies Corporation", 150 | [49] = "H I Solutions Inc.", 151 | [50] = "MBS GmbH", 152 | [51] = "SAMSON AG", 153 | [52] = "Badger Meter Inc.", 154 | [53] = "DAIKIN Industries Ltd.", 155 | [54] = "NARA Controls Inc.", 156 | [55] = "Mammoth Inc.", 157 | [56] = "Liebert Corporation", 158 | [57] = "SEMCO Incorporated", 159 | [58] = "Air Monitor Corporation", 160 | [59] = "TRIATEK LLC", 161 | [60] = "NexLight", 162 | [61] = "Multistack", 163 | [62] = "TSI Incorporated", 164 | [63] = "Weather-Rite Inc.", 165 | [64] = "Dunham-Bush", 166 | [65] = "Reliance Electric", 167 | [66] = "LCS Inc.", 168 | [67] = "Regulator Australia PTY Ltd.", 169 | [68] = "Touch-Plate Lighting Controls", 170 | [69] = "Amann GmbH", 171 | [70] = "RLE Technologies", 172 | [71] = "Cardkey Systems", 173 | [72] = "SECOM Co. Ltd.", 174 | [73] = "ABB Gebäetechnik AG Bereich NetServ", 175 | [74] = "KNX Association cvba", 176 | [75] = "Institute of Electrical Installation Engineers of Japan (IEIEJ)", 177 | [76] = "Nohmi Bosai Ltd.", 178 | [77] = "Carel S.p.A.", 179 | [78] = "AirSense Technology Inc.", 180 | [79] = "Hochiki Corporation", 181 | [80] = "Fr. Sauter AG", 182 | [81] = "Matsushita Electric Works Ltd.", 183 | [82] = "Mitsubishi Electric Corporation Inazawa Works", 184 | [83] = "Mitsubishi Heavy Industries Ltd.", 185 | [84] = "ITT Bell & Gossett", 186 | [85] = "Yamatake Building Systems Co. Ltd.", 187 | [86] = "The Watt Stopper Inc.", 188 | [87] = "Aichi Tokei Denki Co. Ltd.", 189 | [88] = "Activation Technologies LLC", 190 | [89] = "Saia-Burgess Controls Ltd.", 191 | [90] = "Hitachi Ltd.", 192 | [91] = "Novar Corp./Trend Control Systems Ltd.", 193 | [92] = "Mitsubishi Electric Lighting Corporation", 194 | [93] = "Argus Control Systems Ltd.", 195 | [94] = "Kyuki Corporation", 196 | [95] = "Richards-Zeta Building Intelligence Inc.", 197 | [96] = "Scientech R&D Inc.", 198 | [97] = "VCI Controls Inc.", 199 | [98] = "Toshiba Corporation", 200 | [99] = "Mitsubishi Electric Corporation Air Conditioning & Refrigeration Systems Works", 201 | [100] = "Custom Mechanical Equipment LLC", 202 | [101] = "ClimateMaster", 203 | [102] = "ICP Panel-Tec Inc.", 204 | [103] = "D-Tek Controls", 205 | [104] = "NEC Engineering Ltd.", 206 | [105] = "PRIVA BV", 207 | [106] = "Meidensha Corporation", 208 | [107] = "JCI Systems Integration Services", 209 | [108] = "Freedom Corporation", 210 | [109] = "Neuberger Gebäeautomation GmbH", 211 | [110] = "Sitronix", 212 | [111] = "Leviton Manufacturing", 213 | [112] = "Fujitsu Limited", 214 | [113] = "Emerson Network Power", 215 | [114] = "S. A. Armstrong Ltd.", 216 | [115] = "Visonet AG", 217 | [116] = "M&M Systems Inc.", 218 | [117] = "Custom Software Engineering", 219 | [118] = "Nittan Company Limited", 220 | [119] = "Elutions Inc. (Wizcon Systems SAS)", 221 | [120] = "Pacom Systems Pty. Ltd.", 222 | [121] = "Unico Inc.", 223 | [122] = "Ebtron Inc.", 224 | [123] = "Scada Engine", 225 | [124] = "AC Technology Corporation", 226 | [125] = "Eagle Technology", 227 | [126] = "Data Aire Inc.", 228 | [127] = "ABB Inc.", 229 | [128] = "Transbit Sp. z o. o.", 230 | [129] = "Toshiba Carrier Corporation", 231 | [130] = "Shenzhen Junzhi Hi-Tech Co. Ltd.", 232 | [131] = "Tokai Soft", 233 | [132] = "Blue Ridge Technologies", 234 | [133] = "Veris Industries", 235 | [134] = "Centaurus Prime", 236 | [135] = "Sand Network Systems", 237 | [136] = "Regulvar Inc.", 238 | [137] = "AFDtek Division of Fastek International Inc.", 239 | [138] = "PowerCold Comfort Air Solutions Inc.", 240 | [139] = "I Controls", 241 | [140] = "Viconics Electronics Inc.", 242 | [141] = "Yaskawa America Inc.", 243 | [142] = "DEOS control systems GmbH", 244 | [143] = "Digitale Mess- und Steuersysteme AG", 245 | [144] = "Fujitsu General Limited", 246 | [145] = "Project Engineering S.r.l.", 247 | [146] = "Sanyo Electric Co. Ltd.", 248 | [147] = "Integrated Information Systems Inc.", 249 | [148] = "Temco Controls Ltd.", 250 | [149] = "Airtek International Inc.", 251 | [150] = "Advantech Corporation", 252 | [151] = "Titan Products Ltd.", 253 | [152] = "Regel Partners", 254 | [153] = "National Environmental Product", 255 | [154] = "Unitec Corporation", 256 | [155] = "Kanden Engineering Company", 257 | [156] = "Messner Gebäetechnik GmbH", 258 | [157] = "Integrated.CH", 259 | [158] = "Price Industries", 260 | [159] = "SE-Elektronic GmbH", 261 | [160] = "Rockwell Automation", 262 | [161] = "Enflex Corp.", 263 | [162] = "ASI Controls", 264 | [163] = "SysMik GmbH Dresden", 265 | [164] = "HSC Regelungstechnik GmbH", 266 | [165] = "Smart Temp Australia Pty. Ltd.", 267 | [166] = "Cooper Controls", 268 | [167] = "Duksan Mecasys Co. Ltd.", 269 | [168] = "Fuji IT Co. Ltd.", 270 | [169] = "Vacon Plc", 271 | [170] = "Leader Controls", 272 | [171] = "Cylon Controls Ltd.", 273 | [172] = "Compas", 274 | [173] = "Mitsubishi Electric Building Techno-Service Co. Ltd.", 275 | [174] = "Building Control Integrators", 276 | [175] = "ITG Worldwide (M) Sdn Bhd", 277 | [176] = "Lutron Electronics Co. Inc.", 278 | [178] = "LOYTEC Electronics GmbH", 279 | [179] = "ProLon", 280 | [180] = "Mega Controls Limited", 281 | [181] = "Micro Control Systems Inc.", 282 | [182] = "Kiyon Inc.", 283 | [183] = "Dust Networks", 284 | [184] = "Advanced Building Automation Systems", 285 | [185] = "Hermos AG", 286 | [186] = "CEZIM", 287 | [187] = "Softing", 288 | [188] = "Lynxspring", 289 | [189] = "Schneider Toshiba Inverter Europe", 290 | [190] = "Danfoss Drives A/S", 291 | [191] = "Eaton Corporation", 292 | [192] = "Matyca S.A.", 293 | [193] = "Botech AB", 294 | [194] = "Noveo Inc.", 295 | [195] = "AMEV", 296 | [196] = "Yokogawa Electric Corporation", 297 | [197] = "GFR Gesellschaft füelungstechnik", 298 | [198] = "Exact Logic", 299 | [199] = "Mass Electronics Pty Ltd dba Innotech Control Systems Australia", 300 | [200] = "Kandenko Co. Ltd.", 301 | [201] = "DTF Daten-Technik Fries", 302 | [202] = "Klimasoft Ltd.", 303 | [203] = "Toshiba Schneider Inverter Corporation", 304 | [204] = "Control Applications Ltd.", 305 | [205] = "KDT Systems Co. Ltd.", 306 | [206] = "Onicon Incorporated", 307 | [207] = "Automation Displays Inc.", 308 | [208] = "Control Solutions Inc.", 309 | [209] = "Remsdaq Limited", 310 | [210] = "NTT Facilities Inc.", 311 | [211] = "VIPA GmbH", 312 | [212] = "TSC21 Association of Japan", 313 | [213] = "Strato Automation", 314 | [214] = "HRW Limited", 315 | [215] = "Lighting Control & Design Inc.", 316 | [216] = "Mercy Electronic and Electrical Industries", 317 | [217] = "Samsung SDS Co.Ltd", 318 | [218] = "Impact Facility Solutions Inc.", 319 | [219] = "Aircuity", 320 | [220] = "Control Techniques Ltd.", 321 | [221] = "OpenGeneral Pty. Ltd.", 322 | [222] = "WAGO Kontakttechnik GmbH & Co. KG", 323 | [223] = "Cerus Industrial", 324 | [224] = "Chloride Power Protection Company", 325 | [225] = "Computrols Inc.", 326 | [226] = "Phoenix Contact GmbH & Co. KG", 327 | [227] = "Grundfos Management A/S", 328 | [228] = "Ridder Drive Systems", 329 | [229] = "Soft Device SDN BHD", 330 | [230] = "Integrated Control Technology Limited", 331 | [231] = "AIRxpert Systems Inc.", 332 | [232] = "Microtrol Limited", 333 | [233] = "Red Lion Controls", 334 | [234] = "Digital Electronics Corporation", 335 | [235] = "Ennovatis GmbH", 336 | [236] = "Serotonin Software Technologies Inc.", 337 | [237] = "LS Industrial Systems Co. Ltd.", 338 | [238] = "Square D Company", 339 | [239] = "S Squared Innovations Inc.", 340 | [240] = "Aricent Ltd.", 341 | [241] = "EtherMetrics LLC", 342 | [242] = "Industrial Control Communications Inc.", 343 | [243] = "Paragon Controls Inc.", 344 | [244] = "A. O. Smith Corporation", 345 | [245] = "Contemporary Control Systems Inc.", 346 | [246] = "Intesis Software SL", 347 | [247] = "Ingenieurgesellschaft N. Hartleb mbH", 348 | [248] = "Heat-Timer Corporation", 349 | [249] = "Ingrasys Technology Inc.", 350 | [250] = "Costerm Building Automation", 351 | [251] = "WILO SE", 352 | [252] = "Embedia Technologies Corp.", 353 | [253] = "Technilog", 354 | [254] = "HR Controls Ltd. & Co. KG", 355 | [255] = "Lennox International Inc.", 356 | [256] = "RK-Tec Rauchklappen-Steuerungssysteme GmbH & Co. KG", 357 | [257] = "Thermomax Ltd.", 358 | [258] = "ELCON Electronic Control Ltd.", 359 | [259] = "Larmia Control AB", 360 | [260] = "BACnet Stack at SourceForge", 361 | [261] = "G4S Security Services A/S", 362 | [262] = "Exor International S.p.A.", 363 | [263] = "Cristal Controles", 364 | [264] = "Regin AB", 365 | [265] = "Dimension Software Inc.", 366 | [266] = "SynapSense Corporation", 367 | [267] = "Beijing Nantree Electronic Co. Ltd.", 368 | [268] = "Camus Hydronics Ltd.", 369 | [269] = "Kawasaki Heavy Industries Ltd.", 370 | [270] = "Critical Environment Technologies", 371 | [271] = "ILSHIN IBS Co. Ltd.", 372 | [272] = "ELESTA Energy Control AG", 373 | [273] = "KROPMAN Installatietechniek", 374 | [274] = "Baldor Electric Company", 375 | [275] = "INGA mbH", 376 | [276] = "GE Consumer & Industrial", 377 | [277] = "Functional Devices Inc.", 378 | [278] = "ESAC", 379 | [279] = "M-System Co. Ltd.", 380 | [280] = "Yokota Co. Ltd.", 381 | [281] = "Hitranse Technology Co.LTD", 382 | [282] = "Federspiel Controls", 383 | [283] = "Kele Inc.", 384 | [284] = "Opera Electronics Inc.", 385 | [285] = "Gentec", 386 | [286] = "Embedded Science Labs LLC", 387 | [287] = "Parker Hannifin Corporation", 388 | [288] = "MaCaPS International Limited", 389 | [289] = "Link4 Corporation", 390 | [290] = "Romutec Steuer-u. Regelsysteme GmbH", 391 | [291] = "Pribusin Inc.", 392 | [292] = "Advantage Controls", 393 | [293] = "Critical Room Control", 394 | [294] = "LEGRAND", 395 | [295] = "Tongdy Control Technology Co. Ltd.", 396 | [296] = "ISSARO Integrierte Systemtechnik", 397 | [297] = "Pro-Dev Industries", 398 | [298] = "DRI-STEEM", 399 | [299] = "Creative Electronic GmbH", 400 | [300] = "Swegon AB", 401 | [301] = "Jan Brachacek", 402 | [302] = "Hitachi Appliances Inc.", 403 | [303] = "Real Time Automation Inc.", 404 | [304] = "ITEC Hankyu-Hanshin Co.", 405 | [305] = "Cyrus E&M Engineering Co. Ltd.", 406 | [306] = "Racine Federated Inc.", 407 | [307] = "Cirrascale Corporation", 408 | [308] = "Elesta GmbH Building Automation", 409 | [309] = "Securiton", 410 | [310] = "OSlsoft Inc.", 411 | [311] = "Hanazeder Electronic GmbH", 412 | [312] = "Honeywell Security DeutschlandNovar GmbH", 413 | [313] = "Siemens Energy & Automation Inc.", 414 | [314] = "ETM Professional Control GmbH", 415 | [315] = "Meitav-tec Ltd.", 416 | [316] = "Janitza Electronics GmbH", 417 | [317] = "MKS Nordhausen", 418 | [318] = "De Gier Drive Systems B.V.", 419 | [319] = "Cypress Envirosystems", 420 | [320] = "SMARTron s.r.o.", 421 | [321] = "Verari Systems Inc.", 422 | [322] = "K-W Electronic Service Inc.", 423 | [323] = "ALFA-SMART Energy Management", 424 | [324] = "Telkonet Inc.", 425 | [325] = "Securiton GmbH", 426 | [326] = "Cemtrex Inc.", 427 | [327] = "Performance Technologies Inc.", 428 | [328] = "Xtralis (Aust) Pty Ltd", 429 | [329] = "TROX GmbH", 430 | [330] = "Beijing Hysine Technology Co.Ltd", 431 | [331] = "RCK Controls Inc.", 432 | [332] = "Distech Controls SAS", 433 | [333] = "Novar/Honeywell", 434 | [334] = "The S4 Group Inc.", 435 | [335] = "Schneider Electric", 436 | [336] = "LHA Systems", 437 | [337] = "GHM engineering Group Inc.", 438 | [338] = "Cllimalux S.A.", 439 | [339] = "VAISALA Oyj", 440 | [340] = "COMPLEX (Beijing) TechnologyCo. Ltd.", 441 | [341] = "SCADAmetrics", 442 | [342] = "POWERPEG NSI Limited", 443 | [343] = "BACnet Interoperability Testing Services Inc.", 444 | [344] = "Teco a.s.", 445 | [345] = "Plexus Technology Inc.", 446 | [346] = "Energy Focus Inc.", 447 | [347] = "Powersmiths International Corp.", 448 | [348] = "Nichibei Co. Ltd.", 449 | [349] = "HKC Technology Ltd.", 450 | [350] = "Ovation Networks Inc.", 451 | [351] = "Setra Systems", 452 | [352] = "AVG Automation", 453 | [353] = "ZXC Ltd.", 454 | [354] = "Byte Sphere", 455 | [355] = "Generiton Co. Ltd.", 456 | [356] = "Holter Regelarmaturen GmbH & Co. KG", 457 | [357] = "Bedford Instruments LLC", 458 | [358] = "Standair Inc.", 459 | [359] = "WEG Automation - R&D", 460 | [360] = "Prolon Control Systems ApS", 461 | [361] = "Inneasoft", 462 | [362] = "ConneXSoft GmbH", 463 | [363] = "CEAG Notlichtsysteme GmbH", 464 | [364] = "Distech Controls Inc.", 465 | [365] = "Industrial Technology Research Institute", 466 | [366] = "ICONICS Inc.", 467 | [367] = "IQ Controls s.c.", 468 | [368] = "OJ Electronics A/S", 469 | [369] = "Rolbit Ltd.", 470 | [370] = "Synapsys Solutions Ltd.", 471 | [371] = "ACME Engineering Prod. Ltd.", 472 | [372] = "Zener Electric Pty Ltd.", 473 | [373] = "Selectronix Inc.", 474 | [374] = "Gorbet & Banerjee LLC.", 475 | [375] = "IME", 476 | [376] = "Stephen H. Dawson Computer Service", 477 | [377] = "Accutrol LLC", 478 | [378] = "Schneider Elektronik GmbH", 479 | [379] = "Alpha-Inno Tec GmbH", 480 | [380] = "ADMMicro Inc.", 481 | [381] = "Greystone Energy Systems Inc.", 482 | [382] = "CAP Technologie", 483 | [383] = "KeRo Systems", 484 | [384] = "Domat Control System s.r.o.", 485 | [385] = "Efektronics Pty. Ltd.", 486 | [386] = "Hekatron Vertriebs GmbH", 487 | [387] = "Securiton AG", 488 | [388] = "Carlo Gavazzi Controls SpA", 489 | [389] = "Chipkin Automation Systems", 490 | [390] = "Savant Systems LLC", 491 | [391] = "Simmtronic Lighting Controls", 492 | [392] = "Abelko Innovation AB", 493 | [393] = "Seresco Technologies Inc.", 494 | [394] = "IT Watchdogs", 495 | [395] = "Automation Assist Japan Corp.", 496 | [396] = "Thermokon Sensortechnik GmbH", 497 | [397] = "EGauge Systems LLC", 498 | [398] = "Quantum Automation (ASIA) PTE Ltd.", 499 | [399] = "Toshiba Lighting & Technology Corp.", 500 | [400] = "SPIN Engenharia de Automaç Ltda.", 501 | [401] = "Logistics Systems & Software Services India PVT. Ltd.", 502 | [402] = "Delta Controls Integration Products", 503 | [403] = "Focus Media", 504 | [404] = "LUMEnergi Inc.", 505 | [405] = "Kara Systems", 506 | [406] = "RF Code Inc.", 507 | [407] = "Fatek Automation Corp.", 508 | [408] = "JANDA Software Company LLC", 509 | [409] = "Open System Solutions Limited", 510 | [410] = "Intelec Systems PTY Ltd.", 511 | [411] = "Ecolodgix LLC", 512 | [412] = "Douglas Lighting Controls", 513 | [413] = "iSAtech GmbH", 514 | [414] = "AREAL", 515 | [415] = "Beckhoff Automation GmbH", 516 | [416] = "IPAS GmbH", 517 | [417] = "KE2 Therm Solutions", 518 | [418] = "Base2Products", 519 | [419] = "DTL Controls LLC", 520 | [420] = "INNCOM International Inc.", 521 | [421] = "BTR Netcom GmbH", 522 | [422] = "Greentrol AutomationInc", 523 | [423] = "BELIMO Automation AG", 524 | [424] = "Samsung Heavy Industries CoLtd", 525 | [425] = "Triacta Power Technologies Inc.", 526 | [426] = "Globestar Systems", 527 | [427] = "MLB Advanced MediaLP", 528 | [428] = "SWG Stuckmann Wirtschaftliche Gebäesysteme GmbH", 529 | [429] = "SensorSwitch", 530 | [430] = "Multitek Power Limited", 531 | [431] = "Aquametro AG", 532 | [432] = "LG Electronics Inc.", 533 | [433] = "Electronic Theatre Controls Inc.", 534 | [434] = "Mitsubishi Electric Corporation Nagoya Works", 535 | [435] = "Delta Electronics Inc.", 536 | [436] = "Elma Kurtalj Ltd.", 537 | [437] = "ADT Fire and Security Sp. A.o.o.", 538 | [438] = "Nedap Security Management", 539 | [439] = "ESC Automation Inc.", 540 | [440] = "DSP4YOU Ltd.", 541 | [441] = "GE Sensing and Inspection Technologies", 542 | [442] = "Embedded Systems SIA", 543 | [443] = "BEFEGA GmbH", 544 | [444] = "Baseline Inc.", 545 | [445] = "M2M Systems Integrators", 546 | [446] = "OEMCtrl", 547 | [447] = "Clarkson Controls Limited", 548 | [448] = "Rogerwell Control System Limited", 549 | [449] = "SCL Elements", 550 | [450] = "Hitachi Ltd.", 551 | [451] = "Newron System SA", 552 | [452] = "BEVECO Gebouwautomatisering BV", 553 | [453] = "Streamside Solutions", 554 | [454] = "Yellowstone Soft", 555 | [455] = "Oztech Intelligent Systems Pty Ltd.", 556 | [456] = "Novelan GmbH", 557 | [457] = "Flexim Americas Corporation", 558 | [458] = "ICP DAS Co. Ltd.", 559 | [459] = "CARMA Industries Inc.", 560 | [460] = "Log-One Ltd.", 561 | [461] = "TECO Electric & Machinery Co. Ltd.", 562 | [462] = "ConnectEx Inc.", 563 | [463] = "Turbo DDC Sü", 564 | [464] = "Quatrosense Environmental Ltd.", 565 | [465] = "Fifth Light Technology Ltd.", 566 | [466] = "Scientific Solutions Ltd.", 567 | [467] = "Controller Area Network Solutions (M) Sdn Bhd", 568 | [468] = "RESOL - Elektronische Regelungen GmbH", 569 | [469] = "RPBUS LLC", 570 | [470] = "BRS Sistemas Eletronicos", 571 | [471] = "WindowMaster A/S", 572 | [472] = "Sunlux Technologies Ltd.", 573 | [473] = "Measurlogic", 574 | [474] = "Frimat GmbH", 575 | [475] = "Spirax Sarco", 576 | [476] = "Luxtron", 577 | [477] = "Raypak Inc", 578 | [478] = "Air Monitor Corporation", 579 | [479] = "Regler Och Webbteknik Sverige (ROWS)", 580 | [480] = "Intelligent Lighting Controls Inc.", 581 | [481] = "Sanyo Electric Industry Co.Ltd", 582 | [482] = "E-Mon Energy Monitoring Products", 583 | [483] = "Digital Control Systems", 584 | [484] = "ATI Airtest Technologies Inc.", 585 | [485] = "SCS SA", 586 | [486] = "HMS Industrial Networks AB", 587 | [487] = "Shenzhen Universal Intellisys Co Ltd", 588 | [488] = "EK Intellisys Sdn Bhd", 589 | [489] = "SysCom", 590 | [490] = "Firecom Inc.", 591 | [491] = "ESA Elektroschaltanlagen Grimma GmbH", 592 | [492] = "Kumahira Co Ltd", 593 | [493] = "Hotraco", 594 | [494] = "SABO Elektronik GmbH", 595 | [495] = "Equip'Trans", 596 | [496] = "TCS Basys Controls", 597 | [497] = "FlowCon International A/S", 598 | [498] = "ThyssenKrupp Elevator Americas", 599 | [499] = "Abatement Technologies", 600 | [500] = "Continental Control Systems LLC", 601 | [501] = "WISAG Automatisierungstechnik GmbH & Co KG", 602 | [502] = "EasyIO", 603 | [503] = "EAP-Electric GmbH", 604 | [504] = "Hardmeier", 605 | [505] = "Mircom Group of Companies", 606 | [506] = "Quest Controls", 607 | [507] = "MestekInc", 608 | [508] = "Pulse Energy", 609 | [509] = "Tachikawa Corporation", 610 | [510] = "University of Nebraska-Lincoln", 611 | [511] = "Redwood Systems", 612 | [512] = "PASStec Industrie-Elektronik GmbH", 613 | [513] = "NgEK Inc.", 614 | [514] = "FAW Electronics Ltd", 615 | [515] = "Jireh Energy Tech Co. Ltd.", 616 | [516] = "Enlighted Inc.", 617 | [517] = "El-Piast Sp. Z o.o", 618 | [518] = "NetxAutomation Software GmbH", 619 | [519] = "Invertek Drives", 620 | [520] = "Deutschmann Automation GmbH & Co. KG", 621 | [521] = "EMU Electronic AG", 622 | [522] = "Phaedrus Limited", 623 | [523] = "Sigmatek GmbH & Co KG", 624 | [524] = "Marlin Controls", 625 | [525] = "CircutorSA", 626 | [526] = "UTC Fire & Security", 627 | [527] = "DENT Instruments Inc.", 628 | [528] = "FHP Manufacturing Company - Bosch Group", 629 | [529] = "GE Intelligent Platforms", 630 | [530] = "Inner Range Pty Ltd", 631 | [531] = "GLAS Energy Technology", 632 | [532] = "MSR-Electronic-GmbH", 633 | [533] = "Energy Control Systems Inc.", 634 | [534] = "EMT Controls", 635 | [535] = "Daintree Networks Inc.", 636 | [536] = "EURO ICC d.o.o", 637 | [537] = "TE Connectivity Energy", 638 | [538] = "GEZE GmbH", 639 | [539] = "NEC Corporation", 640 | [540] = "Ho Cheung International Company Limited", 641 | [541] = "Sharp Manufacturing Systems Corporation", 642 | [542] = "DOT CONTROLS a.s.", 643 | [543] = "BeaconMedæ0220", 644 | [544] = "Midea Commercial Aircon", 645 | [545] = "WattMaster Controls", 646 | [546] = "Kamstrup A/S", 647 | [547] = "CA Computer Automation GmbH", 648 | [548] = "Laars Heating Systems Company", 649 | [549] = "Hitachi Systems Ltd.", 650 | [550] = "Fushan AKE Electronic Engineering Co. Ltd.", 651 | [551] = "Toshiba International Corporation", 652 | [552] = "Starman Systems LLC", 653 | [553] = "Samsung Techwin Co. Ltd.", 654 | [554] = "ISAS-Integrated Switchgear and Systems P/L", 655 | [556] = "Obvius", 656 | [557] = "Marek Guzik", 657 | [558] = "Vortek Instruments LLC", 658 | [559] = "Universal Lighting Technologies", 659 | [560] = "Myers Power Products Inc.", 660 | [561] = "Vector Controls GmbH", 661 | [562] = "Crestron Electronics Inc.", 662 | [563] = "A&E Controls Limited", 663 | [564] = "Projektomontaza A.D.", 664 | [565] = "Freeaire Refrigeration", 665 | [566] = "Aqua Cooler Pty Limited", 666 | [567] = "Basic Controls", 667 | [568] = "GE Measurement and Control Solutions Advanced Sensors", 668 | [569] = "EQUAL Networks", 669 | [570] = "Millennial Net", 670 | [571] = "APLI Ltd", 671 | [572] = "Electro Industries/GaugeTech", 672 | [573] = "SangMyung University", 673 | [574] = "Coppertree Analytics Inc.", 674 | [575] = "CoreNetiX GmbH", 675 | [576] = "Acutherm", 676 | [577] = "Dr. Riedel Automatisierungstechnik GmbH", 677 | [578] = "Shina System Co.Ltd", 678 | [579] = "Iqapertus", 679 | [580] = "PSE Technology", 680 | [581] = "BA Systems", 681 | [582] = "BTICINO", 682 | [583] = "Monico Inc.", 683 | [584] = "iCue", 684 | [585] = "tekmar Control Systems Ltd.", 685 | [586] = "Control Technology Corporation", 686 | [587] = "GFAE GmbH", 687 | [588] = "BeKa Software GmbH", 688 | [589] = "Isoil Industria SpA", 689 | [590] = "Home Systems Consulting SpA", 690 | [591] = "Socomec", 691 | [592] = "Everex Communications Inc.", 692 | [593] = "Ceiec Electric Technology", 693 | [594] = "Atrila GmbH", 694 | [595] = "WingTechs", 695 | [596] = "Shenzhen Mek Intellisys Pte Ltd.", 696 | [597] = "Nestfield Co. Ltd.", 697 | [598] = "Swissphone Telecom AG", 698 | [599] = "PNTECH JSC", 699 | [600] = "Horner APG LLC", 700 | [601] = "PVI Industries LLC", 701 | [602] = "Ela-compil", 702 | [603] = "Pegasus Automation International LLC", 703 | [604] = "Wight Electronic Services Ltd.", 704 | [605] = "Marcom", 705 | [606] = "Exhausto A/S", 706 | [607] = "Dwyer Instruments Inc.", 707 | [608] = "Link GmbH", 708 | [609] = "Oppermann Regelgerate GmbH", 709 | [610] = "NuAire Inc.", 710 | [611] = "Nortec Humidity Inc.", 711 | [612] = "Bigwood Systems Inc.", 712 | [613] = "Enbala Power Networks", 713 | [614] = "Inter Energy Co. Ltd.", 714 | [615] = "ETC", 715 | [616] = "COMELEC S.A.R.L", 716 | [617] = "Pythia Technologies", 717 | [618] = "TrendPoint Systems Inc.", 718 | [619] = "AWEX", 719 | [620] = "Eurevia", 720 | [621] = "Kongsberg E-lon AS", 721 | [622] = "FlaktWoods", 722 | [623] = "E + E Elektronik GES M.B.H.", 723 | [624] = "ARC Informatique", 724 | [625] = "SKIDATA AG", 725 | [626] = "WSW Solutions", 726 | [627] = "Trefon Electronic GmbH", 727 | [628] = "Dongseo System", 728 | [629] = "Kanontec Intelligence Technology Co. Ltd.", 729 | [630] = "EVCO S.p.A.", 730 | [631] = "Accuenergy (CANADA) Inc.", 731 | [632] = "SoftDEL", 732 | [633] = "Orion Energy Systems Inc.", 733 | [634] = "Roboticsware", 734 | [635] = "DOMIQ Sp. z o.o.", 735 | [636] = "Solidyne", 736 | [637] = "Elecsys Corporation", 737 | [638] = "Conditionaire International Pty. Limited", 738 | [639] = "Quebec Inc.", 739 | [640] = "Homerun Holdings", 740 | [641] = "RFM Inc.", 741 | [642] = "Comptek", 742 | [643] = "Westco Systems Inc.", 743 | [644] = "Advancis Software & Services GmbH", 744 | [645] = "Intergrid LLC", 745 | [646] = "Markerr Controls Inc.", 746 | [647] = "Toshiba Elevator and Building Systems Corporation", 747 | [648] = "Spectrum Controls Inc.", 748 | [649] = "Mkservice", 749 | [650] = "Fox Thermal Instruments", 750 | [651] = "SyxthSense Ltd", 751 | [652] = "DUHA System S R.O.", 752 | [653] = "NIBE", 753 | [654] = "Melink Corporation", 754 | [655] = "Fritz-Haber-Institut", 755 | [656] = "MTU Onsite Energy GmbHGas Power Systems", 756 | [657] = "Omega Engineering Inc.", 757 | [658] = "Avelon", 758 | [659] = "Ywire Technologies Inc.", 759 | [660] = "M.R. Engineering Co. Ltd.", 760 | [661] = "Lochinvar LLC", 761 | [662] = "Sontay Limited", 762 | [663] = "GRUPA Slawomir Chelminski", 763 | [664] = "Arch Meter Corporation", 764 | [665] = "Senva Inc.", 765 | [667] = "FM-Tec", 766 | [668] = "Systems Specialists Inc.", 767 | [669] = "SenseAir", 768 | [670] = "AB IndustrieTechnik Srl", 769 | [671] = "Cortland Research LLC", 770 | [672] = "MediaView", 771 | [673] = "VDA Elettronica", 772 | [674] = "CSS Inc.", 773 | [675] = "Tek-Air Systems Inc.", 774 | [676] = "ICDT", 775 | [677] = "The Armstrong Monitoring Corporation", 776 | [678] = "DIXELL S.r.l", 777 | [679] = "Lead System Inc.", 778 | [680] = "ISM EuroCenter S.A.", 779 | [681] = "TDIS", 780 | [682] = "Trade FIDES", 781 | [683] = "KnübH (Emerson Network Power)", 782 | [684] = "Resource Data Management", 783 | [685] = "Abies Technology Inc.", 784 | [686] = "Amalva", 785 | [687] = "MIRAE Electrical Mfg. Co. Ltd.", 786 | [688] = "HunterDouglas Architectural Projects Scandinavia ApS", 787 | [689] = "RUNPAQ Group Co.Ltd", 788 | [690] = "Unicard SA", 789 | [691] = "IE Technologies", 790 | [692] = "Ruskin Manufacturing", 791 | [693] = "Calon Associates Limited", 792 | [694] = "Contec Co. Ltd.", 793 | [695] = "iT GmbH", 794 | [696] = "Autani Corporation", 795 | [697] = "Christian Fortin", 796 | [698] = "HDL", 797 | [699] = "IPID Sp. Z.O.O Limited", 798 | [700] = "Fuji Electric Co.Ltd", 799 | [701] = "View Inc.", 800 | [702] = "Samsung S1 Corporation", 801 | [703] = "New Lift", 802 | [704] = "VRT Systems", 803 | [705] = "Motion Control Engineering Inc.", 804 | [706] = "Weiss Klimatechnik GmbH", 805 | [707] = "Elkon", 806 | [708] = "Eliwell Controls S.r.l.", 807 | [709] = "Japan Computer Technos Corp", 808 | [710] = "Rational Network ehf", 809 | [711] = "Magnum Energy Solutions LLC", 810 | [712] = "MelRok", 811 | [713] = "VAE Group", 812 | [714] = "LGCNS", 813 | [715] = "Berghof Automationstechnik GmbH", 814 | [716] = "Quark Communications Inc.", 815 | [717] = "Sontex", 816 | [718] = "mivune AG", 817 | [719] = "Panduit", 818 | [720] = "Smart Controls LLC", 819 | [721] = "Compu-Aire Inc.", 820 | [722] = "Sierra", 821 | [723] = "ProtoSense Technologies", 822 | [724] = "Eltrac Technologies Pvt Ltd", 823 | [725] = "Bektas Invisible Controls GmbH", 824 | [726] = "Entelec", 825 | [727] = "Innexiv", 826 | [728] = "Covenant" 827 | } 828 | --return vendor information 829 | function vendor_lookup(vennum) 830 | local vendorname = vendor_id[vennum] or "Unknown Vendor Number" 831 | return string.format("%s (%d)", vendorname, vennum) 832 | end 833 | 834 | --- 835 | -- Function to lookup the length of the Field to be used for Vendor ID, Firmware 836 | -- Object Name, Software Version, and Location. It will then return the Value 837 | -- that is stored inside the packet for this information as a String Value. 838 | -- The field is located in the 18th byte of the data field of a valid packet. 839 | -- Depending on this field the information will be stored in field 20 + length 840 | -- or in field 22 + length. 841 | -- 842 | -- @param packet The packet that was received and is ready to be parsed 843 | function field_size(packet) 844 | local info 845 | 846 | -- read the Length field from the packet data byte 18 847 | local offset 848 | -- Verify the field from byte 18 to determine if the vendor number is one byte or two bytes? 849 | local value = string.byte(packet, 18) 850 | if ( value % 0x10 < 5 ) then 851 | value = value % 0x10 - 1 852 | offset = 19 853 | else 854 | value = string.byte(packet, 19) - 1 855 | offset = 20 856 | end 857 | -- unpack a string of length 858 | offset, charset, info = bin.unpack("CA" .. tostring(value), packet, offset) 859 | -- return information that was found in the packet 860 | if charset == 0 then -- UTF-8 861 | return info 862 | elseif charset == 4 then -- UCS-2 big-endian 863 | return unicode.transcode(info, unicode.utf16_dec, unicode.utf8_enc, true, nil) 864 | else -- TODO: other encodings not supported by unicode.lua 865 | return info 866 | end 867 | end 868 | --- 869 | -- Function to set the nmap output for the host, if a valid BACNet packet 870 | -- is received then the output will show that the port is open instead of 871 | -- open|filtered 872 | -- 873 | -- @param host Host that was passed in via nmap 874 | -- @param port port that BACNet is running on (Default UDP/47808) 875 | function set_nmap(host, port) 876 | 877 | --set port Open 878 | port.state = "open" 879 | -- set version name to BACNet 880 | port.version.name = "BACNet -- Building Automation and Control Networks" 881 | nmap.set_port_version(host, port) 882 | nmap.set_port_state(host, port, "open") 883 | 884 | end 885 | 886 | --- 887 | -- Function to send a query to the discovered BACNet devices. This will pull extra 888 | -- information to help identify the device. Information such as firmware, application software 889 | -- object name, description, and location parameters configured inside of the device. 890 | -- 891 | -- @param socket The socket that was created in the action function 892 | -- @param type Type is the type of packet to send, this can be firmware, application, object, description, or location 893 | function standard_query(socket, type) 894 | 895 | 896 | -- set the query for vendor name 897 | local vendor_query = bin.pack("H","810a001101040005010c0c023FFFFF1979") 898 | -- set the firmware version query data for sending 899 | local firmware_query = bin.pack("H","810a001101040005010c0c023FFFFF192c") 900 | -- set the application version query data for sending 901 | local appsoft_query = bin.pack("H","810a001101040005010c0c023FFFFF190c") 902 | -- set the object name query data for sending 903 | local object_query = bin.pack("H","810a001101040005010c0c023FFFFF194d") 904 | -- set the model name query data for sending 905 | local model_query = bin.pack("H","810a001101040005010c0c023FFFFF1946") 906 | -- set the desc name query data for sending 907 | local desc_query = bin.pack("H","810a001101040005010c0c023FFFFF191c") 908 | -- set the location name query data for sending 909 | local location_query = bin.pack("H","810a001101040005010c0c023FFFFF193A") 910 | local query 911 | 912 | -- 913 | -- determine what type of packet to send 914 | if (type == "firmware") then 915 | query = firmware_query 916 | elseif (type == "application") then 917 | query = appsoft_query 918 | elseif (type == "model") then 919 | query = model_query 920 | elseif (type == "object") then 921 | query = object_query 922 | elseif (type == "description") then 923 | query = desc_query 924 | elseif (type == "location") then 925 | query = location_query 926 | elseif (type == "vendor") then 927 | query = vendor_query 928 | end 929 | 930 | --try to pull the information 931 | local status, result = socket:send(query) 932 | if(status == false) then 933 | stdnse.debug1("Socket error sending query: %s", result) 934 | return nil 935 | end 936 | -- receive packet from response 937 | local rcvstatus, response = socket:receive() 938 | if(rcvstatus == false) then 939 | stdnse.debug1("Socket error receiving: %s", response) 940 | return nil 941 | end 942 | -- validate valid BACNet Packet 943 | if( string.starts(response, "\x81")) then 944 | -- Lookup byte 7 (pakcet type) 945 | local pos, value = bin.unpack("C", response, 7) 946 | -- verify that the response packet was not an error packet 947 | if( value ~= 0x50) then 948 | --collect information by looping thru the packet 949 | return field_size(response) 950 | -- if it was an error packet, set the string to error for later purposes 951 | else 952 | stdnse.debug1("Error receiving: BACNet Error") 953 | return nil 954 | end 955 | -- else ERROR 956 | else 957 | stdnse.debug1("Error receiving Vendor ID: Invalid BACNet packet") 958 | return nil 959 | end 960 | 961 | end 962 | --- 963 | -- Function to send a query to the discovered BACNet devices. This function queries extra 964 | -- information to help identify the device. Vendor ID query is sent with this 965 | -- function and the Vendor ID number is parsed out of the packet. 966 | -- 967 | -- @param socket The socket that was created in the action function 968 | function vendornum_query(socket) 969 | 970 | -- set the vendor query data for sending 971 | local vendor_query = bin.pack("H","810a001101040005010c0c023FFFFF1978") 972 | 973 | 974 | --send the vendor information 975 | local status, result = socket:send(vendor_query) 976 | if(status == false) then 977 | stdnse.debug1("Socket error sending vendor query: %s", result) 978 | return nil 979 | end 980 | -- receive vendor information packet 981 | local rcvstatus, response = socket:receive() 982 | if(rcvstatus == false) then 983 | stdnse.debug1("Socket error receiving vendor query: %s", response) 984 | return nil 985 | end 986 | -- validate valid BACNet Packet 987 | if( string.starts(response, "\x81")) then 988 | local pos, value = bin.unpack("C", response, 7) 989 | --if the vendor query resulted in an error 990 | if( value ~= 0x50) then 991 | -- read values for byte 18 in the packet data 992 | -- this value determines if vendor number is 1 or 2 bytes 993 | pos, value = bin.unpack("C", response, 18) 994 | else 995 | stdnse.debug1("Error receiving Vendor ID: BACNet Error") 996 | return nil 997 | end 998 | -- if value is 21 (byte 18) 999 | if( value == 0x21 ) then 1000 | -- convert hex to decimal 1001 | local vendornum = string.byte(response, 19) 1002 | -- look up vendor name from table 1003 | return vendor_lookup(vendornum) 1004 | -- if value is 22 (byte 18) 1005 | elseif( value == 0x22 ) then 1006 | -- convert hex to decimal 1007 | local vendornum 1008 | pos, vendornum = bin.unpack(">S", response, 19) 1009 | -- look up vendor name from table 1010 | return vendor_lookup(vendornum) 1011 | else 1012 | -- set return value to an Error if byte 18 was not 21/22 1013 | stdnse.debug1("Error receiving Vendor ID: Invalid BACNet packet") 1014 | return nil 1015 | end 1016 | end 1017 | 1018 | end 1019 | 1020 | --- 1021 | -- Function to send a request for BVLC info to the discovered BACNet devices. 1022 | -- This includes the BBMD and the FDT queries. These are read only and do not 1023 | -- attempt to join the router as a Foreign Device. 1024 | -- 1025 | -- @param socket The socket that was created in the action function 1026 | -- @param type Type is the type of packet to send, this can be bbmd or fdt 1027 | function bvlc_query(socket, type) 1028 | 1029 | -- set the BVLC query data for sending 1030 | -- BBMD = 0x02 1031 | local bbmd_query = bin.pack("H","81020004") 1032 | -- FDT = 0x06 1033 | local fdt_query = bin.pack("H","81060004") 1034 | -- initialize query var 1035 | local query 1036 | 1037 | -- Based on type parameter passed in from Action 1038 | if (type == "bbmd") then 1039 | query = bbmd_query 1040 | elseif (type == "fdt") then 1041 | query = fdt_query 1042 | end 1043 | 1044 | -- Send the query that was set by the type 1045 | local status, result = socket:send(query) 1046 | if(status == false) then 1047 | stdnse.debug1("BVLC-" .. type .. ": Socket error sending query: %s", result) 1048 | return nil 1049 | end 1050 | -- Recive response from the query 1051 | local rcvstatus, response = socket:receive() 1052 | if(rcvstatus == false) then 1053 | stdnse.debug1("BVLC-" .. type .. ": Socket error receiving: %s", response) 1054 | return nil 1055 | end 1056 | 1057 | -- Validate that packet is BACNet, if it is then we will start parsing more response 1058 | if( string.starts(response, "\x81")) then 1059 | 1060 | -- init up vars 1061 | local info = "" 1062 | local ips = {} 1063 | local length 1064 | local mask 1065 | local resptype 1066 | 1067 | -- unpack response type, this will be used to determine BBMD vs FDT 1068 | local pos, resptype = bin.unpack("C", response, 2) 1069 | 1070 | -- unpack length, this will be the length of the information to be parsed 1071 | pos, length = bin.unpack(">S", response, 3) 1072 | -- add one to length since Lua starts at 1 not 0 1073 | length = length + 1 1074 | stdnse.debug1("BVLC-" .. type .. ": starting on bacnet bytes: " .. length) 1075 | -- if length is 7(packet size 6), then we will test to see if it was NAK response 1076 | if length == 7 then 1077 | -- response type will be BVLC-Result 1078 | if resptype == 0 then 1079 | -- unpack two bytes of interest 1080 | pos, byte1 = bin.unpack("C", response, 4) 1081 | pos, byte2 = bin.unpack("C", response, 6) 1082 | if byte1 == 0x06 and byte2 == 0x40 then 1083 | return "Non-Acknowledgement (NAK)" 1084 | elseif byte1 == 0x06 and byte2 == 0x20 then 1085 | return "Non-Acknowledgement (NAK)" 1086 | end 1087 | end 1088 | -- if the packet length is 5(packet size 4) then check to see if a Empty response 1089 | elseif length == 5 then 1090 | -- validate the response is for the FDT query 1091 | if resptype == 7 then 1092 | return "Empty Table" 1093 | end 1094 | -- if packet is not long enough then we will exit 1095 | elseif length < 15 then 1096 | stdnse.debug1( 1097 | "BVLC-" .. type .. ": stopping, this response had not enough bytes: " .. length .. " < 15") 1098 | return nil 1099 | end 1100 | -- While loop for the length of the packet as determined from above. 1101 | while pos < length do 1102 | local ipaddr = "" 1103 | --Unpack and the IP Address from the response 1104 | pos, info = bin.unpack("S", response, pos) 1110 | -- Make string to be stored in output table to be returned to Nmap 1111 | ipaddr = ipaddr .. ":" .. info 1112 | -- shift by 4 bytes 1113 | pos = pos + 4 1114 | 1115 | -- else if the type is FDT 1116 | elseif resptype == 7 then 1117 | --Unpack port number 1118 | pos, info = bin.unpack(">S", response, pos) 1119 | ipaddr = ipaddr .. ":" .. info 1120 | --Unpack TTL field 1121 | pos, info = bin.unpack(">S", response, pos) 1122 | ipaddr = ipaddr .. ":ttl=" .. info 1123 | --Unpack the timeout field 1124 | pos, info = bin.unpack(">S", response, pos) 1125 | ipaddr = ipaddr .. ":timeout=" .. info 1126 | stdnse.debug1("BVLC-" .. type .. ": found this: " .. ipaddr) 1127 | -- else the type was not something we were asking for 1128 | --we don't know what response type this is! 1129 | else 1130 | stdnse.debug1("BVLC-" .. type .. ": unknown response type encountered!") 1131 | return nil 1132 | end 1133 | -- insert to the ips table for output to Nmap 1134 | table.insert(ips, ipaddr) 1135 | 1136 | -- consider if its time to quit based on the last pos from the last 1137 | -- unpack was the end of the packet 1138 | if pos == length then 1139 | stdnse.debug1("BVLC-" .. type .. ": bailing because we are at the end: " .. pos) 1140 | return ips 1141 | end 1142 | stdnse.debug1("BVLC-" .. type .. ": done with loop") 1143 | end 1144 | -- else ERROR 1145 | else 1146 | stdnse.debug1("Invalid BACNet packet in response to: " .. type) 1147 | return nil 1148 | end 1149 | 1150 | end 1151 | 1152 | --- 1153 | -- Action Function that is used to run the NSE. This function will send the initial query to the 1154 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 1155 | -- is a BACNet device. If it is then more actions are taken to gather extra information. 1156 | -- 1157 | -- @param host Host that was scanned via nmap 1158 | -- @param port port that was scanned via nmap 1159 | action = function(host, port) 1160 | --set the first query data for sending 1161 | local orig_query = bin.pack("H","810a001101040005010c0c023FFFFF194b" ) 1162 | 1163 | local to_return = nil 1164 | -- create new socket 1165 | local sock = nmap.new_socket() 1166 | -- Bind to port for niceness with BACNet this may need to be commented out if 1167 | -- scanning more than one host at a time, may fix some issues seen on Windows 1168 | -- 1169 | local status, err = sock:bind(nil, 47808) 1170 | if(status == false) then 1171 | stdnse.debug1( 1172 | "Couldn't bind to 47808/udp. Continuing anyway, results may vary") 1173 | end 1174 | -- connect to the remote host 1175 | local constatus, conerr = sock:connect(host, port) 1176 | if not constatus then 1177 | stdnse.debug1( 1178 | 'Error establishing a UDP connection for %s - %s', host, conerr 1179 | ) 1180 | return nil 1181 | end 1182 | -- send the original query to see if it is a valid BACNet Device 1183 | local sendstatus, senderr = sock:send(orig_query) 1184 | if not sendstatus then 1185 | stdnse.debug1( 1186 | 'Error sending BACNet request to %s:%d - %s', 1187 | host.ip, port.number, senderr 1188 | ) 1189 | return nil 1190 | end 1191 | 1192 | -- receive response 1193 | local rcvstatus, response = sock:receive() 1194 | if(rcvstatus == false) then 1195 | stdnse.debug1("Receive error: %s", response) 1196 | return nil 1197 | end 1198 | 1199 | -- if the response starts with 0x81 then its BACNet 1200 | if( string.starts(response, "\x81")) then 1201 | local pos, value = bin.unpack("C", response, 7) 1202 | --if the first query resulted in an error 1203 | -- 1204 | if( value == 0x50) then 1205 | -- set the nmap output for the port and version 1206 | set_nmap(host, port) 1207 | -- return that BACNet Error was received 1208 | to_return = "\nBACNet ADPU Type: Error (5) \n\t" .. stdnse.tohex(response) 1209 | --else pull the InstanceNumber and move onto the pulling more information 1210 | -- 1211 | else 1212 | to_return = stdnse.output_table() 1213 | -- set the nmap output for the port and version 1214 | set_nmap(host, port) 1215 | 1216 | -- Vendor Number to Name lookup 1217 | to_return["Vendor ID"] = vendornum_query(sock) 1218 | 1219 | -- vendor name 1220 | to_return["Vendor Name"] = standard_query(sock, "vendor") 1221 | 1222 | -- Instance Number (object number) 1223 | local instance_upper, instance 1224 | pos, instance_upper, instance = bin.unpack("C>S", response, 20) 1225 | to_return["Object-identifier"] = instance_upper * 0x10000 + instance 1226 | 1227 | --Firmware Verson 1228 | to_return["Firmware"] = standard_query(sock, "firmware") 1229 | 1230 | -- Application Software Version 1231 | to_return["Application Software"] = standard_query(sock, "application") 1232 | 1233 | -- Object Name 1234 | to_return["Object Name"] = standard_query(sock, "object") 1235 | 1236 | -- Model Name 1237 | to_return["Model Name"] = standard_query(sock, "model") 1238 | 1239 | -- Description 1240 | to_return["Description"] = standard_query(sock, "description") 1241 | 1242 | -- Location 1243 | to_return["Location"] = standard_query(sock, "location") 1244 | 1245 | -- for each element in the table, if it is nil, then remove the information from the table 1246 | for key,value in pairs(to_return) do 1247 | if(string.len(to_return[key]) == 0) then 1248 | to_return[key] = nil 1249 | end 1250 | end 1251 | -- check for script-args, if its set to yes, then run this additional queries 1252 | local arguments = stdnse.get_script_args('full') 1253 | if ( arguments == "yes" ) then 1254 | -- BACnet Broadcast Management Device Query/Response 1255 | to_return["Broadcast Distribution Table (BDT)"] = bvlc_query(sock, "bbmd") 1256 | 1257 | -- Foreign Device Table Query/Response 1258 | to_return["Foreign Device Table (FDT)"] = bvlc_query(sock, "fdt") 1259 | end 1260 | end 1261 | else 1262 | -- return nothing, no BACNet was detected 1263 | -- close socket 1264 | sock:close() 1265 | return nil 1266 | end 1267 | -- close socket 1268 | sock:close() 1269 | -- return all information that was found 1270 | return to_return 1271 | 1272 | end 1273 | -------------------------------------------------------------------------------- /enip-enumerate.nse: -------------------------------------------------------------------------------- 1 | local bin = require "bin" 2 | local ipOps = require "ipOps" 3 | local nmap = require "nmap" 4 | local shortport = require "shortport" 5 | local stdnse = require "stdnse" 6 | local string = require "string" 7 | local table = require "table" 8 | 9 | description = [[ 10 | This NSE script is used to send a EtherNet/IP packet to a remote device that 11 | has TCP 44818 open. The script will send a Request Identity Packet and once a 12 | response is received, it validates that it was a proper response to the command 13 | that was sent, and then will parse out the data. Information that is parsed 14 | includes Vendor ID, Device Type, Product name, Serial Number, Product code, 15 | Revision Number, as well as the Device IP. 16 | 17 | This script was written based of information collected by using the the 18 | Wireshark dissector for CIP, and EtherNet/IP, The original information was 19 | collected by running a modified version of the ethernetip.py script ( 20 | https://github.com/paperwork/pyenip ) 21 | 22 | http://digitalbond.com 23 | 24 | ]] 25 | --- 26 | -- @usage 27 | -- nmap --script enip-enumerate -sU -p 44818 28 | -- 29 | -- 30 | -- @output 31 | --44818/tcp open EtherNet/IP 32 | --| enip-enumerate: 33 | --| Vendor: Rockwell Automation/Allen-Bradley (1) 34 | --| Product Name: 1769-L32E Ethernet Port 35 | --| Serial Number: 0x000000 36 | --| Device Type: Communications Adapter (12) 37 | --| Product Code: 158 38 | --| Revision: 3.7 39 | --|_ Device IP: 192.168.1.1 40 | -- @xmloutput 41 | --Rockwell Automation/Allen-Bradley (1) 42 | --1769-L32E Ethernet Port 43 | --0x000000 44 | --Communications Adapter (12) 45 | --158 46 | --3,7 47 | --192.168.1.1 48 | 49 | 50 | author = "Stephen Hilt (Digital Bond)" 51 | license = "Same as Nmap--See http://nmap.org/book/man-legal.html" 52 | categories = {"discovery", "intrusive","digitalbond"} 53 | 54 | -- 55 | -- Function to define the portrule as per nmap standards 56 | -- 57 | -- 58 | -- 59 | portrule = shortport.portnumber(44818, "tcp") 60 | 61 | --- 62 | -- Table to look up the Vendor Name based on Vendor ID 63 | -- Returns "Unknown Vendor Number" if Vendor ID not recognized 64 | -- Table data from Wireshark dissector ( link to unofficial mirror ) 65 | -- https://github.com/avsej/wireshark/blob/master/epan/dissectors/packet-enip.c 66 | -- Fetched on 4/19/2014 67 | -- 68 | -- @key vennum Vendor number parsed out of the EtherNet/IP packet 69 | local vendor_id = { 70 | [0] = "Reserved", 71 | [1] = "Rockwell Automation/Allen-Bradley", 72 | [2] = "Namco Controls Corp.", 73 | [3] = "Honeywell Inc.", 74 | [4] = "Parker Hannifin Corp. (Veriflo Division)", 75 | [5] = "Rockwell Automation/Reliance Elec.", 76 | [6] = "Reserved", 77 | [7] = "SMC Corporation", 78 | [8] = "Molex Incorporated", 79 | [9] = "Western Reserve Controls Corp.", 80 | [10] = "Advanced Micro Controls Inc. (AMCI)", 81 | [11] = "ASCO Pneumatic Controls", 82 | [12] = "Banner Engineering Corp.", 83 | [13] = "Belden Wire & Cable Company", 84 | [14] = "Cooper Interconnect", 85 | [15] = "Reserved", 86 | [16] = "Daniel Woodhead Co. (Woodhead Connectivity)", 87 | [17] = "Dearborn Group Inc.", 88 | [18] = "Reserved", 89 | [19] = "Helm Instrument Company", 90 | [20] = "Huron Net Works", 91 | [21] = "Lumberg Inc.", 92 | [22] = "Online Development Inc.(Automation Value)", 93 | [23] = "Vorne Industries Inc.", 94 | [24] = "ODVA Special Reserve", 95 | [25] = "Reserved", 96 | [26] = "Festo Corporation", 97 | [27] = "Reserved", 98 | [28] = "Reserved", 99 | [29] = "Reserved", 100 | [30] = "Unico Inc.", 101 | [31] = "Ross Controls", 102 | [32] = "Reserved", 103 | [33] = "Reserved", 104 | [34] = "Hohner Corp.", 105 | [35] = "Micro Mo Electronics Inc.", 106 | [36] = "MKS Instruments Inc.", 107 | [37] = "Yaskawa Electric America formerly Magnetek Drives", 108 | [38] = "Reserved", 109 | [39] = "AVG Automation (Uticor)", 110 | [40] = "Wago Corporation", 111 | [41] = "Kinetics (Unit Instruments)", 112 | [42] = "IMI Norgren Limited", 113 | [43] = "BALLUFF Inc.", 114 | [44] = "Yaskawa Electric America Inc.", 115 | [45] = "Eurotherm Controls Inc", 116 | [46] = "ABB Industrial Systems", 117 | [47] = "Omron Corporation", 118 | [48] = "TURCk Inc.", 119 | [49] = "Grayhill Inc.", 120 | [50] = "Real Time Automation (C&ID)", 121 | [51] = "Reserved", 122 | [52] = "Numatics Inc.", 123 | [53] = "Lutze Inc.", 124 | [54] = "Reserved", 125 | [55] = "Reserved", 126 | [56] = "Softing GmbH", 127 | [57] = "Pepperl + Fuchs", 128 | [58] = "Spectrum Controls Inc.", 129 | [59] = "D.I.P. Inc. MKS Inst.", 130 | [60] = "Applied Motion Products Inc.", 131 | [61] = "Sencon Inc.", 132 | [62] = "High Country Tek", 133 | [63] = "SWAC Automation Consult GmbH", 134 | [64] = "Clippard Instrument Laboratory", 135 | [65] = "Reserved", 136 | [66] = "Reserved", 137 | [67] = "Reserved", 138 | [68] = "Eaton Electrical", 139 | [69] = "Reserved", 140 | [70] = "Reserved", 141 | [71] = "Toshiba International Corp.", 142 | [72] = "Control Technology Incorporated", 143 | [73] = "TCS (NZ) Ltd.", 144 | [74] = "HitachiLtd.", 145 | [75] = "ABB Robotics Products AB", 146 | [76] = "NKE Corporation", 147 | [77] = "Rockwell Software Inc.", 148 | [78] = "Escort Memory Systems (A Datalogic Group Co.)", 149 | [79] = "Reserved", 150 | [80] = "Industrial Devices Corporation", 151 | [81] = "IXXAT Automation GmbH", 152 | [82] = "Mitsubishi Electric Automation Inc.", 153 | [83] = "OPTO-22", 154 | [84] = "Reserved", 155 | [85] = "Reserved", 156 | [86] = "Horner Electric", 157 | [87] = "Burkert Werke GmbH & Co. KG", 158 | [88] = "Reserved", 159 | [89] = "Industrial Indexing Systems Inc.", 160 | [90] = "HMS Industrial Networks AB", 161 | [91] = "Robicon", 162 | [92] = "Helix Technology (Granville-Phillips)", 163 | [93] = "Arlington Laboratory", 164 | [94] = "Advantech Co. Ltd.", 165 | [95] = "Square D Company", 166 | [96] = "Digital Electronics Corp.", 167 | [97] = "Danfoss", 168 | [98] = "Reserved", 169 | [99] = "Reserved", 170 | [100] = "Bosch Rexroth Corporation] = Pneumatics", 171 | [101] = "Applied Materials Inc.", 172 | [102] = "Showa Electric Wire & Cable Co.", 173 | [103] = "Pacific Scientific (API Controls Inc.)", 174 | [104] = "Sharp Manufacturing Systems Corp.", 175 | [105] = "Olflex Wire & Cable Inc.", 176 | [106] = "Reserved", 177 | [107] = "Unitrode", 178 | [108] = "Beckhoff Automation GmbH", 179 | [109] = "National Instruments", 180 | [110] = "Mykrolis Corporations (Millipore)", 181 | [111] = "International Motion Controls Corp.", 182 | [112] = "Reserved", 183 | [113] = "SEG Kempen GmbH", 184 | [114] = "Reserved", 185 | [115] = "Reserved", 186 | [116] = "MTS Systems Corp.", 187 | [117] = "Krones Inc", 188 | [118] = "Reserved", 189 | [119] = "EXOR Electronic R & D", 190 | [120] = "SIEI S.p.A.", 191 | [121] = "KUKA Roboter GmbH", 192 | [122] = "Reserved", 193 | [123] = "SEC (Samsung Electronics Co.Ltd)", 194 | [124] = "Binary Electronics Ltd", 195 | [125] = "Flexible Machine Controls", 196 | [126] = "Reserved", 197 | [127] = "ABB Inc. (Entrelec)", 198 | [128] = "MAC Valves Inc.", 199 | [129] = "Auma Actuators Inc", 200 | [130] = "Toyoda Machine WorksLtd", 201 | [131] = "Reserved", 202 | [132] = "Reserved", 203 | [133] = "Balogh T.A.G.] = Corporation", 204 | [134] = "TR Systemtechnik GmbH", 205 | [135] = "UNIPULSE Corporation", 206 | [136] = "Reserved", 207 | [137] = "Reserved", 208 | [138] = "Conxall Corporation Inc.", 209 | [139] = "Reserved", 210 | [140] = "Reserved", 211 | [141] = "Kuramo Electric Co.Ltd.", 212 | [142] = "Creative Micro Designs", 213 | [143] = "GE Industrial Systems", 214 | [144] = "Leybold Vacuum GmbH", 215 | [145] = "Siemens Energy & Automation/Drives", 216 | [146] = "Kodensha Ltd", 217 | [147] = "Motion Engineering Inc.", 218 | [148] = "Honda Engineering Co.Ltd", 219 | [149] = "EIM Valve Controls", 220 | [150] = "Melec Inc.", 221 | [151] = "Sony Manufacturing Systems Corporation", 222 | [152] = "North American Mfg.", 223 | [153] = "WATLOW", 224 | [154] = "Japan Radio Co.Ltd", 225 | [155] = "NADEX Co.Ltd", 226 | [156] = "Ametek Automation & Process Technologies", 227 | [157] = "Reserved", 228 | [158] = "KVASER AB", 229 | [159] = "IDEC IZUMI Corporation", 230 | [160] = "Mitsubishi Heavy Industries Ltd", 231 | [161] = "Mitsubishi Electric Corporation", 232 | [162] = "Horiba-STEC Inc.", 233 | [163] = "esd electronic system design gmbh", 234 | [164] = "DAIHEN Corporation", 235 | [165] = "Tyco Valves & Controls/Keystone", 236 | [166] = "EBARA Corporation", 237 | [167] = "Reserved", 238 | [168] = "Reserved", 239 | [169] = "Hokuyo Electric Co. Ltd", 240 | [170] = "Pyramid Solutions Inc.", 241 | [171] = "Denso Wave Incorporated", 242 | [172] = "HLS Hard-Line Solutions Inc", 243 | [173] = "Caterpillar Inc.", 244 | [174] = "PDL Electronics Ltd.", 245 | [175] = "Reserved", 246 | [176] = "Red Lion Controls", 247 | [177] = "ANELVA Corporation", 248 | [178] = "Toyo Denki Seizo KK", 249 | [179] = "Sanyo Denki Co.Ltd", 250 | [180] = "Advanced Energy Japan K.K. (Aera Japan)", 251 | [181] = "Pilz GmbH & Co", 252 | [182] = "Marsh Bellofram-Bellofram PCD Division", 253 | [183] = "Reserved", 254 | [184] = "M-SYSTEM Co. Ltd", 255 | [185] = "Nissin Electric Co.Ltd", 256 | [186] = "Hitachi Metals Ltd.", 257 | [187] = "Oriental Motor Company", 258 | [188] = "A&D Co.Ltd", 259 | [189] = "Phasetronics Inc.", 260 | [190] = "Cummins Engine Company", 261 | [191] = "Deltron Inc.", 262 | [192] = "Geneer Corporation", 263 | [193] = "Anatol Automation Inc.", 264 | [194] = "Reserved", 265 | [195] = "Reserved", 266 | [196] = "Medar Inc.", 267 | [197] = "Comdel Inc.", 268 | [198] = "Advanced Energy Industries Inc", 269 | [199] = "Reserved", 270 | [200] = "DAIDEN Co.Ltd", 271 | [201] = "CKD Corporation", 272 | [202] = "Toyo Electric Corporation", 273 | [203] = "Reserved", 274 | [204] = "AuCom Electronics Ltd", 275 | [205] = "Shinko Electric Co.Ltd", 276 | [206] = "Vector Informatik GmbH", 277 | [207] = "Reserved", 278 | [208] = "Moog Inc.", 279 | [209] = "Contemporary Controls", 280 | [210] = "Tokyo Sokki Kenkyujo Co.Ltd", 281 | [211] = "Schenck-AccuRate Inc.", 282 | [212] = "The Oilgear Company", 283 | [213] = "Reserved", 284 | [214] = "ASM Japan K.K.", 285 | [215] = "HIRATA Corp.", 286 | [216] = "SUNX Limited", 287 | [217] = "Meidensha Corp.", 288 | [218] = "NIDEC SANKYO CORPORATION (Sankyo Seiki Mfg. Co.Ltd)", 289 | [219] = "KAMRO Corp.", 290 | [220] = "Nippon System Development Co.Ltd", 291 | [221] = "EBARA Technologies Inc.", 292 | [222] = "Reserved", 293 | [223] = "Reserved", 294 | [224] = "SG Co.Ltd", 295 | [225] = "Vaasa Institute of Technology", 296 | [226] = "MKS Instruments (ENI Technology)", 297 | [227] = "Tateyama System Laboratory Co.Ltd.", 298 | [228] = "QLOG Corporation", 299 | [229] = "Matric Limited Inc.", 300 | [230] = "NSD Corporation", 301 | [231] = "Reserved", 302 | [232] = "Sumitomo Wiring SystemsLtd", 303 | [233] = "Group 3 Technology Ltd", 304 | [234] = "CTI Cryogenics", 305 | [235] = "POLSYS CORP", 306 | [236] = "Ampere Inc.", 307 | [237] = "Reserved", 308 | [238] = "Simplatroll Ltd", 309 | [239] = "Reserved", 310 | [240] = "Reserved", 311 | [241] = "Leading Edge Design", 312 | [242] = "Humphrey Products", 313 | [243] = "Schneider Automation Inc.", 314 | [244] = "Westlock Controls Corp.", 315 | [245] = "Nihon Weidmuller Co.Ltd", 316 | [246] = "Brooks Instrument (Div. of Emerson)", 317 | [247] = "Reserved", 318 | [248] = " Moeller GmbH", 319 | [249] = "Varian Vacuum Products", 320 | [250] = "Yokogawa Electric Corporation", 321 | [251] = "Electrical Design Daiyu Co.Ltd", 322 | [252] = "Omron Software Co.Ltd", 323 | [253] = "BOC Edwards", 324 | [254] = "Control Technology Corporation", 325 | [255] = "Bosch Rexroth", 326 | [256] = "Turck", 327 | [257] = "Control Techniques PLC", 328 | [258] = "Hardy Instruments Inc.", 329 | [259] = "LS Industrial Systems", 330 | [260] = "E.O.A. Systems Inc.", 331 | [261] = "Reserved", 332 | [262] = "New Cosmos Electric Co.Ltd.", 333 | [263] = "Sense Eletronica LTDA", 334 | [264] = "Xycom Inc.", 335 | [265] = "Baldor Electric", 336 | [266] = "Reserved", 337 | [267] = "Patlite Corporation", 338 | [268] = "Reserved", 339 | [269] = "Mogami Wire & Cable Corporation", 340 | [270] = "Welding Technology Corporation (WTC)", 341 | [271] = "Reserved", 342 | [272] = "Deutschmann Automation GmbH", 343 | [273] = "ICP Panel-Tec Inc.", 344 | [274] = "Bray Controls USA", 345 | [275] = "Reserved", 346 | [276] = "Status Technologies", 347 | [277] = "Trio Motion Technology Ltd", 348 | [278] = "Sherrex Systems Ltd", 349 | [279] = "Adept Technology Inc.", 350 | [280] = "Spang Power Electronics", 351 | [281] = "Reserved", 352 | [282] = "Acrosser Technology Co.Ltd", 353 | [283] = "Hilscher GmbH", 354 | [284] = "IMAX Corporation", 355 | [285] = "Electronic Innovation Inc. (Falter Engineering)", 356 | [286] = "Netlogic Inc.", 357 | [287] = "Bosch Rexroth Corporation] = Indramat", 358 | [288] = "Reserved", 359 | [289] = "Reserved", 360 | [290] = "Murata Machinery Ltd.", 361 | [291] = "MTT Company Ltd.", 362 | [292] = "Kanematsu Semiconductor Corp.", 363 | [293] = "Takebishi Electric Sales Co.", 364 | [294] = "Tokyo Electron Device Ltd", 365 | [295] = "PFU Limited", 366 | [296] = "Hakko Automation Co.Ltd.", 367 | [297] = "Advanet Inc.", 368 | [298] = "Tokyo Electron Software Technologies Ltd.", 369 | [299] = "Reserved", 370 | [300] = "Shinagawa Electric Wire Co.Ltd.", 371 | [301] = "Yokogawa M&C Corporation", 372 | [302] = "KONAN Electric Co.Ltd.", 373 | [303] = "Binar Elektronik AB", 374 | [304] = "Furukawa Electric Co.", 375 | [305] = "Cooper Energy Services", 376 | [306] = "Schleicher GmbH & Co.", 377 | [307] = "Hirose Electric Co.Ltd", 378 | [308] = "Western Servo Design Inc.", 379 | [309] = "Prosoft Technology", 380 | [310] = "Reserved", 381 | [311] = "Towa Shoko Co.Ltd", 382 | [312] = "Kyopal Co.Ltd", 383 | [313] = "Extron Co.", 384 | [314] = "Wieland Electric GmbH", 385 | [315] = "SEW Eurodrive GmbH", 386 | [316] = "Aera Corporation", 387 | [317] = "STA Reutlingen", 388 | [318] = "Reserved", 389 | [319] = "Fuji Electric Co.Ltd.", 390 | [320] = "Reserved", 391 | [321] = "Reserved", 392 | [322] = "ifm efector] = inc.", 393 | [323] = "Reserved", 394 | [324] = "IDEACOD-Hohner Automation S.A.", 395 | [325] = "CommScope Inc.", 396 | [326] = "GE Fanuc Automation North America Inc.", 397 | [327] = "Matsushita Electric Industrial Co.Ltd", 398 | [328] = "Okaya Electronics Corporation", 399 | [329] = "KASHIYAMA IndustriesLtd", 400 | [330] = "JVC", 401 | [331] = "Interface Corporation", 402 | [332] = "Grape Systems Inc.", 403 | [333] = "Reserved", 404 | [334] = "Reserved", 405 | [335] = "Toshiba IT & Control Systems Corporation", 406 | [336] = "Sanyo Machine WorksLtd.", 407 | [337] = "Vansco Electronics Ltd.", 408 | [338] = "Dart Container Corp.", 409 | [339] = "Livingston & Co. Inc.", 410 | [340] = "Alfa Laval LKM as", 411 | [341] = "BF ENTRON Ltd. (British Federal)", 412 | [342] = "Bekaert Engineering NV", 413 | [343] = "Ferran Scientific Inc.", 414 | [344] = "KEBA AG", 415 | [345] = "Endress + Hauser", 416 | [346] = "Reserved", 417 | [347] = "ABB ALSTOM Power UK Ltd. (EGT)", 418 | [348] = "Berger Lahr GmbH", 419 | [349] = "Reserved", 420 | [350] = "Federal Signal Corp.", 421 | [351] = "Kawasaki Robotics (USA) Inc.", 422 | [352] = "Bently Nevada Corporation", 423 | [353] = "Reserved", 424 | [354] = "FRABA Posital GmbH", 425 | [355] = "Elsag Bailey Inc.", 426 | [356] = "Fanuc Robotics America", 427 | [357] = "Reserved", 428 | [358] = "Surface Combustion Inc.", 429 | [359] = "Reserved", 430 | [360] = "AILES Electronics Ind. Co.Ltd.", 431 | [361] = "Wonderware Corporation", 432 | [362] = "Particle Measuring Systems Inc.", 433 | [363] = "Reserved", 434 | [364] = "Reserved", 435 | [365] = "BITS Co.Ltd", 436 | [366] = "Japan Aviation Electronics Industry Ltd", 437 | [367] = "Keyence Corporation", 438 | [368] = "Kuroda Precision Industries Ltd.", 439 | [369] = "Mitsubishi Electric Semiconductor Application", 440 | [370] = "Nippon Seisen CableLtd.", 441 | [371] = "Omron ASO Co.Ltd", 442 | [372] = "Seiko Seiki Co.Ltd.", 443 | [373] = "Sumitomo Heavy IndustriesLtd.", 444 | [374] = "Tango Computer Service Corporation", 445 | [375] = "Technology Service Inc.", 446 | [376] = "Toshiba Information Systems (Japan) Corporation", 447 | [377] = "TOSHIBA Schneider Inverter Corporation", 448 | [378] = "Toyooki Kogyo Co.Ltd.", 449 | [379] = "XEBEC", 450 | [380] = "Madison Cable Corporation", 451 | [381] = "Hitati Engineering & Services Co.Ltd", 452 | [382] = "TEM-TECH Lab Co.Ltd", 453 | [383] = "International Laboratory Corporation", 454 | [384] = "Dyadic Systems Co.Ltd.", 455 | [385] = "SETO Electronics Industry Co.Ltd", 456 | [386] = "Tokyo Electron Kyushu Limited", 457 | [387] = "KEI System Co.Ltd", 458 | [388] = "Reserved", 459 | [389] = "Asahi Engineering Co.Ltd", 460 | [390] = "Contrex Inc.", 461 | [391] = "Paradigm Controls Ltd.", 462 | [392] = "Reserved", 463 | [393] = "Ohm Electric Co.Ltd.", 464 | [394] = "RKC Instrument Inc.", 465 | [395] = "Suzuki Motor Corporation", 466 | [396] = "Custom Servo Motors Inc.", 467 | [397] = "PACE Control Systems", 468 | [398] = "Reserved", 469 | [399] = "Reserved", 470 | [400] = "LINTEC Co.Ltd.", 471 | [401] = "Hitachi Cable Ltd.", 472 | [402] = "BUSWARE Direct", 473 | [403] = "Eaton Electric B.V. (former Holec Holland N.V.)", 474 | [404] = "VAT Vakuumventile AG", 475 | [405] = "Scientific Technologies Incorporated", 476 | [406] = "Alfa Instrumentos Eletronicos Ltda", 477 | [407] = "TWK Elektronik GmbH", 478 | [408] = "ABB Welding Systems AB", 479 | [409] = "BYSTRONIC Maschinen AG", 480 | [410] = "Kimura Electric Co.Ltd", 481 | [411] = "Nissei Plastic Industrial Co.Ltd", 482 | [412] = "Reserved", 483 | [413] = "Kistler-Morse Corporation", 484 | [414] = "Proteous Industries Inc.", 485 | [415] = "IDC Corporation", 486 | [416] = "Nordson Corporation", 487 | [417] = "Rapistan Systems", 488 | [418] = "LP-Elektronik GmbH", 489 | [419] = "GERBI & FASE S.p.A.(Fase Saldatura)", 490 | [420] = "Phoenix Digital Corporation", 491 | [421] = "Z-World Engineering", 492 | [422] = "Honda R&D Co.Ltd.", 493 | [423] = "Bionics Instrument Co.Ltd.", 494 | [424] = "Teknic Inc.", 495 | [425] = "R.Stahl Inc.", 496 | [426] = "Reserved", 497 | [427] = "Ryco Graphic Manufacturing Inc.", 498 | [428] = "Giddings & Lewis Inc.", 499 | [429] = "Koganei Corporation", 500 | [430] = "Reserved", 501 | [431] = "Nichigoh Communication Electric Wire Co.Ltd.", 502 | [432] = "Reserved", 503 | [433] = "Fujikura Ltd.", 504 | [434] = "AD Link Technology Inc.", 505 | [435] = "StoneL Corporation", 506 | [436] = "Computer Optical Products Inc.", 507 | [437] = "CONOS Inc.", 508 | [438] = "Erhardt + Leimer GmbH", 509 | [439] = "UNIQUE Co. Ltd", 510 | [440] = "Roboticsware Inc.", 511 | [441] = "Nachi Fujikoshi Corporation", 512 | [442] = "Hengstler GmbH", 513 | [443] = "Reserved", 514 | [444] = "SUNNY GIKEN Inc.", 515 | [445] = "Lenze Drive Systems GmbH", 516 | [446] = "CD Systems B.V.", 517 | [447] = "FMT/Aircraft Gate Support Systems AB", 518 | [448] = "Axiomatic Technologies Corp", 519 | [449] = "Embedded System Products Inc.", 520 | [450] = "Reserved", 521 | [451] = "Mencom Corporation", 522 | [452] = "Reserved", 523 | [453] = "Matsushita Welding Systems Co.Ltd.", 524 | [454] = "Dengensha Mfg. Co. Ltd.", 525 | [455] = "Quinn Systems Ltd.", 526 | [456] = "Tellima Technology Ltd", 527 | [457] = "MDT] = Software", 528 | [458] = "Taiwan Keiso Co.Ltd", 529 | [459] = "Pinnacle Systems", 530 | [460] = "Ascom Hasler Mailing Sys", 531 | [461] = "INSTRUMAR Limited", 532 | [462] = "Reserved", 533 | [463] = "Navistar International Transportation Corp", 534 | [464] = "Huettinger Elektronik GmbH + Co. KG", 535 | [465] = "OCM Technology Inc.", 536 | [466] = "Professional Supply Inc.", 537 | [467] = "Control Solutions", 538 | [468] = "Baumer IVO GmbH & Co. KG", 539 | [469] = "Worcester Controls Corporation", 540 | [470] = "Pyramid Technical Consultants Inc.", 541 | [471] = "Reserved", 542 | [472] = "Apollo Fire Detectors Limited", 543 | [473] = "Avtron Manufacturing Inc.", 544 | [474] = "Reserved", 545 | [475] = "Tokyo Keiso Co.Ltd.", 546 | [476] = "Daishowa Swiki Co.Ltd.", 547 | [477] = "Kojima Instruments Inc.", 548 | [478] = "Shimadzu Corporation", 549 | [479] = "Tatsuta Electric Wire & Cable Co.Ltd.", 550 | [480] = "MECS Corporation", 551 | [481] = "Tahara Electric", 552 | [482] = "Koyo Electronics", 553 | [483] = "Clever Devices", 554 | [484] = "GCD Hardware & Software GmbH", 555 | [485] = "Reserved", 556 | [486] = "Miller Electric Mfg Co.", 557 | [487] = "GEA Tuchenhagen GmbH", 558 | [488] = "Riken Keiki Co.] = LTD", 559 | [489] = "Keisokugiken Corporation", 560 | [490] = "Fuji Machine Mfg. Co.Ltd", 561 | [491] = "Reserved", 562 | [492] = "Nidec-Shimpo Corp.", 563 | [493] = "UTEC Corporation", 564 | [494] = "Sanyo Electric Co. Ltd.", 565 | [495] = "Reserved", 566 | [496] = "Reserved", 567 | [497] = "Okano Electric Wire Co. Ltd", 568 | [498] = "Shimaden Co. Ltd.", 569 | [499] = "Teddington Controls Ltd", 570 | [500] = "Reserved", 571 | [501] = "VIPA GmbH", 572 | [502] = "Warwick Manufacturing Group", 573 | [503] = "Danaher Controls", 574 | [504] = "Reserved", 575 | [505] = "Reserved", 576 | [506] = "American Science & Engineering", 577 | [507] = "Accutron Controls International Inc.", 578 | [508] = "Norcott Technologies Ltd", 579 | [509] = "TB Woods Inc", 580 | [510] = "Proportion-Air Inc.", 581 | [511] = "SICK Stegmann GmbH", 582 | [512] = "Reserved", 583 | [513] = "Edwards Signaling", 584 | [514] = "Sumitomo Metal IndustriesLtd", 585 | [515] = "Cosmo Instruments Co.Ltd.", 586 | [516] = "Denshosha Co.Ltd.", 587 | [517] = "Kaijo Corp.", 588 | [518] = "Michiproducts Co.Ltd.", 589 | [519] = "Miura Corporation", 590 | [520] = "TG Information Network Co.Ltd.", 591 | [521] = "Fujikin Inc.", 592 | [522] = "Estic Corp.", 593 | [523] = "GS Hydraulic Sales", 594 | [524] = "Reserved", 595 | [525] = "MTE Limited", 596 | [526] = "Hyde Park Electronics Inc.", 597 | [527] = "Pfeiffer Vacuum GmbH", 598 | [528] = "Cyberlogic Technologies", 599 | [529] = "OKUMA Corporation FA Systems Division", 600 | [530] = "Reserved", 601 | [531] = "Hitachi Kokusai Electric Co.Ltd.", 602 | [532] = "SHINKO TECHNOS Co.Ltd.", 603 | [533] = "Itoh Electric Co.Ltd.", 604 | [534] = "Colorado Flow Tech Inc.", 605 | [535] = "Love Controls Division/Dwyer Inst.", 606 | [536] = "Alstom Drives and Controls", 607 | [537] = "The Foxboro Company", 608 | [538] = "Tescom Corporation", 609 | [539] = "Reserved", 610 | [540] = "Atlas Copco Controls UK", 611 | [541] = "Reserved", 612 | [542] = "Autojet Technologies", 613 | [543] = "Prima Electronics S.p.A.", 614 | [544] = "PMA GmbH", 615 | [545] = "Shimafuji Electric Co.Ltd", 616 | [546] = "Oki Electric Industry Co.Ltd", 617 | [547] = "Kyushu Matsushita Electric Co.Ltd", 618 | [548] = "Nihon Electric Wire & Cable Co.Ltd", 619 | [549] = "Tsuken Electric Ind Co.Ltd", 620 | [550] = "Tamadic Co.", 621 | [551] = "MAATEL SA", 622 | [552] = "OKUMA America", 623 | [553] = "Control Techniques PLC-NA", 624 | [554] = "TPC Wire & Cable", 625 | [555] = "ATI Industrial Automation", 626 | [556] = "Microcontrol (Australia) Pty Ltd", 627 | [557] = "Serra Soldadura] = S.A.", 628 | [558] = "Southwest Research Institute", 629 | [559] = "Cabinplant International", 630 | [560] = "Sartorius Mechatronics T&H GmbH", 631 | [561] = "Comau S.p.A. Robotics & Final Assembly Division", 632 | [562] = "Phoenix Contact", 633 | [563] = "Yokogawa MAT Corporation", 634 | [564] = "asahi sangyo co.] = ltd.", 635 | [565] = "Reserved", 636 | [566] = "Akita Myotoku Ltd.", 637 | [567] = "OBARA Corp.", 638 | [568] = "Suetron Electronic GmbH", 639 | [569] = "Reserved", 640 | [570] = "Serck Controls Limited", 641 | [571] = "Fairchild Industrial Products Company", 642 | [572] = "ARO S.A.", 643 | [573] = "M2C GmbH", 644 | [574] = "Shin Caterpillar Mitsubishi Ltd.", 645 | [575] = "Santest Co.Ltd.", 646 | [576] = "Cosmotechs Co.Ltd.", 647 | [577] = "Hitachi Electric Systems", 648 | [578] = "Smartscan Ltd", 649 | [579] = "Woodhead Software & Electronics France", 650 | [580] = "Athena Controls Inc.", 651 | [581] = "Syron Engineering & Manufacturing Inc.", 652 | [582] = "Asahi Optical Co.Ltd.", 653 | [583] = "Sansha Electric Mfg. Co.Ltd.", 654 | [584] = "Nikki Denso Co.Ltd.", 655 | [585] = "Star Micronics] = Co.Ltd.", 656 | [586] = "Ecotecnia Socirtat Corp.", 657 | [587] = "AC Technology Corp.", 658 | [588] = "West Instruments Limited", 659 | [589] = "NTI Limited", 660 | [590] = "Delta Computer Systems Inc.", 661 | [591] = "FANUC Ltd.", 662 | [592] = "Hearn-Gu Lee", 663 | [593] = "ABB Automation Products", 664 | [594] = "Orion Machinery Co.Ltd.", 665 | [595] = "Reserved", 666 | [596] = "Wire-Pro Inc.", 667 | [597] = "Beijing Huakong Technology Co. Ltd.", 668 | [598] = "Yokoyama Shokai Co.Ltd.", 669 | [599] = "Toyogiken Co.Ltd.", 670 | [600] = "Coester Equipamentos Eletronicos Ltda.", 671 | [601] = "Reserved", 672 | [602] = "Electroplating Engineers of Japan Ltd.", 673 | [603] = "ROBOX S.p.A.", 674 | [604] = "Spraying Systems Company", 675 | [605] = "Benshaw Inc.", 676 | [606] = "ZPA-DP A.S.", 677 | [607] = "Wired Rite Systems", 678 | [608] = "Tandis Research Inc.", 679 | [609] = "SSD Drives GmbH", 680 | [610] = "ULVAC Japan Ltd.", 681 | [611] = "DYNAX Corporation", 682 | [612] = "Nor-Cal Products Inc.", 683 | [613] = "Aros Electronics AB", 684 | [614] = "Jun-Tech Co.Ltd.", 685 | [615] = "HAN-MI Co. Ltd.", 686 | [616] = "uniNtech (formerly SungGi Internet)", 687 | [617] = "Hae Pyung Electronics Reserch Institute", 688 | [618] = "Milwaukee Electronics", 689 | [619] = "OBERG Industries", 690 | [620] = "Parker Hannifin/Compumotor Division", 691 | [621] = "TECHNO DIGITAL CORPORATION", 692 | [622] = "Network Supply Co.Ltd.", 693 | [623] = "Union Electronics Co.Ltd.", 694 | [624] = "Tritronics Services PM Ltd.", 695 | [625] = "Rockwell Automation-Sprecher+Schuh", 696 | [626] = "Matsushita Electric Industrial Co.Ltd/Motor Co.", 697 | [627] = "Rolls-Royce Energy Systems Inc.", 698 | [628] = "JEONGIL INTERCOM CO.] = LTD", 699 | [629] = "Interroll Corp.", 700 | [630] = "Hubbell Wiring Device-Kellems (Delaware)", 701 | [631] = "Intelligent Motion Systems", 702 | [632] = "Reserved", 703 | [633] = "INFICON AG", 704 | [634] = "Hirschmann Inc.", 705 | [635] = "The Siemon Company", 706 | [636] = "YAMAHA Motor Co. Ltd.", 707 | [637] = "aska corporation", 708 | [638] = "Woodhead Connectivity", 709 | [639] = "Trimble AB", 710 | [640] = "Murrelektronik GmbH", 711 | [641] = "Creatrix Labs Inc.", 712 | [642] = "TopWorx", 713 | [643] = "Kumho Industrial Co.Ltd.", 714 | [644] = "Wind River Systems Inc.", 715 | [645] = "Bihl & Wiedemann GmbH", 716 | [646] = "Harmonic Drive Systems Inc.", 717 | [647] = "Rikei Corporation", 718 | [648] = "BL AutotecLtd.", 719 | [649] = "Hana Information & Technology Co.Ltd.", 720 | [650] = "Seoil Electric Co.Ltd.", 721 | [651] = "Fife Corporation", 722 | [652] = "Shanghai Electrical Apparatus Research Institute", 723 | [653] = "Reserved", 724 | [654] = "Parasense Development Centre", 725 | [655] = "Reserved", 726 | [656] = "Reserved", 727 | [657] = "Six Tau S.p.A.", 728 | [658] = "Aucos GmbH", 729 | [659] = "Rotork Controls", 730 | [660] = "Automationdirect.com", 731 | [661] = "Thermo BLH", 732 | [662] = "System ControlsLtd.", 733 | [663] = "Univer S.p.A.", 734 | [664] = "MKS-Tenta Technology", 735 | [665] = "Lika Electronic SNC", 736 | [666] = "Mettler-Toledo Inc.", 737 | [667] = "DXL USA Inc.", 738 | [668] = "Rockwell Automation/Entek IRD Intl.", 739 | [669] = "Nippon Otis Elevator Company", 740 | [670] = "Sinano Electric] = Co.Ltd.", 741 | [671] = "Sony Manufacturing Systems", 742 | [672] = "Reserved", 743 | [673] = "Contec Co.Ltd.", 744 | [674] = "Automated Solutions", 745 | [675] = "Controlweigh", 746 | [676] = "Reserved", 747 | [677] = "Fincor Electronics", 748 | [678] = "Cognex Corporation", 749 | [679] = "Qualiflow", 750 | [680] = "Weidmuller Inc.", 751 | [681] = "Morinaga Milk Industry Co.Ltd.", 752 | [682] = "Takagi Industrial Co.Ltd.", 753 | [683] = "Wittenstein AG", 754 | [684] = "Sena Technologies Inc.", 755 | [685] = "Reserved", 756 | [686] = "APV Products Unna", 757 | [687] = "Creator Teknisk Utvedkling AB", 758 | [688] = "Reserved", 759 | [689] = "Mibu Denki Industrial Co.Ltd.", 760 | [690] = "Takamastsu Machineer Section", 761 | [691] = "Startco Engineering Ltd.", 762 | [692] = "Reserved", 763 | [693] = "Holjeron", 764 | [694] = "ALCATEL High Vacuum Technology", 765 | [695] = "Taesan LCD Co.Ltd.", 766 | [696] = "POSCON", 767 | [697] = "VMIC", 768 | [698] = "Matsushita Electric WorksLtd.", 769 | [699] = "IAI Corporation", 770 | [700] = "Horst GmbH", 771 | [701] = "MicroControl GmbH & Co.", 772 | [702] = "Leine & Linde AB", 773 | [703] = "Reserved", 774 | [704] = "EC Elettronica Srl", 775 | [705] = "VIT Software HB", 776 | [706] = "Bronkhorst High-Tech B.V.", 777 | [707] = "Optex Co.Ltd.", 778 | [708] = "Yosio Electronic Co.", 779 | [709] = "Terasaki Electric Co.Ltd.", 780 | [710] = "Sodick Co.Ltd.", 781 | [711] = "MTS Systems Corporation-Automation Division", 782 | [712] = "Mesa Systemtechnik", 783 | [713] = "SHIN HO SYSTEM Co.Ltd.", 784 | [714] = "Goyo Electronics CoLtd.", 785 | [715] = "Loreme", 786 | [716] = "SAB Brockskes GmbH & Co. KG", 787 | [717] = "Trumpf Laser GmbH + Co. KG", 788 | [718] = "Niigata Electronic Instruments Co.Ltd.", 789 | [719] = "Yokogawa Digital Computer Corporation", 790 | [720] = "O.N. Electronic Co.Ltd.", 791 | [721] = "Industrial Control Communication Inc.", 792 | [722] = "ABB Inc.", 793 | [723] = "ElectroWave USA Inc.", 794 | [724] = "Industrial Network Controls] = LLC", 795 | [725] = "KDT Systems Co.Ltd.", 796 | [726] = "SEFA Technology Inc.", 797 | [727] = "Nippon POP Rivets and Fasteners Ltd.", 798 | [728] = "Yamato Scale Co.Ltd.", 799 | [729] = "Zener Electric", 800 | [730] = "GSE Scale Systems", 801 | [731] = "ISAS (Integrated Switchgear & Sys. Pty Ltd)", 802 | [732] = "Beta LaserMike Limited", 803 | [733] = "TOEI Electric Co.Ltd.", 804 | [734] = "Hakko Electronics Co.Ltd", 805 | [735] = "Reserved", 806 | [736] = "RFID Inc.", 807 | [737] = "Adwin Corporation", 808 | [738] = "Osaka VacuumLtd.", 809 | [739] = "A-Kyung Motion Inc.", 810 | [740] = "Camozzi S.P. A.", 811 | [741] = "Crevis Co.] = LTD", 812 | [742] = "Rice Lake Weighing Systems", 813 | [743] = "Linux Network Services", 814 | [744] = "KEB Antriebstechnik GmbH", 815 | [745] = "Hagiwara Electric Co.Ltd.", 816 | [746] = "Glass Inc. International", 817 | [747] = "Reserved", 818 | [748] = "DVT Corporation", 819 | [749] = "Woodward Governor", 820 | [750] = "Mosaic Systems Inc.", 821 | [751] = "Laserline GmbH", 822 | [752] = "COM-TEC Inc.", 823 | [753] = "Weed Instrument", 824 | [754] = "Prof-face European Technology Center", 825 | [755] = "Fuji Automation Co.Ltd.", 826 | [756] = "Matsutame Co.Ltd.", 827 | [757] = "Hitachi Via MechanicsLtd.", 828 | [758] = "Dainippon Screen Mfg. Co. Ltd.", 829 | [759] = "FLS Automation A/S", 830 | [760] = "ABB Stotz Kontakt GmbH", 831 | [761] = "Technical Marine Service", 832 | [762] = "Advanced Automation Associates Inc.", 833 | [763] = "Baumer Ident GmbH", 834 | [764] = "Tsubakimoto Chain Co.", 835 | [765] = "Reserved", 836 | [766] = "Furukawa Co.Ltd.", 837 | [767] = "Active Power", 838 | [768] = "CSIRO Mining Automation", 839 | [769] = "Matrix Integrated Systems", 840 | [770] = "Digitronic Automationsanlagen GmbH", 841 | [771] = "SICK STEGMANN Inc.", 842 | [772] = "TAE-Antriebstechnik GmbH", 843 | [773] = "Electronic Solutions", 844 | [774] = "Rocon L.L.C.", 845 | [775] = "Dijitized Communications Inc.", 846 | [776] = "Asahi Organic Chemicals Industry Co.Ltd.", 847 | [777] = "Hodensha", 848 | [778] = "Harting Inc. NA", 849 | [779] = "Kubler GmbH", 850 | [780] = "Yamatake Corporation", 851 | [781] = "JEOL", 852 | [782] = "Yamatake Industrial Systems Co.Ltd.", 853 | [783] = "HAEHNE Elektronische Messgerate GmbH", 854 | [784] = "Ci Technologies Pty Ltd (for Pelamos Industries)", 855 | [785] = "N. SCHLUMBERGER & CIE", 856 | [786] = "Teijin Seiki Co.Ltd.", 857 | [787] = "DAIKIN IndustriesLtd", 858 | [788] = "RyuSyo Industrial Co.Ltd.", 859 | [789] = "SAGINOMIYA SEISAKUSHO] = INC.", 860 | [790] = "Seishin Engineering Co.Ltd.", 861 | [791] = "Japan Support System Ltd.", 862 | [792] = "Decsys", 863 | [793] = "Metronix Messgerate u. Elektronik GmbH", 864 | [794] = "Reserved", 865 | [795] = "Vaccon Company Inc.", 866 | [796] = "Siemens Energy & Automation Inc.", 867 | [797] = "Ten X Technology Inc.", 868 | [798] = "Tyco Electronics", 869 | [799] = "Delta Power Electronics Center", 870 | [800] = "Denker", 871 | [801] = "Autonics Corporation", 872 | [802] = "JFE Electronic Engineering Pty. Ltd.", 873 | [803] = "Reserved", 874 | [804] = "Electro-Sensors Inc.", 875 | [805] = "Digi International Inc.", 876 | [806] = "Texas Instruments", 877 | [807] = "ADTEC Plasma Technology Co.Ltd", 878 | [808] = "SICK AG", 879 | [809] = "Ethernet Peripherals Inc.", 880 | [810] = "Animatics Corporation", 881 | [811] = "Reserved", 882 | [812] = "Process Control Corporation", 883 | [813] = "SystemV. Inc.", 884 | [814] = "Danaher Motion SRL", 885 | [815] = "SHINKAWA Sensor Technology Inc.", 886 | [816] = "Tesch GmbH & Co. KG", 887 | [817] = "Reserved", 888 | [818] = "Trend Controls Systems Ltd.", 889 | [819] = "Guangzhou ZHIYUAN Electronic Co.Ltd.", 890 | [820] = "Mykrolis Corporation", 891 | [821] = "Bethlehem Steel Corporation", 892 | [822] = "KK ICP", 893 | [823] = "Takemoto Denki Corporation", 894 | [824] = "The Montalvo Corporation", 895 | [825] = "Reserved", 896 | [826] = "LEONI Special Cables GmbH", 897 | [827] = "Reserved", 898 | [828] = "ONO SOKKI CO.,LTD.", 899 | [829] = "Rockwell Samsung Automation", 900 | [830] = "SHINDENGEN ELECTRIC MFG. CO. LTD", 901 | [831] = "Origin Electric Co. Ltd.", 902 | [832] = "Quest Technical Solutions Inc.", 903 | [833] = "LS CableLtd.", 904 | [834] = "Enercon-Nord Electronic GmbH", 905 | [835] = "Northwire Inc.", 906 | [836] = "Engel Elektroantriebe GmbH", 907 | [837] = "The Stanley Works", 908 | [838] = "Celesco Transducer Products Inc.", 909 | [839] = "Chugoku Electric Wire and Cable Co.", 910 | [840] = "Kongsberg Simrad AS", 911 | [841] = "Panduit Corporation", 912 | [842] = "Spellman High Voltage Electronics Corp.", 913 | [843] = "Kokusai Electric Alpha Co.Ltd.", 914 | [844] = "Brooks Automation Inc.", 915 | [845] = "ANYWIRE CORPORATION", 916 | [846] = "Honda Electronics Co. Ltd", 917 | [847] = "REO Elektronik AG", 918 | [848] = "Fusion UV Systems Inc.", 919 | [849] = "ASI Advanced Semiconductor Instruments GmbH", 920 | [850] = "Datalogic Inc.", 921 | [851] = "SoftPLC Corporation", 922 | [852] = "Dynisco Instruments LLC", 923 | [853] = "WEG Industrias SA", 924 | [854] = "Frontline Test Equipment Inc.", 925 | [855] = "Tamagawa Seiki Co.Ltd.", 926 | [856] = "Multi Computing Co.Ltd.", 927 | [857] = "RVSI", 928 | [858] = "Commercial Timesharing Inc.", 929 | [859] = "Tennessee Rand Automation LLC", 930 | [860] = "Wacogiken Co.Ltd", 931 | [861] = "Reflex Integration Inc.", 932 | [862] = "Siemens AG] = A&D PI Flow Instruments", 933 | [863] = "G. Bachmann Electronic GmbH", 934 | [864] = "NT International", 935 | [865] = "Schweitzer Engineering Laboratories", 936 | [866] = "ATR Industrie-Elektronik GmbH Co.", 937 | [867] = "PLASMATECH Co.Ltd", 938 | [868] = "Reserved", 939 | [869] = "GEMU GmbH & Co. KG", 940 | [870] = "Alcorn McBride Inc.", 941 | [871] = "MORI SEIKI CO.] = LTD", 942 | [872] = "NodeTech Systems Ltd", 943 | [873] = "Emhart Teknologies", 944 | [874] = "Cervis Inc.", 945 | [875] = "FieldServer Technologies (Div Sierra Monitor Corp)", 946 | [876] = "NEDAP Power Supplies", 947 | [877] = "Nippon Sanso Corporation", 948 | [878] = "Mitomi Giken Co.Ltd.", 949 | [879] = "PULS GmbH", 950 | [880] = "Reserved", 951 | [881] = "Japan Control Engineering Ltd", 952 | [882] = "Embedded Systems Korea (Former Zues Emtek Co Ltd.)", 953 | [883] = "Automa SRL", 954 | [884] = "Harms+Wende GmbH & Co KG", 955 | [885] = "SAE-STAHL GmbH", 956 | [886] = "Microwave Data Systems", 957 | [887] = "Bernecker + Rainer Industrie-Elektronik GmbH", 958 | [888] = "Hiprom Technologies", 959 | [889] = "Reserved", 960 | [890] = "Nitta Corporation", 961 | [891] = "Kontron Modular Computers GmbH", 962 | [892] = "Marlin Controls", 963 | [893] = "ELCIS s.r.l.", 964 | [894] = "Acromag Inc.", 965 | [895] = "Avery Weigh-Tronix", 966 | [896] = "Reserved", 967 | [897] = "Reserved", 968 | [898] = "Reserved", 969 | [899] = "Practicon Ltd", 970 | [900] = "Schunk GmbH & Co. KG", 971 | [901] = "MYNAH Technologies", 972 | [902] = "Defontaine Groupe", 973 | [903] = "Emerson Process Management Power & Water Solutions", 974 | [904] = "F.A. Elec", 975 | [905] = "Hottinger Baldwin Messtechnik GmbH", 976 | [906] = "Coreco Imaging Inc.", 977 | [907] = "London Electronics Ltd.", 978 | [908] = "HSD SpA", 979 | [909] = "Comtrol Corporation", 980 | [910] = "TEAM] = S.A. (Tecnica Electronica de Automatismo Y Medida)", 981 | [911] = "MAN B&W Diesel Ltd. Regulateurs Europa", 982 | [912] = "Reserved", 983 | [913] = "Reserved", 984 | [914] = "Micro Motion Inc.", 985 | [915] = "Eckelmann AG", 986 | [916] = "Hanyoung Nux", 987 | [917] = "Ransburg Industrial Finishing KK", 988 | [918] = "Kun Hung Electric Co. Ltd.", 989 | [919] = "Brimos wegbebakening b.v.", 990 | [920] = "Nitto Seiki Co.Ltd", 991 | [921] = "PPT Vision Inc.", 992 | [922] = "Yamazaki Machinery Works", 993 | [923] = "SCHMIDT Technology GmbH", 994 | [924] = "Parker Hannifin SpA (SBC Division)", 995 | [925] = "HIMA Paul Hildebrandt GmbH", 996 | [926] = "RivaTek Inc.", 997 | [927] = "Misumi Corporation", 998 | [928] = "GE Multilin", 999 | [929] = "Measurement Computing Corporation", 1000 | [930] = "Jetter AG", 1001 | [931] = "Tokyo Electronics Systems Corporation", 1002 | [932] = "Togami Electric Mfg. Co.Ltd.", 1003 | [933] = "HK Systems", 1004 | [934] = "CDA Systems Ltd.", 1005 | [935] = "Aerotech Inc.", 1006 | [936] = "JVL Industrie Elektronik A/S", 1007 | [937] = "NovaTech Process Solutions LLC", 1008 | [938] = "Reserved", 1009 | [939] = "Cisco Systems", 1010 | [940] = "Grid Connect", 1011 | [941] = "ITW Automotive Finishing", 1012 | [942] = "HanYang System", 1013 | [943] = "ABB K.K. Technical Center", 1014 | [944] = "Taiyo Electric Wire & Cable Co.Ltd.", 1015 | [945] = "Reserved", 1016 | [946] = "SEREN IPS INC", 1017 | [947] = "Belden CDT Electronics Division", 1018 | [948] = "ControlNet International", 1019 | [949] = "Gefran S.P.A.", 1020 | [950] = "Jokab Safety AB", 1021 | [951] = "SUMITA OPTICAL GLASS] = INC.", 1022 | [952] = "Biffi Italia srl", 1023 | [953] = "Beck IPC GmbH", 1024 | [954] = "Copley Controls Corporation", 1025 | [955] = "Fagor Automation S. Coop.", 1026 | [956] = "DARCOM", 1027 | [957] = "Frick Controls (div. of York International)", 1028 | [958] = "SymCom Inc.", 1029 | [959] = "Infranor", 1030 | [960] = "Kyosan CableLtd.", 1031 | [961] = "Varian Vacuum Technologies", 1032 | [962] = "Messung Systems", 1033 | [963] = "Xantrex Technology Inc.", 1034 | [964] = "StarThis Inc.", 1035 | [965] = "Chiyoda Co.Ltd.", 1036 | [966] = "Flowserve Corporation", 1037 | [967] = "Spyder Controls Corp.", 1038 | [968] = "IBA AG", 1039 | [969] = "SHIMOHIRA ELECTRIC MFG.CO.,LTD", 1040 | [970] = "Reserved", 1041 | [971] = "Siemens L&A", 1042 | [972] = "Micro Innovations AG", 1043 | [973] = "Switchgear & Instrumentation", 1044 | [974] = "PRE-TECH CO.] = LTD.", 1045 | [975] = "National Semiconductor", 1046 | [976] = "Invensys Process Systems", 1047 | [977] = "Ametek HDR Power Systems", 1048 | [978] = "Reserved", 1049 | [979] = "TETRA-K Corporation", 1050 | [980] = "C & M Corporation", 1051 | [981] = "Siempelkamp Maschinen", 1052 | [982] = "Reserved", 1053 | [983] = "Daifuku America Corporation", 1054 | [984] = "Electro-Matic Products Inc.", 1055 | [985] = "BUSSAN MICROELECTRONICS CORP.", 1056 | [986] = "ELAU AG", 1057 | [987] = "Hetronic USA", 1058 | [988] = "NIIGATA POWER SYSTEMS Co.Ltd.", 1059 | [989] = "Software Horizons Inc.", 1060 | [990] = "B3 Systems Inc.", 1061 | [991] = "Moxa Networking Co.Ltd.", 1062 | [992] = "Reserved", 1063 | [993] = "S4 Integration", 1064 | [994] = "Elettro Stemi S.R.L.", 1065 | [995] = "AquaSensors", 1066 | [996] = "Ifak System GmbH", 1067 | [997] = "SANKEI MANUFACTURING Co.,LTD.", 1068 | [998] = "Emerson Network Power Co.Ltd.", 1069 | [999] = "Fairmount Automation Inc.", 1070 | [1000] = "Bird Electronic Corporation", 1071 | [1001] = "Nabtesco Corporation", 1072 | [1002] = "AGM Electronics Inc.", 1073 | [1003] = "ARCX Inc.", 1074 | [1004] = "DELTA I/O Co.", 1075 | [1005] = "Chun IL Electric Ind. Co.", 1076 | [1006] = "N-Tron", 1077 | [1007] = "Nippon Pneumatics/Fludics System CO.,LTD.", 1078 | [1008] = "DDK Ltd.", 1079 | [1009] = "Seiko Epson Corporation", 1080 | [1010] = "Halstrup-Walcher GmbH", 1081 | [1011] = "ITT", 1082 | [1012] = "Ground Fault Systems bv", 1083 | [1013] = "Scolari Engineering S.p.A.", 1084 | [1014] = "Vialis Traffic bv", 1085 | [1015] = "Weidmueller Interface GmbH & Co. KG", 1086 | [1016] = "Shanghai Sibotech Automation Co. Ltd", 1087 | [1017] = "AEG Power Supply Systems GmbH", 1088 | [1018] = "Komatsu Electronics Inc.", 1089 | [1019] = "Souriau", 1090 | [1020] = "Baumuller Chicago Corp.", 1091 | [1021] = "J. Schmalz GmbH", 1092 | [1022] = "SEN Corporation", 1093 | [1023] = "Korenix Technology Co. Ltd", 1094 | [1024] = "Cooper Power Tools", 1095 | [1025] = "INNOBIS", 1096 | [1026] = "Shinho System", 1097 | [1027] = "Xm Services Ltd.", 1098 | [1028] = "KVC Co.Ltd.", 1099 | [1029] = "Sanyu Seiki Co.Ltd.", 1100 | [1030] = "TuxPLC", 1101 | [1031] = "Northern Network Solutions", 1102 | [1032] = "Converteam GmbH", 1103 | [1033] = "Symbol Technologies", 1104 | [1034] = "S-TEAM Lab", 1105 | [1035] = "Maguire Products Inc.", 1106 | [1036] = "AC&T", 1107 | [1037] = "MITSUBISHI HEAVY INDUSTRIES] = LTD. KOBE SHIPYARD & MACHINERY WORKS", 1108 | [1038] = "Hurletron Inc.", 1109 | [1039] = "Chunichi Denshi Co.Ltd", 1110 | [1040] = "Cardinal Scale Mfg. Co.", 1111 | [1041] = "BTR NETCOM via RIA Connect Inc.", 1112 | [1042] = "Base2", 1113 | [1043] = "ASRC Aerospace", 1114 | [1044] = "Beijing Stone Automation", 1115 | [1045] = "Changshu Switchgear Manufacture Ltd.", 1116 | [1046] = "METRONIX Corp.", 1117 | [1047] = "WIT", 1118 | [1048] = "ORMEC Systems Corp.", 1119 | [1049] = "ASATech (China) Inc.", 1120 | [1050] = "Controlled Systems Limited", 1121 | [1051] = "Mitsubishi Heavy Ind. Digital System Co.Ltd. (M.H.I.)", 1122 | [1052] = "Electrogrip", 1123 | [1053] = "TDS Automation", 1124 | [1054] = "T&C Power Conversion Inc.", 1125 | [1055] = "Robostar Co.Ltd", 1126 | [1056] = "Scancon A/S", 1127 | [1057] = "Haas Automation Inc.", 1128 | [1058] = "Eshed Technology", 1129 | [1059] = "Delta Electronic Inc.", 1130 | [1060] = "Innovasic Semiconductor", 1131 | [1061] = "SoftDEL Systems Limited", 1132 | [1062] = "FiberFin Inc.", 1133 | [1063] = "Nicollet Technologies Corp.", 1134 | [1064] = "B.F. Systems", 1135 | [1065] = "Empire Wire and Supply LLC", 1136 | [1066] = "Reserved", 1137 | [1067] = "Elmo Motion Control LTD", 1138 | [1068] = "Reserved", 1139 | [1069] = "Asahi Keiki Co.Ltd.", 1140 | [1070] = "Joy Mining Machinery", 1141 | [1071] = "MPM Engineering Ltd", 1142 | [1072] = "Wolke Inks & Printers GmbH", 1143 | [1073] = "Mitsubishi Electric Engineering Co.Ltd.", 1144 | [1074] = "COMET AG", 1145 | [1075] = "Real Time Objects & Systems] = LLC", 1146 | [1076] = "MISCO Refractometer", 1147 | [1077] = "JT Engineering Inc.", 1148 | [1078] = "Automated Packing Systems", 1149 | [1079] = "Niobrara R&D Corp.", 1150 | [1080] = "Garmin Ltd.", 1151 | [1081] = "Japan Mobile Platform Co.Ltd", 1152 | [1082] = "Advosol Inc.", 1153 | [1083] = "ABB Global Services Limited", 1154 | [1084] = "Sciemetric Instruments Inc.", 1155 | [1085] = "Tata Elxsi Ltd.", 1156 | [1086] = "TPC Mechatronics] = Co.Ltd.", 1157 | [1087] = "Cooper Bussmann", 1158 | [1088] = "Trinite Automatisering B.V.", 1159 | [1089] = "Peek Traffic B.V.", 1160 | [1090] = "Acrison Inc", 1161 | [1091] = "Applied Robotics Inc.", 1162 | [1092] = "FireBus Systems Inc.", 1163 | [1093] = "Beijing Sevenstar Huachuang Electronics", 1164 | [1094] = "Magnetek", 1165 | [1095] = "Microscan", 1166 | [1096] = "Air Water Inc.", 1167 | [1097] = "Sensopart Industriesensorik GmbH", 1168 | [1098] = "Tiefenbach Control Systems GmbH", 1169 | [1099] = "INOXPA S.A", 1170 | [1100] = "Zurich University of Applied Sciences", 1171 | [1101] = "Ethernet Direct", 1172 | [1102] = "GSI-Micro-E Systems", 1173 | [1103] = "S-Net Automation Co.Ltd.", 1174 | [1104] = "Power Electronics S.L.", 1175 | [1105] = "Renesas Technology Corp.", 1176 | [1106] = "NSWCCD-SSES", 1177 | [1107] = "Porter Engineering Ltd.", 1178 | [1108] = "Meggitt Airdynamics Inc.", 1179 | [1109] = "Inductive Automation", 1180 | [1110] = "Neural ID", 1181 | [1111] = "EEPod LLC", 1182 | [1112] = "Hitachi Industrial Equipment Systems Co.Ltd.", 1183 | [1113] = "Salem Automation", 1184 | [1114] = "port GmbH", 1185 | [1115] = "B & PLUS", 1186 | [1116] = "Graco Inc.", 1187 | [1117] = "Altera Corporation", 1188 | [1118] = "Technology Brewing Corporation", 1189 | [1121] = "CSE Servelec", 1190 | [1124] = "Fluke Networks", 1191 | [1125] = "Tetra Pak Packaging Solutions SPA", 1192 | [1126] = "Racine Federated Inc.", 1193 | [1127] = "Pureron Japan Co.Ltd.", 1194 | [1130] = "Brother IndustriesLtd.", 1195 | [1132] = "Leroy Automation", 1196 | [1134] = "THK CO.] = LTD.", 1197 | [1137] = "TR-Electronic GmbH", 1198 | [1138] = "ASCON S.p.A.", 1199 | [1139] = "Toledo do Brasil Industria de Balancas Ltda.", 1200 | [1140] = "Bucyrus DBT Europe GmbH", 1201 | [1141] = "Emerson Process Management Valve Automation", 1202 | [1142] = "Alstom Transport", 1203 | [1144] = "Matrox Electronic Systems", 1204 | [1145] = "Littelfuse", 1205 | [1146] = "PLASMART Inc.", 1206 | [1147] = "Miyachi Corporation", 1207 | [1150] = "Promess Incorporated", 1208 | [1151] = "COPA-DATA GmbH", 1209 | [1152] = "Precision Engine Controls Corporation", 1210 | [1153] = "Alga Automacao e controle LTDA", 1211 | [1154] = "U.I. Lapp GmbH", 1212 | [1155] = "ICES", 1213 | [1156] = "Philips Lighting bv", 1214 | [1157] = "Aseptomag AG", 1215 | [1158] = "ARC Informatique", 1216 | [1159] = "Hesmor GmbH", 1217 | [1160] = "Kobe SteelLtd.", 1218 | [1161] = "FLIR Systems", 1219 | [1162] = "Simcon A/S", 1220 | [1163] = "COPALP", 1221 | [1164] = "Zypcom Inc.", 1222 | [1165] = "Swagelok", 1223 | [1166] = "Elspec", 1224 | [1167] = "ITT Water & Wastewater AB", 1225 | [1168] = "Kunbus GmbH Industrial Communication", 1226 | [1170] = "Performance Controls Inc.", 1227 | [1171] = "ACS Motion ControlLtd.", 1228 | [1173] = "IStar Technology Limited", 1229 | [1174] = "Alicat Scientific Inc.", 1230 | [1176] = "ADFweb.com SRL", 1231 | [1177] = "Tata Consultancy Services Limited", 1232 | [1178] = "CXR Ltd.", 1233 | [1179] = "Vishay Nobel AB", 1234 | [1181] = "SolaHD", 1235 | [1182] = "Endress+Hauser", 1236 | [1183] = "Bartec GmbH", 1237 | [1185] = "AccuSentry Inc.", 1238 | [1186] = "Exlar Corporation", 1239 | [1187] = "ILS Technology", 1240 | [1188] = "Control Concepts Inc.", 1241 | [1190] = "Procon Engineering Limited", 1242 | [1191] = "Hermary Opto Electronics Inc.", 1243 | [1192] = "Q-Lambda", 1244 | [1194] = "VAMP Ltd", 1245 | [1195] = "FlexLink", 1246 | [1196] = "Office FA.com Co.Ltd.", 1247 | [1197] = "SPMC (Changzhou) Co. Ltd.", 1248 | [1198] = "Anton Paar GmbH", 1249 | [1199] = "Zhuzhou CSR Times Electric Co.Ltd.", 1250 | [1200] = "DeStaCo", 1251 | [1201] = "Synrad Inc", 1252 | [1202] = "Bonfiglioli Vectron GmbH", 1253 | [1203] = "Pivotal Systems", 1254 | [1204] = "TKSCT", 1255 | [1205] = "Randy Nuernberger", 1256 | [1206] = "CENTRALP", 1257 | [1207] = "Tengen Group", 1258 | [1208] = "OES Inc.", 1259 | [1209] = "Actel Corporation", 1260 | [1210] = "Monaghan Engineering Inc.", 1261 | [1211] = "wenglor sensoric gmbh", 1262 | [1212] = "HSA Systems", 1263 | [1213] = "MK Precision Co.Ltd.", 1264 | [1214] = "Tappan Wire and Cable", 1265 | [1215] = "Heinzmann GmbH & Co. KG", 1266 | [1216] = "Process Automation International Ltd.", 1267 | [1217] = "Secure Crossing", 1268 | [1218] = "SMA Railway Technology GmbH", 1269 | [1219] = "FMS Force Measuring Systems AG", 1270 | [1220] = "ABT Endustri Enerji Sistemleri Sanayi Tic. Ltd. Sti.", 1271 | [1221] = "MagneMotion Inc.", 1272 | [1222] = "STS Co.Ltd.", 1273 | [1223] = "MERAK SIC] = SA", 1274 | [1224] = "ABOUNDI Inc.", 1275 | [1225] = "Rosemount Inc.", 1276 | [1226] = "GEA FES Inc.", 1277 | [1227] = "TMG Technologie und Engineering GmbH", 1278 | [1228] = "embeX GmbH", 1279 | [1229] = "GH Electrotermia] = S.A.", 1280 | [1230] = "Tolomatic", 1281 | [1231] = "Dukane", 1282 | [1232] = "Elco (Tian Jin) Electronics Co.Ltd.", 1283 | [1233] = "Jacobs Automation", 1284 | [1234] = "Noda Radio Frequency Technologies Co.Ltd.", 1285 | [1235] = "MSC Tuttlingen GmbH", 1286 | [1236] = "Hitachi Cable Manchester", 1287 | [1237] = "ACOREL SAS", 1288 | [1238] = "Global Engineering Solutions Co.Ltd.", 1289 | [1239] = "ALTE Transportation] = S.L.", 1290 | [1240] = "Penko Engineering B.V." 1291 | } 1292 | --return vendor information 1293 | local function vendor_lookup(vennum) 1294 | return vendor_id[vennum] or "Unknown Vendor Number" 1295 | end 1296 | 1297 | --- 1298 | -- Table to look up the Device Type based on Device ID Number 1299 | -- Returns "Unknown Device Type" if Device ID Number not recognized 1300 | -- Table data from Wireshark dissector ( link to unofficial mirror ) 1301 | -- https://github.com/avsej/wireshark/blob/master/epan/dissectors/packet-enip.c 1302 | -- Fetched on 4/19/2014 1303 | -- 1304 | -- @key devtype Device ID number parsed out of the EtherNet/IP packet 1305 | local device_type = { 1306 | [0] = "Generic Device (deprecated)", 1307 | [2] = "AC Drive", 1308 | [3] = "Motor Overload", 1309 | [4] = "Limit Switch", 1310 | [5] = "Inductive Proximity Switch" , 1311 | [6] = "Photoelectric Sensor", 1312 | [7] = "General Purpose Discrete I/O", 1313 | [9] = "Resolver", 1314 | [12] = "Communications Adapter", 1315 | [14] = "Programmable Logic Controller", 1316 | [16] = "Position Controller", 1317 | [19] = "DC Drive", 1318 | [21] = "Contactor", 1319 | [22] = "Motor Starter", 1320 | [23] = "Soft Start", 1321 | [24] = "Human-Machine Interface", 1322 | [26] = "Mass Flow Controller", 1323 | [27] = "Pneumatic Valve", 1324 | [28] = "Vacuum Pressure Gauge", 1325 | [29] = "Process Control Value", 1326 | [30] = "Residual Gas Analyzer", 1327 | [31] = "DC Power Generator", 1328 | [32] = "RF Power Generator", 1329 | [33] = "Turbomolecular Vacuum Pump", 1330 | [34] = "Encoder" , 1331 | [35] = "Safety Discrete I/O Device", 1332 | [36] = "Fluid Flow Controller", 1333 | [37] = "CIP Motion Drive", 1334 | [38] = "CompoNet Repeater", 1335 | [39] = "Mass Flow Controller Enhanced", 1336 | [40] = "CIP Modbus Device", 1337 | [41] = "CIP Modbus Translator", 1338 | [42] = "Safety Analog I/O Device", 1339 | [43] = "Generic Device (keyable)", 1340 | [44] = "Managed Switch", 1341 | [59] = "ControlNet Physical Layer Component" 1342 | 1343 | } 1344 | --return device type information 1345 | function device_type_lookup (devtype) 1346 | return device_type[devtype] or "Unknown Device Type" 1347 | end 1348 | 1349 | --- 1350 | -- Function to set the nmap output for the host, if a valid EtherNet/IP packet 1351 | -- is received then the output will show that the port as EtherNet/IP instead of 1352 | -- unknown 1353 | -- 1354 | -- @param host Host that was passed in via nmap 1355 | -- @param port port that EtherNet/IP is running on (Default TCP/44818) 1356 | function set_nmap(host, port) 1357 | 1358 | --set port Open 1359 | port.state = "open" 1360 | -- set version name to EtherNet/IP 1361 | port.version.name = "EtherNet/IP" 1362 | nmap.set_port_version(host, port) 1363 | nmap.set_port_state(host, port, "open") 1364 | 1365 | end 1366 | --- 1367 | -- Action Function that is used to run the NSE. This function will send the initial query to the 1368 | -- host and port that were passed in via nmap. The initial response is parsed to determine if host 1369 | -- is a EtherNet/IP device. If it is then more actions are taken to gather extra information. 1370 | -- 1371 | -- @param host Host that was scanned via nmap 1372 | -- @param port port that was scanned via nmap 1373 | action = function(host,port) 1374 | -- pack the request identity packet (0x63) 1375 | local enip_req_ident = bin.pack("H","63000000000000000000000000000000c1debed100000000") 1376 | -- create table for output 1377 | local output = stdnse.output_table() 1378 | -- create local vars for socket handling 1379 | local socket, try, catch 1380 | -- create new socket 1381 | socket = nmap.new_socket() 1382 | -- define the catch of the try statement 1383 | catch = function() 1384 | socket:close() 1385 | end 1386 | -- create new try 1387 | try = nmap.new_try(catch) 1388 | 1389 | -- connect to port on host 1390 | try(socket:connect(host, port)) 1391 | -- send Req Identity packet 1392 | try(socket:send(enip_req_ident)) 1393 | -- receive response 1394 | local rcvstatus, response = socket:receive() 1395 | if(rcvstatus == false) then 1396 | return false, response 1397 | end 1398 | -- unpack the response command 1399 | local pos, command = bin.unpack("C", response, 1) 1400 | -- unpack the response type id 1401 | local pos, typeid = bin.unpack("C", response, 27) 1402 | -- if command is 0x63 1403 | if ( command == 0x63) then 1404 | -- if typeid == 0x0c (req ident) 1405 | if( typeid == 0x0c) then 1406 | 1407 | -- vendor number 1408 | local pos, vennum = bin.unpack("