assemblyline 4.7.2.dev28__tar.gz → 4.7.2.dev30__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {assemblyline-4.7.2.dev28/assemblyline.egg-info → assemblyline-4.7.2.dev30}/PKG-INFO +2 -8
- assemblyline-4.7.2.dev30/assemblyline/VERSION +1 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/digests.py +11 -16
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/entropy.py +2 -40
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/logformat.py +1 -1
- assemblyline-4.7.2.dev30/assemblyline/common/net.py +93 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/postprocess.py +0 -288
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30/assemblyline.egg-info}/PKG-INFO +2 -8
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline.egg-info/SOURCES.txt +0 -1
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline.egg-info/requires.txt +1 -7
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/setup.py +3 -16
- assemblyline-4.7.2.dev28/assemblyline/VERSION +0 -1
- assemblyline-4.7.2.dev28/assemblyline/common/frequency.pyx +0 -39
- assemblyline-4.7.2.dev28/assemblyline/common/net.py +0 -185
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/LICENCE.md +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/MANIFEST.in +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/README.md +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/cachestore/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/archiving.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/attack_map.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/backupmanager.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/banner.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/bundling.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/caching.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/chunk.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/classification.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/classification.yml +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/cleanup_filestore.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/codec.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/comms.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/constants.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/custom.magic +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/custom.yara +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/dict_utils.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/dispatcher.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/exceptions.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/file.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/forge.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/heuristics.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/hexdump.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/identify.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/identify_defaults.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/importing.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/iprange.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/isotime.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/log.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/lucene.lark +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/memory_zip.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/metrics.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/net_static.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/null.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/path.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/random_user.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/security.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/signaturing.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/str_utils.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/tag_safelist.yml +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/tagging.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/threading.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/uid.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/common/version.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/datasource/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/datasource/al.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/datasource/alert.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/datasource/common.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/datastore/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/datastore/bulk.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/datastore/collection.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/datastore/exceptions.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/datastore/helper.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/datastore/store.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/datastore/support/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/datastore/support/build.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/datastore/support/schemas.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/filestore/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/filestore/transport/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/filestore/transport/azure.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/filestore/transport/base.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/filestore/transport/ftp.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/filestore/transport/http.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/filestore/transport/local.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/filestore/transport/s3.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/filestore/transport/sftp.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/base.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/common.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/alert.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/alerter_heartbeat.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/archive_heartbeat.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/changes.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/dispatcher_heartbeat.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/dispatching.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/elastic_heartbeat.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/expiry_heartbeat.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/ingest_heartbeat.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/metrics.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/retrohunt_heartbeat.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/scaler_heartbeat.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/scaler_status_heartbeat.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/service_heartbeat.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/service_timing_heartbeat.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/submission.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/task.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/messages/vacuum_heartbeat.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/actions.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/alert.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/apikey.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/badlist.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/cached_file.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/config.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/emptyresult.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/error.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/file.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/filescore.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/heuristic.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/ontology/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/ontology/file.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/ontology/filetypes/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/ontology/filetypes/pe.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/ontology/ontology.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/ontology/results/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/ontology/results/antivirus.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/ontology/results/http.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/ontology/results/malware_config.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/ontology/results/network.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/ontology/results/process.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/ontology/results/sandbox.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/ontology/results/signature.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/replay.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/result.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/retrohunt.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/safelist.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/service.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/service_delta.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/signature.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/statistics.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/submission.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/submission_summary.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/submission_tree.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/tagging.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/user.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/user_favorites.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/user_settings.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/models/workflow.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/random_data/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/random_data/create_test_data.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/random_data/sample_rules.yar +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/random_data/sample_suricata.rules +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/odm/randomizer.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/py.typed +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/datatypes/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/datatypes/cache.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/datatypes/counters.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/datatypes/daily_quota_tracker.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/datatypes/events.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/datatypes/exporting_counter.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/datatypes/hash.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/datatypes/lock.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/datatypes/queues/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/datatypes/queues/comms.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/datatypes/queues/multi.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/datatypes/queues/named.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/datatypes/queues/priority.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/datatypes/set.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/remote/datatypes/user_quota_tracker.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/run/__init__.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/run/cli.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/run/pubsub_reader.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/run/suricata_importer.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline/run/yara_importer.py +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline.egg-info/dependency_links.txt +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline.egg-info/entry_points.txt +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/assemblyline.egg-info/top_level.txt +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/pyproject.toml +0 -0
- {assemblyline-4.7.2.dev28 → assemblyline-4.7.2.dev30}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: assemblyline
|
|
3
|
-
Version: 4.7.2.
|
|
3
|
+
Version: 4.7.2.dev30
|
|
4
4
|
Summary: Assemblyline 4 - Automated malware analysis framework
|
|
5
5
|
Home-page: https://github.com/CybercentreCanada/assemblyline-base
|
|
6
6
|
Author: CCCS Assemblyline development team
|
|
@@ -24,25 +24,20 @@ Requires-Dist: urllib3>=2.6.0
|
|
|
24
24
|
Requires-Dist: python-baseconv
|
|
25
25
|
Requires-Dist: boto3
|
|
26
26
|
Requires-Dist: pysftp
|
|
27
|
-
Requires-Dist: netifaces
|
|
28
|
-
Requires-Dist: pyroute2.core
|
|
29
27
|
Requires-Dist: redis
|
|
30
28
|
Requires-Dist: requests[socks]
|
|
31
29
|
Requires-Dist: elasticsearch<9.0.0,>=8.0.0
|
|
32
30
|
Requires-Dist: python-datemath!=3.0.2
|
|
33
31
|
Requires-Dist: packaging
|
|
34
|
-
Requires-Dist: tabulate
|
|
35
32
|
Requires-Dist: PyYAML
|
|
36
|
-
Requires-Dist: easydict
|
|
37
33
|
Requires-Dist: bcrypt
|
|
38
34
|
Requires-Dist: cart
|
|
39
|
-
Requires-Dist:
|
|
35
|
+
Requires-Dist: assemblyline-toolbox==0.3.0
|
|
40
36
|
Requires-Dist: python-magic
|
|
41
37
|
Requires-Dist: pytz
|
|
42
38
|
Requires-Dist: apscheduler
|
|
43
39
|
Requires-Dist: websocket_client<1.0.0
|
|
44
40
|
Requires-Dist: elastic-apm[flask]>=6.13.0
|
|
45
|
-
Requires-Dist: cython
|
|
46
41
|
Requires-Dist: docker
|
|
47
42
|
Requires-Dist: kubernetes>18
|
|
48
43
|
Requires-Dist: notifications-python-client
|
|
@@ -52,7 +47,6 @@ Requires-Dist: azure-identity
|
|
|
52
47
|
Requires-Dist: msoffcrypto-tool
|
|
53
48
|
Requires-Dist: chardet<6
|
|
54
49
|
Requires-Dist: yara-python
|
|
55
|
-
Requires-Dist: python-tlsh
|
|
56
50
|
Requires-Dist: hauntedhouse==0.1.10
|
|
57
51
|
Requires-Dist: magika
|
|
58
52
|
Requires-Dist: paramiko<4
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4.7.2.dev30
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import hashlib
|
|
2
|
-
import ssdeep
|
|
3
|
-
import tlsh
|
|
4
2
|
from typing import Dict
|
|
5
3
|
|
|
6
4
|
from assemblyline.common import entropy
|
|
7
|
-
|
|
5
|
+
from assemblyline_toolbox import SsdeepHasher, TlshHasher
|
|
8
6
|
DEFAULT_BLOCKSIZE = 65536
|
|
9
7
|
|
|
10
8
|
|
|
@@ -14,10 +12,7 @@ def get_digests_for_file(path: str, blocksize: int = DEFAULT_BLOCKSIZE, calculat
|
|
|
14
12
|
""" Generate digests for file reading only 'blocksize bytes at a time."""
|
|
15
13
|
bc = None
|
|
16
14
|
if calculate_entropy:
|
|
17
|
-
|
|
18
|
-
bc = entropy.BufferedCalculator()
|
|
19
|
-
except Exception:
|
|
20
|
-
pass
|
|
15
|
+
bc = entropy.BufferedCalculator()
|
|
21
16
|
|
|
22
17
|
result = {}
|
|
23
18
|
|
|
@@ -25,7 +20,9 @@ def get_digests_for_file(path: str, blocksize: int = DEFAULT_BLOCKSIZE, calculat
|
|
|
25
20
|
sha1 = hashlib.sha1()
|
|
26
21
|
sha256 = hashlib.sha256()
|
|
27
22
|
if not skip_fuzzy_hashes:
|
|
28
|
-
th =
|
|
23
|
+
th = TlshHasher()
|
|
24
|
+
ssdeep = SsdeepHasher()
|
|
25
|
+
|
|
29
26
|
size = 0
|
|
30
27
|
|
|
31
28
|
with open(path, 'rb') as f:
|
|
@@ -37,12 +34,13 @@ def get_digests_for_file(path: str, blocksize: int = DEFAULT_BLOCKSIZE, calculat
|
|
|
37
34
|
|
|
38
35
|
while length > 0:
|
|
39
36
|
if bc is not None:
|
|
40
|
-
bc.update(data
|
|
37
|
+
bc.update(data)
|
|
41
38
|
md5.update(data)
|
|
42
39
|
sha1.update(data)
|
|
43
40
|
sha256.update(data)
|
|
44
41
|
if not skip_fuzzy_hashes:
|
|
45
42
|
th.update(data)
|
|
43
|
+
ssdeep.update(data)
|
|
46
44
|
size += length
|
|
47
45
|
|
|
48
46
|
data = f.read(blocksize)
|
|
@@ -58,13 +56,10 @@ def get_digests_for_file(path: str, blocksize: int = DEFAULT_BLOCKSIZE, calculat
|
|
|
58
56
|
result['size'] = size
|
|
59
57
|
|
|
60
58
|
if not skip_fuzzy_hashes:
|
|
61
|
-
result["ssdeep"] = ssdeep.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
result['tlsh'] = th.hexdigest()
|
|
66
|
-
except Exception:
|
|
67
|
-
pass
|
|
59
|
+
result["ssdeep"] = ssdeep.digest()
|
|
60
|
+
thash = th.digest()
|
|
61
|
+
if thash:
|
|
62
|
+
result['tlsh'] = thash
|
|
68
63
|
|
|
69
64
|
return result
|
|
70
65
|
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import io
|
|
2
|
+
from typing import Tuple, List, BinaryIO
|
|
2
3
|
|
|
3
|
-
from
|
|
4
|
-
from typing import Tuple, List, BinaryIO, AnyStr
|
|
4
|
+
from assemblyline_toolbox import BufferedCalculator
|
|
5
5
|
|
|
6
|
-
frequency = None
|
|
7
6
|
|
|
8
7
|
# The minimum partition size should be 256 bytes as the keyspace
|
|
9
8
|
# for a char is 256 bytes
|
|
@@ -52,40 +51,3 @@ def calculate_partition_entropy(fin: BinaryIO, num_partitions: int = 50) -> Tupl
|
|
|
52
51
|
full_entropy_calculator.update(partition)
|
|
53
52
|
return full_entropy_calculator.entropy(), p_entropies
|
|
54
53
|
|
|
55
|
-
|
|
56
|
-
class BufferedCalculator(object):
|
|
57
|
-
def __init__(self):
|
|
58
|
-
global frequency
|
|
59
|
-
import pyximport
|
|
60
|
-
pyximport.install()
|
|
61
|
-
# noinspection PyUnresolvedReferences
|
|
62
|
-
from assemblyline.common import frequency
|
|
63
|
-
|
|
64
|
-
self.c = {}
|
|
65
|
-
self.length = 0
|
|
66
|
-
|
|
67
|
-
def entropy(self) -> float:
|
|
68
|
-
if self.length == 0:
|
|
69
|
-
return 0.0
|
|
70
|
-
|
|
71
|
-
length = float(self.length)
|
|
72
|
-
|
|
73
|
-
entropy = 0.0
|
|
74
|
-
for v in self.c.values():
|
|
75
|
-
prob = float(v) / length
|
|
76
|
-
entropy += prob * log(prob, 2)
|
|
77
|
-
|
|
78
|
-
entropy *= -1
|
|
79
|
-
|
|
80
|
-
# Make sure we don't return -0.0.
|
|
81
|
-
if not entropy:
|
|
82
|
-
entropy = 0.0
|
|
83
|
-
|
|
84
|
-
return entropy
|
|
85
|
-
|
|
86
|
-
def update(self, data: AnyStr, length: int = 0):
|
|
87
|
-
if not length:
|
|
88
|
-
length = len(data)
|
|
89
|
-
|
|
90
|
-
self.length += length
|
|
91
|
-
self.c = frequency.counts(data, length, self.c)
|
|
@@ -10,7 +10,7 @@ except Exception: # pylint:disable=W0702
|
|
|
10
10
|
ip = 'x.x.x.x'
|
|
11
11
|
# noinspection PyBroadException
|
|
12
12
|
try:
|
|
13
|
-
from
|
|
13
|
+
from assemblyline_toolbox import get_hostip
|
|
14
14
|
ip = get_hostip()
|
|
15
15
|
except Exception: # pylint:disable=W0702
|
|
16
16
|
pass
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
from ipaddress import ip_address, IPv4Network
|
|
2
|
+
import socket
|
|
3
|
+
import os
|
|
4
|
+
import functools
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
from assemblyline.common.net_static import TLDS_ALPHA_BY_DOMAIN, TLDS_SPECIAL_BY_DOMAIN
|
|
8
|
+
SYSTEM_LOCAL_TLD = os.getenv('SYSTEM_LOCAL_TLD', '')
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def is_valid_port(value: int) -> bool:
|
|
12
|
+
try:
|
|
13
|
+
if 1 <= int(value) <= 65535:
|
|
14
|
+
return True
|
|
15
|
+
except ValueError:
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
return False
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@functools.cache
|
|
22
|
+
def find_top_level_domains():
|
|
23
|
+
"""Combine (once and memoize) the three different sources of TLD."""
|
|
24
|
+
combined_tlds = TLDS_ALPHA_BY_DOMAIN.union({d for d in TLDS_SPECIAL_BY_DOMAIN if '.' not in d})
|
|
25
|
+
local_tld = [tld.strip().strip('.').upper() for tld in SYSTEM_LOCAL_TLD.split(";")]
|
|
26
|
+
combined_tlds |= {tld for tld in local_tld if tld}
|
|
27
|
+
return combined_tlds
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def is_valid_domain(domain: str) -> bool:
|
|
31
|
+
if "@" in domain:
|
|
32
|
+
return False
|
|
33
|
+
|
|
34
|
+
if "." in domain:
|
|
35
|
+
domain = domain.upper()
|
|
36
|
+
tld = domain.split(".")[-1]
|
|
37
|
+
if not tld.isascii():
|
|
38
|
+
try:
|
|
39
|
+
tld = tld.encode('idna').decode('ascii').upper()
|
|
40
|
+
except ValueError:
|
|
41
|
+
return False
|
|
42
|
+
|
|
43
|
+
combined_tlds = find_top_level_domains()
|
|
44
|
+
if tld in combined_tlds:
|
|
45
|
+
# Single term TLD check
|
|
46
|
+
return True
|
|
47
|
+
|
|
48
|
+
elif any(domain.endswith(d) for d in TLDS_SPECIAL_BY_DOMAIN):
|
|
49
|
+
# Multi-term TLD check
|
|
50
|
+
return True
|
|
51
|
+
|
|
52
|
+
return False
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def is_valid_ip(ip: str) -> bool:
|
|
56
|
+
parts = ip.split(".")
|
|
57
|
+
if len(parts) == 4:
|
|
58
|
+
for p in parts:
|
|
59
|
+
try:
|
|
60
|
+
if not (0 <= int(p) <= 255):
|
|
61
|
+
return False
|
|
62
|
+
except ValueError:
|
|
63
|
+
return False
|
|
64
|
+
|
|
65
|
+
if int(parts[0]) == 0:
|
|
66
|
+
return False
|
|
67
|
+
|
|
68
|
+
if int(parts[3]) == 0:
|
|
69
|
+
return False
|
|
70
|
+
|
|
71
|
+
return True
|
|
72
|
+
|
|
73
|
+
return False
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def is_ip_in_network(ip: str, network: IPv4Network) -> bool:
|
|
77
|
+
if not is_valid_ip(ip):
|
|
78
|
+
return False
|
|
79
|
+
|
|
80
|
+
return ip_address(ip) in network
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def is_valid_email(email: str) -> bool:
|
|
84
|
+
parts = email.split("@")
|
|
85
|
+
if len(parts) == 2:
|
|
86
|
+
if is_valid_domain(parts[1]):
|
|
87
|
+
return True
|
|
88
|
+
|
|
89
|
+
return False
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def get_hostname() -> str:
|
|
93
|
+
return socket.gethostname()
|
|
@@ -582,291 +582,3 @@ class SubmissionFilter:
|
|
|
582
582
|
return '<SubmissionFilter ' + str(self.expression) + '>'
|
|
583
583
|
|
|
584
584
|
|
|
585
|
-
def should_resubmit(score: float, shift: float = 500) -> bool:
|
|
586
|
-
|
|
587
|
-
# Resubmit:
|
|
588
|
-
#
|
|
589
|
-
# 100% with a score above 400.
|
|
590
|
-
# 10% with a score of 301 to 400.
|
|
591
|
-
# 1% with a score of 201 to 300.
|
|
592
|
-
# 0.1% with a score of 101 to 200.
|
|
593
|
-
# 0.01% with a score of 1 to 100.
|
|
594
|
-
# 0.001% with a score of 0.
|
|
595
|
-
# 0% with a score below 0.
|
|
596
|
-
|
|
597
|
-
if score < 0:
|
|
598
|
-
return False
|
|
599
|
-
|
|
600
|
-
if score >= shift:
|
|
601
|
-
return True
|
|
602
|
-
|
|
603
|
-
resubmit_probability = 1.0 / 10 ** ((shift - score) / 100)
|
|
604
|
-
|
|
605
|
-
return random.random() < resubmit_probability
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
class ActionWorker:
|
|
609
|
-
def __init__(self, cache: bool, config, datastore, redis_persist) -> None:
|
|
610
|
-
# Store parameters
|
|
611
|
-
self.running_cache_tasks = cache
|
|
612
|
-
|
|
613
|
-
# Setup dependencies
|
|
614
|
-
self.config = config
|
|
615
|
-
self.datastore = datastore
|
|
616
|
-
|
|
617
|
-
# Submissions that should have alerts generated
|
|
618
|
-
self.alert_queue: NamedQueue[dict] = NamedQueue(ALERT_QUEUE_NAME, redis_persist)
|
|
619
|
-
self.unique_queue: PriorityQueue[dict] = PriorityQueue('m-unique', redis_persist)
|
|
620
|
-
self.config_hash: Hash[str] = Hash(CONFIG_HASH, redis_persist)
|
|
621
|
-
|
|
622
|
-
# Archive manager (late import due to circular import)
|
|
623
|
-
from assemblyline.common.archiving import ArchiveManager
|
|
624
|
-
self.archive_manager: ArchiveManager = ArchiveManager(self.config, self.datastore)
|
|
625
|
-
|
|
626
|
-
# Load actions
|
|
627
|
-
self.actions: dict[str, tuple[SubmissionFilter, PostprocessAction]] = {}
|
|
628
|
-
self._load_actions()
|
|
629
|
-
|
|
630
|
-
# Make sure we load any changed actions
|
|
631
|
-
self.reload_watcher: EventWatcher[str] = EventWatcher()
|
|
632
|
-
self.reload_watcher.register('system.postprocess', self._load_actions)
|
|
633
|
-
self.reload_watcher.start()
|
|
634
|
-
|
|
635
|
-
# Create an event loop to handle highly parallel webhook calls
|
|
636
|
-
self.loop = asyncio.new_event_loop()
|
|
637
|
-
threading.Thread(target=self.loop.run_forever, name='webhook_caller', daemon=True).start()
|
|
638
|
-
|
|
639
|
-
def stop(self):
|
|
640
|
-
self.reload_watcher.stop()
|
|
641
|
-
while self.loop.is_running():
|
|
642
|
-
if len(asyncio.all_tasks(self.loop)) == 0:
|
|
643
|
-
break
|
|
644
|
-
time.sleep(0.1)
|
|
645
|
-
self.loop.call_soon_threadsafe(self.loop.stop)
|
|
646
|
-
|
|
647
|
-
def _load_actions(self, _path: Optional[str] = None):
|
|
648
|
-
# Load the action data from redis
|
|
649
|
-
data = self.config_hash.get(POST_PROCESS_CONFIG_KEY)
|
|
650
|
-
|
|
651
|
-
# If nothing is in redis, fall back to legacy storage
|
|
652
|
-
if data is None:
|
|
653
|
-
try:
|
|
654
|
-
with CacheStore('system', config=self.config, datastore=self.datastore) as cache:
|
|
655
|
-
byte_data = cache.get('postprocess_actions')
|
|
656
|
-
if byte_data:
|
|
657
|
-
data = byte_data.decode()
|
|
658
|
-
except Exception:
|
|
659
|
-
logger.warn("Couldn't access system files")
|
|
660
|
-
|
|
661
|
-
# Decode data
|
|
662
|
-
objects = DEFAULT_POSTPROCESS_ACTIONS
|
|
663
|
-
if data:
|
|
664
|
-
try:
|
|
665
|
-
raw: dict[str, Any] = yaml.safe_load(data)
|
|
666
|
-
objects = {
|
|
667
|
-
key: PostprocessAction(data)
|
|
668
|
-
for key, data in raw.items()
|
|
669
|
-
}
|
|
670
|
-
except Exception:
|
|
671
|
-
logger.exception("Couldn't load stored actions")
|
|
672
|
-
|
|
673
|
-
# Check which ones can be active
|
|
674
|
-
ready_objects: dict[str, tuple[SubmissionFilter, PostprocessAction]] = {}
|
|
675
|
-
for key, action in objects.items():
|
|
676
|
-
if not action.enabled:
|
|
677
|
-
continue
|
|
678
|
-
|
|
679
|
-
try:
|
|
680
|
-
fltr = SubmissionFilter(action.filter)
|
|
681
|
-
except Exception:
|
|
682
|
-
logger.exception("Failed to load submission filter")
|
|
683
|
-
continue
|
|
684
|
-
|
|
685
|
-
if self.running_cache_tasks and action.run_on_cache:
|
|
686
|
-
if not fltr.cache_safe:
|
|
687
|
-
logger.error("Tried to apply non-cache-safe filter to cached submissions.")
|
|
688
|
-
continue
|
|
689
|
-
ready_objects[key] = fltr, action
|
|
690
|
-
|
|
691
|
-
if not self.running_cache_tasks and action.run_on_completed:
|
|
692
|
-
ready_objects[key] = fltr, action
|
|
693
|
-
|
|
694
|
-
# Swap in the new actions
|
|
695
|
-
self.actions = ready_objects
|
|
696
|
-
|
|
697
|
-
def process_submission(self, submission: Submission, tags: list[dict[str, Any]]) -> bool:
|
|
698
|
-
return self.process(submission=submission, tags=tags, score=submission.max_score)
|
|
699
|
-
|
|
700
|
-
def process_cachehit(self, submission: SubmissionMessage, score: float) -> bool:
|
|
701
|
-
return self.process(submission=submission, tags=None, score=score)
|
|
702
|
-
|
|
703
|
-
def process(self, submission: Union[Submission, SubmissionMessage],
|
|
704
|
-
score: float, tags: Optional[list[dict[str, Any]]]) -> bool:
|
|
705
|
-
""" Handle any postprocessing events for a submission.
|
|
706
|
-
|
|
707
|
-
Return bool indicating if a resubmission action has happened.
|
|
708
|
-
"""
|
|
709
|
-
archive_submission = submission.params.auto_archive
|
|
710
|
-
use_archive_alternate_dtl = submission.params.use_archive_alternate_dtl
|
|
711
|
-
create_alert = False
|
|
712
|
-
resubmit: Optional[set[str]] = None
|
|
713
|
-
webhooks = []
|
|
714
|
-
|
|
715
|
-
for fltr, action in self.actions.values():
|
|
716
|
-
if not fltr.test(submission, score=score, tags=tags):
|
|
717
|
-
continue
|
|
718
|
-
|
|
719
|
-
# Check if we need to launch an alert
|
|
720
|
-
create_alert |= action.raise_alert
|
|
721
|
-
|
|
722
|
-
# Check if we need to archive the submission
|
|
723
|
-
archive_submission |= action.archive_submission
|
|
724
|
-
use_archive_alternate_dtl |= action.use_archive_alternate_dtl
|
|
725
|
-
|
|
726
|
-
# Accumulate resubmit services
|
|
727
|
-
if action.resubmit is not None:
|
|
728
|
-
do_resubmit = True
|
|
729
|
-
if action.resubmit.random_below is not None:
|
|
730
|
-
do_resubmit = should_resubmit(score, action.resubmit.random_below)
|
|
731
|
-
|
|
732
|
-
if do_resubmit:
|
|
733
|
-
if resubmit is None:
|
|
734
|
-
resubmit = set()
|
|
735
|
-
resubmit.update(set(action.resubmit.additional_services))
|
|
736
|
-
|
|
737
|
-
# Accumulate hooks
|
|
738
|
-
if action.webhook is not None and action.webhook not in webhooks:
|
|
739
|
-
webhooks.append(action.webhook)
|
|
740
|
-
|
|
741
|
-
# Bail early if nothing is to be done
|
|
742
|
-
if resubmit is None and not create_alert and not webhooks and not archive_submission:
|
|
743
|
-
return False
|
|
744
|
-
|
|
745
|
-
# Prepare a message formatted submission
|
|
746
|
-
if isinstance(submission, Submission):
|
|
747
|
-
submission_msg = from_datastore_submission(submission)
|
|
748
|
-
else:
|
|
749
|
-
submission_msg = submission
|
|
750
|
-
|
|
751
|
-
# Default values
|
|
752
|
-
extended_scan = 'skipped'
|
|
753
|
-
did_resubmit = False
|
|
754
|
-
submit_to = []
|
|
755
|
-
|
|
756
|
-
# Check if we resubmit
|
|
757
|
-
if resubmit is not None:
|
|
758
|
-
selected = set(submission.params.services.selected)
|
|
759
|
-
resubmit_to = set(submission.params.services.resubmit) | resubmit
|
|
760
|
-
|
|
761
|
-
if not selected.issuperset(resubmit_to):
|
|
762
|
-
submit_to = sorted(selected | resubmit_to)
|
|
763
|
-
extended_scan = 'submitted'
|
|
764
|
-
|
|
765
|
-
# Raise alert
|
|
766
|
-
if submission.params.generate_alert and create_alert:
|
|
767
|
-
logger.info(f"[{submission_msg.sid} :: {submission_msg.files[0].sha256}] Notifying alerter to "
|
|
768
|
-
"create or update an alert")
|
|
769
|
-
|
|
770
|
-
self.alert_queue.push(dict(
|
|
771
|
-
submission=submission_msg.as_primitives(),
|
|
772
|
-
score=score,
|
|
773
|
-
extended_scan=extended_scan,
|
|
774
|
-
ingest_id=submission_msg.metadata.get('ingest_id', None)
|
|
775
|
-
))
|
|
776
|
-
|
|
777
|
-
if submit_to:
|
|
778
|
-
logger.info(f"[{submission.sid} :: {submission.files[0].sha256}] Resubmitted for extended analysis")
|
|
779
|
-
resubmission = SubmissionMessage(submission_msg.as_primitives())
|
|
780
|
-
resubmission.params.psid = submission.sid
|
|
781
|
-
resubmission.sid = get_random_id()
|
|
782
|
-
resubmission.scan_key = None
|
|
783
|
-
resubmission.params.services.resubmit = []
|
|
784
|
-
resubmission.params.services.selected = submit_to
|
|
785
|
-
|
|
786
|
-
self.unique_queue.push(submission.params.priority, dict(
|
|
787
|
-
score=score,
|
|
788
|
-
extended_scan=extended_scan,
|
|
789
|
-
ingest_id=submission.metadata.get('ingest_id', None),
|
|
790
|
-
submission=resubmission.as_primitives(),
|
|
791
|
-
))
|
|
792
|
-
did_resubmit = True
|
|
793
|
-
|
|
794
|
-
# Archive the submission
|
|
795
|
-
if archive_submission:
|
|
796
|
-
if self.config.datastore.archive.enabled:
|
|
797
|
-
logger.info(f"[{submission_msg.sid} :: {submission_msg.files[0].sha256}] Evaluating if the file can"
|
|
798
|
-
" be moved to the malware archive")
|
|
799
|
-
|
|
800
|
-
if self.archive_manager.archive_submission(
|
|
801
|
-
submission_msg.as_primitives(),
|
|
802
|
-
submission_msg.params.delete_after_archive,
|
|
803
|
-
use_alternate_dtl=use_archive_alternate_dtl)['action'] == "archive":
|
|
804
|
-
logger.info(f"[{submission_msg.sid} :: {submission_msg.files[0].sha256}] Archiver was notified "
|
|
805
|
-
"to copy the file in the malware archive")
|
|
806
|
-
else:
|
|
807
|
-
logger.info(f"[{submission_msg.sid} :: {submission_msg.files[0].sha256}] The file was "
|
|
808
|
-
"re-submitted for analysis because it does not meet the minimum service requirement")
|
|
809
|
-
|
|
810
|
-
else:
|
|
811
|
-
logger.warning(f"[{submission_msg.sid} :: {submission_msg.files[0].sha256}] Trying to archive a "
|
|
812
|
-
"submission on a system where archiving is disabled")
|
|
813
|
-
|
|
814
|
-
# Trigger webhooks
|
|
815
|
-
for hook in webhooks:
|
|
816
|
-
asyncio.run_coroutine_threadsafe(self._process_hook(hook, submission, score), self.loop)
|
|
817
|
-
|
|
818
|
-
return did_resubmit
|
|
819
|
-
|
|
820
|
-
async def _process_hook(self, hook: Webhook, submission: Union[Submission, SubmissionMessage], score: float):
|
|
821
|
-
backoff = 0.0
|
|
822
|
-
cafile = None
|
|
823
|
-
|
|
824
|
-
try:
|
|
825
|
-
is_cache = isinstance(submission, SubmissionMessage)
|
|
826
|
-
payload = json.dumps({
|
|
827
|
-
'is_cache': is_cache,
|
|
828
|
-
'score': score,
|
|
829
|
-
'submission': submission.as_primitives()
|
|
830
|
-
})
|
|
831
|
-
|
|
832
|
-
# Setup auth headers and other headers
|
|
833
|
-
auth = None
|
|
834
|
-
if hook.username and hook.password:
|
|
835
|
-
auth = aiohttp.BasicAuth(login=hook.username, password=hook.password)
|
|
836
|
-
headers = {head.name: head.value for head in hook.headers}
|
|
837
|
-
headers.setdefault('Content-Type', 'application/json')
|
|
838
|
-
|
|
839
|
-
# Setup ssl details
|
|
840
|
-
sslcontext: Union[None, bool, ssl.SSLContext] = None
|
|
841
|
-
if hook.ssl_ignore_errors:
|
|
842
|
-
sslcontext = False
|
|
843
|
-
if hook.ca_cert:
|
|
844
|
-
cafile = tempfile.NamedTemporaryFile()
|
|
845
|
-
cafile.write(hook.ca_cert.encode())
|
|
846
|
-
cafile.flush()
|
|
847
|
-
sslcontext = ssl.create_default_context(cafile=cafile.name)
|
|
848
|
-
|
|
849
|
-
# Setup setup http query details
|
|
850
|
-
async with aiohttp.ClientSession(auth=auth, headers=headers) as session:
|
|
851
|
-
# Loop up to retry limit
|
|
852
|
-
for _ in range(hook.retries):
|
|
853
|
-
# Wait before retrying, 0 first time, so we can have this before the post
|
|
854
|
-
# and not wait after the final failure
|
|
855
|
-
await asyncio.sleep(backoff)
|
|
856
|
-
backoff = min(RETRY_MAX_BACKOFF, backoff * 2) + 0.1
|
|
857
|
-
|
|
858
|
-
# Try posting to the webhook once. If it succeeds return and let
|
|
859
|
-
# the withs and finallys finish all the cleanup
|
|
860
|
-
try:
|
|
861
|
-
resp = await session.request(hook.method, hook.uri, data=payload,
|
|
862
|
-
ssl=sslcontext, proxy=hook.proxy)
|
|
863
|
-
resp.raise_for_status()
|
|
864
|
-
return
|
|
865
|
-
except Exception:
|
|
866
|
-
logger.exception(f"Error pushing to webhook: {hook}")
|
|
867
|
-
|
|
868
|
-
except Exception:
|
|
869
|
-
logger.exception(f"Error reading webhook configuration: {hook}")
|
|
870
|
-
finally:
|
|
871
|
-
if cafile is not None:
|
|
872
|
-
cafile.close()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: assemblyline
|
|
3
|
-
Version: 4.7.2.
|
|
3
|
+
Version: 4.7.2.dev30
|
|
4
4
|
Summary: Assemblyline 4 - Automated malware analysis framework
|
|
5
5
|
Home-page: https://github.com/CybercentreCanada/assemblyline-base
|
|
6
6
|
Author: CCCS Assemblyline development team
|
|
@@ -24,25 +24,20 @@ Requires-Dist: urllib3>=2.6.0
|
|
|
24
24
|
Requires-Dist: python-baseconv
|
|
25
25
|
Requires-Dist: boto3
|
|
26
26
|
Requires-Dist: pysftp
|
|
27
|
-
Requires-Dist: netifaces
|
|
28
|
-
Requires-Dist: pyroute2.core
|
|
29
27
|
Requires-Dist: redis
|
|
30
28
|
Requires-Dist: requests[socks]
|
|
31
29
|
Requires-Dist: elasticsearch<9.0.0,>=8.0.0
|
|
32
30
|
Requires-Dist: python-datemath!=3.0.2
|
|
33
31
|
Requires-Dist: packaging
|
|
34
|
-
Requires-Dist: tabulate
|
|
35
32
|
Requires-Dist: PyYAML
|
|
36
|
-
Requires-Dist: easydict
|
|
37
33
|
Requires-Dist: bcrypt
|
|
38
34
|
Requires-Dist: cart
|
|
39
|
-
Requires-Dist:
|
|
35
|
+
Requires-Dist: assemblyline-toolbox==0.3.0
|
|
40
36
|
Requires-Dist: python-magic
|
|
41
37
|
Requires-Dist: pytz
|
|
42
38
|
Requires-Dist: apscheduler
|
|
43
39
|
Requires-Dist: websocket_client<1.0.0
|
|
44
40
|
Requires-Dist: elastic-apm[flask]>=6.13.0
|
|
45
|
-
Requires-Dist: cython
|
|
46
41
|
Requires-Dist: docker
|
|
47
42
|
Requires-Dist: kubernetes>18
|
|
48
43
|
Requires-Dist: notifications-python-client
|
|
@@ -52,7 +47,6 @@ Requires-Dist: azure-identity
|
|
|
52
47
|
Requires-Dist: msoffcrypto-tool
|
|
53
48
|
Requires-Dist: chardet<6
|
|
54
49
|
Requires-Dist: yara-python
|
|
55
|
-
Requires-Dist: python-tlsh
|
|
56
50
|
Requires-Dist: hauntedhouse==0.1.10
|
|
57
51
|
Requires-Dist: magika
|
|
58
52
|
Requires-Dist: paramiko<4
|
|
@@ -37,7 +37,6 @@ assemblyline/common/entropy.py
|
|
|
37
37
|
assemblyline/common/exceptions.py
|
|
38
38
|
assemblyline/common/file.py
|
|
39
39
|
assemblyline/common/forge.py
|
|
40
|
-
assemblyline/common/frequency.pyx
|
|
41
40
|
assemblyline/common/heuristics.py
|
|
42
41
|
assemblyline/common/hexdump.py
|
|
43
42
|
assemblyline/common/identify.py
|
|
@@ -5,25 +5,20 @@ urllib3>=2.6.0
|
|
|
5
5
|
python-baseconv
|
|
6
6
|
boto3
|
|
7
7
|
pysftp
|
|
8
|
-
netifaces
|
|
9
|
-
pyroute2.core
|
|
10
8
|
redis
|
|
11
9
|
requests[socks]
|
|
12
10
|
elasticsearch<9.0.0,>=8.0.0
|
|
13
11
|
python-datemath!=3.0.2
|
|
14
12
|
packaging
|
|
15
|
-
tabulate
|
|
16
13
|
PyYAML
|
|
17
|
-
easydict
|
|
18
14
|
bcrypt
|
|
19
15
|
cart
|
|
20
|
-
|
|
16
|
+
assemblyline-toolbox==0.3.0
|
|
21
17
|
python-magic
|
|
22
18
|
pytz
|
|
23
19
|
apscheduler
|
|
24
20
|
websocket_client<1.0.0
|
|
25
21
|
elastic-apm[flask]>=6.13.0
|
|
26
|
-
cython
|
|
27
22
|
docker
|
|
28
23
|
kubernetes>18
|
|
29
24
|
notifications-python-client
|
|
@@ -33,7 +28,6 @@ azure-identity
|
|
|
33
28
|
msoffcrypto-tool
|
|
34
29
|
chardet<6
|
|
35
30
|
yara-python
|
|
36
|
-
python-tlsh
|
|
37
31
|
hauntedhouse==0.1.10
|
|
38
32
|
magika
|
|
39
33
|
paramiko<4
|