├── .DS_Store ├── .gitmodules ├── .gitignore ├── .github └── workflows │ └── cicd.yml ├── json ├── EVENT_RECORD_CASE_1.0.0.json ├── FILE_CASE_1.0.0.json ├── DEVICE_CASE_1.0.0.json ├── URL_HISTORY_CASE_1.0.0.json ├── CELL_SITE_CASE_1.0.0.json ├── Call_CASE_1.0.0.json ├── WIRELESS_NETWORK_CASE_1.0.0.json ├── EMAIL_MESSAGE_CASE_1.0.0.json ├── URL_HISTORY_MULTI_ITEMS_CASE_1.0.0.json ├── Message_CASE_1.0.0.json └── ACTION_CASE_1.0.0.json ├── drafting.ttl ├── README.md ├── parserDebug.py ├── UFEDdebug.py ├── LICENSE └── UFED_case_generator.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/casework/CASE-Implementation-UFED-XML/HEAD/.DS_Store -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "dependencies"] 2 | path = dependencies 3 | url = https://github.com/casework/CASE-Mapping-Python 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/* 2 | _* 3 | *zip 4 | *err 5 | *wp? 6 | .DS_Stor* 7 | venv/* 8 | .github/workflows/* 9 | Makefile 10 | -------------------------------------------------------------------------------- /.github/workflows/cicd.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - develop 8 | pull_request: 9 | branches: 10 | - main 11 | - develop 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | # Checkout the repository for processing 19 | - name: Checkout Repository 20 | uses: actions/checkout@v3 21 | 22 | # Test the output files to confirm they're both conformant to the CASE Ontology 23 | - name: CASE Validation 24 | uses: kchason/case-validation-action@v2.9.0 25 | with: 26 | case-path: ./json/ 27 | case-version: "case-1.3.0" 28 | -------------------------------------------------------------------------------- /json/EVENT_RECORD_CASE_1.0.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "kb": "http://example.org/kb/", 4 | "drafting": "http://example.org/ontology/drafting/", 5 | "co": "http://purl.org/co/", 6 | "rdfs": "http://www.w3.org/2000/01/rdf-schema#", 7 | "uco-core": "https://ontology.unifiedcyberontology.org/uco/core/", 8 | "uco-identity": "https://ontology.unifiedcyberontology.org/uco/identity/", 9 | "uco-location": "https://ontology.unifiedcyberontology.org/uco/location/", 10 | "uco-role": "https://ontology.unifiedcyberontology.org/uco/role/", 11 | "uco-action": "https://ontology.unifiedcyberontology.org/uco/action/", 12 | "uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/", 13 | "uco-types": "https://ontology.unifiedcyberontology.org/uco/types/", 14 | "uco-tool": "https://ontology.unifiedcyberontology.org/uco/tool/", 15 | "case-investigation": "https://ontology.caseontology.org/case/investigation/", 16 | "xsd": "http://www.w3.org/2001/XMLSchema#" 17 | }, 18 | "uco-core:object": [ 19 | { 20 | "@id": "kb:fe688202-4b21-48d2-b07d-170e14971935", 21 | "@type": "uco-observable:ObservableObject", 22 | "uco-core:hasFacet": [ 23 | { 24 | "@id": "kb:a45c81a7-9afc-482d-9d37-a2b55ddb570d", 25 | "@type": "uco-observable:EventRecordFacet", 26 | "uco-observable:eventType": "PowerEvent", 27 | "uco-observable:eventRecordText": "Power on", 28 | "uco-observable:observableCreatedTime": { 29 | "@type": "xsd:dateTime", 30 | "@value": "2021-05-18T11:31:46+00:00" 31 | } 32 | } 33 | ] 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /drafting.ttl: -------------------------------------------------------------------------------- 1 | # imports: https://ontology.unifiedcyberontology.org/uco/action/1.0.0 2 | # imports: https://ontology.unifiedcyberontology.org/uco/configuration/1.0.0 3 | # imports: https://ontology.unifiedcyberontology.org/uco/core/1.0.0 4 | # imports: https://ontology.unifiedcyberontology.org/uco/identity/1.0.0 5 | # imports: https://ontology.unifiedcyberontology.org/uco/location/1.0.0 6 | # imports: https://ontology.unifiedcyberontology.org/uco/types/1.0.0 7 | # imports: https://ontology.unifiedcyberontology.org/uco/vocabulary/1.0.0 8 | 9 | @prefix action: . 10 | @prefix co: . 11 | @prefix configuration: . 12 | @prefix core: . 13 | @prefix identity: . 14 | @prefix location: . 15 | @prefix observable: . 16 | @prefix drafting: . 17 | @prefix owl: . 18 | @prefix rdf: . 19 | @prefix rdfs: . 20 | @prefix sh: . 21 | @prefix types: . 22 | @prefix vocabulary: . 23 | @prefix xsd: . 24 | 25 | 26 | a owl:Ontology ; 27 | rdfs:label "drafting"@en ; 28 | owl:imports 29 | action:1.0.0 , 30 | configuration:1.0.0 , 31 | core:1.0.0 , 32 | identity:1.0.0 , 33 | location:1.0.0 , 34 | types:1.0.0 , 35 | vocabulary:1.0.0 36 | ; 37 | owl:ontologyIRI ; 38 | owl:versionIRI drafting:1.0.0 ; 39 | . 40 | 41 | drafting:SearchedItemFacet 42 | a 43 | owl:Class , 44 | sh:NodeShape 45 | ; 46 | rdfs:subClassOf core:Facet ; 47 | rdfs:label "SearchedItemFacet"@en ; 48 | rdfs:comment "A searched item facet is a grouping of characteristics unique to the strings searched by using a web browse."@en ; 49 | sh:property 50 | [ 51 | sh:datatype xsd:string ; 52 | sh:maxCount "1"^^xsd:integer ; 53 | sh:nodeKind sh:Literal ; 54 | sh:path observable:searchValue ; 55 | ] , 56 | [ 57 | sh:datatype xsd:string ; 58 | sh:maxCount "1"^^xsd:integer ; 59 | sh:nodeKind sh:Literal ; 60 | sh:path observable:searchResult ; 61 | ] , 62 | [ 63 | sh:datatype xsd:dateTime ; 64 | sh:maxCount "1"^^xsd:integer ; 65 | sh:nodeKind sh:Literal ; 66 | sh:path observable:searchLaunchedTime ; 67 | ] 68 | ; 69 | sh:targetClass drafting:SearchedItemFacet ; 70 | . 71 | -------------------------------------------------------------------------------- /json/FILE_CASE_1.0.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "kb": "http://example.org/kb/", 4 | "acme": "http://custompb.acme.org/core#", 5 | "drafting": "http://example.org/ontology/drafting/", 6 | "rdfs": "http://www.w3.org/2000/01/rdf-schema#", 7 | "uco-core": "https://ontology.unifiedcyberontology.org/uco/core/", 8 | "uco-identity": "https://ontology.unifiedcyberontology.org/uco/identity/", 9 | "uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/", 10 | "uco-types": "https://ontology.unifiedcyberontology.org/uco/types/", 11 | "uco-vocabulary": "https://ontology.unifiedcyberontology.org/uco/vocabulary/", 12 | "xsd": "http://www.w3.org/2001/XMLSchema#" 13 | }, 14 | "uco-core:object": [ 15 | { 16 | "@id": "kb:5e350cd9-3e48-4f8a-82f1-26e394e0780f", 17 | "@type": "uco-observable:ObservableObject", 18 | "uco-core:tag": "Uncategorized", 19 | "uco-core:hasFacet": [ 20 | { 21 | "@id": "kb:0be208ff-034c-4529-b004-39b8426393b4", 22 | "@type": "uco-observable:FileFacet", 23 | "uco-observable:fileName": "Apple_iPhone X (A1901).zip", 24 | "uco-observable:filePath": "Apple_iPhone X (A1901).zip", 25 | "drafting:fileLocalPath": "files/Ucategorized/Apple_iPhone X (A1901).zip", 26 | "uco-observable:extension": ".zip", 27 | "uco-observable:accessedTime": { 28 | "@type": "xsd:dateTime", 29 | "@value": "1900-01-01T08:00:00+00:00" 30 | }, 31 | "uco-observable:observableCreatedTime": { 32 | "@type": "xsd:dateTime", 33 | "@value": "1900-01-01T08:00:00+00:00" 34 | }, 35 | "uco-observable:modifiedTime": { 36 | "@type": "xsd:dateTime", 37 | "@value": "1900-01-01T08:00:00+00:00" 38 | }, 39 | "uco-observable:sizeInBytes": { 40 | "@type": "xsd:integer", 41 | "@value": 16965760332 42 | } 43 | }, 44 | { 45 | "@id": "kb:097bc2b2-45e4-453a-a208-aeab7e77da99", 46 | "@type": "uco-observable:ContentDataFacet", 47 | "uco-observable:hash": [ 48 | { 49 | "@id":"f1bfa603-2214-4d52-87b2-0afe244851de", 50 | "@type": "uco-types:Hash", 51 | "uco-types:hashMethod": { 52 | "@type": "uco-vocabulary:HashNameVocab", 53 | "@value": "SHA256" 54 | }, 55 | "uco-types:hashValue": { 56 | "@type": "xsd:hexBinary", 57 | "@value": "4758982E5B94DF45F4400558608928F1A866104CB20A17BCB513D9B682644E484758982E5B94DF45F4400558608928F1A866104CB20A17BCB513D9B682644E48" 58 | } 59 | } 60 | ] 61 | } 62 | ] 63 | } 64 | 65 | ] 66 | } -------------------------------------------------------------------------------- /json/DEVICE_CASE_1.0.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "kb": "http://example.org/kb/", 4 | "drafting": "http://example.org/ontology/drafting/", 5 | "co": "http://purl.org/co/", 6 | "rdfs": "http://www.w3.org/2000/01/rdf-schema#", 7 | "uco-core": "https://ontology.unifiedcyberontology.org/uco/core/", 8 | "uco-identity": "https://ontology.unifiedcyberontology.org/uco/identity/", 9 | "uco-location": "https://ontology.unifiedcyberontology.org/uco/location/", 10 | "uco-role": "https://ontology.unifiedcyberontology.org/uco/role/", 11 | "uco-action": "https://ontology.unifiedcyberontology.org/uco/action/", 12 | "uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/", 13 | "uco-types": "https://ontology.unifiedcyberontology.org/uco/types/", 14 | "uco-tool": "https://ontology.unifiedcyberontology.org/uco/tool/", 15 | "case-investigation": "https://ontology.caseontology.org/case/investigation/", 16 | "xsd": "http://www.w3.org/2001/XMLSchema#" 17 | }, 18 | "uco-core:object": [ 19 | { 20 | "@id": "kb:cbd39ad4-ab25-452d-b03e-10364c7fd40e", 21 | "@type": "uco-observable:ObservableObject", 22 | "rdfs:comment": "version: CASE 1.0.0", 23 | "rdfs:comment": "description: Device example complied with UCO/CASE 1.0.0" 24 | }, 25 | { 26 | "@id": "kb:e4912cd1-abc3-4ad4-9d73-f54379752e02", 27 | "@type": "uco-observable:ObservableObject", 28 | "uco-core:hasFacet": [ 29 | { 30 | "@id": "kb:22f9f968-e829-4a22-89fc-751feff9d0b0", 31 | "@type": "uco-observable:DeviceFacet", 32 | "uco-observable:deviceType": "Mobile phone", 33 | "uco-observable:model": "iPhone X", 34 | "uco-observable:serialNumber": "HW095687Y2022" 35 | }, 36 | { 37 | "@id": "kb:1d4e9269-ad19-4fe4-8055-377301bdefde", 38 | "@type": "uco-observable:MobileDeviceFacet", 39 | "uco-observable:IMSI": "310260249043715", 40 | "uco-observable:ICCID": "8901260243790437158", 41 | "uco-observable:IMEI": "359405082912450", 42 | "uco-observable:MSISDN": "3383725981" 43 | }, 44 | { 45 | "@id": "kb:6bd89154-b501-4fd8-a750-58d39e4a51e7", 46 | "@type": "uco-observable:OperatingSystemFacet", 47 | "uco-observable:displayName": "iOS", 48 | "uco-observable:manufacturer": 49 | { 50 | "@id": "kb:73952c43-8df5-4fa3-888c-f0f00d2eab8f" 51 | }, 52 | "uco-observable:version": "14.6" 53 | }, 54 | { 55 | "@id": "kb:75be1e84-348e-4d19-85d3-a1e23eed77cc", 56 | "@type": "uco-observable:BluetoothAddressFacet", 57 | "uco-observable:displayName": "Good hook", 58 | "uco-observable:addressValue": "D4:A3:3D:B5:F4:6C" 59 | }, 60 | { 61 | "@id": "kb:a265c5ed-95c2-46e9-af91-4b73023f918b", 62 | "@type": "uco-observable:WifiAddressFacet", 63 | "uco-observable:addressValue": "D4:A3:3D:B5:F4:48" 64 | } 65 | ] 66 | }, 67 | { 68 | "@id": "kb:73952c43-8df5-4fa3-888c-f0f00d2eab8f", 69 | "@type": "uco-identity:Identity", 70 | "uco-core:description": "Huawei UK" 71 | } 72 | ] 73 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## XML SAX parser for UFED/Cellebrite. 2 | 3 | [![Continuous Integration](https://github.com/casework/CASE-Implementation-UFED-XML/actions/workflows/cicd.yml/badge.svg)](https://github.com/casework/CASE-Implementation-UFED-XML/actions/workflows/cicd.yml) 4 | ![CASE Version](https://img.shields.io/badge/CASE%20Version-1.3.0-green) 5 | 6 | The parser extracts some digital traces (Cyber items) from XML reports generated by UFED Physical Analyser (version 7.x) and convert them into UCO/CASE as JSON-LD files. 7 | ======= 8 | The parser extracts the most relevat digital traces (cyber items) from XML reports generated by UFED Physical Analyser (version 7.x) and convert them into UCO/CASE as JSON-LD files. 9 | 10 | The UFED parser is able to process any report, regardless their size, it has been developed using **Python, version 3.x** and based on **SAX** (Simple API for XML). 11 | 12 | The UFED parser is composed of two different modules: 13 | 14 | * parser_UFEDtoCASE (XML parser program) 15 | * UFEDtoJSON.py (data converter into CASE-JSON-LD files) 16 | 17 | and it uses the **Case-Mapping-Python** (github.com/casework/CASE-Mapping-Python) repository as submodule, located in the folder 18 | 19 | * dependencies/CASE_Mapping_Python 20 | 21 | The CASE-Mapping-Python library is also part of the PyPI and can be used as a package. 22 | 23 | 24 | ## Requirements 25 | The tool has been developed in Python version 3.x and here are some required modules: 26 | 27 | * xml.sax (SAX classes) 28 | * argparse (args input management) 29 | * os (operating system utilities) 30 | * codecs (UTF-8 and other codec management) 31 | * re (regular expressions management) 32 | * uuid (global unique identifier management) 33 | * datetime 34 | * timeit 35 | * time 36 | * json 37 | 38 | ## Usage 39 | 40 | ```js 41 | > *parser_UFEDtoCASE.py [-h]* 42 | > *-r INFILEXML* 43 | > *-o OUTPUT_CASE_JSON* 44 | ``` 45 | where: 46 | 47 | ```js 48 | * -h, --help (show the help message and exit) 49 | * -r | --report INFILEXML (the UFED XML report to be converted into CASE, compulsary) 50 | * -o | --output OUTPUT_CASE_JSON (CASE-JSON-LD file to be generated, compulsory) 51 | ``` 52 | 53 | ## Mobile Forensic Data set 54 | The UFED parser has been developed and tested relying on a huge collection of mobile forensic dataset. This is composed of images made available on the Computer Forensic Reference Data Sets (CFReDS) Project and also on those provided by Cellebrite within he Catch The Flag annual competition. 55 | 56 | ## CASE representation: JSON-LD files 57 | All the XML reports have been processed to generate the corresponding CASE representation of the following Cyber items: 58 | 59 | * Calendar 60 | * Call 61 | * Cell Site 62 | * Chat (Whatsapp, Skype, etc.) 63 | * Contact 64 | * Cookie 65 | * Device Connectivity (Bluetooth connections) 66 | * Device Event 67 | * Email 68 | * File 69 | * Installed Application 70 | * Instant Message 71 | * Location (related to the Device) 72 | * Social Media Activity (drafting namespace) 73 | * SMS 74 | * URL History 75 | * Web Bookmarks 76 | * Wifi Connection 77 | * Chain of Evidence (represented as a relationship between the Artifact and the File/Db from which it was extracted) 78 | * Context 79 | * Device info 80 | * Tool 81 | * Performer 82 | * Provenance Record 83 | * Investigative Acquisition 84 | * Investigative Extraction 85 | 86 | ## XML reports 87 | 88 | The repo also includes the XMLreports folder containing examples of reports from Cellebrite UFED PA. 89 | 90 | ## Drafting TTL 91 | 92 | The drafting.ttl file describing the additional ontology classes based on the drafting namespace 93 | 94 | ## Development status 95 | 96 | This repository follows [CASE community guidance on describing development status](https://caseontology.org/resources/github_policies.html#development-statuses), by adherence to noted support requirements. 97 | 98 | The status of this repository is: 99 | 100 | 4 - Beta 101 | -------------------------------------------------------------------------------- /json/URL_HISTORY_CASE_1.0.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "kb": "http://example.org/kb/", 4 | "drafting": "http://example.org/ontology/drafting/", 5 | "co": "http://purl.org/co/", 6 | "rdfs": "http://www.w3.org/2000/01/rdf-schema#", 7 | "uco-core": "https://ontology.unifiedcyberontology.org/uco/core/", 8 | "uco-identity": "https://ontology.unifiedcyberontology.org/uco/identity/", 9 | "uco-location": "https://ontology.unifiedcyberontology.org/uco/location/", 10 | "uco-role": "https://ontology.unifiedcyberontology.org/uco/role/", 11 | "uco-action": "https://ontology.unifiedcyberontology.org/uco/action/", 12 | "uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/", 13 | "uco-types": "https://ontology.unifiedcyberontology.org/uco/types/", 14 | "uco-tool": "https://ontology.unifiedcyberontology.org/uco/tool/", 15 | "case-investigation": "https://ontology.caseontology.org/case/investigation/", 16 | "xsd": "http://www.w3.org/2001/XMLSchema#" 17 | }, 18 | "uco-core:object": [ 19 | { 20 | "@id": "kb:5d96df90-d9e1-423c-b8db-c2327812ab38", 21 | "@type": "uco-observable:ObservableObject", 22 | "uco-core:hasFacet": [ 23 | { 24 | "@id": "kb:1723ed9c-2d8e-415c-8cf6-31599c49df79", 25 | "@type": "uco-observable:ApplicationFacet", 26 | "uco-observable:applicationIdentifier": "Safari Apple", 27 | "uco-observable:version": "15.23.45" 28 | } 29 | ] 30 | }, 31 | { 32 | "@id": "kb:39ff4987-8ae5-47e3-8369-dbd0d5f79398", 33 | "@type": "uco-observable:ObservableObject", 34 | "rdfs:comment": "@type=uco-observable:URLHistory", 35 | "uco-core:hasFacet": [ 36 | { 37 | "@id": "kb:a455b867-957e-4fce-a0ad-1af9c6fa4edb", 38 | "@type": "uco-observable:URLHistoryFacet", 39 | "uco-observable:browserInformation": { 40 | "@id": "kb:5d96df90-d9e1-423c-b8db-c2327812ab38" 41 | }, 42 | "uco-observable:urlHistoryEntry": [ 43 | { 44 | "@id": "kb:193a7fc6-5f15-4b3c-8763-f1dc3c9bfd14", 45 | "@type": "uco-observable:URLHistoryEntry", 46 | "uco-observable:firstVisit": { 47 | "@type": "xsd:dateTime", 48 | "@value": "2017-01-25T02:20:22.00Z" 49 | }, 50 | "uco-observable:lastVisit": { 51 | "@type": "xsd:dateTime", 52 | "@value": "2017-01-25T02:20:22.00Z" 53 | }, 54 | "uco-observable:expirationTime": null, 55 | "rdfs:comment": "TODO: Was uco-observable:browserUserProfile meant to be an object property?", 56 | "drafting:browserUserProfileAccount": { 57 | "@id": "kb:profile-account-857c7f17-2f6b-4618-aeca-50d79fa69b97" 58 | }, 59 | "uco-observable:url": { 60 | "@id": "kb:b7906534-0483-4cf4-979c-5351916602ed" 61 | }, 62 | "uco-observable:referrerUrl": null, 63 | "uco-observable:pageTitle": "Where can you find baby owls for sale? Are owls legal to keep as pets? - Quora", 64 | "uco-observable:visitCount": 2, 65 | "uco-observable:manuallyEnteredCount": { 66 | "@type": "xsd:nonNegativeInteger", 67 | "@value": 0 68 | }, 69 | "uco-observable:keywordSearchTerm": "Baby owl shops" 70 | } 71 | ] 72 | } 73 | ] 74 | }, 75 | { 76 | "@id": "kb:b7906534-0483-4cf4-979c-5351916602ed", 77 | "@type": "uco-observable:URL", 78 | "uco-core:hasFacet": [ 79 | { 80 | "@id": "kb:f2618636-aec3-459e-bda7-eeedfbeac3c0", 81 | "@type": "uco-observable:URLFacet", 82 | "uco-observable:fullValue": "https://www.quora.com/Where-can-you-find-baby-owls-for-sale-Are-owls-legal-to-keep-as-pets" 83 | } 84 | ] 85 | } 86 | ] 87 | } 88 | -------------------------------------------------------------------------------- /json/CELL_SITE_CASE_1.0.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "kb": "http://example.org/kb/", 4 | "acme": "http://custompb.acme.org/core#", 5 | "drafting": "http://example.org/ontology/drafting/", 6 | "rdfs": "http://www.w3.org/2000/01/rdf-schema#", 7 | "uco-core": "https://ontology.unifiedcyberontology.org/uco/core/", 8 | "uco-identity": "https://ontology.unifiedcyberontology.org/uco/identity/", 9 | "uco-location": "https://ontology.unifiedcyberontology.org/uco/location/", 10 | "uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/", 11 | "uco-types": "https://ontology.unifiedcyberontology.org/uco/types/", 12 | "uco-vocabulary": "https://ontology.unifiedcyberontology.org/uco/vocabulary/", 13 | "xsd": "http://www.w3.org/2001/XMLSchema#" 14 | }, 15 | "uco-core:object": [ 16 | { 17 | "@id": "kb:dc9b8413-f681-4bc6-a66e-b70a7ecde4d4", 18 | "@type": "uco-observable:ObservableObject", 19 | "rdfs:comment": "@type=uco-observable:CellSite", 20 | "uco-core:hasFacet": [ 21 | { 22 | "@id": "kb:fcfa96c3-3824-4132-a156-8ac857800c05", 23 | "@type": "uco-observable:CellSiteFacet", 24 | "uco-observable:cellSiteType": "GSM", 25 | "uco-observable:cellSiteCountryCode": "228", 26 | "uco-observable:cellSiteNetworkCode": "2", 27 | "uco-observable:cellSiteLocationAreaCode": "22100", 28 | "uco-observable:cellSiteIdentifier": "29220952" 29 | }, 30 | { 31 | "@id": "kb:749dc5c5-f3f2-4e9b-b53c-89bfaf177d76", 32 | "@type": "uco-observable:AntennaFacet", 33 | "uco-observable:azimuth": { 34 | "@type": "xsd:decimal", 35 | "@value": "45" 36 | }, 37 | "uco-observable:elevation": { 38 | "@type": "xsd:decimal", 39 | "@value": "5" 40 | }, 41 | "uco-observable:skew": { 42 | "@type": "xsd:decimal", 43 | "@value": "10" 44 | }, 45 | "uco-observable:horizontalBeamWidth": { 46 | "@type": "xsd:decimal", 47 | "@value": "110" 48 | }, 49 | "uco-observable:signalStrength": { 50 | "@type": "xsd:decimal", 51 | "@value": "20" 52 | }, 53 | "uco-observable:antennaHeight": { 54 | "@type": "xsd:decimal", 55 | "@value": "25" 56 | } 57 | } 58 | ] 59 | }, 60 | { 61 | "@id": "kb:f2e90997-16c9-4822-be30-fa4f36553768", 62 | "@type": "uco-observable:ObservableObject", 63 | "uco-core:hasFacet": [ 64 | { 65 | "@id": "kb:e7540964-bca0-4dbe-a886-fdd2115d6aed", 66 | "@type": "uco-location:LatLongCoordinatesFacet", 67 | "uco-location:latitude": { 68 | "@type": "xsd:decimal", 69 | "@value": "40.05659866" 70 | }, 71 | "uco-location:longitude": { 72 | "@type": "xsd:decimal", 73 | "@value": "-75.67047119" 74 | } 75 | } 76 | ] 77 | }, 78 | 79 | { 80 | "@id": "kb:cdf48c35-c65d-41e4-843b-720f1ad24ab3", 81 | "@type": "uco-observable:ObservableRelationship", 82 | "uco-observable:startTime": { 83 | "@type": "xsd:dateTime", 84 | "@value": "2018-06-12T09:10:11Z" 85 | }, 86 | "uco-observable:endTime": { 87 | "@type": "xsd:dateTime", 88 | "@value": "2018-06-12T15:36:39Z" 89 | }, 90 | "uco-core:source": { 91 | "@id": "kb:dc9b8413-f681-4bc6-a66e-b70a7ecde4d4" 92 | }, 93 | "uco-core:target": { 94 | "@id": "kb:f2e90997-16c9-4822-be30-fa4f36553768" 95 | }, 96 | "uco-core:kindOfRelationship": "Located_At", 97 | "uco-core:isDirectional": { 98 | "@type": "xsd:boolean", 99 | "@value": true 100 | } 101 | } 102 | 103 | ] 104 | } 105 | -------------------------------------------------------------------------------- /json/Call_CASE_1.0.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "kb": "http://example.org/kb/", 4 | "drafting": "http://example.org/ontology/drafting/", 5 | "co": "http://purl.org/co/", 6 | "rdfs": "http://www.w3.org/2000/01/rdf-schema#", 7 | "uco-core": "https://ontology.unifiedcyberontology.org/uco/core/", 8 | "uco-identity": "https://ontology.unifiedcyberontology.org/uco/identity/", 9 | "uco-location": "https://ontology.unifiedcyberontology.org/uco/location/", 10 | "uco-role": "https://ontology.unifiedcyberontology.org/uco/role/", 11 | "uco-action": "https://ontology.unifiedcyberontology.org/uco/action/", 12 | "uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/", 13 | "uco-types": "https://ontology.unifiedcyberontology.org/uco/types/", 14 | "uco-tool": "https://ontology.unifiedcyberontology.org/uco/tool/", 15 | "case-investigation": "https://ontology.caseontology.org/case/investigation/", 16 | "xsd": "http://www.w3.org/2001/XMLSchema#" 17 | }, 18 | "uco-core:object": [ 19 | { 20 | "@id": "kb:0d191a90-7f5f-4df7-9cc3-3b5024e66983", 21 | "@type": "uco-observable:ObservableObject", 22 | "uco-core:name": "Native application", 23 | "uco-core:hasFacet": [ 24 | { 25 | "@id": "kb:f35ce51a-cb45-49ca-83d1-546cedd73b21", 26 | "@type": "uco-observable:ApplicationFacet", 27 | "uco-observable:applicationIdentifier": "Native" 28 | } 29 | ] 30 | }, 31 | { 32 | "@id": "kb:d4d81ef9-9598-4e29-aaf6-297c47315269", 33 | "@type": "uco-observable:ObservableObject", 34 | "uco-core:hasFacet": [ 35 | { 36 | "@id": "4cb32da0-4d54-49c6-9de7-961135c86578", 37 | "@type": "uco-observable:AccountFacet", 38 | "uco-observable:accountIdentifier": "Rose Noomur", 39 | "uco-observable:isActive": { 40 | "@type": "xsd:boolean", 41 | "@value": true 42 | } 43 | }, 44 | { 45 | "@id": "d25ecc35-74ea-4c82-b7e3-4e082a7c6e54", 46 | "@type": "uco-observable:PhoneAccountFacet", 47 | "uco-observable:phoneNumber": "+19734468551" 48 | } 49 | ] 50 | }, 51 | { 52 | "@id": "kb:e91445f8-406b-4ade-bd12-ec9ecdce5810", 53 | "@type": "uco-observable:ObservableObject", 54 | "uco-core:hasFacet": [ 55 | { 56 | "@id": "fdf3e4cf-8d9b-4959-97f1-3506e5132ac9", 57 | "@type": "uco-observable:AccountFacet", 58 | "uco-observable:accountIdentifier": "Jane Malone", 59 | "uco-observable:isActive": { 60 | "@type": "xsd:boolean", 61 | "@value": true 62 | } 63 | }, 64 | { 65 | "@id": "b9f40fda-b69f-48c6-9efd-d1c3858bbb26", 66 | "@type": "uco-observable:PhoneAccountFacet", 67 | "uco-observable:phoneNumber": "+19732941683/19732941683", 68 | "uco-observable:displayName": "Jane M." 69 | } 70 | ] 71 | }, 72 | { 73 | "@id": "kb:238070ba-b740-4aa9-89af-4f52d0efc1a0", 74 | "@type": "uco-observable:ObservableObject", 75 | "uco-core:hasFacet": [ 76 | { 77 | "@id": "kb:a8bdd70b-3d5d-4196-8f27-45ff429fbc6f", 78 | "@type": "uco-observable:CallFacet", 79 | "uco-observable:callType": "incoming", 80 | "uco-observable:allocationStatus": "Intact", 81 | "uco-observable:duration": { 82 | "@type": "xsd:integer", 83 | "@value": "0" 84 | }, 85 | "uco-observable:startTime": { 86 | "@type": "xsd:dateTime", 87 | "@value": "2022-01-19T21:38:19.023000+00:00" 88 | }, 89 | "uco-observable:application": { 90 | "@id": "kb:0d191a90-7f5f-4df7-9cc3-3b5024e66983" 91 | }, 92 | "uco-observable:from": { 93 | "@id": "kb:d4d81ef9-9598-4e29-aaf6-297c47315269" 94 | }, 95 | "uco-observable:to": { 96 | "@id": "kb:e91445f8-406b-4ade-bd12-ec9ecdce5810" 97 | } 98 | } 99 | ] 100 | } 101 | ] 102 | } -------------------------------------------------------------------------------- /json/WIRELESS_NETWORK_CASE_1.0.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "kb": "http://example.org/kb/", 4 | "drafting": "http://example.org/ontology/drafting/", 5 | "co": "http://purl.org/co/", 6 | "rdfs": "http://www.w3.org/2000/01/rdf-schema#", 7 | "uco-core": "https://ontology.unifiedcyberontology.org/uco/core/", 8 | "uco-identity": "https://ontology.unifiedcyberontology.org/uco/identity/", 9 | "uco-location": "https://ontology.unifiedcyberontology.org/uco/location/", 10 | "uco-role": "https://ontology.unifiedcyberontology.org/uco/role/", 11 | "uco-action": "https://ontology.unifiedcyberontology.org/uco/action/", 12 | "uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/", 13 | "uco-types": "https://ontology.unifiedcyberontology.org/uco/types/", 14 | "uco-tool": "https://ontology.unifiedcyberontology.org/uco/tool/", 15 | "case-investigation": "https://ontology.caseontology.org/case/investigation/", 16 | "xsd": "http://www.w3.org/2001/XMLSchema#" 17 | }, 18 | "uco-core:object": [ 19 | { 20 | "@id": "kb:e4912cd1-abc3-4ad4-9d73-f54379752e02", 21 | "@type": "uco-observable:ObservableObject", 22 | "uco-core:hasFacet": [ 23 | { 24 | "@id": "kb:22f9f968-e829-4a22-89fc-751feff9d0b0", 25 | "@type": "uco-observable:DeviceFacet", 26 | "uco-observable:deviceType": "Mobile phone", 27 | "uco-observable:model": "iPhone X", 28 | "uco-observable:serialNumber": "HW095687Y2022" 29 | }, 30 | { 31 | "@id": "kb:1d4e9269-ad19-4fe4-8055-377301bdefde", 32 | "@type": "uco-observable:MobileDeviceFacet", 33 | "uco-observable:IMSI": "310260249043715", 34 | "uco-observable:ICCID": "8901260243790437158", 35 | "uco-observable:IMEI": "359405082912450", 36 | "uco-observable:MSISDN": "3383725981" 37 | } 38 | ] 39 | }, 40 | { 41 | "@id": "kb:37445ac8-7fd9-4ab4-ba82-231eba274480", 42 | "@type": "uco-observable:ObservableObject", 43 | "uco-core:hasFacet": [ 44 | { 45 | "@id": "kb:b4cfbacd-050c-4b01-8a12-284aae1a6ccb", 46 | "@type": "uco-location:LatLongCoordinatesFacet", 47 | "uco-location:latitude": { 48 | "@type": "xsd:decimal", 49 | "@value": "40.05659866" 50 | }, 51 | "uco-location:longitude": { 52 | "@type": "xsd:decimal", 53 | "@value": "-75.67047119" 54 | }, 55 | "uco-location:altitude": { 56 | "@type": "xsd:decimal", 57 | "@value": "0.0" 58 | } 59 | } 60 | ] 61 | }, 62 | { 63 | "@id": "kb:c64804f4-bd52-4194-8409-08018386374f", 64 | "@type": "uco-observable:ObservableObject", 65 | "uco-core:hasFacet": [ 66 | { 67 | "@id": "kb:bc1d7cec-bea9-4ccf-8f72-457728aa42d2", 68 | "@type": "uco-observable:WirelessNetworkConnectionFacet", 69 | "uco-observable:ssid": "78:BC:1A:36:25:E0" 70 | } 71 | ] 72 | }, 73 | { 74 | "@id": "kb:701b2190-5d5a-4786-bc0c-e6e0bf1dbd65", 75 | "@type": "uco-observable:ObservableRelationship", 76 | "uco-core:isDirectional": { 77 | "@type": "xsd:boolean", 78 | "@value": true 79 | }, 80 | "uco-core:kindOfRelationship": "Mapped_Into", 81 | "uco-core:source": { 82 | "@id": "kb:c64804f4-bd52-4194-8409-08018386374f" 83 | }, 84 | "uco-core:target": { 85 | "@id": "kb:37445ac8-7fd9-4ab4-ba82-231eba274480" 86 | } 87 | }, 88 | { 89 | "@id": "kb:d00d2e24-684f-4d8e-9563-3b92a85c2dea", 90 | "@type": "uco-observable:ObservableRelationship", 91 | "uco-core:isDirectional": { 92 | "@type": "xsd:boolean", 93 | "@value": true 94 | }, 95 | "uco-core:kindOfRelationship": "Connected_To", 96 | "uco-observable:startTime": { 97 | "@type": "xsd:dateTime", 98 | "@value": "2021-07-29T13:42:11+00:00" 99 | }, 100 | "uco-observable:endTime": { 101 | "@type": "xsd:dateTime", 102 | "@value": "2021-07-29T17:55:19+00:00" 103 | }, 104 | "uco-core:source": { 105 | "@id": "kb:e4912cd1-abc3-4ad4-9d73-f54379752e02" 106 | }, 107 | "uco-core:target": { 108 | "@id": "kb:c64804f4-bd52-4194-8409-08018386374f" 109 | } 110 | } 111 | ] 112 | } -------------------------------------------------------------------------------- /json/EMAIL_MESSAGE_CASE_1.0.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "kb": "http://example.org/kb/", 4 | "drafting": "http://example.org/ontology/drafting/", 5 | "co": "http://purl.org/co/", 6 | "rdfs": "http://www.w3.org/2000/01/rdf-schema#", 7 | "uco-core": "https://ontology.unifiedcyberontology.org/uco/core/", 8 | "uco-identity": "https://ontology.unifiedcyberontology.org/uco/identity/", 9 | "uco-location": "https://ontology.unifiedcyberontology.org/uco/location/", 10 | "uco-role": "https://ontology.unifiedcyberontology.org/uco/role/", 11 | "uco-action": "https://ontology.unifiedcyberontology.org/uco/action/", 12 | "uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/", 13 | "uco-types": "https://ontology.unifiedcyberontology.org/uco/types/", 14 | "uco-tool": "https://ontology.unifiedcyberontology.org/uco/tool/", 15 | "case-investigation": "https://ontology.caseontology.org/case/investigation/", 16 | "xsd": "http://www.w3.org/2001/XMLSchema#" 17 | }, 18 | "uco-core:object": [ 19 | 20 | { 21 | "@id": "kb:b35a22bb-4724-456d-9d5e-cb10bac9939d", 22 | "@type": "uco-observable:ObservableObject", 23 | "uco-core:hasFacet": [ 24 | { 25 | "@id": "kb:9822afd7-c7c3-4d36-84b4-65e2f33e9f9a", 26 | "@type": "uco-observable:EmailAddressFacet", 27 | "uco-observable:addressValue": "tornadobeth@gmail.com" 28 | } 29 | ] 30 | }, 31 | { 32 | "@id": "kb:0e9ee8e2-a3ae-4034-ad6e-9faf2d74be4f", 33 | "@type": "uco-observable:ObservableObject", 34 | "uco-core:hasFacet": [ 35 | { 36 | "@id": "kb:171e2ad5-4487-4c49-b5b3-fce438264222", 37 | "@type": "uco-observable:EmailAddressFacet", 38 | "uco-observable:addressValue": "sofia.karppi@supo.fi" 39 | } 40 | ] 41 | }, 42 | { 43 | "@id": "kb:4da63ae2-4dde-46ed-902b-707fba9c4ec6", 44 | "@type": "uco-observable:ObservableObject", 45 | "uco-core:hasFacet": [ 46 | { 47 | "@id": "22099976-cf95-412f-aa81-73019ee6e5cb", 48 | "@type": "uco-observable:AccountFacet", 49 | "uco-observable:isActive": { 50 | "@type": "xsd:boolean", 51 | "@value": true 52 | }, 53 | "uco-observable:accountIdentifier": "Sofia K." 54 | }, 55 | { 56 | "@id": "kb:abefde69-763c-421f-ab98-68ec712c3240", 57 | "@type": "uco-observable:EmailAccountFacet", 58 | "uco-observable:emailAddress": { 59 | "@id": "kb:0e9ee8e2-a3ae-4034-ad6e-9faf2d74be4f" 60 | } 61 | } 62 | ] 63 | }, 64 | { 65 | "@id": "kb:29ec4e5c-79b4-470b-89b0-05f4e4d7438f", 66 | "@type": "uco-observable:ObservableObject", 67 | "uco-core:hasFacet": [ 68 | { 69 | "@id": "kb:7727e140-c0cf-4d58-8b1f-fe6872b928fd", 70 | "@type": "uco-observable:AccountFacet", 71 | "uco-observable:isActive": { 72 | "@type": "xsd:boolean", 73 | "@value": true 74 | }, 75 | "uco-observable:accountIdentifier": "Beth T." 76 | }, 77 | { 78 | "@id": "kb:b93c1c72-f83f-45a3-b08e-3e56f370c26c", 79 | "@type": "uco-observable:EmailAccountFacet", 80 | "uco-observable:emailAddress": { 81 | "@id": "kb:b35a22bb-4724-456d-9d5e-cb10bac9939d" 82 | } 83 | } 84 | ] 85 | }, 86 | { 87 | "@id": "kb:86c4539e-6bd2-4f73-aa44-00debcd57326", 88 | "@type": "uco-observable:ObservableObject", 89 | "uco-core:hasFacet": [ 90 | { 91 | "@id": "kb:a4f1bc5a-9250-442f-b2c0-508cf226809c", 92 | "@type": "uco-observable:EmailMessageFacet", 93 | "uco-observable:subject": "Helena Willamo clues.", 94 | "uco-observable:body": "Dear Friends, Nice to hearing from you! Thank you for the invitation. I’ll answer to you asap.", 95 | "uco-observable:allocationStatus": "Intact", 96 | "uco-observable:sentTime": { 97 | "@type": "xsd:dateTime", 98 | "@value": "2021-02-25T14:55:51+00:00" 99 | }, 100 | "uco-observable:from": { 101 | "@id": "kb:4da63ae2-4dde-46ed-902b-707fba9c4ec6" 102 | }, 103 | "uco-observable:to": [ 104 | { 105 | "@id": "kb:29ec4e5c-79b4-470b-89b0-05f4e4d7438f" 106 | } 107 | ], 108 | "uco-observable:cc": [], 109 | "uco-observable:bcc": [] 110 | } 111 | ] 112 | } 113 | ] 114 | } -------------------------------------------------------------------------------- /json/URL_HISTORY_MULTI_ITEMS_CASE_1.0.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "kb": "http://example.org/kb/", 4 | "drafting": "http://example.org/ontology/drafting/", 5 | "co": "http://purl.org/co/", 6 | "rdfs": "http://www.w3.org/2000/01/rdf-schema#", 7 | "uco-core": "https://ontology.unifiedcyberontology.org/uco/core/", 8 | "uco-identity": "https://ontology.unifiedcyberontology.org/uco/identity/", 9 | "uco-location": "https://ontology.unifiedcyberontology.org/uco/location/", 10 | "uco-role": "https://ontology.unifiedcyberontology.org/uco/role/", 11 | "uco-action": "https://ontology.unifiedcyberontology.org/uco/action/", 12 | "uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/", 13 | "uco-types": "https://ontology.unifiedcyberontology.org/uco/types/", 14 | "uco-tool": "https://ontology.unifiedcyberontology.org/uco/tool/", 15 | "case-investigation": "https://ontology.caseontology.org/case/investigation/", 16 | "xsd": "http://www.w3.org/2001/XMLSchema#" 17 | }, 18 | "uco-core:object": [ 19 | { 20 | "@id": "kb:5d96df90-d9e1-423c-b8db-c2327812ab38", 21 | "@type": "uco-observable:ObservableObject", 22 | "uco-core:hasFacet": [ 23 | { 24 | "@id": "kb:1723ed9c-2d8e-415c-8cf6-31599c49df79", 25 | "@type": "uco-observable:ApplicationFacet", 26 | "uco-observable:applicationIdentifier": "Safari Apple", 27 | "uco-observable:version": "15.23.45" 28 | } 29 | ] 30 | }, 31 | { 32 | "@id": "kb:39ff4987-8ae5-47e3-8369-dbd0d5f79398", 33 | "@type": "uco-observable:ObservableObject", 34 | "rdfs:comment": "@type=uco-observable:URLHistory", 35 | "uco-core:hasFacet": [ 36 | { 37 | "@id": "kb:a455b867-957e-4fce-a0ad-1af9c6fa4edb", 38 | "@type": "uco-observable:URLHistoryFacet", 39 | "uco-observable:browserInformation": { 40 | "@id": "kb:5d96df90-d9e1-423c-b8db-c2327812ab38" 41 | }, 42 | "uco-observable:urlHistoryEntry": [ 43 | { 44 | "@id": "kb:193a7fc6-5f15-4b3c-8763-f1dc3c9bfd14", 45 | "@type": "uco-observable:URLHistoryEntry", 46 | "uco-observable:firstVisit": { 47 | "@type": "xsd:dateTime", 48 | "@value": "2017-01-25T02:20:22.00Z" 49 | }, 50 | "uco-observable:lastVisit": { 51 | "@type": "xsd:dateTime", 52 | "@value": "2017-01-25T02:20:22.00Z" 53 | }, 54 | "uco-observable:expirationTime": null, 55 | "uco-observable:url": { 56 | "@id": "kb:b7906534-0483-4cf4-979c-5351916602ed" 57 | }, 58 | "uco-observable:pageTitle": "Where can you find baby owls for sale? Are owls legal to keep as pets? - Quora", 59 | "uco-observable:visitCount": 2, 60 | "uco-observable:manuallyEnteredCount": { 61 | "@type": "xsd:nonNegativeInteger", 62 | "@value": 0 63 | }, 64 | "uco-observable:keywordSearchTerm": "Baby owl shops" 65 | }, 66 | { 67 | "@id": "kb:f3d8a186-3863-42f9-b4f9-05cfdec34c75", 68 | "@type": "uco-observable:URLHistoryEntry", 69 | "uco-observable:firstVisit": { 70 | "@type": "xsd:dateTime", 71 | "@value": "2022-02-22T02:20:22.00Z" 72 | }, 73 | "uco-observable:lastVisit": { 74 | "@type": "xsd:dateTime", 75 | "@value": "2022-05-18T02:20:22.00Z" 76 | }, 77 | "uco-observable:expirationTime": null, 78 | "uco-observable:url": { 79 | "@id": "kb:b88d66e8-3fae-4e15-879b-1e068240d2a0" 80 | }, 81 | "uco-observable:pageTitle": "Otter AI plans", 82 | "uco-observable:visitCount": 12, 83 | "uco-observable:manuallyEnteredCount": { 84 | "@type": "xsd:nonNegativeInteger", 85 | "@value": 0 86 | }, 87 | "uco-observable:keywordSearchTerm": "From mp3 to text" 88 | } 89 | ] 90 | } 91 | ] 92 | }, 93 | { 94 | "@id": "kb:b7906534-0483-4cf4-979c-5351916602ed", 95 | "@type": "uco-observable:URL", 96 | "uco-core:hasFacet": [ 97 | { 98 | "@id": "kb:f2618636-aec3-459e-bda7-eeedfbeac3c0", 99 | "@type": "uco-observable:URLFacet", 100 | "uco-observable:fullValue": "https://www.quora.com/Where-can-you-find-baby-owls-for-sale-Are-owls-legal-to-keep-as-pets" 101 | } 102 | ] 103 | }, 104 | { 105 | "@id": "kb:b88d66e8-3fae-4e15-879b-1e068240d2a0", 106 | "@type": "uco-observable:URL", 107 | "uco-core:hasFacet": [ 108 | { 109 | "@id": "kb:12c098ec-0466-47b3-a3ba-5addc7778083", 110 | "@type": "uco-observable:URLFacet", 111 | "uco-observable:fullValue": "https://otter.ai/setting/plan" 112 | } 113 | ] 114 | } 115 | ] 116 | } 117 | -------------------------------------------------------------------------------- /json/Message_CASE_1.0.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "kb": "http://example.org/kb/", 4 | "drafting": "http://example.org/ontology/drafting/", 5 | "co": "http://purl.org/co/", 6 | "rdfs": "http://www.w3.org/2000/01/rdf-schema#", 7 | "uco-core": "https://ontology.unifiedcyberontology.org/uco/core/", 8 | "uco-identity": "https://ontology.unifiedcyberontology.org/uco/identity/", 9 | "uco-location": "https://ontology.unifiedcyberontology.org/uco/location/", 10 | "uco-role": "https://ontology.unifiedcyberontology.org/uco/role/", 11 | "uco-action": "https://ontology.unifiedcyberontology.org/uco/action/", 12 | "uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/", 13 | "uco-types": "https://ontology.unifiedcyberontology.org/uco/types/", 14 | "uco-tool": "https://ontology.unifiedcyberontology.org/uco/tool/", 15 | "case-investigation": "https://ontology.caseontology.org/case/investigation/", 16 | "xsd": "http://www.w3.org/2001/XMLSchema#" 17 | }, 18 | "uco-core:object": [ 19 | { 20 | "@id": "kb:5340d5ad-0fe1-463c-a461-f211e64edfd4", 21 | "@type": "uco-observable:ObservableObject", 22 | "uco-core:hasFacet": [ 23 | { 24 | "@id": "kb:1723ed9c-2d8e-415c-8cf6-31599c49df79", 25 | "@type": "uco-observable:ApplicationFacet", 26 | "uco-observable:applicationIdentifier": "com.whatsapp", 27 | "uco-observable:version": "1.23.45" 28 | } 29 | ] 30 | }, 31 | { 32 | "@id": "kb:a5931c7e-fc1e-4def-a618-fc31d9ae4cc7", 33 | "@type": "uco-observable:ApplicationAccount", 34 | "uco-core:hasFacet": [ 35 | { 36 | "@id": "kb:0279d259-3195-418b-b5bc-ac3d7b8dbf66", 37 | "@type": "uco-observable:AccountFacet", 38 | "uco-observable:accountIdentifier": "393369402190@s.whatsapp.net" 39 | }, 40 | { 41 | "@id": "kb:6a4fc272-4ca3-4da3-93d0-0711ca3e85d6", 42 | "@type": "uco-observable:ApplicationAccountFacet", 43 | "uco-observable:application": { 44 | "@id": "kb:5340d5ad-0fe1-463c-a461-f211e64edfd4" 45 | } 46 | }, 47 | { 48 | "@id": "kb:0d2ac063-7bed-4525-be4c-7dc38a4288f1", 49 | "@type": "uco-observable:DigitalAccountFacet", 50 | "uco-observable:displayName": "Jane Balding" 51 | } 52 | ] 53 | }, 54 | { 55 | "@id": "kb:f135dee3-ba06-4ded-ad63-5484ce240ec8", 56 | "@type": "uco-observable:ApplicationAccount", 57 | "uco-core:hasFacet": [ 58 | { 59 | "@id": "kb:36d0abb1-bdd8-460c-8422-63f715e2e1c2", 60 | "@type": "uco-observable:AccountFacet", 61 | "uco-observable:isActive": { 62 | "@type": "xsd:boolean", 63 | "@value": "true" 64 | }, 65 | "uco-observable:accountIdentifier": "363483643499@s.whatsapp.net" 66 | }, 67 | { 68 | "@id": "kb:9e8995f1-fa79-432f-915d-1eed79b83413", 69 | "@type": "uco-observable:ApplicationAccountFacet", 70 | "uco-observable:application": { 71 | "@id": "kb:5340d5ad-0fe1-463c-a461-f211e64edfd4" 72 | } 73 | }, 74 | { 75 | "@id": "kb:cc9400b6-044d-4fef-a7d1-adecdf0b7aa2", 76 | "@type": "uco-observable:DigitalAccountFacet", 77 | "uco-observable:displayName": "Vivienne Joosha" 78 | } 79 | ] 80 | }, 81 | 82 | { 83 | "@id": "kb:4237ff8b-e049-4a56-bcf7-e89ed2797d83", 84 | "rdfs:comment": "@type: uco-observable:MessageThread", 85 | "@type": "uco-observable:ObservableObject", 86 | "uco-core:hasFacet": [ 87 | { 88 | "@id": "kb:0cd2f9f8-9040-4af7-82f8-8287fb3f861d", 89 | "@type": "uco-observable:MessageThreadFacet", 90 | "identifier": "jane~vivienne@whatsapp.gs.net", 91 | "uco-observable:displayName": "Best Friend Chat!!", 92 | "uco-observable:messageThread": { 93 | "@id": "kb:1a921f84-eadd-4591-be0d-57b936933622", 94 | "@type": "uco-types:Thread", 95 | "co:size": { 96 | "@type": "xsd:nonNegativeInteger", 97 | "@value": 2 98 | }, 99 | "co:element": [ 100 | { 101 | "@id": "kb:d8330d5a-b8de-4425-9cd8-a37b038afe81" 102 | }, 103 | { 104 | "@id": "kb:3328fbc7-1f63-4e66-b8fc-e27143a64331" 105 | } 106 | ] 107 | }, 108 | "uco-observable:participant": [ 109 | { 110 | "@id": "kb:a5931c7e-fc1e-4def-a618-fc31d9ae4cc7" 111 | }, 112 | { 113 | "@id": "kb:f135dee3-ba06-4ded-ad63-5484ce240ec8" 114 | } 115 | ] 116 | } 117 | ] 118 | }, 119 | { 120 | "@id": "kb:3328fbc7-1f63-4e66-b8fc-e27143a64331", 121 | "@type": "uco-observable:Message", 122 | "uco-core:hasFacet": [ 123 | { 124 | "@id": "kb:3104e958-381e-4aa5-ba0a-6fc47b33ebc7", 125 | "@type": "uco-observable:MessageFacet", 126 | "uco-observable:application": { 127 | "@id": "kb:5340d5ad-0fe1-463c-a461-f211e64edfd4" 128 | }, 129 | "uco-observable:messageText": "I said some things in a tweet! @sarahsmithtweeter #hashtag", 130 | "uco-observable:from": { 131 | "@id": "kb:f135dee3-ba06-4ded-ad63-5484ce240ec8" 132 | }, 133 | "uco-observable:to": [ 134 | { 135 | "@id": "kb:a5931c7e-fc1e-4def-a618-fc31d9ae4cc7" 136 | } 137 | ], 138 | "uco-observable:sentTime": { 139 | "@type": "xsd:dateTime", 140 | "@value": "2010-01-16T16:34:56.25Z" 141 | } 142 | } 143 | ] 144 | }, 145 | { 146 | "@id": "kb:d8330d5a-b8de-4425-9cd8-a37b038afe81", 147 | "@type": "uco-observable:Message", 148 | "uco-core:hasFacet": [ 149 | { 150 | "@id": "kb:51b43eaf-49fb-4812-baf2-210f4893e6d0", 151 | "@type": "uco-observable:MessageFacet", 152 | "uco-observable:application": { 153 | "@id": "kb:5340d5ad-0fe1-463c-a461-f211e64edfd4" 154 | }, 155 | "uco-observable:messageText": "Hey bud!", 156 | "uco-observable:from": { 157 | "@id": "kb:a5931c7e-fc1e-4def-a618-fc31d9ae4cc7" 158 | }, 159 | "uco-observable:to": [ 160 | { 161 | "@id": "kb:f135dee3-ba06-4ded-ad63-5484ce240ec8" 162 | } 163 | ], 164 | "uco-observable:sentTime": { 165 | "@type": "xsd:dateTime", 166 | "@value": "2010-01-15T17:59:43.25Z" 167 | } 168 | } 169 | ] 170 | } 171 | ] 172 | } 173 | -------------------------------------------------------------------------------- /json/ACTION_CASE_1.0.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "kb": "http://example.org/kb/", 4 | "drafting": "http://example.org/ontology/drafting/", 5 | "co": "http://purl.org/co/", 6 | "rdfs": "http://www.w3.org/2000/01/rdf-schema#", 7 | "uco-core": "https://ontology.unifiedcyberontology.org/uco/core/", 8 | "uco-identity": "https://ontology.unifiedcyberontology.org/uco/identity/", 9 | "uco-location": "https://ontology.unifiedcyberontology.org/uco/location/", 10 | "uco-role": "https://ontology.unifiedcyberontology.org/uco/role/", 11 | "uco-action": "https://ontology.unifiedcyberontology.org/uco/action/", 12 | "uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/", 13 | "uco-vocabulary":"https://ontology.unifiedcyberontology.org/uco/vocabulary/", 14 | "uco-types": "https://ontology.unifiedcyberontology.org/uco/types/", 15 | "uco-tool": "https://ontology.unifiedcyberontology.org/uco/tool/", 16 | "case-investigation": "https://ontology.caseontology.org/case/investigation/", 17 | "xsd": "http://www.w3.org/2001/XMLSchema#" 18 | }, 19 | "uco-core:object": [ 20 | { 21 | "@id": "kb:e4912cd1-abc3-4ad4-9d73-f54379752e02", 22 | "@type": "uco-observable:ObservableObject", 23 | "uco-core:hasFacet": [ 24 | { 25 | "@id": "kb:22f9f968-e829-4a22-89fc-751feff9d0b0", 26 | "@type": "uco-observable:DeviceFacet", 27 | "uco-observable:deviceType": "Mobile phone", 28 | "uco-observable:model": "iPhone X", 29 | "uco-observable:serialNumber": "HW095687Y2022" 30 | }, 31 | { 32 | "@id": "kb:1d4e9269-ad19-4fe4-8055-377301bdefde", 33 | "@type": "uco-observable:MobileDeviceFacet", 34 | "uco-observable:IMSI": "310260249043715", 35 | "uco-observable:ICCID": "8901260243790437158", 36 | "uco-observable:IMEI": "359405082912450" 37 | }, 38 | { 39 | "@id": "kb:6bd89154-b501-4fd8-a750-58d39e4a51e7", 40 | "@type": "uco-observable:OperatingSystemFacet", 41 | "uco-observable:displayName": "iOS", 42 | "uco-observable:manufacturer": 43 | { 44 | "@id": "kb:73952c43-8df5-4fa3-888c-f0f00d2eab8f" 45 | }, 46 | "uco-observable:version": "14.6" 47 | }, 48 | { 49 | "@id": "kb:75be1e84-348e-4d19-85d3-a1e23eed77cc", 50 | "@type": "uco-observable:BluetoothAddressFacet", 51 | "uco-observable:displayName": "Good hook", 52 | "uco-observable:addressValue": "D4:A3:3D:B5:F4:6C" 53 | }, 54 | { 55 | "@id": "kb:a265c5ed-95c2-46e9-af91-4b73023f918b", 56 | "@type": "uco-observable:WifiAddressFacet", 57 | "uco-observable:addressValue": "D4:A3:3D:B5:F4:48" 58 | } 59 | ] 60 | }, 61 | { 62 | "@id": "kb:73952c43-8df5-4fa3-888c-f0f00d2eab8f", 63 | "@type": "uco-identity:Identity", 64 | "uco-core:description": "Huawei UK" 65 | }, 66 | { 67 | "@id": "kb:7ae6b781-4704-428f-85df-3367515dc608", 68 | "@type": "uco-identity:Identity", 69 | "uco-core:description": "Cellebrite, Petah Tikva, Israel" 70 | }, 71 | { 72 | "@id": "kb:8e4f771d-4fa0-4f70-b593-20d8f00e0461", 73 | "@type": "uco-observable:ObservableObject", 74 | "uco-core:hasFacet": [ 75 | { 76 | "@id": "kb:22e1dd8f-6209-479d-b5e7-b8cc4ecc5f6f", 77 | "@type": "uco-identity:SimpleNameFacet", 78 | "uco-identity:givenName": "Forensic Lab FG Consulting" 79 | } 80 | ] 81 | }, 82 | { 83 | "@id": "kb:4252f4ee-d2bd-4d83-bbb4-2669a7be8286", 84 | "@type": "uco-tool:Tool", 85 | "uco-core:name": "UFED PA", 86 | "uco-tool:version": "7.57.1.9", 87 | "uco-tool:toolType": "Acquisition", 88 | "uco-tool:creator": { 89 | "@id": "kb:7ae6b781-4704-428f-85df-3367515dc608" 90 | } 91 | }, 92 | { 93 | "@id": "kb:5e350cd9-3e48-4f8a-82f1-26e394e0780f", 94 | "@type": "uco-observable:ObservableObject", 95 | "uco-core:hasFacet": [ 96 | { 97 | "@id": "kb:0be208ff-034c-4529-b004-39b8426393b4", 98 | "@type": "uco-observable:FileFacet", 99 | "uco-observable:fileName": "Apple_iPhone X (A1901).zip", 100 | "uco-observable:filePath": "Apple_iPhone X (A1901).zip", 101 | "drafting:fileLocalPath": "files/Ucategorized/Apple_iPhone X (A1901).zip", 102 | "uco-observable:extension": ".zip", 103 | "uco-observable:accessedTime": { 104 | "@type": "xsd:dateTime", 105 | "@value": "1900-01-01T08:00:00+00:00" 106 | }, 107 | "uco-observable:observableCreatedTime": { 108 | "@type": "xsd:dateTime", 109 | "@value": "1900-01-01T08:00:00+00:00" 110 | }, 111 | "uco-observable:modifiedTime": { 112 | "@type": "xsd:dateTime", 113 | "@value": "1900-01-01T08:00:00+00:00" 114 | }, 115 | "uco-core:tag": [ 116 | "Uncategorized" 117 | ], 118 | "uco-observable:sizeInBytes": { 119 | "@type": "xsd:integer", 120 | "@value": 16965760332 121 | } 122 | }, 123 | { 124 | "@id": "kb:097bc2b2-45e4-453a-a208-aeab7e77da99", 125 | "@type": "uco-observable:ContentDataFacet", 126 | "uco-observable:hash": [ 127 | { 128 | "@id": "kb:fbd39b90-551d-5a80-8f3d-70e91c5fe472", 129 | "@type": "uco-types:Hash", 130 | "uco-types:hashMethod": { 131 | "@type": "uco-vocabulary:HashNameVocab", 132 | "@value": "SHA256" 133 | }, 134 | "uco-types:hashValue": { 135 | "@type": "xsd:hexBinary", 136 | "@value": "6b51d431df5d7f141cbececcf79edf3dd861c3b4069f0b11661a3eefacbba918" 137 | } 138 | } 139 | ] 140 | } 141 | ] 142 | }, 143 | { 144 | "@id": "kb:9ebe7b98-5323-4bf5-b44a-d499c928b93d", 145 | "@type": "case-investigation:ProvenanceRecord", 146 | "case-investigation:exhibitNumber": "E01", 147 | "uco-core:object": [ 148 | { 149 | "@id": "kb:5e350cd9-3e48-4f8a-82f1-26e394e0780f" 150 | } 151 | ] 152 | 153 | }, 154 | { 155 | "@id": "kb:0d549b0e-4484-4858-9e48-fb21e3f317f7", 156 | "@type": "case-investigation:InvestigativeAction", 157 | "rdfs:comment": "also the @type= uco-action:Action is admsissible", 158 | "uco-core:name": "Forensic mobile device acquisition", 159 | "uco-action:startTime": { 160 | "@type": "xsd:dateTime", 161 | "@value": "2021-07-29T12:28:49+00:00" 162 | }, 163 | "uco-action:endTime": { 164 | "@type": "xsd:dateTime", 165 | "@value": "2021-07-29T12:43:44+00:00" 166 | }, 167 | "uco-action:performer": { 168 | "@id": "kb:8e4f771d-4fa0-4f70-b593-20d8f00e0461" 169 | }, 170 | "uco-action:instrument": { 171 | "@id": "kb:4252f4ee-d2bd-4d83-bbb4-2669a7be8286" 172 | }, 173 | "uco-action:result": [ 174 | { 175 | "@id": "kb:9ebe7b98-5323-4bf5-b44a-d499c928b93d" 176 | } 177 | ], 178 | "uco-action:object": { 179 | "@id": "kb:e4912cd1-abc3-4ad4-9d73-f54379752e02" 180 | } 181 | } 182 | ] 183 | } -------------------------------------------------------------------------------- /parserDebug.py: -------------------------------------------------------------------------------- 1 | import codecs 2 | 3 | #--- class ParserDebug.py 4 | class ParserDebug: 5 | def __init__(self, debugFile): 6 | self.dFileName = debugFile 7 | self.dFileHandle = codecs.open(self.dFileName, 'w', encoding='utf8') 8 | 9 | def writeDebugCALL(self, data): 10 | line = "\n*---\nTotal CALL (deleted) " + str(data.CALLtotal) 11 | line += ' (' + str(data.CALLdeleted) + ')' 12 | line += '\n*---' 13 | self.dFileHandle.write(line) 14 | for i in range(data.CALLtotal): 15 | line = '\n[id] ' + data.CALLid[i] 16 | line += '\n\t[status] ' + data.CALLstatus[i] 17 | line += '\n\t[source] ' + data.CALLsource[i] 18 | line += '\n\t[direction] ' + data.CALLdirection[i] 19 | line += '\n\t[outcome] ' + data.CALLoutcome[i] 20 | line += '\n\t[time] ' + data.CALLtimeStamp[i] 21 | line += '\n\t[duration]' + data.CALLduration[i] 22 | if (len(data.CALLrolesTO[i]) > 0): 23 | line += '\n\t[roleTO] ' + data.CALLrolesTO[i][0] 24 | else: 25 | line += '\n\t[roleTO] ' + '_NOT_PROVIDED_' 26 | 27 | if (len(data.CALLrolesFROM[i]) > 0): 28 | line += '\n\t[roleFROM] ' + data.CALLrolesFROM[i][0] 29 | else: 30 | line += '\n\t[roleFROM] ' + '_NOT_PROVIDED_' 31 | 32 | if (len(data.CALLnamesTO[i]) > 0): 33 | line += '\n\t[nameTO] ' + data.CALLnamesTO[i][0] 34 | else: 35 | line += '\n\t[nameTO] ' + '_NOT_PROVIDED_' 36 | 37 | if (len(data.CALLnamesFROM[i]) > 0): 38 | line += '\n\t[nameFROM] ' + data.CALLnamesFROM[i][0] 39 | else: 40 | line += '\n\t[nameFROM] ' + '_NOT_PROVIDED_' 41 | 42 | if (len(data.CALLidentifiersTO[i]) > 0): 43 | line += '\n\t[identifierTO] ' + data.CALLidentifiersTO[i][0] 44 | else: 45 | line += '\n\t[identifierTO] ' + '_NOT_PROVIDED_' 46 | 47 | if (len(data.CALLidentifiersFROM[i]) > 0): 48 | line += '\n\t[identifierFROM] ' + data.CALLidentifiersFROM[i][0] 49 | else: 50 | line += '\n\t[identifierFROM] ' + '_NOT_PROVIDED_' 51 | 52 | self.dFileHandle.write(line) 53 | 54 | def writeDebugCHAT(self, data): 55 | line = "\n*---\nTotal CHAT (deleted) " + str(data.CHATtotal) 56 | line += ' (' + str(data.CHATdeleted) + ')' 57 | line += '\n*---' 58 | self.dFileHandle.write(line) 59 | for i in range(data.CHATtotal): 60 | line = '\n* [CHATid] ' + data.CHATid[i] 61 | line += '\n\t[source] ' + data.CHATsource[i] 62 | for j in range(len(data.CHATpartyIdentifiers[i])): 63 | line += '\n\t[particpantIdentifier] ' + data.CHATpartyIdentifiers[i][j] 64 | line += '\n\t[particpantName] ' + data.CHATpartyNames[i][j] 65 | for j in range(len(data.CHATmsgBodies[i])): 66 | line += '\n\t[msg n.] ' + str(j + 1) 67 | line += '\n\t\t[IdentifierFROM] ' + data.CHATmsgIdentifiersFrom[i][j] 68 | line += '\n\t\t[NameFROM] ' + data.CHATmsgNamesFrom[i][j] 69 | line += '\n\t\t[msgIdentifierTO] ' + data.CHATmsgIdentifiersTo[i][j] 70 | line += '\n\t\t[msgNameTO] ' + data.CHATmsgNamesTo[i][j] 71 | line += '\n\t\t[msgBody] ' + data.CHATmsgBodies[i][j] 72 | line += '\n\t\t[Status] ' + data.CHATmsgStatuses[i][j] 73 | line += '\n\t\t[msgTimeStamp] ' + data.CHATmsgTimeStamps[i][j] 74 | line += '\n\t\t[Attachment (File/Url)] ' + data.CHATmsgAttachmentFilenames[i][j] 75 | line += ' / ' + data.CHATmsgAttachmentUrls[i][j] 76 | self.dFileHandle.write(line) 77 | 78 | def writeDebugCONTACT(self, data): 79 | line = "\n*---\nTotal CONTACT (deleted) " + str(data.CONTACTtotal) 80 | line += ' (' + str(data.CONTACTdeleted) + ')' 81 | line += '\n*---' 82 | self.dFileHandle.write(line + '\n') 83 | for i in range(data.CONTACTtotal): 84 | line = '[CONTACTid] ' + data.CONTACTid[i] + '\n' 85 | line += ' [Name] ' + data.CONTACTname[i] 86 | for j in range(len(data.CONTACTphoneNums[i])): 87 | line += ' [PhoneNums] ' + data.CONTACTphoneNums[i][j] + ' ' 88 | line += '\n' 89 | self.dFileHandle.write(line) 90 | 91 | def writeDebugCONTEXT(self, data): 92 | line = "\n*---\nCONTEXT" 93 | line += '\n*---' 94 | line += '\n\t[Ufed version] ' + data.CONTEXTufedVersionText 95 | line += '\n\t[Device Extraction start date/time] ' 96 | line += data.CONTEXTdeviceCreationTimeText + '\n' 97 | line += '\n\t[Device Acquisition Start/End date/time] ' 98 | line += data.CONTEXTdeviceExtractionStartText + ' / ' 99 | line += data.CONTEXTdeviceExtractionEndText + '\n' 100 | line += '\n\t[Examiner name] ' 101 | line += data.CONTEXTexaminerNameText + '\n' 102 | line += '\n\t[Bluetooth MAC] ' + data.CONTEXTdeviceBluetoothAddressText 103 | line += '\n\t[DeviceID] ' + data.CONTEXTdeviceIdText 104 | line += '\n\t[PhoneModel] ' + data.CONTEXTdevicePhoneModelText 105 | line += '\n\t[OS type] ' + data.CONTEXTdeviceOsTypeText 106 | line += '\n\t[OS version] ' + data.CONTEXTdeviceOsVersionText 107 | line += '\n\t[PhoneVendor] ' + data.CONTEXTdevicePhoneVendorText 108 | line += '\n\t[MAC] ' + data.CONTEXTdeviceMacAddressText 109 | line += '\n\t[ICCID] ' + data.CONTEXTdeviceIccidText 110 | line += '\n\t[IMSI] ' + data.CONTEXTdeviceImsiText 111 | line += '\n\t[IMEI] ' + data.CONTEXTdeviceImeiText 112 | line += '\n\t[Files]' 113 | for i in range (len(data.CONTEXTimagePath)): 114 | line += '\n\t\t[path]' + data.CONTEXTimagePath[i] 115 | line += '\n\t\t[size]' + data.CONTEXTimageSize[i] 116 | line += '\n\t\t[hash SHA256 / MD5]' + data.CONTEXTimageMetadataHashSHA[i] + ' / ' 117 | line += data.CONTEXTimageMetadataHashMD5[i] 118 | self.dFileHandle.write(line) 119 | 120 | def writeDebugEMAIL(self, data): 121 | line = "\n*---\nTotal EMAIL (deleted) " + str(data.EMAILtotal) 122 | line += ' (' + str(data.EMAILdeleted) + ')' 123 | line += '\n*---' 124 | self.dFileHandle.write(line) 125 | for i in range(data.EMAILtotal): 126 | line = '\n[EMAILid] ' + data.EMAILid[i] 127 | line += '\n\t[status] ' + data.EMAILstatus[i] 128 | line += '\n\t[Source] ' + data.EMAILsource[i] 129 | line += '\n\t[FROM] ' + data.EMAILidentifierFROM[i] 130 | line += '\n\t[TO] ' 131 | for j in range(len(data.EMAILidentifiersTO[i])): 132 | line += '\n\t\t' + data.EMAILidentifiersTO[i][j] 133 | line += '\n\t[CC] ' 134 | for j in range(len(data.EMAILidentifiersCC[i])): 135 | line += '\n\t\t' + data.EMAILidentifiersCC[i][j] 136 | line += '\n\t[BCC] ' 137 | for j in range(len(data.EMAILidentifiersBCC[i])): 138 | line += '\n\t\t' + data.EMAILidentifiersBCC[i][j] 139 | 140 | line += '\n\t[Body] ' + data.EMAILbody[i] 141 | line += '\n\t[Subject] ' + data.EMAILsubject[i] 142 | line += '\n\t[TimeStamp] ' + data.EMAILtimeStamp[i] 143 | line += '\n\t[Attachments]' 144 | for j in range(len(data.EMAILattachmentsFilename[i])): 145 | line += '\n\t\t' + data.EMAILattachmentsFilename[i][j] 146 | self.dFileHandle.write(line) 147 | 148 | def writeDebugEXTRA_INFO(self, data): 149 | line = '\n*---\nTotal EXTRA_INFO ' + str(len(data.EXTRA_INFOid)) 150 | line += '\n*---' 151 | self.dFileHandle.write(line) 152 | for key in data.EXTRA_INFOdictPath: 153 | line = '\n[extraInofId] ' + key 154 | line += '\n\t[path] ' + data.EXTRA_INFOdictPath[key] 155 | line += '\n\t[size] ' + data.EXTRA_INFOdictSize[key] 156 | line += '\n\t[tableName] ' + data.EXTRA_INFOdictTableName[key] 157 | line += '\n\t[offset] ' + data.EXTRA_INFOdictOffset[key] 158 | line += '\n\t[nodeInfoId] ' + data.EXTRA_INFOdictNodeInfoId[key] 159 | self.dFileHandle.write(line) 160 | 161 | def writeDebugFILES(self, data): 162 | line = "\n*---\nTotal FILE " + str(len(data.FILEid)) 163 | line += '\n*---' 164 | self.dFileHandle.write(line) 165 | for i in range(len(data.FILEid)): 166 | line = '\n[id]=' + data.FILEid[i] 167 | line += '\n\t[path] ' + data.FILEpath[i] 168 | line += '\n\t[size] ' + data.FILEsize[i] 169 | line += '\n\t[MD5] ' + data.FILEmd5[i] 170 | line += '\n\t[Tags] ' + data.FILEtags[i] 171 | line += '\n\t[Ctime] ' + data.FILEtimeCreate[i] 172 | line += '\n\t[Mtime] ' + data.FILEtimeModify[i] 173 | line += '\n\t[Atime] ' + data.FILEtimeAccess[i] 174 | line += '\n\t[localPath] ' + data.FILElocalPath[i] 175 | line += '\n\t[iNodeNumber] ' + data.FILEiNodeNumber[i] 176 | line += '\n\t[OwnerGID] ' + data.FILEownerGID[i] 177 | line += '\n\t[OwnerUID] ' + data.FILEownerUID[i] 178 | self.dFileHandle.write(line) 179 | 180 | def writeDebugSMS(self, data): 181 | line = "\n*---\nTotal SMS (deleted) " + str(data.SMStotal) 182 | line += ' (' + str(data.SMSdeleted) + ')' 183 | line += '\n*---' 184 | self.dFileHandle.write(line) 185 | for i in range(len(data.SMSbody)): 186 | line = '\n[SMSid] ' + data.SMSid[i] 187 | line += '\n\t[status] ' + data.SMSstatus[i] 188 | line += '\n\t[source] ' + data.SMSsource[i] 189 | line += '\n\t[parties]' 190 | for j in range(len(data.SMSpartyRoles[i])): 191 | line += '\n\t\t[role] ' + data.SMSpartyRoles[i][j] 192 | line += '\n\t\t[identifier] ' + data.SMSpartyIdentifiers[i][j] 193 | line += '\n\t\t[name] ' + data.SMSpartyNames[i][j] 194 | 195 | line += '\n\t[time] ' + data.SMStimeStamp[i] 196 | line += '\n\t[body] ' + data.SMSbody[i] 197 | self.dFileHandle.write(line) 198 | 199 | def writeDebugU_ACCOUNT(self, data): 200 | line = "\n*---\nTotal U_ACCOUNT " + str(data.U_ACCOUNTtotal) 201 | line += '\n*---' 202 | self.dFileHandle.write(line) 203 | for i in range(len(data.U_ACCOUNTsource)): 204 | line = '\n\t[Source] ' + data.U_ACCOUNTsource[i] 205 | line += '\n\t[Name] ' + data.U_ACCOUNTname[i] 206 | line += '\n\t[User Name] ' + data.U_ACCOUNTusername[i] 207 | self.dFileHandle.write(line) 208 | 209 | 210 | def writeDebugWEB_PAGE(self, data): 211 | line = "\n*---\nTotal WEB_PAGE (deleted) " + str(data.WEB_PAGEtotal) 212 | line += ' (' + str(data.WEB_PAGEdeleted) + ')' 213 | line += '\n*---' 214 | self.dFileHandle.write(line) 215 | for i in range(data.WEB_PAGEtotal): 216 | line = '\n[id] ' + data.WEB_PAGEid[i] 217 | line += '\n\t[source] ' + data.WEB_PAGEsource[i] 218 | line += '\n\t[url] ' + data.WEB_PAGEurl[i] 219 | line += '\n\t[title] ' + data.WEB_PAGEtitle[i] 220 | line += '\n\t[visitCount] ' + data.WEB_PAGEvisitCount[i] 221 | line += '\n\t[lastVisited] ' + data.WEB_PAGElastVisited[i] 222 | self.dFileHandle.write(line) 223 | 224 | def closeDebug(self): 225 | self.dFileHandle.close() 226 | 227 | -------------------------------------------------------------------------------- /UFEDdebug.py: -------------------------------------------------------------------------------- 1 | import codecs 2 | 3 | #--- class ParserDebug.py 4 | class ParserDebug: 5 | def __init__(self, debugFile): 6 | self.dFileName = debugFile 7 | self.dFileHandle = codecs.open(self.dFileName, 'w', encoding='utf8') 8 | 9 | def writeDebugCALL(self, data): 10 | line = "\n*---\nTotal CALL (deleted) " + str(data.CALLtotal) 11 | line += ' (' + str(data.CALLdeleted) + ')' 12 | line += '\n*---' 13 | self.dFileHandle.write(line) 14 | for i in range(data.CALLtotal): 15 | line = '\n[id] ' + data.CALLid[i] 16 | line += '\n\t[status] ' + data.CALLstatus[i] 17 | line += '\n\t[source] ' + data.CALLsource[i] 18 | line += '\n\t[direction] ' + data.CALLdirection[i] 19 | line += '\n\t[outcome] ' + data.CALLoutcome[i] 20 | line += '\n\t[time] ' + data.CALLtimeStamp[i] 21 | line += '\n\t[duration]' + data.CALLduration[i] 22 | if (len(data.CALLrolesTO[i]) > 0): 23 | line += '\n\t[roleTO] ' + data.CALLrolesTO[i][0] 24 | else: 25 | line += '\n\t[roleTO] ' + '_NOT_PROVIDED_' 26 | 27 | if (len(data.CALLrolesFROM[i]) > 0): 28 | line += '\n\t[roleFROM] ' + data.CALLrolesFROM[i][0] 29 | else: 30 | line += '\n\t[roleFROM] ' + '_NOT_PROVIDED_' 31 | 32 | if (len(data.CALLnamesTO[i]) > 0): 33 | line += '\n\t[nameTO] ' + data.CALLnamesTO[i][0] 34 | else: 35 | line += '\n\t[nameTO] ' + '_NOT_PROVIDED_' 36 | 37 | if (len(data.CALLnamesFROM[i]) > 0): 38 | line += '\n\t[nameFROM] ' + data.CALLnamesFROM[i][0] 39 | else: 40 | line += '\n\t[nameFROM] ' + '_NOT_PROVIDED_' 41 | 42 | if (len(data.CALLidentifiersTO[i]) > 0): 43 | line += '\n\t[identifierTO] ' + data.CALLidentifiersTO[i][0] 44 | else: 45 | line += '\n\t[identifierTO] ' + '_NOT_PROVIDED_' 46 | 47 | if (len(data.CALLidentifiersFROM[i]) > 0): 48 | line += '\n\t[identifierFROM] ' + data.CALLidentifiersFROM[i][0] 49 | else: 50 | line += '\n\t[identifierFROM] ' + '_NOT_PROVIDED_' 51 | 52 | self.dFileHandle.write(line) 53 | 54 | def writeDebugCHAT(self, data): 55 | line = "\n*---\nTotal CHAT (deleted) " + str(data.CHATtotal) 56 | line += ' (' + str(data.CHATdeleted) + ')' 57 | line += '\n*---' 58 | self.dFileHandle.write(line) 59 | for i in range(data.CHATtotal): 60 | line = '\n* [CHATid] ' + data.CHATid[i] 61 | line += '\n\t[source] ' + data.CHATsource[i] 62 | for j in range(len(data.CHATpartyIdentifiers[i])): 63 | line += '\n\t[particpantIdentifier] ' + data.CHATpartyIdentifiers[i][j] 64 | line += '\n\t[particpantName] ' + data.CHATpartyNames[i][j] 65 | for j in range(len(data.CHATmsgBodies[i])): 66 | line += '\n\t[msg n.] ' + str(j + 1) 67 | line += '\n\t\t[IdentifierFROM] ' + data.CHATmsgIdentifiersFrom[i][j] 68 | line += '\n\t\t[NameFROM] ' + data.CHATmsgNamesFrom[i][j] 69 | line += '\n\t\t[msgIdentifierTO] ' + data.CHATmsgIdentifiersTo[i][j] 70 | line += '\n\t\t[msgNameTO] ' + data.CHATmsgNamesTo[i][j] 71 | line += '\n\t\t[msgBody] ' + data.CHATmsgBodies[i][j] 72 | line += '\n\t\t[Status] ' + data.CHATmsgStatuses[i][j] 73 | line += '\n\t\t[msgTimeStamp] ' + data.CHATmsgTimeStamps[i][j] 74 | line += '\n\t\t[Attachment (File/Url)] ' + data.CHATmsgAttachmentFilenames[i][j] 75 | line += ' @@@ ' + data.CHATmsgAttachmentUrls[i][j] 76 | self.dFileHandle.write(line) 77 | 78 | def writeDebugCONTACT(self, data): 79 | line = "\n*---\nTotal CONTACT (deleted) " + str(data.CONTACTtotal) 80 | line += ' (' + str(data.CONTACTdeleted) + ')' 81 | line += '\n*---' 82 | self.dFileHandle.write(line + '\n') 83 | for i in range(data.CONTACTtotal): 84 | line = '[CONTACTid] ' + data.CONTACTid[i] + '\n' 85 | line += ' [Name] ' + data.CONTACTname[i] 86 | for j in range(len(data.CONTACTphoneNums[i])): 87 | line += ' [PhoneNums] ' + data.CONTACTphoneNums[i][j] + ' ' 88 | line += '\n' 89 | self.dFileHandle.write(line) 90 | 91 | def writeDebugCONTEXT(self, data): 92 | line = "\n*---\nCONTEXT" 93 | line += '\n*---' 94 | line += '\n\t[Ufed version] ' + data.CONTEXTufedVersionText 95 | line += '\n\t[Device Extraction start date/time] ' 96 | line += data.CONTEXTdeviceCreationTimeText + '\n' 97 | line += '\n\t[Device Acquisition Start/End date/time] ' 98 | line += data.CONTEXTdeviceExtractionStartText + ' / ' 99 | line += data.CONTEXTdeviceExtractionEndText + '\n' 100 | line += '\n\t[Examiner name] ' 101 | line += data.CONTEXTexaminerNameText + '\n' 102 | line += '\n\t[Bluetooth MAC] ' + data.CONTEXTdeviceBluetoothAddressText 103 | line += '\n\t[DeviceID] ' + data.CONTEXTdeviceIdText 104 | line += '\n\t[PhoneModel] ' + data.CONTEXTdevicePhoneModelText 105 | line += '\n\t[OS type] ' + data.CONTEXTdeviceOsTypeText 106 | line += '\n\t[OS version] ' + data.CONTEXTdeviceOsVersionText 107 | line += '\n\t[PhoneVendor] ' + data.CONTEXTdevicePhoneVendorText 108 | line += '\n\t[MAC] ' + data.CONTEXTdeviceMacAddressText 109 | line += '\n\t[ICCID] ' + data.CONTEXTdeviceIccidText 110 | line += '\n\t[IMSI] ' + data.CONTEXTdeviceImsiText 111 | line += '\n\t[IMEI] ' + data.CONTEXTdeviceImeiText 112 | line += '\n\t[Files]' 113 | for i in range (len(data.CONTEXTimagePath)): 114 | line += '\n\t\t[path]' + data.CONTEXTimagePath[i] 115 | line += '\n\t\t[size]' + data.CONTEXTimageSize[i] 116 | line += '\n\t\t[hash SHA256 / MD5]' + data.CONTEXTimageMetadataHashSHA[i] + ' / ' 117 | line += data.CONTEXTimageMetadataHashMD5[i] 118 | self.dFileHandle.write(line) 119 | 120 | def writeDebugEMAIL(self, data): 121 | line = "\n*---\nTotal EMAIL (deleted) " + str(data.EMAILtotal) 122 | line += ' (' + str(data.EMAILdeleted) + ')' 123 | line += '\n*---' 124 | self.dFileHandle.write(line) 125 | for i in range(data.EMAILtotal): 126 | line = '\n[EMAILid] ' + data.EMAILid[i] 127 | line += '\n\t[status] ' + data.EMAILstatus[i] 128 | line += '\n\t[Source] ' + data.EMAILsource[i] 129 | line += '\n\t[FROM] ' + data.EMAILidentifierFROM[i] 130 | line += '\n\t[TO] ' 131 | for j in range(len(data.EMAILidentifiersTO[i])): 132 | line += '\n\t\t' + data.EMAILidentifiersTO[i][j] 133 | line += '\n\t[CC] ' 134 | for j in range(len(data.EMAILidentifiersCC[i])): 135 | line += '\n\t\t' + data.EMAILidentifiersCC[i][j] 136 | line += '\n\t[BCC] ' 137 | for j in range(len(data.EMAILidentifiersBCC[i])): 138 | line += '\n\t\t' + data.EMAILidentifiersBCC[i][j] 139 | 140 | line += '\n\t[Body] ' + data.EMAILbody[i] 141 | line += '\n\t[Subject] ' + data.EMAILsubject[i] 142 | line += '\n\t[TimeStamp] ' + data.EMAILtimeStamp[i] 143 | line += '\n\t[Attachments]' 144 | for j in range(len(data.EMAILattachmentsFilename[i])): 145 | line += '\n\t\t' + data.EMAILattachmentsFilename[i][j] 146 | self.dFileHandle.write(line) 147 | 148 | def writeDebugEXTRA_INFO(self, data): 149 | line = '\n*---\nTotal EXTRA_INFO ' + str(len(data.EXTRA_INFOdictPath)) 150 | line += '\n*---' 151 | self.dFileHandle.write(line) 152 | for key in data.EXTRA_INFOdictPath: 153 | line = '\n[extraInofId] ' + key 154 | line += '\n\t[path] ' + data.EXTRA_INFOdictPath[key] 155 | line += '\n\t[size] ' + data.EXTRA_INFOdictSize[key] 156 | line += '\n\t[tableName] ' + data.EXTRA_INFOdictTableName[key] 157 | line += '\n\t[offset] ' + data.EXTRA_INFOdictOffset[key] 158 | line += '\n\t[nodeInfoId] ' + data.EXTRA_INFOdictNodeInfoId[key] 159 | self.dFileHandle.write(line) 160 | 161 | def writeDebugFILES(self, data): 162 | line = "\n*---\nTotal FILE " + str(len(data.FILEid)) 163 | line += '\n*---' 164 | self.dFileHandle.write(line) 165 | for i in range(len(data.FILEid)): 166 | line = '\n[id]=' + data.FILEid[i] 167 | line += '\n\t[path] ' + data.FILEpath[i] 168 | line += '\n\t[size] ' + data.FILEsize[i] 169 | line += '\n\t[MD5] ' + data.FILEmd5[i] 170 | line += '\n\t[Tags] ' + data.FILEtags[i] 171 | line += '\n\t[Ctime] ' + data.FILEtimeCreate[i] 172 | line += '\n\t[Mtime] ' + data.FILEtimeModify[i] 173 | line += '\n\t[Atime] ' + data.FILEtimeAccess[i] 174 | line += '\n\t[localPath] ' + data.FILElocalPath[i] 175 | line += '\n\t[iNodeNumber] ' + data.FILEiNodeNumber[i] 176 | line += '\n\t[OwnerGID] ' + data.FILEownerGID[i] 177 | line += '\n\t[OwnerUID] ' + data.FILEownerUID[i] 178 | if data.FILEexifLatitudeRef[i] != '': 179 | line += '\n\t[EXIF]\n' + '\t' + data.FILEexifLatitudeRef[i] + \ 180 | ' ' + data.FILEexifLatitude[i] + '\n' + \ 181 | '\t' + data.FILEexifLongitudeRef[i] + ' ' + data.FILEexifLongitude[i] + '\n' + \ 182 | '\t' + data.FILEexifAltitude[i] + '\n' + \ 183 | '\t' + data.FILEexifMake[i] + ' ' + data.FILEexifModel[i] 184 | self.dFileHandle.write(line) 185 | 186 | def writeDebugSMS(self, data): 187 | line = "\n*---\nTotal SMS (deleted) " + str(data.SMStotal) 188 | line += ' (' + str(data.SMSdeleted) + ')' 189 | line += '\n*---' 190 | self.dFileHandle.write(line) 191 | for i in range(len(data.SMSbody)): 192 | line = '\n[SMSid] ' + data.SMSid[i] 193 | line += '\n\t[status] ' + data.SMSstatus[i] 194 | line += '\n\t[source] ' + data.SMSsource[i] 195 | line += '\n\t[parties]' 196 | for j in range(len(data.SMSpartyRoles[i])): 197 | line += '\n\t\t[role] ' + data.SMSpartyRoles[i][j] 198 | line += '\n\t\t[identifier] ' + data.SMSpartyIdentifiers[i][j] 199 | line += '\n\t\t[name] ' + data.SMSpartyNames[i][j] 200 | 201 | line += '\n\t[time] ' + data.SMStimeStamp[i] 202 | line += '\n\t[body] ' + data.SMSbody[i] 203 | self.dFileHandle.write(line) 204 | 205 | def writeDebugU_ACCOUNT(self, data): 206 | line = "\n*---\nTotal U_ACCOUNT " + str(data.U_ACCOUNTtotal) 207 | line += '\n*---' 208 | self.dFileHandle.write(line) 209 | for i in range(len(data.U_ACCOUNTsource)): 210 | line = '\n\t[Source] ' + data.U_ACCOUNTsource[i] 211 | line += '\n\t[Name] ' + data.U_ACCOUNTname[i] 212 | line += '\n\t[User Name] ' + data.U_ACCOUNTusername[i] 213 | self.dFileHandle.write(line) 214 | 215 | 216 | def writeDebugWEB_PAGE(self, data): 217 | line = "\n*---\nTotal WEB_PAGE (deleted) " + str(data.WEB_PAGEtotal) 218 | line += ' (' + str(data.WEB_PAGEdeleted) + ')' 219 | line += '\n*---' 220 | self.dFileHandle.write(line) 221 | for i in range(data.WEB_PAGEtotal): 222 | line = '\n[id] ' + data.WEB_PAGEid[i] 223 | line += '\n\t[source] ' + data.WEB_PAGEsource[i] 224 | line += '\n\t[url] ' + data.WEB_PAGEurl[i] 225 | line += '\n\t[title] ' + data.WEB_PAGEtitle[i] 226 | line += '\n\t[visitCount] ' + data.WEB_PAGEvisitCount[i] 227 | line += '\n\t[lastVisited] ' + data.WEB_PAGElastVisited[i] 228 | self.dFileHandle.write(line) 229 | 230 | def closeDebug(self): 231 | self.dFileHandle.close() 232 | 233 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /UFED_case_generator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | #--- 4 | # CASE_generate.py: 5 | # generate the JSON file pieces (Observables) that compose the final JSON-LD CASE file 6 | # 7 | 8 | import json 9 | from datetime import datetime 10 | from uuid import uuid4 11 | from datetime import datetime 12 | 13 | class ObjectCore(dict): 14 | 15 | def __init__(self): 16 | super().__init__() 17 | 18 | def _set_properties_str(self, **kwargs): 19 | for key, var in kwargs.items(): 20 | if isinstance(var, str): 21 | self[key] = var 22 | else: 23 | self.__handle_var_type_errors(key, var, 'str') 24 | 25 | def _set_properties_float(self, **kwargs): 26 | for key, var in kwargs.items(): 27 | if isinstance(var, float): 28 | self[key] = {"@type": "xsd:decimal", "@value": str(var)} 29 | else: 30 | self.__handle_var_type_errors(key, var, 'float') 31 | 32 | def _set_properties_int(self, **kwargs): 33 | for key, var in kwargs.items(): 34 | if isinstance(var, int): 35 | self[key] = {"@type": "xsd:integer", "@value": str(var)} 36 | else: 37 | self.__handle_var_type_errors(key, var, 'int') 38 | 39 | def _set_properties_bool(self, **kwargs): 40 | for key, var in kwargs.items(): 41 | if isinstance(var, bool): 42 | self[key] = {"@type": "xsd:boolean", "@value": var} 43 | else: 44 | self.__handle_var_type_errors(key, var, 'bool') 45 | 46 | def _set_properties_date_time(self, **kwargs): 47 | for key, var in kwargs.items(): 48 | if isinstance(var, datetime): 49 | tz_info = var.strftime("%z") 50 | iso_format = var.isoformat() if tz_info else var.isoformat() + '+00:00' 51 | self[key] = {"@type": "xsd:dateTime", "@value": iso_format} 52 | else: 53 | self.__handle_var_type_errors(key, var, 'date time') 54 | 55 | def _set_properties_id_reference(self, **kwargs): 56 | for key, var in kwargs.items(): 57 | if var is not None: 58 | self[key] = {'@id': var.get_id()} 59 | 60 | def _set_properties_list_id_reference(self, **kwargs): 61 | for key, var in kwargs.items(): 62 | if var is not None: 63 | self[key] = [{'@id': item.get_id()} for item in var] 64 | 65 | def _set_properties_list_id_reference_array(self, **kwargs): 66 | for key, var in kwargs.items(): 67 | if var is not None: 68 | # print(f"key={key}") 69 | # print(f"var={var}") 70 | self[key] = [{'@id': var.get_id()}] 71 | 72 | def __str__(self): 73 | return json.dumps(self, indent=4) 74 | 75 | def __handle_var_type_errors(self, var_name, var_val, expected_type): 76 | if var_val is None: 77 | pass 78 | else: 79 | print(f"Value provided for {var_name} is not of type {expected_type}: value provided: {var_val}") 80 | raise TypeError 81 | 82 | def _add_reference_list_vars(self, **kwargs): 83 | pass 84 | 85 | 86 | def get_id(self): 87 | return self["@id"] 88 | 89 | def append_to_uco_object(self, *args): 90 | for item in args: 91 | #self[self.root].append(item) 92 | self["uco-core:object"].append(item) 93 | 94 | class Bundle(ObjectCore): 95 | 96 | def __init__(self, uco_core_name=None, spec_version=None, description=None, 97 | root="uco-core:object"): 98 | """ 99 | The header of the JSON and the CASE Object container (root) of Observables. 100 | """ 101 | super().__init__() 102 | #self.build = [] # ??? 103 | case_identifier = 'bundle-' + str(uuid4()) 104 | self["@context"] = { 105 | "@vocabulary":"http://example.org/kb/", 106 | "kb": "http://example.org/kb/", 107 | "drafting":"http://example.org/ontology/drafting/", 108 | "co": "http://purl.org/co/", 109 | "case-investigation":"https://ontology.caseontology.org/case/investigation/", 110 | "uco-action":"https://ontology.unifiedcyberontology.org/uco/action/", 111 | "uco-core":"https://ontology.unifiedcyberontology.org/uco/core/", 112 | "uco-identity":"https://ontology.unifiedcyberontology.org/uco/identity/", 113 | "uco-role":"https://ontology.unifiedcyberontology.org/uco/role/", 114 | "uco-location":"https://ontology.unifiedcyberontology.org/uco/location/", 115 | "uco-observable":"https://ontology.unifiedcyberontology.org/uco/observable/", 116 | "uco-tool":"https://ontology.unifiedcyberontology.org/uco/tool/", 117 | "uco-types":"https://ontology.unifiedcyberontology.org/uco/types/", 118 | "uco-vocabulary":"https://ontology.unifiedcyberontology.org/uco/vocabulary/", 119 | "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", 120 | "rdfs": "http://www.w3.org/2000/01/rdf-schema#", 121 | "xsd": "http://www.w3.org/2001/XMLSchema#" 122 | } 123 | 124 | self["@type"] = "uco-core:Bundle" 125 | # self._set_properties_str(**{"uco-core:account_name": uco_core_name, 126 | # 'uco-core:specVersion': spec_version, 127 | # 'uco-core:description': description, 128 | # '@id': case_identifier}) 129 | self._set_properties_str(**{'@id': case_identifier}) 130 | self.root = root 131 | self[self.root] = list() 132 | 133 | #def append_object_to_root(self, *args): 134 | #for items in args: 135 | #self["uco-core:object"].append(item) 136 | 137 | class ObjectFacet(ObjectCore): 138 | def __init__(self): 139 | super().__init__() 140 | # each Facet/@type require to have IRIs (`@id`s) 141 | self["@id"] = "kb:" + str(uuid4()) 142 | 143 | 144 | class ObjectObservable(ObjectCore): 145 | 146 | def __init__(self, object_class="uco-observable:ObservableObject"): 147 | """ 148 | An observable object contains Facet, a group of unique features that characterises a 149 | Cyber item / Digital vestige. 150 | :param facets: the dictionary representing the Cyber item 151 | """ 152 | super().__init__() 153 | self["@id"] = "kb:" + str(uuid4()) 154 | self["@type"] = object_class 155 | self["uco-core:hasFacet"] = list() 156 | 157 | def append_facets(self, *facets): 158 | for facet in facets: 159 | self["uco-core:hasFacet"].append(facet) 160 | 161 | 162 | class ObjectSpecial(ObjectCore): 163 | def __init__(self): 164 | super().__init__() 165 | self["@id"] = "kb:" + str(uuid4()) 166 | 167 | class Relationship(ObjectSpecial): 168 | def __init__(self, source=None, target=None, kind_of_relationship=None, start_time=None, end_time=None, 169 | directional=None): 170 | super().__init__() 171 | self["@type"] = "uco-observable:ObservableRelationship" 172 | self._set_properties_str(**{"uco-core:kindOfRelationship": kind_of_relationship}) 173 | self._set_properties_bool(**{"uco-core:isDirectional": directional}) 174 | self._set_properties_date_time(**{"uco-observable:startTime": start_time, 175 | "uco-observable:endTime": end_time, 176 | }) 177 | self._set_properties_id_reference(**{"uco-core:source": source, 178 | "uco-core:target": target}) 179 | 180 | class ProvenanceRecord(ObjectSpecial): 181 | def __init__(self, exhibit_number=None, uco_core_objects=None): 182 | super().__init__() 183 | self['@type'] = 'case-investigation:ProvenanceRecord' 184 | self._set_properties_str(**{"case-investigation:exhibitNumber": exhibit_number}) 185 | self._set_properties_list_id_reference(**{"uco-core:object": uco_core_objects}) 186 | 187 | class ObjectInfo(ObjectCore): 188 | 189 | def __init__(self, name="", version="", description=""): 190 | """ 191 | An observable object contains Facet, a group of unique features that characterises a 192 | Cyber item / Digital vestige. This is for storing info about name, 193 | description and version o fthe bundle 194 | """ 195 | super().__init__() 196 | self["@id"] = "kb:" + str(uuid4()) 197 | self["@type"] = "uco-observable:ObservableObject" 198 | self["uco-core:name"] = name 199 | self["uco-core:description"] = description 200 | self["rdfs:comment"] = "version: " + version 201 | 202 | class Account(ObjectFacet): 203 | 204 | def __init__(self, identifier=None, is_active=True, issuer_id=None): 205 | """ 206 | Used to represent user accounts 207 | :param is_active: Active unless specified otherwise (False) 208 | :param identifier: The idenitifier of the account (like a Skype username) 209 | :param issuer_id: The id of issuing body for application 210 | (e.g., kb:organization-skypeapp-cc44c2ae-bdd3-4df8-9ca3-1f58d682d62b) 211 | """ 212 | super().__init__() 213 | self._set_properties_str(**{"@type": "uco-observable:AccountFacet", 214 | "uco-observable:accountIdentifier": identifier}) 215 | self._set_properties_id_reference(**{"uco-observable:accountIssuer": issuer_id}) 216 | 217 | self._set_properties_bool(**{"uco-observable:isActive": is_active}) 218 | 219 | 220 | class ContentData(ObjectFacet): 221 | 222 | def __init__(self, byte_order=None, magic_number=None, mime_type=None, size_bytes=None, data_payload=None, 223 | entropy=None, is_encrypted=None, hash_method=None, hash_value=None): 224 | """ 225 | The characteristics of a block of digital data. 226 | :param byte_order: Byte order of data. Example - "BigEndian" 227 | :param magic_number: The magic phone_number of a file 228 | :param mime_type: The mime type of a file. Example - "image/jpg" 229 | :param size_bytes: A phone_number representing the size of the content 230 | :param data_payload: A base64 representation of the data 231 | :param entropy: The entropy value for the data 232 | :param is_encrypted: A boolean True/False, if encrypted or not. 233 | :param hash_method: The algorithm used to calculate the hash value 234 | :param hash_value: The cryptographic hash of this content 235 | """ 236 | super().__init__() 237 | self["@type"] = "uco-observable:ContentDataFacet" 238 | self._set_properties_str(**{"uco-observable:byteOrder": byte_order, 239 | "uco-observable:magicNumber": magic_number, 240 | "uco-observable:mimeType": mime_type, 241 | "uco-observable:dataPayload": data_payload, 242 | "uco-observable:entropy": entropy, 243 | "uco-observable:sizeInBytes": size_bytes, 244 | "uco-observable:isEncrypted": is_encrypted}) 245 | 246 | if hash_method is not None or hash_value is not None or hash_value != "-": 247 | data = {"@type": "uco-types:Hash", "@id": "kb:" + str(uuid4())} 248 | if hash_method is not None: 249 | data["uco-types:hashMethod"] = {"@type": "uco-vocabulary:HashNameVocab", 250 | "@value": hash_method} 251 | if hash_value is not None: 252 | data["uco-types:hashValue"] = {"@type": "xsd:hexBinary", "@value": hash_value} 253 | self["uco-observable:hash"] = [data] 254 | 255 | 256 | class Application(ObjectFacet): 257 | 258 | def __init__(self, app_name=None, app_identifier=None, installed_version_history=None, num_launches=None, os=None, version=None): 259 | """ 260 | A simple application 261 | :param app_name: Name of application (e.g. Native, Facebook, WhatsApp, etc.) 262 | """ 263 | super().__init__() 264 | self["@type"] = "uco-observable:ApplicationFacet" 265 | self._set_properties_str(**{"uco-core:name": app_name, 266 | "uco-observable:applicationIdentifier": app_identifier, 267 | "uco-observable:version": version, 268 | "uco-observable:operatingSystem": os}) 269 | self._set_properties_int(**{"uco-observable:numberOfLaunches": num_launches}) 270 | self._set_properties_id_reference(**{"uco-observable:installedVersionHistory": installed_version_history}) 271 | 272 | class ApplicationVersion(ObjectFacet): 273 | """ 274 | A simple application version to manage the installed application 275 | :param install_date: The date when the application was installed/purchased on the device 276 | """ 277 | def __init__(self, install_date): 278 | """ 279 | A simple application 280 | :param install_date: installation date of an application 281 | """ 282 | super().__init__() 283 | self["@type"] = "uco-observable:ApplicationVersion" 284 | self._set_properties_date_time(**{"uco-observable:installDate": install_date}) 285 | 286 | class DataRange(ObjectFacet): 287 | 288 | def __init__(self, range_offset=None, range_size=None): 289 | """ 290 | A data range facet is a grouping of characteristics unique to a particular contiguous scope 291 | within a block of digital data 292 | :param range_offset: location in data at which the contiguous data starts 293 | :param range_size: the length of the data starting at the offset point 294 | """ 295 | super().__init__() 296 | self["@type"] = "uco-observable:DataRangeFacet" 297 | self._set_properties_str(**{"uco-observable:rangeOffset": range_offset, 298 | "uco-observable:rangeSize": range_size}) 299 | 300 | 301 | class Device(ObjectFacet): 302 | 303 | def __init__(self, device_type=None, manufacturer=None, model=None, serial=None): 304 | """ 305 | Characteristics of a piece of electronic equipment. 306 | :param device_type: The type of device (e.g., "camera") 307 | :param manufacturer: The producer of the device (e.g., "Canon") 308 | :param model: The model of the device (e.g., "Powershot SX540") 309 | :param serial: The serial phone_number of the device (e.g., "1296-3219-8792-CL918") 310 | """ 311 | super().__init__() 312 | self["@type"] = "uco-observable:DeviceFacet" 313 | self._set_properties_str(**{"uco-observable:deviceType": device_type, 314 | "uco-observable:manufacturer": manufacturer, 315 | "uco-observable:model": model, 316 | "uco-observable:serialNumber": serial}) 317 | 318 | 319 | class WifiAddress(ObjectFacet): 320 | 321 | def __init__(self, wifi_mac_address=None): 322 | """ 323 | :param wifi_mac_address: The wifi mac address of a device (EG: 11:54:00:bc:c8:ba) 324 | """ 325 | super().__init__() 326 | self["@type"] = "uco-observable:WifiAddressFacet" 327 | self._set_properties_str(**{"uco-observable:addressValue": wifi_mac_address}) 328 | 329 | 330 | class BrowserBookmark(ObjectFacet): 331 | def __init__(self, bookmark_source=None, url=None, bookmark_path=None, bookmark_accessed_time=None): 332 | """ 333 | :param source: 334 | :param url: 335 | :param path: 336 | :param manually_entered_count: 337 | :param accessed_time: An observable object with a URLFacet 338 | """ 339 | super().__init__() 340 | 341 | self['@type'] = 'uco-observable:BrowserBookmarkFacet' 342 | 343 | self._set_properties_str(**{'uco-observable:bookmarkPath': bookmark_path}) 344 | self._set_properties_date_time(**{'uco-observable:observableCreatedTime': bookmark_accessed_time}) 345 | self._set_properties_id_reference(**{'uco-observable:application':bookmark_source, 'uco-observable:urlTargeted': url}) 346 | 347 | class BluetoothAddress(ObjectFacet): 348 | 349 | def __init__(self, name=None, address=None): 350 | """ 351 | :param name: 352 | :param address: The Bluetooth address value (e.g. "D4:A3:3D:B5:F4:6C") 353 | """ 354 | super().__init__() 355 | self["@type"] = "uco-observable:BluetoothAddressFacet" 356 | self._set_properties_str(**{'uco-core:name': name, 357 | 'uco-observable:addressValue': address}) 358 | 359 | 360 | class UrlHistory(ObjectFacet): 361 | 362 | def __init__(self, browser=None, history_entries=None): 363 | """ 364 | :param browser_info: An observable object containing a URLHistoryFacet 365 | :param history_entries: A list of URLHistoryEntry types 366 | """ 367 | 368 | super().__init__() 369 | self["@type"] = "uco-observable:URLHistoryFacet" 370 | self._set_properties_id_reference(**{'uco-observable:browserInformation': browser}) 371 | #self.append_history_entries(history_entries) 372 | 373 | #def append_history_entries(self, entries): 374 | #""" 375 | #Used to add history entries to this URL History facet 376 | #:param args: A single/tuple of URLHistoryEntry class types 377 | #""" 378 | ##for entry in entries: 379 | #self["uco-core:hasFacet"].append(history_entries) 380 | 381 | 382 | class UrlHistoryEntry(ObjectFacet): 383 | 384 | def __init__(self, first_visit=None, last_visit=None, expiration_time=None, manually_entered_count=None, url=None, 385 | user_profile=None, page_title=None, referrer_url=None, visit_count=None, keyword_search_term=None, 386 | allocation_status=None, browser=None): 387 | """ 388 | :param first_visit: 389 | :param last_visit: 390 | :param expiration_time: 391 | :param manually_entered_count: 392 | :param url: An observable object with a URLFacet 393 | :param user_profile: 394 | :param page_title: 395 | :param referrer_url: 396 | :param visit_count: 397 | :param keyword_search_term: 398 | :param allocation_status: 399 | """ 400 | 401 | super().__init__() 402 | 403 | self['@type'] = 'uco-observable:URLHistoryFacet' 404 | 405 | #self._set_properties_id_reference(**{'uco-observable:browserInformation': browser}) 406 | self['uco-observable:browserInformation'] = {'@id': browser.get_id()} 407 | 408 | # self._set_properties_str(**{'uco-observable:userProfile': user_profile, # todo: referral? 409 | # 'uco-observable:pageTitle': page_title, 410 | # 'uco-observable:referrerUrl': referrer_url, 411 | # 'uco-observable:keywordSearchTerm': keyword_search_term, 412 | # 'uco-observable:allocationStatus': allocation_status}) 413 | # self._set_properties_int(**{'uco-observable:visitCount': visit_count, 414 | # 'uco-observable:manuallyEnteredCount': manually_entered_count}) 415 | # self._set_properties_date_time(**{'uco-observable:firstVisit': first_visit, 416 | # 'uco-observable:lastVisit': last_visit, 417 | # 'uco-observable:expirationTime': expiration_time}) 418 | # self._set_properties_id_reference(**{'uco-observable:url': url}) 419 | 420 | 421 | if first_visit: 422 | tz_info = first_visit.strftime("%z") 423 | first_iso_format = first_visit.isoformat() if tz_info else first_visit.isoformat() + '+00:00' 424 | else: 425 | first_iso_format = '1900-01-01T08:00:00+00:00' 426 | 427 | if last_visit: 428 | tz_info = last_visit.strftime("%z") 429 | last_iso_format = last_visit.isoformat() if tz_info else last_visit.isoformat() + '+00:00' 430 | else: 431 | last_iso_format = '1900-01-01T08:00:00+00:00' 432 | 433 | self['uco-observable:urlHistoryEntry'] = [] 434 | self['uco-observable:urlHistoryEntry'].append( 435 | {'@id': "kb:" + str(uuid4()), 436 | '@type': 'uco-observable:URLHistoryEntry', 437 | 'uco-observable:firstVisit': {"@type": "xsd:dateTime", "@value": first_iso_format}, 438 | 'uco-observable:lastVisit': {"@type": "xsd:dateTime", "@value": last_iso_format}, 439 | 'uco-observable:pageTitle': page_title, 440 | 'uco-observable:url': {'@id': url.get_id()}, 441 | 'uco-observable:visitCount': {"@type": "xsd:integer", "@value": visit_count}, 442 | 'uco-observable:allocationStatus': allocation_status, 443 | 'uco-observable:keywordSearchTerm': keyword_search_term}) 444 | 445 | 446 | class Url(ObjectFacet): 447 | 448 | def __init__(self, url_address=None, url_port=None, url_host=None, url_fragment=None, url_password=None, 449 | url_path=None, url_query=None, url_scheme=None, url_username=None): 450 | """ 451 | :param url_address: an address of a url (i.e. google.ie) 452 | :param url_port: a tcp or udp port of a url for example 3000 453 | :param url_host: the Ip address of a host that was requested (e.g.192.168.1.1 could be your home router) 454 | :param url_fragment: A fragment of a url pointing to a specific resource (i.e subdomain=api) 455 | :param url_password: A password that may be used in authentication scheme for accessing restricted resources 456 | :param url_path: the location that may have resources available e.g. /chatapp 457 | :param url_query: a query that may be used with a resource such as an api e.g. ?health 458 | :param url_scheme: Identifies the type of URL. (e.g. ssh://) 459 | :param url_username: A username that may be required for authentication for a specific resource. (login) 460 | """ 461 | super().__init__() 462 | self["@type"] = "uco-observable:URLFacet" 463 | self._set_properties_str(**{"uco-observable:fullValue": url_address, 464 | "uco-observable:host": url_host, 465 | "uco-observable:fragment": url_fragment, 466 | "uco-observable:password": url_password, 467 | "uco-observable:path": url_path, 468 | "uco-observable:query": url_query, 469 | "uco-observable:scheme": url_scheme, 470 | "uco-observable:userName": url_username}) 471 | self._set_properties_int(**{"uco-observable:port": url_port}) 472 | 473 | 474 | class RasterPicture(ObjectFacet): 475 | 476 | def __init__(self, camera_id=None, bits_per_pixel=None, picture_height=None, picture_width=None, 477 | image_compression_method=None, picture_type=None): 478 | """ 479 | This CASEObject represents the contents of a file or device 480 | :param camera_id: An observable cyberitem 481 | :param bits_per_pixel: The phone_number (integer) of bits per pixel 482 | :param picture_height: The height of a picture (integer) 483 | :param picture_width: The width of a picture (integer) 484 | :param image_compression_method: The compression method used 485 | :param picture_type: The type of picture ("jpg", "png" etc.) 486 | """ 487 | super().__init__() 488 | self["@type"] = "uco-observable:RasterPictureFacet" 489 | self._set_properties_str(**{"uco-observable:imageCompressionMethod": image_compression_method, 490 | "uco-observable:pictureType": picture_type, 491 | "uco-observable:pictureHeight": picture_height, 492 | "uco-observable:pictureWidth": picture_width, 493 | "uco-observable:bitsPerPixel": bits_per_pixel}) 494 | self._set_properties_id_reference(**{"uco-observable:camera": camera_id}) 495 | 496 | 497 | class PhoneCall(ObjectFacet): 498 | 499 | def __init__(self, call_type=None, start_time=None, application=None, call_from=None, 500 | call_to=None, call_duration=None, allocation_status=None): 501 | """ 502 | :param call_type: incoming outgoing etc 503 | :param start_time: the time at which the device registered the call as starting 504 | :param application: ObjectObservable with call-application (e.g. WhatsApp) facet-info 505 | :param call_from: ObjectObservable with person/caller facet-info 506 | :param call_to: ObjectObservable with person/caller facet-info 507 | :param call_duration: how long the call was registedred on the device as lasting in minutes (E.G. 60) 508 | :param allocation_status: The allocation status of the record of the call i.e intact for records that are 509 | present on the device 510 | """ 511 | super().__init__() 512 | self["@type"] = "uco-observable:PhoneCallFacet" 513 | self._set_properties_str(**{"uco-observable:callType": call_type, 514 | "uco-observable:allocationStatus": allocation_status}) 515 | self._set_properties_int(**{"uco-observable:duration": call_duration}) 516 | self._set_properties_date_time(**{"uco-observable:startTime": start_time}) 517 | self._set_properties_id_reference(**{"uco-observable:application": application, 518 | "uco-observable:from": call_from, 519 | "uco-observable:to": call_to}) 520 | 521 | class Call(ObjectFacet): 522 | 523 | def __init__(self, call_type=None, start_time=None, application=None, call_from=None, 524 | call_to=None, call_duration=None, allocation_status=None): 525 | """ 526 | :param call_type: incoming outgoing etc 527 | :param start_time: the time at which the device registered the call as starting 528 | :param application: ObjectObservable with call-application (e.g. WhatsApp) facet-info 529 | :param call_from: ObjectObservable with person/caller facet-info 530 | :param call_to: ObjectObservable with person/caller facet-info 531 | :param call_duration: how long the call was registedred on the device as lasting in minutes (E.G. 60) 532 | :param allocation_status: The allocation status of the record of the call i.e intact for records that are 533 | present on the device 534 | """ 535 | super().__init__() 536 | self["@type"] = "uco-observable:CallFacet" 537 | self._set_properties_str(**{"uco-observable:callType": call_type, 538 | "uco-observable:allocationStatus": allocation_status}) 539 | self._set_properties_int(**{"uco-observable:duration": call_duration}) 540 | self._set_properties_date_time(**{"uco-observable:startTime": start_time}) 541 | self._set_properties_id_reference(**{"uco-observable:application": application, 542 | "uco-observable:from": call_from, 543 | "uco-observable:to": call_to}) 544 | 545 | 546 | class PhoneAccount(ObjectFacet): 547 | 548 | def __init__(self, phone_number=None, account_name=None): 549 | """ 550 | 551 | :param phone_number: The number for this account (e.g., "+16503889249") 552 | :param account_name: The name of this account/user (e.g., "Bill Bryson") 553 | """ 554 | super().__init__() 555 | self["@type"] = "uco-observable:PhoneAccountFacet" 556 | self._set_properties_str(**{"uco-observable:phoneNumber": phone_number, 557 | "uco-observable:displayName": account_name}) 558 | 559 | 560 | class EmailAccount(ObjectFacet): 561 | 562 | def __init__(self, email_address): 563 | """ 564 | :param email_address: An ObjectObservable (with EmailAdressFacet) 565 | """ 566 | super().__init__() 567 | self["@type"] = "uco-observable:EmailAccountFacet" 568 | self._set_properties_id_reference(**{"uco-observable:emailAddress": email_address}) 569 | 570 | 571 | class EmailAddress(ObjectFacet): 572 | 573 | def __init__(self, email_address_value=None, display_name=None): 574 | """ 575 | Used to represent the value of an email address. 576 | :param email_address_value: a single email address (e.g., "bob@example.com") 577 | """ 578 | super().__init__() 579 | self["@type"] = "uco-observable:EmailAddressFacet" 580 | self._set_properties_str(**{"uco-observable:addressValue": email_address_value, 581 | "uco-core:displayName": display_name}) 582 | 583 | 584 | class EmailMessage(ObjectFacet): 585 | 586 | def __init__(self, msg_to=None, msg_from=None, cc=None, bcc=None, subject=None, body=None, received_time=None, 587 | sent_time=None, modified_time=None, other_headers=None, application=None, body_raw=None, 588 | header_raw=None, in_reply_to=None, sender=None, x_originating_ip=None, is_read=None, 589 | content_disposition=None, content_type=None, message_id=None, priority=None, x_mailer=None, 590 | is_mime_encoded=None, allocation_status=None, is_multipart=None): 591 | """ 592 | An instance of an email message, corresponding to the internet message format described in RFC 5322 and related. 593 | :param msg_to: A list of ObjectObservables (with EmailAccountFacet) 594 | :param msg_from: An ObjectObservable (with EmailAccountFacet) 595 | :param cc: A list of ObjectObservables (with EmailAccountFacet) in carbon copy 596 | :param bcc: A list of ObjectObservables (with EmailAccountFacet) in blind carbon copy 597 | :param subject: The subject of the email. 598 | :param body: The content of the email. 599 | :param received_time: The time received, in ISO8601 time format (e.g., "2020-09-29T12:13:01Z") 600 | :param sent_time: The time sent, in ISO8601 time format (e.g., "2020-09-29T12:13:01Z") 601 | :param modified_time: The time modified, in ISO8601 time format (e.g., "2020-09-29T12:13:01Z") 602 | :param other_headers: A dictionary of other headers 603 | :param application: The application associated with this object. 604 | :param body_raw: 605 | :param header_raw: 606 | :param in_reply_to: One of more unique identifiers for identifying the email(s) this email is a reply to. 607 | :param sender: ??? 608 | :param x_originating_ip: 609 | :param is_read: A boolean True/False 610 | :param content_disposition: 611 | :param content_type: 612 | :param message_id: A unique identifier for the message. 613 | :param priority: The priority of the email. 614 | :param x_mailer: 615 | :param is_mime_encoded: A boolean True/False 616 | :param is_multipart: A boolean True/False 617 | :param allocation_status: 618 | """ 619 | super().__init__() 620 | self["@type"] = "uco-observable:EmailMessageFacet" 621 | self._set_properties_str(**{"uco-observable:subject": subject, 622 | "uco-observable:body": body, 623 | "uco-observable:otherHeaders": other_headers, 624 | "uco-observable:bodyRaw": body_raw, 625 | "uco-observable:headerRaw": header_raw, 626 | "uco-observable:contentDisposition": content_disposition, 627 | "uco-observable:contentType": content_type, 628 | "uco-observable:messageID": message_id, 629 | "uco-observable:priority": priority, 630 | "uco-observable:xMailer": x_mailer, 631 | "uco-observable:allocationStatus": allocation_status, 632 | "uco-observable:receivedTime": received_time, 633 | "uco-observable:modifiedTime": modified_time, 634 | "uco-observable:isRead": is_read, 635 | "uco-observable:isMimeEncoded": is_mime_encoded, 636 | "uco-observable:isMultipart": is_multipart}) 637 | self._set_properties_date_time(**{"uco-observable:sentTime": sent_time}) 638 | self._set_properties_list_id_reference(**{"uco-observable:to": msg_to, 639 | "uco-observable:cc": cc, 640 | "uco-observable:bcc": bcc, 641 | "uco-observable:inReplyTo": in_reply_to, 642 | "uco-observable:sender": sender, 643 | "uco-observable:xOriginatingIP": x_originating_ip, 644 | "uco-observable:application": application}) 645 | self._set_properties_id_reference(**{"uco-observable:from": msg_from}) 646 | 647 | 648 | class EXIF(ObjectFacet): 649 | 650 | def __init__(self, **kwargs): 651 | """ 652 | Specifies exchangeable image file format (Exif) metadata tags for image and sound files recorded by digital cameras. 653 | :param kwargs: The user provided key/value pairs of exif items (e.g., Make="Canon", etc.). 654 | """ 655 | super().__init__() 656 | self["@type"] = "uco-observable:EXIFFacet" 657 | 658 | self["uco-observable:exifData"] = {"@type": "uco-types:ControlledDictionary", "uco-types:entry": []} 659 | for k, v in kwargs.items(): 660 | if v not in ["", " "]: 661 | item = {"@type": "uco-types:ControlledDictionaryEntry", "uco-types:key": k, "uco-types:value": v} 662 | self["uco-observable:exifData"]["uco-types:entry"].append(item) 663 | 664 | 665 | class ExtInode(ObjectFacet): 666 | 667 | def __init__(self, deletion_time=None, inode_change_time=None, file_type=None, flags=None, hard_link_count=None, 668 | inode_id=None, permissions=None, sgid=None, suid=None): 669 | """ 670 | An instance of an email message, corresponding to the internet message format described in RFC 5322 and related. 671 | :param deletion_time: Specifies the time at which the file represented by an Inode was 'deleted'. 672 | :param inode_change_time: The date and time at which the file Inode metadata was last modified. 673 | :param file_type: Specifies the EXT file type (FIFO, Directory, Regular file, Symbolic link, etc) for the Inode. 674 | :param flags: Specifies user flags to further protect (limit its use and modification) the file represented by an Inode. 675 | :param hard_link_count: Specifies a count of how many hard links point to an Inode. 676 | :param inode_id: Specifies a single Inode identifier. 677 | :param permissions: Specifies the read/write/execute permissions for the file represented by an EXT Inode. 678 | :param sgid: Specifies the group ID for the file represented by an Inode. 679 | :param suid: Specifies the user ID that 'owns' the file represented by an Inode. 680 | """ 681 | super().__init__() 682 | self["@type"] = "uco-observable:ExtInodeFacet" 683 | self._set_properties_str(**{"uco-observable:extFileType": file_type, 684 | "uco-observable:extFlags": flags, 685 | "uco-observable:extHardLinkCount": hard_link_count, 686 | "uco-observable:extPermissions": permissions, 687 | }) 688 | self._set_properties_int(**{"uco-observable:extSGID": sgid, 689 | "uco-observable:extSUID": suid, 690 | "uco-observable:extInodeID": inode_id}) 691 | self._set_properties_date_time(**{"uco-observable:extDeletionTime": deletion_time, 692 | "uco-observable:extInodeChangeTime": inode_change_time}) 693 | 694 | 695 | class CalendarEntry(ObjectFacet): 696 | 697 | def __init__(self, group=None, subject=None, details=None, start_time=None, end_time=None, repeat_until=None, 698 | repeat_interval=None, status=None, private=None, recurrence=None, remind_time=None, 699 | attendants=None): 700 | super().__init__() 701 | self["@type"] = "uco-observable:CalendarEntryFacet" 702 | self._set_properties_str(**{"drafting:group": group, 703 | "uco:observable:subject": subject, 704 | "drafting:details": details, 705 | "drafting:repeatInterval": repeat_interval, # todo: type? 706 | 'uco-observable:eventStatus': status, 707 | 'uco-observable:recurrence': recurrence, 708 | 'uco-observable:remindTime': remind_time, 709 | "drafting:repeatUntil": repeat_until, 710 | 'uco:observable:isPrivate': private}) 711 | self._set_properties_date_time(**{"uco-observable:startTime": start_time, 712 | "uco-observable:endTime": end_time}) 713 | #self.append_attendants(attendants) 714 | 715 | 716 | # def append_attendants(self, *args): 717 | # self._append_observable_objects("uco-observable:attendant", *args) 718 | 719 | 720 | class BrowserCookie(ObjectFacet): 721 | 722 | def __init__(self, source=None, name=None, path=None, domain=None, created_time=None, 723 | last_access_time=None, expiration_time=None, secure=None): 724 | super().__init__() 725 | self["@type"] = "uco-observable:BrowserCookieFacet" 726 | self._set_properties_str(**{'uco-observable:cookieName': name, 727 | "uco-observable:cookiePath": path, 728 | 'uco-observable:isSecure': secure}) 729 | self._set_properties_date_time(**{'uco-observable:observableCreatedTime': created_time, 730 | "uco-observable:accessedTime": last_access_time, 731 | 'uco-observable:expirationTime': expiration_time}) 732 | self._set_properties_id_reference(**{"drafting:source": source, 733 | 'uco-observable:cookieDomain': domain}) 734 | 735 | 736 | class File(ObjectFacet): 737 | 738 | def __init__(self, file_system_type=None, file_name=None, file_path=None, file_local_path=None, 739 | file_extension=None, 740 | size_bytes=None, accessed_time=None, created_time=None, modified_time=None, 741 | metadata_changed_time=None, 742 | tag=None): 743 | """ 744 | The basic properties associated with the storage of a file on a file system. 745 | :param file_system_type: The specific type of a file system (e.g., "EXT4") 746 | :param file_name: Specifies the account_name associated with a file in a file system (e.g., "IMG_0123.jpg"). 747 | :param file_path: Specifies the file path for the location of a file within a filesystem. (e.g., "/sdcard/IMG_0123.jpg") 748 | :param file_extension: The file account_name extension. Not present if the file has no dot in its account_name. (e.g., "jpg"). 749 | :param size_bytes: The size of the data in bytes (e.g., integer like 35125) 750 | :param accessed_time: The datetime the file was last accessed 751 | :param created_time: The datetime the file was created 752 | :param modified_time: The datetime the file was last modified 753 | :param metadata_changed_time: The last change to metadata of a file but not necessarily the file contents 754 | :param tag: A generic (string) tag/label, or a list/tuple of (strings) tags/labels. 755 | """ 756 | super().__init__() 757 | self["@type"] = "uco-observable:FileFacet" 758 | self._set_properties_str(**{"uco-observable:fileSystemType": file_system_type, 759 | "uco-observable:fileName": file_name, 760 | "uco-observable:filePath": file_path, 761 | "drafting:fileLocalPath": file_local_path, 762 | "uco-observable:extension": file_extension, 763 | "uco-observable:mimeType": tag, 764 | "uco-observable:metadataChangeTime": metadata_changed_time}) 765 | #self._set_properties_str(**{'uco-core:tag': tag}) 766 | #self['uco-core:tag'] = tag 767 | self._set_properties_date_time(**{"uco-observable:accessedTime": accessed_time, 768 | "uco-observable:observableCreatedTime": created_time, 769 | "uco-observable:modifiedTime": modified_time}) 770 | self._set_properties_int(**{"uco-observable:sizeInBytes": size_bytes}) 771 | 772 | 773 | class Message(ObjectFacet): 774 | 775 | def __init__(self, msg_to=None, msg_from=None, message_text=None, sent_time=None, 776 | application=None, message_type=None, message_id=None, session_id=None): 777 | """ 778 | Characteristics of an electronic message. 779 | :param msg_to: A list of ObjectObservables 780 | :param msg_from: An ObjectObservable 781 | :param message_text: The content of the email. 782 | :param sent_time: The time sent, in ISO8601 time format (e.g., "2020-09-29T12:13:01Z") 783 | :param application: The application associated with this object. 784 | :param message_type: 785 | :param message_id: A unique identifier for the message. 786 | :param session_id: The priority of the email. 787 | """ 788 | super().__init__() 789 | self["@type"] = "uco-observable:MessageFacet" 790 | self._set_properties_str(**{"uco-observable:messageText": message_text, 791 | "uco-observable:messageType": message_type, 792 | "uco-observable:messageID": message_id, 793 | "uco-observable:sessionID": session_id}) 794 | self._set_properties_date_time(**{"uco-observable:sentTime": sent_time}) 795 | self._set_properties_id_reference(**{"uco-observable:from": msg_from, 796 | "uco-observable:application": application}) 797 | self._set_properties_list_id_reference(**{"uco-observable:to": msg_to}) 798 | 799 | class SmsMessage(ObjectFacet): 800 | 801 | def __init__(self, msg_to=None, msg_from=None, message_text=None, sent_time=None, 802 | application=None, message_id=None, session_id=None): 803 | """ 804 | Characteristics of an electronic message. 805 | :param msg_to: A list of ObjectObservables 806 | :param msg_from: An ObjectObservable 807 | :param message_text: The content of the email. 808 | :param sent_time: The time sent, in ISO8601 time format (e.g., "2020-09-29T12:13:01Z") 809 | :param application: The application associated with this object. 810 | :param message_type: 811 | :param message_id: A unique identifier for the message. 812 | :param session_id: The priority of the email. 813 | """ 814 | super().__init__() 815 | self["@type"] = "uco-observable:SMSMessageFacet" 816 | self._set_properties_str(**{"uco-observable:messageText": message_text, 817 | "uco-observable:messageID": message_id, 818 | "uco-observable:sessionID": session_id}) 819 | self._set_properties_date_time(**{"uco-observable:sentTime": sent_time}) 820 | self._set_properties_id_reference(**{"uco-observable:from": msg_from, 821 | "uco-observable:application": application}) 822 | self._set_properties_list_id_reference(**{"uco-observable:to": msg_to}) 823 | 824 | class MobileDevice(ObjectFacet): 825 | 826 | def __init__(self, IMSI=None, ICCID=None, IMEI=None, storage_capacity=None, keypad_pin=None): 827 | """ 828 | The basic properties associated with a phone and phone account of a device or user. 829 | :param IMSI International mobile subscriber identity 830 | :param ICCID Integrated Circuit Card Identification Number 831 | :param IMEI international mobile equipment identity 832 | :param storage_capacity storage capacity of device in bytes 833 | """ 834 | super().__init__() 835 | self["@type"] = "uco-observable:MobileDeviceFacet" 836 | self._set_properties_str(**{"uco-observable:IMSI": IMSI, 837 | "uco-observable:ICCID": ICCID, 838 | "uco-observable:IMEI": IMEI}) 839 | self._set_properties_int(**{"uco-observable:storageCapacityInBytes": storage_capacity, 840 | "uco-observable:keypadUnlockCode": keypad_pin}) 841 | 842 | 843 | class OperatingSystem(ObjectFacet): 844 | 845 | def __init__(self, os_name=None, os_manufacturer=None, os_version=None, os_install_date=None): 846 | super().__init__() 847 | self["@type"] = "uco-observable:OperatingSystemFacet" 848 | self._set_properties_str(**{"uco-observable:displayName": os_name, 849 | "uco-observable:version": os_version}) 850 | self._set_properties_id_reference(**{"uco-observable:manufacturer": os_manufacturer}) 851 | self._set_properties_date_time(**{"uco-observable:installDate": os_install_date}) 852 | 853 | 854 | class PathRelation(ObjectFacet): 855 | 856 | def __init__(self, path): 857 | """ 858 | This CASE object specifies the location of one object within another containing object. 859 | :param path: The full path to the object (e.g, "/sdcard/IMG_0123.jpg") 860 | """ 861 | super().__init__() 862 | self["@type"] = "uco-observable:PathRelationFacet" 863 | self._set_properties_str(**{"uco-observable:path": path}) 864 | 865 | 866 | class Event(ObjectFacet): 867 | 868 | def __init__(self, event_type=None, event_text=None, event_id=None, cyber_action=None, computer_name=None, 869 | created_time=None, start_time=None, end_time=None): 870 | """ 871 | An event facet is a grouping of characteristics unique to something that happens in a digital context 872 | (e.g., operating system events). 873 | :param event_type: The type of the event, for example 'information', 'warning' or 'error'. 874 | :param event_text: The textual representation of the event. 875 | :param event_id: The identifier of the event. 876 | :param cyber_action: The action taken in response to the event. 877 | :param computer_name: A name of the computer on which the log entry was created. 878 | """ 879 | super().__init__() 880 | self["@type"] = "uco-observable:EventRecordFacet" 881 | self._set_properties_str(**{"uco-observable:eventType": event_type, 882 | "uco-observable:eventRecordText": event_text, 883 | "uco-observable:eventID": event_id, 884 | "uco-observable:computerName": computer_name}) 885 | self._set_properties_id_reference(**{'uco-observable:cyberAction': cyber_action}) 886 | self._set_properties_date_time(**{'uco-observable:observableCreatedTime': created_time, 887 | 'drafting:observableStartTime': start_time, 888 | 'drafting:observableEndTime': end_time}) 889 | 890 | 891 | # class ObservableRelationship(ObjectSpecial): 892 | 893 | # def __init__(self, source, target, start_time=None, end_time=None, kind_of_relationship=None, directional=None): 894 | # """ 895 | # This object represents an assertion that one or more objects are related to another object in some way 896 | # :param source: An observable object 897 | # :param target: An observable object 898 | # :param start_time: The time, in ISO8601 time format, the action was started (e.g., "2020-09-29T12:13:01Z") 899 | # :param end_time: The time, in ISO8601 time format, the action completed (e.g., "2020-09-29T12:13:43Z") 900 | # :param kind_of_relationship: How these items relate from source to target (e.g., "Contained_Within") 901 | # :param directional: A boolean representing ???? Usually set to True 902 | # """ 903 | # super().__init__() 904 | # self["@type"] = "uco-observable:ObservableRelationship" 905 | # self._bool_vars(**{"uco-core:isDirectional": directional}) 906 | # self._str_vars(**{"uco-core:kindOfRelationship": kind_of_relationship}) 907 | # self._datetime_vars(**{"uco-observable:startTime": start_time, 908 | # "uco-observable:endTime": end_time}) 909 | # self._node_reference_vars(**{"uco-core:source": source, 910 | # "uco-core:target": target}) 911 | 912 | # def set_start_accessed_time(self): 913 | # """Set the time when this action initiated.""" 914 | # self._addtime(_type='start') 915 | 916 | # def set_end_accessed_time(self): 917 | # """Set the time when this action completed.""" 918 | # self._addtime(_type='end') 919 | 920 | # def _addtime(self, _type): 921 | # time = datetime.now(timezone('UTC')) 922 | # self[f"uco-observable:{_type}Time"] = {"@type": "xsd:dateTime", "@value": time.isoformat()} 923 | 924 | 925 | class ApplicationAccount(ObjectFacet): 926 | 927 | def __init__(self, application=None): 928 | """ 929 | An application account facet is a grouping of characteristics unique to an account within a particular software 930 | program designed for end users. 931 | :param application: An Observable Object (containing an Application Facet) 932 | """ 933 | super().__init__() 934 | self["@type"] = "uco-observable:ApplicationAccountFacet" 935 | self._set_properties_id_reference(**{"uco-observable:application": application}) 936 | 937 | 938 | class DigitalAccount(ObjectFacet): 939 | 940 | def __init__(self, display_name=None, login=None, first_login_time=None, disabled=None, last_login_time=None): 941 | """ 942 | A digital account facet is a grouping of characteristics unique to an arrangement with an entity to enable and 943 | control the provision of some capability or service within the digital domain. 944 | """ 945 | super().__init__() 946 | self["@type"] = "uco-observable:DigitalAccountFacet" 947 | self._set_properties_str(**{"uco-observable:displayName": display_name, 948 | 'uco-observable:accountLogin': login}) 949 | self._set_properties_date_time(**{'uco-observable:firstLoginTime': first_login_time, 950 | 'uco-observable:lastLoginTime': last_login_time}) 951 | self._set_properties_bool(**{'uco-observable:isDisabled': disabled}) 952 | 953 | 954 | class WirelessNetworkConnection(ObjectFacet): 955 | 956 | def __init__(self, ssid=None, base_station=None): 957 | """ 958 | A wireless network connection facet is a grouping of characteristics unique to a connection (completed or 959 | attempted) across an IEEE 802.11 standards-conformant digital network (a group of two or more computer systems 960 | linked together). 961 | """ 962 | super().__init__() 963 | self["@type"] = "uco-observable:WirelessNetworkConnectionFacet" 964 | self._set_properties_str(**{"uco-observable:ssid": ssid, 965 | 'uco-observable:baseStation': base_station}) 966 | 967 | class Messagethread(ObjectFacet): 968 | 969 | def __init__(self, visibility=None, participants=None, display_name=None, 970 | messages=None, message_state=None, message_has_changed=None): 971 | """ 972 | A message thread facet is a grouping of characteristics unique to a running commentary of electronic messages 973 | pertaining to one topic or question. 974 | """ 975 | super().__init__() 976 | self["@type"] = "uco-observable:MessageThreadFacet" 977 | self._set_properties_str(**{"uco-observable:displayName": display_name}) 978 | self._set_properties_bool(**{'uco-observable:visibility': visibility}) 979 | self._set_properties_list_id_reference(**{'uco-observable:participant': participants}) 980 | 981 | self["uco-observable:messageThread"]=dict() 982 | self["uco-observable:messageThread"]["@id"]= "kb:" + str(uuid4()) 983 | self["uco-observable:messageThread"]["@type"] = "uco-types:Thread" 984 | self["uco-observable:messageThread"]["co:size"]= dict() 985 | self["uco-observable:messageThread"]["co:size"]["@type"] = "xsd:nonNegativeInteger" 986 | self["uco-observable:messageThread"]["co:size"]["@value"] = str(len(messages)) 987 | self["uco-observable:messageThread"]["co:element"]= list() 988 | for i, m in enumerate(messages): 989 | self["uco-observable:messageThread"]["co:element"].append({"@id":m.get_id()}) 990 | 991 | # def append_messages(self, messages): 992 | # self['uco-observable:message'].append_indexed_items(messages) 993 | 994 | # def append_participants(self, participants): 995 | # self._append_refs('uco-observable:participant', *participants) 996 | 997 | 998 | class MessageSMS(ObjectFacet): 999 | 1000 | def __init__(self, has_changed=None, state=None, indexed_items=None): 1001 | """ 1002 | A message is a discrete unit of electronic communication intended by the source for consumption by some 1003 | recipient or group of recipients. [based on https://en.wikipedia.org/wiki/Message] 1004 | """ 1005 | super().__init__() 1006 | self["@type"] = "uco-observable:Message" 1007 | self._set_properties_str(**{'uco-observable:state': state}) 1008 | self._set_properties_bool(**{'uco-observable:hasChanged': has_changed}) 1009 | #self.append_indexed_items(indexed_items) 1010 | 1011 | 1012 | class DiskPartition(ObjectFacet): 1013 | 1014 | def __init__(self, serial_number=None, partition_type=None, total_space=None, space_left=None, 1015 | space_used=None, offset=None): 1016 | """ 1017 | Used to represent Disk Partition 1018 | :param serial_number: disk partition identifier 1019 | :param partition_type: FAT32, NTFS etc. 1020 | :param total_space: free space 1021 | :param space_left: total - used space 1022 | :param space_used: used space 1023 | :param space_used: the offset to the beginning of the disk 1024 | """ 1025 | super().__init__() 1026 | self["@type"] = "uco-observable:DiskPartitionFacet" 1027 | self._set_properties_str(**{"uco-observable:serialNumber": serial_number, 1028 | "uco-observable:diskPartitionType": partition_type}) 1029 | self._set_properties_int(**{"uco-observable:totalSpace": total_space, 1030 | "uco-observable:spaceLeft": space_left, 1031 | "uco-observable:spaceUsed": space_used, 1032 | "uco-observable:partitionOffset": offset}) 1033 | 1034 | 1035 | class Disk(ObjectFacet): 1036 | 1037 | def __init__(self, disk_type=None, size=None, partition=None): 1038 | """ 1039 | Used to represent Fixed Disk 1040 | :param disk_type: Fixed default value 1041 | :param size: disk size 1042 | :param partition: array of @id references to the partitions contained 1043 | """ 1044 | super().__init__() 1045 | self["@type"] = "uco-observable:DiskFacet" 1046 | self._set_properties_str(**{"uco-observable:diskType": disk_type}) 1047 | self._set_properties_int(**{"uco-observable:diskSize": size}) 1048 | self._set_properties_list_id_reference_array(**{"uco-observable:partition": partition}) 1049 | 1050 | class CellSite(ObjectFacet): 1051 | 1052 | def __init__(self, country_code=None, network_code=None, area_code=None, site_id=None): 1053 | super().__init__() 1054 | self['@type'] = "uco-observable:CellSiteFacet" 1055 | self._set_properties_str(**{"uco-observable:cellSiteType": "GSM", 1056 | "uco-observable:cellSiteCountryCode": country_code, 1057 | "uco-observable:cellSiteNetworkCode": network_code, 1058 | "uco-observable:cellSiteLocationAreaCode": area_code, 1059 | "uco-observable:cellSiteIdentifier": site_id}) 1060 | 1061 | class SocialMediaActivity(ObjectFacet): 1062 | 1063 | def __init__(self, application=None, created_time=None, body=None, page_title=None, url=None, author_id=None, 1064 | author_name=None, reactions_count=None, shares_count=None, activity_type=None, comment_count=None, 1065 | account_id=None): 1066 | """ 1067 | :param application: An observable object 1068 | :param created_time: 1069 | :param body: 1070 | :param page_title: 1071 | :param url: An observable object 1072 | :param author_id: 1073 | :param author_name: 1074 | :param reactions_count: 1075 | :param shares_count: 1076 | :param activity_type: 1077 | :param comment_count: 1078 | :param account_id: 1079 | """ 1080 | super().__init__() 1081 | self['@type'] = "drafting:SocialMediaActivityFacet" 1082 | self._set_properties_str(**{"uco-observable:body": body, 1083 | "uco-observable:pageTitle": page_title, 1084 | "drafting:authorIdentifier": author_id, 1085 | "drafting:authorName": author_name, 1086 | "drafting:reactionsCount": reactions_count, 1087 | "drafting:sharesCount": shares_count, 1088 | "drafting:activityType": activity_type, 1089 | "drafting:commentCount": comment_count, 1090 | "uco-observable:accountIdentifier": account_id}) 1091 | self._set_properties_date_time( 1092 | **{'uco-observable:observableCreatedTime': created_time}) 1093 | self._set_properties_id_reference(**{"uco-observable:application": application, 1094 | "uco-observable:url": url}) 1095 | 1096 | class SearchedItem(ObjectFacet): 1097 | 1098 | def __init__(self, search_value=None, search_result=None, application=None, search_launch_time=None): 1099 | super().__init__() 1100 | self["@type"] = "drafting:SearchedItemFacet" 1101 | self._set_properties_str(**{"drafting:searchValue": search_value, 1102 | "drafting:searchResult": search_result}) 1103 | self._set_properties_date_time( 1104 | **{'drafting:searchLaunchedTime': search_launch_time}) 1105 | self._set_properties_id_reference( 1106 | **{'uco-observable:application': application}) 1107 | 1108 | class Location(ObjectFacet): 1109 | 1110 | def __init__(self, latitude=None, longitude=None, altitude=None): 1111 | super().__init__() 1112 | self["@type"] = "uco-location:LatLongCoordinatesFacet" 1113 | self._set_properties_float(**{"uco-location:latitude": latitude, 1114 | "uco-location:longitude": longitude, 1115 | 'uco-location:altitude': altitude}) 1116 | #self._set_properties_str(**{'drafting:locationType': location_type}) 1117 | 1118 | class SimpleName(ObjectFacet): 1119 | 1120 | def __init__(self, given_name=None, family_name=None): 1121 | """ 1122 | :param given_name: Full name of the identity of person 1123 | :param family_name: Family name of identity of person 1124 | """ 1125 | super().__init__() 1126 | self["@type"] = "uco-identity:SimpleNameFacet" 1127 | self._set_properties_str(**{"uco-identity:givenName": given_name, 1128 | "uco-identity:familyName": family_name}) 1129 | 1130 | class Role(ObjectSpecial): 1131 | 1132 | def __init__(self, description=None, _id=None, modified_time=None, name=None, created_time=None, spec_version=None, 1133 | tag=None, _type=None, created_by=None, objet_marking=None): 1134 | """ 1135 | A role is a usual or customary function based on contextual perspective. 1136 | :param description: A description of a particular concept characterization. 1137 | :param _id: A globally unique identifier for a characterization of a concept. 1138 | :param modified_time: Specifies the time that this particular version of the object was modified. 1139 | :param name: The name of a particular concept characterization. 1140 | :param created_time: The time at which a characterization of a concept is created. 1141 | :param spec_version: The version of UCO used to characterize a concept. 1142 | :param tag: A generic tag/label. 1143 | :param _type: The explicitly-defined type of characterization of a concept. 1144 | :param created_by: The identity that created a characterization of a concept. 1145 | :param objet_marking: Marking definitions to be applied to a particular concept characterization in its entirety 1146 | """ 1147 | 1148 | super().__init__() 1149 | self["@type"] = "uco-role:Role" 1150 | self._set_properties_str(**{"uco-core:description": description, 1151 | "uco-core:name": name, 1152 | "uco-core:specVersion": spec_version, 1153 | "uco-core:tag": tag, 1154 | "uco-core:type": _type}) 1155 | self._set_properties_date_time(**{"uco-core:modifiedTime": modified_time, 1156 | "uco-core:objectCreatedTime": created_time}) 1157 | self._set_properties_id_reference(**{"uco-core:id": _id, 1158 | "uco-core:createdBy": created_by, 1159 | "uco-core:objectMarking": objet_marking}) 1160 | 1161 | class SimpleAdress(ObjectFacet): 1162 | 1163 | def __init__(self, country=None, locality=None, street=None, postal_code=None, region=None, address_type=None): 1164 | super().__init__() 1165 | self["@type"] = "uco-location:SimpleAddressFacet" 1166 | self._set_properties_str(**{"uco-location:adressType": address_type, 1167 | "uco-location:country": country, 1168 | 'uco-location:locality': locality, 1169 | 'uco-location:postalCode': postal_code, 1170 | 'uco-location:region': region, 1171 | 'uco-location:street': street}) 1172 | 1173 | class Tool(ObjectSpecial): 1174 | 1175 | def __init__(self, tool_name=None, tool_version=None, tool_type=None, tool_creator=None): 1176 | """ 1177 | The Uco tool is a way to define the specfifics of a tool used in an investigation 1178 | :param tool_name: The account_name of the tool (e.g., "exiftool") 1179 | :param tool_creator: The developer and or organisation that produces this tool {might need to add a dict here} 1180 | :param tool_type: The type of tool 1181 | :param tool_version: The version of the tool 1182 | """ 1183 | super().__init__() 1184 | self["@type"] = "uco-tool:Tool" 1185 | self._set_properties_str(**{"uco-core:name": tool_name, 1186 | "uco-tool:version": tool_version, 1187 | "uco-tool:toolType": tool_type}) 1188 | self._set_properties_id_reference(**{"uco-tool:creator": tool_creator}) 1189 | 1190 | class InvestigativeAction(ObjectSpecial): 1191 | 1192 | def __init__(self, name=None, description=None, start_time=None, end_time=None, 1193 | performer=None, instrument=None, location=None, environment=None, results=None, objects=None): 1194 | """ 1195 | An investigative action is a CASE object that represents the who, when, what outcome of an action 1196 | :param name: The account_name of the action (e.g., "annotated") 1197 | :param start_time: The time, in ISO8601 time format, the action was started (e.g., "2020-09-29T12:13:01Z") 1198 | :param end_time: The time, in ISO8601 time format, the action completed (e.g., "2020-09-29T12:13:43Z") 1199 | """ 1200 | super().__init__() 1201 | self["@type"] = "case-investigation:InvestigativeAction" 1202 | self._set_properties_str(**{"uco-core:name": name, 1203 | 'uco-core:description': description, 1204 | "uco-action:environment": environment}) 1205 | self._set_properties_date_time(**{"uco-action:startTime": start_time, 1206 | "uco-action:endTime": end_time}) 1207 | self._set_properties_id_reference(**{"uco-action:performer": performer, 1208 | "uco-action:instrument": instrument, 1209 | "uco-action:location": location}) 1210 | self._set_properties_list_id_reference(**{"uco-action:result": results}) 1211 | self._set_properties_list_id_reference_array(**{"uco-action:object": objects}) 1212 | 1213 | 1214 | class ActionReferences(ObjectFacet): 1215 | 1216 | def __init__(self, performer=None, instrument=None, location=None, environment=None, results=None, objects=None): 1217 | """ 1218 | An action reference contains the details of an InvestigativeAction. 1219 | It groups the properties characterizing the core elements (who, how, with what, where, etc.) for actions. 1220 | The properties consist of identifier references to separate UCO objects detailing the particular property. 1221 | :param performer: The account_name or id of the person conducting the action 1222 | :param instrument: The tool used to conduct the action 1223 | :param location: The general location where the action took place (Room, Building or Town) 1224 | :param environment: The type of environment (lab, office) 1225 | :param results: A list of resulting output identifiers 1226 | """ 1227 | super().__init__() 1228 | self["@type"] = "uco-action:ActionReferencesFacet" 1229 | self._set_properties_str(**{"uco-action:environment": environment}) 1230 | self._set_properties_id_reference(**{"uco-action:performer": performer, 1231 | "uco-action:instrument": instrument, 1232 | "uco-action:location": location}) 1233 | self._set_properties_list_id_reference(**{"uco-action:result": results}) 1234 | self._set_properties_list_id_reference_array(**{"uco-action:object": objects}) 1235 | 1236 | def append_results(self, *args): 1237 | """ 1238 | Add result(s) to the list of outputs from an action 1239 | :param args: A CASE object, or objects, often an observable. (e.g., one or many devices from a search operation) 1240 | """ 1241 | self._set_properties_list_id_reference("uco-action:result", *args) 1242 | 1243 | def append_objects(self, *args): 1244 | """ 1245 | Add object(s) to the list of outputs from an action 1246 | :param args: A CASE object, or objects, often an observable. (e.g., one or many devices from a search operation) 1247 | """ 1248 | self._set_properties_list_id_reference("uco-action:object", *args) 1249 | 1250 | --------------------------------------------------------------------------------