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
19 changes: 18 additions & 1 deletion src/plugins/analysis/device_tree/code/device_tree.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import re
from typing import TYPE_CHECKING, Dict

from semver import Version
Expand All @@ -13,13 +14,16 @@
if TYPE_CHECKING:
import io

DT_BINARY_DATA_REGEX_1 = re.compile(r'\[[0-9a-f ]{32,}]')
DT_BINARY_DATA_REGEX_2 = re.compile(r'<(0x[0-9a-f]+ ?){10,}>')


class AnalysisPlugin(AnalysisPluginV0):
def __init__(self):
metadata = self.MetaData(
name='device_tree',
description='get the device tree in text from the device tree blob',
version=Version(2, 0, 1),
version=Version(3, 0, 0),
system_version=None,
mime_blacklist=[*MIME_BLACKLIST_COMPRESSED, 'audio', 'image', 'video'],
timeout=10,
Expand All @@ -28,6 +32,9 @@ def __init__(self):
super().__init__(metadata=metadata)

def summarize(self, result: Schema) -> list[str]:
if not result.device_trees:
return []

models = [device_tree.model for device_tree in result.device_trees if device_tree.model]

if not models:
Expand All @@ -50,6 +57,7 @@ def analyze(
while (offset := binary.find(DeviceTree.Header.MAGIC, offset)) >= 0:
try:
device_tree = DeviceTree.from_binary(binary, offset=offset)
device_tree.string = self.replace_binary_data(device_tree.string)
# We found a valid device tree.
# Skip only the header because device trees may contain device trees themselves.
offset += DeviceTree.Header.SIZE
Expand All @@ -68,3 +76,12 @@ def get_tags(self, result: Schema, summary: list[str]) -> list[Tag]:
color=TagColor.ORANGE,
),
]

@staticmethod
def replace_binary_data(device_tree: str) -> str:
# textual device tree data can contain huge chunks of binary data
# -> remove them from the result if they are too large
return DT_BINARY_DATA_REGEX_2.sub(
'(BINARY DATA ...)',
DT_BINARY_DATA_REGEX_1.sub('(BINARY DATA ...)', device_tree),
)
17 changes: 17 additions & 0 deletions src/plugins/analysis/device_tree/test/test_device_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,21 @@ def test_multiple_device_trees(file, analysis_plugin):
@pytest.mark.parametrize('file', [TEST_FP, TEST_BROKEN])
def test_no_device_trees(file, analysis_plugin):
result = analysis_plugin.analyze(io.FileIO(file), {}, {})
summary = analysis_plugin.summarize(result)
assert result.device_trees == []
assert summary == []


@pytest.mark.AnalysisPluginTestConfig(plugin_class=AnalysisPlugin)
@pytest.mark.parametrize(
('input_dts', 'expected_result'),
[
('', ''),
('data = [01 23 45 67 89 ab cd ef 01 23 45 67 89 ab cd ef];', 'data = (BINARY DATA ...);'),
('data = <0x01 0x2345 0x67 0x89 0xabcdef 0x1234 0x56 0x78 0x90 0xab 0xcd>;', 'data = (BINARY DATA ...);'),
('data = [01 23 45 67];', 'data = [01 23 45 67];'), # short entries should not be replaced
('data = <0x01 0x2345 0x67>;', 'data = <0x01 0x2345 0x67>;'), # short entries should not be replaced
],
)
def test_replace_binary_data(analysis_plugin, input_dts, expected_result):
assert analysis_plugin.replace_binary_data(input_dts) == expected_result
12 changes: 6 additions & 6 deletions src/plugins/analysis/device_tree/view/device_tree.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

{% macro device_tree_table_cell(dt_data, colspan="1") %}
<td colspan="{{ colspan }}">
<pre class="dt-pre">{{ dt_data | hide_dts_binary_data | nice_generic | safe }}</pre>
<pre class="dt-pre">{{ dt_data | nice_generic | safe }}</pre>
</td>
{% endmacro %}

Expand All @@ -22,15 +22,15 @@
max-height: 768px;
}
</style>
<script src="{{ url_for('static', filename='highlight.js/languages/dts.min.js') }}"></script>
<script src="{{ url_for('static', filename='node_modules/@highlightjs/cdn-assets/languages/dts.min.js') }}"></script>
<script>
async function async_highlight(element) {
element.innerHTML = hljs.highlight(
element.innerHTML.replaceAll("&lt;", "<").replaceAll("&gt;", ">"),
{language: 'dts'}
).value;
};
document.addEventListener('DOMContentLoaded', (event) => {
}
document.addEventListener('DOMContentLoaded', (_) => {
document.querySelectorAll('.dt-pre').forEach((element) => {
async_highlight(element);
});
Expand All @@ -53,8 +53,8 @@
<table class="table table-bordered table-sm m-0" style="width: 100%">
{% for key, value in device_tree.header.items() -%}
<tr>
<td width="200px">{{ key | replace_underscore }}</td>
<td width="125px">{{ value | nice_number }}</td>
<td style="width: 200px;">{{ key | replace_underscore }}</td>
<td style="width: 125px;">{{ value | nice_number }}</td>
<td>{{ value | hex }}</td>
</tr>
{%- endfor %}
Expand Down
14 changes: 0 additions & 14 deletions src/test/unit/web_interface/test_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,20 +457,6 @@ def test_sort_cve_result(input_list, expected_result):
assert id_list == expected_result


@pytest.mark.parametrize(
('input_dts', 'expected_result'),
[
('', ''),
('data = [01 23 45 67 89 ab cd ef 01 23 45 67 89 ab cd ef];', 'data = (BINARY DATA ...);'),
('data = <0x01 0x2345 0x67 0x89 0xabcdef 0x1234 0x56 0x78 0x90 0xab 0xcd>;', 'data = (BINARY DATA ...);'),
('data = [01 23 45 67];', 'data = [01 23 45 67];'), # short entries should not be replaced
('data = <0x01 0x2345 0x67>;', 'data = <0x01 0x2345 0x67>;'), # short entries should not be replaced
],
)
def test_hide_dts_data(input_dts, expected_result):
assert flt.hide_dts_binary_data(input_dts) == expected_result


@pytest.mark.parametrize(
('input_', 'expected_result'),
[
Expand Down
1 change: 0 additions & 1 deletion src/web_interface/components/jinja_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ def _setup_filters(self):
'group_dict_list_by_key': flt.group_dict_list_by_key,
'group_changed_text_files': flt.group_path_dict_by_dirs,
'hex': hex,
'hide_dts_binary_data': flt.hide_dts_binary_data,
'infection_color': flt.infection_color,
'is_list': lambda item: isinstance(item, list),
'is_text_file_or_image': flt.is_text_file_or_image,
Expand Down
6 changes: 0 additions & 6 deletions src/web_interface/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -540,12 +540,6 @@ def linter_reformat_issues(issues) -> dict[str, list[dict[str, str]]]:
return reformatted


def hide_dts_binary_data(device_tree: str) -> str:
# textual device tree data can contain huge chunks of binary data -> hide them from view if they are too large
device_tree = re.sub(r'\[[0-9a-f ]{32,}]', '(BINARY DATA ...)', device_tree)
return re.sub(r'<(0x[0-9a-f]+ ?){10,}>', '(BINARY DATA ...)', device_tree)


def get_searchable_crypto_block(crypto_material: str) -> str:
"""crypto material plugin results contain spaces and line breaks -> get a contiguous block without those"""
blocks = crypto_material.replace(' ', '').split('\n')
Expand Down
7 changes: 4 additions & 3 deletions src/web_interface/static/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.