#!/usr/bin/python
# coding=utf-8

'''
 netsploit - a security research tool with shodan implementation
 Copyright (C) 2017 Carter Brainerd

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
'''

import re
import os
import sys
if (sys.version_info > (3, 0)):
    print "This program uses python 2.7, NOT python 3"
    sys.exit(2)
import urllib
import socket
import shodan
import platform
import readline
import traceback
from time import sleep
from random import randint
from subprocess import call  # For calling external programs
from optparse import OptionParser

NETSPLOIT_BASE = os.path.dirname(__file__)

parser = OptionParser()
parser.add_option("--init", action="store_false", dest="key_init", help="Re-enter your Shodan API key")
parser.add_option("-v", "--verbose", action="store_false", dest="verbose", help="Use verbose output")
(options, args) = parser.parse_args()

if options.key_init:
    with open(NETSPLOIT_BASE + "/util/keyget.py", 'r') as keygetfile:
        exec(keygetfile.read())  # This is super unsafe
        keygetfile.close()
        sys.exit(0)

if options.verbose:
  print "Checking for tools directory"
# Checks for tools directory
if not os.path.isdir(NETSPLOIT_BASE + '/tools'):
    call(['bash', 'setup.sh'])

# Tries to read the api key from a hidden file
# generated from the setup script
try:
    with open(NETSPLOIT_BASE + '/.api_key', 'r') as f:
        firstline = f.readline()
    f.close()
except:
    print "Couldn't locate api key, running ketget.py"
    with open(NETSPLOIT_BASE + "/util/keyget.py", 'r') as keygetfile:
        exec(keygetfile.read())
        keygetfile.close()

key = firstline.strip()
# Since the colors are not defined as variables yet
# we need to use the raw octal code for them
print "\033[96mStarting netsploit...\033[0m"
if len(key) < 32:
 print "\033[93mInvalid API key (too short)\033[0m"
 key = raw_input("What is your api key? ")
 os.remove(".api_key")
 with open(".api_key", 'w') as f:
    f.write(key)
 f.close()

api = shodan.Shodan(key)
try:
    # Check if API key is valid
    test = api.info()
except Exception as exc:
    print "\033[31m{}\033[0m".format(exc)
    sys.exit(0)
call(['clear'])
class bcolors:
    HEADER   =  '\033[95m'
    OKBLUE   =  '\033[34m'
    OKGREEN  =  '\033[32m'
    WARNING  =  '\033[93m'
    FAIL     =  '\033[31m'
    ENDC     =  '\033[0m'
    BOLD     =  '\033[1m'
    TITLE    =  '\033[96m'
    UL       =  '\033[4m'

# predefine commands for tab completion
cmds = ['search', 'exit', 'search_host', 'facets', 'help', 'myip', 'exec', 'banner', 'resolve',
'portscan', 'slowloris', 'ssl', 'mailsniff', 'heartbleed', '3d', '?', 'honeyscore', 'protocols',
'internet', 'cam', 'blacknurse', 'cfresolve', 'history', 'subbrute', 'tcpstream', 'smbserver', 'clear']

# Tab completion logic method
def completer(text, state):
    options = [i for i in cmds if i.startswith(text)]
    if state < len(options):
        return options[state]
    else:
        return None


# Set up tab completion
readline.parse_and_bind("tab: complete")
readline.set_completer(completer)


def clear():
    if "wind" in platform.platform():
        call(["cls"])
    else:
        call(["clear"])

# Some basic UI print functions, make it look a bit nicer
def print_msg(msg):
    """
        Print an informational message
    """
    print bcolors.OKBLUE + bcolors.BOLD + "[*] " + bcolors.ENDC + msg



def print_err(msg):
    """
        Print an error message
    """
    print bcolors.FAIL + bcolors.BOLD + "[!] " + bcolors.ENDC + str(msg)


def print_good(msg):
    """
        Print a success message
    """
    print bcolors.OKGREEN + bcolors.BOLD + "[+] " + bcolors.ENDC + msg


def vprint_msg(msg=''):
  """
      Only print message if verbose is on
  """
  if options.verbose:
    print bcolors.OKBLUE + bcolors.BOLD + "[*] " + bcolors.ENDC + msg
  else:
    return


def banner():
    """
        Print a random banner
    """
    banner1 =  bcolors.FAIL + bcolors.BOLD + '''
                  ____
                 /  @   \==]|[=(]               N E T S P L O I T ! !
                |--------|
                ==========       .  *                                     *
                ==========     .\ * . *.   *                         .    * \  .
               ||||||||||||      \ * ./  *    .   * SYN   ACK   SYN      .  \ \\
              |||||||||| --]%%%%%% .- =--=---=-=-=-=--=-=--=-==-----=-=-=-=-=-=
              [=========\  ]===========(  *         ACK   SYN   ACK     . /  /
             [==============|   / *  \    .                          *  *   /  .
             C| @ @ @ @ @ @ D         *      *                        *
              |              \           .                          *  *
            C| @  @ @  @ @ @  D       .
             |                 \          *                          *
           C| @  @  @  @  @  @  D
            |                    \
          C| @  @  @   @   @   @  D
           |                       \\
          |@@@@@@@@@@@@@@@@@@@@@@@@@|
           -------------------------

\033[0mBy thecarterb <0xCB[at]protonmail.com>
'''

    banner2 = bcolors.OKBLUE + bcolors.BOLD + '''
                 ____________________________________________________
                /                                                    \\
               |    _____________________________________________     |
               |   |                                             |    |
               |   |  bash$ ./netsploit                          |    |
               |   |                                             |    |
               |   |                                             |    |
               |   |                                             |    |
               |   |                                             |    |
               |   |                                             |    |
               |   |                                             |    |
               |   |                                             |    |
               |   |                                             |    |
               |   |                                             |    |
               |   |                                             |    |
               |   |                                             |    |
               |   |_____________________________________________|    |
               |                                                      |
                \_____________________________________________________/
                       \_______________________________________/
                    _______________________________________________
                 _-'    .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.  --- `-_
              _-'.-.-. .---.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.--.  .-.-.`-_
           _-'.-.-.-. .---.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-`__`. .-.-.-.`-_
        _-'.-.-.-.-. .-----.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-----. .-.-.-.-.`-_
     _-'.-.-.-.-.-. .---.-. .-----------------------------. .-.---. .---.-.-.-.`-_
    :-----------------------------------------------------------------------------:
    `---._.-----------------------------------------------------------------._.---'
    ''' + bcolors.ENDC

    banner3 = bcolors.OKGREEN + '''
                                NETSPLOIT
          _                      _______                      _
       _dMMMb._              .adOOOOOOOOOba.              _,dMMMb_
      dP'  ~YMMb            dOOOOOOOOOOOOOOOb            aMMP~  `Yb
      V      ~"Mb          dOOOOOOOOOOOOOOOOOb          dM"~      V
               `Mb.       dOOOOOOOOOOOOOOOOOOOb       ,dM'
                `YMb._   |OOOOOOOOOOOOOOOOOOOOO|   _,dMP'
           __     `YMMM| OP'~"YOOOOOOOOOOOP"~`YO |MMMP'     __
         ,dMMMb.     ~~' OO     `YOOOOOP'     OO `~~     ,dMMMb.
      _,dP~  `YMba_      OOb      `OOO'      dOO      _aMMP'  ~Yb._
     <MMP'     `~YMMa_   YOOo   @  OOO  @   oOOP   _adMP~'      `YMM>
                  `YMMMM\`OOOo     OOO     oOOO'/MMMMP'
          ,aa.     `~YMMb `OOOb._,dOOOb._,dOOO'dMMP~'       ,aa.
        ,dMYYMba._         `OOOOOOOOOOOOOOOOO'          _,adMYYMb.
       ,MP'   `YMMba._      OOOOOOOOOOOOOOOOO       _,adMMP'   `YM.
       MP'        ~YMMMba._ YOOOOPVVVVVYOOOOP  _,adMMMMP~       `YM
       YMb           ~YMMMM\`OOOOI`````IOOOOO'/MMMMP~           dMP
        `Mb.           `YMMMb`OOOI,,,,,IOOOO'dMMMP'           ,dM'
          `'                  `OObNNNNNdOO'                   `'
                                `~OOOOO~'   BLEEG BLERG, ALL YOUR PACKETS ARE BELONG TO US
    ''' + bcolors.ENDC

    banner4 = '''\033[033m""
    ^+xw*\"\"\"^q_  0 p" F  F _F  p^^"___jM   j  F              F
      _,,__   q x" [  F J_ J  P  w\"\"\"\"_  _,"  9  _m^`"*____x"    _____
 v,,_w"   "M_ @ `, ",_!u_9__L F #  r^""^^"    f j"      "      _*"   "6_
     _,,__  B 9_ "v,_Zp*\"\"\"\"\"^@u# P _m^"^u,a*"  j   ____       9       ""
   _F    `4 A_ "*-ap"            ^Lj" _smu,    _* ,-"   9_   _wf
 ^^"__,,_ jL  -- m<                5j! ____*-*^   &       \"\"\"\"     ___
   p"    9p`^u,av'       {}N E T{}     `,*\"\"\"\"q_   _x" _aa,_        p^\" \"\"u
 ,r  _____!L___,M     {}S P L O I T{}    Lsr--x_"^^`" qP     9      J      `M
   y^    "_    _J                    L_,,_ ?_    _#       ^v- -^"
  _F  __,_`^---"jr                  j___ ""y""^^""_,-r-u_
 r^ j!    ?s_, *"jp                g\"\"\"\"^q_b_    _F     "p      j^^""-w
    L  _,wma_  _x"jN__          __d\"\"\"^c  F  "-^""  _    "c____j'      L
   j" J"    \"\"\"  _F 99Nu______g**L_""s  4 A,    _P\"\"\"^q_    ""         "-
 m^  j_  _-^""mw^" _' # 9"N""L ^, "s  b #   "--^"      0
      @ j"   _v-wa+" ," j  #  p  r j qF "q_   _*-wu_   9,     y^`"^w_
   _,!  0_  f   _m-**" _F _F  L _FjP ?,    "^""    "u    "---^      j
 \"\"\"     # J   j"   p\"\"\"p-^ x^ p" d_   -q__a-mw_    j               `L
        V  `q  #   f   j   4   b   ^,   __      6_  ?,     _,__       "--
 *`^ww-"     F 9L_ b   1   4   `u_   "-^""*,    jh    ^-xm*"   9z
            )    0 `+a_ W__ 9,___"^^"+_     L   0                k
     _x-*v+"     9    0   "b    "_    "p   _0   `&    ___       d_

    {}'''.format(bcolors.ENDC, "\033[033m", bcolors.ENDC, "\033[033m", bcolors.ENDC)
    randnum = randint(1, 4)
    if randnum == 1:
        return banner1
    elif randnum == 2:
        return banner2
    elif randnum == 3:
        return banner3
    else:
        return banner4


####
#
#   These handle
#   the commands
#
####
def search(content, outfile=False, filename=''):
    """
        Do a basic shodan search
    """
    print_msg("Searching for {}".format(content))
    if outfile:
        print_msg("Outputting to \'{}\'".format(filename))
    else:
        print_msg("Printing to STDOUT")
    results = api.search(content)  # Search shodan
    if outfile:
        with open(filename, 'w') as outf:
            for result in results['matches']:
                outf.write(result['ip_str'] + "\n")
    else:
        for result in results['matches']:
            print_good(result['ip_str'])

# http://bit.ly/2lThKgm
def search_host(hostname, outfile=False, filename=''):
    """
        Search a host (ip) on Shodan.
    """
    if ".com" in hostname or ".net" in hostname or ".org" in hostname or ".io" in hostname:
        hstip = socket.gethostbyname(hostname)
        print_msg("Searching shodan for {}({})...".format(hstip, hostname))
        host = api.host(hstip)
    else:
        print_msg("Searching for {}".format(hostname))
        host = api.host(hostname)
    if outfile:
        print_msg("Outputting results to: %s" % filename)
    else:
        print_msg("Outputting results to STDOUT")

    if outfile:
        with open(filename, 'w') as outf:
            outf.write("IP: %s\n" % host['ip_str'])
            outf.write("Organization: %s\n" % host.get('org', 'n/a'))
            outf.write("Operating System: %s\n" % host.get('os', 'n/a'))
            for item in host['data']:
                outf.write("Port: %s\n" % item['port'])
                outf.write("Banner: %s\n" % item['data'])

    # print general information about host
    print_good("IP: %s" % host['ip_str'])
    print_good("Organization: %s" % host.get('org', 'n/a'))
    print_good("Operating System: %s" % host.get('os', 'n/a'))

    for item in host['data']:
        print """
                Port: %s
                Banner: %s
        """ % (item['port'], item['data'])


def facet_search(query):
    """
        Do a facet search on Shodan
    """
    # The list of properties we want summary information on
    FACETS = [
        'org',
        'domain',
        'port',
        'asn',

        # We only care about the top 5 countries, this is how we let Shodan know to return 5 instead of the
        # default 10 for a facet. If you want to see more than 10, you could do ('country', 1000) for example
        # to see the top 1,000 countries for a search query.
        ('country', 5),
    ]

    FACET_TITLES = {
        'org': 'Top 10 Organizations',
        'domain': 'Top 10 Domains',
        'port': 'Top 10 Ports',
        'asn': 'Top 10 Autonomous Systems',
        'country': 'Top 5 Countries',
    }

    try:
        # Generate a query string out of the params
        query = ' '.join(query)

        # Use the count() method because it doesn't return results and doesn't require a paid API plan
        # And it also runs faster than doing a search().
        result = api.count(query, facets=FACETS)

        print 'Shodan Summary Information'
        print 'Query: %s' % query
        print 'Total Results: %s\n' % result['total']

        # Print the summary info from the facets
        for facet in result['facets']:
            print FACET_TITLES[facet]

            for term in result['facets'][facet]:
                print '%s: %s' % (term['value'], term['count'])

            # Print an empty line between summary info
            print ''
    except Exception as e:
        print_err("Error: {}".format(str(e)))

# Doesn't use shodan, but it works well and it's fast
# the regex here is insane I wanted to kms doing it
def myip():
    """
        Gets the current WAN IP address
    """
    f = urllib.urlopen("http://www.canyouseeme.org/")
    html_doc = f.read()
    f.close()
    m = re.search('(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)',html_doc)
    print_good("Your IP is %s" % m.group(0))

# NOTE: I'm pretty sure that this doesn't work
def portscan(host, mini, maxi):
    print_msg("Scanning {}".format(host))
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    open_ports = 0
    for port in range(mini, maxi):
        vprint_msg("Scanning port {}".format(port))
        result = s.connect_ex((host, port))
        if result == 0:
            print_good("Open port: {}".format(port))
            open_ports += 1
    print_msg("{} has {} open ports.".format(host, open_ports))

def slowloris(tgt, port='80'):
    """
        Perform a slowloris attack on a given IP
    """
    print_msg("Attacking {} on port {}".format(tgt, port))
    call(['python', 'tools/slowloris/slowloris.py', tgt, '-ua', '-p', port])

# This function uses sslyze.
# sslyze should be put in the $PATH when setup.sh is run
def ssl(target, outfile=False, filename=''):
    """
        Use [sslyze](https://github.com/nabla-c0d3/sslyze) to analyze
        the ssl configuration of a web server
    """
    if not outfile:
        print_msg("Analyzing {}".format(target))
        print_msg("Printing to STDOUT")
        call(['sslyze', '--regular', target])
    else:
        print_msg("Analyzing {}".format(target))
        print_msg("Outputting to {}".format(filename))
        call(['sslyze', '--regular', target, ' > ', filename])

# I could use exec() here to read the .py file instead of running
# another instance of the interpreter, but this works for now
def mailsniff(interface, time):
    """
        Use [mail0wner](https://github.com/thecarterb/mail0wner) to sniff the LAN for email credentials
    """
    try:
        call(['sudo', 'python', 'tools/mail0wner/mail0wner.py', '-q', '-i', interface, '-t', time])
    except KeyboardInterrupt:
        print_err("Stopping sniff...")
        sleep(1)


def hb_test(target, outfile=False, filename=''):
    """
        Exploit heartbleed and print the memory response
    """
    if not outfile:
        call(['python', 'tools/heartbleed/hb-test.py', target])
    else:
        print_msg("Outputting to {}".format(filename))
        call(['python', 'tools/heartbleed/hb-test.py', '-f', filename, target])


def honey(ip):
    """
        Uses the shodan api to check if something is a honeypot
        Honeyscore can range from 0.0-1.0
    """
    try:
        score = api.labs.honeyscore(ip)
        if score == 1.0:
            print_good("{} is a honeypot!".format(ip))
        elif score > 0.5:
            print "{}[-]{}{ } is probably a honeypot.".format(bcolors.WARN, bcolors.ENDC, ip)
        elif score <= 0.5 and score != 0.0:
            print_msg("{} is probably not a honeypot.".format(ip))
        else:
            print_err("{} is not a honeypot.".format(ip))
        print_msg("{} honeyscore: {}".format(ip, score))
    except Exception as e:
        print_err("Could not determine honeyscore. ({})".format(e))


def protocols():
    """
        Shows account specifics about what you can filter for
    """
    try:
        prots = api.protocols()

        for name, description in iter(prots.items()):
            print_msg('{0:<30}'.format(name) + description)
    except shodan.APIError as e:
        print_err(str(e))

def subbrute(host, outfile=False, filename=''):
    """
        Bruteforces subdomains of a given domain with Sublist3r
    """
    if not outfile:
        print_msg("Enumerating {}'s subdomains".format(host))
        call(['python', 'tools/Sublist3r/sublist3r.py', '-d', host, '-v'])
    else:
        print_msg("Enumerating {}'s subdomains (Outputting results to text file)".format(host))
        call(['python', 'tools/Sublist3r/sublist3r.py', '-d', host, '-v', '-o', filename])


# Tcpdump the LAN
def dump(outfile=False, filename=''):
    """
        Use tcpdump to sniff packets on the LAN
    """
    try:
        if not outfile:
            call(['sudo', 'tcpdump'])
        else:
            call(['sudo', 'tcpdump', '-w', filename])
    except KeyboardInterrupt:
        return


####
#
#   This handles
#   the command prompt
#
####

def main():
    ban = banner()
    print ban
    history = ""
    ite = 1  # Iterator for the 'history' command
    import readline
    while True:
        try:
            user_in = raw_input(bcolors.UL + "netsploit{} > ".format(bcolors.ENDC))  # prompt
            user_in = user_in.strip()

            # These 3 lines implement the history command.
            # It first checks if the input is blank,
            # Then appends the command number and used command
            # To the 'history' string
            if not user_in == '':
                history += str(ite) + "  " + user_in + "\n"
                ite += 1

            if cmds[0] in user_in and not "_host" in user_in:  # search
                inarr = user_in.split(' ')
                if len(inarr) == 1:
                    print "\'search\' usage: search <query> [output_file]"
                elif len(inarr) == 2:
                    search(inarr[1])
                elif len(inarr) == 3:
                    search(inarr[1], True, inarr[2])

            elif cmds[1] in user_in:  # exit
                print_err("Exiting.")
                sys.exit(0)

            elif cmds[2] in user_in:  # search_host
                inarr = user_in.split(' ')
                if len(inarr) == 1:
                    print_msg("\'search_host\' usage: search_host <hostname> [outfilename]")
                elif len(inarr) == 2:
                    search_host(inarr[1])
                elif len(inarr) == 3:
                    search_host(inarr[1], True, inarr[2])

            elif cmds[3] in user_in: # facets
                inarr = user_in.split(' ')
                if len(inarr) == 1:
                    print_msg("\'facets\' usage: facets <search query>")
                else:
                    facet_search(inarr[1:])

            elif user_in == cmds[4] or user_in == "?": # help
                print """
Shodan commands:

  Command         Meaning
 ---------       ---------
  3d             Open shodan 3d in your browser
  facets         Gets top ports, services, companies, etc.
  honeyscore     Check if an ip is a honeypot or not (0.0 - 1.0)
  key            Display your shodan API key
  protocols      Show protocols you can scan
  search         Basic shodan search
  search_host    Search shodan for a given host


Networking commands:

  Command         Meaning
 ---------       ---------
  blacknurse     Perform a blacknurse attack on a given ip
  cam            Open a random camera in your web browser
  cfresolve      Attempt to resolve a domain protected by couldflare
  heartbleed     Determine if a server is vulnerable to heartbleed
  internet       Scan the whole internet on a given port (noisy)
  myip           Get your external IP
  mailsniff      Sniff the local network for email credentials
  resolve        Resolve the ip of a given hostname
  slowloris      Perform a slowloris attack on a target(IP)
  ssl            Do a scan of the targets SSL configuration
  subbrute       Use Sublist3r to enumerate subdomains of a given domain
  tcpstream      Output the tcp stream of the network
  smbserver      Start a SMB server to get LM/NTLM hashes from connecting clients
                 (password required)


Misc commands:

  Command         Meaning
 ---------       ---------
  banner         Print a starting banner
  clear          Clear the screen
  exec           Execute shell commands
  exit           Exit netsploit
  help           Print this help message
  history        Show all commands used since runtime
  ?              Alias for `help`

                """

            elif user_in == '':
                pass
            elif 'smbserver' in user_in:
                inarr = user_in.split(' ')
                if len(inarr) != 3:
                    print "\'smbserver\' usage: smbserver <sharename> <sharepath>"
                else:
                    call(['sudo', 'python', 'tools/impacket/examples/smbserver.py', inarr[1], inarr[2]])
            elif user_in == "clear":
                call(["clear"])
            elif user_in == cmds[5]:
                myip()
            elif cmds[6] in user_in:
                inarr = user_in.split(' ')
                call(inarr[1:])  # This doesn't really need its own function, as it's only used once
            elif user_in == cmds[7]:
                clear()
                ban = banner()
                print ban
            elif cmds[8] in user_in and not "cfresolve" in user_in:  # When I added `cfresolve`, it caused some confusion with this commmand
                inarr = user_in.split(' ')
                if len(inarr) < 2:
                    print "\'resolve\' usage: resolve <domain>"
                try:
                    print_good("{} is {}".format(inarr[1], socket.gethostbyname(inarr[1])))
                except Exception:
                    print_err("Could not resolve {}".format(inarr[1]))
            elif cmds[9] in user_in:  # portscan
                inarr = user_in.split(' ')
                if len(inarr) < 3:
                    print_msg("\'portscan\' usage: portscan <ip> <min port> <max port>")
                else:
                    portscan(inarr[1], int(inarr[2]), int(inarr[3]))
            elif cmds[10] in user_in:  # slowloris
                inarr = user_in.split(' ')
                if len(inarr) < 2 and not len(inarr) > 4:
                    print_msg("\'slowloris\' usage: slowloris <target IP> [port (default: 80)]")
                elif len(inarr) == 3:
                    try:
                        slowloris(inarr[1], inarr[2])
                    except KeyboardInterrupt:
                        continue
                else:
                    try:
                        slowloris(inarr[1])
                    except KeyboardInterrupt:
                        continue
            elif cmds[11] in user_in:  # ssl
                inarr = user_in.split(' ')
                if len(inarr) < 2:
                    print_msg("\'ssl\' usage: ssl <target> [outfilename]")
                elif len(inarr) == 2:
                    ssl(inarr[1])
                elif len(inarr) == 3:
                    ssl(inarr[1], True, inarr[2])
            elif user_in == "key":  # No function for this, but it's still an cool little command
                print_msg("Your Shodan API key is: {}".format(key))
            elif cmds[12] in user_in:  # mailsniff
                inarr = user_in.split(' ')
                if len(inarr) < 2:
                    print_msg("\'mailsniff\' usage: mailsniff <interface> <time>")
                elif len(inarr) == 2:
                    print_err("Not a full command!")
                    print_msg("\'mailsniff\' usage: mailsniff <interface> <time>")
                else:
                    mailsniff(inarr[1], inarr[2])
            elif cmds[13] in user_in:  # heartbleed
                inarr = user_in.split(' ')
                if len(inarr) < 2:
                    print_msg("\'heartbleed\' usage: heartbleed <target ip> [memdumpfile]")
                elif len(inarr) == 2:
                    hb_test(inarr[1])
                else:
                    hb_test(inarr[1], True, inarr[2])
            elif user_in == cmds[14]:  # 3d
                url = "https://simple.shodan.io/"
                call(['open', url])  # Only works if you have a GUI desktop (or $TERM is set idk)
            elif 'robots' in user_in:  # I was too lazy to fullt remove this, to fake error messages it is then :)
                inarr = user_in.split(' ')
                print_err("Unknown statement: robots")
            elif cmds[16] in user_in:  # honeyscore
                inarr = user_in.split(' ')
                if len(inarr) < 2:
                    print_msg("\'honeyscore\' usage: honeyscore <ip>")
                else:
                    honey(inarr[1])
            elif cmds[17] in user_in:
                protocols()
            elif cmds[18] in user_in:
                inarr = user_in.split(' ')
                if len(inarr) < 2:
                    print_msg("\'internet\' usage: internet <port> [outfilename]")
                elif len(inarr) == 2:  # internet
                    print_msg("Outputting to STDOUT.")
                    print("[" + bcolors.WARNING + "WARNING" + bcolors.ENDC + "] " + "This will produce a lot of data, it is recommended to output to a file.") # fo real
                    sleep(3)  # Wait for the reader to read the warning
                    call([NETSPLOIT_BASE + '/tools/zmap/src/zmap', '-p', inarr[1]])  # again, a function isn't really needed
                elif len(inarr) == 3:
                    print_msg("Outputting to {}".format(inarr[2]))
                    call(['zmap', '-p', port, '-o', inarr[2]])
            elif user_in == cmds[19]:
                call(['./tools/c4.sh'])
            elif cmds[20] in user_in:  # blacknurse
                inarr = user_in.split(' ')
                if len(inarr) < 2:
                    print_msg("\'blacknurse\' usage: blacknurse <ip>")
                else:
                    call(['./tools/blacknurse/blacknurse', inarr[1]])
            elif cmds[21] in user_in:  # cfresolve
                inarr = user_in.split(' ')
                if len(inarr) < 2:
                    print_msg("\'cfresolve\' usage: cfresolve <domain>")
                elif len(inarr) == 2:
                    call(['python', 'tools/cf-resolve.py', inarr[1]])
                else:
                    pass
            elif user_in == "history":
                print history
            elif cmds[23] in user_in:  # subbrute
                inarr = user_in.split(' ')
                if len(inarr) < 2:
                    print_msg("\'subbrute\' usage: subbrute <domain> [outfilename]")
                elif len(inarr) == 2:
                    subbrute(inarr[1])
                elif len(inarr) == 3:
                    subbrute(inarr[1], True, inarr[2 ])
            elif cmds[24] in user_in:
                inarr = user_in.split(' ')
                if len(inarr) == 1:
                    print_msg("Outputting to STDOUT")
                    print("[" + bcolors.WARN + "WARNING" + bcolors.ENDC + "] " + "This will produce a lot of data. Outputting to a file is recommended")
                    sleep(3)
                    dump()
                else:
                    print_msg("Outputting to {}".format(inarr[1]))
                    dump(True, inarr[1])

            else:
                print_err("Unknown statement: {}".format(user_in))
        except Exception as e:
            if options.verbose:
                print e
            else:
                print_err(e)
                traceback.print_exc(file=sys.stdout)
            pass
        except KeyboardInterrupt:
            print "\n"
            print_msg("Use \"exit\" to exit the program")
            pass



if __name__ == "__main__":
    main()
