I am writing a script using the Nmap Scripting Engine (NSE) to extract the product name and the article number through a Lookup Request using DCE/RPC Endpoint Mapper. However, while testing the script, I encountered something unusual. Here is a snippet from my experiments:
First, the machine scanning the network (IP: 192.168.10.56) sends a request with a random source port 51336 to the UDP destination port 34964. The first scanned Siemens device (IP: 192.168.10.12) responds as expected, using port 34964 as source port for the reply. However, the second scanned device (IP: 192.168.10.21) behaves differently. It also replies to the request but uses a random source port for the reply, in this case, 49344. NMAP receives the response from IP 192.168.10.12 but not from IP 192.168.10.21 due to this unexpected new source port. Is there a way to open a socket using NSE to accept all incoming messages on a specific port? Something like a "server port" accepting all incoming requests? Right now I am using the funtion socket:connect(ip, 34964, "udp") specifing the port on the scanned hosts causing this problem. Here a snippet from the script I am using:
send_udp_payload = function(ip, timeout, payload)
local socket, try, catch
-- create a new udp socket
local socket = nmap.new_socket("udp")
-- set timeout
socket:set_timeout(tonumber(timeout))
catch = function()
socket:close()
end
-- create new try
try = nmap.new_try(catch)
-- connect to port on host
try(socket:connect(ip, 34964, "udp"))
-- send lookup packet with PNIO Interface UUID
try(socket:send(payload))
-- receive response
local rcvstatus, response = socket:receive()
-- close socket
socket:close()
if rcvstatus then
return response
else
return nil
end
end
Using pcap:receive() could solve my problem:
lookup_request = function(host, port, src_port_number, payload, timeout)
local socket, try, catch
local socket = nmap.new_socket("udp")
local pcap = nmap.new_socket()
socket:set_timeout(tonumber(timeout))
catch = function()
socket:close()
end
try = nmap.new_try(catch)
socket:bind(nil, src_port_number)
try(socket:connect(host.ip, port["number"], "udp"))
pcap:pcap_open(host.interface, 1500, false, "udp dst port " .. src_port_number .. " and src host " .. host.ip)
pcap:set_timeout(host.times.timeout * 1000)
try(socket:send(payload))
local status, len, _, layer3 = pcap:pcap_receive()
pcap:close()
socket:close()
-- parse response
-- ...
end