Skip to content

Commit 665bb11

Browse files
authored
Merge pull request kevoreilly#2949 from rkoumis/python-check-is-too-broad
Check for python content was too broad
2 parents cefb40c + 1929082 commit 665bb11

6 files changed

Lines changed: 81 additions & 2 deletions

File tree

analyzer/windows/lib/api/process.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import urllib.error
1414
import urllib.parse
1515
import urllib.request
16-
from ctypes import byref, c_buffer, c_int, c_ulong, create_string_buffer, sizeof, windll, ArgumentError
16+
from ctypes import byref, c_buffer, c_int, c_ulong, create_string_buffer, sizeof, ArgumentError
1717
from pathlib import Path
1818
from shutil import copy
1919

@@ -38,6 +38,7 @@
3838
)
3939

4040
if sys.platform == "win32":
41+
from ctypes import windll
4142
from lib.common.constants import (
4243
CAPEMON32_NAME,
4344
CAPEMON64_NAME,

analyzer/windows/lib/core/packages.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,11 @@ def choose_package(file_type, file_name, exports, target):
6969
return "rar"
7070
elif "Macromedia Flash" in file_type or file_name.endswith((".swf", ".fws")):
7171
return "swf"
72-
elif file_name.endswith((".py", ".pyc")) or "Python script" in file_type or b"import" in file_content:
72+
elif (
73+
file_name.endswith((".py", ".pyc"))
74+
or "Python script" in file_type
75+
or (file_content.startswith(b"#!/") and b"python" in file_content.split(b"\n", 1)[0])
76+
):
7377
return "python"
7478
elif file_name.endswith(".ps1"):
7579
return "ps1"

analyzer/windows/tests/test_analyzer.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ def test_prepare(self, set_lock, init_logging, config, pipeserver):
8181

8282

8383
class TestAnalyzerChoosePackage(unittest.TestCase):
84+
def setUp(self):
85+
patch_process = patch("analyzer.Process")
86+
self.mock_process = patch_process.start()
87+
self.mock_process.return_value = MagicMock()
88+
self.addCleanup(patch_process.stop)
89+
8490
def test_choose_package_shellcode(self):
8591
test = analyzer.Analyzer()
8692
test.config = MagicMock()
@@ -621,6 +627,34 @@ def test_choose_package_zip_compound(self):
621627
self.assertEqual("modules.packages.zip_compound", pkg_name)
622628
self.assertEqual(pkg_class.__class__.__name__, "ZipCompound")
623629

630+
def _assert_autodetected_package(self, file_name, expected_pkg_module, expected_pkg_class_name, file_type="ASCII text"):
631+
"""Helper: auto-detect a package from a file in test_data and assert the result."""
632+
file_path = os.path.join(os.path.dirname(__file__), "test_data", file_name)
633+
test = analyzer.Analyzer()
634+
test.config = MagicMock()
635+
test.options = MagicMock()
636+
test.config.package = ""
637+
test.config.category = "file"
638+
test.config.file_name = file_name
639+
test.config.file_type = file_type
640+
test.config.exports = ""
641+
test.target = file_path
642+
pkg_name, pkg_class = test.choose_package()
643+
self.assertEqual(f"modules.packages.{expected_pkg_module}", pkg_name)
644+
self.assertEqual(expected_pkg_class_name, pkg_class.__class__.__name__)
645+
646+
def test_choose_package_from_eml_file(self):
647+
"""Auto-detect eml package by reading test_email.eml from test_data."""
648+
self._assert_autodetected_package("test_email.eml", "eml", "EML")
649+
650+
def test_choose_package_from_python_py_file(self):
651+
"""Auto-detect python package from test_python_file1.py via file extension."""
652+
self._assert_autodetected_package("test_python_file1.py", "python", "Python")
653+
654+
def test_choose_package_from_python_data_file(self):
655+
"""Auto-detect python package from test_python_file2.data via #!/usr/bin/env python in content."""
656+
self._assert_autodetected_package("test_python_file2.data", "python", "Python")
657+
624658

625659
class TestAnalyzerMonitoring(unittest.TestCase):
626660
def setUp(self):
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Received: from bogus.com
2+
Authentication-Results: spf=pass (sender IP is 1.2.3.4)
3+
Received-SPF: Pass (protection.outlook.com: domain of bogus.com
4+
Received: from bogus.bogus.com
5+
Authentication-Results-Original: mx-bogus.com;
6+
Date: Wed, 18 Mar 2026 09:59:38 +0000
7+
From: "Alice Bogus" <alice@bogus.com>
8+
Reply-To: "Alice Bogus" <alice@bogus.com>
9+
To: <bob@bogus.com>
10+
Message-ID: <12345@bogus.com>
11+
Subject: Hi Bob
12+
13+
Hi Bob,
14+
15+
How's it going?
16+
17+
Did you import that file I sent you last week?
18+
19+
Please let me know. Thanks.
20+
21+
Alice
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# sample file to test if python detection is working
2+
import sys
3+
4+
5+
def greet(name):
6+
return f"Hello, {name}!"
7+
8+
9+
if __name__ == "__main__":
10+
print(greet(sys.argv[1] if len(sys.argv) > 1 else "world"))
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/env python3
2+
# sample file to test if python detection, based on first line of file
3+
import hashlib
4+
5+
def compute_hash(data):
6+
return hashlib.sha256(data.encode()).hexdigest()
7+
8+
if __name__ == "__main__":
9+
print(compute_hash("cape"))

0 commit comments

Comments
 (0)