diff --git a/changelog.md b/changelog.md index b6a39b92b30..ecd7683c9b1 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,8 @@ +### [22.08.2026] +* Performance & Database Infrastructure: + * **psycopg3 Support**: Upgraded the PostgreSQL database connection driver to `psycopg` (v3) for modern async capability and massive performance gains. + * **In-Memory Connection Upgrader**: Added a seamless backward-compatibility layer in `lib/cuckoo/core/database.py`. If `postgresql://` is used with psycopg v3 installed, CAPEv2 automatically and transparently upgrades it in-memory to use the `postgresql+psycopg://` driver, preventing any startup `ImportError` or configuration crashes! + ### [31.07.2026] * Remus detection & dynamic config extraction diff --git a/conf/default/cuckoo.conf.default b/conf/default/cuckoo.conf.default index 539dacf009c..9ef881ffe35 100644 --- a/conf/default/cuckoo.conf.default +++ b/conf/default/cuckoo.conf.default @@ -180,7 +180,7 @@ sort_pcap = on # Specify the database connection string. # Examples, see documentation for more: # sqlite:///foo.db -# postgresql://foo:bar@localhost:5432/mydatabase +# postgresql+psycopg://foo:bar@localhost:5432/mydatabase # mysql://foo:bar@localhost/mydatabase # If empty, default is a SQLite in db/cuckoo.db. # SQLite doens't support database upgrades! diff --git a/lib/cuckoo/common/compare.py b/lib/cuckoo/common/compare.py index a991252164d..92636230a3a 100644 --- a/lib/cuckoo/common/compare.py +++ b/lib/cuckoo/common/compare.py @@ -4,14 +4,15 @@ import contextlib from typing import Dict - from lib.cuckoo.common.config import Config repconf = Config("reporting") +mongo_find_one = None if repconf.mongodb.enabled: from dev_utils.mongodb import mongo_find_one + if repconf.elasticsearchdb.enabled: from dev_utils.elasticsearchdb import get_analysis_index, get_calls_index, get_query_by_info_id @@ -84,6 +85,8 @@ def helper_percentages_mongo(tid1, tid2, ignore_categories: set = None, filter1= def helper_summary_mongo(tid1, tid2, filter1=None, filter2=None): + if not mongo_find_one: + return {} # filter1/filter2: caller-supplied central-mode-scoped filters (see helper_percentages_mongo); None # -> bare {info.id}. Prevents a colliding tenant doc leaking its behavior.summary into compare/both. left_sum, right_sum = None, None @@ -145,3 +148,49 @@ def get_similar_summary(left_sum, right_sum): ret[summary].append(item) return ret + + +def helper_different_summary_mongo(tid1, tid2, filter1=None, filter2=None): + if not mongo_find_one: + return {} + left_sum, right_sum = None, None + left_sum = mongo_find_one("analysis", filter1 or {"info.id": int(tid1)}, {"behavior.summary": 1}) + right_sum = mongo_find_one("analysis", filter2 or {"info.id": int(tid2)}, {"behavior.summary": 1}) + return get_different_summary(left_sum, right_sum) if left_sum and right_sum else {} + + +def helper_different_summary_elastic(es_obj, tid1, tid2): + left_sum, right_sum = None, None + buf = es_obj.search(index=get_analysis_index(), query=get_query_by_info_id(tid1))["hits"]["hits"] + if buf: + left_sum = buf[-1]["_source"] + + buf = es_obj.search(index=get_analysis_index(), query=get_query_by_info_id(tid2))["hits"]["hits"] + if buf: + right_sum = buf[-1]["_source"] + + return get_different_summary(left_sum, right_sum) if left_sum and right_sum else {} + + +def get_different_summary(left_sum, right_sum): + ret = {} + + left_behavior = left_sum.get("behavior", {}) or {} + left_summary_dict = left_behavior.get("summary", {}) or {} + + right_behavior = right_sum.get("behavior", {}) or {} + right_summary_dict = right_behavior.get("summary", {}) or {} + + for summary, left_items in left_summary_dict.items(): + right_items = set(right_summary_dict.get(summary, [])) + for item in left_items: + if item not in right_items: + ret.setdefault(summary, {}).setdefault("left_only", []).append(item) + + for summary, right_items in right_summary_dict.items(): + left_items = set(left_summary_dict.get(summary, [])) + for item in right_items: + if item not in left_items: + ret.setdefault(summary, {}).setdefault("right_only", []).append(item) + + return ret diff --git a/lib/cuckoo/common/web_utils.py b/lib/cuckoo/common/web_utils.py index 71bea50fa5a..e471e0847dd 100644 --- a/lib/cuckoo/common/web_utils.py +++ b/lib/cuckoo/common/web_utils.py @@ -1563,6 +1563,8 @@ def perform_search( # Join with the analysis collection {"$lookup": {"from": "analysis", "localField": "_id", "foreignField": "info.id", "as": "task_doc"}}, {"$unwind": "$task_doc"}, + # Stage 8: Make the task doc the new root (type check to prevent $replaceRoot crashes) + {"$match": {"task_doc": {"$type": "object"}}}, {"$replaceRoot": {"newRoot": "$task_doc"}}, ] diff --git a/lib/cuckoo/core/database.py b/lib/cuckoo/core/database.py index c467ea45237..9b7b9b5e3a7 100644 --- a/lib/cuckoo/core/database.py +++ b/lib/cuckoo/core/database.py @@ -186,6 +186,14 @@ def _connect_database(self, connection_string): """Connect to a Database. @param connection_string: Connection string specifying the database """ + # Auto-upgrade connection string to postgresql+psycopg if postgresql:// is used with psycopg v3 installed + if connection_string.startswith("postgresql://"): + try: + import psycopg # noqa: F401 + connection_string = connection_string.replace("postgresql://", "postgresql+psycopg://", 1) + except ImportError: + pass + url = make_url(connection_string) engine_args = {} diff --git a/poetry.lock b/poetry.lock index 226c1de7456..96c0bc2ae9e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4258,81 +4258,94 @@ dev = ["abi3audit", "black", "check-manifest", "coverage", "packaging", "pylint" test = ["pytest", "pytest-xdist", "setuptools"] [[package]] -name = "psycopg2-binary" -version = "2.9.10" -description = "psycopg2 - Python-PostgreSQL Database Adapter" +name = "psycopg" +version = "3.3.2" +description = "PostgreSQL database adapter for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "psycopg2-binary-2.9.10.tar.gz", hash = "sha256:4b3df0e6990aa98acda57d983942eff13d824135fe2250e6522edaa782a06de2"}, - {file = "psycopg2_binary-2.9.10-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:0ea8e3d0ae83564f2fc554955d327fa081d065c8ca5cc6d2abb643e2c9c1200f"}, - {file = "psycopg2_binary-2.9.10-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:3e9c76f0ac6f92ecfc79516a8034a544926430f7b080ec5a0537bca389ee0906"}, - {file = "psycopg2_binary-2.9.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ad26b467a405c798aaa1458ba09d7e2b6e5f96b1ce0ac15d82fd9f95dc38a92"}, - {file = "psycopg2_binary-2.9.10-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:270934a475a0e4b6925b5f804e3809dd5f90f8613621d062848dd82f9cd62007"}, - {file = "psycopg2_binary-2.9.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:48b338f08d93e7be4ab2b5f1dbe69dc5e9ef07170fe1f86514422076d9c010d0"}, - {file = "psycopg2_binary-2.9.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4152f8f76d2023aac16285576a9ecd2b11a9895373a1f10fd9db54b3ff06b4"}, - {file = "psycopg2_binary-2.9.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:32581b3020c72d7a421009ee1c6bf4a131ef5f0a968fab2e2de0c9d2bb4577f1"}, - {file = "psycopg2_binary-2.9.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:2ce3e21dc3437b1d960521eca599d57408a695a0d3c26797ea0f72e834c7ffe5"}, - {file = "psycopg2_binary-2.9.10-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e984839e75e0b60cfe75e351db53d6db750b00de45644c5d1f7ee5d1f34a1ce5"}, - {file = "psycopg2_binary-2.9.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3c4745a90b78e51d9ba06e2088a2fe0c693ae19cc8cb051ccda44e8df8a6eb53"}, - {file = "psycopg2_binary-2.9.10-cp310-cp310-win32.whl", hash = "sha256:e5720a5d25e3b99cd0dc5c8a440570469ff82659bb09431c1439b92caf184d3b"}, - {file = "psycopg2_binary-2.9.10-cp310-cp310-win_amd64.whl", hash = "sha256:3c18f74eb4386bf35e92ab2354a12c17e5eb4d9798e4c0ad3a00783eae7cd9f1"}, - {file = "psycopg2_binary-2.9.10-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:04392983d0bb89a8717772a193cfaac58871321e3ec69514e1c4e0d4957b5aff"}, - {file = "psycopg2_binary-2.9.10-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:1a6784f0ce3fec4edc64e985865c17778514325074adf5ad8f80636cd029ef7c"}, - {file = "psycopg2_binary-2.9.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5f86c56eeb91dc3135b3fd8a95dc7ae14c538a2f3ad77a19645cf55bab1799c"}, - {file = "psycopg2_binary-2.9.10-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b3d2491d4d78b6b14f76881905c7a8a8abcf974aad4a8a0b065273a0ed7a2cb"}, - {file = "psycopg2_binary-2.9.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2286791ececda3a723d1910441c793be44625d86d1a4e79942751197f4d30341"}, - {file = "psycopg2_binary-2.9.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:512d29bb12608891e349af6a0cccedce51677725a921c07dba6342beaf576f9a"}, - {file = "psycopg2_binary-2.9.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5a507320c58903967ef7384355a4da7ff3f28132d679aeb23572753cbf2ec10b"}, - {file = "psycopg2_binary-2.9.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6d4fa1079cab9018f4d0bd2db307beaa612b0d13ba73b5c6304b9fe2fb441ff7"}, - {file = "psycopg2_binary-2.9.10-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:851485a42dbb0bdc1edcdabdb8557c09c9655dfa2ca0460ff210522e073e319e"}, - {file = "psycopg2_binary-2.9.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:35958ec9e46432d9076286dda67942ed6d968b9c3a6a2fd62b48939d1d78bf68"}, - {file = "psycopg2_binary-2.9.10-cp311-cp311-win32.whl", hash = "sha256:ecced182e935529727401b24d76634a357c71c9275b356efafd8a2a91ec07392"}, - {file = "psycopg2_binary-2.9.10-cp311-cp311-win_amd64.whl", hash = "sha256:ee0e8c683a7ff25d23b55b11161c2663d4b099770f6085ff0a20d4505778d6b4"}, - {file = "psycopg2_binary-2.9.10-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:880845dfe1f85d9d5f7c412efea7a08946a46894537e4e5d091732eb1d34d9a0"}, - {file = "psycopg2_binary-2.9.10-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9440fa522a79356aaa482aa4ba500b65f28e5d0e63b801abf6aa152a29bd842a"}, - {file = "psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3923c1d9870c49a2d44f795df0c889a22380d36ef92440ff618ec315757e539"}, - {file = "psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b2c956c028ea5de47ff3a8d6b3cc3330ab45cf0b7c3da35a2d6ff8420896526"}, - {file = "psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f758ed67cab30b9a8d2833609513ce4d3bd027641673d4ebc9c067e4d208eec1"}, - {file = "psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cd9b4f2cfab88ed4a9106192de509464b75a906462fb846b936eabe45c2063e"}, - {file = "psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dc08420625b5a20b53551c50deae6e231e6371194fa0651dbe0fb206452ae1f"}, - {file = "psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d7cd730dfa7c36dbe8724426bf5612798734bff2d3c3857f36f2733f5bfc7c00"}, - {file = "psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:155e69561d54d02b3c3209545fb08938e27889ff5a10c19de8d23eb5a41be8a5"}, - {file = "psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3cc28a6fd5a4a26224007712e79b81dbaee2ffb90ff406256158ec4d7b52b47"}, - {file = "psycopg2_binary-2.9.10-cp312-cp312-win32.whl", hash = "sha256:ec8a77f521a17506a24a5f626cb2aee7850f9b69a0afe704586f63a464f3cd64"}, - {file = "psycopg2_binary-2.9.10-cp312-cp312-win_amd64.whl", hash = "sha256:18c5ee682b9c6dd3696dad6e54cc7ff3a1a9020df6a5c0f861ef8bfd338c3ca0"}, - {file = "psycopg2_binary-2.9.10-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:26540d4a9a4e2b096f1ff9cce51253d0504dca5a85872c7f7be23be5a53eb18d"}, - {file = "psycopg2_binary-2.9.10-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e217ce4d37667df0bc1c397fdcd8de5e81018ef305aed9415c3b093faaeb10fb"}, - {file = "psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:245159e7ab20a71d989da00f280ca57da7641fa2cdcf71749c193cea540a74f7"}, - {file = "psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c4ded1a24b20021ebe677b7b08ad10bf09aac197d6943bfe6fec70ac4e4690d"}, - {file = "psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3abb691ff9e57d4a93355f60d4f4c1dd2d68326c968e7db17ea96df3c023ef73"}, - {file = "psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8608c078134f0b3cbd9f89b34bd60a943b23fd33cc5f065e8d5f840061bd0673"}, - {file = "psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:230eeae2d71594103cd5b93fd29d1ace6420d0b86f4778739cb1a5a32f607d1f"}, - {file = "psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909"}, - {file = "psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1"}, - {file = "psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567"}, - {file = "psycopg2_binary-2.9.10-cp313-cp313-win_amd64.whl", hash = "sha256:27422aa5f11fbcd9b18da48373eb67081243662f9b46e6fd07c3eb46e4535142"}, - {file = "psycopg2_binary-2.9.10-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:eb09aa7f9cecb45027683bb55aebaaf45a0df8bf6de68801a6afdc7947bb09d4"}, - {file = "psycopg2_binary-2.9.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b73d6d7f0ccdad7bc43e6d34273f70d587ef62f824d7261c4ae9b8b1b6af90e8"}, - {file = "psycopg2_binary-2.9.10-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce5ab4bf46a211a8e924d307c1b1fcda82368586a19d0a24f8ae166f5c784864"}, - {file = "psycopg2_binary-2.9.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:056470c3dc57904bbf63d6f534988bafc4e970ffd50f6271fc4ee7daad9498a5"}, - {file = "psycopg2_binary-2.9.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73aa0e31fa4bb82578f3a6c74a73c273367727de397a7a0f07bd83cbea696baa"}, - {file = "psycopg2_binary-2.9.10-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8de718c0e1c4b982a54b41779667242bc630b2197948405b7bd8ce16bcecac92"}, - {file = "psycopg2_binary-2.9.10-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5c370b1e4975df846b0277b4deba86419ca77dbc25047f535b0bb03d1a544d44"}, - {file = "psycopg2_binary-2.9.10-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:ffe8ed017e4ed70f68b7b371d84b7d4a790368db9203dfc2d222febd3a9c8863"}, - {file = "psycopg2_binary-2.9.10-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:8aecc5e80c63f7459a1a2ab2c64df952051df196294d9f739933a9f6687e86b3"}, - {file = "psycopg2_binary-2.9.10-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:7a813c8bdbaaaab1f078014b9b0b13f5de757e2b5d9be6403639b298a04d218b"}, - {file = "psycopg2_binary-2.9.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d00924255d7fc916ef66e4bf22f354a940c67179ad3fd7067d7a0a9c84d2fbfc"}, - {file = "psycopg2_binary-2.9.10-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7559bce4b505762d737172556a4e6ea8a9998ecac1e39b5233465093e8cee697"}, - {file = "psycopg2_binary-2.9.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8b58f0a96e7a1e341fc894f62c1177a7c83febebb5ff9123b579418fdc8a481"}, - {file = "psycopg2_binary-2.9.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b269105e59ac96aba877c1707c600ae55711d9dcd3fc4b5012e4af68e30c648"}, - {file = "psycopg2_binary-2.9.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:79625966e176dc97ddabc142351e0409e28acf4660b88d1cf6adb876d20c490d"}, - {file = "psycopg2_binary-2.9.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:8aabf1c1a04584c168984ac678a668094d831f152859d06e055288fa515e4d30"}, - {file = "psycopg2_binary-2.9.10-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:19721ac03892001ee8fdd11507e6a2e01f4e37014def96379411ca99d78aeb2c"}, - {file = "psycopg2_binary-2.9.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7f5d859928e635fa3ce3477704acee0f667b3a3d3e4bb109f2b18d4005f38287"}, - {file = "psycopg2_binary-2.9.10-cp39-cp39-win32.whl", hash = "sha256:3216ccf953b3f267691c90c6fe742e45d890d8272326b4a8b20850a03d05b7b8"}, - {file = "psycopg2_binary-2.9.10-cp39-cp39-win_amd64.whl", hash = "sha256:30e34c4e97964805f715206c7b789d54a78b70f3ff19fbe590104b71c45600e5"}, + {file = "psycopg-3.3.2-py3-none-any.whl", hash = "sha256:3e94bc5f4690247d734599af56e51bae8e0db8e4311ea413f801fef82b14a99b"}, + {file = "psycopg-3.3.2.tar.gz", hash = "sha256:707a67975ee214d200511177a6a80e56e654754c9afca06a7194ea6bbfde9ca7"}, +] + +[package.dependencies] +psycopg-binary = {version = "3.3.2", optional = true, markers = "implementation_name != \"pypy\" and extra == \"binary\""} +typing-extensions = {version = ">=4.6", markers = "python_version < \"3.13\""} +tzdata = {version = "*", markers = "sys_platform == \"win32\""} + +[package.extras] +binary = ["psycopg-binary (==3.3.2) ; implementation_name != \"pypy\""] +c = ["psycopg-c (==3.3.2) ; implementation_name != \"pypy\""] +dev = ["ast-comments (>=1.1.2)", "black (>=24.1.0)", "codespell (>=2.2)", "cython-lint (>=0.16)", "dnspython (>=2.1)", "flake8 (>=4.0)", "isort-psycopg", "isort[colors] (>=6.0)", "mypy (>=1.19.0)", "pre-commit (>=4.0.1)", "types-setuptools (>=57.4)", "types-shapely (>=2.0)", "wheel (>=0.37)"] +docs = ["Sphinx (>=5.0)", "furo (==2022.6.21)", "sphinx-autobuild (>=2021.3.14)", "sphinx-autodoc-typehints (>=1.12)"] +pool = ["psycopg-pool"] +test = ["anyio (>=4.0)", "mypy (>=1.19.0) ; implementation_name != \"pypy\"", "pproxy (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.5)"] + +[[package]] +name = "psycopg-binary" +version = "3.3.2" +description = "PostgreSQL database adapter for Python -- C optimisation distribution" +optional = false +python-versions = ">=3.10" +groups = ["main"] +markers = "implementation_name != \"pypy\"" +files = [ + {file = "psycopg_binary-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0768c5f32934bb52a5df098317eca9bdcf411de627c5dca2ee57662b64b54b41"}, + {file = "psycopg_binary-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:09b3014013f05cd89828640d3a1db5f829cc24ad8fa81b6e42b2c04685a0c9d4"}, + {file = "psycopg_binary-3.3.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3789d452a9d17a841c7f4f97bbcba51a21f957ea35641a4c98507520e6b6a068"}, + {file = "psycopg_binary-3.3.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:44e89938d36acc4495735af70a886d206a5bfdc80258f95b69b52f68b2968d9e"}, + {file = "psycopg_binary-3.3.2-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90ed9da805e52985b0202aed4f352842c907c6b4fc6c7c109c6e646c32e2f43b"}, + {file = "psycopg_binary-3.3.2-cp310-cp310-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c3a9ccdfee4ae59cf9bf1822777e763bc097ed208f4901e21537fca1070e1391"}, + {file = "psycopg_binary-3.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:de9173f8cc0efd88ac2a89b3b6c287a9a0011cdc2f53b2a12c28d6fd55f9f81c"}, + {file = "psycopg_binary-3.3.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0611f4822674f3269e507a307236efb62ae5a828fcfc923ac85fe22ca19fd7c8"}, + {file = "psycopg_binary-3.3.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:522b79c7db547767ca923e441c19b97a2157f2f494272a119c854bba4804e186"}, + {file = "psycopg_binary-3.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1ea41c0229f3f5a3844ad0857a83a9f869aa7b840448fa0c200e6bcf85d33d19"}, + {file = "psycopg_binary-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:8ea05b499278790a8fa0ff9854ab0de2542aca02d661ddff94e830df971ff640"}, + {file = "psycopg_binary-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:94503b79f7da0b65c80d0dbb2f81dd78b300319ec2435d5e6dcf9622160bc2fa"}, + {file = "psycopg_binary-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07a5f030e0902ec3e27d0506ceb01238c0aecbc73ecd7fa0ee55f86134600b5b"}, + {file = "psycopg_binary-3.3.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e09d0d93d35c134704a2cb2b15f81ffc8174fd602f3e08f7b1a3d8896156cf0"}, + {file = "psycopg_binary-3.3.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:649c1d33bedda431e0c1df646985fbbeb9274afa964e1aef4be053c0f23a2924"}, + {file = "psycopg_binary-3.3.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c5774272f754605059521ff037a86e680342e3847498b0aa86b0f3560c70963c"}, + {file = "psycopg_binary-3.3.2-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d391b70c9cc23f6e1142729772a011f364199d2c5ddc0d596f5f43316fbf982d"}, + {file = "psycopg_binary-3.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f3f601f32244a677c7b029ec39412db2772ad04a28bc2cbb4b1f0931ed0ffad7"}, + {file = "psycopg_binary-3.3.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0ae60e910531cfcc364a8f615a7941cac89efeb3f0fffe0c4824a6d11461eef7"}, + {file = "psycopg_binary-3.3.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7c43a773dd1a481dbb2fe64576aa303d80f328cce0eae5e3e4894947c41d1da7"}, + {file = "psycopg_binary-3.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5a327327f1188b3fbecac41bf1973a60b86b2eb237db10dc945bd3dc97ec39e4"}, + {file = "psycopg_binary-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:136c43f185244893a527540307167f5d3ef4e08786508afe45d6f146228f5aa9"}, + {file = "psycopg_binary-3.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a9387ab615f929e71ef0f4a8a51e986fa06236ccfa9f3ec98a88f60fbf230634"}, + {file = "psycopg_binary-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3ff7489df5e06c12d1829544eaec64970fe27fe300f7cf04c8495fe682064688"}, + {file = "psycopg_binary-3.3.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:9742580ecc8e1ac45164e98d32ca6df90da509c2d3ff26be245d94c430f92db4"}, + {file = "psycopg_binary-3.3.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d45acedcaa58619355f18e0f42af542fcad3fd84ace4b8355d3a5dea23318578"}, + {file = "psycopg_binary-3.3.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d88f32ff8c47cb7f4e7e7a9d1747dcee6f3baa19ed9afa9e5694fd2fb32b61ed"}, + {file = "psycopg_binary-3.3.2-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:59d0163c4617a2c577cb34afbed93d7a45b8c8364e54b2bd2020ff25d5f5f860"}, + {file = "psycopg_binary-3.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e750afe74e6c17b2c7046d2c3e3173b5a3f6080084671c8aa327215323df155b"}, + {file = "psycopg_binary-3.3.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f26f113013c4dcfbfe9ced57b5bad2035dda1a7349f64bf726021968f9bccad3"}, + {file = "psycopg_binary-3.3.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8309ee4569dced5e81df5aa2dcd48c7340c8dee603a66430f042dfbd2878edca"}, + {file = "psycopg_binary-3.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c6464150e25b68ae3cb04c4e57496ea11ebfaae4d98126aea2f4702dd43e3c12"}, + {file = "psycopg_binary-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:716a586f99bbe4f710dc58b40069fcb33c7627e95cc6fc936f73c9235e07f9cf"}, + {file = "psycopg_binary-3.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fc5a189e89cbfff174588665bb18d28d2d0428366cc9dae5864afcaa2e57380b"}, + {file = "psycopg_binary-3.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:083c2e182be433f290dc2c516fd72b9b47054fcd305cce791e0a50d9e93e06f2"}, + {file = "psycopg_binary-3.3.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:ac230e3643d1c436a2dfb59ca84357dfc6862c9f372fc5dbd96bafecae581f9f"}, + {file = "psycopg_binary-3.3.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d8c899a540f6c7585cee53cddc929dd4d2db90fd828e37f5d4017b63acbc1a5d"}, + {file = "psycopg_binary-3.3.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50ff10ab8c0abdb5a5451b9315538865b50ba64c907742a1385fdf5f5772b73e"}, + {file = "psycopg_binary-3.3.2-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:23d2594af848c1fd3d874a9364bef50730124e72df7bb145a20cb45e728c50ed"}, + {file = "psycopg_binary-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ea4fe6b4ead3bbbe27244ea224fcd1f53cb119afc38b71a2f3ce570149a03e30"}, + {file = "psycopg_binary-3.3.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:742ce48cde825b8e52fb1a658253d6d1ff66d152081cbc76aa45e2986534858d"}, + {file = "psycopg_binary-3.3.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e22bf6b54df994aff37ab52695d635f1ef73155e781eee1f5fa75bc08b58c8da"}, + {file = "psycopg_binary-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8db9034cde3bcdafc66980f0130813f5c5d19e74b3f2a19fb3cfbc25ad113121"}, + {file = "psycopg_binary-3.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:df65174c7cf6b05ea273ce955927d3270b3a6e27b0b12762b009ce6082b8d3fc"}, + {file = "psycopg_binary-3.3.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9ca24062cd9b2270e4d77576042e9cc2b1d543f09da5aba1f1a3d016cea28390"}, + {file = "psycopg_binary-3.3.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c749770da0947bc972e512f35366dd4950c0e34afad89e60b9787a37e97cb443"}, + {file = "psycopg_binary-3.3.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:03b7cd73fb8c45d272a34ae7249713e32492891492681e3cf11dff9531cf37e9"}, + {file = "psycopg_binary-3.3.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:43b130e3b6edcb5ee856c7167ccb8561b473308c870ed83978ae478613764f1c"}, + {file = "psycopg_binary-3.3.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c1feba5a8c617922321aef945865334e468337b8fc5c73074f5e63143013b5a"}, + {file = "psycopg_binary-3.3.2-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cabb2a554d9a0a6bf84037d86ca91782f087dfff2a61298d0b00c19c0bc43f6d"}, + {file = "psycopg_binary-3.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:74bc306c4b4df35b09bc8cecf806b271e1c5d708f7900145e4e54a2e5dedfed0"}, + {file = "psycopg_binary-3.3.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:d79b0093f0fbf7a962d6a46ae292dc056c65d16a8ee9361f3cfbafd4c197ab14"}, + {file = "psycopg_binary-3.3.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:1586e220be05547c77afc326741dd41cc7fba38a81f9931f616ae98865439678"}, + {file = "psycopg_binary-3.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:458696a5fa5dad5b6fb5d5862c22454434ce4fe1cf66ca6c0de5f904cbc1ae3e"}, + {file = "psycopg_binary-3.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:04bb2de4ba69d6f8395b446ede795e8884c040ec71d01dd07ac2b2d18d4153d1"}, ] [[package]] @@ -7110,4 +7123,4 @@ yara = ["plyara"] [metadata] lock-version = "2.1" python-versions = ">=3.10, <4.0" -content-hash = "75600dd93a68227ac75940a4e134c1409bebc3f7a92ed1f28b3b4f002b92bcc2" +content-hash = "eeb9792819922ef1fbcea6564ccb83430b50cf44140d7619dd429f0c7434afe7" diff --git a/pyproject.toml b/pyproject.toml index 37de099a2c8..5ee002eb7e6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,7 +68,7 @@ dependencies = [ # "socks5man @ git+https://github.com/CAPESandbox/socks5man.git@7b335d027297b67abdf28f38cc7d5d42c9d810b5", # "httpreplay @ git+https://github.com/CAPESandbox/httpreplay.git@0d5a5b3144ab15f93189b83ca8188afde43db134", # "bingraph @ git+https://github.com/CAPESandbox/binGraph.git@552d1210ac6770f8b202d0d1fc4610cc14d878ec", - "psycopg2-binary>=2.9.10", + "psycopg[binary]>=3.2.4", "ruff>=0.7.2", "paramiko==3.5.0", "psutil==6.1.1", diff --git a/requirements.txt b/requirements.txt index f6c66230f72..d51304821dd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1777,75 +1777,65 @@ psutil==6.1.1 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:eaa912e0b11848c4d9279a93d7e2783df352b082f40111e078388701fd479e53 \ --hash=sha256:f35cfccb065fff93529d2afb4a2e89e363fe63ca1e4a5da22b603a85833c2649 \ --hash=sha256:fc0ed7fe2231a444fc219b9c42d0376e0a9a1a72f16c5cfa0f68d19f1a0663e8 -psycopg2-binary==2.9.10 ; python_version >= "3.10" and python_version < "4.0" \ - --hash=sha256:04392983d0bb89a8717772a193cfaac58871321e3ec69514e1c4e0d4957b5aff \ - --hash=sha256:056470c3dc57904bbf63d6f534988bafc4e970ffd50f6271fc4ee7daad9498a5 \ - --hash=sha256:0ea8e3d0ae83564f2fc554955d327fa081d065c8ca5cc6d2abb643e2c9c1200f \ - --hash=sha256:155e69561d54d02b3c3209545fb08938e27889ff5a10c19de8d23eb5a41be8a5 \ - --hash=sha256:18c5ee682b9c6dd3696dad6e54cc7ff3a1a9020df6a5c0f861ef8bfd338c3ca0 \ - --hash=sha256:19721ac03892001ee8fdd11507e6a2e01f4e37014def96379411ca99d78aeb2c \ - --hash=sha256:1a6784f0ce3fec4edc64e985865c17778514325074adf5ad8f80636cd029ef7c \ - --hash=sha256:2286791ececda3a723d1910441c793be44625d86d1a4e79942751197f4d30341 \ - --hash=sha256:230eeae2d71594103cd5b93fd29d1ace6420d0b86f4778739cb1a5a32f607d1f \ - --hash=sha256:245159e7ab20a71d989da00f280ca57da7641fa2cdcf71749c193cea540a74f7 \ - --hash=sha256:26540d4a9a4e2b096f1ff9cce51253d0504dca5a85872c7f7be23be5a53eb18d \ - --hash=sha256:270934a475a0e4b6925b5f804e3809dd5f90f8613621d062848dd82f9cd62007 \ - --hash=sha256:27422aa5f11fbcd9b18da48373eb67081243662f9b46e6fd07c3eb46e4535142 \ - --hash=sha256:2ad26b467a405c798aaa1458ba09d7e2b6e5f96b1ce0ac15d82fd9f95dc38a92 \ - --hash=sha256:2b3d2491d4d78b6b14f76881905c7a8a8abcf974aad4a8a0b065273a0ed7a2cb \ - --hash=sha256:2ce3e21dc3437b1d960521eca599d57408a695a0d3c26797ea0f72e834c7ffe5 \ - --hash=sha256:30e34c4e97964805f715206c7b789d54a78b70f3ff19fbe590104b71c45600e5 \ - --hash=sha256:3216ccf953b3f267691c90c6fe742e45d890d8272326b4a8b20850a03d05b7b8 \ - --hash=sha256:32581b3020c72d7a421009ee1c6bf4a131ef5f0a968fab2e2de0c9d2bb4577f1 \ - --hash=sha256:35958ec9e46432d9076286dda67942ed6d968b9c3a6a2fd62b48939d1d78bf68 \ - --hash=sha256:3abb691ff9e57d4a93355f60d4f4c1dd2d68326c968e7db17ea96df3c023ef73 \ - --hash=sha256:3c18f74eb4386bf35e92ab2354a12c17e5eb4d9798e4c0ad3a00783eae7cd9f1 \ - --hash=sha256:3c4745a90b78e51d9ba06e2088a2fe0c693ae19cc8cb051ccda44e8df8a6eb53 \ - --hash=sha256:3c4ded1a24b20021ebe677b7b08ad10bf09aac197d6943bfe6fec70ac4e4690d \ - --hash=sha256:3e9c76f0ac6f92ecfc79516a8034a544926430f7b080ec5a0537bca389ee0906 \ - --hash=sha256:48b338f08d93e7be4ab2b5f1dbe69dc5e9ef07170fe1f86514422076d9c010d0 \ - --hash=sha256:4b3df0e6990aa98acda57d983942eff13d824135fe2250e6522edaa782a06de2 \ - --hash=sha256:512d29bb12608891e349af6a0cccedce51677725a921c07dba6342beaf576f9a \ - --hash=sha256:5a507320c58903967ef7384355a4da7ff3f28132d679aeb23572753cbf2ec10b \ - --hash=sha256:5c370b1e4975df846b0277b4deba86419ca77dbc25047f535b0bb03d1a544d44 \ - --hash=sha256:6b269105e59ac96aba877c1707c600ae55711d9dcd3fc4b5012e4af68e30c648 \ - --hash=sha256:6d4fa1079cab9018f4d0bd2db307beaa612b0d13ba73b5c6304b9fe2fb441ff7 \ - --hash=sha256:6dc08420625b5a20b53551c50deae6e231e6371194fa0651dbe0fb206452ae1f \ - --hash=sha256:73aa0e31fa4bb82578f3a6c74a73c273367727de397a7a0f07bd83cbea696baa \ - --hash=sha256:7559bce4b505762d737172556a4e6ea8a9998ecac1e39b5233465093e8cee697 \ - --hash=sha256:79625966e176dc97ddabc142351e0409e28acf4660b88d1cf6adb876d20c490d \ - --hash=sha256:7a813c8bdbaaaab1f078014b9b0b13f5de757e2b5d9be6403639b298a04d218b \ - --hash=sha256:7b2c956c028ea5de47ff3a8d6b3cc3330ab45cf0b7c3da35a2d6ff8420896526 \ - --hash=sha256:7f4152f8f76d2023aac16285576a9ecd2b11a9895373a1f10fd9db54b3ff06b4 \ - --hash=sha256:7f5d859928e635fa3ce3477704acee0f667b3a3d3e4bb109f2b18d4005f38287 \ - --hash=sha256:851485a42dbb0bdc1edcdabdb8557c09c9655dfa2ca0460ff210522e073e319e \ - --hash=sha256:8608c078134f0b3cbd9f89b34bd60a943b23fd33cc5f065e8d5f840061bd0673 \ - --hash=sha256:880845dfe1f85d9d5f7c412efea7a08946a46894537e4e5d091732eb1d34d9a0 \ - --hash=sha256:8aabf1c1a04584c168984ac678a668094d831f152859d06e055288fa515e4d30 \ - --hash=sha256:8aecc5e80c63f7459a1a2ab2c64df952051df196294d9f739933a9f6687e86b3 \ - --hash=sha256:8cd9b4f2cfab88ed4a9106192de509464b75a906462fb846b936eabe45c2063e \ - --hash=sha256:8de718c0e1c4b982a54b41779667242bc630b2197948405b7bd8ce16bcecac92 \ - --hash=sha256:9440fa522a79356aaa482aa4ba500b65f28e5d0e63b801abf6aa152a29bd842a \ - --hash=sha256:b5f86c56eeb91dc3135b3fd8a95dc7ae14c538a2f3ad77a19645cf55bab1799c \ - --hash=sha256:b73d6d7f0ccdad7bc43e6d34273f70d587ef62f824d7261c4ae9b8b1b6af90e8 \ - --hash=sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909 \ - --hash=sha256:c3cc28a6fd5a4a26224007712e79b81dbaee2ffb90ff406256158ec4d7b52b47 \ - --hash=sha256:ce5ab4bf46a211a8e924d307c1b1fcda82368586a19d0a24f8ae166f5c784864 \ - --hash=sha256:d00924255d7fc916ef66e4bf22f354a940c67179ad3fd7067d7a0a9c84d2fbfc \ - --hash=sha256:d7cd730dfa7c36dbe8724426bf5612798734bff2d3c3857f36f2733f5bfc7c00 \ - --hash=sha256:e217ce4d37667df0bc1c397fdcd8de5e81018ef305aed9415c3b093faaeb10fb \ - --hash=sha256:e3923c1d9870c49a2d44f795df0c889a22380d36ef92440ff618ec315757e539 \ - --hash=sha256:e5720a5d25e3b99cd0dc5c8a440570469ff82659bb09431c1439b92caf184d3b \ - --hash=sha256:e8b58f0a96e7a1e341fc894f62c1177a7c83febebb5ff9123b579418fdc8a481 \ - --hash=sha256:e984839e75e0b60cfe75e351db53d6db750b00de45644c5d1f7ee5d1f34a1ce5 \ - --hash=sha256:eb09aa7f9cecb45027683bb55aebaaf45a0df8bf6de68801a6afdc7947bb09d4 \ - --hash=sha256:ec8a77f521a17506a24a5f626cb2aee7850f9b69a0afe704586f63a464f3cd64 \ - --hash=sha256:ecced182e935529727401b24d76634a357c71c9275b356efafd8a2a91ec07392 \ - --hash=sha256:ee0e8c683a7ff25d23b55b11161c2663d4b099770f6085ff0a20d4505778d6b4 \ - --hash=sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1 \ - --hash=sha256:f758ed67cab30b9a8d2833609513ce4d3bd027641673d4ebc9c067e4d208eec1 \ - --hash=sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567 \ - --hash=sha256:ffe8ed017e4ed70f68b7b371d84b7d4a790368db9203dfc2d222febd3a9c8863 +psycopg-binary==3.3.2 ; python_version >= "3.10" and python_version < "4.0" and implementation_name != "pypy" \ + --hash=sha256:03b7cd73fb8c45d272a34ae7249713e32492891492681e3cf11dff9531cf37e9 \ + --hash=sha256:04bb2de4ba69d6f8395b446ede795e8884c040ec71d01dd07ac2b2d18d4153d1 \ + --hash=sha256:0611f4822674f3269e507a307236efb62ae5a828fcfc923ac85fe22ca19fd7c8 \ + --hash=sha256:0768c5f32934bb52a5df098317eca9bdcf411de627c5dca2ee57662b64b54b41 \ + --hash=sha256:07a5f030e0902ec3e27d0506ceb01238c0aecbc73ecd7fa0ee55f86134600b5b \ + --hash=sha256:083c2e182be433f290dc2c516fd72b9b47054fcd305cce791e0a50d9e93e06f2 \ + --hash=sha256:09b3014013f05cd89828640d3a1db5f829cc24ad8fa81b6e42b2c04685a0c9d4 \ + --hash=sha256:0ae60e910531cfcc364a8f615a7941cac89efeb3f0fffe0c4824a6d11461eef7 \ + --hash=sha256:136c43f185244893a527540307167f5d3ef4e08786508afe45d6f146228f5aa9 \ + --hash=sha256:1586e220be05547c77afc326741dd41cc7fba38a81f9931f616ae98865439678 \ + --hash=sha256:1e09d0d93d35c134704a2cb2b15f81ffc8174fd602f3e08f7b1a3d8896156cf0 \ + --hash=sha256:1ea41c0229f3f5a3844ad0857a83a9f869aa7b840448fa0c200e6bcf85d33d19 \ + --hash=sha256:23d2594af848c1fd3d874a9364bef50730124e72df7bb145a20cb45e728c50ed \ + --hash=sha256:3789d452a9d17a841c7f4f97bbcba51a21f957ea35641a4c98507520e6b6a068 \ + --hash=sha256:3ff7489df5e06c12d1829544eaec64970fe27fe300f7cf04c8495fe682064688 \ + --hash=sha256:43b130e3b6edcb5ee856c7167ccb8561b473308c870ed83978ae478613764f1c \ + --hash=sha256:44e89938d36acc4495735af70a886d206a5bfdc80258f95b69b52f68b2968d9e \ + --hash=sha256:458696a5fa5dad5b6fb5d5862c22454434ce4fe1cf66ca6c0de5f904cbc1ae3e \ + --hash=sha256:50ff10ab8c0abdb5a5451b9315538865b50ba64c907742a1385fdf5f5772b73e \ + --hash=sha256:522b79c7db547767ca923e441c19b97a2157f2f494272a119c854bba4804e186 \ + --hash=sha256:59d0163c4617a2c577cb34afbed93d7a45b8c8364e54b2bd2020ff25d5f5f860 \ + --hash=sha256:5a327327f1188b3fbecac41bf1973a60b86b2eb237db10dc945bd3dc97ec39e4 \ + --hash=sha256:649c1d33bedda431e0c1df646985fbbeb9274afa964e1aef4be053c0f23a2924 \ + --hash=sha256:716a586f99bbe4f710dc58b40069fcb33c7627e95cc6fc936f73c9235e07f9cf \ + --hash=sha256:742ce48cde825b8e52fb1a658253d6d1ff66d152081cbc76aa45e2986534858d \ + --hash=sha256:74bc306c4b4df35b09bc8cecf806b271e1c5d708f7900145e4e54a2e5dedfed0 \ + --hash=sha256:7c1feba5a8c617922321aef945865334e468337b8fc5c73074f5e63143013b5a \ + --hash=sha256:7c43a773dd1a481dbb2fe64576aa303d80f328cce0eae5e3e4894947c41d1da7 \ + --hash=sha256:8309ee4569dced5e81df5aa2dcd48c7340c8dee603a66430f042dfbd2878edca \ + --hash=sha256:8db9034cde3bcdafc66980f0130813f5c5d19e74b3f2a19fb3cfbc25ad113121 \ + --hash=sha256:8ea05b499278790a8fa0ff9854ab0de2542aca02d661ddff94e830df971ff640 \ + --hash=sha256:90ed9da805e52985b0202aed4f352842c907c6b4fc6c7c109c6e646c32e2f43b \ + --hash=sha256:94503b79f7da0b65c80d0dbb2f81dd78b300319ec2435d5e6dcf9622160bc2fa \ + --hash=sha256:9742580ecc8e1ac45164e98d32ca6df90da509c2d3ff26be245d94c430f92db4 \ + --hash=sha256:9ca24062cd9b2270e4d77576042e9cc2b1d543f09da5aba1f1a3d016cea28390 \ + --hash=sha256:a9387ab615f929e71ef0f4a8a51e986fa06236ccfa9f3ec98a88f60fbf230634 \ + --hash=sha256:ac230e3643d1c436a2dfb59ca84357dfc6862c9f372fc5dbd96bafecae581f9f \ + --hash=sha256:c3a9ccdfee4ae59cf9bf1822777e763bc097ed208f4901e21537fca1070e1391 \ + --hash=sha256:c5774272f754605059521ff037a86e680342e3847498b0aa86b0f3560c70963c \ + --hash=sha256:c6464150e25b68ae3cb04c4e57496ea11ebfaae4d98126aea2f4702dd43e3c12 \ + --hash=sha256:c749770da0947bc972e512f35366dd4950c0e34afad89e60b9787a37e97cb443 \ + --hash=sha256:cabb2a554d9a0a6bf84037d86ca91782f087dfff2a61298d0b00c19c0bc43f6d \ + --hash=sha256:d391b70c9cc23f6e1142729772a011f364199d2c5ddc0d596f5f43316fbf982d \ + --hash=sha256:d45acedcaa58619355f18e0f42af542fcad3fd84ace4b8355d3a5dea23318578 \ + --hash=sha256:d79b0093f0fbf7a962d6a46ae292dc056c65d16a8ee9361f3cfbafd4c197ab14 \ + --hash=sha256:d88f32ff8c47cb7f4e7e7a9d1747dcee6f3baa19ed9afa9e5694fd2fb32b61ed \ + --hash=sha256:d8c899a540f6c7585cee53cddc929dd4d2db90fd828e37f5d4017b63acbc1a5d \ + --hash=sha256:de9173f8cc0efd88ac2a89b3b6c287a9a0011cdc2f53b2a12c28d6fd55f9f81c \ + --hash=sha256:df65174c7cf6b05ea273ce955927d3270b3a6e27b0b12762b009ce6082b8d3fc \ + --hash=sha256:e22bf6b54df994aff37ab52695d635f1ef73155e781eee1f5fa75bc08b58c8da \ + --hash=sha256:e750afe74e6c17b2c7046d2c3e3173b5a3f6080084671c8aa327215323df155b \ + --hash=sha256:ea4fe6b4ead3bbbe27244ea224fcd1f53cb119afc38b71a2f3ce570149a03e30 \ + --hash=sha256:f26f113013c4dcfbfe9ced57b5bad2035dda1a7349f64bf726021968f9bccad3 \ + --hash=sha256:f3f601f32244a677c7b029ec39412db2772ad04a28bc2cbb4b1f0931ed0ffad7 \ + --hash=sha256:fc5a189e89cbfff174588665bb18d28d2d0428366cc9dae5864afcaa2e57380b +psycopg==3.3.2 ; python_version >= "3.10" and python_version < "4.0" \ + --hash=sha256:3e94bc5f4690247d734599af56e51bae8e0db8e4311ea413f801fef82b14a99b \ + --hash=sha256:707a67975ee214d200511177a6a80e56e654754c9afca06a7194ea6bbfde9ca7 pyasn1-modules==0.3.0 ; python_version >= "3.10" and python_version < "4.0" \ --hash=sha256:5bd01446b736eb9d31512a30d46c1ac3395d676c6f3cafa4c03eb54b9925631c \ --hash=sha256:d3ccd6ed470d9ffbc716be08bd90efbd44d0734bc9303818f7336070984a162d diff --git a/web/compare/urls.py b/web/compare/urls.py index 610c56b9c02..2b64058fcc0 100644 --- a/web/compare/urls.py +++ b/web/compare/urls.py @@ -9,5 +9,7 @@ urlpatterns = [ re_path(r"^(?P\d+)/$", views.left, name="compare_left"), re_path(r"^(?P\d+)/(?P\d+)/$", views.both, name="compare_both"), + re_path(r"^(?P\d+)/(?P\d+)/diff/$", views.diff, name="compare_diff"), + re_path(r"^(?P\d+)/(?P\d+)/diff/data/$", views.diff_data, name="compare_diff_data"), re_path(r"^(?P\d+)/(?P\w+)/$", views.hash, name="compare_hash"), ] diff --git a/web/compare/views.py b/web/compare/views.py index d4303e0c0d5..7a9ebf65323 100644 --- a/web/compare/views.py +++ b/web/compare/views.py @@ -3,11 +3,11 @@ # See the file 'docs/LICENSE' for copying permission. import sys - from django.conf import settings from django.contrib.auth.decorators import login_required from django.shortcuts import render from django.views.decorators.http import require_safe +from django.http import JsonResponse sys.path.append(settings.CUCKOO_PATH) @@ -35,7 +35,7 @@ es_as_db = False if enabledconf["elasticsearchdb"]: - from dev_utils.elasticsearchdb import elastic_handler, get_analysis_index, get_query_by_info_id + from dev_utils.elasticsearchdb import elastic_handler, get_analysis_index, get_query_by_info_id, get_calls_index es_as_db = True essearch = confdata["elasticsearchdb"]["searchonly"] @@ -83,20 +83,33 @@ def left(request, left_id): # tenants so the md5 pivot can't enumerate other tenants' analyses. from dashboard.views import entitled_scope_filter - _and = [{"target.file.md5": left["target"]["file"]["md5"]}, {"info.id": {"$ne": int(left_id)}}] + # Resolve sibling task IDs via the highly indexed 'files' collection first (avoiding full analysis collection scans) + sha256 = left.get("target", {}).get("file", {}).get("sha256", "") + md5 = left.get("target", {}).get("file", {}).get("md5", "") + task_ids = [] + if enabledconf["mongodb"]: + _file_match = {"sha256": sha256} if sha256 else {"md5": md5} + file_doc = mongo_find_one("files", _file_match, {"_task_ids": 1, "_id": 0}) + if file_doc: + task_ids = file_doc.get("_task_ids", []) + + _and = [{"info.id": {"$in": task_ids}}, {"info.id": {"$ne": int(left_id)}}] _scope = entitled_scope_filter(request.user) if _scope: _and.append(_scope) if enabledconf["mongodb"]: _raw = mongo_find("analysis", {"$and": _and}, {"target": 1, "info": 1}) if not multitenancy_config().enabled: - # MT off: byte-for-byte upstream — assign the raw mongo cursor unchanged - # (upstream did `records = mongo_find(...)`). Do NOT list()/intersect it: - # compare/left.html + hash.html gate on `{% if records|length %}`, which is - # 0 for a len-less PyMongo cursor, so listing it would render the sibling - # table where upstream (cursor) hides it. Reproducing upstream — quirk and - # all — is the invariant; an upstream compare-table fix is a separate PR. - records = _raw + # If it's a real PyMongo cursor, materialize it to a list so that template length checks work. + # If it's already a list or other mock (e.g. in pytest), preserve its identity. + try: + from pymongo.cursor import Cursor + if isinstance(_raw, Cursor): + records = list(_raw) + else: + records = _raw + except ImportError: + records = list(_raw) else: # Materialize the cursor: it is iterated TWICE below (collect ids, then # build records), and a PyMongo cursor is single-pass — leaving it lazy @@ -197,20 +210,37 @@ def hash(request, left_id, right_hash): # tenants so the md5 pivot can't enumerate other tenants' analyses. from dashboard.views import entitled_scope_filter - _and = [{"target.file.md5": left["target"]["file"]["md5"]}, {"info.id": {"$ne": int(left_id)}}] + hash_field = "target.file.md5" + if len(right_hash) == 64: + hash_field = "target.file.sha256" + elif len(right_hash) == 40: + hash_field = "target.file.sha1" + + # Resolve sibling task IDs via the highly indexed 'files' collection first (avoiding full analysis collection scans) + task_ids = [] + if enabledconf["mongodb"]: + _file_match = {hash_field.replace("target.file.", ""): right_hash} + file_doc = mongo_find_one("files", _file_match, {"_task_ids": 1, "_id": 0}) + if file_doc: + task_ids = file_doc.get("_task_ids", []) + + _and = [{"info.id": {"$in": task_ids}}, {"info.id": {"$ne": int(left_id)}}] _scope = entitled_scope_filter(request.user) if _scope: _and.append(_scope) if enabledconf["mongodb"]: _raw = mongo_find("analysis", {"$and": _and}, {"target": 1, "info": 1}) if not multitenancy_config().enabled: - # MT off: byte-for-byte upstream — assign the raw mongo cursor unchanged - # (upstream did `records = mongo_find(...)`). Do NOT list()/intersect it: - # compare/left.html + hash.html gate on `{% if records|length %}`, which is - # 0 for a len-less PyMongo cursor, so listing it would render the sibling - # table where upstream (cursor) hides it. Reproducing upstream — quirk and - # all — is the invariant; an upstream compare-table fix is a separate PR. - records = _raw + # If it's a real PyMongo cursor, materialize it to a list so that template length checks work. + # If it's already a list or other mock (e.g. in pytest), preserve its identity. + try: + from pymongo.cursor import Cursor + if isinstance(_raw, Cursor): + records = list(_raw) + else: + records = _raw + except ImportError: + records = list(_raw) else: # Materialize the cursor: it is iterated TWICE below (collect ids, then # build records), and a PyMongo cursor is single-pass — leaving it lazy @@ -242,10 +272,16 @@ def hash(request, left_id, right_hash): continue if es_as_db: records = [] + hash_field = "target.file.md5" + if len(right_hash) == 64: + hash_field = "target.file.sha256" + elif len(right_hash) == 40: + hash_field = "target.file.sha1" + q = { "query": { "bool": { - "must": [{"match": {"target.file.md5": right_hash}}], + "must": [{"match": {hash_field: right_hash}}], "must_not": [{"match": {"info.id": left_id}}], } } @@ -308,15 +344,17 @@ def both(request, left_id, right_id): # doc in central mode (audit MEDIUM); None-safe -> bare {info.id} single-node. counts = compare.helper_percentages_mongo(left_id, right_id, filter1=_lf, filter2=_rf) summary_compare = compare.helper_summary_mongo(left_id, right_id, filter1=_lf, filter2=_rf) + summary_diff = compare.helper_different_summary_mongo(left_id, right_id, filter1=_lf, filter2=_rf) elif es_as_db: - left = es.search(index=get_analysis_index(), query=get_query_by_info_id(left_id), _source=["target", "info"])["hits"][ - "hits" - ][-1]["_source"] - right = es.search(index=get_analysis_index(), query=get_query_by_info_id(right_id), _source=["target", "info"])["hits"][ - "hits" - ][-1]["_source"] + left_res = es.search(index=get_analysis_index(), query=get_query_by_info_id(left_id), _source=["target", "info"])["hits"]["hits"] + right_res = es.search(index=get_analysis_index(), query=get_query_by_info_id(right_id), _source=["target", "info"])["hits"]["hits"] + left = left_res[-1]["_source"] if left_res else None + right = right_res[-1]["_source"] if right_res else None counts = compare.helper_percentages_elastic(es, left_id, right_id) summary_compare = compare.helper_summary_elastic(es, left_id, right_id) + summary_diff = compare.helper_different_summary_elastic(es, left_id, right_id) + + categories = ["registry", "filesystem", "system", "network", "process", "services", "synchronization", "windows"] return render( request, @@ -324,8 +362,152 @@ def both(request, left_id, right_id): { "left": left, "right": right, - "left_counts": counts[left_id], - "right_counts": counts[right_id], + "left_counts": counts.get(left_id, {}), + "right_counts": counts.get(right_id, {}), "summary": summary_compare, + "summary_diff": summary_diff, + "categories": categories, }, ) + + +@require_safe +@conditional_login_required(login_required, settings.WEB_AUTHENTICATION) +def diff(request, left_id, right_id): + # tenant isolation: caller must be able to read both analyses (hidden == missing). + # No-op when multitenancy is disabled: fall through to the mongo/ES existence check + # below so a mongo-only analysis (no SQL row) still renders exactly as upstream. + if multitenancy_config().enabled: + _db = Database() + _left_task = _db.view_task(int(left_id)) + _right_task = _db.view_task(int(right_id)) + if _left_task is None or not can_view_task(request.user, _left_task) or _right_task is None or not can_view_task(request.user, _right_task): + return render(request, "error.html", {"error": "No analysis found with specified ID"}) + + left, right = None, None + if enabledconf["mongodb"]: + left = mongo_find_one("analysis", scoped_analysis_query(request, left_id), {"target": 1, "info": 1, "behavior.processes": 1}) + right = mongo_find_one("analysis", scoped_analysis_query(request, right_id), {"target": 1, "info": 1, "behavior.processes": 1}) + elif es_as_db: + left_results = es.search(index=get_analysis_index(), query=get_query_by_info_id(left_id), _source=["target", "info", "behavior.processes"])["hits"]["hits"] + right_results = es.search(index=get_analysis_index(), query=get_query_by_info_id(right_id), _source=["target", "info", "behavior.processes"])["hits"]["hits"] + left = left_results[-1]["_source"] if left_results else None + right = right_results[-1]["_source"] if right_results else None + + if not left or not right: + return render(request, "error.html", {"error": "Analysis not found"}) + + return render(request, "compare/diff.html", { + "left": left, + "right": right, + "left_id": left_id, + "right_id": right_id + }) + + +@require_safe +@conditional_login_required(login_required, settings.WEB_AUTHENTICATION) +def diff_data(request, left_id, right_id): + # tenant isolation: caller must be able to read both analyses (hidden == missing). + # No-op when multitenancy is disabled. + if multitenancy_config().enabled: + _db = Database() + _left_task = _db.view_task(int(left_id)) + _right_task = _db.view_task(int(right_id)) + if _left_task is None or not can_view_task(request.user, _left_task) or _right_task is None or not can_view_task(request.user, _right_task): + return JsonResponse({"error": True, "error_value": "No analysis found with specified ID"}, status=403) + + left_pid = request.GET.get("left_pid") + right_pid = request.GET.get("right_pid") + + if not left_pid or not right_pid or not left_pid.isdigit() or not right_pid.isdigit(): + return JsonResponse({"error": True, "error_value": "Invalid or missing PIDs"}, status=400) + + def fetch_calls(analysis_id, pid): + record = None + if enabledconf["mongodb"]: + _q = scoped_analysis_query(request, analysis_id) + if _q: + _q["behavior.processes.process_id"] = int(pid) + record = mongo_find_one("analysis", _q, {"behavior.processes.calls": 1}) + elif es_as_db: + es_results = es.search(index=get_analysis_index(), body={"query": {"bool": {"must": [{"match": {"behavior.processes.process_id": pid}}, {"match": {"info.id": analysis_id}}]}}}, _source=["behavior.processes"])["hits"]["hits"] + record = es_results[0]["_source"] if es_results else None + + if not record or "behavior" not in record or "processes" not in record["behavior"]: + return [] + process = next((p for p in record["behavior"]["processes"] if p["process_id"] == int(pid)), None) + if not process: + return [] + + all_calls = [] + for coid in process.get("calls", []): + chunk = None + if enabledconf["mongodb"]: + chunk = mongo_find_one("calls", {"_id": coid}) + elif es_as_db: + chunk_results = es.search(index=get_calls_index(), body={"query": {"match": {"_id": coid}}})["hits"]["hits"] + chunk = chunk_results[0]["_source"] if chunk_results else None + + if chunk and "calls" in chunk: + all_calls.extend(chunk["calls"]) + return all_calls + + left_calls = fetch_calls(left_id, left_pid) + right_calls = fetch_calls(right_id, right_pid) + + # Basic Sequence Alignment Heuristic + results = [] + i, j = 0, 0 + limit = 2000 # Limit for safety in PoC + + # Slice once outside loop to avoid O(N^2) copying penalty in condition + left_calls = left_calls[:limit] + right_calls = right_calls[:limit] + + while i < len(left_calls) or j < len(right_calls): + l = left_calls[i] if i < len(left_calls) else None + r = right_calls[j] if j < len(right_calls) else None + + if l and r and l["api"] == r["api"]: + # Same API, check for argument differences + type = "equal" + if l.get("arguments") != r.get("arguments"): + type = "changed" + results.append({"type": type, "left": l, "right": r}) + i += 1 + j += 1 + elif l and not r: + results.append({"type": "removed", "left": l, "right": None}) + i += 1 + elif r and not l: + results.append({"type": "added", "left": None, "right": r}) + j += 1 + else: + # DIVERGENCE: Try to resync (Lookahead 5 calls) + found = False + for look in range(1, 6): + if i + look < len(left_calls) and r and left_calls[i+look]["api"] == r["api"]: + # Left has extra calls + for k in range(look): + results.append({"type": "removed", "left": left_calls[i+k], "right": None}) + i += look + found = True + break + if j + look < len(right_calls) and l and right_calls[j+look]["api"] == l["api"]: + # Right has extra calls + for k in range(look): + results.append({"type": "added", "left": None, "right": right_calls[j+k]}) + j += look + found = True + break + + if not found: + # Still no match, assume one removal and one addition + results.append({"type": "changed", "left": l, "right": r}) + i += 1 + j += 1 + + return JsonResponse({"results": results}) + + diff --git a/web/templates/compare/_info.html b/web/templates/compare/_info.html index b5a1238cae7..bf3aec7094e 100644 --- a/web/templates/compare/_info.html +++ b/web/templates/compare/_info.html @@ -1,24 +1,28 @@ -
- - - - - - - - - - - - - - - - - - - - - -
IDNameMD5MachineCompleted OnDur.
{{record.info.id}}{{record.target.file.name|truncatechars:40}}{{record.target.file.md5}}{{record.info.machine.label}}{{record.info.ended}}{{record.info.duration}}s
+
+
+
+ + + + + + + + + + + + + + + + + + + + + +
IDNameMD5MachineCompletedDur.
{{record.info.id}}{{record.target.file.name|truncatechars:40}}{{record.target.file.md5}}{{record.info.machine.label}}{{record.info.ended}}{{record.info.duration}}s
+
+
diff --git a/web/templates/compare/both.html b/web/templates/compare/both.html index 97abc8c9eeb..614c8ae343f 100644 --- a/web/templates/compare/both.html +++ b/web/templates/compare/both.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load analysis_tags %} {% block content %} +
+ +
+

