Skip to content

Commit

Permalink
Make inverted scanning for ScanQr optional, update doc
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanohoro committed Oct 24, 2023
1 parent 6c00644 commit 6fd5191
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 9 deletions.
2 changes: 2 additions & 0 deletions configs/python/backend/backend.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,8 @@ scanners:
- 'bmp_file'
- 'image/webp'
priority: 5
options:
support_inverted: True
'ScanRar':
- positive:
flavors:
Expand Down
6 changes: 3 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ The table below describes each scanner and its options. Each scanner has the hid
| ScanFloss | Analyzes executable files with FireEye [floss](https://github.com/fireeye/flare-floss) | `tempfile_directory` -- location where `tempfile` will write temporary files (defaults to `/tmp/`)<br>`limit` -- Maximum amount of strings to collect. (defaults to `100`) |
| ScanFooter | Collects file footer | `length` -- number of footer characters to log as metadata (defaults to `50`) <br> `encodings` -- list of output encodings, any of `classic`, `raw`, `hex`, `backslash` |
| ScanGif | Extracts data embedded in GIF files | N/A |
| ScanGzip | Decompresses gzip files | N/A
| ScanGzip | Decompresses gzip files | N/A
| ScanHash | Calculates file hash values | N/A |
| ScanHeader | Collects file header | `length` -- number of header characters to log as metadata (defaults to `50`) <br> `encodings` -- list of output encodings, any of `classic`, `raw`, `hex`, `backslash` |
| ScanHtml | Collects metadata and extracts embedded files from HTML files | `parser` -- sets the HTML parser used during scanning (defaults to `html.parser`) <br> `max_links` -- Maximum amount of links to output in hyperlinks field (defaults to `50`) |
Expand All @@ -784,7 +784,7 @@ The table below describes each scanner and its options. Each scanner has the hid
| ScanPhp | Collects metadata from PHP files | N/A |
| ScanPkcs7 | Extracts files from PKCS7 certificate files | N/A |
| ScanPlist | Collects attributes from binary and XML property list files | `keys` -- list of keys to log (defaults to `all`) |
| ScanQr | Collects QR code metadata from image files | N/A | [Aaron Herman](https://github.com/aaronherman)
| ScanQr | Collects QR code metadata from image files | `support_inverted` -- Enable/disable image inversion to support inverted QR codes (white on black). Adds some image processing overhead. | [Aaron Herman](https://github.com/aaronherman)
| ScanRar | Extracts files from RAR archives | `limit` -- maximum number of files to extract (defaults to `1000`)<br>`password_file` -- location of passwords file for RAR archives (defaults to `/etc/strelka/passwords.dat`) |
| ScanRpm | Collects metadata and extracts files from RPM files | `tempfile_directory` -- location where `tempfile` will write temporary files (defaults to `/tmp/`) |
| ScanRtf | Extracts embedded files from RTF files | `limit` -- maximum number of files to extract (defaults to `1000`) |
Expand All @@ -808,7 +808,7 @@ The table below describes each scanner and its options. Each scanner has the hid
| ScanXml | Log metadata and extract files from XML files | `extract_tags` -- list of XML tags that will have their text extracted as child files (defaults to empty list)<br>`metadata_tags` -- list of XML tags that will have their text logged as metadata (defaults to empty list) |
| ScanYara | Scans files with YARA rules | `location` -- location of the YARA rules file or directory (defaults to `/etc/strelka/yara/`)<br>`compiled` -- Enable use of compiled YARA rules, as well as the path.<br>`store_offset` -- Stores file offset for YARA match<br>`offset_meta_key` -- YARA meta key that must exist in the YARA rule for the offset to be stored.<br>`offset_padding` -- Amount of data to be stored before and after offset for additional context. |
| ScanZip | Extracts files from zip archives | `limit` -- maximum number of files to extract (defaults to `1000`)<br>`password_file` -- location of passwords file for zip archives (defaults to `/etc/strelka/passwords.dat`) |
| ScanZlib | Decompresses gzip files | N/A
| ScanZlib | Decompresses gzip files | N/A

## Tests
As Strelka consists of many scanners and dependencies for those scanners. Pytests are particularly valuable for testing the ongoing functionality of Strelka and it's scanners. Tests allow users to write test cases that verify the correct behavior of Strelka scanners to ensure that the scanners remain reliable and accurate. Additionally, using pytests can help streamline the development process, allowing developers to focus on writing new features and improvements for the scanners. Strelka contains a set of standard test fixture files that represent the types of files Strelka ingests. Test fixtures can also be loaded remotely with the helper functions `get_remote_fixture` and `get_remote_fixture_archive` for scanner tests that need malicious samples.
Expand Down
14 changes: 8 additions & 6 deletions src/python/strelka/scanners/scan_qr.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class ScanQr(strelka.Scanner):
"""

def scan(self, data, file, options, expire_at):
support_inverted = options.get("support_inverted", True)

self.event["data"] = []

Expand All @@ -28,13 +29,14 @@ def scan(self, data, file, options, expire_at):
for barcode in barcodes:
barcode_data.append(barcode.data.decode("utf-8"))

img_inverted = ImageOps.invert(img)
barcodes = decode(img_inverted)
if support_inverted:
img_inverted = ImageOps.invert(img)
barcodes = decode(img_inverted)

if barcodes:
self.flags.append("inverted")
for barcode in barcodes:
barcode_data.append(barcode.data.decode("utf-8"))
if barcodes:
self.flags.append("inverted")
for barcode in barcodes:
barcode_data.append(barcode.data.decode("utf-8"))

if barcode_data:
self.event["data"] = barcode_data
Expand Down
43 changes: 43 additions & 0 deletions src/python/strelka/tests/test_scan_qr.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from unittest import TestCase, mock

import pytest

from strelka.scanners.scan_qr import ScanQr as ScanUnderTest
from strelka.tests import run_test_scan

Expand Down Expand Up @@ -75,3 +76,45 @@ def test_scan_qr(mocker, fmt):

TestCase.maxDiff = None
TestCase().assertDictEqual(test_scan_event, scanner_event)


def test_scan_qr_support_inverted_true(mocker):
"""
Pass: Sample event matches output of scanner.
Failure: Unable to load file or sample event fails to match.
"""

test_scan_event = {
"elapsed": mock.ANY,
"flags": ["inverted"],
"data": ["Plain Text Code"],
}

scanner_event = run_test_scan(
mocker=mocker,
scan_class=ScanUnderTest,
fixture_path=Path(__file__).parent / "fixtures/test_qr_inverted.png",
options={"support_inverted": True},
)

TestCase.maxDiff = None
TestCase().assertDictEqual(test_scan_event, scanner_event)


def test_scan_qr_support_inverted_false(mocker):
"""
Pass: Sample event matches output of scanner.
Failure: Unable to load file or sample event fails to match.
"""

test_scan_event = {"elapsed": mock.ANY, "flags": [], "data": []}

scanner_event = run_test_scan(
mocker=mocker,
scan_class=ScanUnderTest,
fixture_path=Path(__file__).parent / "fixtures/test_qr_inverted.png",
options={"support_inverted": False},
)

TestCase.maxDiff = None
TestCase().assertDictEqual(test_scan_event, scanner_event)

0 comments on commit 6fd5191

Please sign in to comment.