diff --git a/CHANGELOG b/CHANGELOG index a516fb7fa..d01479e7a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ # Nmap Changelog ($Id$); -*-text-*- +o [NSE] Added msrpc-enum script which queries MSRPC endpoint mapper for + available services and their information. [Aleksandar Nikolic] + o Made source port numbers (used to encode probe metadata) increment so as not to overlap between different scanning phases. Previously it was possible for an RST response to an ACK probe from host diff --git a/nselib/msrpc.lua b/nselib/msrpc.lua index 18ef9b72e..2a0bcb035 100644 --- a/nselib/msrpc.lua +++ b/nselib/msrpc.lua @@ -97,6 +97,13 @@ ATSVC_PATH = "\\atsvc" ATSVC_UUID = string.char(0x82, 0x06, 0xf7, 0x1f, 0x51, 0x0a, 0xe8, 0x30, 0x07, 0x6d, 0x74, 0x0b, 0xe8, 0xce, 0xe9, 0x8b) ATSVC_VERSION = 1 + +-- UUID and version for epmapper e1af8308-5d1f-11c9-91a4-08002b14a0fa v3.0 +EPMAPPER_PATH = "\\epmapper" +EPMAPPER_UUID = string.char(0x08, 0x83, 0xaf, 0xe1, 0x1f, 0x5d, 0xc9, 0x11, 0x91, 0xa4, 0x08, 0x00, 0x2b, 0x14, 0xa0, 0xfa) +EPMAPPER_VERSION = 3 + + -- This is the only transfer syntax I've seen in the wild, not that I've looked hard. It seems to work well. TRANSFER_SYNTAX = string.char(0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60) @@ -123,6 +130,55 @@ local LSA_GROUPSIZE = 20 -- up. Raising this could find more users, but at the expense of more packets. local LSA_MINEMPTY = 10 +---Mapping between well known MSRPC UUIDs and coresponding exe/service +local UUID2EXE = { + ["1ff70682-0a51-30e8-076d-740be8cee98b"] = "mstask.exe atsvc interface (Scheduler service)", + ["3faf4738-3a21-4307-b46c-fdda9bb8c0d5"] = "AudioSrv AudioSrv interface (Windows Audio service)", + ["6bffd098-a112-3610-9833-012892020162"] = "Browser browser interface (Computer Browser service)", + ["91ae6020-9e3c-11cf-8d7c-00aa00c091be"] = "certsrv.exe ICertPassage interface (Certificate services)", + ["5ca4a760-ebb1-11cf-8611-00a0245420ed"] = "termsrv.exe winstation_rpc interface", + ["c8cb7687-e6d3-11d2-a958-00c04f682e16"] = "WebClient davclntrpc interface (WebDAV client service)", + ["50abc2a4-574d-40b3-9d66-ee4fd5fba076"] = "dns.exe DnsServer interface (DNS Server service)", + ["e1af8308-5d1f-11c9-91a4-08002b14a0fa"] = "RpcSs epmp interface (RPC endpoint mapper)", + ["82273fdc-e32a-18c3-3f78-827929dc23ea"] = "Eventlog eventlog interface (Eventlog service)", + ["3d267954-eeb7-11d1-b94e-00c04fa3080d"] = "lserver.exe Terminal Server Licensing", + ["894de0c0-0d55-11d3-a322-00c04fa321a1"] = "winlogon.exe InitShutdown interface", + ["8d0ffe72-d252-11d0-bf8f-00c04fd9126b"] = "CryptSvc IKeySvc interface (Cryptographic services)", + ["0d72a7d4-6148-11d1-b4aa-00c04fb66ea0"] = "CryptSvc ICertProtect interface (Cryptographic services)", + ["d6d70ef0-0e3b-11cb-acc3-08002b1d29c4"] = "locator.exe NsiS interface (RPC Locator service)", + ["342cfd40-3c6c-11ce-a893-08002b2e9c6d"] = "llssrv.exe llsrpc interface (Licensing Logging service)", + ["12345778-1234-abcd-ef00-0123456789ab"] = "lsass.exe lsarpc interface", + ["3919286a-b10c-11d0-9ba8-00c04fd92ef5"] = "lsass.exe dssetup interface", + ["5a7b91f8-ff00-11d0-a9b2-00c04fb6e6fc"] = "messenger msgsvcsend interface (Messenger service)", + ["2f5f3220-c126-1076-b549-074d078619da"] = "netdde.exe nddeapi interface (NetDDE service)", + ["4fc742e0-4a10-11cf-8273-00aa004ae673"] = "Dfssvc netdfs interface (Distributed File System service)", + ["12345678-1234-abcd-ef00-01234567cffb"] = "Netlogon netlogon interface (Net Logon service)", + ["8d9f4e40-a03d-11ce-8f69-08003e30051b"] = "PlugPlay pnp interface (Plug and Play service)", +-- ["8d9f4e40-a03d-11ce-8f69-08003e30051b"] = "PlugPlay pnp interface (Plug and Play Windows Vista service)", + ["d335b8f6-cb31-11d0-b0f9-006097ba4e54"] = "PolicyAgent PolicyAgent interface (IPSEC Policy Agent (Windows 2000))", +-- ["12345678-1234-abcd-ef00-0123456789ab"] = "PolicyAgent winipsec interface (IPsec Services)", + ["369ce4f0-0fdc-11d3-bde8-00c04f8eee78"] = "winlogon.exe pmapapi interface", + ["c9378ff1-16f7-11d0-a0b2-00aa0061426a"] = "lsass.exe IPStoreProv interface (Protected Storage)", + ["8f09f000-b7ed-11ce-bbd2-00001a181cad"] = "mprdim.dll Remote Access", + ["12345778-1234-abcd-ef00-0123456789ac"] = "lsass.exe samr interface", + ["93149ca2-973b-11d1-8c39-00c04fb984f9"] = "services.exe SceSvc", + ["12b81e99-f207-4a4c-85d3-77b42f76fd14"] = "seclogon ISeclogon interface (Secondary logon service)", + ["83da7c00-e84f-11d2-9807-00c04f8ec850"] = "winlogon.exe sfcapi interface (Windows File Protection)", +-- ["12345678-1234-abcd-ef00-0123456789ab"] = "spoolsv.exe spoolss interface (Spooler service)", + ["4b324fc8-1670-01d3-1278-5a47bf6ee188"] = "services.exe (w2k) or svchost.exe (wxp and w2k3) srvsvc interface (Server service)", + ["4b112204-0e19-11d3-b42b-0000f81feb9f"] = "ssdpsrv ssdpsrv interface (SSDP service)", + ["367aeb81-9844-35f1-ad32-98f038001003"] = "services.exe svcctl interface (Services control manager)", + ["2f5f6520-ca46-1067-b319-00dd010662da"] = "Tapisrv tapsrv interface (Telephony service)", + ["300f3532-38cc-11d0-a3f0-0020af6b0add"] = "Trkwks trkwks interface (Distributed Link Tracking Client)", + ["8fb6d884-2388-11d0-8c35-00c04fda2795"] = "w32time w32time interface (Windows Time)", +-- ["8fb6d884-2388-11d0-8c35-00c04fda2795"] = "w32time w32time interface (Windows Time (Windows Server 2003, Windows Vista))", + ["a002b3a0-c9b7-11d1-ae88-0080c75e4ec1"] = "winlogon.exe GetUserToken interface", + ["338cd001-2244-31f1-aaaa-900038001003"] = "RemoteRegistry winreg interface (Remote registry service)", + ["45f52c28-7f9f-101a-b52b-08002b2efabe"] = "wins.exe winsif interface (WINS service)", + ["6bffd098-a112-3610-9833-46c3f87e345a"] = "services.exe (w2k) or svchost.exe (wxp and w2k3) wkssvc interface (Workstation service)" +} + + --- This is a wrapper around the SMB class, designed to get SMB going quickly for MSRPC calls. This will -- connect to the SMB server, negotiate the protocol, open a session, connect to the IPC$ share, and -- open the named pipe given by 'path'. When this successfully returns, the 'smbstate' table can be immediately @@ -1080,6 +1136,150 @@ function spoolss_abort_printer(smbstate,printer_handle) end +---Helper function to convert binary UUID representation to usual string. +-- +--@param uuid UUID byte string +--@return UUID converted to string representation +function uuid_to_string(uuid) + local pos, i1,s1,s2,c1,c2,c3,c4,c5,c6,c7,c8 = bin.unpack(" 1 then + lookup_response.annotation = string.sub(data,pos,pos+annotation_length-2) + end + local padding = (4-(annotation_length%4)) + if padding == 4 then padding = 0 end + pos = pos + annotation_length + padding + --skip lengths + pos = pos + 8 + local num_floors,floor_len,uuid, address_type,address_len,tcp_port,udp_port,ip_addr,saved_pos,ncalrpc,ncacn_np,netbios,ncacn_http + pos, num_floors = bin.unpack("S",data,pos) + elseif address_type == 0x08 then + pos,lookup_response.udp_port = bin.unpack(">S",data,pos) + elseif address_type == 0x09 then + local i1,i2,i3,i4 + pos,i1,i2,i3,i4 = bin.unpack("CCCC",data,pos) + lookup_response.ip_addr = string.format("%d.%d.%d.%d",i1,i2,i3,i4) + elseif address_type == 0x0f then + lookup_response.ncacn_np = string.sub(data,pos,pos+address_len-2) + floor_len = floor_len + address_len - 2 + elseif address_type == 0x10 then + lookup_response.ncalrpc = string.sub(data,pos,pos+address_len-2) + floor_len = floor_len + address_len - 2 + elseif address_type == 0x11 then + lookup_response.netbios = string.sub(data,pos,pos+address_len-2) + floor_len = floor_len + address_len - 2 + elseif address_type == 0x1f then + pos, lookup_response.ncacn_http = bin.unpack(">S",data,pos) + else + stdnse.print_debug("unknown address type %x",address_type) + end + end + end + pos = saved_pos + floor_len + 6 + end + return status,lookup_response +end + ---A proxy to a msrpctypes function that converts a PasswordProperties to an english string. -- I implemented this as a proxy so scripts don't have to make direct calls to msrpctypes -- functions. diff --git a/scripts/msrpc-enum.nse b/scripts/msrpc-enum.nse new file mode 100644 index 000000000..1263ec37f --- /dev/null +++ b/scripts/msrpc-enum.nse @@ -0,0 +1,113 @@ +local msrpc = require "msrpc" +local smb = require "smb" +local string = require "string" +local stdnse = require "stdnse" +local table = require "table" + +description = [[ +Script queries MSRPC endpoint mapper for a list of mapped +services and displays the gathered information. + +As it is using smb library, you can specify optional +username and password to use. + +Script works much like Microsoft's rpcdump tool +or dcedump tool from SPIKE fuzzer. +]] +--- +-- @usage nmap --script=msrpc-enum +-- +-- @output +-- PORT STATE SERVICE REASON +-- 445/tcp open microsoft-ds syn-ack + +-- Host script results: +-- | msrpc-enum: +-- | +-- | uuid: 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d5 +-- | annotation: DHCP Client LRPC Endpoint +-- | ncalrpc: dhcpcsvc +-- | +-- | uuid: 12345678-1234-abcd-ef00-0123456789ab +-- | annotation: IPSec Policy agent endpoint +-- | ncalrpc: audit +-- | +-- | uuid: 3c4728c5-f0ab-448b-bda1-6ce01eb0a6d5 +-- | ip_addr: 0.0.0.0 +-- | annotation: DHCP Client LRPC Endpoint +-- | tcp_port: 49153 +-- | + -- +-- | +-- | uuid: 12345678-1234-abcd-ef00-0123456789ab +-- | annotation: IPSec Policy agent endpoint +-- | ncalrpc: securityevent +-- | +-- | uuid: 12345678-1234-abcd-ef00-0123456789ab +-- | annotation: IPSec Policy agent endpoint +-- |_ ncalrpc: protected_storage +-- +-- @xmloutput +-- -snip- +-- +-- c100beab-d33a-4a4b-bf23-bbef4663d017 +-- wcncsvc.wcnprpc +-- wcncsvc.wcnprpc +--
+-- +-- 6b5bdd1e-528c-422c-af8c-a4079be4fe48 +-- Remote Fw APIs +-- 49158 +-- 0.0.0.0 +--
+-- +-- 12345678-1234-abcd-ef00-0123456789ab +-- IPSec Policy agent endpoint +-- 49158 +-- 0.0.0.0 +--
+-- -snip- + +author = "Aleksandar Nikolic" +license = "Same as Nmap--See http://nmap.org/book/man-legal.html" +categories = {"safe","discovery"} + +hostrule = function(host) + return smb.get_port(host) ~= nil +end + +action = function(host,port) + local status, smbstate + status, smbstate = msrpc.start_smb(host,msrpc.EPMAPPER_PATH,true) + if(status == false) then + stdnse.print_debug("SMB: " .. smbstate) + return false, smbstate + end + local bind_result,epresult -- bind to endpoint mapper service + status, bind_result = msrpc.bind(smbstate,msrpc.EPMAPPER_UUID, msrpc.EPMAPPER_VERSION, nil) + if(status == false) then + msrpc.stop_smb(smbstate) + stdnse.print_debug("SMB: " .. bind_result) + return false, bind_result + end + local results = {} + status, epresult = msrpc.epmapper_lookup(smbstate,nil) -- get the initial handle + if not status then + stdnse.print_debug("SMB: " .. epresult) + return false, epresult + + end + local handle = epresult.new_handle + epresult.new_handle = nil + table.insert(results,epresult) + + while not (epresult == nil) do + status, epresult = msrpc.epmapper_lookup(smbstate,handle) -- get next result until there are no more + if not status then + break + end + epresult.new_handle = nil + table.insert(results,epresult) + end + return results +end diff --git a/scripts/script.db b/scripts/script.db index eb15cc6f2..2a54f9dfb 100644 --- a/scripts/script.db +++ b/scripts/script.db @@ -253,7 +253,6 @@ Entry { filename = "mongodb-brute.nse", categories = { "brute", "intrusive", } } Entry { filename = "mongodb-databases.nse", categories = { "default", "discovery", "safe", } } Entry { filename = "mongodb-info.nse", categories = { "default", "discovery", "safe", } } Entry { filename = "mrinfo.nse", categories = { "broadcast", "discovery", "safe", } } - Entry { filename = "ms-sql-brute.nse", categories = { "brute", "intrusive", } } Entry { filename = "ms-sql-config.nse", categories = { "discovery", "safe", } } Entry { filename = "ms-sql-dac.nse", categories = { "discovery", "safe", } } @@ -264,6 +263,7 @@ Entry { filename = "ms-sql-info.nse", categories = { "default", "discovery", "sa Entry { filename = "ms-sql-query.nse", categories = { "discovery", "safe", } } Entry { filename = "ms-sql-tables.nse", categories = { "discovery", "safe", } } Entry { filename = "ms-sql-xp-cmdshell.nse", categories = { "intrusive", } } +Entry { filename = "msrpc-enum.nse", categories = { "discovery", "safe", } } Entry { filename = "mtrace.nse", categories = { "broadcast", "discovery", "safe", } } Entry { filename = "mysql-audit.nse", categories = { "discovery", "safe", } } Entry { filename = "mysql-brute.nse", categories = { "brute", "intrusive", } }