Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion beagle/transformers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from .procmon_transformer import ProcmonTransformer
from .sysmon_transformer import SysmonTransformer
from .darpa_tc_transformer import DRAPATCTransformer

from .ossem_transformer import OSSEMTransformer

__all__ = [
"Transformer",
Expand All @@ -19,4 +19,5 @@
"ProcmonTransformer",
"SysmonTransformer",
"DRAPATCTransformer",
"OSSEMTransformer",
]
92 changes: 92 additions & 0 deletions beagle/transformers/ossem_transformer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from typing import List, Optional, Tuple

from beagle.common import logger, split_path
from beagle.nodes import File, Process
from beagle.transformers.base_transformer import Transformer


class OSSEMTransformer(Transformer):
"""Transformer based on the fields defined here:
https://github.com/Cyb3rWard0g/OSSEM/tree/master/common_information_model

And the relationships defined here:
https://docs.google.com/spreadsheets/d/1ow7YRDEDJs67kcKMZZ66_5z1ipJry9QrsDQkjQvizJM/edit#gid=0

Parameters
----------
Transformer : [type]
[description]
"""

name = "OSSEM"

def __init__(self, *args, **kwargs) -> None:

super().__init__(*args, **kwargs)

logger.info("Created OSSEM Transformer.")

def transform(self, event: dict) -> Optional[Tuple]:

relationship = event["event_type"]

if relationship == "launched":
return self.created(event)
elif relationship in ["loaded", "created", "modified", "downloaded"]:
return self.file_ops(event)

return tuple()

def created(self, event: dict) -> Tuple[Process, File, Process, File]:

proc_name, proc_path = split_path(event["process_path"])

proc = Process(
process_id=event.get("process_id"),
process_image=proc_name,
process_image_path=proc_path,
command_line=event.get("process_command_line"),
)

proc_name, proc_path = split_path(event["process_parent_path"])

parent = Process(
process_id=event.get("process_parent_id"),
process_image=proc_name,
process_image_path=proc_path,
command_line=event.get("process_parent_command_line"),
)

parent_file = parent.get_file_node()
proc_file = proc.get_file_node()

parent_file.file_of[parent]
proc_file.file_of[proc]

parent.launched[proc].append(timestamp=event["event_creation_time"])

return (proc, proc_file, parent, parent_file)

def file_ops(self, event: dict) -> Tuple[Process, File, File]:
proc_name, proc_path = split_path(event["process_path"])

proc = Process(
process_id=event.get("process_id"),
process_image=proc_name,
process_image_path=proc_path,
command_line=event.get("process_command_line"),
)
proc_file = proc.get_file_node()

proc_file.file_of[proc]

name, path = split_path(event["file_path"])

dest_file = File(file_name=name, file_path=path, extension=event.get("file_extension"))

if event["event_type"] == "loaded":
proc.loaded[dest_file].append(timestamp=event["event_creation_time"])
elif event["event_type"] in ["created", "modified", "downloaded"]:
proc.wrote[dest_file].append(timestamp=event["event_creation_time"])

return (proc, proc_file, dest_file)
89 changes: 89 additions & 0 deletions tests/transformers/test_ossem_transformer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import pytest

from beagle.nodes import Process, File
from beagle.transformers import OSSEMTransformer


@pytest.fixture
def transformer() -> OSSEMTransformer:
return OSSEMTransformer(datasource=None) # type: ignore


def test_unknown_event(transformer):
assert transformer.transform({"event_type": "foooo"}) == ()


def test_make_process(transformer):
test_event = {
"event_creation_time": "1",
"event_type": "launched",
"process_id": "4756",
"process_name": "conhost.exe",
"process_path": "C:\\Windows\\System32\\conhost.exe",
"process_command_line": "??\\C:\\WINDOWS\\system32\\conhost.exe 0xffffffff -ForceV1",
"process_integrity_level": "Medium",
"process_parent_guid": "A98268C1-9C2E-5ACD-0000-00100266AB00}",
"process_parent_id": "240",
"process_parent_name": "cmd.exe",
"process_parent_path": "C:\\Windows\\System32\\cmd.exe",
"process_parent_command_line": "C:\\WINDOWS\\system32\\cmd.exe",
}

nodes = transformer.transform(test_event)

assert len(nodes) == 4

proc: Process = nodes[0]
proc_file: File = nodes[1]
parent_proc: Process = nodes[2]
parent_proc_file: File = nodes[3]

assert {"timestamp": "1"} in parent_proc.launched[proc]
assert proc in proc_file.file_of
assert parent_proc in parent_proc_file.file_of

assert proc.process_id == "4756"
assert proc.process_image == "conhost.exe"
assert proc.process_image_path == "C:\\Windows\\System32"
assert proc.command_line == "??\\C:\\WINDOWS\\system32\\conhost.exe 0xffffffff -ForceV1"

assert parent_proc.process_id == "240"
assert parent_proc.process_image == "cmd.exe"
assert parent_proc.process_image_path == "C:\\Windows\\System32"
assert parent_proc.command_line == "C:\\WINDOWS\\system32\\cmd.exe"


@pytest.mark.parametrize(
"eventtype,attribute",
[("loaded", "loaded"), ("created", "wrote"), ("modified", "wrote"), ("downloaded", "wrote")],
)
def test_file_operations(transformer, eventtype, attribute):
test_event = {
"event_creation_time": "1",
"event_type": eventtype,
"process_id": "4756",
"process_name": "conhost.exe",
"process_path": "C:\\Windows\\System32\\conhost.exe",
"process_command_line": "??\\C:\\WINDOWS\\system32\\conhost.exe 0xffffffff -ForceV1",
"file_name": "cmd.exe",
"file_path": "C:\\Windows\\System32\\cmd.exe",
}
nodes = transformer.transform(test_event)

assert len(nodes) == 3

proc: Process = nodes[0]
proc_file: File = nodes[1]
dest_file: File = nodes[2]

assert proc in proc_file.file_of

assert proc.process_id == "4756"
assert proc.process_image == "conhost.exe"
assert proc.process_image_path == "C:\\Windows\\System32"
assert proc.command_line == "??\\C:\\WINDOWS\\system32\\conhost.exe 0xffffffff -ForceV1"

assert dest_file.file_name == "cmd.exe"
assert dest_file.file_path == "C:\\Windows\\System32"

assert {"timestamp": "1"} in getattr(proc, attribute)[dest_file]