Busy Administrator's Toolbox - Search Optimizer for Network and Application Resources
#!/usr/bin/python | |
import argparse | |
import os, sys | |
import subprocess | |
import re | |
from os import listdir | |
from os.path import isfile, join, isdir, exists | |
NAME = "Search Optimizer for Network and Application Resources" | |
EPILOG = """ | |
example usage: | |
batsonar -r1 192.168.0.1/24 (recipe 1) | |
batsonar -r1,2,3 -a1,2,3 -p- 192.168.0.5 (recipes 1, 2 & 3 on all ports) | |
batsonar -r1 -o xml 192.168.0.7 (xml output format) | |
batsonar -x -r1 192.168.0.1 (execute query) | |
batsonar -R (show recipes) | |
batsonar -A (show additional options) | |
batsonar -S (show scripts) | |
\n | |
""" | |
RECIPES = { | |
'0': [' '], # empty recipe | |
'1': ['-A'], | |
'2': ['-sV'], | |
'3': ['-F', '-A'], | |
'4': ['-sV', '--version-intensity 9'], | |
'5': ['-sS', '-sU', '-A'], | |
'6': ['-A', '-v'], | |
'7': ['-A', '-O'], | |
'8': ['-sN'], | |
'9': ['-sF'], | |
'10': ['-sX'], | |
'11': ['-sO'], | |
'12': ['-sR'], | |
'13': ['-sU'], | |
'14': ['-sP'], | |
'15': ['-sA'], | |
'16': ['-sT'], | |
'17': ['-sP', '-PP'], | |
'18': ['-sP', '-PM'], | |
'19': ['-O', '--osscan-guess'], | |
'20': ['-A', '-O', '--osscan-guess'], | |
'21': ['-PY'], | |
'22': ['--scanflags SYNURG'], | |
'23': ['-PO'], | |
'24': ['-sP', '-PR'], | |
'25': ['-sP', '-PS'], | |
'26': ['-n', '-T4', '-sP', '-PE', '-PS21,22,23,25,80,113,31339', '-PA80,113,443,10042'] | |
} | |
ADDITIONAL = { | |
'1': ['-F'], | |
'2': ['-A'], | |
'3': ['-v'], | |
'4': ['-p-'], | |
'5': ['-n'], | |
'6': ['-vv'], | |
'7': ['-n', '-v'], | |
'8': ['-PN'], | |
'9': ['--stats-every 5s'], | |
'10': ['--stats-every 10s'], | |
'11': ['-sV'], | |
'12': ['-r'], | |
'13': ['--open'], | |
'14': ['-T4'], | |
'15': ['-sS'], | |
'16': ['-n', '--stats-every 10s'], | |
'17': ['-n', '-p-', '--stats-every 10s'], | |
'18': ['-n', '-p-', '-vv'], | |
'19': ['--top-ports 100'], | |
'20': ['--top-ports 500'], | |
'21': ['--top-ports 1000'], | |
'22': ['-n', '-v', '-r'], | |
'23': ['-n', '-p-', '-r'], | |
'24': ['--reason'], | |
'25': ['-T4', '-n', '--stats-every 10s'] | |
} | |
SCRIPTS = { | |
'1': ['--script version,discovery'], | |
'2': ['--script vuln'], | |
'3': ['--script auth'], | |
'4': ['--script default'], | |
'5': ['--script safe'], | |
'6': ['--script http*'], | |
'7': ['--script broadcast', '--script-args targets-sniffer.timeout 30'], | |
'8': ['--script ipidseq', '-n'], | |
'9': ['--script http-methods', '--script-args http-methods.retest'], | |
'10': ['--script sniffer-detect'], | |
'11': ['--script telnet*'], | |
'12': ['--script jdwp*'], | |
'13': ['--script sshv'], | |
'14': ['--script http-phpself-xss,http-unsafe-output-escaping', '--script-args httpspider.maxpagecount=200'], | |
'15': ['--script http-slowloris-check'], | |
'16': ['--script mysql*'], | |
'17': ['--script oracle*'], | |
'18': ['--script ms-sql*'], | |
'19': ['--script mongodb*'], | |
'20': ['--script couchdb*'], | |
'21': ['--script smtp*'], | |
'22': ['--script imap*'], | |
'23': ['--script smb*'], | |
'24': ['--script ftp*'], | |
'25': ['--script irc*'] | |
} | |
def call(line): | |
subprocess.call(line, shell=True) | |
def fsafe(fname): | |
return fname.replace('/','|') | |
def prepare_dir(dir_name): | |
dir_name = fsafe(dir_name) | |
if not os.path.exists(dir_name): | |
print "[*] Creating directory: %s" % dir_name | |
os.makedirs(dir_name) | |
def option_show_recipes(): | |
option_show_dict(RECIPES, 'r') | |
def option_show_dict(d, prefix): | |
keys = d.keys() | |
keys.sort(key=int) | |
if len(keys) > 0: | |
print '\n' + '-'*20 + ' Options ' + '-'*20 + '\n' | |
for k in keys: | |
v = d[k] | |
print " -%s%s\t\t%s" % (prefix, k, ' '.join(sorted(v))) | |
print '' | |
def get_option_list(source, query): | |
return source[str(query)] | |
def get_main_query(recipe, additional, ports=None, script=None): | |
recipe_option_list = get_option_list(RECIPES, recipe) | |
additional_options_list = [] | |
ports_list = [] | |
script_option_list = [] | |
for additional_option in additional: | |
additional_options_list += get_option_list(ADDITIONAL, additional_option) | |
if script is not None: | |
script_option_list = get_option_list(SCRIPTS, script) | |
if ports is not None: | |
if "all" in ports: | |
ports_list = ['-p-'] | |
elif "top" in ports: | |
ports_list = ['--top-ports 1000'] | |
else: | |
ports_list = ['-p' + ports] | |
main_options_list = recipe_option_list + additional_options_list + ports_list + script_option_list | |
main_options_list = list(set(main_options_list)) | |
main_options_list.sort() | |
main_query = ' '.join(main_options_list) | |
main_query = re.sub(' +', ' ', main_query) | |
return main_query | |
def option_show_port_options(): | |
print 'Port options: -p- or -p80,443 or -p all or -p top\n' | |
def option_show_additional_options(): | |
option_show_dict(ADDITIONAL, 'a') | |
def option_show_scripts(): | |
option_show_dict(SCRIPTS, 's') | |
def argsplit(string): | |
try: | |
return_list = string.split(',') | |
return map(int, return_list) | |
except Exception: | |
return [] | |
def view_mode(target): | |
# open folder | |
# read all files | |
# display list of files with numbers | |
# accept input | |
# then do less -N <filename> | |
mypath = fsafe(target) | |
if exists(mypath) and isdir(mypath): | |
results = [ f for f in listdir(mypath) if isfile(join(mypath,f)) ] | |
if results: | |
while True: | |
print "\n(0)\t\tAll" | |
for idx, val in enumerate(results): | |
print "(%s)\t\t%s" % (idx + 1, val.replace('|', '/')) | |
print "(x)\t\tExit\n" | |
number = -1 | |
while number < 0: | |
try: | |
number = raw_input('>>> ') | |
if number == 'x': | |
return | |
number = int(number) | |
if number > len(results): | |
raise | |
except Exception: | |
number = -1 | |
if number == 0: | |
command = "cat " | |
for current_file in results: | |
command += "'%s'/'%s' " % (mypath, current_file) | |
command += " | less -N" | |
call(command) | |
else: | |
current_file = results[number - 1] | |
call("less -N '%s'/'%s'" % (mypath, current_file)) | |
else: | |
print 'No data for %s' % target | |
else: | |
print 'No data for %s' % target | |
return | |
def process_args(): | |
parser = argparse.ArgumentParser(description=NAME, | |
epilog=EPILOG, | |
formatter_class=argparse.RawTextHelpFormatter) | |
parser.add_argument("target", nargs="?", help="Target/s") | |
parser.add_argument("-r", "--recipe", nargs="?", type=str, help="Recipe/s") | |
parser.add_argument("-p", "--ports", nargs="?", type=str, help="Port/s") | |
parser.add_argument("-a", "--additional", nargs="?", type=str, help="Additional Option/s") | |
parser.add_argument("-s", "--scripts", nargs="?", type=str, help="Script/s") | |
parser.add_argument("-R", "--show-recipes", action="store_true", help="Show Recipes") | |
parser.add_argument("-P", "--show-port-options", action="store_true", help="Show Port Options") | |
parser.add_argument("-A", "--show-additional-options", action="store_true", help="Show Additional Options") | |
parser.add_argument("-S", "--show-scripts", action="store_true", help="Show Scripts") | |
parser.add_argument("-x", "--execute", action="store_true", help="Execute Command") | |
parser.add_argument("--grep", action="store_true", help="Output in grep format") | |
parser.add_argument("--xml", action="store_true", help="Output in xml format") | |
args = parser.parse_args() | |
B = (False, True) | |
show_recipes = B[args.show_recipes] | |
show_port_options = B[args.show_port_options] | |
show_additional_options = B[args.show_additional_options] | |
show_scripts = B[args.show_scripts] | |
execute = B[args.execute] | |
if show_recipes: option_show_recipes() | |
if show_port_options: option_show_port_options() | |
if show_additional_options: option_show_additional_options() | |
if show_scripts: option_show_scripts() | |
if show_recipes or show_port_options or show_additional_options or show_scripts: | |
sys.exit(0) | |
recipes = argsplit(args.recipe) or [] | |
additional = argsplit(args.additional) or [] | |
scripts = argsplit(args.scripts) or [] | |
ports = args.ports or None | |
target = args.target or None | |
if (target) and (not recipes) and (not additional) and (not scripts) and (not ports): | |
view_mode(target) | |
sys.exit(0) | |
output = 'default' | |
if args.xml: | |
output = 'xml' | |
elif args.grep: | |
output = 'grep' | |
if len(recipes) == 0: | |
recipes.append(0) | |
if len(recipes) > 0 and target is None: | |
print '[-] Target is required. (e.g. 192.168.0.20 or 192.168.0.1/24)' | |
print '[*] Use -h option (help)\n' | |
sys.exit(1) | |
for recipe in recipes: | |
if len(scripts) == 0: | |
command = generate_command(recipe, | |
target=target, | |
additional=additional, | |
ports=ports, | |
output=output) | |
process_command(target, command, execute) | |
else: | |
for script in scripts: | |
command = generate_command(recipe, | |
target=target, | |
additional=additional, | |
ports=ports, | |
script=script, | |
output=output) | |
process_command(target, command, execute) | |
def process_command(target, command, execute=False): | |
if execute: | |
print "[*] Executing: %s\n" % command | |
prepare_dir(target) | |
call(command) | |
else: | |
print command | |
def generate_command(recipe, target=None, additional=[], ports=None, script=None, output='default'): | |
c_main_query = get_main_query(recipe, additional, ports, script) | |
c_target = target or '' | |
output_key = '-oN' | |
if output == 'grep': | |
output_key = '-oG' | |
elif output == 'xml': | |
output_key = '-oX' | |
c_output = "%s '%s'/'nmap %s %s'" % (output_key, fsafe(c_target), c_main_query, fsafe(c_target)) | |
command = "nmap %s %s %s" % (c_main_query, c_output, c_target) | |
return command | |
def main(): | |
process_args() | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment