1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
|
This file contains some basic examples on how to use the
internal libraries included with NDiff to do useful things
with nmap data in Perl.
This is just a starter - not all classes and methods are discussed
here. Read the source.
-----------------------------------------------------------------
DataStore.pm: handles external representations of nmap data
1. reading nmap data
TODO: There appears to be some redundancy of methods with respect to
prepare_tag() below.
use PortScan::DataStore;
use Carp;
# define some tag associated with the ScanSet (results set)
my $input_tag = "10.0.1-net-30May";
# pass the tag through prepare_tag() to evaluate any embedded % substitutions
my $prepared_input_tag = PortScan::DataStore::prepare_tag( $input_tag );
# now generate a data store attached to the tag
my( $processed_input_tag, $input_data_store )
= PortScan::DataStore::data_store_for( $prepared_input_tag );
# now retrieve the PortScan::ScanSet (results set) associated with the tag
my $input_scanset = $input_data_store->retrieve_scanset( $processed_input_tag );
# failed if $input_scanset is not defined
croak "can't get input scanset" if !defined $input_scanset;
-----------------------------------------------------------------
DataStore.pm:
2. writing nmap data
use PortScan::DataStore;
use Carp;
# read in or generate a ScanSet...
my $scan_set = ...
# ... manipulations on the ScanSet...
# now prepare to write the ScanSet...
# define some tag associated with the ScanSet (results set)
my $output_tag = "10.0.1-net-30May-processed";
# pass the tag through prepare_tag() to evaluate any embedded % substitutions
my $prepared_output_tag = PortScan::DataStore::prepare_tag( $output_tag );
# associate the tag with the ScanSet
$scan_set->tag( $output_tag );
# now generate a data store attached to the tag
my( $processed_output_tag, $output_data_store )
= PortScan::DataStore::data_store_for( $prepared_output_tag );
# now retrieve the PortScan::ScanSet (results set) associated with the tag
my $result = $output_data_store->put_scanset( $scan_set );
croak "couldn't write scanset $prepared_output_tag" if $result != 0;
-----------------------------------------------------------------
ScanSet.pm: container for a set of hosts all scanned at the same time
use ScanSet;
use PortSpec;
# normally one retrieves a ScanSet from a DataStore but it is
# possible one would generate one programmatically as well
#
# see ScanSet.pm for description of the values passed in the
# constructor...in this example will set them after construction
my $set = new PortScan::ScanSet( "", {}, {}, {} );
# associate a tag with the set
$set->tag( "syn-scan-Thursday" );
# add one or more scanned ports to the master set
# each host contained in a ScanSet is assumed to have had
# this master set of ports scanned
$set->add_scanned_port( new PortScan::PortSpec( 80, 'open', 'tcp', "", "", "", "" ) );
$set->add_scanned_port( new PortScan::PortSpec( 22, 'open, 'tcp', "", "", "", "" ) );
$set->add_scanned_port( new PortScan::PortSpec( 43, 'closed', 'udp', "", "", "", "" ) );
# add a few hosts to the set
# normally one might have added some ports to the hosts
$set->add_host( new PortScan::ScannedHost( undef, {}, '192.168.2.3', 'closed' ) );
$set->add_host( new PortScan::ScannedHost( undef, {}, '192.168.2.4', 'closed' ) );
$set->add_host( new PortScan::ScannedHost( undef, {}, '192.168.2.123', 'closed' ) );
$set->add_host( new PortScan::ScannedHost( undef, {}, '192.168.2.200', 'closed' ) );
# oops, need to remove one
$set->remove_host( '192.168.2.200' );
# retrieve a host for some reason
my $check = $set->get_host( '192.168.2.200' );
# will return undef if not found
print "not found" if ! defined $check;
# print out all hosts
my @hosts = $set->hosts_sorted_list;
foreach my $h ( @hosts )
{
# do something...
# $h is an instance of PortScan::ScannedHost
}
-----------------------------------------------------------------
ScannedHost.pm: encapsulates the information about a host scanned with nmap
use PortScan::ScannedHost;
use PortScan::PortSpec;
# create a new ScannedHost instance
my $host = new PortScan::ScannedHost( undef, {}, "10.0.1.12", "closed" );
# "closed" is the "Ignored State" in nmap terms. All ports not
# explicitly added to the host, but which exist in the hosts's
# owner-ScanSet master set, will have this Ignored State applied to it.
#
# Nmap models the information this way to save space during runtime and
# in results display and storage. The "interesting ports" listed for a
# given host are the exceptions to the Ignored State. The Ignored State
# applies only to the remaining ports which were scanned, which is
# the ScanSet's master set minus those interesting ports.
# add a PortScan::PortSpec instance
$host->add_port( new PortScan::PortSpec( 80, "open", "tcp", "", "", "", "" ) );
# add some ports using a slightly more convenient method
$host->set_port( 22, "open", "tcp", "", "", "", "" );
$host->set_port( 43, "open", "tcp", "", "", "", "" );
$host->set_port( 43, "filtered", "udp", "", "", "", "" );
# remove a port, which are referenced by opaque keys defined
# by PortScan::PortSpec
$host->remove_port( PortScan::PortSpec::make_key( 80, "tcp" ) );
# retrieve a port, or undef
# note that ScannedHost methods use ( proto, port ) while PortSpec
# methods use ( prot, proto ). Mea culpa.
my $port = $host->get_port( "tcp", "80" );
carp "no such port" if ! defined $port;
# get a hashref of all ports contained
my $specs = $host->port_specs();
# iterate over the hash of specs and do something
while my( $key, $pspec ) = each %$specs
{
# do something with each $pspec, which is an instance of PortScan::PortSpec
# $key is an opaque key created by PortScan::PortSpec, but can always be
# split into ( port, proto ) by PortScan::PortSpec::decode_key
my( $port, $proto ) = PortScan::PortSpec::decode_key( $key );
}
# get the sorted list of ports contained and iterate over them
my $sorted_specs = $host->port_specs_sorted_list
foreach my $pspec ( @sorted_specs )
{
# do something...$pspec is a PortScan::PortSpec instance
}
# get the state associated with some port, but only if explicitly
# inserted into the host (the ScannedHosts's owner/ScanSet is not checked)
# will return the psuedo-state "unknown" if the port isn't found.
my $state = $host->get_state( "tcp", 22 );
print "tcp/22 -> '$state'\n";
-----------------------------------------------------------------
PortSpec.pm: Encapsulates the properties of a "port", in the general
sense for TCP and UDP
use PortScan::PortSpec;
use PortScan::ScannedHost;
# generate a PortSpec
my $spec = new PortScan::PortSpec( 80, "open", "tcp", "", "", "", "" );
# the four trailing parameters are defined by nmap and require some
# further research by documentation. The second of the four is
# the well-known service name.
# insert the spec into a ScannedHost instance
$some_host->add_port( $spec );
# make a copy of the PortSpec
my $spec2 = $spec->clone();
# query the members and print
print "port number: " . $spec->number();
print "port state: " . $spec->state();
print "port proto: " . $spec->proto();
print "port service: " . $spec->service();
print "port user1: " . $spec->u1();
print "port user2: " . $spec->u2();
print "port user3: " . $spec->u3();
# for internal use of ndiff, map the state to
# a canonical uppercase single-character code
my $code = $spec->state_sm;
print "open" if $code eq "O";
print "closed" if $code eq "C";
print "filtered" if $code eq "F";
...
# print out a canonical key for the well-known service name
print "service for port http/tcp: "
. PortScan::PortSpec::spec->known_port_by_name( "http", "tcp" );
# print out a canonical key for the well-known port number
print "service for port 80/tcp: "
. PortScan::PortSpec::spec->known_port_by_number( 80, "tcp" );
-----------------------------------------------------------------
TODO:
IPAddress.pm
ScanComparison.pm
NmapFile.pm
ScanContext.pm
SetOps.pm
|