txt2stix 1.0.8__tar.gz → 1.0.10__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.
- {txt2stix-1.0.8 → txt2stix-1.0.10}/PKG-INFO +1 -1
- {txt2stix-1.0.8 → txt2stix-1.0.10}/pyproject.toml +1 -1
- txt2stix-1.0.10/requirements.txt +233 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/attack_flow_demo.txt +3 -1
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/manual-tests/cases-standard-tests.md +18 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/src/test_attack_flow.py +76 -26
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/ai_extractor/openai.py +6 -1
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/attack_flow.py +16 -5
- txt2stix-1.0.8/requirements.txt +0 -377
- {txt2stix-1.0.8 → txt2stix-1.0.10}/.env.example +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/.env.markdown +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/.github/workflows/create-release.yml +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/.github/workflows/run-tests.yml +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/.gitignore +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/LICENSE +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/README.md +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/docs/README.md +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/docs/stix-mapping.md +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/docs/txt2stix.png +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/__init__.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/extractions/ai/config.yaml +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/extractions/lookup/config.yaml +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/extractions/pattern/config.yaml +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/helpers/mimetype_filename_extension_list.csv +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/helpers/stix_relationship_types.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/helpers/tlds.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/helpers/windows_registry_key_prefix.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/_README.md +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/_generate_lookups.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/attack_pattern.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/campaign.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/country_iso3166_alpha2.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/course_of_action.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/disarm_id_v1_5.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/disarm_name_v1_5.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/extensions.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/identity.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/infrastructure.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/intrusion_set.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/malware.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/mitre_atlas_id_v4_5_2.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/mitre_atlas_name_v4_5_2.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/mitre_attack_enterprise_aliases_v16_0.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/mitre_attack_enterprise_id_v16_0.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/mitre_attack_enterprise_name_v16_0.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/mitre_attack_ics_aliases_v16_0.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/mitre_attack_ics_id_v16_0.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/mitre_attack_ics_name_v16_0.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/mitre_attack_mobile_aliases_v16_0.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/mitre_attack_mobile_id_v16_0.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/mitre_attack_mobile_name_v16_0.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/mitre_capec_id_v3_9.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/mitre_capec_name_v3_9.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/mitre_cwe_id_v4_15.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/mitre_cwe_name_v4_15.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/threat_actor.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/tld.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/lookups/tool.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/includes/tests/test_cases.yaml +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/README.md +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/ai_country.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/ai_mitre_attack_enterprise.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/ai_mitre_attack_ics.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/ai_mitre_attack_mobile.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/ai_mitre_capec.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/ai_mitre_cwe.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/all_cases.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_autonomous_system_number.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_bank_card_all.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_bank_card_amex.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_bank_card_diners.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_bank_card_discover.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_bank_card_jcb.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_bank_card_mastercard.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_bank_card_union_pay.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_bank_card_visa.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_country_alpha2.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_cpe_uri.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_cryptocurrency_btc_transaction.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_cryptocurrency_btc_wallet.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_cryptocurrency_eth_transaction.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_cryptocurrency_eth_wallet.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_cryptocurrency_xmr_transaction.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_cryptocurrency_xmr_wallet.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_cve_id.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_directory_unix.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_directory_unix_file.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_directory_windows.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_directory_windows_with_file.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_disarm.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_disarm_name.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_domain_name_only.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_domain_name_subdomain.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_email_address.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_file_hash_md5.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_file_hash_sha_1.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_file_hash_sha_224.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_file_hash_sha_256.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_file_hash_sha_384.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_file_hash_sha_512.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_file_name.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_host_name.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_host_name_file.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_host_name_path.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_host_name_subdomain.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_host_name_url.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_iban_number.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_ipv4_address_cidr.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_ipv4_address_only.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_ipv4_address_port.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_ipv6_address_cidr.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_ipv6_address_only.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_ipv6_address_port.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mac_address.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mitre_atlas.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mitre_atlas_name.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mitre_attack_enterprise.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mitre_attack_enterprise_aliases.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mitre_attack_enterprise_name.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mitre_attack_ics.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mitre_attack_ics_aliases.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mitre_attack_ics_name.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mitre_attack_mobile.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mitre_attack_mobile_aliases.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mitre_attack_mobile_name.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mitre_capec.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mitre_capec_name.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mitre_cwe.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_mitre_cwe_name.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_phone_number.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_url.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_url_file.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_url_path.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_user_agent.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/generic_windows_registry_key.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/lookup_attack_pattern.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/lookup_campaign.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/lookup_course_of_action.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/lookup_identity.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/lookup_infrastructure.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/lookup_intrusion_set.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/lookup_malware.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/lookup_threat_actor.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/extraction_types/lookup_tool.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/attack_navigator_demo.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/basic_relationship.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/char_length_too_long.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/descriptive_for_ai_relationships_1.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/disarm_demo.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/embedded_img_ignore.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/embedded_link_ignore.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/ip1.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/ip2.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/known_whitelist_match.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/mitre_attack_enterprise_ai_demo.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/mitre_attack_enterprise_lookup_demo.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/mixed_extractions.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/not_security_content.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/test_ai_hash_error_with_stix2_lib.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/test_aliases.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/test_extraction_boundary.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/test_extraction_escapes.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/real_intel_reports/APT28-Center-of-Storm-2017.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/real_intel_reports/Bitdefender-Labs-Report-X-creat6958-en-EN.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/real_intel_reports/FireEyeAPT39.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/real_intel_reports/France_CERT_APT31_Pakdoor_TLPWHITE.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/real_intel_reports/Group-IB_Ransomware_Uncovered_whitepaper_eng.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/real_intel_reports/JOINT_CSA_HUNTING_RU_INTEL_SNAKE_MALWARE_20230509.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/real_intel_reports/TA22-0126-QAKBOT-analysis-TLP-GREEN.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/real_intel_reports/dinners_card.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/real_intel_reports/mandiant-apt1.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/real_intel_reports/mykings_report_final.txt +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/manual-tests/cases-ai-relationships.md +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/manual-tests/cases-extraction-type-ai.md +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/manual-tests/cases-extraction-type-lookup.md +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/manual-tests/cases-extraction-type-pattern.md +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/scripts/generate_simple_extraction_test_cases_txt_files.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/src/__init__.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/src/test_bundler.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/src/test_extractors.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/src/test_indicator.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/src/test_lookups.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/src/test_main.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/src/test_retriever.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/src/test_run_txt2stix.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/src/test_utils.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/tests/src/utils.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/__init__.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/ai_extractor/__init__.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/ai_extractor/anthropic.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/ai_extractor/base.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/ai_extractor/deepseek.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/ai_extractor/gemini.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/ai_extractor/openrouter.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/ai_extractor/prompts.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/ai_extractor/utils.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/bundler.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/common.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/credential_checker.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/extractions.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/indicator.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/lookups.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/__init__.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/__init__.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/base_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/card/README.md +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/card/__init__.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/card/amex_card_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/card/diners_card_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/card/discover_card_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/card/jcb_card_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/card/master_card_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/card/union_card_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/card/visa_card_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/crypto/__init__.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/crypto/btc_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/directory/__init__.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/directory/unix_directory_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/directory/unix_file_path_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/directory/windows_directory_path_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/directory/windows_file_path_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/domain/__init__.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/domain/domain_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/domain/hostname_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/domain/sub_domain_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/hashes/__init__.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/hashes/md5_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/hashes/sha1_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/hashes/sha224_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/hashes/sha2_256_exactor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/hashes/sha2_512_exactor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/hashes/sha3_256_exactor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/hashes/sha3_512_exactor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/helper.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/ip/__init__.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/ip/ipv4_cidr_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/ip/ipv4_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/ip/ipv4_port_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/ip/ipv6_cidr_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/ip/ipv6_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/ip/ipv6_port_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/others/__init__.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/others/asn_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/others/cpe_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/others/cve_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/others/email_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/others/filename_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/others/iban_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/others/mac_address_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/others/phonenumber_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/others/user_agent_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/others/windows_registry_key_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/url/__init__.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/url/url_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/url/url_file_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/pattern/extractors/url/url_path_extractor.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/retriever.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/stix.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/txt2stix.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix/utils.py +0 -0
- {txt2stix-1.0.8 → txt2stix-1.0.10}/txt2stix.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: txt2stix
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.10
|
4
4
|
Summary: txt2stix is a Python script that is designed to identify and extract IoCs and TTPs from text files, identify the relationships between them, convert them to STIX 2.1 objects, and output as a STIX 2.1 bundle.
|
5
5
|
Project-URL: Homepage, https://github.com/muchdogesec/txt2stix
|
6
6
|
Project-URL: Issues, https://github.com/muchdogesec/txt2stix/issues
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "txt2stix"
|
7
|
-
version = "1.0.
|
7
|
+
version = "1.0.10"
|
8
8
|
authors = [{ name = "dogesec" }]
|
9
9
|
maintainers = [{ name = "dogesec" }]
|
10
10
|
description = "txt2stix is a Python script that is designed to identify and extract IoCs and TTPs from text files, identify the relationships between them, convert them to STIX 2.1 objects, and output as a STIX 2.1 bundle."
|
@@ -0,0 +1,233 @@
|
|
1
|
+
#
|
2
|
+
# This file is autogenerated by pip-compile with Python 3.13
|
3
|
+
# by the following command:
|
4
|
+
#
|
5
|
+
# pip-compile --output-file=requirements.txt pyproject.toml
|
6
|
+
#
|
7
|
+
aiohappyeyeballs==2.6.1
|
8
|
+
# via aiohttp
|
9
|
+
aiohttp==3.12.15
|
10
|
+
# via llama-index-core
|
11
|
+
aiosignal==1.4.0
|
12
|
+
# via aiohttp
|
13
|
+
aiosqlite==0.21.0
|
14
|
+
# via llama-index-core
|
15
|
+
annotated-types==0.7.0
|
16
|
+
# via pydantic
|
17
|
+
antlr4-python3-runtime==4.9.3
|
18
|
+
# via stix2-patterns
|
19
|
+
anyio==4.10.0
|
20
|
+
# via
|
21
|
+
# httpx
|
22
|
+
# openai
|
23
|
+
attrs==25.3.0
|
24
|
+
# via aiohttp
|
25
|
+
banks==2.2.0
|
26
|
+
# via llama-index-core
|
27
|
+
base58==2.1.1
|
28
|
+
# via txt2stix (pyproject.toml)
|
29
|
+
beautifulsoup4==4.13.5
|
30
|
+
# via txt2stix (pyproject.toml)
|
31
|
+
certifi==2025.8.3
|
32
|
+
# via
|
33
|
+
# httpcore
|
34
|
+
# httpx
|
35
|
+
# requests
|
36
|
+
charset-normalizer==3.4.3
|
37
|
+
# via requests
|
38
|
+
click==8.2.1
|
39
|
+
# via nltk
|
40
|
+
colorama==0.4.6
|
41
|
+
# via griffe
|
42
|
+
dataclasses-json==0.6.7
|
43
|
+
# via llama-index-core
|
44
|
+
deprecated==1.2.18
|
45
|
+
# via
|
46
|
+
# banks
|
47
|
+
# llama-index-core
|
48
|
+
# llama-index-instrumentation
|
49
|
+
dirtyjson==1.0.8
|
50
|
+
# via llama-index-core
|
51
|
+
distro==1.9.0
|
52
|
+
# via openai
|
53
|
+
filelock==3.19.1
|
54
|
+
# via tldextract
|
55
|
+
filetype==1.2.0
|
56
|
+
# via llama-index-core
|
57
|
+
frozenlist==1.7.0
|
58
|
+
# via
|
59
|
+
# aiohttp
|
60
|
+
# aiosignal
|
61
|
+
fsspec==2025.7.0
|
62
|
+
# via llama-index-core
|
63
|
+
greenlet==3.2.4
|
64
|
+
# via sqlalchemy
|
65
|
+
griffe==1.13.0
|
66
|
+
# via banks
|
67
|
+
h11==0.16.0
|
68
|
+
# via httpcore
|
69
|
+
httpcore==1.0.9
|
70
|
+
# via httpx
|
71
|
+
httpx==0.28.1
|
72
|
+
# via
|
73
|
+
# llama-index-core
|
74
|
+
# openai
|
75
|
+
idna==3.10
|
76
|
+
# via
|
77
|
+
# anyio
|
78
|
+
# httpx
|
79
|
+
# requests
|
80
|
+
# tldextract
|
81
|
+
# yarl
|
82
|
+
jinja2==3.1.6
|
83
|
+
# via banks
|
84
|
+
jiter==0.10.0
|
85
|
+
# via openai
|
86
|
+
joblib==1.5.1
|
87
|
+
# via nltk
|
88
|
+
llama-index-core==0.13.3
|
89
|
+
# via
|
90
|
+
# llama-index-llms-openai
|
91
|
+
# txt2stix (pyproject.toml)
|
92
|
+
llama-index-instrumentation==0.4.0
|
93
|
+
# via llama-index-workflows
|
94
|
+
llama-index-llms-openai==0.5.4
|
95
|
+
# via txt2stix (pyproject.toml)
|
96
|
+
llama-index-workflows==1.3.0
|
97
|
+
# via llama-index-core
|
98
|
+
markupsafe==3.0.2
|
99
|
+
# via jinja2
|
100
|
+
marshmallow==3.26.1
|
101
|
+
# via dataclasses-json
|
102
|
+
mistune==3.1.3
|
103
|
+
# via txt2stix (pyproject.toml)
|
104
|
+
multidict==6.6.4
|
105
|
+
# via
|
106
|
+
# aiohttp
|
107
|
+
# yarl
|
108
|
+
mypy-extensions==1.1.0
|
109
|
+
# via typing-inspect
|
110
|
+
nest-asyncio==1.6.0
|
111
|
+
# via llama-index-core
|
112
|
+
networkx==3.5
|
113
|
+
# via llama-index-core
|
114
|
+
nltk==3.9.1
|
115
|
+
# via llama-index-core
|
116
|
+
numpy==2.3.2
|
117
|
+
# via llama-index-core
|
118
|
+
openai==1.101.0
|
119
|
+
# via llama-index-llms-openai
|
120
|
+
packaging==25.0
|
121
|
+
# via marshmallow
|
122
|
+
pathvalidate==3.3.1
|
123
|
+
# via txt2stix (pyproject.toml)
|
124
|
+
phonenumbers==9.0.12
|
125
|
+
# via txt2stix (pyproject.toml)
|
126
|
+
pillow==11.3.0
|
127
|
+
# via llama-index-core
|
128
|
+
platformdirs==4.3.8
|
129
|
+
# via
|
130
|
+
# banks
|
131
|
+
# llama-index-core
|
132
|
+
propcache==0.3.2
|
133
|
+
# via
|
134
|
+
# aiohttp
|
135
|
+
# yarl
|
136
|
+
pycountry==24.6.1
|
137
|
+
# via schwifty
|
138
|
+
pydantic==2.11.7
|
139
|
+
# via
|
140
|
+
# banks
|
141
|
+
# llama-index-core
|
142
|
+
# llama-index-instrumentation
|
143
|
+
# llama-index-workflows
|
144
|
+
# openai
|
145
|
+
pydantic-core==2.33.2
|
146
|
+
# via pydantic
|
147
|
+
python-dotenv==1.1.1
|
148
|
+
# via txt2stix (pyproject.toml)
|
149
|
+
pytz==2025.2
|
150
|
+
# via stix2
|
151
|
+
pyyaml==6.0.2
|
152
|
+
# via llama-index-core
|
153
|
+
regex==2025.7.34
|
154
|
+
# via
|
155
|
+
# nltk
|
156
|
+
# tiktoken
|
157
|
+
requests==2.32.5
|
158
|
+
# via
|
159
|
+
# llama-index-core
|
160
|
+
# requests-file
|
161
|
+
# stix2
|
162
|
+
# stix2extensions
|
163
|
+
# tiktoken
|
164
|
+
# tldextract
|
165
|
+
# txt2stix (pyproject.toml)
|
166
|
+
requests-file==2.1.0
|
167
|
+
# via tldextract
|
168
|
+
rstr==3.2.2
|
169
|
+
# via schwifty
|
170
|
+
schwifty==2025.7.0
|
171
|
+
# via txt2stix (pyproject.toml)
|
172
|
+
simplejson==3.20.1
|
173
|
+
# via stix2
|
174
|
+
six==1.17.0
|
175
|
+
# via stix2-patterns
|
176
|
+
sniffio==1.3.1
|
177
|
+
# via
|
178
|
+
# anyio
|
179
|
+
# openai
|
180
|
+
soupsieve==2.7
|
181
|
+
# via beautifulsoup4
|
182
|
+
sqlalchemy[asyncio]==2.0.43
|
183
|
+
# via llama-index-core
|
184
|
+
stix2==3.0.1
|
185
|
+
# via stix2extensions
|
186
|
+
stix2-patterns==2.0.0
|
187
|
+
# via stix2
|
188
|
+
stix2extensions==1.1.1
|
189
|
+
# via txt2stix (pyproject.toml)
|
190
|
+
tenacity==9.1.2
|
191
|
+
# via llama-index-core
|
192
|
+
tiktoken==0.11.0
|
193
|
+
# via llama-index-core
|
194
|
+
tld==0.13.1
|
195
|
+
# via txt2stix (pyproject.toml)
|
196
|
+
tldextract==5.3.0
|
197
|
+
# via txt2stix (pyproject.toml)
|
198
|
+
tqdm==4.67.1
|
199
|
+
# via
|
200
|
+
# llama-index-core
|
201
|
+
# nltk
|
202
|
+
# openai
|
203
|
+
typing-extensions==4.15.0
|
204
|
+
# via
|
205
|
+
# aiosqlite
|
206
|
+
# beautifulsoup4
|
207
|
+
# llama-index-core
|
208
|
+
# llama-index-workflows
|
209
|
+
# openai
|
210
|
+
# pydantic
|
211
|
+
# pydantic-core
|
212
|
+
# sqlalchemy
|
213
|
+
# typing-inspect
|
214
|
+
# typing-inspection
|
215
|
+
typing-inspect==0.9.0
|
216
|
+
# via
|
217
|
+
# dataclasses-json
|
218
|
+
# llama-index-core
|
219
|
+
typing-inspection==0.4.1
|
220
|
+
# via pydantic
|
221
|
+
urllib3==2.5.0
|
222
|
+
# via requests
|
223
|
+
validators==0.35.0
|
224
|
+
# via txt2stix (pyproject.toml)
|
225
|
+
wrapt==1.17.3
|
226
|
+
# via
|
227
|
+
# deprecated
|
228
|
+
# llama-index-core
|
229
|
+
yarl==1.20.1
|
230
|
+
# via aiohttp
|
231
|
+
|
232
|
+
# The following packages are considered to be unsafe in a requirements file:
|
233
|
+
# setuptools
|
{txt2stix-1.0.8 → txt2stix-1.0.10}/tests/data/manually_generated_reports/attack_flow_demo.txt
RENAMED
@@ -4,4 +4,6 @@ Due to password protection, the zip files are able to bypass some AV detections.
|
|
4
4
|
|
5
5
|
The zip files are extracted and usually contain a malicious document, such as a .doc, .pdf, or .xls. Some examples are malware.pdf and bad.com
|
6
6
|
|
7
|
-
The extracted files contain malicious macros that connect to a C2 server 1.1.1.1
|
7
|
+
The extracted files contain malicious macros that connect to a C2 server 1.1.1.1
|
8
|
+
|
9
|
+
And here is a mobile ID to test behaviour of multiple matrices T1630.001
|
@@ -486,6 +486,24 @@ python3 txt2stix.py \
|
|
486
486
|
--report_id 3b160a8d-12dd-4e7c-aee8-5af6e371b425
|
487
487
|
```
|
488
488
|
|
489
|
+
with two domains
|
490
|
+
|
491
|
+
no indicators
|
492
|
+
|
493
|
+
```shell
|
494
|
+
python3 txt2stix.py \
|
495
|
+
--relationship_mode ai \
|
496
|
+
--ai_settings_relationships openai:gpt-5 \
|
497
|
+
--input_file tests/data/manually_generated_reports/attack_flow_demo.txt \
|
498
|
+
--name 'Test MITRE ATT&CK Flow demo' \
|
499
|
+
--tlp_level clear \
|
500
|
+
--confidence 100 \
|
501
|
+
--use_extractions 'ai_mitre_attack_*' \
|
502
|
+
--ai_settings_extractions openai:gpt-5 \
|
503
|
+
--ai_create_attack_flow \
|
504
|
+
--report_id ccc8c844-6a89-4762-b4e7-77c918fa4b8f
|
505
|
+
```
|
506
|
+
|
489
507
|
### attack navigator demo
|
490
508
|
|
491
509
|
```shell
|
@@ -8,6 +8,7 @@ from txt2stix.attack_flow import (
|
|
8
8
|
create_navigator_layer,
|
9
9
|
get_all_tactics,
|
10
10
|
get_techniques_from_extracted_objects,
|
11
|
+
parse_domain_flow,
|
11
12
|
parse_flow,
|
12
13
|
extract_attack_flow_and_navigator,
|
13
14
|
)
|
@@ -21,31 +22,30 @@ def test_parse_flow(dummy_report, dummy_objects, dummy_flow):
|
|
21
22
|
techniques = get_techniques_from_extracted_objects(dummy_objects, tactics)
|
22
23
|
flow = dummy_flow
|
23
24
|
report = dummy_report
|
24
|
-
expected_ids =
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
25
|
+
expected_ids = {
|
26
|
+
"attack-pattern--1b22b676-9347-4c55-9a35-ef0dc653db5b",
|
27
|
+
"x-mitre-tactic--298fe907-7931-4fd2-8131-2814dd493134",
|
28
|
+
"attack-action--1fd63972-ef98-5da5-81f5-4090c7dfa585",
|
29
|
+
"extension-definition--fb9c968a-745b-4ade-9b25-c324172197f4",
|
30
|
+
"attack-pattern--1a80d097-54df-41d8-9d33-34e755ec5e72",
|
31
|
+
"report--9c88fbcb-8c0d-4124-868b-3dcb1e9b696c",
|
32
|
+
"attack-flow--bb21585c-5f82-55cf-b73d-89b5217ef092",
|
33
|
+
"relationship--22e97298-819a-55ac-b57b-2185ffb72c62",
|
34
|
+
"x-mitre-tactic--2558fd61-8c75-4730-94c4-11926db2a263",
|
35
|
+
"attack-action--c7e06b10-252d-520d-82eb-e32314bbec34",
|
36
|
+
"x-mitre-tactic--696af733-728e-49d7-8261-75fdc590f453",
|
37
|
+
"x-mitre-tactic--5bc1d813-693e-4823-9961-abf9af4b0e92",
|
38
|
+
"attack-pattern--f9e9365a-9ca2-4d9c-8e7c-050d73d1101a",
|
39
|
+
"attack-action--51dc1572-cb10-581b-b9ef-9e589615ecaa",
|
40
|
+
"relationship--931f6b0d-5136-534a-93bc-8cce065e04dc",
|
41
|
+
"attack-pattern--0fe075d5-beac-4d02-b93e-0f874997db72",
|
42
|
+
"attack-flow--b48ec5d9-407c-5e4a-a6d0-fe851cd4ea0e",
|
43
|
+
"attack-action--e03c89ba-a476-5509-ac0a-049b61514be7",
|
44
|
+
}
|
44
45
|
|
45
46
|
flow_objects = parse_flow(report, flow, techniques, tactics)
|
46
47
|
assert {obj["id"] for obj in flow_objects} == expected_ids
|
47
48
|
|
48
|
-
|
49
49
|
def test_parse_flow__no_success(dummy_report):
|
50
50
|
flow_objects = parse_flow(
|
51
51
|
dummy_report,
|
@@ -61,6 +61,48 @@ def test_parse_flow__no_success(dummy_report):
|
|
61
61
|
assert len(flow_objects) == 0
|
62
62
|
|
63
63
|
|
64
|
+
@pytest.mark.parametrize(
|
65
|
+
["domain", "expected_ids"],
|
66
|
+
[
|
67
|
+
("mobile-attack", set()),
|
68
|
+
[
|
69
|
+
"ics-attack",
|
70
|
+
{
|
71
|
+
"x-mitre-tactic--298fe907-7931-4fd2-8131-2814dd493134",
|
72
|
+
"x-mitre-tactic--696af733-728e-49d7-8261-75fdc590f453",
|
73
|
+
"attack-pattern--1b22b676-9347-4c55-9a35-ef0dc653db5b",
|
74
|
+
"relationship--22e97298-819a-55ac-b57b-2185ffb72c62",
|
75
|
+
"attack-action--1fd63972-ef98-5da5-81f5-4090c7dfa585",
|
76
|
+
"attack-pattern--0fe075d5-beac-4d02-b93e-0f874997db72",
|
77
|
+
"attack-flow--bb21585c-5f82-55cf-b73d-89b5217ef092",
|
78
|
+
"attack-action--51dc1572-cb10-581b-b9ef-9e589615ecaa",
|
79
|
+
},
|
80
|
+
],
|
81
|
+
[
|
82
|
+
"enterprise-attack",
|
83
|
+
{
|
84
|
+
"attack-action--e03c89ba-a476-5509-ac0a-049b61514be7",
|
85
|
+
"relationship--931f6b0d-5136-534a-93bc-8cce065e04dc",
|
86
|
+
"attack-flow--b48ec5d9-407c-5e4a-a6d0-fe851cd4ea0e",
|
87
|
+
"attack-pattern--f9e9365a-9ca2-4d9c-8e7c-050d73d1101a",
|
88
|
+
"x-mitre-tactic--2558fd61-8c75-4730-94c4-11926db2a263",
|
89
|
+
"attack-pattern--1a80d097-54df-41d8-9d33-34e755ec5e72",
|
90
|
+
"x-mitre-tactic--5bc1d813-693e-4823-9961-abf9af4b0e92",
|
91
|
+
"attack-action--c7e06b10-252d-520d-82eb-e32314bbec34",
|
92
|
+
},
|
93
|
+
],
|
94
|
+
],
|
95
|
+
)
|
96
|
+
def test_parse_domain_flow(dummy_report, dummy_objects, dummy_flow, domain, expected_ids):
|
97
|
+
tactics = get_all_tactics()
|
98
|
+
techniques = get_techniques_from_extracted_objects(dummy_objects, tactics)
|
99
|
+
flow = dummy_flow
|
100
|
+
report = dummy_report
|
101
|
+
flow_objects = parse_domain_flow(report, flow, techniques, tactics, domain)
|
102
|
+
print([domain, {obj["id"] for obj in flow_objects}], ",")
|
103
|
+
assert {obj["id"] for obj in flow_objects} == expected_ids
|
104
|
+
|
105
|
+
|
64
106
|
def test_get_techniques_from_extracted_objects(dummy_objects):
|
65
107
|
tactics = get_all_tactics()
|
66
108
|
techniques = get_techniques_from_extracted_objects(dummy_objects, tactics)
|
@@ -142,7 +184,11 @@ def test_extract_attack_flow_and_navigator(dummy_objects, dummy_report):
|
|
142
184
|
mock_extract_flow.assert_called_once_with(text, techniques)
|
143
185
|
|
144
186
|
mock_create_navigator_layer.assert_called_once_with(
|
145
|
-
bundler.report,
|
187
|
+
bundler.report,
|
188
|
+
bundler.summary,
|
189
|
+
mock_extract_flow.return_value,
|
190
|
+
techniques,
|
191
|
+
tactics,
|
146
192
|
)
|
147
193
|
|
148
194
|
### reset mocks
|
@@ -181,7 +227,11 @@ def test_extract_attack_flow_and_navigator(dummy_objects, dummy_report):
|
|
181
227
|
mock_parse_flow.assert_not_called()
|
182
228
|
|
183
229
|
mock_create_navigator_layer.assert_called_once_with(
|
184
|
-
bundler.report,
|
230
|
+
bundler.report,
|
231
|
+
bundler.summary,
|
232
|
+
mock_extract_flow.return_value,
|
233
|
+
techniques,
|
234
|
+
tactics,
|
185
235
|
)
|
186
236
|
|
187
237
|
### reset mocks
|
@@ -281,7 +331,7 @@ def test_create_navigator_layer(dummy_report):
|
|
281
331
|
{
|
282
332
|
"versions": {
|
283
333
|
"layer": "4.5",
|
284
|
-
"attack":
|
334
|
+
"attack": "16.1",
|
285
335
|
"navigator": "5.1.0",
|
286
336
|
},
|
287
337
|
"name": "some markdown document",
|
@@ -311,7 +361,7 @@ def test_create_navigator_layer(dummy_report):
|
|
311
361
|
{
|
312
362
|
"versions": {
|
313
363
|
"layer": "4.5",
|
314
|
-
"attack":
|
364
|
+
"attack": "17.0",
|
315
365
|
"navigator": "5.1.0",
|
316
366
|
},
|
317
367
|
"name": "some markdown document",
|
@@ -341,7 +391,7 @@ def test_create_navigator_layer(dummy_report):
|
|
341
391
|
{
|
342
392
|
"versions": {
|
343
393
|
"layer": "4.5",
|
344
|
-
"attack":
|
394
|
+
"attack": "13.1",
|
345
395
|
"navigator": "5.1.0",
|
346
396
|
},
|
347
397
|
"name": "some markdown document",
|
@@ -1,4 +1,5 @@
|
|
1
1
|
|
2
|
+
import logging
|
2
3
|
import os
|
3
4
|
from txt2stix.ai_extractor.base import BaseAIExtractor
|
4
5
|
from llama_index.llms.openai import OpenAI
|
@@ -11,5 +12,9 @@ class OpenAIExtractor(BaseAIExtractor, provider="openai"):
|
|
11
12
|
super().__init__()
|
12
13
|
|
13
14
|
def count_tokens(self, text):
|
14
|
-
|
15
|
+
try:
|
16
|
+
return len(self.llm._tokenizer.encode(text))
|
17
|
+
except Exception as e:
|
18
|
+
logging.warning(e)
|
19
|
+
return super().count_tokens(text)
|
15
20
|
|
@@ -16,15 +16,26 @@ def parse_flow(report, flow: AttackFlowList, techniques, tactics):
|
|
16
16
|
logging.info(f"flow.success = {flow.success}")
|
17
17
|
if not flow.success:
|
18
18
|
return []
|
19
|
-
|
19
|
+
objects = [report, attack_flow_ExtensionDefinitionSMO]
|
20
|
+
for domain in ["enterprise-attack", "mobile-attack", "ics-attack"]:
|
21
|
+
flow_objects = parse_domain_flow(report, flow, techniques, tactics, domain)
|
22
|
+
objects.extend(flow_objects)
|
23
|
+
return objects
|
24
|
+
|
25
|
+
def parse_domain_flow(report, flow: AttackFlowList, techniques, tactics, domain):
|
26
|
+
flow_objects = []
|
27
|
+
flow_obj = None
|
20
28
|
last_action = None
|
21
29
|
for i, item in enumerate(flow.items):
|
22
30
|
try:
|
23
31
|
technique = techniques[item.attack_technique_id]
|
32
|
+
if technique["domain"] != domain:
|
33
|
+
continue
|
24
34
|
tactic_id = technique["possible_tactics"][
|
25
35
|
flow.tactic_mapping[item.attack_technique_id]
|
26
36
|
]
|
27
37
|
technique_obj = technique["stix_obj"]
|
38
|
+
|
28
39
|
tactic_obj = tactics[technique["domain"]][tactic_id]
|
29
40
|
action_obj = AttackAction(
|
30
41
|
**{
|
@@ -40,16 +51,16 @@ def parse_flow(report, flow: AttackFlowList, techniques, tactics):
|
|
40
51
|
allow_custom=True,
|
41
52
|
)
|
42
53
|
action_obj.effect_refs.clear()
|
43
|
-
if
|
54
|
+
if not flow_obj:
|
44
55
|
flow_obj = {
|
45
56
|
"type": "attack-flow",
|
46
|
-
"id":
|
57
|
+
"id": "attack-flow--"+str(uuid.uuid5(UUID_NAMESPACE, f"attack-flow+{domain}+{report.id}")),
|
47
58
|
"spec_version": "2.1",
|
48
59
|
"created": report.created,
|
49
60
|
"modified": report.modified,
|
50
61
|
"created_by_ref": report.created_by_ref,
|
51
62
|
"start_refs": [action_obj["id"]],
|
52
|
-
"name": report.name,
|
63
|
+
"name": f"[{domain.split('-')[0].upper()}] {report.name}",
|
53
64
|
"description": report.description,
|
54
65
|
"scope": "malware",
|
55
66
|
"external_references": report.external_references,
|
@@ -61,7 +72,7 @@ def parse_flow(report, flow: AttackFlowList, techniques, tactics):
|
|
61
72
|
type="relationship",
|
62
73
|
spec_version="2.1",
|
63
74
|
id="relationship--"
|
64
|
-
+ str(uuid.uuid5(UUID_NAMESPACE, f"attack-flow+{report.id}")),
|
75
|
+
+ str(uuid.uuid5(UUID_NAMESPACE, f"attack-flow+{report.id}+{flow_obj['id']}")),
|
65
76
|
created_by_ref=report.created_by_ref,
|
66
77
|
created=report.created,
|
67
78
|
modified=report.modified,
|