summaryrefslogtreecommitdiffstats
path: root/scripts/omron-info.nse
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/omron-info.nse')
-rw-r--r--scripts/omron-info.nse197
1 files changed, 197 insertions, 0 deletions
diff --git a/scripts/omron-info.nse b/scripts/omron-info.nse
new file mode 100644
index 0000000..54561c4
--- /dev/null
+++ b/scripts/omron-info.nse
@@ -0,0 +1,197 @@
+local nmap = require "nmap"
+local shortport = require "shortport"
+local stdnse = require "stdnse"
+local string = require "string"
+
+description = [[
+This NSE script is used to send a FINS packet to a remote device. The script
+will send a Controller Data Read Command and once a response is received, it
+validates that it was a proper response to the command that was sent, and then
+will parse out the data.
+]]
+---
+-- @usage
+-- nmap --script omron-info -sU -p 9600 <host>
+--
+-- @output
+-- 9600/tcp open OMRON FINS
+-- | omron-info:
+-- | Controller Model: CJ2M-CPU32 02.01
+-- | Controller Version: 02.01
+-- | For System Use:
+-- | Program Area Size: 20
+-- | IOM size: 23
+-- | No. DM Words: 32768
+-- | Timer/Counter: 8
+-- | Expansion DM Size: 1
+-- | No. of steps/transitions: 0
+-- | Kind of Memory Card: 0
+-- |_ Memory Card Size: 0
+
+-- @xmloutput
+-- <elem key="Controller Model">CS1G_CPU44H 03.00</elem>
+-- <elem key="Controller Version">03.00</elem>
+-- <elem key="For System Use"></elem>
+-- <elem key="Program Area Size">20</elem>
+-- <elem key="IOM size">23</elem>
+-- <elem key="No. DM Words">32768</elem>
+-- <elem key="Timer/Counter">8</elem>
+-- <elem key="Expansion DM Size">1</elem>
+-- <elem key="No. of steps/transitions">0</elem>
+-- <elem key="Kind of Memory Card">0</elem>
+-- <elem key="Memory Card Size">0</elem>
+
+
+author = "Stephen Hilt (Digital Bond)"
+license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
+categories = {"discovery", "version"}
+
+--
+-- Function to define the portrule as per nmap standards
+--
+--
+portrule = shortport.version_port_or_service(9600, "fins", {"tcp", "udp"})
+
+---
+-- Function to set the nmap output for the host, if a valid OMRON FINS packet
+-- is received then the output will show that the port is open instead of
+-- <code>open|filtered</code>
+--
+-- @param host Host that was passed in via nmap
+-- @param port port that FINS is running on (Default UDP/9600)
+function set_nmap(host, port)
+
+ --set port Open
+ port.state = "open"
+ -- set version name to OMRON FINS
+ port.version.name = "fins"
+ nmap.set_port_version(host, port)
+ nmap.set_port_state(host, port, "open")
+
+end
+
+local memcard = {
+ [0] = "No Memory Card",
+ [1] = "SPRAM",
+ [2] = "EPROM",
+ [3] = "EEPROM"
+}
+
+function memory_card(value)
+ local mem_card = memcard[value] or "Unknown Memory Card Type"
+ return mem_card
+end
+---
+-- send_udp is a function that is used to run send the appropriate traffic to
+-- the omron devices via UDP
+--
+-- @param socket Socket that is passed in from Action
+function send_udp(socket)
+ local controller_data_read = stdnse.fromhex( "800002000000006300ef050100")
+ -- send Request Information Packet
+ socket:send(controller_data_read)
+ local rcvstatus, response = socket:receive()
+ return response
+end
+---
+-- send_tcp is a function that is used to run send the appropriate traffic to
+-- the omron devices via TCP
+--
+-- @param socket Socket that is passed in from Action
+function send_tcp(socket)
+ -- this is the request address command
+ local req_addr = stdnse.fromhex( "46494e530000000c000000000000000000000000")
+ -- TCP requires a network address that is revived from the first request,
+ -- The read controller data these two strings will be joined with the address
+ local controller_data_read = stdnse.fromhex("46494e5300000015000000020000000080000200")
+ local controller_data_read2 = stdnse.fromhex("000000ef050501")
+
+ -- send Request Information Packet
+ socket:send(req_addr)
+ local rcvstatus, response = socket:receive()
+ local header = string.byte(response, 1)
+ if(header == 0x46) then
+ local address = string.byte(response, 24)
+ local controller_data = ("%s%c%s%c"):format(controller_data_read, address, controller_data_read2, 0x00)
+ -- send the read controller data request
+ socket:send(controller_data)
+ local rcvstatus, response = socket:receive()
+ return response
+ end
+ return "ERROR"
+end
+
+---
+-- Action Function that is used to run the NSE. This function will send the initial query to the
+-- host and port that were passed in via nmap. The initial response is parsed to determine if host
+-- is a FINS supported device.
+--
+-- @param host Host that was scanned via nmap
+-- @param port port that was scanned via nmap
+action = function(host,port)
+
+ -- create table for output
+ local output = stdnse.output_table()
+ -- create new socket
+ local socket = nmap.new_socket()
+ local catch = function()
+ socket:close()
+ end
+ -- create new try
+ local try = nmap.new_try(catch)
+ -- connect to port on host
+ try(socket:connect(host, port))
+ -- init response var
+ local response = ""
+ -- set offset to 0, this will mean its UDP
+ local offset = 0
+ -- check to see if the protocol is TCP, if it is set offset to 16
+ -- and perform the tcp_send function
+ if (port.protocol == "tcp")then
+ offset = 16
+ response = send_tcp(socket)
+ -- else its udp and call the send_udp function
+ else
+ response = send_udp(socket)
+ end
+ -- unpack the first byte for checking that it was a valid response
+ local header = string.unpack("B", response, 1)
+ if(header == 0xc0 or header == 0xc1 or header == 0x46) then
+ set_nmap(host, port)
+ local response_code = string.unpack("<I2", response, 13 + offset)
+ -- test for a few of the error codes I saw when testing the script
+ if(response_code == 2081) then
+ output["Response Code"] = "Data cannot be changed (0x2108)"
+ elseif(response_code == 290) then
+ output["Response Code"] = "The mode is wrong (executing) (0x2201)"
+ -- if a successful response code then
+ elseif(response_code == 0) then
+ -- parse information from response
+ output["Response Code"] = "Normal completion (0x0000)"
+ output["Controller Model"] = string.unpack("z", response,15 + offset)
+ output["Controller Version"] = string.unpack("z", response, 35 + offset)
+ output["For System Use"] = string.unpack("z", response, 55 + offset)
+ local pos
+ output["Program Area Size"], pos = string.unpack(">I2", response, 95 + offset)
+ output["IOM size"], pos = string.unpack("B", response, pos)
+ output["No. DM Words"], pos = string.unpack(">I2", response, pos)
+ output["Timer/Counter"], pos = string.unpack("B", response, pos)
+ output["Expansion DM Size"], pos = string.unpack("B", response, pos)
+ output["No. of steps/transitions"], pos = string.unpack(">I2", response, pos)
+ local mem_card_type
+ mem_card_type, pos = string.unpack("B", response, pos)
+ output["Kind of Memory Card"] = memory_card(mem_card_type)
+ output["Memory Card Size"], pos = string.unpack(">I2", response, pos)
+
+ else
+ output["Response Code"] = "Unknown Response Code"
+ end
+ socket:close()
+ return output
+
+ else
+ socket:close()
+ return nil
+ end
+
+end