Skip to content

Commit

Permalink
plugins/device_tree: Use AnalysisPluginV0
Browse files Browse the repository at this point in the history
Version bumped because unknown-model is now also part of the summary.
  • Loading branch information
maringuu committed Sep 18, 2023
1 parent a31382a commit 1b1b284
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 57 deletions.
6 changes: 5 additions & 1 deletion src/plugins/analysis/architecture_detection/internal/dt.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,12 @@ def _get_compatible_entry(dts: str) -> str | None:


def construct_result(file_object):
device_tree_result = file_object.processed_analysis['device_tree'].get('result', {})
if not device_tree_result:
return {}

result = {}
for dt_dict in file_object.processed_analysis['device_tree'].get('result', {}).get('device_trees', []):
for dt_dict in device_tree_result.get('device_trees', []):
dt = dt_dict['device_tree']

compatible_entry = _get_compatible_entry(dt)
Expand Down
89 changes: 58 additions & 31 deletions src/plugins/analysis/device_tree/code/device_tree.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,65 @@
from analysis.PluginBase import AnalysisBasePlugin
import io

import pydantic

from helperFunctions.tag import TagColor
from objects.file import FileObject
from plugins.mime_blacklists import MIME_BLACKLIST_COMPRESSED
from analysis.plugin.compat import AnalysisBasePluginAdapterMixin
from analysis.plugin import AnalysisPluginV0, Tag
from typing import Optional, List, Dict

from ..internal.device_tree_utils import dump_device_trees


class AnalysisPlugin(AnalysisBasePlugin):
"""
Device Tree Plug-in
"""

NAME = 'device_tree'
DESCRIPTION = 'get the device tree in text from the device tree blob'
VERSION = '1.0.1'
MIME_BLACKLIST = [*MIME_BLACKLIST_COMPRESSED, 'audio', 'image', 'video'] # noqa: RUF012
FILE = __file__

def process_object(self, file_object: FileObject):
file_object.processed_analysis[self.NAME] = {'summary': []}

device_trees = dump_device_trees(file_object.binary)
if device_trees:
file_object.processed_analysis[self.NAME]['device_trees'] = device_trees
for result in device_trees:
model = result.get('model')
if model:
file_object.processed_analysis[self.NAME]['summary'].append(model)
self.add_analysis_tag(
file_object=file_object,
tag_name=self.NAME,
value=self.NAME.replace('_', ' '),
color=TagColor.ORANGE,
propagate=False,
)
class AnalysisPlugin(AnalysisPluginV0, AnalysisBasePluginAdapterMixin):
class Schema(pydantic.BaseModel):
class DeviceTree(pydantic.BaseModel):
header: Optional[dict]
device_tree: Optional[str]
model: Optional[str]
description: Optional[str]
offset: int

device_trees: List[DeviceTree]

def __init__(self):
metadata = AnalysisPluginV0.MetaData(
name='device_tree',
description='get the device tree in text from the device tree blob',
version='1.1.0',
system_version=None,
mime_blacklist=[*MIME_BLACKLIST_COMPRESSED, 'audio', 'image', 'video'],
timeout=10,
Schema=AnalysisPlugin.Schema,
)
super().__init__(metadata=metadata)

return file_object
def summarize(self, result: Schema) -> list[str]:
models = [device_tree.model for device_tree in result.device_trees if device_tree.model]

if not models:
return ['unknown-model']

return models

def analyze(
self,
file_handle: io.FileIO,
virtual_file_path: dict,
analyses: Dict[str, dict],
) -> Optional[Schema]:
del virtual_file_path, analyses
device_trees = dump_device_trees(file_handle.readall())
if len(device_trees) == 0:
return None
return AnalysisPlugin.Schema(device_trees=device_trees)

def get_tags(self, result: Schema, summary: list[str]) -> list[Tag]:
del result, summary
return [
Tag(
name=self.metadata.name,
value='device tree',
color=TagColor.ORANGE,
),
]
19 changes: 8 additions & 11 deletions src/plugins/analysis/device_tree/test/test_device_tree.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import io
from pathlib import Path

import pytest

from objects.file import FileObject

from ..code.device_tree import AnalysisPlugin
from ..internal.device_tree_utils import dump_device_trees
Expand All @@ -16,16 +16,13 @@


@pytest.mark.AnalysisPluginTestConfig(plugin_class=AnalysisPlugin)
def test_process_object(analysis_plugin):
test_object = FileObject()
test_object.binary = TEST_FILE.read_bytes()
test_object.file_path = str(TEST_FILE)
processed_object = analysis_plugin.process_object(test_object)
result = processed_object.processed_analysis[analysis_plugin.NAME]

assert len(result['device_trees']) == 1
assert result['device_trees'][0]['model'] == 'Manufac XYZ1234ABC'
assert result['summary'] == ['Manufac XYZ1234ABC']
def test_analyze(analysis_plugin):
result = analysis_plugin.analyze(io.FileIO(TEST_FILE), {}, {})
summary = analysis_plugin.summarize(result)

assert len(result.device_trees) == 1
assert result.device_trees[0].model == 'Manufac XYZ1234ABC'
assert summary == ['Manufac XYZ1234ABC']


@pytest.mark.parametrize('file', [TEST_EMBEDDED, TEST_IMAGE])
Expand Down
15 changes: 1 addition & 14 deletions src/plugins/analysis/device_tree/view/device_tree.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,7 @@


{% block analysis_result_details %}

{# Don't break on legacy result #}
{% if "device_tree" in analysis_result %}
<tr class="table-warning">
<td> Deprecation Warning </td>
<td> Analysis version is deprecated, please update the analysis </td>
</tr>
<tr>
<td> Device Tree </td>
{{ device_tree_table_cell(analysis_result.device_tree, "1") }}
</tr>
{% endif %}

{% for dt_dict in analysis_result.get("device_trees", []) %}
{% for dt_dict in analysis_result["device_trees"] %}
<tr data-toggle="collapse" data-target="#collapse-{{ dt_dict.offset }}">
<td class="clickable" colspan=2>
<i class="fas fa-angle-down"></i>
Expand Down

0 comments on commit 1b1b284

Please sign in to comment.