mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 12:41:29 +00:00
socket:connect(host.ip, port.number) socket:connect(host.ip, port.number, port.protocol) to this: socket:connect(host, port) connect can take host and port tables now, and the default protocol is taken from the port table if possible.
158 lines
4.0 KiB
Lua
158 lines
4.0 KiB
Lua
description = [[
|
|
Extracts a list of published applications from the ICA Browser service.
|
|
]]
|
|
|
|
---
|
|
-- @usage sudo ./nmap -sU --script=citrix-enum-apps -p 1604 <host>
|
|
--
|
|
-- @output
|
|
-- PORT STATE SERVICE
|
|
-- 1604/udp open unknown
|
|
-- 1604/udp open unknown
|
|
-- | citrix-enum-apps:
|
|
-- | Notepad
|
|
-- | iexplorer
|
|
-- |_ registry editor
|
|
--
|
|
|
|
-- Version 0.2
|
|
|
|
-- Created 11/24/2009 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
|
|
-- Revised 11/25/2009 - v0.2 - fixed multiple packet response bug
|
|
|
|
author = "Patrik Karlsson"
|
|
|
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
|
|
|
categories = {"discovery","safe"}
|
|
|
|
require "comm"
|
|
require "shortport"
|
|
require "stdnse"
|
|
require "bin"
|
|
|
|
portrule = shortport.portnumber(1604, "udp")
|
|
|
|
|
|
-- process the response from the server
|
|
-- @param response string, complete server response
|
|
-- @return string row delimited with \n containing all published applications
|
|
function process_pa_response(response)
|
|
|
|
local pos, packet_len = bin.unpack("SS", response)
|
|
local app_name
|
|
local pa_list = {}
|
|
|
|
if packet_len < 40 then
|
|
return
|
|
end
|
|
|
|
-- the list of published applications starts at offset 40
|
|
offset = 41
|
|
|
|
while offset < packet_len do
|
|
pos, app_name = bin.unpack("z", response:sub(offset))
|
|
offset = offset + pos - 1
|
|
|
|
table.insert(pa_list, app_name)
|
|
end
|
|
|
|
return pa_list
|
|
|
|
end
|
|
|
|
|
|
action = function(host, port)
|
|
|
|
local packet, counter
|
|
local query = {}
|
|
local pa_list = {}
|
|
|
|
--
|
|
-- Packets were intercepted from the Citrix Program Neighborhood client
|
|
-- They are used to query a server for it's list of servers
|
|
--
|
|
-- We're really not interested in the responses to the first two packets
|
|
-- The third response contains the list of published applications
|
|
-- I couldn't find any documentation on this protocol so I'm providing
|
|
-- some brief information for the bits and bytes this script uses.
|
|
--
|
|
-- Spec. of response to query[2] that contains a list of published apps
|
|
--
|
|
-- offset size content
|
|
-- -------------------------
|
|
-- 0 16-bit Length
|
|
-- 12 32-bit Server IP (not used here)
|
|
-- 30 8-bit Last packet (1), More packets(0)
|
|
-- 40 - null-separated list of applications
|
|
--
|
|
query[0] = string.char(
|
|
0x1e, 0x00, -- Length: 30
|
|
0x01, 0x30, 0x02, 0xfd, 0xa8, 0xe3, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00
|
|
)
|
|
|
|
query[1] = string.char(
|
|
0x20, 0x00, -- Length: 32
|
|
0x01, 0x36, 0x02, 0xfd, 0xa8, 0xe3, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
)
|
|
|
|
query[2] = string.char(
|
|
0x2a, 0x00, -- Length: 42
|
|
0x01, 0x32, 0x02, 0xfd, 0xa8, 0xe3, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x21, 0x00, 0x02, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
)
|
|
|
|
counter = 0
|
|
|
|
local socket = nmap.new_socket()
|
|
socket:set_timeout(5000)
|
|
|
|
try = nmap.new_try(function() socket:close() end)
|
|
|
|
try( socket:connect(host, port) )
|
|
|
|
-- send the two first packets and never look back
|
|
repeat
|
|
try( socket:send(query[counter]) )
|
|
packet = try(socket:receive())
|
|
counter = counter + 1
|
|
until (counter>#query)
|
|
|
|
-- process the first response
|
|
pa_list = process_pa_response( packet )
|
|
|
|
--
|
|
-- the byte at offset 31 in the response has a really magic function
|
|
-- if it is set to zero (0) we have more response packets to process
|
|
-- if it is set to one (1) we have arrived at the last packet of our journey
|
|
--
|
|
while packet:sub(31,31) ~= string.char(0x01) do
|
|
packet = try( socket:receive() )
|
|
local tmp_table = process_pa_response( packet )
|
|
|
|
for _,v in pairs(tmp_table) do
|
|
table.insert(pa_list, v)
|
|
end
|
|
|
|
end
|
|
|
|
-- set port to open
|
|
if #pa_list>0 then
|
|
nmap.set_port_state(host, port, "open")
|
|
end
|
|
|
|
socket:close()
|
|
|
|
return stdnse.format_output(true, pa_list)
|
|
|
|
end
|