1local datetime = require "datetime"
2local msrpc = require "msrpc"
3local smb = require "smb"
4local stdnse = require "stdnse"
5local string = require "string"
6local table = require "table"
7
8description = [[
9Pulls back information about the remote system from the registry. Getting all
10of the information requires an administrative account, although a user account
11will still get a lot of it. Guest probably won't get any, nor will anonymous.
12This goes for all operating systems, including Windows 2000.
13
14Windows Vista disables remote registry access by default, so unless it was enabled,
15this script won't work.
16
17If you know of more information stored in the Windows registry that could be interesting,
18post a message to the nmap-dev mailing list and I (Ron Bowes) will add it to my todo list.
19Adding new checks to this is extremely easy.
20
21WARNING: I have experienced crashes in <code>regsvc.exe</code> while making registry calls
22against a fully patched Windows 2000 system; I've fixed the issue that caused it,
23but there's no guarantee that it (or a similar vuln in the same code) won't show
24up again. Since the process automatically restarts, it doesn't negatively impact
25the system, besides showing a message box to the user.
26]]
27
28---
29-- @usage
30-- nmap --script smb-system-info.nse -p445 <host>
31-- sudo nmap -sU -sS --script smb-system-info.nse -p U:137,T:139 <host>
32--
33-- @output
34-- Host script results:
35-- |  smb-system-info:
36-- |  |  OS Details
37-- |  |  |  Microsoft Windows 2000 Service Pack 4 (ServerNT 5.0 build 2195)
38-- |  |  |  Installed on 2008-10-10 05:47:19
39-- |  |  |  Registered to Ron (organization: Government of Manitoba)
40-- |  |  |  Path: %SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;C:\Program Files\Graphviz2.20\Bin;
41-- |  |  |  Systemroot: C:\WINNT
42-- |  |  |_ Page files: C:\pagefile.sys 192 384 (cleared at shutdown => 0)
43-- |  |  Hardware
44-- |  |  |  CPU 0: Intel(R) Xeon(TM) CPU 2.80GHz [2800mhz GenuineIntel]
45-- |  |  |  |_ Identifier 0: x86 Family 15 Model 3 Stepping 8
46-- |  |  |_ Video driver: VMware SVGA II
47-- |  |  Browsers
48-- |  |  |  Internet Explorer 6.0000
49-- |_ |_ |_ Firefox 3.0.12 (en-US)
50-----------------------------------------------------------------------
51
52
53
54author = "Ron Bowes"
55copyright = "Ron Bowes"
56license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
57categories = {"discovery","intrusive"}
58dependencies = {"smb-brute"}
59
60
61-- TODO: This script needs some love
62
63hostrule = function(host)
64  return smb.get_port(host) ~= nil
65end
66
67---Retrieves the requested value from the registry.
68--@param smbstate The SMB table we're using, bound to the WINREG service.
69--@param handle   The handle to the hive (HKLM or HKU, for example).
70--@param key      The full path of the key to retrieve (like <code>"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"</code>).
71--@param value    The value to retrieve (like <code>"NUMBER_OF_PROCESSORS"</code>).
72--@return Status (true or false).
73--@return The value (if status is true) or an error string (if status is false).
74local function reg_get_value(smbstate, handle, key, value)
75  -- Open the key
76  local status, openkey_result = msrpc.winreg_openkey(smbstate, handle, key)
77  if(status == false) then
78    return false, openkey_result
79  end
80
81  -- Query the value
82  local status, queryvalue_result = msrpc.winreg_queryvalue(smbstate, openkey_result['handle'], value)
83  if(status == false) then
84    return false, queryvalue_result
85  end
86
87  -- Close the key
88  local status, closekey_result = msrpc.winreg_closekey(smbstate, openkey_result['handle'], value)
89  if(status == false) then
90    return false, closekey_result
91  end
92
93  return true, queryvalue_result['value']
94end
95
96local function get_info_registry(host)
97
98  local result = {}
99
100  -- Create the SMB session
101  local status, smbstate = msrpc.start_smb(host, msrpc.WINREG_PATH)
102  if(status == false) then
103    return false, smbstate
104  end
105
106  -- Bind to WINREG service
107  local status, bind_result = msrpc.bind(smbstate, msrpc.WINREG_UUID, msrpc.WINREG_VERSION, nil)
108  if(status == false) then
109    msrpc.stop_smb(smbstate)
110    return false, bind_result
111  end
112
113  -- Open HKEY_LOCAL_MACHINE
114  local status, openhklm_result = msrpc.winreg_openhklm(smbstate)
115  if(status == false) then
116    msrpc.stop_smb(smbstate)
117    return false, openhklm_result
118  end
119
120  -- Processor information
121  result['status-number_of_processors'], result['number_of_processors']   = reg_get_value(smbstate, openhklm_result['handle'], "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", "NUMBER_OF_PROCESSORS")
122  if(result['status-number_of_processors'] == false) then
123    result['number_of_processors'] = 0
124  end
125  result['status-os'], result['os']                                         = reg_get_value(smbstate, openhklm_result['handle'], "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", "OS")
126  result['status-path'], result['path']                                     = reg_get_value(smbstate, openhklm_result['handle'], "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", "Path")
127  result['status-processor_architecture'], result['processor_architecture'] = reg_get_value(smbstate, openhklm_result['handle'], "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", "PROCESSOR_ARCHITECTURE")
128  result['status-processor_identifier'], result['processor_identifier']     = reg_get_value(smbstate, openhklm_result['handle'], "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", "PROCESSOR_IDENTIFIER")
129  result['status-processor_level'], result['processor_level']               = reg_get_value(smbstate, openhklm_result['handle'], "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", "PROCESSOR_LEVEL")
130  result['status-processor_revision'], result['processor_revision']         = reg_get_value(smbstate, openhklm_result['handle'], "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", "PROCESSOR_REVISION")
131
132  -- remove trailing zero terminator
133  local num_procs = result['number_of_processors']:match("^[^%z]*")
134
135  for i = 0, tonumber(num_procs) - 1, 1 do
136    result['status-~mhz'..i], result['~mhz' .. i]                               = reg_get_value(smbstate, openhklm_result['handle'], "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\" .. i, "~MHz")
137    result['status-identifier'..i], result['identifier' .. i]                   = reg_get_value(smbstate, openhklm_result['handle'], "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\" .. i, "Identifier")
138    result['status-processornamestring'..i], result['processornamestring' .. i] = reg_get_value(smbstate, openhklm_result['handle'], "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\" .. i, "ProcessorNameString")
139    result['status-vendoridentifier'..i], result['vendoridentifier' .. i]       = reg_get_value(smbstate, openhklm_result['handle'], "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\" .. i, "VendorIdentifier")
140  end
141  -- status, result['physicalmemory']   = reg_get_value(smbstate, openhklm_result['handle'], "HARDWARE\\ResourceMap\\System Resources\\Physical Memory", ".Translated")
142
143  -- TODO: Known DLLs?
144
145  -- Paging file
146  result['status-pagingfiles'], result['pagingfiles']                         = reg_get_value(smbstate, openhklm_result['handle'], "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management", "PagingFiles")
147  result['status-clearpagefileatshutdown'], result['clearpagefileatshutdown'] = reg_get_value(smbstate, openhklm_result['handle'], "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management", "ClearPageFileAtShutdown")
148
149  -- OS Information
150  result['status-csdversion'], result['csdversion']              = reg_get_value(smbstate, openhklm_result['handle'], "Software\\Microsoft\\Windows NT\\CurrentVersion", "CSDVersion")
151  if(result['status-csdversion'] == false) then
152    result['csdversion'] = "(no service packs)"
153  end
154  result['status-currentbuildnumber'], result['currentbuildnumber']  = reg_get_value(smbstate, openhklm_result['handle'], "Software\\Microsoft\\Windows NT\\CurrentVersion", "CurrentBuildNumber")
155  result['status-currenttype'], result['currenttype']                = reg_get_value(smbstate, openhklm_result['handle'], "Software\\Microsoft\\Windows NT\\CurrentVersion", "CurrentType")
156  result['status-currentversion'], result['currentversion']          = reg_get_value(smbstate, openhklm_result['handle'], "Software\\Microsoft\\Windows NT\\CurrentVersion", "CurrentVersion")
157  result['status-installdate'], result['installdate']                = reg_get_value(smbstate, openhklm_result['handle'], "Software\\Microsoft\\Windows NT\\CurrentVersion", "InstallDate")
158  if(result['status-installdate'] ~= false) then
159    result['installdate'] = datetime.format_timestamp(result['installdate'])
160  end
161
162  result['status-productname'], result['productname']                        = reg_get_value(smbstate, openhklm_result['handle'], "Software\\Microsoft\\Windows NT\\CurrentVersion", "Productname")
163  result['status-registeredowner'], result['registeredowner']                = reg_get_value(smbstate, openhklm_result['handle'], "Software\\Microsoft\\Windows NT\\CurrentVersion", "RegisteredOwner")
164  result['status-registeredorganization'], result['registeredorganization']  = reg_get_value(smbstate, openhklm_result['handle'], "Software\\Microsoft\\Windows NT\\CurrentVersion", "RegisteredOrganization")
165  result['status-systemroot'], result['systemroot']                          = reg_get_value(smbstate, openhklm_result['handle'], "Software\\Microsoft\\Windows NT\\CurrentVersion", "SystemRoot")
166  result['status-producttype'], result['producttype']                        = reg_get_value(smbstate, openhklm_result['handle'], "System\\CurrentControlSet\\Control\\ProductOptions", "ProductType")
167  result['status-productsuite'], result['productsuite']                      = reg_get_value(smbstate, openhklm_result['handle'], "System\\CurrentControlSet\\Control\\ProductOptions", "ProductSuite")
168
169  -- Driver information
170  result['status-video_driverdesc'], result['video_driverdesc']        = reg_get_value(smbstate, openhklm_result['handle'], "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000", "DriverDesc")
171
172  -- Software versions
173  result['status-ie_version'], result['ie_version']              = reg_get_value(smbstate, openhklm_result['handle'], "Software\\Microsoft\\Internet Explorer\\Version Vector", "IE")
174  result['status-ff_version'], result['ff_version']              = reg_get_value(smbstate, openhklm_result['handle'], "Software\\Mozilla\\Mozilla Firefox", "CurrentVersion")
175  if(result['status-ff_version'] == false) then
176    result['ff_version'] = "<not installed>"
177  end
178
179  msrpc.stop_smb(smbstate)
180
181  return true, result
182end
183
184action = function(host)
185
186  local status, result = get_info_registry(host)
187
188  if(status == false) then
189    return stdnse.format_output(false, result)
190  end
191
192  local response = {}
193
194  if(result['status-os'] == true) then
195    local osdetails = {}
196    osdetails['name'] = "OS Details"
197    table.insert(osdetails, string.format("%s %s (%s %s build %s)",                     result['productname'], result['csdversion'], result['producttype'], result['currentversion'], result['currentbuildnumber']))
198    table.insert(osdetails, string.format("Installed on %s",                            result['installdate']))
199    table.insert(osdetails, string.format("Registered to %s (organization: %s)",        result['registeredowner'], result['registeredorganization']))
200    table.insert(osdetails, string.format("Path: %s",                                   result['path']))
201    table.insert(osdetails, string.format("Systemroot: %s",                             result['systemroot']))
202    table.insert(osdetails, string.format("Page files: %s (cleared at shutdown => %s)", result['pagingfiles'], result['clearpagefileatshutdown']))
203    table.insert(response, osdetails)
204
205    local hardware = {}
206    hardware['name'] = "Hardware"
207    -- remove trailing zero terminator
208    local num_procs = result['number_of_processors']:match("^[^%z]*")
209    for i = 0, tonumber(num_procs) - 1, 1 do
210      if(result['status-processornamestring'..i] == false) then
211        result['status-processornamestring'..i] = "Unknown"
212      end
213
214      local processor = {}
215      processor['name'] = string.format("CPU %d: %s [%dmhz %s]", i, string.gsub(result['processornamestring'..i], '  ', ''), result['~mhz'..i], result['vendoridentifier'..i])
216      table.insert(processor, string.format("Identifier %d: %s",  i, result['identifier'..i]))
217      table.insert(hardware, processor)
218    end
219    table.insert(hardware, string.format("Video driver: %s", result['video_driverdesc']))
220    table.insert(response, hardware)
221
222    local browsers = {}
223    browsers['name'] = "Browsers"
224    table.insert(browsers, string.format("Internet Explorer %s", result['ie_version']))
225    if(result['status-ff_version']) then
226      table.insert(browsers, string.format("Firefox %s", result['ff_version']))
227    end
228    table.insert(response, browsers)
229
230    return stdnse.format_output(true, response)
231  elseif(result['status-productname'] == true) then
232
233    local osdetails = {}
234    osdetails['name'] = 'OS Details'
235    osdetails['warning'] = "Access was denied for certain values; try an administrative account for more complete information"
236
237    table.insert(osdetails, string.format("%s %s (%s %s build %s)",              result['productname'], result['csdversion'], result['producttype'], result['currentversion'], result['currentbuildnumber']))
238    table.insert(osdetails, string.format("Installed on %s",                     result['installdate']))
239    table.insert(osdetails, string.format("Registered to %s (organization: %s)", result['registeredowner'], result['registeredorganization']))
240    table.insert(osdetails, string.format("Systemroot: %s",                      result['systemroot']))
241    table.insert(response, osdetails)
242
243    return stdnse.format_output(true, response)
244  end
245
246  return stdnse.format_output(false, "Account being used was unable to probe for information, try using an administrative account")
247end
248
249
250