| import pytest |
| from app.objects.c_adversary import Adversary |
| from app.objects.secondclass.c_executor import Executor |
| from app.objects.secondclass.c_fact import Fact |
| from app.utility.base_world import BaseWorld |
| |
| |
| @pytest.fixture |
| async def setup_learning_service(data_svc, ability, operation, link): |
| texecutor = Executor(name='sh', platform='darwin', command='whoami', payloads=['wifi.sh']) |
| tability = ability(tactic='discovery', technique_id='T1033', technique_name='Find', name='test', |
| description='find active user', privilege=None, executors=[texecutor]) |
| await data_svc.store(tability) |
| toperation = operation(name='sample', agents=None, adversary=Adversary(name='sample', adversary_id='XYZ', |
| atomic_ordering=[], description='test')) |
| await data_svc.store(toperation) |
| tlink1 = link(ability=tability, command='', paw='1234', executor=texecutor) |
| tlink2 = link(ability=tability, command='', paw='5678', executor=texecutor) |
| yield toperation, tlink1, tlink2 |
| |
| |
| class TestLearningSvc: |
| |
| async def test_learn(self, setup_learning_service, learning_svc, knowledge_svc): |
| operation, link, _ = setup_learning_service |
| operation.add_link(link) |
| all_facts = await operation.all_facts() |
| await learning_svc.learn( |
| facts=all_facts, |
| link=link, |
| blob=BaseWorld.encode_string('i contain 1 ip address 192.168.0.1 and one file /etc/host.txt. that is all.')) |
| knowledge_facts = await knowledge_svc.get_facts(dict(source=link.id)) |
| assert len(link.facts) == 2 |
| assert len(knowledge_facts) == 2 |
| |
| async def test_same_fact_different_agents(self, setup_learning_service, learning_svc, knowledge_svc): |
| operation, link1, link2 = setup_learning_service |
| link1.id = 'link1' |
| link2.id = 'link2' |
| operation.add_link(link1) |
| all_facts = await operation.all_facts() |
| await learning_svc.learn( |
| facts=all_facts, |
| link=link1, |
| blob=BaseWorld.encode_string('i contain 1 ip address 192.168.0.1 and one file /etc/host.txt. that is all.'), |
| operation=operation) |
| operation.add_link(link2) |
| all_facts = await operation.all_facts() |
| await learning_svc.learn( |
| facts=all_facts, |
| link=link2, |
| blob=BaseWorld.encode_string('i contain 1 ip address 192.168.0.1 and one file /etc/host.txt. that is all.'), |
| operation=operation) |
| |
| knowledge_facts = await knowledge_svc.get_facts(dict(source=operation.id)) |
| assert len(link1.facts) == 2 |
| assert len(link2.facts) == 2 |
| assert len(knowledge_facts) == 2 |
| assert len(knowledge_facts[0].collected_by) == 2 |
| |
| async def test_build_relationships(self, setup_learning_service, learning_svc, knowledge_svc): |
| _, link, _ = setup_learning_service |
| learning_svc.model.add(frozenset({'host.user.name', 'target.org.name'})) |
| learning_svc.model.add(frozenset({'host.file.extension', 'host.user.name', 'domain.user.name'})) |
| facts = [ |
| Fact(trait='target.org.name', value='something'), |
| Fact(trait='host.user.name', value='admin'), |
| Fact(trait='host.user.name', value='root'), |
| Fact(trait='domain.user.name', value='user'), |
| Fact(trait='not.really.here', value='should never be found') |
| ] |
| await learning_svc._store_results(link, facts) |
| assert len(link.relationships) == 4 |