Nmap Development mailing list archives

Re: [NSE] rpcinfo script


From: Sven Klemm <sven () c3d2 de>
Date: Sun, 06 Jan 2008 18:05:44 +0100

Fyodor wrote:
On Wed, Dec 19, 2007 at 11:32:04PM +0100, Sven Klemm wrote:
Hi everyone,

I've attached a NSE script that will query the portmapper for a list
of all registered programs. This is similar to rpcinfo -p.

Thanks, it worked well in my testing.  I added all the rpc entries
(almost 400) from nmap-rpc, though it would be nice to find a way to
remove that redundancy.  Like maybe the script could read nmap-rpc
itself, though I'm not sure how easily it could find the file.  Or it
could call the Nmap function which converts from rpc number to name.
Anyway, for now I've just added them to the array.  If a second script
needs this though, we should definitely put the funcionality in a
common NSELib function (either Lua or C).

rpcinfo.nse is now checked into SVN.

Thank you very much.

I've modified the script to format the output more nicely.

The old output looked like this returning a line for every entry of
the answer.

Starting Nmap 4.52 ( http://insecure.org ) at 2008-01-06 17:44 CET
Interesting ports on localhost (127.0.0.1):
PORT    STATE SERVICE
111/tcp open  rpcbind
|  rpcinfo: rpcbind(2) 111/tcp
|  rpcbind(2) 111/udp
|  status(1) 32769/udp
|  nlockmgr(1) 32769/udp
|  nlockmgr(3) 32769/udp
|  nlockmgr(4) 32769/udp
|  status(1) 59834/tcp
|  nlockmgr(1) 59834/tcp
|  nlockmgr(3) 59834/tcp
|  nlockmgr(4) 59834/tcp
|  nfs(2) 2049/udp
|  nfs(3) 2049/udp
|  nfs(4) 2049/udp
|  nfs(2) 2049/tcp
|  nfs(3) 2049/tcp
|  nfs(4) 2049/tcp
|  mountd(1) 710/udp
|  mountd(1) 711/tcp
|  mountd(2) 710/udp
|  mountd(2) 711/tcp
|  mountd(3) 710/udp
|_ mountd(3) 711/tcp

I changed the script to merge multiple versions of the same program on
the same port and sort the output by protocol, port. This is the
output of the same host with the new formating.

Starting Nmap 4.52 ( http://insecure.org ) at 2008-01-06 17:44 CET
Interesting ports on localhost (127.0.0.1):
PORT    STATE SERVICE
111/tcp open  rpcbind
|  rpcinfo:
|  100000 2       111/udp rpcbind
|  100005 1-3     710/udp mountd
|  100003 2-4    2049/udp nfs
|  100024 1     32769/udp status
|  100021 1,3,4 32769/udp nlockmgr
|  100000 2       111/tcp rpcbind
|  100005 1-3     711/tcp mountd
|  100003 2-4    2049/tcp nfs
|  100024 1     59834/tcp status
|_ 100021 1,3,4 59834/tcp nlockmgr

Cheers
sven

-- 
Sven Klemm
http://cthulhu.c3d2.de/~sven/

Index: rpcinfo.nse
===================================================================
--- rpcinfo.nse (revision 6670)
+++ rpcinfo.nse (working copy)
@@ -16,7 +16,7 @@
        local path = nmap.fetchfile("nmap-rpc")
 
        if path == nil then
-               return false
+               return false, "Can't read from RPC file!"
        end
 
        local file = io.open(path, "r")
@@ -52,16 +52,13 @@
   local try, catch
   local transaction_id = "nmap"
   local socket = nmap.new_socket()
-  local result = ""
+  local result = " \n"
 
-  if not fillrpc() then
-    stdnse.print_debug("rpcinfo: Can't read from RPC file!")
-    return
-  end
-
   catch = function() socket:close() end
   try = nmap.new_try( catch )
 
+  try( fillrpc() )
+
   local ntohl = function( s )
     return bit.lshift(s:byte(1),24) + bit.lshift(s:byte(2),16) +
            bit.lshift(s:byte(3),8) + s:byte(4)
@@ -83,6 +80,7 @@
     status, answer_part = socket:receive_bytes( 1 )
     if status then answer = answer .. answer_part end
   end
+  socket:close()
 
   local fragment_length = answer:byte(4) + answer:byte(3) * 256 + answer:byte(2) * 65536
   if answer:sub(5,8) == transaction_id and answer:byte(12) == 1 and answer:byte(16) == 0 and answer:byte(28) == 0 then
@@ -97,9 +95,9 @@
       answer_part = answer_part:sub( fragment_length + 4 + 1 )
     end
 
+    local dir = { udp = {}, tcp = {}}
+    local rpc_prog, rpc_vers, rpc_proto, rpc_port
     while answer:byte(4) == 1 and answer:len() >= 20 do
-      local rpc_prog, rpc_vers, rpc_proto, rpc_port
-      if result:len() > 0 then result = result .. '\n' end
       rpc_prog = ntohl( answer:sub(5,8))
       rpc_vers = ntohl( answer:sub(9,12))
       rpc_proto = ntohl( answer:sub(13,16))
@@ -110,9 +108,36 @@
       elseif rpc_proto == 17 then
         rpc_proto = "udp"
       end
-      result = result .. string.format("%s(%d) %d/%s",rpc_numbers[rpc_prog] or rpc_prog,rpc_vers,rpc_port,rpc_proto)
+      if not dir[rpc_proto][rpc_port] then dir[rpc_proto][rpc_port] = {} end
+      if not dir[rpc_proto][rpc_port][rpc_prog] then dir[rpc_proto][rpc_port][rpc_prog] = {} end
+      table.insert( dir[rpc_proto][rpc_port][rpc_prog], rpc_vers )
     end
 
+    local format_version = function( version_table )
+      if #version_table == 1 then return version_table[1] end
+      table.sort( version_table )
+      for i=2,#version_table do
+        if version_table[i-1] ~= version_table[i] - 1 then
+          return table.concat( version_table, ',' )
+        end
+      end
+      return string.format('%d-%d',version_table[1],version_table[#version_table])
+    end
+
+    for rpc_proto, o in pairs(dir) do
+      local ports = {}
+      for rpc_port, i in pairs(o) do table.insert(ports, rpc_port) end
+      table.sort(ports)
+      for i, rpc_port in ipairs(ports) do
+        i = o[rpc_port]
+        for rpc_prog, versions in pairs(o[rpc_port]) do
+          versions = format_version( versions )
+          local name = rpc_numbers[rpc_prog] or ''
+          result = result .. string.format('%d %-5s %5d/%s %s\n',rpc_prog,versions,rpc_port,rpc_proto,name)
+        end
+      end
+    end
+
   end
 
   return result

Attachment: signature.asc
Description: OpenPGP digital signature


_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org

Current thread: