progress_bar.update(len(buffy)) buffy = reader.read(self.chunk_size) write_str( "\r") # Add the carriage return after the tqdm progress bar. # Copy the actual stager and let it run. shell_exec("%s\r\n__EOF__" % self.stager_script, print_output=True, output_cleaner=lambda s: s.lstrip(" >")) @staticmethod def regexp(): return r"^\s*\!elf($| )" @staticmethod def usage(): write_str( "Usage: !elf [elf on the local machine] [program arguments]\r\n", LogLevel.WARNING) @staticmethod def name(): return "!elf" @staticmethod def description(): return "Runs an executable from the local machine in memory." register_plugin(RemoteElf)
with open(self.destination, 'wb') as f: with tqdm.tqdm(total=file_size, unit="o", unit_scale=True) as progress_bar: while bytes_read < file_size: chunk_size = min(4096, file_size - bytes_read) if check_command_existence("xxd"): data = shell_exec( "xxd -p -l%d -s%d %s" % (chunk_size, bytes_read, self.target_file), False) else: data = shell_exec( "od -vt x1 -N%d -j%d %s | awk '{$1=\"\"; print $0}'" % (chunk_size, bytes_read, self.target_file), False) data = re.sub(r"\r|\n|\r\n", "", data) # Strip newlines from output. data = bytearray.fromhex(data) progress_bar.update(chunk_size) bytes_read += chunk_size md5.update(data) f.write(data) md5sum = md5.hexdigest() remote_md5sum = shell_exec("md5sum %s |cut -d' ' -f1" % self.target_file) write_str( "\rLocal MD5: %s\r\nRemote MD5: %s\r\n" % (md5sum, remote_md5sum), LogLevel.WARNING) register_plugin(Download)
if self.target_file == "off": if context.log is None: write_str("This session is not currently logged.\r\n") elif self.disable_logging(): write_str("Logging has been disabled.\r\n") return # Enabling the logging if self.disable_logging() and self.fd: # First, close the current log file. write_str("This session will now be logged to %s.\r\n" % self.target_file) context.log = self.fd @staticmethod def regexp(): return r"^\s*\!log($| )" @staticmethod def name(): return "!log" @staticmethod def usage(): return "Usage: !log [filename] or !log off.\r\n" @staticmethod def description(): return "Toggles logging the harness' input and output to a file." register_plugin(LogCommand)
class Debug(Command): def __init__(self, *args, **kwargs): pass @staticmethod def regexp(): return r"^\s*!dbg($| )" @staticmethod def name(): return "!dbg" @staticmethod def description(): return "Prints debug information." @staticmethod def usage(): return "Usage: !dbg" def execute(self): write_str( "Current command prompt: %s\r\n" % context.active_session.input_driver.last_line.encode("UTF-8"), LogLevel.WARNING) register_plugin(GetOS) register_plugin(PtySpawn) register_plugin(Debug)
class RunShScript(RemoteScript): @staticmethod def regexp(): return r"^\s*\!sh($| )" @staticmethod def usage(): write_str( "Usage: !sh [script on the local machine] [script arguments]\r\n", LogLevel.WARNING) @staticmethod def name(): return "!sh" @staticmethod def description(): return "Runs a shell script from the local machine in memory." def _get_interpreter(self): return "sh" def _get_command_line(self): return "{interpreter} -s {args} <<'__EOF__'\r\n{script}\r\n__EOF__" # ----------------------------------------------------------------------------- register_plugin(RunPyScript) register_plugin(RunShScript)
def execute(self): # Create an askpass script shell_exec('cat <<\'__EOF__\' > %s\n#!/bin/bash\necho \'%s\'\n__EOF__\n' % (self.work_file, self.password)) shell_exec('chmod +x %s' % self.work_file) # Call sudo with the askpass script. # pass_command is used because sudo has a very weird behavior: # > SUDO_ASKPASS=/tmp/test.sh sudo -A id ; echo -n "AAAAAA" # [...] # sudoAAAAAA: 3 incorrect password attempts # The echo data is mangled with sudo's output which screws with FFM's internals. pass_command('SUDO_ASKPASS=%s sudo -A %s ; rm %s' % (self.work_file, " ".join(self.command), self.work_file)) @staticmethod def regexp(): return r"^\s*\!sudo($| )" @staticmethod def usage(): write_str("Usage: !sudo [password] [optional sudo arguments] command\r\n", LogLevel.WARNING) @staticmethod def name(): return "!sudo" @staticmethod def description(): return "Invoke sudo without a TTY." register_plugin(Sudo)
@staticmethod def usage(): write_str("Usage: !upload [local file] [remote destination]\r\n", LogLevel.WARNING) @staticmethod def name(): return "!upload" @staticmethod def description(): return "Uploads a file to the remote machine." def execute(self): with open(self.target_file, 'rb') as f: md5 = hashlib.md5() with tqdm.tqdm(total=os.stat(self.target_file).st_size, unit="o", unit_scale=True) as progress_bar: contents = f.read(2048) while contents: data = gzip.compress(contents) b64 = base64.b64encode(data) shell_exec("echo \"%s\" |base64 -d |gunzip >> %s" % (b64.decode("ascii"), self.destination)) md5.update(contents) progress_bar.update(len(contents)) contents = f.read(2048) md5sum = md5.hexdigest() remote_md5sum = shell_exec("md5sum %s |cut -d' ' -f1" % self.destination) write_str("\rLocal MD5: %s\r\nRemote MD5: %s\r\n" % (md5sum, remote_md5sum), LogLevel.WARNING) register_plugin(Upload)