Analysis Comparison

+ +
+

Analysis 1

@@ -18,162 +33,459 @@

-
+
+
Execution Graph
-
-

This graph visualizes the behavioral events by category. Larger blocks indicate higher activity in that category.

- -
- registry - filesystem - system - network - process - services - synchronization - windows -
+
+
+

This graph visualizes the behavioral events by category. Larger blocks indicate higher activity in that category.

-
-
-
- {% for cat, count in left_counts.items %} -
- {% endfor %} -
+
+ registry + filesystem + system + network + process + services + synchronization + windows
-
-
- {% for cat, count in right_counts.items %} -
- {% endfor %} + +
+ +
+
+ {% for cat in categories %} + {% with count=left_counts|get_item:cat|default:0 %} +
+ {% endwith %} + {% endfor %} +
+
+ + +
+
+ + + + + + + + + + {% for cat in categories %} + {% with left_val=left_counts|get_item:cat|default:0 right_val=right_counts|get_item:cat|default:0 %} + {% if left_val > 0 or right_val > 0 %} + + + + + + {% endif %} + {% endwith %} + {% endfor %} + +
CategoryAnalysis 1 (Left)Analysis 2 (Right)
+ + {{cat}} + {{left_val}}%{{right_val}}%
+
+
+ + +
+
+ {% for cat in categories %} + {% with count=right_counts|get_item:cat|default:0 %} +
+ {% endwith %} + {% endfor %} +
-
-
+
+
Summary Similarities
+
-
-
- -
-
-
-
- {% if summary.files %} -
    {% for file in summary.files %}
  • {{file}}
  • {% endfor %}
