From e112deb3b352576910e0e82be7b59486ffaafed2 Mon Sep 17 00:00:00 2001 From: doomedraven Date: Wed, 30 Oct 2024 14:08:51 +0100 Subject: [PATCH] maco optional (#2380) * maco optional * Update poetry.lock --- poetry.lock | 7 +- pyproject.toml | 2 + tests_parsers/test_agenttesla.py | 54 +++--- tests_parsers/test_asyncrat.py | 43 +++-- tests_parsers/test_aurorastealer.py | 33 ++-- tests_parsers/test_blackdropper.py | 30 ++-- tests_parsers/test_bumblebee.py | 23 ++- tests_parsers/test_carbanak.py | 17 +- tests_parsers/test_cobaltstrikebeacon.py | 126 +++++++------- tests_parsers/test_darkgate.py | 17 +- tests_parsers/test_icedid.py | 19 +- tests_parsers/test_koiloader.py | 24 +-- tests_parsers/test_latrodectus.py | 211 ++++++++++++----------- tests_parsers/test_lumma.py | 61 ++++--- tests_parsers/test_nanocore.py | 119 +++++++------ tests_parsers/test_njrat.py | 25 +-- tests_parsers/test_oyster.py | 29 ++-- tests_parsers/test_pikabot.py | 169 +++++++++--------- tests_parsers/test_quickbind.py | 30 ++-- tests_parsers/test_redline.py | 28 +-- tests_parsers/test_smokeloader.py | 18 +- tests_parsers/test_sparkrat.py | 33 ++-- tests_parsers/test_zloader.py | 30 ++-- 23 files changed, 630 insertions(+), 518 deletions(-) diff --git a/poetry.lock b/poetry.lock index c47b98b49da..9aeb10ad277 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "alembic" @@ -4609,7 +4609,10 @@ docs = ["Sphinx", "repoze.sphinx.autointerface", "sphinx-rtd-theme"] test = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] +[extras] +maco = ["maco"] + [metadata] lock-version = "2.0" python-versions = ">=3.10, <4.0" -content-hash = "d8e5cf52c678477800f15c8cbc7b3aa9a888a98e0cab0c8f4c3e18dd7b30e705" +content-hash = "ab3f807dcdc7fa1fb2098ee2222602ffde65894297ca6b4c3629f2528d584d09" diff --git a/pyproject.toml b/pyproject.toml index 418cbb9aff9..43be4a45a58 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -92,6 +92,8 @@ setproctitle = "1.3.2" # tmp dependency to fix vuln certifi = "2024.7.4" +[tool.poetry.extras] +maco = ["maco"] [tool.poetry.dev-dependencies] black = "^24.3.0" diff --git a/tests_parsers/test_agenttesla.py b/tests_parsers/test_agenttesla.py index 5390edb9b70..37050c3328e 100644 --- a/tests_parsers/test_agenttesla.py +++ b/tests_parsers/test_agenttesla.py @@ -1,5 +1,10 @@ from modules.processing.parsers.CAPE.AgentTesla import extract_config -from modules.processing.parsers.MACO.AgentTesla import convert_to_MACO + +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.AgentTesla import convert_to_MACO + HAVE_MACO = True def test_agenttesla(): @@ -16,26 +21,27 @@ def test_agenttesla(): "ExternalIPCheckServices": ["http://ip-api.com/line/?fields=hosting"], } - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "AgentTesla", - "other": { - "Protocol": "SMTP", - "C2": "mail.guestequipment.com.au", - "Username": "sendlog@guestequipment.com.au", - "Password": "Clone89!", - "EmailTo": "info@marethon.com", - "Persistence_Filename": "newfile.exe", - "ExternalIPCheckServices": ["http://ip-api.com/line/?fields=hosting"], - }, - "smtp": [ - { - "username": "sendlog@guestequipment.com.au", - "password": "Clone89!", - "hostname": "mail.guestequipment.com.au", - "mail_to": ["info@marethon.com"], - "usage": "c2", - } - ], - "http": [{"uri": "http://ip-api.com/line/?fields=hosting", "usage": "other"}], - "paths": [{"path": "newfile.exe", "usage": "storage"}], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "AgentTesla", + "other": { + "Protocol": "SMTP", + "C2": "mail.guestequipment.com.au", + "Username": "sendlog@guestequipment.com.au", + "Password": "Clone89!", + "EmailTo": "info@marethon.com", + "Persistence_Filename": "newfile.exe", + "ExternalIPCheckServices": ["http://ip-api.com/line/?fields=hosting"], + }, + "smtp": [ + { + "username": "sendlog@guestequipment.com.au", + "password": "Clone89!", + "hostname": "mail.guestequipment.com.au", + "mail_to": ["info@marethon.com"], + "usage": "c2", + } + ], + "http": [{"uri": "http://ip-api.com/line/?fields=hosting", "usage": "other"}], + "paths": [{"path": "newfile.exe", "usage": "storage"}], + } diff --git a/tests_parsers/test_asyncrat.py b/tests_parsers/test_asyncrat.py index 376e711751b..8394d0af6d5 100644 --- a/tests_parsers/test_asyncrat.py +++ b/tests_parsers/test_asyncrat.py @@ -1,5 +1,9 @@ from modules.processing.parsers.CAPE.AsyncRAT import extract_config -from modules.processing.parsers.MACO.AsyncRAT import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.AsyncRAT import convert_to_MACO + HAVE_MACO = True def test_asyncrat(): @@ -16,21 +20,22 @@ def test_asyncrat(): "Pastebin": "null", } - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "AsyncRAT", - "version": "0.5.7B", - "capability_disabled": ["persistence"], - "mutex": ["AsyncMutex_6SI8OkPnk"], - "other": { - "C2s": ["todfg.duckdns.org"], - "Ports": "6745", - "Version": "0.5.7B", - "Folder": "%AppData%", - "Filename": "updateee.exe", - "Install": "false", - "Mutex": "AsyncMutex_6SI8OkPnk", - "Pastebin": "null", - }, - "http": [{"hostname": "todfg.duckdns.org", "port": 6, "usage": "c2"}], - "paths": [{"path": "%AppData%/updateee.exe", "usage": "install"}], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "AsyncRAT", + "version": "0.5.7B", + "capability_disabled": ["persistence"], + "mutex": ["AsyncMutex_6SI8OkPnk"], + "other": { + "C2s": ["todfg.duckdns.org"], + "Ports": "6745", + "Version": "0.5.7B", + "Folder": "%AppData%", + "Filename": "updateee.exe", + "Install": "false", + "Mutex": "AsyncMutex_6SI8OkPnk", + "Pastebin": "null", + }, + "http": [{"hostname": "todfg.duckdns.org", "port": 6, "usage": "c2"}], + "paths": [{"path": "%AppData%/updateee.exe", "usage": "install"}], + } diff --git a/tests_parsers/test_aurorastealer.py b/tests_parsers/test_aurorastealer.py index 53af23b3f8c..ddb2b157cb9 100644 --- a/tests_parsers/test_aurorastealer.py +++ b/tests_parsers/test_aurorastealer.py @@ -1,5 +1,9 @@ from modules.processing.parsers.CAPE.AuroraStealer import extract_config -from modules.processing.parsers.MACO.AuroraStealer import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.AuroraStealer import convert_to_MACO + HAVE_MACO = True def test_aurorastealer(): @@ -15,16 +19,17 @@ def test_aurorastealer(): "Date": "2023-04-06 19", } - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "AuroraStealer", - "other": { - "BuildID": "x64pump", - "MD5Hash": "f29f33b296b35ec5e7fc3ee784ef68ee", - "C2": "77.91.85.73", - "Architecture": "X64", - "BuildGroup": "x64pump", - "BuildAccept": "0", - "Date": "2023-04-06 19", - }, - "http": [{"hostname": "77.91.85.73", "usage": "c2"}], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "AuroraStealer", + "other": { + "BuildID": "x64pump", + "MD5Hash": "f29f33b296b35ec5e7fc3ee784ef68ee", + "C2": "77.91.85.73", + "Architecture": "X64", + "BuildGroup": "x64pump", + "BuildAccept": "0", + "Date": "2023-04-06 19", + }, + "http": [{"hostname": "77.91.85.73", "usage": "c2"}], + } diff --git a/tests_parsers/test_blackdropper.py b/tests_parsers/test_blackdropper.py index 7e4dc59d067..d773329c4dc 100644 --- a/tests_parsers/test_blackdropper.py +++ b/tests_parsers/test_blackdropper.py @@ -3,7 +3,12 @@ # See the file 'docs/LICENSE' for copying permission. from modules.processing.parsers.CAPE.BlackDropper import extract_config -from modules.processing.parsers.MACO.BlackDropper import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.BlackDropper import convert_to_MACO + HAVE_MACO = True + def test_blackdropper(): @@ -15,14 +20,15 @@ def test_blackdropper(): "campaign": "oFwQ0aQ3v", } - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "BlackDropper", - "campaign_id": ["oFwQ0aQ3v"], - "other": { - "urls": ["http://72.5.42.222:8568/api/dll/", "http://72.5.42.222:8568/api/fileZip"], - "directories": ["\\Music\\dkcydqtwjv"], - "campaign": "oFwQ0aQ3v", - }, - "http": [{"uri": "http://72.5.42.222:8568/api/dll/"}, {"uri": "http://72.5.42.222:8568/api/fileZip"}], - "paths": [{"path": "\\Music\\dkcydqtwjv"}], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "BlackDropper", + "campaign_id": ["oFwQ0aQ3v"], + "other": { + "urls": ["http://72.5.42.222:8568/api/dll/", "http://72.5.42.222:8568/api/fileZip"], + "directories": ["\\Music\\dkcydqtwjv"], + "campaign": "oFwQ0aQ3v", + }, + "http": [{"uri": "http://72.5.42.222:8568/api/dll/"}, {"uri": "http://72.5.42.222:8568/api/fileZip"}], + "paths": [{"path": "\\Music\\dkcydqtwjv"}], + } diff --git a/tests_parsers/test_bumblebee.py b/tests_parsers/test_bumblebee.py index fd06f12ee10..3ac5f6b57c7 100644 --- a/tests_parsers/test_bumblebee.py +++ b/tests_parsers/test_bumblebee.py @@ -3,18 +3,23 @@ # See the file 'docs/LICENSE' for copying permission. from modules.processing.parsers.CAPE.BumbleBee import extract_config -from modules.processing.parsers.MACO.BumbleBee import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.BumbleBee import convert_to_MACO + HAVE_MACO = True def test_bumblebee(): with open("tests/data/malware/f8a6eddcec59934c42ea254cdd942fb62917b5898f71f0feeae6826ba4f3470d", "rb") as data: conf = extract_config(data.read()) assert conf == {"Botnet ID": "YTBSBbNTWU", "Campaign ID": "1904r", "Data": "XNgHUGLrCD", "C2s": ["444"]} - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "BumbleBee", - "campaign_id": ["1904r"], - "identifier": ["YTBSBbNTWU"], - "other": {"Botnet ID": "YTBSBbNTWU", "Campaign ID": "1904r", "Data": "XNgHUGLrCD", "C2s": ["444"]}, - "binaries": [{"data": "XNgHUGLrCD"}], - "http": [{"hostname": "444", "usage": "c2"}], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "BumbleBee", + "campaign_id": ["1904r"], + "identifier": ["YTBSBbNTWU"], + "other": {"Botnet ID": "YTBSBbNTWU", "Campaign ID": "1904r", "Data": "XNgHUGLrCD", "C2s": ["444"]}, + "binaries": [{"data": "XNgHUGLrCD"}], + "http": [{"hostname": "444", "usage": "c2"}], + } diff --git a/tests_parsers/test_carbanak.py b/tests_parsers/test_carbanak.py index 8d5169fea96..cb93c32bd58 100644 --- a/tests_parsers/test_carbanak.py +++ b/tests_parsers/test_carbanak.py @@ -1,13 +1,18 @@ from modules.processing.parsers.CAPE.Carbanak import extract_config -from modules.processing.parsers.MACO.Carbanak import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.Carbanak import convert_to_MACO + HAVE_MACO = True def test_carbanak(): with open("tests/data/malware/c9c1b06cb9c9bd6fc4451f5e2847a1f9524bb2870d7bb6f0ee09b9dd4e3e4c84", "rb") as data: conf = extract_config(data.read()) assert conf["C2"] == ["5.161.223.210:443", "207.174.30.226:443"] - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "Carbanak", - "other": {"C2": ["5.161.223.210:443", "207.174.30.226:443"]}, - "http": [{"hostname": "5.161.223.210:443", "usage": "c2"}, {"hostname": "207.174.30.226:443", "usage": "c2"}], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "Carbanak", + "other": {"C2": ["5.161.223.210:443", "207.174.30.226:443"]}, + "http": [{"hostname": "5.161.223.210:443", "usage": "c2"}, {"hostname": "207.174.30.226:443", "usage": "c2"}], + } diff --git a/tests_parsers/test_cobaltstrikebeacon.py b/tests_parsers/test_cobaltstrikebeacon.py index 47c26163b54..1c6451afec6 100644 --- a/tests_parsers/test_cobaltstrikebeacon.py +++ b/tests_parsers/test_cobaltstrikebeacon.py @@ -3,7 +3,12 @@ # See the file 'docs/LICENSE' for copying permission. from modules.processing.parsers.CAPE.CobaltStrikeBeacon import extract_config -from modules.processing.parsers.MACO.CobaltStrikeBeacon import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.CobaltStrikeBeacon import convert_to_MACO + HAVE_MACO = True + def test_csb(): @@ -56,62 +61,63 @@ def test_csb(): "bUsesCookies": "True", "HostHeader": "", } - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "CobaltStrikeBeacon", - "capability_enabled": ["ProcInject_StartRWX", "ProcInject_UseRWX", "UsesCookies"], - "capability_disabled": ["StageCleanup", "CFGCaution"], - "sleep_delay": 60000, - "sleep_delay_jitter": 0, - "other": { - "BeaconType": ["HTTP"], - "Port": 4848, - "SleepTime": 60000, - "MaxGetSize": 1048576, - "Jitter": 0, - "MaxDNS": "Not Found", - "PublicKey": "30819f300d06092a864886f70d010101050003818d0030818902818100bebe41805d3c15a738caf3e308a992d4d507ce827996a8c9d783c766963e7e73083111729ae0abc1b49af0bcf803efdcaf83ac694fb53d043a88e9333f169e026a3c4e63cc6d4cd1aa5e199cb95eec500f948ac472c0ab2eda385d35fb8592d74b1154a1c671afb310eccb0b139ee1100907bfcdd8dfbf3385803a11bc252995020301000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "C2Server": "192.144.206.100,/load", - "UserAgent": "Not Found", - "HttpPostUri": "/submit.php", - "Malleable_C2_Instructions": [], - "HttpGet_Metadata": "Not Found", - "HttpPost_Metadata": "Not Found", - "SpawnTo": "d7a9ca15a07f82bfd3b63020da38aa16", - "PipeName": "Not Found", - "DNS_Idle": "Not Found", - "DNS_Sleep": "Not Found", - "SSH_Host": "Not Found", - "SSH_Port": "Not Found", - "SSH_Username": "Not Found", - "SSH_Password_Plaintext": "Not Found", - "SSH_Password_Pubkey": "Not Found", - "HttpGet_Verb": "GET", - "HttpPost_Verb": "POST", - "HttpPostChunk": 0, - "Spawnto_x86": "%windir%\\syswow64\\rundll32.exe", - "Spawnto_x64": "%windir%\\sysnative\\rundll32.exe", - "CryptoScheme": 0, - "Proxy_Config": "Not Found", - "Proxy_User": "Not Found", - "Proxy_Password": "Not Found", - "Proxy_Behavior": "Use IE settings", - "Watermark": 391144938, - "bStageCleanup": "False", - "bCFGCaution": "False", - "KillDate": 0, - "bProcInject_StartRWX": "True", - "bProcInject_UseRWX": "True", - "bProcInject_MinAllocSize": 0, - "ProcInject_PrependAppend_x86": "Empty", - "ProcInject_PrependAppend_x64": "Empty", - "ProcInject_Execute": ["CreateThread", "SetThreadContext", "CreateRemoteThread", "RtlCreateUserThread"], - "ProcInject_AllocationMethod": "VirtualAllocEx", - "bUsesCookies": "True", - "HostHeader": "", - }, - "http": [ - {"hostname": "192.144.206.100", "port": 4848, "path": "/load", "method": "GET", "usage": "c2"}, - {"hostname": "192.144.206.100", "port": 4848, "path": "/submit.php", "method": "POST", "usage": "c2"}, - ], - "paths": [{"path": "%windir%\\syswow64\\rundll32.exe"}, {"path": "%windir%\\sysnative\\rundll32.exe"}], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "CobaltStrikeBeacon", + "capability_enabled": ["ProcInject_StartRWX", "ProcInject_UseRWX", "UsesCookies"], + "capability_disabled": ["StageCleanup", "CFGCaution"], + "sleep_delay": 60000, + "sleep_delay_jitter": 0, + "other": { + "BeaconType": ["HTTP"], + "Port": 4848, + "SleepTime": 60000, + "MaxGetSize": 1048576, + "Jitter": 0, + "MaxDNS": "Not Found", + "PublicKey": "30819f300d06092a864886f70d010101050003818d0030818902818100bebe41805d3c15a738caf3e308a992d4d507ce827996a8c9d783c766963e7e73083111729ae0abc1b49af0bcf803efdcaf83ac694fb53d043a88e9333f169e026a3c4e63cc6d4cd1aa5e199cb95eec500f948ac472c0ab2eda385d35fb8592d74b1154a1c671afb310eccb0b139ee1100907bfcdd8dfbf3385803a11bc252995020301000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "C2Server": "192.144.206.100,/load", + "UserAgent": "Not Found", + "HttpPostUri": "/submit.php", + "Malleable_C2_Instructions": [], + "HttpGet_Metadata": "Not Found", + "HttpPost_Metadata": "Not Found", + "SpawnTo": "d7a9ca15a07f82bfd3b63020da38aa16", + "PipeName": "Not Found", + "DNS_Idle": "Not Found", + "DNS_Sleep": "Not Found", + "SSH_Host": "Not Found", + "SSH_Port": "Not Found", + "SSH_Username": "Not Found", + "SSH_Password_Plaintext": "Not Found", + "SSH_Password_Pubkey": "Not Found", + "HttpGet_Verb": "GET", + "HttpPost_Verb": "POST", + "HttpPostChunk": 0, + "Spawnto_x86": "%windir%\\syswow64\\rundll32.exe", + "Spawnto_x64": "%windir%\\sysnative\\rundll32.exe", + "CryptoScheme": 0, + "Proxy_Config": "Not Found", + "Proxy_User": "Not Found", + "Proxy_Password": "Not Found", + "Proxy_Behavior": "Use IE settings", + "Watermark": 391144938, + "bStageCleanup": "False", + "bCFGCaution": "False", + "KillDate": 0, + "bProcInject_StartRWX": "True", + "bProcInject_UseRWX": "True", + "bProcInject_MinAllocSize": 0, + "ProcInject_PrependAppend_x86": "Empty", + "ProcInject_PrependAppend_x64": "Empty", + "ProcInject_Execute": ["CreateThread", "SetThreadContext", "CreateRemoteThread", "RtlCreateUserThread"], + "ProcInject_AllocationMethod": "VirtualAllocEx", + "bUsesCookies": "True", + "HostHeader": "", + }, + "http": [ + {"hostname": "192.144.206.100", "port": 4848, "path": "/load", "method": "GET", "usage": "c2"}, + {"hostname": "192.144.206.100", "port": 4848, "path": "/submit.php", "method": "POST", "usage": "c2"}, + ], + "paths": [{"path": "%windir%\\syswow64\\rundll32.exe"}, {"path": "%windir%\\sysnative\\rundll32.exe"}], + } diff --git a/tests_parsers/test_darkgate.py b/tests_parsers/test_darkgate.py index 9a32a515a5a..7a46843a84e 100644 --- a/tests_parsers/test_darkgate.py +++ b/tests_parsers/test_darkgate.py @@ -1,13 +1,18 @@ from modules.processing.parsers.CAPE.DarkGate import extract_config -from modules.processing.parsers.MACO.DarkGate import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.DarkGate import convert_to_MACO + HAVE_MACO = True def test_darkgate(): with open("tests/data/malware/1c3ae64795b61034080be00601b947819fe071efd69d7fc791a99ec666c2043d", "rb") as data: conf = extract_config(data.read()) assert conf["C2"] == ["http://80.66.88.145"] - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "DarkGate", - "other": {"C2": ["http://80.66.88.145"]}, - "http": [{"uri": "http://80.66.88.145", "usage": "c2"}], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "DarkGate", + "other": {"C2": ["http://80.66.88.145"]}, + "http": [{"uri": "http://80.66.88.145", "usage": "c2"}], + } diff --git a/tests_parsers/test_icedid.py b/tests_parsers/test_icedid.py index 590591c2701..4a8c93fc529 100644 --- a/tests_parsers/test_icedid.py +++ b/tests_parsers/test_icedid.py @@ -1,14 +1,19 @@ from modules.processing.parsers.CAPE.IcedIDLoader import extract_config -from modules.processing.parsers.MACO.IcedIDLoader import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.IcedIDLoader import convert_to_MACO + HAVE_MACO = True def test_icedid(): with open("tests/data/malware/7aaf80eb1436b946b2bd710ab57d2dcbaad2b1553d45602f2f3af6f2cfca5212", "rb") as data: conf = extract_config(data.read()) assert conf == {"C2": "anscowerbrut.com", "Campaign": 2738000827} - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "IcedIDLoader", - "campaign_id": ["2738000827"], - "other": {"C2": "anscowerbrut.com", "Campaign": 2738000827}, - "http": [{"hostname": "anscowerbrut.com", "usage": "c2"}], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "IcedIDLoader", + "campaign_id": ["2738000827"], + "other": {"C2": "anscowerbrut.com", "Campaign": 2738000827}, + "http": [{"hostname": "anscowerbrut.com", "usage": "c2"}], + } diff --git a/tests_parsers/test_koiloader.py b/tests_parsers/test_koiloader.py index 8844a08acef..0e9a3a01020 100644 --- a/tests_parsers/test_koiloader.py +++ b/tests_parsers/test_koiloader.py @@ -3,18 +3,22 @@ # See the file 'docs/LICENSE' for copying permission. from modules.processing.parsers.CAPE.KoiLoader import extract_config -from modules.processing.parsers.MACO.KoiLoader import convert_to_MACO - +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.KoiLoader import convert_to_MACO + HAVE_MACO = True def test_koiloader(): with open("tests/data/malware/b462e3235c7578450b2b56a8aff875a3d99d22f6970a01db3ba98f7ecb6b01a0", "rb") as data: conf = extract_config(data.read()) assert conf == {"C2": ["http://91.202.233.209/hypermetropia.php", "https://admiralpub.ca/wp-content/uploads/2017"]} - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "KoiLoader", - "other": {"C2": ["http://91.202.233.209/hypermetropia.php", "https://admiralpub.ca/wp-content/uploads/2017"]}, - "http": [ - {"uri": "http://91.202.233.209/hypermetropia.php", "usage": "c2"}, - {"uri": "https://admiralpub.ca/wp-content/uploads/2017", "usage": "c2"}, - ], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "KoiLoader", + "other": {"C2": ["http://91.202.233.209/hypermetropia.php", "https://admiralpub.ca/wp-content/uploads/2017"]}, + "http": [ + {"uri": "http://91.202.233.209/hypermetropia.php", "usage": "c2"}, + {"uri": "https://admiralpub.ca/wp-content/uploads/2017", "usage": "c2"}, + ], + } diff --git a/tests_parsers/test_latrodectus.py b/tests_parsers/test_latrodectus.py index d71d20a4977..31aab069bad 100644 --- a/tests_parsers/test_latrodectus.py +++ b/tests_parsers/test_latrodectus.py @@ -3,7 +3,11 @@ # See the file 'docs/LICENSE' for copying permission. from modules.processing.parsers.CAPE.Latrodectus import extract_config -from modules.processing.parsers.MACO.Latrodectus import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.Latrodectus import convert_to_MACO + HAVE_MACO = True def test_latrodectus(): @@ -99,101 +103,13 @@ def test_latrodectus(): "URLS|%d|%s\r\n", ], } - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "Latrodectus", - "version": "1.1", - "campaign_id": ["1053565364"], - "identifier": ["Novik"], - "decoded_strings": [ - "/c ipconfig /all", - "C:\\Windows\\System32\\cmd.exe", - "/c systeminfo", - "C:\\Windows\\System32\\cmd.exe", - "/c nltest /domain_trusts", - "C:\\Windows\\System32\\cmd.exe", - "/c nltest /domain_trusts /all_trusts", - "C:\\Windows\\System32\\cmd.exe", - "/c net view /all /domain", - "C:\\Windows\\System32\\cmd.exe", - "/c net view /all", - "C:\\Windows\\System32\\cmd.exe", - '/c net group "Domain Admins" /domain', - "C:\\Windows\\System32\\cmd.exe", - "/Node:localhost /Namespace:\\\\root\\SecurityCenter2 Path AntiVirusProduct Get * /Format:List", - "C:\\Windows\\System32\\wbem\\wmic.exe", - "/c net config workstation", - "C:\\Windows\\System32\\cmd.exe", - "/c wmic.exe /node:localhost /namespace:\\\\root\\SecurityCenter2 path AntiVirusProduct Get DisplayName | findstr /V /B /C:displayName || echo No Antivirus installed", - "C:\\Windows\\System32\\cmd.exe", - "/c whoami /groups", - "C:\\Windows\\System32\\cmd.exe", - ".dll", - ".exe", - '"%s"', - "rundll32.exe", - '"%s", %s %s', - "runnung", - ":wtfbbq", - "%s%s", - "%s\\%d.dll", - "%d.dat", - "%s\\%s", - 'init -zzzz="%s\\%s"', - "front", - "/files/", - "Novik", - ".exe", - "Content-Type: application/x-www-form-urlencoded", - "POST", - "GET", - "curl/7.88.1", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Tob 1.1)", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Tob 1.1)", - "CLEARURL", - "URLS", - "COMMAND", - "ERROR", - "12345", - "counter=%d&type=%d&guid=%s&os=%d&arch=%d&username=%s&group=%lu&ver=%d.%d&up=%d&direction=%s", - "counter=%d&type=%d&guid=%s&os=%d&arch=%d&username=%s&group=%lu&ver=%d.%d&up=%d&direction=%s", - "counter=%d&type=%d&guid=%s&os=%d&arch=%d&username=%s&group=%lu&ver=%d.%d&up=%d&direction=%s", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Tob 1.1)", - "%s%d.dll", - "%s%d.exe", - "LogonTrigger", - "%x%x", - "TimeTrigger", - "PT1H%02dM", - "&mac=", - "%04d-%02d-%02dT%02d:%02d:%02d", - "%02x", - ":%02x", - "PT0S", - "&computername=%s", - "&domain=%s", - "\\*.dll", - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", - "%04X%04X%04X%04X%08X%04X", - "%04X%04X%04X%04X%08X%04X", - "\\Registry\\Machine\\", - "AppData", - "Desktop", - "Startup", - "Personal", - "Local AppData", - "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", - "C:\\WINDOWS\\SYSTEM32\\rundll32.exe %s,%s", - "C:\\WINDOWS\\SYSTEM32\\rundll32.exe %s", - "URLS", - "URLS|%d|%s\r\n", - ], - "other": { - "C2": ["https://arsimonopa.com/live/", "https://lemonimonakio.com/live/"], - "Group name": "Novik", - "Campaign ID": 1053565364, - "Version": "1.1", - "RC4 key": "12345", - "Strings": [ + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "Latrodectus", + "version": "1.1", + "campaign_id": ["1053565364"], + "identifier": ["Novik"], + "decoded_strings": [ "/c ipconfig /all", "C:\\Windows\\System32\\cmd.exe", "/c systeminfo", @@ -276,10 +192,99 @@ def test_latrodectus(): "URLS", "URLS|%d|%s\r\n", ], - }, - "http": [ - {"uri": "https://arsimonopa.com/live/", "usage": "c2"}, - {"uri": "https://lemonimonakio.com/live/", "usage": "c2"}, - ], - "encryption": [{"algorithm": "RC4", "key": "12345"}], - } + "other": { + "C2": ["https://arsimonopa.com/live/", "https://lemonimonakio.com/live/"], + "Group name": "Novik", + "Campaign ID": 1053565364, + "Version": "1.1", + "RC4 key": "12345", + "Strings": [ + "/c ipconfig /all", + "C:\\Windows\\System32\\cmd.exe", + "/c systeminfo", + "C:\\Windows\\System32\\cmd.exe", + "/c nltest /domain_trusts", + "C:\\Windows\\System32\\cmd.exe", + "/c nltest /domain_trusts /all_trusts", + "C:\\Windows\\System32\\cmd.exe", + "/c net view /all /domain", + "C:\\Windows\\System32\\cmd.exe", + "/c net view /all", + "C:\\Windows\\System32\\cmd.exe", + '/c net group "Domain Admins" /domain', + "C:\\Windows\\System32\\cmd.exe", + "/Node:localhost /Namespace:\\\\root\\SecurityCenter2 Path AntiVirusProduct Get * /Format:List", + "C:\\Windows\\System32\\wbem\\wmic.exe", + "/c net config workstation", + "C:\\Windows\\System32\\cmd.exe", + "/c wmic.exe /node:localhost /namespace:\\\\root\\SecurityCenter2 path AntiVirusProduct Get DisplayName | findstr /V /B /C:displayName || echo No Antivirus installed", + "C:\\Windows\\System32\\cmd.exe", + "/c whoami /groups", + "C:\\Windows\\System32\\cmd.exe", + ".dll", + ".exe", + '"%s"', + "rundll32.exe", + '"%s", %s %s', + "runnung", + ":wtfbbq", + "%s%s", + "%s\\%d.dll", + "%d.dat", + "%s\\%s", + 'init -zzzz="%s\\%s"', + "front", + "/files/", + "Novik", + ".exe", + "Content-Type: application/x-www-form-urlencoded", + "POST", + "GET", + "curl/7.88.1", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Tob 1.1)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Tob 1.1)", + "CLEARURL", + "URLS", + "COMMAND", + "ERROR", + "12345", + "counter=%d&type=%d&guid=%s&os=%d&arch=%d&username=%s&group=%lu&ver=%d.%d&up=%d&direction=%s", + "counter=%d&type=%d&guid=%s&os=%d&arch=%d&username=%s&group=%lu&ver=%d.%d&up=%d&direction=%s", + "counter=%d&type=%d&guid=%s&os=%d&arch=%d&username=%s&group=%lu&ver=%d.%d&up=%d&direction=%s", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Tob 1.1)", + "%s%d.dll", + "%s%d.exe", + "LogonTrigger", + "%x%x", + "TimeTrigger", + "PT1H%02dM", + "&mac=", + "%04d-%02d-%02dT%02d:%02d:%02d", + "%02x", + ":%02x", + "PT0S", + "&computername=%s", + "&domain=%s", + "\\*.dll", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + "%04X%04X%04X%04X%08X%04X", + "%04X%04X%04X%04X%08X%04X", + "\\Registry\\Machine\\", + "AppData", + "Desktop", + "Startup", + "Personal", + "Local AppData", + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", + "C:\\WINDOWS\\SYSTEM32\\rundll32.exe %s,%s", + "C:\\WINDOWS\\SYSTEM32\\rundll32.exe %s", + "URLS", + "URLS|%d|%s\r\n", + ], + }, + "http": [ + {"uri": "https://arsimonopa.com/live/", "usage": "c2"}, + {"uri": "https://lemonimonakio.com/live/", "usage": "c2"}, + ], + "encryption": [{"algorithm": "RC4", "key": "12345"}], + } diff --git a/tests_parsers/test_lumma.py b/tests_parsers/test_lumma.py index 6f13eb15f3e..c681636e01b 100644 --- a/tests_parsers/test_lumma.py +++ b/tests_parsers/test_lumma.py @@ -3,7 +3,11 @@ # See the file 'docs/LICENSE' for copying permission. from modules.processing.parsers.CAPE.Lumma import extract_config -from modules.processing.parsers.MACO.Lumma import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.Lumma import convert_to_MACO + HAVE_MACO = True def test_lumma(): @@ -22,30 +26,31 @@ def test_lumma(): "agentyanlark.site", ] } - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "Lumma", - "other": { - "C2": [ - "delaylacedmn.site", - "writekdmsnu.site", - "agentyanlark.site", - "bellykmrebk.site", - "underlinemdsj.site", - "commandejorsk.site", - "possiwreeste.site", - "famikyjdiag.site", - "agentyanlark.site", - ] - }, - "http": [ - {"hostname": "delaylacedmn.site", "usage": "c2"}, - {"hostname": "writekdmsnu.site", "usage": "c2"}, - {"hostname": "agentyanlark.site", "usage": "c2"}, - {"hostname": "bellykmrebk.site", "usage": "c2"}, - {"hostname": "underlinemdsj.site", "usage": "c2"}, - {"hostname": "commandejorsk.site", "usage": "c2"}, - {"hostname": "possiwreeste.site", "usage": "c2"}, - {"hostname": "famikyjdiag.site", "usage": "c2"}, - {"hostname": "agentyanlark.site", "usage": "c2"}, - ], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "Lumma", + "other": { + "C2": [ + "delaylacedmn.site", + "writekdmsnu.site", + "agentyanlark.site", + "bellykmrebk.site", + "underlinemdsj.site", + "commandejorsk.site", + "possiwreeste.site", + "famikyjdiag.site", + "agentyanlark.site", + ] + }, + "http": [ + {"hostname": "delaylacedmn.site", "usage": "c2"}, + {"hostname": "writekdmsnu.site", "usage": "c2"}, + {"hostname": "agentyanlark.site", "usage": "c2"}, + {"hostname": "bellykmrebk.site", "usage": "c2"}, + {"hostname": "underlinemdsj.site", "usage": "c2"}, + {"hostname": "commandejorsk.site", "usage": "c2"}, + {"hostname": "possiwreeste.site", "usage": "c2"}, + {"hostname": "famikyjdiag.site", "usage": "c2"}, + {"hostname": "agentyanlark.site", "usage": "c2"}, + ], + } diff --git a/tests_parsers/test_nanocore.py b/tests_parsers/test_nanocore.py index 445f2127e82..c0aeba7a3a4 100644 --- a/tests_parsers/test_nanocore.py +++ b/tests_parsers/test_nanocore.py @@ -3,7 +3,11 @@ # See the file 'docs/LICENSE' for copying permission. from modules.processing.parsers.CAPE.NanoCore import extract_config -from modules.processing.parsers.MACO.NanoCore import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.NanoCore import convert_to_MACO + HAVE_MACO = True def test_nanocore(): @@ -42,59 +46,60 @@ def test_nanocore(): "BackupDnsServer": "8.8.4.4", "cncs": ["6coinc.zapto.org:6696", "127.0.0.1:6696"], } - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "NanoCore", - "version": "1.2.2.0", - "capability_enabled": [ - "RunOnStartup", - "BypassUserAccountControl", - "ClearZoneIdentifier", - "PreventSystemSleep", - "UseCustomDnsServer", - ], - "capability_disabled": [ - "RequestElevation", - "ClearAccessControl", - "SetCriticalProcess", - "ActivateAwayMode", - "EnableDebugMode", - ], - "mutex": ["dc5ce709-95b6-4a26-9175-16a1a8446828"], - "other": { - "BuildTime": "2023-11-22 00:25:26.569697", - "Version": "1.2.2.0", - "Mutex": "dc5ce709-95b6-4a26-9175-16a1a8446828", - "DefaultGroup": "6coinc", - "PrimaryConnectionHost": "6coinc.zapto.org", - "BackupConnectionHost": "127.0.0.1", - "ConnectionPort": "6696", - "RunOnStartup": "True", - "RequestElevation": "False", - "BypassUserAccountControl": "True", - "ClearZoneIdentifier": "True", - "ClearAccessControl": "False", - "SetCriticalProcess": "False", - "PreventSystemSleep": "True", - "ActivateAwayMode": "False", - "EnableDebugMode": "False", - "RunDelay": "0", - "ConnectDelay": "4000", - "RestartDelay": "5000", - "TimeoutInterval": "5000", - "KeepAliveTimeout": "30000", - "MutexTimeout": "5000", - "LanTimeout": "2500", - "WanTimeout": "8000", - "BufferSize": "65535", - "MaxPacketSize": "10485760", - "GCThreshold": "10485760", - "UseCustomDnsServer": "True", - "PrimaryDnsServer": "8.8.8.8", - "BackupDnsServer": "8.8.4.4", - "cncs": ["6coinc.zapto.org:6696", "127.0.0.1:6696"], - }, - "http": [ - {"hostname": "6coinc.zapto.org", "port": 6696, "usage": "c2"}, - {"hostname": "127.0.0.1", "port": 6696, "usage": "c2"}, - ], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "NanoCore", + "version": "1.2.2.0", + "capability_enabled": [ + "RunOnStartup", + "BypassUserAccountControl", + "ClearZoneIdentifier", + "PreventSystemSleep", + "UseCustomDnsServer", + ], + "capability_disabled": [ + "RequestElevation", + "ClearAccessControl", + "SetCriticalProcess", + "ActivateAwayMode", + "EnableDebugMode", + ], + "mutex": ["dc5ce709-95b6-4a26-9175-16a1a8446828"], + "other": { + "BuildTime": "2023-11-22 00:25:26.569697", + "Version": "1.2.2.0", + "Mutex": "dc5ce709-95b6-4a26-9175-16a1a8446828", + "DefaultGroup": "6coinc", + "PrimaryConnectionHost": "6coinc.zapto.org", + "BackupConnectionHost": "127.0.0.1", + "ConnectionPort": "6696", + "RunOnStartup": "True", + "RequestElevation": "False", + "BypassUserAccountControl": "True", + "ClearZoneIdentifier": "True", + "ClearAccessControl": "False", + "SetCriticalProcess": "False", + "PreventSystemSleep": "True", + "ActivateAwayMode": "False", + "EnableDebugMode": "False", + "RunDelay": "0", + "ConnectDelay": "4000", + "RestartDelay": "5000", + "TimeoutInterval": "5000", + "KeepAliveTimeout": "30000", + "MutexTimeout": "5000", + "LanTimeout": "2500", + "WanTimeout": "8000", + "BufferSize": "65535", + "MaxPacketSize": "10485760", + "GCThreshold": "10485760", + "UseCustomDnsServer": "True", + "PrimaryDnsServer": "8.8.8.8", + "BackupDnsServer": "8.8.4.4", + "cncs": ["6coinc.zapto.org:6696", "127.0.0.1:6696"], + }, + "http": [ + {"hostname": "6coinc.zapto.org", "port": 6696, "usage": "c2"}, + {"hostname": "127.0.0.1", "port": 6696, "usage": "c2"}, + ], + } diff --git a/tests_parsers/test_njrat.py b/tests_parsers/test_njrat.py index 5fb816a30a1..17729a6d9c1 100644 --- a/tests_parsers/test_njrat.py +++ b/tests_parsers/test_njrat.py @@ -3,7 +3,11 @@ # See the file 'docs/LICENSE' for copying permission. from modules.processing.parsers.CAPE.Njrat import extract_config -from modules.processing.parsers.MACO.Njrat import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.Njrat import convert_to_MACO + HAVE_MACO = True def test_njrat(): @@ -14,16 +18,17 @@ def test_njrat(): "campaign id": "HacKed", "version": "Njrat 0.7 Golden By Hassan Amiri", } - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "Njrat", - "version": "Njrat 0.7 Golden By Hassan Amiri", - "other": { - "cncs": ["peter-bikini.gl.at.ply.gg:64215"], - "campaign id": "HacKed", + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "Njrat", "version": "Njrat 0.7 Golden By Hassan Amiri", - }, - "http": [{"hostname": "peter-bikini.gl.at.ply.gg", "port": 64215, "usage": "c2"}], - } + "other": { + "cncs": ["peter-bikini.gl.at.ply.gg:64215"], + "campaign id": "HacKed", + "version": "Njrat 0.7 Golden By Hassan Amiri", + }, + "http": [{"hostname": "peter-bikini.gl.at.ply.gg", "port": 64215, "usage": "c2"}], + } """ diff --git a/tests_parsers/test_oyster.py b/tests_parsers/test_oyster.py index ed758e42362..d831764f686 100644 --- a/tests_parsers/test_oyster.py +++ b/tests_parsers/test_oyster.py @@ -3,7 +3,11 @@ # See the file 'docs/LICENSE' for copying permission. from modules.processing.parsers.CAPE.Oyster import extract_config -from modules.processing.parsers.MACO.Oyster import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.Oyster import convert_to_MACO + HAVE_MACO = True def test_oyster(): @@ -14,14 +18,15 @@ def test_oyster(): "Dll Version": "v1.0 #ads 2", "Strings": ["api/connect", "Content-Type: application/json", "api/session"], } - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "Oyster", - "version": "v1.0 #ads 2", - "decoded_strings": ["api/connect", "Content-Type: application/json", "api/session"], - "other": { - "C2": ["https://connectivity-check.linkpc.net/"], - "Dll Version": "v1.0 #ads 2", - "Strings": ["api/connect", "Content-Type: application/json", "api/session"], - }, - "http": [{"uri": "https://connectivity-check.linkpc.net/", "usage": "c2"}], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "Oyster", + "version": "v1.0 #ads 2", + "decoded_strings": ["api/connect", "Content-Type: application/json", "api/session"], + "other": { + "C2": ["https://connectivity-check.linkpc.net/"], + "Dll Version": "v1.0 #ads 2", + "Strings": ["api/connect", "Content-Type: application/json", "api/session"], + }, + "http": [{"uri": "https://connectivity-check.linkpc.net/", "usage": "c2"}], + } diff --git a/tests_parsers/test_pikabot.py b/tests_parsers/test_pikabot.py index 18bc7018f06..318b9f17a06 100644 --- a/tests_parsers/test_pikabot.py +++ b/tests_parsers/test_pikabot.py @@ -3,7 +3,11 @@ # See the file 'docs/LICENSE' for copying permission. from modules.processing.parsers.CAPE.PikaBot import extract_config -from modules.processing.parsers.MACO.PikaBot import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.PikaBot import convert_to_MACO + HAVE_MACO = True def test_pikabot(): @@ -28,85 +32,86 @@ def test_pikabot(): "Campaign Name": "GG24_T@T@f0adda360d2b4ccda11468e026526576", "Registry Key": "MWnkl", } - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "PikaBot", - "version": "1.8.32-beta", - "campaign_id": ["GG24_T@T@f0adda360d2b4ccda11468e026526576"], - "other": { - "C2s": [ - "154.53.55.165:13783", - "158.247.240.58:5632", - "70.34.223.164:5000", - "70.34.199.64:9785", - "45.77.63.237:5632", - "198.38.94.213:2224", - "94.72.104.80:5000", - "84.46.240.42:2083", - "154.12.236.248:13786", - "94.72.104.77:13724", - "209.126.86.48:1194", - ], - "Version": "1.8.32-beta", - "User Agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", - "Campaign Name": "GG24_T@T@f0adda360d2b4ccda11468e026526576", - "Registry Key": "MWnkl", - }, - "http": [ - { - "hostname": "154.53.55.165", - "port": 13783, - "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", - }, - { - "hostname": "158.247.240.58", - "port": 5632, - "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", - }, - { - "hostname": "70.34.223.164", - "port": 5000, - "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", - }, - { - "hostname": "70.34.199.64", - "port": 9785, - "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", - }, - { - "hostname": "45.77.63.237", - "port": 5632, - "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", - }, - { - "hostname": "198.38.94.213", - "port": 2224, - "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", - }, - { - "hostname": "94.72.104.80", - "port": 5000, - "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "PikaBot", + "version": "1.8.32-beta", + "campaign_id": ["GG24_T@T@f0adda360d2b4ccda11468e026526576"], + "other": { + "C2s": [ + "154.53.55.165:13783", + "158.247.240.58:5632", + "70.34.223.164:5000", + "70.34.199.64:9785", + "45.77.63.237:5632", + "198.38.94.213:2224", + "94.72.104.80:5000", + "84.46.240.42:2083", + "154.12.236.248:13786", + "94.72.104.77:13724", + "209.126.86.48:1194", + ], + "Version": "1.8.32-beta", + "User Agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", + "Campaign Name": "GG24_T@T@f0adda360d2b4ccda11468e026526576", + "Registry Key": "MWnkl", }, - { - "hostname": "84.46.240.42", - "port": 2083, - "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", - }, - { - "hostname": "154.12.236.248", - "port": 13786, - "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", - }, - { - "hostname": "94.72.104.77", - "port": 13724, - "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", - }, - { - "hostname": "209.126.86.48", - "port": 1194, - "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", - }, - ], - "registry": [{"key": "MWnkl"}], - } + "http": [ + { + "hostname": "154.53.55.165", + "port": 13783, + "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", + }, + { + "hostname": "158.247.240.58", + "port": 5632, + "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", + }, + { + "hostname": "70.34.223.164", + "port": 5000, + "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", + }, + { + "hostname": "70.34.199.64", + "port": 9785, + "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", + }, + { + "hostname": "45.77.63.237", + "port": 5632, + "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", + }, + { + "hostname": "198.38.94.213", + "port": 2224, + "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", + }, + { + "hostname": "94.72.104.80", + "port": 5000, + "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", + }, + { + "hostname": "84.46.240.42", + "port": 2083, + "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", + }, + { + "hostname": "154.12.236.248", + "port": 13786, + "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", + }, + { + "hostname": "94.72.104.77", + "port": 13724, + "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", + }, + { + "hostname": "209.126.86.48", + "port": 1194, + "user_agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; A7F; BRI/2; Tablet PC 2.0; wbx 1.0.0; Microsoft Outlook 14.0.7233; ms-office;", + }, + ], + "registry": [{"key": "MWnkl"}], + } diff --git a/tests_parsers/test_quickbind.py b/tests_parsers/test_quickbind.py index 91a2248dd70..19dac107ae0 100644 --- a/tests_parsers/test_quickbind.py +++ b/tests_parsers/test_quickbind.py @@ -3,8 +3,11 @@ # See the file 'docs/LICENSE' for copying permission. from modules.processing.parsers.CAPE.Quickbind import extract_config -from modules.processing.parsers.MACO.Quickbind import convert_to_MACO - +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.Quickbind import convert_to_MACO + HAVE_MACO = True def test_quickbind(): with open("tests/data/malware/bfcb215f86fc4f8b4829f6ddd5acb118e80fb5bd977453fc7e8ef10a52fc83b7", "rb") as data: @@ -14,14 +17,15 @@ def test_quickbind(): "Mutex": ["15432a4d-34ca-4d0d-a4ac-04df9a373862"], "C2": ["185.49.69.41"], } - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "Quickbind", - "mutex": ["15432a4d-34ca-4d0d-a4ac-04df9a373862"], - "other": { - "Encryption Key": "24de21a8dc08434c", - "Mutex": ["15432a4d-34ca-4d0d-a4ac-04df9a373862"], - "C2": ["185.49.69.41"], - }, - "http": [{"hostname": "185.49.69.41", "usage": "c2"}], - "encryption": [{"key": "24de21a8dc08434c"}], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "Quickbind", + "mutex": ["15432a4d-34ca-4d0d-a4ac-04df9a373862"], + "other": { + "Encryption Key": "24de21a8dc08434c", + "Mutex": ["15432a4d-34ca-4d0d-a4ac-04df9a373862"], + "C2": ["185.49.69.41"], + }, + "http": [{"hostname": "185.49.69.41", "usage": "c2"}], + "encryption": [{"key": "24de21a8dc08434c"}], + } diff --git a/tests_parsers/test_redline.py b/tests_parsers/test_redline.py index 17ffaaa20cf..6e7712dde23 100644 --- a/tests_parsers/test_redline.py +++ b/tests_parsers/test_redline.py @@ -3,7 +3,12 @@ # See the file "docs/LICENSE" for copying permission. from modules.processing.parsers.CAPE.RedLine import extract_config -from modules.processing.parsers.MACO.RedLine import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.RedLine import convert_to_MACO + HAVE_MACO = True + def test_redline(): @@ -15,13 +20,14 @@ def test_redline(): "Botnet": "krast", "Key": "Formative", } - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "RedLine", - "other": { - "Authorization": "9059ea331e4599de3746df73ccb24514", - "C2": "77.91.68.68:19071", - "Botnet": "krast", - "Key": "Formative", - }, - "http": [{"hostname": "77.91.68.68", "port": 19071, "usage": "c2"}], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "RedLine", + "other": { + "Authorization": "9059ea331e4599de3746df73ccb24514", + "C2": "77.91.68.68:19071", + "Botnet": "krast", + "Key": "Formative", + }, + "http": [{"hostname": "77.91.68.68", "port": 19071, "usage": "c2"}], + } diff --git a/tests_parsers/test_smokeloader.py b/tests_parsers/test_smokeloader.py index cb7f4085a4e..52359c1dedf 100644 --- a/tests_parsers/test_smokeloader.py +++ b/tests_parsers/test_smokeloader.py @@ -1,13 +1,17 @@ from modules.processing.parsers.CAPE.SmokeLoader import extract_config -from modules.processing.parsers.MACO.SmokeLoader import convert_to_MACO - +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.SmokeLoader import convert_to_MACO + HAVE_MACO = True def test_smokeloader(): with open("tests/data/malware/6929fff132c05ae7d348867f4ea77ba18f84fb8fae17d45dde3571c9e33f01f8", "rb") as data: conf = extract_config(data.read()) assert conf == {"C2s": ["http://host-file-host6.com/", "http://host-host-file8.com/"]} - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "SmokeLoader", - "other": {"C2s": ["http://host-file-host6.com/", "http://host-host-file8.com/"]}, - "http": [{"uri": "http://host-file-host6.com/", "usage": "c2"}, {"uri": "http://host-host-file8.com/", "usage": "c2"}], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "SmokeLoader", + "other": {"C2s": ["http://host-file-host6.com/", "http://host-host-file8.com/"]}, + "http": [{"uri": "http://host-file-host6.com/", "usage": "c2"}, {"uri": "http://host-host-file8.com/", "usage": "c2"}], + } diff --git a/tests_parsers/test_sparkrat.py b/tests_parsers/test_sparkrat.py index ba60ca225be..f655bf60132 100644 --- a/tests_parsers/test_sparkrat.py +++ b/tests_parsers/test_sparkrat.py @@ -1,5 +1,9 @@ from modules.processing.parsers.CAPE.SparkRAT import extract_config -from modules.processing.parsers.MACO.SparkRAT import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.SparkRAT import convert_to_MACO + HAVE_MACO = True def test_sparkrat(): @@ -13,16 +17,17 @@ def test_sparkrat(): "uuid": "8dc7e7d8f8576f3e55a00850b72887db", "key": "a1348fb8969ad7a9f85ac173c2027622135e52e0e6d94d10e6a81916a29648ac", } - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "SparkRAT", - "identifier": ["8dc7e7d8f8576f3e55a00850b72887db"], - "other": { - "secure": False, - "host": "67.217.62.106", - "port": 4443, - "path": "/", - "uuid": "8dc7e7d8f8576f3e55a00850b72887db", - "key": "a1348fb8969ad7a9f85ac173c2027622135e52e0e6d94d10e6a81916a29648ac", - }, - "http": [{"uri": "http://67.217.62.106:4443/", "hostname": "67.217.62.106", "port": 4443, "path": "/"}], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "SparkRAT", + "identifier": ["8dc7e7d8f8576f3e55a00850b72887db"], + "other": { + "secure": False, + "host": "67.217.62.106", + "port": 4443, + "path": "/", + "uuid": "8dc7e7d8f8576f3e55a00850b72887db", + "key": "a1348fb8969ad7a9f85ac173c2027622135e52e0e6d94d10e6a81916a29648ac", + }, + "http": [{"uri": "http://67.217.62.106:4443/", "hostname": "67.217.62.106", "port": 4443, "path": "/"}], + } diff --git a/tests_parsers/test_zloader.py b/tests_parsers/test_zloader.py index d9c0ef1f174..3c60247db86 100644 --- a/tests_parsers/test_zloader.py +++ b/tests_parsers/test_zloader.py @@ -3,7 +3,12 @@ # See the file 'docs/LICENSE' for copying permission. from modules.processing.parsers.CAPE.Zloader import extract_config -from modules.processing.parsers.MACO.Zloader import convert_to_MACO +from contextlib import suppress +HAVE_MACO = False +with suppress(ImportError): + from modules.processing.parsers.MACO.AgentTesla import convert_to_MACO + HAVE_MACO = True + def test_zloader(): @@ -15,14 +20,15 @@ def test_zloader(): "address": ["https://dem.businessdeep.com"], "Public key": "-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKGAOWVkikqE7TyKIMtWI8dFsaleTaJNXMJNIPnRE/fGCzqrV+rtY3+ex4MCHEtq2Vwppthf0Rglv8OiWgKlerIN5P6NEyCfIsFYUMDfldQTF03VES8GBIvHq5SjlIz7lawuwfdjdEkaHfOmmu9srraftkI9gZO8WRQgY1uNdsXwIDAQAB-----END PUBLIC KEY-----", } - assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { - "family": "Zloader", - "campaign_id": ["M1"], - "other": { - "Botnet name": "Bing_Mod5", - "Campaign ID": "M1", - "address": ["https://dem.businessdeep.com"], - "Public key": "-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKGAOWVkikqE7TyKIMtWI8dFsaleTaJNXMJNIPnRE/fGCzqrV+rtY3+ex4MCHEtq2Vwppthf0Rglv8OiWgKlerIN5P6NEyCfIsFYUMDfldQTF03VES8GBIvHq5SjlIz7lawuwfdjdEkaHfOmmu9srraftkI9gZO8WRQgY1uNdsXwIDAQAB-----END PUBLIC KEY-----", - }, - "http": [{"uri": "https://dem.businessdeep.com"}], - } + if HAVE_MACO: + assert convert_to_MACO(conf).model_dump(exclude_defaults=True, exclude_none=True) == { + "family": "Zloader", + "campaign_id": ["M1"], + "other": { + "Botnet name": "Bing_Mod5", + "Campaign ID": "M1", + "address": ["https://dem.businessdeep.com"], + "Public key": "-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKGAOWVkikqE7TyKIMtWI8dFsaleTaJNXMJNIPnRE/fGCzqrV+rtY3+ex4MCHEtq2Vwppthf0Rglv8OiWgKlerIN5P6NEyCfIsFYUMDfldQTF03VES8GBIvHq5SjlIz7lawuwfdjdEkaHfOmmu9srraftkI9gZO8WRQgY1uNdsXwIDAQAB-----END PUBLIC KEY-----", + }, + "http": [{"uri": "https://dem.businessdeep.com"}], + }