mirror of
https://github.com/nmap/nmap.git
synced 2025-12-17 21:19:01 +00:00
Merge r19520:r20039 from nmap-exp/djalal/nmap-add-targets. This will let NSE scripts to add new discovered targets to future Nmap scans.
This commit is contained in:
@@ -96,9 +96,14 @@
|
|||||||
#include "TargetGroup.h"
|
#include "TargetGroup.h"
|
||||||
#include "NmapOps.h"
|
#include "NmapOps.h"
|
||||||
#include "nmap_error.h"
|
#include "nmap_error.h"
|
||||||
|
#include "global_structures.h"
|
||||||
|
|
||||||
extern NmapOps o;
|
extern NmapOps o;
|
||||||
|
|
||||||
|
#ifndef NOLUA
|
||||||
|
NewTargets *NewTargets::new_targets;
|
||||||
|
#endif
|
||||||
|
|
||||||
TargetGroup::TargetGroup() {
|
TargetGroup::TargetGroup() {
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
@@ -562,6 +567,97 @@ const std::list<struct sockaddr_storage> &TargetGroup::get_resolved_addrs(void)
|
|||||||
return resolvedaddrs;
|
return resolvedaddrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NOLUA
|
||||||
|
NewTargets *NewTargets::get (void) {
|
||||||
|
if (new_targets)
|
||||||
|
return new_targets;
|
||||||
|
new_targets = new NewTargets();
|
||||||
|
return new_targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
NewTargets::NewTargets (void) {
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NewTargets::Initialize (void) {
|
||||||
|
history.clear();
|
||||||
|
while(!queue.empty())
|
||||||
|
queue.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This private method is used to push new targets to the
|
||||||
|
* queue. It returns the number of targets in the queue. */
|
||||||
|
unsigned long NewTargets::push (const char *target) {
|
||||||
|
std::pair<std::set<std::string>::iterator, bool> pair_iter;
|
||||||
|
std::string tg(target);
|
||||||
|
|
||||||
|
if (tg.length() > 0) {
|
||||||
|
/* save targets in the scanned history here (NSE side). */
|
||||||
|
pair_iter = history.insert(tg);
|
||||||
|
|
||||||
|
/* A new target */
|
||||||
|
if (pair_iter.second == true) {
|
||||||
|
/* push target onto the queue for future scans */
|
||||||
|
queue.push(tg);
|
||||||
|
|
||||||
|
if (o.debugging > 3)
|
||||||
|
log_write(LOG_PLAIN, "New target %s pushed onto the queue.\n", tg.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return queue.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reads a target from the queue and return it to be pushed
|
||||||
|
* onto Nmap scan queue */
|
||||||
|
std::string NewTargets::read (void) {
|
||||||
|
std::string str;
|
||||||
|
|
||||||
|
/* check to see it there are targets in the queue */
|
||||||
|
if (!new_targets->queue.empty()) {
|
||||||
|
str = new_targets->queue.front();
|
||||||
|
new_targets->queue.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NewTargets::clear (void) {
|
||||||
|
new_targets->history.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long NewTargets::get_number (void) {
|
||||||
|
return new_targets->history.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long NewTargets::get_scanned (void) {
|
||||||
|
return new_targets->history.size() - new_targets->queue.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long NewTargets::get_queued (void) {
|
||||||
|
return new_targets->queue.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the function that is used by nse_nmaplib.cc to add
|
||||||
|
* new targets.
|
||||||
|
* Returns the number of targets in the queue on success, or 0 on
|
||||||
|
* failures or when the queue is empty. */
|
||||||
|
unsigned long NewTargets::insert (const char *target) {
|
||||||
|
if (*target) {
|
||||||
|
if (new_targets == NULL) {
|
||||||
|
error("Error: to add targets run with -sC or --script options.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (o.current_scantype == SCRIPT_POST_SCAN) {
|
||||||
|
error("Error: adding targets is disabled in the Post-scanning phase.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_targets->push(target);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Lookahead is the number of hosts that can be
|
/* Lookahead is the number of hosts that can be
|
||||||
checked (such as ping scanned) in advance. Randomize causes each
|
checked (such as ping scanned) in advance. Randomize causes each
|
||||||
group of up to lookahead hosts to be internally shuffled around.
|
group of up to lookahead hosts to be internally shuffled around.
|
||||||
|
|||||||
@@ -96,6 +96,8 @@
|
|||||||
#define TARGETGROUP_H
|
#define TARGETGROUP_H
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <queue>
|
||||||
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "nmap.h"
|
#include "nmap.h"
|
||||||
@@ -172,6 +174,52 @@ class TargetGroup {
|
|||||||
int namedhost;
|
int namedhost;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Adding new targets is for NSE scripts */
|
||||||
|
#ifndef NOLUA
|
||||||
|
class NewTargets {
|
||||||
|
public:
|
||||||
|
NewTargets();
|
||||||
|
|
||||||
|
/* return a previous inserted target */
|
||||||
|
static std::string read (void);
|
||||||
|
|
||||||
|
/* clear the scanned_targets_cache */
|
||||||
|
static void clear (void);
|
||||||
|
|
||||||
|
/* get the number of all new added targets */
|
||||||
|
static unsigned long get_number (void);
|
||||||
|
|
||||||
|
/* get the number that have been scanned */
|
||||||
|
static unsigned long get_scanned (void);
|
||||||
|
|
||||||
|
/* get the number of queued targets left to scan */
|
||||||
|
static unsigned long get_queued (void);
|
||||||
|
|
||||||
|
/* get the new_targets object */
|
||||||
|
static NewTargets *get (void);
|
||||||
|
|
||||||
|
/* insert targets to the new_targets_queue */
|
||||||
|
static unsigned long insert (const char *target);
|
||||||
|
private:
|
||||||
|
/* unsigned long mex_new_targets; */
|
||||||
|
|
||||||
|
/* A queue to push new targets that were discovered by NSE scripts.
|
||||||
|
* Nmap will pop future targets from this queue. */
|
||||||
|
std::queue<std::string> queue;
|
||||||
|
|
||||||
|
/* A cache to save scanned targets specifiactions.
|
||||||
|
* (These are targets that were pushed to Nmap scan queue) */
|
||||||
|
std::set<std::string> history;
|
||||||
|
|
||||||
|
void Initialize();
|
||||||
|
|
||||||
|
/* Save new targets onto the queue */
|
||||||
|
unsigned long push (const char *target);
|
||||||
|
protected:
|
||||||
|
static NewTargets *new_targets;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
class HostGroupState {
|
class HostGroupState {
|
||||||
public:
|
public:
|
||||||
HostGroupState(int lookahead, int randomize, char *target_expressions[],
|
HostGroupState(int lookahead, int randomize, char *target_expressions[],
|
||||||
|
|||||||
24
nmap.cc
24
nmap.cc
@@ -445,6 +445,8 @@ int nmap_main(int argc, char *argv[]) {
|
|||||||
#ifndef NOLUA
|
#ifndef NOLUA
|
||||||
/* Pre-Scan and Post-Scan script results datastructure */
|
/* Pre-Scan and Post-Scan script results datastructure */
|
||||||
ScriptResults *script_scan_results = NULL;
|
ScriptResults *script_scan_results = NULL;
|
||||||
|
/* Only NSE scripts can add targets */
|
||||||
|
NewTargets *new_targets = NULL;
|
||||||
#endif
|
#endif
|
||||||
TargetGroup *exclude_group = NULL;
|
TargetGroup *exclude_group = NULL;
|
||||||
char myname[MAXHOSTNAMELEN + 1];
|
char myname[MAXHOSTNAMELEN + 1];
|
||||||
@@ -1608,6 +1610,7 @@ int nmap_main(int argc, char *argv[]) {
|
|||||||
open_nse();
|
open_nse();
|
||||||
|
|
||||||
if (o.script) {
|
if (o.script) {
|
||||||
|
new_targets = NewTargets::get();
|
||||||
script_scan_results = get_script_scan_results_obj();
|
script_scan_results = get_script_scan_results_obj();
|
||||||
script_scan(Targets, SCRIPT_PRE_SCAN);
|
script_scan(Targets, SCRIPT_PRE_SCAN);
|
||||||
printscriptresults(script_scan_results, SCRIPT_PRE_SCAN);
|
printscriptresults(script_scan_results, SCRIPT_PRE_SCAN);
|
||||||
@@ -1642,6 +1645,23 @@ int nmap_main(int argc, char *argv[]) {
|
|||||||
// For purposes of random scan
|
// For purposes of random scan
|
||||||
host_exp_group[num_host_exp_groups++] = strdup(host_spec);
|
host_exp_group[num_host_exp_groups++] = strdup(host_spec);
|
||||||
}
|
}
|
||||||
|
#ifndef NOLUA
|
||||||
|
/* Add the new NSE discovered targets to the scan queue */
|
||||||
|
if (o.script) {
|
||||||
|
if (new_targets != NULL) {
|
||||||
|
while (new_targets->get_queued() > 0 && num_host_exp_groups < o.ping_group_sz) {
|
||||||
|
std::string target_spec = new_targets->read();
|
||||||
|
if (target_spec.length())
|
||||||
|
host_exp_group[num_host_exp_groups++] = strdup(target_spec.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o.debugging > 3)
|
||||||
|
log_write(LOG_PLAIN,
|
||||||
|
"New targets in the scanned cache: %ld, pending ones: %ld.\n",
|
||||||
|
new_targets->get_scanned(), new_targets->get_queued());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (num_host_exp_groups == 0)
|
if (num_host_exp_groups == 0)
|
||||||
break;
|
break;
|
||||||
delete hstate;
|
delete hstate;
|
||||||
@@ -1876,12 +1896,14 @@ int nmap_main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
o.numhosts_scanning = 0;
|
o.numhosts_scanning = 0;
|
||||||
} while(!o.max_ips_to_scan || o.max_ips_to_scan > o.numhosts_scanned);
|
} while(!o.max_ips_to_scan || o.max_ips_to_scan > o.numhosts_scanned);
|
||||||
|
|
||||||
#ifndef NOLUA
|
#ifndef NOLUA
|
||||||
if (o.script) {
|
if (o.script) {
|
||||||
script_scan(Targets, SCRIPT_POST_SCAN);
|
script_scan(Targets, SCRIPT_POST_SCAN);
|
||||||
printscriptresults(script_scan_results, SCRIPT_POST_SCAN);
|
printscriptresults(script_scan_results, SCRIPT_POST_SCAN);
|
||||||
script_scan_results->clear();
|
script_scan_results->clear();
|
||||||
|
delete new_targets;
|
||||||
|
new_targets = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ extern "C" {
|
|||||||
#include "nmap_error.h"
|
#include "nmap_error.h"
|
||||||
#include "NmapOps.h"
|
#include "NmapOps.h"
|
||||||
#include "Target.h"
|
#include "Target.h"
|
||||||
|
#include "TargetGroup.h"
|
||||||
#include "portlist.h"
|
#include "portlist.h"
|
||||||
#include "service_scan.h"
|
#include "service_scan.h"
|
||||||
#include "nmap_rpc.h"
|
#include "nmap_rpc.h"
|
||||||
@@ -681,6 +682,58 @@ static int l_get_timing_level (lua_State *L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save new discovered targets.
|
||||||
|
*
|
||||||
|
* This function can take a Vararg expression:
|
||||||
|
* A vararg expression that represents targets (IPs or Hostnames).
|
||||||
|
*
|
||||||
|
* Returns two values if it receives target arguments:
|
||||||
|
* The number of targets that were added, or 0 on failures.
|
||||||
|
* An error message on failures.
|
||||||
|
*
|
||||||
|
* If this function was called without an argument then it
|
||||||
|
* will simply return the number of pending targets that are
|
||||||
|
* in the queue (waiting to be passed to Nmap).
|
||||||
|
*
|
||||||
|
* If the function was only able to add a one target, then we
|
||||||
|
* consider this success. */
|
||||||
|
static int l_add_targets (lua_State *L)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
unsigned long ntarget = 0;
|
||||||
|
|
||||||
|
if (lua_gettop(L) > 0) {
|
||||||
|
for (n = 1; n <= lua_gettop(L); n++) {
|
||||||
|
if (!NewTargets::insert(luaL_checkstring(L, n)))
|
||||||
|
break;
|
||||||
|
ntarget++;
|
||||||
|
}
|
||||||
|
/* was able to add some targets */
|
||||||
|
if (ntarget) {
|
||||||
|
lua_pushnumber(L, ntarget);
|
||||||
|
return 1;
|
||||||
|
/* errors */
|
||||||
|
} else {
|
||||||
|
lua_pushnumber(L, ntarget);
|
||||||
|
lua_pushstring(L,
|
||||||
|
"Error: failed to add targets, post-scanning phase or no resources.");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* function called without arguments */
|
||||||
|
/* push the number of pending targets that are in the queue */
|
||||||
|
lua_pushnumber(L, NewTargets::insert(""));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the number of added targets */
|
||||||
|
static int l_get_new_targets_num (lua_State *L)
|
||||||
|
{
|
||||||
|
lua_pushnumber(L, NewTargets::get_number());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// returns a table with DNS servers known to nmap
|
// returns a table with DNS servers known to nmap
|
||||||
static int l_get_dns_servers (lua_State *L)
|
static int l_get_dns_servers (lua_State *L)
|
||||||
{
|
{
|
||||||
@@ -775,6 +828,8 @@ int luaopen_nmap (lua_State *L)
|
|||||||
{"have_ssl", l_get_have_ssl},
|
{"have_ssl", l_get_have_ssl},
|
||||||
{"fetchfile", l_fetchfile},
|
{"fetchfile", l_fetchfile},
|
||||||
{"timing_level", l_get_timing_level},
|
{"timing_level", l_get_timing_level},
|
||||||
|
{"add_targets", l_add_targets},
|
||||||
|
{"new_targets_num",l_get_new_targets_num},
|
||||||
{"get_dns_servers", l_get_dns_servers},
|
{"get_dns_servers", l_get_dns_servers},
|
||||||
{"is_privileged", l_is_privileged},
|
{"is_privileged", l_is_privileged},
|
||||||
{"resolve", l_resolve},
|
{"resolve", l_resolve},
|
||||||
|
|||||||
114
nselib/target.lua
Normal file
114
nselib/target.lua
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
---
|
||||||
|
-- Utility functions to add new discovered targets to Nmap scan queue.
|
||||||
|
--
|
||||||
|
-- The library lets scripts to add new discovered targets to Nmap scan
|
||||||
|
-- queue. Only scripts that run in the script pre-scanning phase
|
||||||
|
-- (prerule) and the script scanning phase (hostrule and portrule) are
|
||||||
|
-- able to add new targets. Post-scanning scripts (postrule) are not
|
||||||
|
-- allowed to add new targets.
|
||||||
|
--
|
||||||
|
-- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html
|
||||||
|
--
|
||||||
|
-- @args newtargets If specified, lets NSE scripts add new targets.
|
||||||
|
-- @args max-newtargets Sets the number of the maximum allowed
|
||||||
|
-- new targets. If set to 0 or less then there
|
||||||
|
-- is no limit. The default value is 0.
|
||||||
|
|
||||||
|
local type = type
|
||||||
|
local select = select
|
||||||
|
local unpack = unpack
|
||||||
|
local tonumber = tonumber
|
||||||
|
|
||||||
|
local stdnse = require "stdnse"
|
||||||
|
local nmap = require "nmap"
|
||||||
|
|
||||||
|
module ("target")
|
||||||
|
|
||||||
|
|
||||||
|
-- This is a special variable and it is a global one, so
|
||||||
|
-- scripts can check it to see if adding targets is allowed,
|
||||||
|
-- before calling target.add() function.
|
||||||
|
-- This variable will be set to true if the script argument
|
||||||
|
-- 'newtargets' was specified.
|
||||||
|
ALLOW_NEW_TARGETS = false
|
||||||
|
|
||||||
|
local newtargets, max_newtargets = stdnse.get_script_args("newtargets",
|
||||||
|
"max-newtargets")
|
||||||
|
if newtargets then
|
||||||
|
ALLOW_NEW_TARGETS = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if max_newtargets then
|
||||||
|
max_newtargets = tonumber(max_newtargets)
|
||||||
|
else
|
||||||
|
max_newtargets = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Local function to calculate max allowed new targets
|
||||||
|
local calc_max_targets = function(targets)
|
||||||
|
if max_newtargets > 0 then
|
||||||
|
local pushed_targets = nmap.new_targets_num()
|
||||||
|
if pushed_targets >= max_newtargets then
|
||||||
|
return 0
|
||||||
|
elseif (targets + pushed_targets) > max_newtargets then
|
||||||
|
return (max_newtargets - pushed_targets)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return targets
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Adds the passed arguments to the Nmap scan queue.
|
||||||
|
--
|
||||||
|
-- Only prerule, portrule and hostrule scripts can add new targets.
|
||||||
|
--
|
||||||
|
-- @param targets A variable number of targets. Target is a
|
||||||
|
-- string that represents an IP or a Hostname. If this function
|
||||||
|
-- is called without target arguments then it will return true
|
||||||
|
-- and the number of pending targets (waiting to be scanned).
|
||||||
|
-- @usage
|
||||||
|
-- local status, err = target.add("192.168.1.1")
|
||||||
|
-- local status, err = target.add("192.168.1.1","192.168.1.2",...)
|
||||||
|
-- local status, err = target.add("scanme.nmap.org","192.168.1.1",...)
|
||||||
|
-- local status, err = target.add(unpack(array_of_targets))
|
||||||
|
-- local status, pending_targets = target.add()
|
||||||
|
-- @return True if it has been able to add a minimum one target, or
|
||||||
|
-- False on failures and if no targets were added. If this
|
||||||
|
-- function is called without target arguments then it will
|
||||||
|
-- return true.
|
||||||
|
-- @return Number of added targets on success, or a string error
|
||||||
|
-- message in case of failures. If this function is called
|
||||||
|
-- without target arguments then it will return the number
|
||||||
|
-- of targets that are in the queue (waiting to be scanned).
|
||||||
|
add = function (...)
|
||||||
|
-- Force the check here, but it would be better if scripts
|
||||||
|
-- check ALLOW_NEW_TARGETS before calling target.add()
|
||||||
|
if not ALLOW_NEW_TARGETS then
|
||||||
|
stdnse.print_debug(3,
|
||||||
|
"Error: to add targets run with --script-args 'newtargets'")
|
||||||
|
return false, "Error: to add targets run with --script-args 'newtargets'"
|
||||||
|
end
|
||||||
|
|
||||||
|
local new_targets = {count = select("#", ...), ...}
|
||||||
|
|
||||||
|
-- function called without arguments
|
||||||
|
if new_targets.count == 0 then
|
||||||
|
return true, nmap.add_targets()
|
||||||
|
end
|
||||||
|
|
||||||
|
new_targets.count = calc_max_targets(new_targets.count)
|
||||||
|
|
||||||
|
if new_targets.count == 0 then
|
||||||
|
stdnse.print_debug(3,
|
||||||
|
"Warning: Maximum new targets reached, no more new targets.")
|
||||||
|
return false, "Warning: Maximum new targets reached, no more new targets."
|
||||||
|
end
|
||||||
|
|
||||||
|
local hosts, err = nmap.add_targets(unpack(new_targets,1,new_targets.count))
|
||||||
|
|
||||||
|
if hosts == 0 then
|
||||||
|
stdnse.print_debug(3, "%s", err)
|
||||||
|
return false, err
|
||||||
|
end
|
||||||
|
|
||||||
|
return true, hosts
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user