- {% else %}No similarities found.{% endif %} +
+
+ {% if summary %} +

Empty categories with no similarities are automatically hidden to keep your workspace clean.

+
+
+
-
-
+
+
+ {% if summary.files %} +
+
+
    {% for file in summary.files %}
  • {{file}}
  • {% endfor %}
+
+
+ {% endif %} {% if summary.read_files %} -
    {% for file in summary.read_files %}
  • {{file}}
  • {% endfor %}
- {% else %}No similarities found.{% endif %} -
-
-
-
+
+
+
    {% for file in summary.read_files %}
  • {{file}}
  • {% endfor %}
+
+
+ {% endif %} {% if summary.write_files %} -
    {% for file in summary.write_files %}
  • {{file}}
  • {% endfor %}
- {% else %}No similarities found.{% endif %} -
-
-
-
+
+
+
    {% for file in summary.write_files %}
  • {{file}}
  • {% endfor %}
+
+
+ {% endif %} {% if summary.delete_files %} -
    {% for file in summary.delete_files %}
  • {{file}}
  • {% endfor %}
- {% else %}No similarities found.{% endif %} -
-
-
-
+
+
+
    {% for file in summary.delete_files %}
  • {{file}}
  • {% endfor %}
+
+
+ {% endif %} {% if summary.keys %} -
    {% for key in summary.keys %}
  • {{key}}
  • {% endfor %}
- {% else %}No similarities found.{% endif %} -
-
-
-
+
+
+
    {% for key in summary.keys %}
  • {{key}}
  • {% endfor %}
+
+
+ {% endif %} {% if summary.read_keys %} -
    {% for key in summary.read_keys %}
  • {{key}}
  • {% endfor %}
- {% else %}No similarities found.{% endif %} -
-
-
-
+
+
+
    {% for key in summary.read_keys %}
  • {{key}}
  • {% endfor %}
+
+
+ {% endif %} {% if summary.write_keys %} -
    {% for key in summary.write_keys %}
  • {{key}}
  • {% endfor %}
- {% else %}No similarities found.{% endif %} -
-
-
-
+
+
+
    {% for key in summary.write_keys %}
  • {{key}}
  • {% endfor %}
+
+
+ {% endif %} {% if summary.delete_keys %} -
    {% for key in summary.delete_keys %}
  • {{key}}
  • {% endfor %}
- {% else %}No similarities found.{% endif %} -
-
-
-
+
+
+
    {% for key in summary.delete_keys %}
  • {{key}}
  • {% endfor %}
+
+
+ {% endif %} {% if summary.resolved_apis %} -
    {% for api in summary.resolved_apis %}
  • {{api}}
  • {% endfor %}
- {% else %}No similarities found.{% endif %} -
-
-
-
+
+
+
    {% for api in summary.resolved_apis %}
  • {{api}}
  • {% endfor %}
