diff --git a/scripts/afp-ls.nse b/scripts/afp-ls.nse index ea5b1cccd..7e9e82422 100644 --- a/scripts/afp-ls.nse +++ b/scripts/afp-ls.nse @@ -2,8 +2,7 @@ local afp = require "afp" local nmap = require "nmap" local shortport = require "shortport" local stdnse = require "stdnse" -local tab = require "tab" -local table = require "table" +local ls = require "ls" description = [[ Attempts to get useful information about files from AFP volumes. @@ -12,45 +11,88 @@ The output is intended to resemble the output of ls. --- -- ---@output +-- @usage +-- nmap -sS -sV -p 548 --script=afp-ls target +-- +-- @output -- PORT STATE SERVICE -- 548/tcp open afp syn-ack -- | afp-ls: --- | Macintosh HD --- | PERMISSION UID GID SIZE TIME FILENAME --- | -rw-r--r-- 501 80 15364 2010-06-13 17:52 .DS_Store --- | ---------- 0 80 0 2009-10-05 07:42 .file --- | drwx------ 501 20 0 2009-11-04 17:28 .fseventsd --- | -rw------- 0 0 393216 2010-06-14 01:49 .hotfiles.btree --- | drwx------ 0 80 0 2009-11-04 18:19 .Spotlight-V100 --- | d-wx-wx-wx 0 80 0 2009-11-04 18:25 .Trashes --- | drwxr-xr-x 0 0 0 2009-05-18 21:29 .vol --- | drwxrwxr-x 0 80 0 2009-04-28 00:06 Applications --- | drwxr-xr-x 0 0 0 2009-05-18 21:43 bin --- | drwxr-xr-x 501 80 0 2010-08-10 22:55 bundles --- | Patrik Karlsson's Public Folder --- | PERMISSION UID GID SIZE TIME FILENAME --- | -rw------- 501 20 6148 2010-12-27 23:45 .DS_Store --- | -rw-r--r-- 501 20 0 2007-07-24 21:17 .localized --- | drwx-wx-wx 501 20 0 2009-06-19 04:01 Drop Box --- | patrik --- | PERMISSION UID GID SIZE TIME FILENAME --- | -rw------- 501 20 11281 2010-06-14 22:51 .bash_history --- | -rw-r--r-- 501 20 33 2011-01-19 20:11 .bashrc --- | -rw------- 501 20 3 2007-07-24 21:17 .CFUserTextEncoding --- | drwx------ 501 20 0 2010-09-12 14:52 .config --- | drwx------ 501 20 0 2010-09-12 12:29 .cups --- | -rw-r--r-- 501 20 15364 2010-06-13 18:34 .DS_Store --- | drwxr-xr-x 501 20 0 2010-09-12 14:13 .fontconfig --- | -rw------- 501 20 102 2010-06-14 01:46 .lesshst --- | -rw-r--r-- 501 20 241 2010-06-14 01:45 .profile --- | -rw------- 501 20 218 2010-09-12 16:35 .recently-used.xbel +-- | Information retrieved as patrik +-- | Volume Macintosh HD +-- | maxfiles limit reached (10) +-- | PERMISSION UID GID SIZE TIME FILENAME +-- | -rw-r--r-- 501 80 15364 2010-06-13 17:52 .DS_Store +-- | ---------- 0 80 0 2009-10-05 07:42 .file +-- | drwx------ 501 20 0 2009-11-04 17:28 .fseventsd +-- | -rw------- 0 0 393216 2010-06-14 01:49 .hotfiles.btree +-- | drwx------ 0 80 0 2009-11-04 18:19 .Spotlight-V100 +-- | d-wx-wx-wx 0 80 0 2009-11-04 18:25 .Trashes +-- | drwxr-xr-x 0 0 0 2009-05-18 21:29 .vol +-- | drwxrwxr-x 0 80 0 2009-04-28 00:06 Applications +-- | drwxr-xr-x 0 0 0 2009-05-18 21:43 bin +-- | drwxr-xr-x 501 80 0 2010-08-10 22:55 bundles -- | --- | Information retrieved as: patrik --- |_ Output restricted to 10 entries per volume. (See afp-ls.maxfiles) --- --- @args afp-ls.maxfiles If set, limits the amount of files returned by the script (default 10). +-- | Volume Patrik Karlsson's Public Folder +-- | PERMISSION UID GID SIZE TIME FILENAME +-- | -rw------- 501 20 6148 2010-12-27 23:45 .DS_Store +-- | -rw-r--r-- 501 20 0 2007-07-24 21:17 .localized +-- | drwx-wx-wx 501 20 0 2009-06-19 04:01 Drop Box +-- | +-- | Volume patrik +-- | maxfiles limit reached (10) +-- | PERMISSION UID GID SIZE TIME FILENAME +-- | -rw------- 501 20 11281 2010-06-14 22:51 .bash_history +-- | -rw-r--r-- 501 20 33 2011-01-19 20:11 .bashrc +-- | -rw------- 501 20 3 2007-07-24 21:17 .CFUserTextEncoding +-- | drwx------ 501 20 0 2010-09-12 14:52 .config +-- | drwx------ 501 20 0 2010-09-12 12:29 .cups +-- | -rw-r--r-- 501 20 15364 2010-06-13 18:34 .DS_Store +-- | drwxr-xr-x 501 20 0 2010-09-12 14:13 .fontconfig +-- | -rw------- 501 20 102 2010-06-14 01:46 .lesshst +-- | -rw-r--r-- 501 20 241 2010-06-14 01:45 .profile +-- | -rw------- 501 20 218 2010-09-12 16:35 .recently-used.xbel +-- |_ -- +-- @xmloutput +-- +--
+-- Storage01 +--
+--
+-- drwx------ +-- 0 +-- 100 +-- 0 +-- 2015-06-26 17:17 +-- Backups +--
+-- +-- drwxr-xr-x +-- 0 +-- 37 +-- 0 +-- 2015-06-19 06:36 +-- Network Trash Folder +--
+-- +-- drwxr-xr-x +-- 0 +-- 37 +-- 0 +-- 2015-06-19 06:36 +-- Temporary Items +--
+-- +-- +-- +-- +-- information retrieved as nil +--
+-- +-- 3 +-- 0 +--
-- Version 0.1 -- Created 04/03/2011 - v0.1 - created by Patrik Karlsson @@ -59,34 +101,17 @@ The output is intended to resemble the output of ls. author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} - - dependencies = {"afp-brute"} -portrule = shortport.portnumber(548, "tcp") - -local function createFileTable() - local filetab = tab.new() - - tab.add(filetab, 1, "PERMISSION") - tab.add(filetab, 2, "UID") - tab.add(filetab, 3, "GID") - tab.add(filetab, 4, "SIZE") - tab.add(filetab, 5, "TIME") - tab.add(filetab, 6, "FILENAME") - tab.nextrow(filetab) - - return filetab -end - +portrule = shortport.port_or_service(548, {"afp"}) action = function(host, port) local afpHelper = afp.Helper:new() local args = nmap.registry.args local users = nmap.registry.afp or { ['nil'] = 'nil' } - local maxfiles = tonumber(stdnse.get_script_args("afp-ls.maxfiles") or 10) - local output = {} + local maxfiles = ls.config("maxfiles") + local output = ls.new_listing() if ( args['afp.username'] ) then users = {} @@ -122,12 +147,12 @@ action = function(host, port) for _, vol in ipairs( vols ) do local status, tbl = afpHelper:Dir( vol ) if ( not(status) ) then - table.insert( + ls.report_error( output, ("ERROR: Failed to list the contents of %s"):format(vol)) else - local file_tab = createFileTable() - local counter = maxfiles or 10 + ls.new_vol(output, vol, true) + local continue = true for _, item in ipairs(tbl[1]) do if ( item and item.name ) then local status, result = afpHelper:GetFileUnixPermissions( @@ -135,27 +160,30 @@ action = function(host, port) if ( status ) then local status, fsize = afpHelper:GetFileSize( vol, item.name) if ( not(status) ) then - table.insert( + ls.report_error( output, - ("\n\nERROR: Failed to retrieve file size for %/%s"):format(vol, item.name)) + ("ERROR: Failed to retrieve file size for %/%s"):format(vol, item.name)) else local status, date = afpHelper:GetFileDates( vol, item.name) if ( not(status) ) then - table.insert( + ls.report_error( output, ("\n\nERROR: Failed to retrieve file dates for %/%s"):format(vol, item.name)) else - tab.addrow(file_tab, result.privs, result.uid, result.gid, fsize, date.create, item.name) - counter = counter - 1 + continue = ls.add_file(output, { + result.privs, result.uid, result.gid, + fsize, date.create, item.name + }) end end end end - if ( counter == 0 ) then break end + if not continue then + ls.report_info(output, ("maxfiles limit reached (%d)"):format(maxfiles)) + break + end end - local result_part = { name = vol } - table.insert(result_part, tab.dump(file_tab)) - table.insert(output, result_part) + ls.end_vol(output) end end end @@ -164,13 +192,9 @@ action = function(host, port) status, response = afpHelper:CloseSession() -- stop after first successful attempt - if ( output and #output > 0 ) then - table.insert(output, "") - table.insert(output, ("Information retrieved as: %s"):format(username)) - if ( maxfiles > 0 ) then - table.insert(output, ("Output restricted to %d entries per volume. (See afp-ls.maxfiles)"):format(maxfiles)) - end - return stdnse.format_output(true, output) + if #output["volumes"] > 0 then + ls.report_info(output, ("information retrieved as %s"):format(username)) + return ls.end_listing(output) end end return diff --git a/scripts/nfs-ls.nse b/scripts/nfs-ls.nse index b347b725e..7cc7fb171 100644 --- a/scripts/nfs-ls.nse +++ b/scripts/nfs-ls.nse @@ -2,7 +2,7 @@ local rpc = require "rpc" local shortport = require "shortport" local stdnse = require "stdnse" local string = require "string" -local tab = require "tab" +local ls = require "ls" local table = require "table" local nmap = require "nmap" @@ -29,47 +29,99 @@ These access permissions are shown only with NFSv3: * Extend: Write new data or add directory entries. * Delete: Delete an existing directory entry. * Execute: Execute file (no meaning for a directory). + +Recursive listing is not implemented. ]] --- -- @usage -- nmap -p 111 --script=nfs-ls -- nmap -sV --script=nfs-ls --- @output --- PORT STATE SERVICE --- 111/tcp open rpcbind --- | nfs-ls: --- | Arguments: --- | maxfiles: 10 (file listing output limited) --- | --- | NFS Export: /mnt/nfs/files --- | NFS Access: Read Lookup NoModify NoExtend NoDelete NoExecute --- | PERMISSION UID GID SIZE MODIFICATION TIME FILENAME --- | drwxr-xr-x 1000 100 4096 2010-06-17 12:28 /mnt/nfs/files --- | drwxr--r-- 1000 1002 4096 2010-05-14 12:58 sources --- | -rw------- 1000 1002 23606 2010-06-17 12:28 notes --- | --- | NFS Export: /home/storage/backup --- | NFS Access: Read Lookup Modify Extend Delete NoExecute --- | PERMISSION UID GID SIZE MODIFICATION TIME FILENAME --- | drwxr-xr-x 1000 100 4096 2010-06-11 22:31 /home/storage/backup --- | -rw-r--r-- 1000 1002 0 2010-06-10 08:34 filetest --- | drwx------ 1000 100 16384 2010-02-05 17:05 lost+found --- | -rw-r--r-- 0 0 5 2010-06-10 11:32 rootfile --- |_ lrwxrwxrwx 1000 1002 8 2010-06-10 08:34 symlink -- --- @args nfs-ls.maxfiles If set, limits the amount of files returned by --- the script. If set to 0 --- or less, all files are shown. The default value is 10. --- @args nfs-ls.human If set to 1 or true, --- shows file sizes in a human readable format with suffixes like --- KB and MB. -- @args nfs-ls.time Specifies which one of the last mac times to use in -- the files attributes output. Possible values are: -- * m: last modification time (mtime) -- * a: last access time (atime) -- * c: last change time (ctime) -- The default value is m (mtime). +-- @args nfs.version The NFS protocol version to use +-- +-- @output +-- PORT STATE SERVICE +-- 111/tcp open rpcbind +-- | nfs-ls: +-- | Volume /mnt/nfs/files +-- | access: Read Lookup NoModify NoExtend NoDelete NoExecute +-- | PERMISSION UID GID SIZE MODIFICATION TIME FILENAME +-- | drwxr-xr-x 1000 100 4096 2010-06-17 12:28 /mnt/nfs/files +-- | drwxr--r-- 1000 1002 4096 2010-05-14 12:58 sources +-- | -rw------- 1000 1002 23606 2010-06-17 12:28 notes +-- | +-- | Volume /home/storage/backup +-- | access: Read Lookup Modify Extend Delete NoExecute +-- | PERMISSION UID GID SIZE MODIFICATION TIME FILENAME +-- | drwxr-xr-x 1000 100 4096 2010-06-11 22:31 /home/storage/backup +-- | -rw-r--r-- 1000 1002 0 2010-06-10 08:34 filetest +-- | drwx------ 1000 100 16384 2010-02-05 17:05 lost+found +-- | -rw-r--r-- 0 0 5 2010-06-10 11:32 rootfile +-- | lrwxrwxrwx 1000 1002 8 2010-06-10 08:34 symlink +-- |_ +-- +-- @xmloutput +-- +--
+-- /mnt/nfs/files +--
+--
+-- drwxr-xr-x +-- 1000 +-- 100 +-- 4096 +-- 2010-06-11 22:31 +-- /mnt/nfs/files +--
+-- +-- -rw-r--r-- +-- 1000 +-- 1002 +-- 0 +-- 2010-06-10 08:34 +-- filetest +--
+-- +-- drwx------ +-- 0 +-- 0 +-- 16384 +-- 2010-02-05 17:05 +-- lost+found +--
+-- +-- -rw-r--r-- +-- 0 +-- 0 +-- 5 +-- 2010-06-10 11:32 +-- rootfile +--
+-- +-- lrwxrwxrwx +-- 1000 +-- 1002 +-- 8 +-- 2010-06-10 08:34 +-- symlink +--
+-- +-- +-- access: Read Lookup NoModify NoExtend NoDelete NoExecute +--
+-- +-- +-- +-- 5 +-- 20493 +--
-- Created 05/28/2010 - v0.1 - combined nfs-dirlist and nfs-acls scripts -- Revised 06/04/2010 - v0.2 - make NFS exports listing with their acls @@ -185,14 +237,12 @@ local function table_dirlist(nfs, mount, dirlist) break end - if v.name ~= ".." and v.name ~= "." then - if v.attributes then - table.insert(files, v.name) - attrs[files[idx]] = table_attributes(nfs, v.name, v.attributes) - idx = idx + 1 - else - stdnse.debug1("ERROR attributes: %s", v.name) - end + if v.attributes then + table.insert(files, v.name) + attrs[files[idx]] = table_attributes(nfs, v.name, v.attributes) + idx = idx + 1 + else + stdnse.debug1("ERROR attributes: %s", v.name) end end @@ -210,53 +260,59 @@ local function unmount_nfs(mount, mnt_obj, nfs_obj) rpc.Helper.UnmountPath(mnt_obj, mount) end -local function nfs_ls(nfs, mount, results, access) +local function nfs_ls(nfs, mount, output) local dirs, attr, acs = {}, {}, {} local nfsobj = rpc.NFS:new() local mnt_comm, nfs_comm, fhandle mnt_comm, fhandle = procedures.MountPath(nfs.host, mount) if mnt_comm == nil then - return false, fhandle + ls.report_error(output, fhandle) + return false end local nfs_comm, status = procedures.NfsOpen(nfs.host) if nfs_comm == nil then rpc.Helper.UnmountPath(mnt_comm, mount) - return false, status + ls.report_error(output, status) + return false end -- check if NFS and Mount versions are compatible -- RPC library will check if the Mount and NFS versions are supported if (nfs_comm.version == 1) then - unmount_nfs(mount, mnt_comm, nfs_comm) - return false, string.format("NFS v%d not supported", nfs_comm.version) + unmount_nfs(mount, mnt_comm, nfs_comm) + ls.report_error(output, + string.format("NFS v%d not supported", nfs_comm.version)) + return false elseif ((nfs_comm.version == 2 and mnt_comm.version > 2) or - (nfs_comm.version == 3 and mnt_comm.version ~= 3)) then - unmount_nfs(mount, mnt_comm, nfs_comm) - return false, string.format("versions mismatch, NFS v%d - Mount v%d", - nfs_comm.version, mnt_comm.version) + (nfs_comm.version == 3 and mnt_comm.version ~= 3)) then + unmount_nfs(mount, mnt_comm, nfs_comm) + ls.report_error(output, + string.format("versions mismatch, NFS v%d - Mount v%d", + nfs_comm.version, mnt_comm.version)) + return false end status, attr = nfsobj:GetAttr(nfs_comm, fhandle) if not status then unmount_nfs(mount, mnt_comm, nfs_comm) - return status, attr + ls.report_error(output, attr) + return status end - table.insert(results, table_attributes(nfs, mount, attr)) - if nfs_comm.version == 3 then status, acs = nfsobj:Access(nfs_comm, fhandle, 0x0000003F) if status then acs.str = rpc.Util.format_access(acs.mask, nfs_comm.version) - table.insert(access, acs.str) + ls.report_info(output, string.format("access: %s", acs.str)) end status, dirs = nfsobj:ReadDirPlus(nfs_comm, fhandle) if status then for _,v in ipairs(table_dirlist(nfs, mount, dirs.entries)) do - table.insert(results, v) + ls.add_file(output, {v.type .. v.mode, v.uid, v.gid, v.size, + v.time, v.filename}) end end elseif nfs_comm.version == 2 then @@ -265,67 +321,39 @@ local function nfs_ls(nfs, mount, results, access) local lookup = {} for _, v in ipairs(dirs.entries) do if ((0 < nfs.maxfiles) and (#lookup >= nfs.maxfiles)) then - break + break end - if v.name ~= ".." and v.name ~= "." then - local f = {} - status, f = nfsobj:LookUp(nfs_comm, fhandle, v.name) - f.name = v.name - table.insert(lookup, f) - end + local f = {} + status, f = nfsobj:LookUp(nfs_comm, fhandle, v.name) + f.name = v.name + table.insert(lookup, f) end for _, v in ipairs(table_dirlist(nfs, mount, lookup)) do - table.insert(results, v) + ls.add_file(output, {v.type .. v.mode, v.uid, v.gid, v.size, + v.time, v.filename}) end end end unmount_nfs(mount, mnt_comm, nfs_comm) - return status, dirs -end - -local function report(nfs, table) - local outtab, time = tab.new(), "" - - if nfs.time == "mtime" then - time = "MODIFICATION TIME" - elseif nfs.time == "atime" then - time = "ACCESS TIME" - elseif nfs.time == "ctime" then - time = "CHANGE TIME" - end - - tab.add(outtab, 1, "PERMISSION") - tab.add(outtab, 2, "UID") - tab.add(outtab, 3, "GID") - tab.add(outtab, 4, "SIZE") - tab.add(outtab, 5, time) - tab.add(outtab, 6, "FILENAME") - tab.nextrow(outtab) - - for _,f in pairs(table) do - local perm = f.type .. f.mode - tab.addrow(outtab, perm, f.uid, f.gid, - f.size, f.time, f.filename) - end - return tab.dump(outtab) + return status end local mainaction = function(host) - local o, results, mounts, status = {}, {}, {} + local results, mounts, status = {}, {} local nfs_info = { host = host, --recurs = tonumber(nmap.registry.args['nfs-ls.recurs']) or 1, } + local output = ls.new_listing() - nfs_info.version, nfs_info.maxfiles, nfs_info.time, - nfs_info.human = stdnse.get_script_args('nfs.version', - 'nfs-ls.maxfiles','nfs-ls.time','nfs-ls.human') - - nfs_info.maxfiles = tonumber(nfs_info.maxfiles) or 10 + nfs_info.version, nfs_info.time = stdnse.get_script_args('nfs.version', + 'nfs-ls.time') + nfs_info.maxfiles = ls.config('maxfiles') + nfs_info.human = ls.config('human') if nfs_info.time == "a" or nfs_info.time == "A" then nfs_info.time = "atime" @@ -335,15 +363,6 @@ local mainaction = function(host) nfs_info.time = "mtime" end - if nfs_info.maxfiles > 0 then - local args = {} - args['name'] = 'Arguments:' - table.insert(args, - string.format("maxfiles: %d (file listing output limited)", - nfs_info.maxfiles)) - table.insert(o, args) - end - status, mounts = procedures.ShowMounts(nfs_info.host) if not status or mounts == nil then if mounts then @@ -354,22 +373,13 @@ local mainaction = function(host) end for _, v in ipairs(mounts) do - local results, access, err = {}, {} - status, err = nfs_ls(nfs_info, v.name, results, access) - if not status then - table.insert(o, string.format("\nNFS Export %s", v.name)) - table.insert(o, string.format("ERROR: %s", err)) - else - table.insert(o, - string.format("\nNFS Export: %s", results[1].filename)) - if #access ~= 0 then - table.insert(o, string.format("NFS Access: %s", access[1])) - end - table.insert(o, {report(nfs_info, results)}) - end + local err + ls.new_vol(output, v.name, true) + status = nfs_ls(nfs_info, v.name, output) + ls.end_vol(output) end - return stdnse.format_output(true, o) + return ls.end_listing(output) end hostaction = function(host) diff --git a/scripts/smb-ls.nse b/scripts/smb-ls.nse index 29060d456..7a8d67f97 100644 --- a/scripts/smb-ls.nse +++ b/scripts/smb-ls.nse @@ -1,8 +1,9 @@ local bit = require 'bit' local smb = require 'smb' +local string = require 'string' local stdnse = require 'stdnse' -local tab = require 'tab' -local table = require "table" +local ls = require 'ls' + local openssl= stdnse.silent_require 'openssl' description = [[ @@ -13,32 +14,97 @@ The output is intended to resemble the output of the UNIX ls comman --- -- @usage -- nmap -p 445 --script smb-ls --script-args 'share=c$,path=\temp' +-- nmap -p 445 --script smb-enum-shares,smb-ls +-- +-- @args smb-ls.share (or smb-ls.shares) the share (or a colon-separated list +-- of shares) to connect to (default: use shares found by smb-enum-shares) +-- @args smb-ls.path the path, relative to the share to list the contents from +-- (default: root of the share) +-- @args smb-ls.pattern the search pattern to execute (default: *) +-- @args smb-ls.checksum download each file and calculate a checksum +-- (default: false) -- -- @output -- Host script results: -- | smb-ls: --- | Directory of \\192.168.56.101\c$\ --- | 2007-12-02 00:20:09 0 AUTOEXEC.BAT --- | 2007-12-02 00:20:09 0 CONFIG.SYS --- | 2007-12-02 00:53:39 Documents and Settings --- | 2009-09-08 13:26:10 e5a6b742d36facb19c5192852c43 --- | 2008-12-01 02:06:29 Inetpub --- | 2007-02-18 00:31:38 94720 msizap.exe --- | 2007-12-02 00:55:01 Program Files --- | 2008-12-01 02:05:52 temp --- | 2011-12-16 14:40:18 usr --- | 2007-12-02 00:42:40 WINDOWS --- |_ 2007-12-02 00:22:38 wmpub --- --- @args smb-ls.share [optional] the share to connect to --- @args smb-ls.shares [optional] a colon-separated list of shares to connect to --- @args smb-ls.path [optional] the path, relative to the share to list the contents from --- @args smb-ls.pattern [optional] the search pattern to execute (default: *) --- @args smb-ls.maxdepth [optional] the maximum depth to recurse into a directory (default: no recursion) --- @args smb-ls.maxfiles [optional] return only a certain amount of files --- @args smb-ls.checksum [optional] download each file and calculate a SHA1 checksum --- @args smb-ls.errors [optional] report connection errors +-- | Volume \\192.168.56.101\c$\ +-- | SIZE TIME FILENAME +-- | 0 2007-12-02 00:20:09 AUTOEXEC.BAT +-- | 0 2007-12-02 00:20:09 CONFIG.SYS +-- | 2007-12-02 00:53:39 Documents and Settings +-- | 2009-09-08 13:26:10 e5a6b742d36facb19c5192852c43 +-- | 2008-12-01 02:06:29 Inetpub +-- | 94720 2007-02-18 00:31:38 msizap.exe +-- | 2007-12-02 00:55:01 Program Files +-- | 2008-12-01 02:05:52 temp +-- | 2011-12-16 14:40:18 usr +-- | 2007-12-02 00:42:40 WINDOWS +-- | 2007-12-02 00:22:38 wmpub +-- |_ -- +-- @xmloutput +-- +--
+--
+--
+-- 0 +-- 2007-12-02 00:20:09 +-- AUTOEXEC.BAT +--
+-- +-- 0 +-- 2007-12-02 00:20:09 +-- CONFIG.SYS +--
+-- +-- <DIR> +-- 2007-12-02 00:53:39 +-- Documents and Settings +--
+-- +-- <DIR> +-- 2009-09-08 13:26:10 +-- e5a6b742d36facb19c5192852c43 +--
+-- +-- <DIR> +-- 2008-12-01 02:06:29 +-- Inetpub +--
+-- +-- 94720 +-- 2007-02-18 00:31:38 +-- msizap.exe +--
+-- +-- <DIR> +-- 2007-12-02 00:55:01 +-- Program Files +--
+-- +-- <DIR> +-- 2008-12-01 02:05:52 +-- temp +--
+-- +-- <DIR> +-- 2011-12-16 14:40:18 +-- usr +--
+-- +-- <DIR> +-- 2007-12-02 00:42:40 +-- WINDOWS +--
+-- +-- <DIR> +-- 2007-12-02 00:22:38 +-- wmpub +--
+-- +-- \\192.168.1.2\Downloads +-- +-- author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" @@ -49,10 +115,6 @@ local arg_shares = stdnse.get_script_args(SCRIPT_NAME .. '.shares') local arg_share = stdnse.get_script_args(SCRIPT_NAME .. '.share') local arg_path = stdnse.get_script_args(SCRIPT_NAME .. '.path') or '\\' local arg_pattern = stdnse.get_script_args(SCRIPT_NAME .. '.pattern') or '*' -local arg_maxfiles = tonumber(stdnse.get_script_args(SCRIPT_NAME .. '.maxfiles')) -local arg_maxdepth = stdnse.get_script_args(SCRIPT_NAME .. '.maxdepth') -local arg_checksum = stdnse.get_script_args(SCRIPT_NAME .. '.checksum') -local arg_errors = stdnse.get_script_args(SCRIPT_NAME .. '.errors') hostrule = function(host) return ( smb.get_port(host) ~= nil and @@ -65,7 +127,45 @@ local function is_dir(fe) return ( bit.band(fe.attrs, 16) == 16 ) end -local function fail(err) return stdnse.format_output(false, err) end +local function list_files(host, share, smbstate, path, options, output, maxdepth, basedir) + basedir = basedir or "" + local continue + + for fe in smb.find_files(smbstate, path .. '\\' .. arg_pattern, options) do + if basedir == "" or (fe.fname ~= "." and fe.fname ~= "..") then + if ls.config('checksum') and not(is_dir(fe)) then + local status, content = smb.file_read(host, share, path .. '\\' .. fe.fname, nil, {file_create_disposition=1}) + local sha1 = status and stdnse.tohex(openssl.sha1(content)) or "" + continue = ls.add_file(output, {is_dir(fe) and '' or fe.eof, + fe.created, basedir .. fe.fname, sha1}) + else + continue = ls.add_file(output, {is_dir(fe) and '' or fe.eof, + fe.created, basedir .. fe.fname}) + end + if not continue then + return false + end + if is_dir(fe) then + continue = true + if maxdepth > 0 then + continue = list_files(host, share, smbstate, + path .. '\\' .. fe.fname, options, + output, maxdepth - 1, + basedir .. fe.fname .. '\\') + elseif maxdepth < 0 then + continue = list_files(host, share, smbstate, + path .. '\\' .. fe.fname, options, + output, -1, + basedir .. fe.fname .. '\\') + end + if not continue then + return false + end + end + end + end + return true +end action = function(host) @@ -78,91 +178,40 @@ action = function(host) arg_shares = host.registry['smb_shares'] end - -- arg_maxdepth defaults to 1 (no recursion) - if arg_maxdepth == nil then - arg_maxdepth = 1 - else - arg_maxdepth = tonumber(arg_maxdepth) - end - - local output = {} + local output = ls.new_listing() for _, share in ipairs(arg_shares) do local status, smbstate = smb.start_ex(host, true, true, share, nil, nil, nil) if ( not(status) ) then - if arg_errors then - table.insert( - output, - ("Failed to authenticate to server (%s) for directory of \\\\%s\\%s%s"):format(smbstate, stdnse.get_hostname(host), share, arg_path)) - table.insert(output, "") - end + ls.report_error( + output, + ("Failed to authenticate to server (%s) for directory of \\\\%s\\%s%s"):format(smbstate, stdnse.get_hostname(host), share, arg_path)) else - table.insert(output, "") - -- remove leading slash arg_path = ( arg_path:sub(1,2) == '\\' and arg_path:sub(2) or arg_path ) - -- fixup checksum argument - arg_checksum = ( arg_checksum == 'true' or arg_checksum == '1' ) and true or false - - local options = { max_depth = arg_maxdepth, max_files = arg_maxfiles } + local options = {} local depth, path, dirs = 0, arg_path, {} local file_count, dir_count, total_bytes = 0, 0, 0 + local continue = true - repeat - -- we need three columns per row, plus one for checksum if - -- requested - local lstab = tab.new((arg_checksum and 4 or 3)) - - for fe in smb.find_files(smbstate, path .. '\\' .. arg_pattern, options ) do - if ( arg_checksum and not(is_dir(fe)) ) then - local status, content = smb.file_read(host, share, path .. '\\' .. fe.fname, nil, {file_create_disposition=1}) - local sha1 = ( status and stdnse.tohex(openssl.sha1(content)) or "" ) - tab.addrow(lstab, fe.created, (is_dir(fe) and '' or fe.eof), fe.fname, sha1) - else - tab.addrow(lstab, fe.created, (is_dir(fe) and '' or fe.eof), fe.fname) - end - - arg_maxfiles = ( arg_maxfiles and arg_maxfiles - 1 ) - if ( arg_maxfiles == 0 ) then - break - end - - if ( is_dir(fe) ) then - dir_count = dir_count + 1 - if ( fe.fname ~= '.' and fe.fname ~= '..' ) then - table.insert(dirs, { depth = depth + 1, path = path .. '\\' .. fe.fname } ) - end - else - total_bytes = total_bytes + fe.eof - file_count = file_count + 1 - end - end - table.insert(output, { name = ("Directory of %s"):format( '\\\\' .. stdnse.get_hostname(host) .. '\\' .. share .. path), tab.dump(lstab) }) - - path = nil - if ( #dirs ~= 0 ) then - local dir = table.remove(dirs, 1) - depth = dir.depth - if ( not(arg_maxdepth) or ( dir.depth < arg_maxdepth ) ) then - path = dir.path - table.insert(output, "") - end - end - until(not(path) or arg_maxfiles == 0) - + ls.new_vol( + output, + '\\\\' .. stdnse.get_hostname(host) .. '\\' .. share .. path, + false) + continue = list_files(host, share, smbstate, path, options, + output, ls.config('maxdepth')) + if not continue then + ls.report_info( + output, + string.format("maxfiles limit reached (%d)", ls.config('maxfiles'))) + end + ls.end_vol(output) smb.stop(smbstate) - - local summary = { name = "Total Files Listed:", - ("%8d File(s)\t%d bytes"):format(file_count, total_bytes), - ("%8d Dir(s)"):format(dir_count) } - table.insert(output, "") - table.insert(output, summary) - table.insert(output, "") end end - return stdnse.format_output(true, output) + return ls.end_listing(output) end