-
Notifications
You must be signed in to change notification settings - Fork 148
/
cspv4-info.nse
102 lines (94 loc) · 3 KB
/
cspv4-info.nse
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
local bin = require "bin"
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
local table = require "table"
description = [[
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
and used by CSPV4 on AB PLC5 systems. This will determine the Session ID of the remote device to verify it as a CSPV4
compliant device. CSPV4 or AB/Ethernet is used by Allen Bradley inside of its software products such as RSLinx to
communicate to the PLCs. This will help ideitify some Allen Bradley PLCs that do not communicate via Ethernet/IP.
Example: PLC5, SLC 500
]]
---
-- @usage
-- nmap --script cspv4-info -p 2222 <host>
--
--
-- @output
--PORT STATE SERVICE
--2222/tcp open CSPV4
--| cspv4-info:
--|_ Session ID: 65792
author = "Stephen Hilt"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"discovery", "intrusive"}
--
-- Function to define the portrule as per nmap standards
--
--
--
portrule = shortport.portnumber(2222, "tcp")
---
-- Function to set the nmap output for the host, if a valid CSPV4 packet
-- is received then the output will show that the port as CSPV4 instead of
-- <code>unknown</code>
--
-- @param host Host that was passed in via nmap
-- @param port port that CSPV4 is running on (Default TCP/2222)
function set_nmap(host, port)
--set port Open
port.state = "open"
-- set version name to cspv4
port.version.name = "CSPV4"
nmap.set_port_version(host, port)
nmap.set_port_state(host, port, "open")
end
---
-- Action Function that is used to run the NSE.
--
-- @param host Host that was scanned via nmap
-- @param port port that was scanned via nmap
action = function(host,port)
-- pack the inital communications to the PLC5
local init_coms = bin.pack("H","01010000000000000000000000040005000000000000000000000000")
-- create table for output
local output = stdnse.output_table()
-- create local vars for socket handling
local socket, try, catch
-- create new socket
socket = nmap.new_socket()
-- define the catch of the try statement
catch = function()
socket:close()
end
-- create new try
try = nmap.new_try(catch)
-- connect to port on host
try(socket:connect(host, port))
-- send Req Identity packet
try(socket:send(init_coms))
-- receive response
local rcvstatus, response = socket:receive()
if(rcvstatus == false) then
return false, response
end
-- unpack the response first byte
local pos, first_check = bin.unpack("C", response, 1)
-- Validate the response is the response we expected
if(first_check == 0x02) then
-- store Session ID in output table
pos, output["Session ID"] = bin.unpack("i", response, 5)
-- set Nmap output
set_nmap(host, port)
-- close socket
socket:close()
-- return output table to Nmap
return output
-- If response is not what expcted then close connection and return nothing
else
socket:close()
return nil
end
end