class Session: def __init__(self, services, log): self.log = log self.services = services self.sessions = [] self.console = Console() async def accept(self, reader, writer): connection = writer.get_extra_info('socket') paw = await self._gen_paw_print(connection) self.sessions.append( dict(id=len(self.sessions) + 1, paw=paw, connection=connection)) self.console.line('New session: %s' % paw) async def refresh(self): for index, session in enumerate(self.sessions): try: session.get('connection').send(str.encode(' ')) except socket.error: del self.sessions[index] async def has_agent(self, paw): agents = await self.services.get('data_svc').locate('agents') return next((i for i in agents if i['paw'] == paw), False) @staticmethod async def _gen_paw_print(connection): paw = '' while True: try: data = str(connection.recv(1), 'utf-8') paw += data except BlockingIOError: break return paw
class Zero: def __init__(self, conn): self.conn = conn self.console = Console() async def enter(self): self.console.hint('You can enter "help" here as well') while True: cmd = await ainput(colored('zero> ', 'magenta')) if cmd == 'help': await self._help() elif cmd == 'bg': break elif len(str.encode(cmd)) > 0: await self._execute(cmd) """ PRIVATE """ @staticmethod async def _help(): print('ZERO SHELL HELP:') print('-> bg: send this shell to the background') print('-> download [filename]: drop any file from the API') print('-> upload [filename]: exfil any file or archive to the API') async def _execute(self, cmd): self.conn.send(str.encode('%s\n' % cmd)) client_response = str(self.conn.recv(4096), 'utf-8') print(client_response, end='')
def __init__(self, services): self.data_svc = services.get('data_svc') self.planning_svc = services.get('planning_svc') self.plugin_svc = services.get('plugin_svc') self.agent_svc = services.get('agent_svc') self.session = Session(services, self.plugin_svc.log) self.prompt = 'caldera> ' self.console = Console()
async def initialize(app, services): data_svc = services.get('data_svc') await data_svc.load_data(directory='plugins/terminal/data') logging.getLogger().setLevel(logging.FATAL) loop = asyncio.get_event_loop() show_welcome_msg() terminal = start_terminal(loop, services) start_socket_listener(loop, terminal) Console().hint('Enter "help" at any point')
def __init__(self, services, log): self.log = log self.services = services self.sessions = [] self.console = Console()
class Shell: def __init__(self, services): self.data_svc = services.get('data_svc') self.planning_svc = services.get('planning_svc') self.plugin_svc = services.get('plugin_svc') self.agent_svc = services.get('agent_svc') self.session = Session(services, self.plugin_svc.log) self.prompt = 'caldera> ' self.console = Console() async def start(self): await asyncio.sleep(1) while True: try: cmd = await ainput(self.prompt) if cmd: self.plugin_svc.log.debug(cmd) await self.session.refresh() commands = { 'help': lambda _: self._help(), 'hosts': lambda _: self._show_hosts(), 'join': lambda c: self._connect_session(cmd), 'new': lambda c: self._new_session(cmd) } command = [c for c in commands.keys() if cmd.startswith(c)] await commands[command[0]](cmd) except Exception: self.console.line('Bad command', 'red') """ PRIVATE """ @staticmethod async def _help(): print('HELP MENU:') print('-> hosts: show all connected computers') print('-> new [n]: start a new session on an agent ID') print('-> join [n]: connect to a session by ID') async def _show_hosts(self): agents = await self.data_svc.locate('agents') sessions = self.session.sessions hosts = [] for paw in set([x['paw'] for x in agents + sessions]): temp_sessions = [s['id'] for s in sessions if s['paw'] == paw] temp_agents = [a['id'] for a in agents if a['paw'] == paw] hosts.append(dict(paw=paw, agents=temp_agents, sessions=temp_sessions)) if not hosts: self.console.hint('Deploy 54ndc47 agents to add new hosts') await self.console.table(hosts) async def _connect_session(self, cmd): session = int(cmd.split(' ')[1]) try: conn = next(i['connection'] for i in self.session.sessions if i['id'] == int(session)) conn.setblocking(True) conn.send(str.encode(' ')) await Zero(conn).enter() except StopIteration: self.console.line('Session cannot be established with %s' % session, 'red') async def _new_session(self, command): agent_id = command.split(' ')[1] agent = await self.data_svc.locate('agents', match=dict(id=agent_id)) if agent: abilities = await self.data_svc.explode('ability', criteria=dict(ability_id='356d1722-7784-40c4-822b-0cf864b0b36d', platform=agent[0]['platform']) ) abilities = await self.agent_svc.capable_agent_abilities(abilities, agent[0]) command = await self.planning_svc.decode(abilities[0]['test'], agent[0], group='') cleanup = self.planning_svc.decode(abilities[0].get('cleanup', ''), agent[0], group='') link = dict(op_id=None, paw=agent[0]['paw'], ability=abilities[0]['id'], jitter=0, score=0, decide=datetime.now(), command=self.plugin_svc.encode_string(command), cleanup=self.plugin_svc.encode_string(cleanup), executor=abilities[0]['executor']) await self.data_svc.save('link', link) self.console.line('Queued. Waiting for agent to beacon...', 'green') else: self.console.line('No agent with an ID = %s' % agent_id, 'red')
def __init__(self, conn): self.conn = conn self.console = Console()