1local nmap = require "nmap"
2local shortport = require "shortport"
3local stdnse = require "stdnse"
4local string = require "string"
5local stringaux = require "stringaux"
6local table = require "table"
7
8description = [[
9Opens a connection to a NetBus server and extracts information about
10the host and the NetBus service itself.
11
12The extracted host information includes a list of running
13applications, and the hosts sound volume settings.
14
15The extracted service information includes its access control list
16(acl), server information, and setup. The acl is a list of IP
17addresses permitted to access the service. Server information
18contains details about the server installation path, restart
19persistence, user account that the server is running on, and the
20amount of connected NetBus clients. The setup information contains
21configuration details, such as the services TCP port number, traffic
22logging setting, password, an email address for receiving login
23notifications, an email address used for sending the notifications,
24and an smtp-server used for notification delivery.
25]]
26
27---
28-- @usage
29-- nmap -p 12345 --script netbus-info <target> --script-args netbus-info.password=<password>
30--
31-- @output
32-- 12345/tcp open  netbus
33-- | netbus-info:
34-- |   ACL
35-- |     127.0.0.1
36-- |   APPLICATIONS
37-- |     PuTTY Configuration
38-- |   INFO
39-- |     Program Path: Z:\home\joeuser\Desktop\Patch.exe
40-- |     Restart persistent: Yes
41-- |     Login ID: joeuser
42-- |     Clients connected to this host: 1
43-- |   SETUP
44-- |     TCP-port: 12345
45-- |     Log traffic: 1
46-- |     Password: password123
47-- |     Notify to: admin@example.com
48-- |     Notify from: spoofed@example.org
49-- |     SMTP-server: smtp.example.net
50-- |   VOLUME
51-- |     Wave: 0
52-- |     Synth: 0
53-- |_    Cd: 0
54-- @xmloutput
55-- <table key="ACL">
56--   <elem>127.0.0.1</elem>
57-- </table>
58-- <table key="APPLICATIONS">
59--   <elem>PuTTY Configuration</elem>
60-- </table>
61-- <table key="INFO">
62--   <elem key="Program Path">Z:\home\joeuser\Desktop\Patch.exe</elem>
63--   <elem key="Restart persistent">Yes</elem>
64--   <elem key="Login ID">joeuser</elem>
65--   <elem key="Clients connected to this host">1</elem>
66-- </table>
67-- <table key="SETUP">
68--   <elem key="TCP-port">12345</elem>
69--   <elem key="Log traffic">1</elem>
70--   <elem key="Password">password123</elem>
71--   <elem key="Notify to">admin@example.com</elem>
72--   <elem key="Notify from">spoofed@example.org</elem>
73--   <elem key="SMTP-server">smtp.example.net</elem>
74-- </table>
75-- <table key="VOLUME">
76--   <elem key="Wave">0</elem>
77--   <elem key="Synth">0</elem>
78--   <elem key="Cd">0</elem>
79-- </table>
80--
81-- @args netbus-info.password The password used for authentication
82
83author = "Toni Ruottu"
84license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
85categories = {"default", "discovery", "safe"}
86
87
88dependencies = {"netbus-version", "netbus-brute"}
89
90portrule = shortport.port_or_service (12345, "netbus", {"tcp"})
91
92local function format_acl(acl)
93  if acl == nil then
94    return nil
95  end
96  local payload = string.sub(acl, 9) --skip header
97  local fields = stringaux.strsplit("|", payload)
98  table.remove(fields, (# fields))
99  return fields
100end
101
102local function format_apps(apps)
103  if apps == nil then
104    return nil
105  end
106  local payload = string.sub(apps, 10) --skip header
107  local fields = stringaux.strsplit("|", payload)
108  table.remove(fields, (# fields))
109  return fields
110end
111
112local function format_info(info)
113  if info == nil then
114    return nil
115  end
116  local payload = string.sub(info, 6) --skip header
117  local fields = stringaux.strsplit("|", payload)
118  return fields
119end
120
121local function format_setup(setup)
122  if setup == nil then
123    return nil
124  end
125  local fields = stringaux.strsplit(";", setup)
126  if # fields < 7 then
127    return nil
128  end
129  local formatted = stdnse.output_table()
130  formatted["TCP-port"] = fields[2]
131  formatted["Log traffic"] = fields[3]
132  formatted["Password"] = fields[4]
133  formatted["Notify to"] = fields[5]
134  formatted["Notify from"] = fields[6]
135  formatted["SMTP-server"] = fields[7]
136  return formatted
137end
138
139local function format_volume(volume)
140  if volume == nil then
141    return nil
142  end
143  local fields = stringaux.strsplit(";", volume)
144  if # fields < 4 then
145    return nil
146  end
147  local formatted = stdnse.output_table()
148  formatted["Wave"] = fields[2]
149  formatted["Synth"] = fields[3]
150  formatted["Cd"] = fields[4]
151  return formatted
152end
153
154action = function( host, port )
155  local password = nmap.registry.args[SCRIPT_NAME .. ".password"]
156  if not password and nmap.registry.netbuspasswords then
157    local key = string.format("%s:%d", host.ip, port.number)
158    password = nmap.registry.netbuspasswords[key]
159  end
160  if not password then
161    password = ""
162  end
163  local socket = nmap.new_socket()
164  socket:set_timeout(5000)
165  local status, err = socket:connect(host, port)
166  local buffer, err = stdnse.make_buffer(socket, "\r")
167  local _ = buffer()
168  if not (_ and _:match("^NetBus")) then
169    stdnse.debug1("Not NetBus")
170    return nil
171  end
172  socket:send(string.format("Password;1;%s\r", password))
173  local gotin = buffer()
174  if gotin == "Access;0" then
175    return
176  end
177
178  socket:send("GetInfo\r")
179  local info = buffer()
180  socket:send("GetSetup\r")
181  local setup = buffer()
182  socket:send("GetACL\r")
183  local acl = buffer()
184  socket:send("GetApps\r")
185  local apps = buffer()
186  socket:send("GetVolume\r")
187  local volume = buffer()
188  socket:close()
189
190  local response = stdnse.output_table()
191  response["ACL"] = format_acl(acl)
192  response["APPLICATIONS"] = format_apps(apps)
193  response["INFO"] = format_info(info)
194  response["SETUP"] = format_setup(setup)
195  response["VOLUME"] = format_volume(volume)
196
197  return response
198end
199
200
201