Nmap Development mailing list archives

[NSE] rpcinfo script


From: Sven Klemm <sven () c3d2 de>
Date: Wed, 19 Dec 2007 23:32:04 +0100

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.

Here are 2 examples:

nmap -sC -p 111 localhost

Starting Nmap 4.50 ( http://insecure.org ) at 2007-12-19 22:55 CET
Interesting ports on localhost (127.0.0.1):
PORT    STATE SERVICE
111/tcp open  rpcbind
|  rpcinfo: portmapper(2) 111/tcp
|_ portmapper(2) 111/udp

Nmap done: 1 IP address (1 host up) scanned in 1.152 seconds

./nmap -sC -p 111 localhost

Starting Nmap 4.50 ( http://insecure.org ) at 2007-12-19 22:52 CET
Interesting ports on localhost (127.0.0.1):
PORT    STATE SERVICE
111/tcp open  rpcbind
|  rpcinfo: portmapper(2) 111/tcp
|  portmapper(2) 111/udp
|  status(1) 32769/udp
|  nlockmgr(1) 32769/udp
|  nlockmgr(3) 32769/udp
|  nlockmgr(4) 32769/udp
|  status(1) 53255/tcp
|  nlockmgr(1) 53255/tcp
|  nlockmgr(3) 53255/tcp
|  nlockmgr(4) 53255/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) 693/udp
|  mountd(1) 694/tcp
|  mountd(2) 693/udp
|  mountd(2) 694/tcp
|  mountd(3) 693/udp
|_ mountd(3) 694/tcp

Nmap done: 1 IP address (1 host up) scanned in 1.072 seconds


Cheers
Sven
id = "rpcinfo"

description = "connects to portmapper and prints a list of all registered programs"
author = "Sven Klemm <sven () c3d2 de>"
license = "See nmaps COPYING for licence"
categories = {"safe","discovery"}

require "shortport"
require "bit"

-- rpc program numbers from /etc/rpc
local rpc_numbers = {
  [100000] = 'portmapper',
  [100001] = 'rstatd',
  [100002] = 'rusersd',
  [100003] = 'nfs',
  [100004] = 'ypserv',
  [100005] = 'mountd',
  [100007] = 'ypbind',
  [100008] = 'walld',
  [100009] = 'yppasswdd',
  [100010] = 'etherstatd',
  [100011] = 'rquotad',
  [100012] = 'sprayd',
  [100013] = '3270_mapper',
  [100014] = 'rje_mapper',
  [100015] = 'selection_svc',
  [100016] = 'database_svc',
  [100017] = 'rexd',
  [100018] = 'alis',
  [100019] = 'sched',
  [100020] = 'llockmgr',
  [100021] = 'nlockmgr',
  [100022] = 'x25.inr',
  [100023] = 'statmon',
  [100024] = 'status',
  [100026] = 'bootparam',
  [100028] = 'ypupdated',
  [100029] = 'keyserv',
  [100037] = 'tfsd',
  [100038] = 'nsed',
  [100039] = 'nsemntd',
  [100069] = 'ypxfrd',
  [150001] = 'pcnfsd',
  [300019] = 'amd',
  [391002] = 'sgi_fam',
  [545580417] = 'ugidd',
  [600100069] = 'fypxfrd',
  [788585389] = 'bwnfsd'
}

portrule = shortport.port_or_service(111, "rpcbind")

action = function(host, port)
  local try, catch
  local transaction_id = "nmap"
  local socket = nmap.new_socket()
  local result = ""

  catch = function() socket:close() end
  try = nmap.new_try( catch )

  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)
  end

  local request = string.char(0x80,0,0,40) -- fragment header
  request = request .. transaction_id -- transaction id
  request = request .. "\0\0\0\0\0\0\0\2" -- message type: call (0) and rpc version 2
  request = request .. string.char(0,1,134,160) -- programm portmap (100000)
  request = request .. "\0\0\0\2\0\0\0\4" -- programm version (2) procedure dump(4)
  request = request .. "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"-- Credentials and verifier

  socket:set_timeout(1000)
  try( socket:connect(host.ip, port.number) )
  try( socket:send( request ) )
  local status, answer, answer_part
  status, answer = socket:receive_bytes( 1 )
  while status do
    status, answer_part = socket:receive_bytes( 1 )
    if status then answer = answer .. answer_part end
  end

  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
    -- transaction_id matches, message type reply, reply state accepted and accept state executed successfully
    answer_part = answer
    answer = answer_part:sub( 28 + 1, fragment_length + 4 )
    answer_part = answer_part:sub( fragment_length + 4 + 1 )

    while answer_part:len() > 0 do -- defragment packet
      fragment_length = answer_part:byte(4) + answer_part:byte(3) * 256 + answer_part:byte(2) * 65536
      answer = answer .. answer_part:sub( 5, fragment_length + 4 )
      answer_part = answer_part:sub( fragment_length + 4 + 1 )
    end

    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))
      rpc_port = ntohl( answer:sub(17,20))
      answer = answer:sub(21)
      if rpc_proto == 6 then
        rpc_proto = "tcp"
      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)
    end

  end

  return result
end

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: