def ConnectAndPerformCommands(hostname, port, username, password, commands): try: client = paramiko.SSHClient() client.load_system_host_keys() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(hostname=hostname, port=port, username=username, password=password) PrintBlueAndLog( f"Successfully established ssh connection to {hostname}") if commands and len(commands) > 0: for command in commands: PrintAndLog(f"Running command remotely: {command}") stdin, stdout, stderr = client.exec_command(command) output = stdout.read().strip().decode().splitlines() responseText = "Command Executed, remote machine response:\n" for line in output: responseText = f"{responseText}\n" \ f" {line}" PrintAndLog(f"{responseText}\n") except Exception as ex: PrintRedAndLog( f"Failed attempting to connect to remote host, exception encountered:\n" f" {ex}\n") finally: PrintBlueAndLog(f"Finished running commands, close connection") client.close()
def RunSubProcess(commandLineInput): try: PrintBlueAndLog(f"Running shell command: {commandLineInput}") result = subprocess.run(commandLineInput, shell=True, check=True, stdout=subprocess.PIPE) PrintAndLog(result.stdout.decode('utf-8')) except Exception as ex: PrintAndLog(f"Failed execute bash command '{commandLineInput}', exception encountered:\n") PrintRedAndLog(ex)
def HelpRequested(self): PrintAndLog( "\n" " asyncforeach works like foreach but receives an additional parameter processCount " "indicating the amount of processes the workload will be split" " asyncforeach receives a command with keys that need to be replaced and a list of key value " "pairs and creates commands of all the possible replacements for keys in the original command " "with key value options\n" " Command parameters: [command] [processCount] [keyValuePairType] [keyValuePairs]" " [keyValuePairs]...\n" " 'command' - The command that will be run. The command must be encased in" "quotations and must have keys that will be replaced matching the key in the key value pairs\n" " 'processCount' - the amount of processes the commands created will run on" " 'keyValuePairType' - Can be either -p or -f:" " '-p' - indicating the key value pair will be a key, an equals " "sign and a list divided by commas\n" " '-f' - indicating the key value pair will be a key, an quals" "sign and a url to a list of values divided by commas\n" " 'keyValuePair' - a key which will be replaced in the command and a list" "of values seperated by commas, a command option will be generated for each permutation available " "of key value pairs\n\n" " for example: foreach -p 'custombash echo x' x='1,2,3' will result in three commands " "replacing x with 1, 2 and 3\n" " additional example: foreach -p 'custombash echo x y' x='1,2,3' y='4,5,6 will result in 9" "commands that will be executed for all the replacements of x and y with 1, 2, 3 and 4, 5, 6" "respectively")
def HelpRequested(self): return PrintAndLog( "\n" " Performs the curl command to get a file into the terminal\n" " retrievefile [fileURL]\n" " 'fileURL' - the URL to the file being downloaded\n" )
def HelpRequested(self): return PrintAndLog( "\n" "Changes the password for a user\n" " changeuserpassword [NewPassword] [User]\n" " 'NewPassword' - the new password that will be set for user\n" " 'User' - the username of the user\n")
def Execute(self): if self.CheckHelpRequested(): return if self.CheckMinimunRequiredParameters(2): return requestType = self.request[0] filePath = self.request[1] if requestType != "-r" and requestType != "-p": PrintRedAndLog(f"Unsupported requestType {requestType}") return if requestType == "-p": if filePath not in GetAllPreMadeBatchNames(): PrintRedAndLog(f"No such PreMade batch command: '{filePath}'") return filePath = f"{PreMadeBatchCommandsPath}{filePath}" try: with open(filePath, "r") as file: commandLines = list( filter(lambda a: not a.startswith('#'), list(file.read().splitlines()))) PrintAndLog( f"Adding {len(commandLines)} Commands from {ntpath.basename(filePath)}" ) self.context.CommandQueue.EnqueueCommandsNext(commandLines) file.close() except Exception as ex: print( f"Failed to load command batch file, exception encountered:\n") PrintRedAndLog(ex)
def HelpRequested(self): return PrintAndLog( "\n" " Stops a service with provided name.\n" " stopservice [ServiceName]\n" " 'ServiceName' - The name of the service being stopped" )
def HelpRequested(self): PrintAndLog( "\n" " Upgrade downloads and installs the latest stable version of Attack Agent, ensures " "Attack Agent Permissions are set and the $PATH variable is updated.\n" " Currently Attack Agent Upgrade is only supported on Linux machines." )
def HelpRequested(self): return PrintAndLog( "\n" " Clones a public git repository'\n" " gitclone [path] [cloneDestination=optional]\n" " 'path' = the full clone url\n" " 'cloneDestination' = an optional path indicating the destination to clone to\n" )
def HelpRequested(self): PrintAndLog( "\n" " Async creates a new process and runs a provided command on that process. The " "provided command can be a scenario command\n" " async [command]\n" " 'command' - The command that will be run in a new process\n" )
def printHelpInfo(freeText, commandTree): text = f"{freeText}\n" \ " The available commands under this category are:\n\n" for command in CommandMappingNameByTree[commandTree]: text = f"{text}" \ f" {command}\n" text = f"{text}\n" \ f" Type -help with a command type of the listed commands to get additional information on that command" PrintAndLog(text)
def HelpRequested(self): return PrintAndLog( "\n" " Creates a file or directory'\n" " createfile [creationType] [path]\n" " creationType options:\n" " '-f' - Create single empty file\n" " '-f-bus' - Create single empty file on the d-bus\n" " '-d' - Create a single empty directory\n")
def HelpRequested(self): PrintAndLog( "\n" " A for loop on the provided function\n" " Command parameters: [Repetitions] [function]\n" " 'Repetitions' - An integer indicating the amount of " "times to perform the provided function\n" " 'function' - an Attack Agent function surrounded " "by parentheses that will be repeated in the loop\n")
def WaitForInput(): if not RunningOnPermittedMachine(): PrintRedAndLog("Not running on non Ariots permitted machine. Exiting") return PrintAndLog( "Hello, Welcome to the Linux based ArIoTS Attack Agent. Type --help at any stage for more information" ) while True: EnqueueAndRun( input("\nPlease enter your next command, type help for options\n"))
def HelpRequested(self): return PrintAndLog( "\n" " Deletes a file or directory'\n" " deletefiles [deleteType] [path]\n" " deleteType options:\n" " '-f' - Delete single file\n" " '-d' - Delete entire directory and all its contents\n" " 'path' - the path of the file being creating including its name" )
def HelpRequested(self): PrintAndLog( "\n" " Asyncpool creates a new process and runs a provided command on that process.\n" " The " "provided command can be a scenario command\n" " async [poolSize] [command] [command] [command]\n" " 'poolSize' - The number of processes that will be opened for the commands\n" " 'command' - The command that will be run in a new process. It is important " "that all commands be enveloped in brackets to separate commands\n" )
def HelpRequested(self): return PrintAndLog( "\n" " Copies a file or directory'\n" " copyfile [copyType] [originPath] [destinationPath]\n" " copyType options:\n" " '-f' - Copy single file\n" " '-d' - Copy a single directory\n" " 'originPath' - the file or directory to copy\n" " 'destinationPath' - the path where the copy will be created\n" )
def HelpRequested(self): return PrintAndLog( "\n" " pings a destination url'\n" " Receives one of the following parameters:\n" " 'google' - pings google.com\n" " 'self' - pings 127.0.0.1\n" " '8' - pings 8.8.8.8\n" " '-c' - in this case the request takes in an additional parameter " "[url] and pings that url - ping [url]\n" " The destination is pinged 4 times, the response will appear once all four " "pings have completed")
def HelpRequested(self): PrintAndLog( "\n" " Connects a remote machine via an ssh connection and performs commands\n" " Command parameters: [hostname] [port] [username] [password] [command] [command] [command]\n" " 'hostname' - The address of the machine you are attempting to connect to\n" " 'port' - The port the connection will be made on\n" " 'username' - The username used in the connection request\n" " 'password' - The password used in the connection request\n" " 'command' - A list of linux shell commands wrapped in parentheses, each " "command will be run in turn once a connection is established to the remote machine\n" )
def HelpRequested(self): PrintAndLog( "\n" " Sleeps for a requested amount of time\n" " Command parameters: [WaitTimeType] [WaitTime]\n" " 'WaitTimeType' - The time format that for the WaitTime parameter," " available options:\n" " -s: seconds\n" " -m: minutes\n" " -h: hours\n" " -d: days\n" " 'WaitTime: The amount of time that will be waited'\n")
def HelpRequested(self): return PrintAndLog( "\n" " Adds a user to the operating system.\n" " useradd [Type] [Username]\n" " 'Type' - indicated the type of user that will be created, currently" " supporting:\n" " '-r' - regular user\n" " '-a' - admin user\n" " '-g' - add to group, must also pass a userID the user will " "be associated with\n" " 'Username' - a string that is the username that will be created" )
def HelpRequested(self): return PrintAndLog( "\n" " Kills an active process\n" " killprocess [KillType] [KillName]\n" " 'KillType' - the type of parameter that will be passed in the KillName, " "currently supporting:\n" " '-p' - KillName is a port and the process on that port will be " "terminated\n" " '-n' - KillName is an exact process name and that process will be " "terminated\n" " '-s' - KillName is a partial name and all processes containing KillName" " will be terminated\n" " '-i' - KillName is a PID (Process ID) and a process with that PID " "will be terminated\n" " 'KillName' - The name of the parameter that will be killed according " "the KillType")
def Execute(self): if self.CheckHelpRequested(): return try: if str.lower(GetOperatingSystemName()) != "linux": PrintRedAndLog( "Failed to upgrade AttackAgent. Upgrade currently supported only in Linux" ) return RunSubProcess( "cd /home/AriotsAttackAgent;sudo git checkout -f HEAD;sudo git pull;sudo chmod +x AttackAgent.py;" ) except Exception as ex: PrintAndLog( f"Failed to upgrade AttackAgent. Upgrade currently supported only in Linux. Ensure you have" f"required permissions and the Attack Agent is not running in another process." ) PrintRedAndLog(ex)
def GetParamArrayFromFile(path): try: with open(path, "r") as file: parameters = list(file.read().splitlines()) PrintAndLog( f"Adding {len(parameters)} commands using commands from {path}" ) file.close() splitParameters = [] for param in parameters: if "," in param: splitParameters.extend(param.split(",")) continue splitParameters.append(param) return splitParameters except Exception as ex: print(f"Failed to load command batch file, exception encountered:\n") PrintRedAndLog(ex)
def HelpRequested(self): PrintAndLog("\n" " All commands follow the format - [CommandName] [CommandsParameter] [CommandsParameter] " "...\n" " Type -help with any CommandType for more information on that command\n\n" " Available commands types:\n" " Alerts Performs Scenarios specifically targeted at raising IoT" " alerts\n" " Bash Uses bash commands to perform tasks\n" " Scenarios References text files containing a row delimited list of " "commands to run, places these commands at the front of the queue\n" " System Perform program and environment commands such as waiting, " "looping, handling environment variables and so on\n" " Remote Performs commands, connection attempts and sniffing on" "remote machines\n" " Upgrade Upgrades to latest version of Ariots Attack Agent - " "currently only supported on linux machines\n\n" " Type -help with a command type of the listed commands to get a list of available " "commands for that command type")
def Execute(self): if self.CheckHelpRequested(): return if self.CheckMinimunRequiredParameters(2): return iterations = self.request[0] command = ' '.join(self.request[1:]) try: commandsList = [] intIterations = int(iterations) for i in range(intIterations): commandsList.append(command) self.context.CommandQueue.EnqueueCommandsNext(commandsList) except Exception as ex: PrintAndLog( f"Failed to execute Loop on repetitions: {iterations}, command: {command}:\n" ) PrintRedAndLog(ex) return
def HelpRequested(self): text = "\n" \ " Run references text files containing a row delimited list of commands to run," \ " places these commands at the front of the queue\n"\ " Command format:\n" \ " run [-f] [filePath]\n" \ " run [-p] [CommandsBatchName]\n\n" \ " Command parameters:\n" \ " '-f' - Indicates you will pass a file path to the batch command file, this will " \ "be followed by the filePath parameter\n" \ " '-p' - Indicating you wish to use one of the pre made batch command scripts, " \ "will be followed by the CommandsBatchName parameter\n" \ " 'filePath' - the full path to the batch command file - The batch file " \ "referenced must contain only commands as provided when normally calling the attack agent\n" \ " 'CommandsBatchName' - The name of the pre made batch commands script\n\n" \ " The available scenarios are:\n" for commandName in GetAllPreMadeBatchNames(): text = f"{text}" \ f" {commandName}\n" text = f"{text}\n" \ " Each command must be separated by a new line\n" \ " It is possible to recursively add additional batch -run calls using a batch file\n" \ " Lines in Command Batch Files can be commented out by adding # to the start of the line\n" PrintAndLog(text)
def HelpRequested(self): return PrintAndLog("\n" " Performs the bash command: 'history -c'\n" " Triggers alert: 'ClearHistoryFile'")
def HelpRequested(self): return PrintAndLog( " Performs the bash command: 'uname -n -s -r -v'\n" " Triggers alert: 'LinuxReconnaissance'")
def HelpRequested(self): return PrintAndLog("\n" " Performs the bash command: 'curl pastebin.com'\n" " Triggers alert: 'PossibleMalware'")