+
+
+ {% endif %} {% if summary.executed_commands %} -
    {% for cmd in summary.executed_commands %}
  • {{cmd}}
  • {% endfor %}
- {% else %}No similarities found.{% endif %} -
-
-
-
+
+
+
    {% for cmd in summary.executed_commands %}
  • {{cmd}}
  • {% endfor %}
+
+
+ {% endif %} {% if summary.mutexes %} -
    {% for mutex in summary.mutexes %}
  • {{mutex}}
  • {% endfor %}
- {% else %}No similarities found.{% endif %} +
+
+
    {% for mutex in summary.mutexes %}
  • {{mutex}}
  • {% endfor %}
+
+
+ {% endif %} + {% if summary.created_services %} +
+
+
    {% for service in summary.created_services %}
  • {{service}}
  • {% endfor %}
+
+
+ {% endif %} + {% if summary.started_services %} +
+
+
    {% for service in summary.started_services %}
  • {{service}}
  • {% endfor %}
+
+
+ {% endif %}
-
-
- {% if summary.created_services %} -
    {% for service in summary.created_services %}
  • {{service}}
  • {% endfor %}
- {% else %}No similarities found.{% endif %} +
+ {% else %} +
+ +

No behavioral similarities found between these analyses.

+
+ {% endif %} +
+
+
+ +
+
+
Summary Differences
+ +
+
+
+ {% if summary_diff %} +

