2.9. Merging NmapScanner objects¶
There may be situations where several NmapScanner
instances may be instantiated separately, so a merge()
is available to
merge scans. It must be called after the instance finishes the scan, and it accepts any number of other NmapScanner
instances
plus additional **kwargs
:
merge_tcp=True
: Flag to allow TCP mergingmerge_udp=True
: Flag to allow UDP mergingmerge_scripts=True
: Flag to merge host scripts. TCP/UDP port scripts are merged if their respective flag isTrue
.merge_trace=True
: Merge Traceroute information.merge_os=True
: Merge OS information.merge_non_scanned=True
: Merge IPs that could not be scanned.
2.9.1. merge()
deep inspect¶
The merge()
method acts differently depending on a main condition, which is: “Does the instance that’s calling the method have the target X?”. Depending on the answer:
- If the target is not in the caller scanner, all the information from the target is copied depending on the
**kwargs
flags values. - If the target is on the caller scanner, the information is copied depending on the flags, particularly:
- TCP/UDP ports are copied if they where not scanned on the caller scan, but if the caller already has information about them, it’s not overwritten.
- OS information, as well as Host scripts are checked one by one, only adding them if the caller does not have information of a particular OS/script.
- Traceroute is only added while no Traceroute information is in the caller scanner.
2.9.2. Example 1: Dividing TCP and UDP scans¶
import nmapthon as nm
# Run a TCP scan synchronously and a UDP async to the same target
main_scanner = nm.NmapScanner('10.10.10.2', ports=[22, 80, 443], arguments='-sV -sS -n')
udp_scanner = nm.AsyncNmapScanner('10.10.10.2', ports=[21, 53], arguments='-sU -n', mute_error=True)
# Launch the UDP first
udp_scanner.run()
# Launch the TCP
try:
main_scanner.run()
except nm.NmapScanError as e:
print('Error while scanning TCP ports:\n{}'.format(e))
# Wait until UDP ends
udp_scanner.wait()
if udp_scanner.finished_successfully():
# Merge the scans (Do not need to set all flags to False since there is no information on the UDP scanner,
# but just to show the usage thay are set to False here
main_scanner.merge(udp_scanner, merge_os=False, merge_scripts=False, merge_tcp=False, merge_trace=False)
2.9.3. Example 2: Multi-threading/processing scans¶
import nmapthon as nm
import multiprocessing
def read_ips(ips_file):
with open(ips_file) as f:
return [x.strip() for x in f.readlines()]
def worker(n, ip, return_dict):
sc = nm.NmapScanner(ip, ports=[1-1000], arguments='-sT -sV -T4 -n')
try:
sc.run()
except nm.NmapScanner as e:
raise e
return_dict[n] = sc
if __name__ == '__main__':
# Create share dict to store scans
manager = multiprocessing.Manager()
return_dict = manager.dict()
jobs = []
# Read IPS from file
ips = read_ips('my_ips_file.txt')
for i in range(len(ips)):
p = multiprocessing.Process(target=worker, args=(i, ips[i], return_dict))
jobs.append(p)
p.start()
# Freeze application until all apps finish
for proc in jobs:
proc.join()
# Take the first scanner as caller
main_scan = return_dict[0]
# Pass the rest of the scans as arguments for merging
main_scan.merge(*list(return_dict.values())[1:])
# Now you can use the main_scan as a single scanner with all the information
for host in main_scan:
# Continue normally