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 "NmapOps.h"
|
||||
#include "nmap_error.h"
|
||||
#include "global_structures.h"
|
||||
|
||||
extern NmapOps o;
|
||||
|
||||
#ifndef NOLUA
|
||||
NewTargets *NewTargets::new_targets;
|
||||
#endif
|
||||
|
||||
TargetGroup::TargetGroup() {
|
||||
Initialize();
|
||||
}
|
||||
@@ -562,6 +567,97 @@ const std::list<struct sockaddr_storage> &TargetGroup::get_resolved_addrs(void)
|
||||
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
|
||||
checked (such as ping scanned) in advance. Randomize causes each
|
||||
group of up to lookahead hosts to be internally shuffled around.
|
||||
|
||||
@@ -96,6 +96,8 @@
|
||||
#define TARGETGROUP_H
|
||||
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "nmap.h"
|
||||
@@ -172,6 +174,52 @@ class TargetGroup {
|
||||
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 {
|
||||
public:
|
||||
HostGroupState(int lookahead, int randomize, char *target_expressions[],
|
||||
|
||||
22
nmap.cc
22
nmap.cc
@@ -445,6 +445,8 @@ int nmap_main(int argc, char *argv[]) {
|
||||
#ifndef NOLUA
|
||||
/* Pre-Scan and Post-Scan script results datastructure */
|
||||
ScriptResults *script_scan_results = NULL;
|
||||
/* Only NSE scripts can add targets */
|
||||
NewTargets *new_targets = NULL;
|
||||
#endif
|
||||
TargetGroup *exclude_group = NULL;
|
||||
char myname[MAXHOSTNAMELEN + 1];
|
||||
@@ -1608,6 +1610,7 @@ int nmap_main(int argc, char *argv[]) {
|
||||
open_nse();
|
||||
|
||||
if (o.script) {
|
||||
new_targets = NewTargets::get();
|
||||
script_scan_results = get_script_scan_results_obj();
|
||||
script_scan(Targets, 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
|
||||
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)
|
||||
break;
|
||||
delete hstate;
|
||||
@@ -1882,6 +1902,8 @@ int nmap_main(int argc, char *argv[]) {
|
||||
script_scan(Targets, SCRIPT_POST_SCAN);
|
||||
printscriptresults(script_scan_results, SCRIPT_POST_SCAN);
|
||||
script_scan_results->clear();
|
||||
delete new_targets;
|
||||
new_targets = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ extern "C" {
|
||||
#include "nmap_error.h"
|
||||
#include "NmapOps.h"
|
||||
#include "Target.h"
|
||||
#include "TargetGroup.h"
|
||||
#include "portlist.h"
|
||||
#include "service_scan.h"
|
||||
#include "nmap_rpc.h"
|
||||
@@ -681,6 +682,58 @@ static int l_get_timing_level (lua_State *L)
|
||||
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
|
||||
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},
|
||||
{"fetchfile", l_fetchfile},
|
||||
{"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},
|
||||
{"is_privileged", l_is_privileged},
|
||||
{"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