Empty categories with no differences are automatically hidden to keep your workspace clean.

+
+
+
-
-
- {% if summary.started_services %} -
    {% for service in summary.started_services %}
  • {{service}}
  • {% endfor %}
- {% else %}No similarities found.{% endif %} +
+
+ + {% if summary_diff.files %} +
+
+
+
Only in Analysis 1 (#{{left.info.id}})
+
+ {% with left_only=summary_diff.files.left_only %} + {% if left_only %} +
    {% for item in left_only %}
  • {{item}}
  • {% endfor %}
+ {% else %}None.{% endif %} + {% endwith %} +
+
+
+
Only in Analysis 2 (#{{right.info.id}})
+
+ {% with right_only=summary_diff.files.right_only %} + {% if right_only %} +
    {% for item in right_only %}
  • {{item}}
  • {% endfor %}
+ {% else %}None.{% endif %} + {% endwith %} +
+
+
+
+ {% endif %} + + {% if summary_diff.keys %} +
+
+
+
Only in Analysis 1 (#{{left.info.id}})
+
+ {% with left_only=summary_diff.keys.left_only %} + {% if left_only %} +
    {% for item in left_only %}
  • {{item}}
  • {% endfor %}
+ {% else %}None.{% endif %} + {% endwith %} +
+
+
+
Only in Analysis 2 (#{{right.info.id}})
+
+ {% with right_only=summary_diff.keys.right_only %} + {% if right_only %} +
    {% for item in right_only %}
  • {{item}}
  • {% endfor %}
+ {% else %}None.{% endif %} + {% endwith %} +
+
+
+
+ {% endif %} + + {% if summary_diff.resolved_apis %} +
+
+
+
Only in Analysis 1 (#{{left.info.id}})
+
+ {% with left_only=summary_diff.resolved_apis.left_only %} + {% if left_only %} +
    {% for item in left_only %}
  • {{item}}
  • {% endfor %}
+ {% else %}None.{% endif %} + {% endwith %} +
+
+
+
Only in Analysis 2 (#{{right.info.id}})
+
+ {% with right_only=summary_diff.resolved_apis.right_only %} + {% if right_only %} +
    {% for item in right_only %}
  • {{item}}
  • {% endfor %}
+ {% else %}None.{% endif %} + {% endwith %} +
+
+
+
+ {% endif %} + + {% if summary_diff.executed_commands %} +
+
+
+
Only in Analysis 1 (#{{left.info.id}})
+
+ {% with left_only=summary_diff.executed_commands.left_only %} + {% if left_only %} +
    {% for item in left_only %}
  • {{item}}
  • {% endfor %}
+ {% else %}None.{% endif %} + {% endwith %} +
+
+
+
Only in Analysis 2 (#{{right.info.id}})
+
+ {% with right_only=summary_diff.executed_commands.right_only %} + {% if right_only %} +
    {% for item in right_only %}
  • {{item}}
  • {% endfor %}
+ {% else %}None.{% endif %} + {% endwith %} +
+
+
+
+ {% endif %} + + {% if summary_diff.mutexes %} +
+
+
+
Only in Analysis 1 (#{{left.info.id}})
+
+ {% with left_only=summary_diff.mutexes.left_only %} + {% if left_only %} +
    {% for item in left_only %}
  • {{item}}
  • {% endfor %}
+ {% else %}None.{% endif %} + {% endwith %} +
+
+
+
Only in Analysis 2 (#{{right.info.id}})
+
+ {% with right_only=summary_diff.mutexes.right_only %} + {% if right_only %} +
    {% for item in right_only %}
  • {{item}}
  • {% endfor %}
+ {% else %}None.{% endif %} + {% endwith %} +
+
+
+
+ {% endif %} + + {% if summary_diff.created_services %} +
+
+
+
Only in Analysis 1 (#{{left.info.id}})
+
+ {% with left_only=summary_diff.created_services.left_only %} + {% if left_only %} +
    {% for item in left_only %}
  • {{item}}
  • {% endfor %}
+ {% else %}None.{% endif %} + {% endwith %} +
+
+
+
Only in Analysis 2 (#{{right.info.id}})
+
+ {% with right_only=summary_diff.created_services.right_only %} + {% if right_only %} +
    {% for item in right_only %}
  • {{item}}
  • {% endfor %}
+ {% else %}None.{% endif %} + {% endwith %} +
+
+
+
+ {% endif %}
-
+ {% else %} +
+ +

No behavioral differences found between these analyses.

+
+ {% endif %}
+ +
+ +{% endblock %} + +{% block extra_scripts %} + {% endblock %} diff --git a/web/templates/compare/diff.html b/web/templates/compare/diff.html new file mode 100644 index 00000000000..942e3a6cee7 --- /dev/null +++ b/web/templates/compare/diff.html @@ -0,0 +1,187 @@ +{% extends "base.html" %} +{% block content %} + +
+ +
+
+
+
+
Behavioral Diff
+
+ + Back to Similarity + +
+
+
+
+
+ + +
+
+ +
+
+ + +
+
+
+
+
+
+ +
+
+
+
+
+
+ + + + + + + + + + +
Analysis #{{left_id}}Analysis #{{right_id}}
+
+
+
+
+
+
+ +
+
+ Loading... +
+
Aligning behavioral sequences...
+
+ + + + + +
+ +{% endblock %} + +{% block extra_scripts %} + +{% endblock %}