1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Try to make sure enough data is present before parsing. See #2117

This commit is contained in:
dmiller
2020-09-10 22:02:12 +00:00
parent 9b113b03be
commit 3b633fd97c

View File

@@ -60,13 +60,14 @@ portrule = shortport.version_port_or_service(102, "iso-tsap", "tcp")
-- inside of the main action.
-- @param socket the socket that was created in Action.
-- @param query the specific query that you want to send/receive on.
local function send_receive(socket, query)
-- @param bytes how many bytes (minimum) you expect back
local function send_receive(socket, query, bytes)
local sendstatus, senderr = socket:send(query)
if(sendstatus == false) then
return "Error Sending S7COMM"
end
-- receive response
local rcvstatus, response = socket:receive()
local rcvstatus, response = socket:receive_bytes(bytes)
if(rcvstatus == false) then
return "Error Reading S7COMM"
end
@@ -90,7 +91,7 @@ local function parse_response(response, host, port, output)
-- unpack the second byte of the SZL-ID
local szl_id = string.byte(response, 31)
-- if the protocol ID is 0x32
if (value == 0x32) then
if (value == 0x32 and #response >= 125) then
-- unpack the module information
output["Module"] = string.unpack("z", response, 44)
-- unpack the basic hardware information
@@ -128,20 +129,26 @@ local function second_parse_response(response, output)
-- change offset to 4, this is where most of valid PLCs will fall
offset = 4
end
if #response < 142 + offset then
stdnse.debug1("Short response cannot be parsed.")
return nil
end
-- parse system name
if #response > 40 + offset then
output["System Name"] = string.unpack("z", response, 40 + offset)
end
-- parse module type
if #response > 74 + offset then
output["Module Type"] = string.unpack("z", response, 74 + offset)
end
-- parse serial number
if #response > 176 + offset then
output["Serial Number"] = string.unpack("z", response, 176 + offset)
end
-- parse plant identification
if #response > 108 + offset then
output["Plant Identification"] = string.unpack("z", response, 108 + offset)
end
-- parse copyright
if #response > 142 + offset then
output["Copyright"] = string.unpack("z", response, 142 + offset)
end
-- for each element in the table, if it is nil, then remove the information from the table
for key, value in pairs(output) do
@@ -206,7 +213,7 @@ local COTP = stdnse.fromhex( "0300001611e00000001400c1020100c2020" .. "102" .. "
return nil
end
-- send and receive the COTP Packet
response = send_receive(sock, COTP)
response = send_receive(sock, COTP, 6)
-- unpack the PDU Type
local CC_connect_confirm = string.byte(response, 6)
-- if PDU type is not 0xd0, then not a successful COTP connection
@@ -221,7 +228,7 @@ local COTP = stdnse.fromhex( "0300001611e00000001400c1020100c2020" .. "102" .. "
stdnse.debug1('Error establishing connection for %s - %s', host, conerr)
return nil
end
response = send_receive(sock, alt_COTP)
response = send_receive(sock, alt_COTP, 6)
local CC_connect_confirm = string.byte(response, 6)
if ( CC_connect_confirm ~= 0xd0) then
stdnse.debug1('S7 INFO:: Could not negotiate COTP')
@@ -229,7 +236,7 @@ local COTP = stdnse.fromhex( "0300001611e00000001400c1020100c2020" .. "102" .. "
end
end
-- send and receive the ROSCTR Setup Packet
response = send_receive(sock, ROSCTR_Setup)
response = send_receive(sock, ROSCTR_Setup, 8)
-- unpack the protocol ID
local protocol_id = string.byte(response, 8)
-- if protocol ID is not 0x32 then return nil
@@ -237,18 +244,18 @@ local COTP = stdnse.fromhex( "0300001611e00000001400c1020100c2020" .. "102" .. "
return nil
end
-- send and receive the READ_SZL packet
response = send_receive(sock, Read_SZL)
response = send_receive(sock, Read_SZL, 8)
local protocol_id = string.byte(response, 8)
-- if protocol ID is not 0x32 then return nil
if ( protocol_id ~= 0x32) then
return nil
end
-- send and receive the first SZL Request packet
response = send_receive(sock, first_SZL_Request)
response = send_receive(sock, first_SZL_Request, 125)
-- parse the response for basic hardware information
output = parse_response(response, host, port, output)
-- send and receive the second SZL Request packet
response = send_receive(sock, second_SZL_Request)
response = send_receive(sock, second_SZL_Request, 180)
-- parse the response for more information
output = second_parse_response(response, output)
-- close the socket