Skip to content

Commit

Permalink
Merge r22026 through r22063 from /nmap-exp/david/nmap-script-help (new
Browse files Browse the repository at this point in the history
--script-help option).
  • Loading branch information
david committed Jan 27, 2011
1 parent 08cf041 commit 8553cb3
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 2 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,13 @@ o [NSE] Nmap has two new NSE script scanning phases. The new pre-scan
found to be running each service. See
http://nmap.org/book/nse-usage.html#nse-script-types. [Djalal]

o A new --script-help option prints out the categories, NSEDoc URL,
and description for scripts matching a specification. Use it like
this for example: nmap --script-help "default or http-*". You can
use this to get a preview of what scripts will run for a given
specification. Martin Holst Swende had the idea for this feature and
wrote the first implementation. [David]

o Dramatically improved nmap.xsl (used for converting Nmap XML output
to HTML). In particular:
- Put verbose details behind expander buttons so you can see them if
Expand Down
1 change: 1 addition & 0 deletions NmapOps.cc
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ void NmapOps::Initialize() {
scriptversion = 0;
scripttrace = 0;
scriptupdatedb = 0;
scripthelp = false;
chosenScripts.clear();
#endif
memset(&sourcesock, 0, sizeof(sourcesock));
Expand Down
1 change: 1 addition & 0 deletions NmapOps.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ class NmapOps {
int scriptversion;
int scripttrace;
int scriptupdatedb;
bool scripthelp;
void chooseScripts(char* argument);
std::vector<std::string> chosenScripts;
#endif
Expand Down
14 changes: 14 additions & 0 deletions docs/nse-scripts.dtd
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!-- DTD for Nmap XML -&#45;script-help output.
nmap -&#45;script-help "<rules>" -oX - -->

<!ELEMENT nse-scripts (script*)>

<!ELEMENT script (categories?, description?)>

<!ATTLIST script filename CDATA #REQUIRED>

<!ELEMENT categories (category*)>

<!ELEMENT category (#PCDATA)>

<!ELEMENT description (#PCDATA)>
50 changes: 49 additions & 1 deletion docs/scripting.xml
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,10 @@ Black Hat Briefings in 2010.</para>
directories full of scripts you wish to execute. You can customize
some scripts by providing arguments to them via the
<option>--script-args</option><indexterm><primary><option>--script-args</option></primary></indexterm>
option. The two remaining options,
option.
The <option>--script-help</option><indexterm><primary><option>--script-help</option></primary></indexterm>
shows a description of what each selected script does.
The two remaining options,
<option>--script-trace</option><indexterm><primary><option>--script-trace</option></primary></indexterm>
and <option>--script-updatedb</option>,<indexterm><primary><option>--script-updatedb</option></primary></indexterm>
are generally only used for script debugging and development. Script scanning is also included as part of the <option>-A</option> (aggressive scan) option.
Expand Down Expand Up @@ -664,6 +667,51 @@ Nmap script database, but should be used cautiously since Nmap may contain explo
<xref linkend="nse-args"/> for a detailed explanation.</para>
</listitem>
</varlistentry>

<varlistentry>
<term>
<indexterm><primary><option>--script-help</option></primary></indexterm>
<option>--script-help <replaceable>filename</replaceable>|<replaceable>category</replaceable>|<replaceable>directory</replaceable>|<replaceable>expression</replaceable>|all<optional>,...</optional></option></term>
</term>
<listitem>
<para>
Shows help about scripts. For each script matching the given
specification, Nmap prints the script name, its categories, and its
description. The specifications are the same as those accepted by
<option>--script</option>; so for example if you want help about
the <literal>ftp-anon</literal> script, you would run
<command>nmap --script-help ftp-anon</command>. A sample of script
help is shown in <xref linkend="nse-script-help"/>.
</para>
<example id="nse-script-help">
<indexterm><primary><option>--script-help</option></primary><secondary>example of</secondary></indexterm>
<title>Script help</title>
<screen>
$ nmap --script-help "afp-* and discovery"

Starting Nmap 5.36TEST4 ( http://nmap.org ) at 2011-01-27 13:04 PST

afp-serverinfo
Categories: discovery safe
http://nmap.org/nsedoc/scripts/afp-serverinfo.html
Shows AFP server information. This information includes the server's
hostname, IPv4 and IPv6 addresses, and hardware type (for example
<code>Macmini</code> or <code>MacBookPro</code>).

afp-showmount
Categories: discovery safe
http://nmap.org/nsedoc/scripts/afp-showmount.html
Shows AFP shares and ACLs.
</example>
<para>
If the
<option>-oX</option><indexterm><primary><option>-oX</option></primary></indexterm>
option is used, an XML representation of the script help will be
written to the given file.
</para>
</listitem>
</varlistentry>

<varlistentry>
<term>
<indexterm><primary><option>--script-trace</option></primary></indexterm>
Expand Down
10 changes: 10 additions & 0 deletions nmap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,8 @@ int nmap_main(int argc, char *argv[]) {
{"script_updatedb", no_argument, 0, 0},
{"script-args",required_argument,0,0},
{"script_args",required_argument,0,0},
{"script-help",required_argument,0,0},
{"script_help",required_argument,0,0},
#endif
{"ip_options", required_argument, 0, 0},
{"ip-options", required_argument, 0, 0},
Expand Down Expand Up @@ -647,6 +649,9 @@ int nmap_main(int argc, char *argv[]) {
o.scripttrace = 1;
} else if (optcmp(long_options[option_index].name, "script-updatedb") == 0){
o.scriptupdatedb = 1;
} else if (optcmp(long_options[option_index].name, "script-help") == 0){
o.scripthelp = true;
o.chooseScripts(optarg);
} else
#endif
if (optcmp(long_options[option_index].name, "max-os-tries") == 0) {
Expand Down Expand Up @@ -1316,6 +1321,11 @@ int nmap_main(int argc, char *argv[]) {
print_iflist();
exit(0);
}
if (o.scripthelp) {
/* Special-case open_nse for --script-help only. */
open_nse();
exit(0);
}

#if HAVE_IPV6
if(o.af() == AF_INET6 && o.traceroute)
Expand Down
67 changes: 67 additions & 0 deletions nse_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "timing.h"
#include "Target.h"
#include "nmap_tty.h"
#include "xml.h"

#include "nse_main.h"
#include "nse_utility.h"
Expand Down Expand Up @@ -193,6 +194,65 @@ static int scan_progress_meter (lua_State *L)
return 1;
}

/* This is like nmap.log_write, but doesn't append "NSE:" to the beginning of
messages. It is only used internally by nse_main.lua and is not available to
scripts. */
static int l_log_write(lua_State *L)
{
static const char *const ops[] = {"stdout", "stderr", NULL};
static const int logs[] = {LOG_STDOUT, LOG_STDERR};
int log = logs[luaL_checkoption(L, 1, NULL, ops)];
log_write(log, "%s", luaL_checkstring(L, 2));
return 0;
}

static int l_xml_start_tag(lua_State *L)
{
const char *name;

name = luaL_checkstring(L, 1);
xml_open_start_tag(name);

if (lua_isnoneornil(L, 2)) {
lua_newtable(L);
lua_replace(L, 2);
}

lua_pushnil(L);
while (lua_next(L, 2)) {
xml_attribute(luaL_checkstring(L, -2), "%s", luaL_checkstring(L, -1));
lua_pop(L, 1);
}

xml_close_start_tag();

return 0;
}

static int l_xml_end_tag(lua_State *L)
{
xml_end_tag();

return 0;
}

static int l_xml_write_escaped(lua_State *L)
{
const char *text;

text = luaL_checkstring(L, 1);
xml_write_escaped(text);

return 0;
}

static int l_xml_newline(lua_State *L)
{
xml_newline();

return 0;
}

static void open_cnse (lua_State *L)
{
static const luaL_Reg nse[] = {
Expand All @@ -208,6 +268,11 @@ static void open_cnse (lua_State *L)
{"script_set_output", script_set_output},
{"host_set_output", host_set_output},
{"port_set_output", port_set_output},
{"log_write", l_log_write},
{"xml_start_tag", l_xml_start_tag},
{"xml_end_tag", l_xml_end_tag},
{"xml_write_escaped", l_xml_write_escaped},
{"xml_newline", l_xml_newline},
{NULL, NULL}
};

Expand All @@ -220,8 +285,10 @@ static void open_cnse (lua_State *L)
setbfield(L, -1, "default", o.script == 1);
setbfield(L, -1, "scriptversion", o.scriptversion == 1);
setbfield(L, -1, "scriptupdatedb", o.scriptupdatedb == 1);
setbfield(L, -1, "scripthelp", o.scripthelp);
setsfield(L, -1, "script_dbpath", SCRIPT_ENGINE_DATABASE);
setsfield(L, -1, "scriptargs", o.scriptargs);
setsfield(L, -1, "NMAP_URL", NMAP_URL);
}

void ScriptResult::set_output (const char *out)
Expand Down
65 changes: 64 additions & 1 deletion nse_main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ end
local script_database_type, script_database_path =
cnse.fetchfile_absolute(cnse.script_dbpath);
local script_database_update = cnse.scriptupdatedb;
local script_help = cnse.scripthelp;

local stdnse = require "stdnse";

Expand Down Expand Up @@ -170,6 +171,7 @@ end

local log_write, verbosity, debugging =
nmap.log_write, nmap.verbosity, nmap.debugging;
local log_write_raw = cnse.log_write;

local function print_verbose (level, fmt, ...)
if verbosity() >= assert(tonumber(level)) or debugging() > 0 then
Expand Down Expand Up @@ -421,6 +423,7 @@ do
portrule = portrule,
postrule = postrule,
args = {n = 0};
description = rawget(env, "description"),
categories = rawget(env, "categories"),
author = rawget(env, "author"),
license = rawget(env, "license"),
Expand Down Expand Up @@ -819,6 +822,62 @@ local function run (threads_iter, scantype)
progress "endTask";
end

-- Format NSEDoc markup (e.g., including bullet lists and <code> sections) into
-- a display string at the given indentation level. Currently this only indents
-- the string and doesn't interpret any other markup.
local function format_nsedoc(nsedoc, indent)
indent = indent or ""

return string.gsub(nsedoc, "([^\n]+)", indent .. "%1")
end

-- Return the NSEDoc URL for the script with the given id.
local function nsedoc_url(id)
return string.format("%s/nsedoc/scripts/%s.html", cnse.NMAP_URL, id)
end

local function script_help_normal(chosen_scripts)
for i, script in ipairs(chosen_scripts) do
log_write_raw("stdout", "\n");
log_write_raw("stdout", string.format("%s\n", script.id));
log_write_raw("stdout", string.format("Categories: %s\n", table.concat(script.categories, " ")));
log_write_raw("stdout", string.format("%s\n", nsedoc_url(script.id)));
log_write_raw("stdout", format_nsedoc(script.description, " "));
end
end

local function script_help_xml(chosen_scripts)
cnse.xml_start_tag("nse-scripts");
cnse.xml_newline();

for i, script in ipairs(chosen_scripts) do
cnse.xml_start_tag("script", { filename = script.filename });
cnse.xml_newline();

cnse.xml_start_tag("categories");
for _, category in ipairs(script.categories) do
cnse.xml_start_tag("category");
cnse.xml_write_escaped(category);
cnse.xml_end_tag();
end
cnse.xml_end_tag();
cnse.xml_newline();

cnse.xml_start_tag("description");
cnse.xml_write_escaped(script.description);
cnse.xml_end_tag();
cnse.xml_newline();

-- script
cnse.xml_end_tag();
cnse.xml_newline();
end

-- nse-scripts
cnse.xml_end_tag();
cnse.xml_newline();
end

do -- Load script arguments (--script-args)
local args = cnse.scriptargs or "";

Expand Down Expand Up @@ -919,10 +978,14 @@ end
local chosen_scripts = get_chosen_scripts(rules);
print_verbose(1, "Loaded %d scripts for scanning.", #chosen_scripts);
for i, script in ipairs(chosen_scripts) do
-- PLEASE DO NOT CHANGE THIS FORMAT. IT IS USED BY ZENMAP TO SELECT SCRIPTS
print_debug(2, "Loaded '%s'.", script.filename);
end

if script_help then
script_help_normal(chosen_scripts);
script_help_xml(chosen_scripts);
end

-- main(hosts)
-- This is the main function we return to NSE (on the C side), nse_main.cc
-- gets this function by loading and executing nse_main.lua. This
Expand Down

0 comments on commit 8553cb3

Please sign in to comment.