def op_for_event_logs(operation_agent, operation_adversary, executor, ability, operation_link, encoded_command): op = Operation(name='test', agents=[operation_agent], adversary=operation_adversary) op.set_start_details() command_1 = 'whoami' command_2 = 'hostname' executor_1 = executor(name='psh', platform='windows', command=command_1) executor_2 = executor(name='psh', platform='windows', command=command_2) ability_1 = ability(ability_id='123', tactic='test tactic', technique_id='T0000', technique_name='test technique', name='test ability', description='test ability desc', executors=[executor_1]) ability_2 = ability(ability_id='456', tactic='test tactic', technique_id='T0000', technique_name='test technique', name='test ability 2', description='test ability 2 desc', executors=[executor_2]) link_1 = operation_link(ability=ability_1, paw=operation_agent.paw, executor=executor_1, command=encoded_command(command_1), status=0, host=operation_agent.host, pid=789, decide=datetime.strptime('2021-01-01 08:00:00', '%Y-%m-%d %H:%M:%S'), collect=datetime.strptime('2021-01-01 08:01:00', '%Y-%m-%d %H:%M:%S'), finish='2021-01-01 08:02:00') link_2 = operation_link(ability=ability_2, paw=operation_agent.paw, executor=executor_2, command=encoded_command(command_2), status=0, host=operation_agent.host, pid=7890, decide=datetime.strptime('2021-01-01 09:00:00', '%Y-%m-%d %H:%M:%S'), collect=datetime.strptime('2021-01-01 09:01:00', '%Y-%m-%d %H:%M:%S'), finish='2021-01-01 09:02:00') discarded_link = operation_link(ability=ability_2, paw=operation_agent.paw, executor=executor_2, command=encoded_command(command_2), status=-2, host=operation_agent.host, pid=7891, decide=datetime.strptime( '2021-01-01 10:00:00', '%Y-%m-%d %H:%M:%S')) op.chain = [link_1, link_2, discarded_link] return op
def op_for_event_logs(operation_agent, operation_adversary, executor, ability, operation_link, encoded_command, parse_datestring): op = Operation(name='test', agents=[operation_agent], adversary=operation_adversary) op.set_start_details() command_1 = 'whoami' command_2 = 'hostname' executor_1 = executor(name='psh', platform='windows', command=command_1) executor_2 = executor(name='psh', platform='windows', command=command_2) ability_1 = ability(ability_id='123', tactic='test tactic', technique_id='T0000', technique_name='test technique', name='test ability', description='test ability desc', executors=[executor_1]) ability_2 = ability(ability_id='456', tactic='test tactic', technique_id='T0000', technique_name='test technique', name='test ability 2', description='test ability 2 desc', executors=[executor_2]) link_1 = operation_link(ability=ability_1, paw=operation_agent.paw, executor=executor_1, command=encoded_command(command_1), status=0, host=operation_agent.host, pid=789, decide=parse_datestring(LINK1_DECIDE_TIME), collect=parse_datestring(LINK1_COLLECT_TIME), finish=LINK1_FINISH_TIME) link_2 = operation_link(ability=ability_2, paw=operation_agent.paw, executor=executor_2, command=encoded_command(command_2), status=0, host=operation_agent.host, pid=7890, decide=parse_datestring(LINK2_DECIDE_TIME), collect=parse_datestring(LINK2_COLLECT_TIME), finish=LINK2_FINISH_TIME) discarded_link = operation_link( ability=ability_2, paw=operation_agent.paw, executor=executor_2, command=encoded_command(command_2), status=-2, host=operation_agent.host, pid=7891, decide=parse_datestring('2021-01-01T10:00:00Z')) op.chain = [link_1, link_2, discarded_link] return op
async def _create_detection_operation(self, red_op_name, red_op_id, red_op_access): planner = (await self.get_service('data_svc').locate( 'planners', match=dict(name='atomic')))[0] adversary_id = self.get_config(prop='adversary', name='gameboard') adversary = (await self.data_svc.locate( 'adversaries', match=dict(adversary_id=adversary_id)))[0] obj = (await self.data_svc.locate('objectives', match=dict(name='default')))[0] agent = Agent(0, 0, 0, paw='gameboard_detection') access = self.Access.BLUE detection_operation = Operation(name=red_op_name + '_' + str(red_op_id) + self.blue_op_name_modifier, agents=[agent], adversary=adversary, access=access, planner=planner, group='blue') detection_operation.objective = obj detection_operation.set_start_details() return [await self.data_svc.store(detection_operation)]
class ResponseService(BaseService): def __init__(self, services): self.log = self.add_service('response_svc', self) self.data_svc = services.get('data_svc') self.rest_svc = services.get('rest_svc') self.agents = [] self.adversary = None self.abilities = [] self.op = None @template('response.html') async def splash(self, request): abilities = [ a for a in await self.data_svc.locate('abilities') if await a.which_plugin() == 'response' ] adversaries = [ a for a in await self.data_svc.locate('adversaries') if await a.which_plugin() == 'response' ] return dict(abilities=abilities, adversaries=adversaries) @staticmethod async def register_handler(event_svc): await event_svc.observe_event('link/completed', handle_link_completed) async def respond_to_pid(self, pid, agent): available_agents = await self.get_available_agents(agent) if not available_agents: return total_facts = [] total_links = [] for blue_agent in available_agents: agent_facts, agent_links = await self.run_abilities_on_agent( blue_agent, pid) total_facts.extend(agent_facts) total_links.extend(agent_links) await self.save_to_operation(total_facts, total_links) async def get_available_agents(self, agent_to_match): await self.refresh_blue_agents_abilities() available_agents = [ a for a in self.agents if a.host == agent_to_match.host ] if not available_agents: self.log.debug('No available blue agents to respond to red action') return [] return available_agents async def refresh_blue_agents_abilities(self): self.agents = await self.data_svc.locate( 'agents', match=dict(access=self.Access.BLUE)) self.adversary = (await self.data_svc.locate( 'adversaries', match=dict(adversary_id=BLUE_ADVERSARY)))[0] self.abilities = [] for a in self.adversary.atomic_ordering: if a not in self.abilities: self.abilities.append(a) async def run_abilities_on_agent(self, blue_agent, original_pid): facts = [Fact(trait='host.process.id', value=original_pid)] links = [] for ability_id in self.abilities: ability_facts, ability_links = await self.run_ability_on_agent( blue_agent, ability_id, facts, original_pid) links.extend(ability_links) facts.extend(ability_facts) return facts, links async def run_ability_on_agent(self, blue_agent, ability_id, agent_facts, original_pid): links = await self.rest_svc.task_agent_with_ability( blue_agent.paw, ability_id, agent_facts) await self.wait_for_link_completion(links, blue_agent) ability_facts = [] for link in links: link.pin = int(original_pid) unique_facts = link.facts[1:] ability_facts.extend(unique_facts) return ability_facts, links @staticmethod async def wait_for_link_completion(links, agent): for link in links: while not link.finish or link.can_ignore(): await asyncio.sleep(3) if not agent.trusted: break async def create_fact_source(self, facts): source_id = str(uuid.uuid4()) source_name = 'blue-pid-{}'.format(source_id) return Source(id=source_id, name=source_name, facts=facts) async def save_to_operation(self, facts, links): if not self.op or await self.op.is_finished(): source = await self.create_fact_source(facts) await self.create_operation(links=links, source=source) else: await self.update_operation(links) await self.get_service('data_svc').store(self.op) async def create_operation(self, links, source): planner = (await self.get_service('data_svc').locate( 'planners', match=dict(name='sequential')))[0] await self.get_service('data_svc').store(source) self.op = Operation(name=BLUE_OP_NAME, agents=self.agents, adversary=self.adversary, source=source, access=self.Access.BLUE, planner=planner, state='running', auto_close=False, jitter='1/4') self.op.set_start_details() await self.update_operation(links) async def update_operation(self, links): for link in links: link.operation = self.op.id self.op.add_link(link)