Details
| ID | vmray |
|---|---|
| Provider | VMRay |
| Category | Forensics & Malware Analysis |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.12.5490952 |
| Supported Modules | Agentix XSIAM EDR Cortex Cloud Cloud Runtime Security |
README
VMRay XSOAR Integration
This integration enables users to design playbooks that involve analyzing a file in VMRay and retrieving the analysis results and associated threat intelligence.
The Playbooks accelerate incident response and make security operations more scalable and efficient.
Configure VMRay in Cortex
| Parameter | Description | Required |
|---|---|---|
| Source Reliability | Reliability of the source providing the intelligence data. | False |
| Server URL (e.g., https://cloud.vmray.com) | True | |
| API Key (Recommended) | False | |
| Use system proxy settings | False | |
| Trust any certificate (not secure) | False | |
| Retry requests when API is rate limited | False | |
| API Key (Deprecated) | Use the “API Key (Recommended)” parameter instead. | False |
Known Limitations
- Non-ASCII characters in file names will be ignored when uploading.
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
- vmray-upload-sample: Submit a sample for analysis
- vmray-upload-url: Submit a URL for analysis
- vmray-get-analysis-by-sample: Get analysis details for a sample
- vmray-get-job-by-sample: Get job details for a sample
- vmray-get-submission: Get submission results
- vmray-get-sample: Get information for a sample
- vmray-get-sample-by-hash: Get information for a sample by hash
- vmray-get-threat-indicators: Get threat indicators
- vmray-add-tag: Add a tag to an analysis or submission
- vmray-delete-tag: Delete a tag from an analysis or submission
- vmray-get-iocs: Get IOCs for a sample
- vmray-get-job-by-id: Get information for a job
- vmray-get-summary: Download Summary JSON v2 for an analysis
- vmray-get-license-usage-verdicts: Get the used quota of verdicts
- vmray-get-license-usage-reports: Get the used quota of reports
vmray-upload-sample
Submits a sample to VMRay for analysis.
Base Command
vmray-upload-sample
Input
| Argument Name | Description | Required |
|---|---|---|
| entry_id | Entry ID of the file to submit. | Required |
| document_password | Password of the document. | Optional |
| archive_password | Password of an archive. | Optional |
| sample_type | Force type of the file. | Optional |
| shareable | Whether the file is shareable. Possible values are: true, false. | Optional |
| max_jobs | Maximum number of jobs to create (number). Default is 1. | Optional |
| tags | A CSV list of tags to add to the sample. | Optional |
| reanalyze | Deprecated. Analyze even if analyses already exist. To control analysis caching, use the API Key settings instead, which are available via the Analysis Settings page, in the VMRay Web Interface. Possible values are: true, false. | Optional |
| net_scheme_name | The network scheme to use. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| VMRay.Job.JobID | Number | ID of a new job |
| VMRay.Job.Created | Date | Timestamp of job creation. |
| VMRay.Job.SampleID | Number | ID of the sample. |
| VMRay.Job.VMName | String | Name of the virtual machine. |
| VMRay.Job.VMID | Number | ID of the virtual machine. |
| VMRay.Sample.SampleID | Number | ID of the sample. |
| VMRay.Sample.SampleURL | String | URL to sample page. |
| VMRay.Sample.Created | Date | Timestamp of sample creation. |
| VMRay.Submission.SubmissionID | Number | Submission ID. |
| VMRay.Submission.SubmissionURL | String | URL to submission page. |
Command Example
vmray-upload-sample entry_id=79@4 max_jobs=1
Context Example
{
"VMRay.Sample": [
{
"SHA1": "69df095557346b3c136db4378afd5ee7a4839dcc",
"Created": "2019-05-27T07:48:11",
"SampleID": 3902285,
"SampleURL": "https://cloud.vmray.com/user/sample/view?id=3902285",
"FileName": "KeePass-2.41-Setup.exe",
"FileSize": 3301376,
"SSDeep": "98304:rk/6KPcsSO9iShSf0UTsj+te5NrYWM+40n3vGJyc:rkCK0UhSfHsKw5z4OvGJL"
}
],
"VMRay.Submission": [
{
"SampleID": 3902285,
"SubmissionID": 4569315,
"SubmissionURL": "https://cloud.vmray.com/user/sample/view?id=3902285"
}
],
"VMRay.Job": [
{
"Created": "2019-05-27T07:48:11",
"JobRuleSampleType": "Windows PE (x86)",
"VMID": 20,
"SampleID": 3902285,
"JobID": 3908304,
"VMName": "win10_64_th2"
}
]
}
Human Readable Output
File submitted to VMRay
| Jobs ID | Samples ID | Submissions ID | Sample URL |
|---|---|---|---|
| 3908304 | 3902285 | 4569315 | https://cloud.vmray.com/user/sample/view?id=3902285 |
vmray-upload-url
Submits a URL for analysis.
Base Command
vmray-upload-url
Input
| Argument Name | Description | Required |
|---|---|---|
| url | The URL to analyze. For example: https://demisto.com. . | Required |
| shareable | Whether the analysis is shareable. Possible values are: true, false. | Optional |
| max_jobs | Maximum number of jobs to create (number). Default is 1. | Optional |
| tags | A CSV list of tags to add to the sample. | Optional |
| net_scheme_name | The network scheme to use. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| VMRay.Job.JobID | Number | ID of a new job |
| VMRay.Job.Created | Date | Timestamp of job creation. |
| VMRay.Job.SampleID | Number | ID of the sample. |
| VMRay.Job.VMName | String | Name of the virtual machine. |
| VMRay.Job.VMID | Number | ID of the virtual machine. |
| VMRay.Sample.SampleID | Number | ID of the sample. |
| VMRay.Sample.SampleURL | String | URL to sample page. |
| VMRay.Sample.Created | Date | Timestamp of sample creation. |
| VMRay.Submission.SubmissionID | Number | Submission ID. |
| VMRay.Submission.SubmissionURL | String | URL to submission page. |
Command Example
{
"VMRay.Sample": [
{
"SHA1": "884a2738124be5dae95e685fb8c919b1460734c5",
"Created": "2019-05-27T07:48:11",
"SampleID": 3902285,
"SampleURL": "https://cloud.vmray.com/user/sample/view?id=3902285",
"FileName": "https://demisto.com",
"FileSize": 20,
"SSDeep": "3:N8W2K:2W2K"
}
],
"VMRay.Submission": [
{
"SampleID": 3902285,
"SubmissionID": 4569315,
"SubmissionURL": "https://cloud.vmray.com/user/sample/view?id=3902285"
}
],
"VMRay.Job": [
{
"Created": "2019-05-27T07:48:11",
"JobRuleSampleType": "Windows PE (x86)",
"VMID": 20,
"SampleID": 3902285,
"JobID": 3908304,
"VMName": "win10_64_th2"
}
]
}
Human Readable Output
URL submitted to VMRay
| Jobs ID | Samples ID | Submissions ID |
|---|---|---|
| 3908304 | 3902285 | 4569315 |
vmray-get-analysis-by-sample
Retrieves all analysis details for a specified sample.
Base Command
vmray-get-analysis-by-sample
Input
| Argument Name | Description | Required |
|---|---|---|
| sample_id | Sample ID. | Required |
| limit | Maximum number of results to return (number). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| VMRay.Analysis.AnalysisID | Number | Analysis ID. |
| VMRay.Analysis.AnalysisURL | String | URL to analysis page. |
| VMRay.Analysis.SampleID | Number | Sample ID in the analysis. |
| VMRay.Analysis.Verdict | String | Verdict for the sample (Malicious, Suspicious, Clean, Not Available). |
| VMRay.Analysis.VerdictReason | String | Description of the Verdict Reason. |
| VMRay.Analysis.Severity | String | Severity of the sample in the submission (Malicious, Suspicious, Good, Blacklisted, Whitelisted, Unknown). Deprecated. |
| VMRay.Analysis.JobCreated | Date | Date when the analysis job started. |
| VMRay.Analysis.MD5 | String | MD5 hash of the sample. |
| VMRay.Analysis.SHA1 | String | SHA1 hash of the sample. |
| VMRay.Analysis.SHA256 | String | SHA256 hash of the sample. |
| VMRay.Analysis.SSDeep | String | ssdeep hash of the sample. |
Command Example
!vmray-get-analysis-by-sample sample_id=3902238
Context Example
{
"VMRay.Analysis": [
{
"SampleID": 3902238,
"SampleURL": "https://cloud.vmray.com/user/sample/view?id=3902238",
"SHA1": "868a53c394f29f8d3aac7b0a20a371999045b6ed",
"SHA256": "b8a4b647e56cb71773d0086b51906b902a7ccafe699f4068da4cb5cd234d9d66",
"JobCreated": "2021-06-14T12:17:07",
"AnalysisID": 2779353,
"Verdict": "Suspicious",
"VerdictReason": null,
"Severity": "Suspicious",
"MD5": "2e0499dc90c2d715a53e05b1890e0442"
}
]
}
Human Readable Output
Analysis results from VMRay for ID 3902238:
| AnalysisID | SampleID | Verdict | AnalysisURL |
|---|---|---|---|
| 2779353 | 3902238 | Suspicious | https://cloud.vmray.com/user/sample/view?id=3902238 |
vmray-get-job-by-sample
Retrieves details for all jobs for a specified sample.
Base Command
vmray-get-job-by-sample
Input
| Argument Name | Description | Required |
|---|---|---|
| sample_id | Sample ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| VMRay.Job.JobID | Number | ID of the job. |
| VMRay.Job.SampleID | Number | Sample ID of the job. |
| VMRay.Job.SubmissionID | Number | ID of the submission. |
| VMRay.Job.MD5 | String | MD5 hash of the sample in the job. |
| VMRay.Job.SHA1 | String | SHA1 hash of the sample in the job. |
| VMRay.Job.SHA256 | String | SHA256 hash of the sample in the job. |
| VMRay.Job.SSDeep | String | ssdeep hash of the sample in the job. |
| VMRay.Job.VMName | String | Name of the virtual machine. |
| VMRay.Job.VMID | Number | ID of the virtual machine. |
| VMRay.Job.Status | String | Status of the job. |
Command Example
!vmray-get-job-by-sample sample_id=3902238
Context Example
{
"VMRay.Job": [
{
"VMName": "win7_32_sp1",
"SampleID": 3902238,
"SHA1": "868a53c394f29f8d3aac7b0a20a371999045b6ed",
"SubmissionID": 18950,
"SHA256": "b8a4b647e56cb71773d0086b51906b902a7ccafe699f4068da4cb5cd234d9d66",
"SSDeep": "1536:Hg8ktOZtz+PZvpJyrOM1GhFNkYL2BxNRjWW:H/kY0Z3yrOMGTkrNRjH",
"Status": "inwork",
"VMID": 3,
"JobID": 29208,
"MD5": "2e0499dc90c2d715a53e05b1890e0442"
}
]
}
Human Readable Output
Job results for sample id: 3902238
| JobID | SampleID | VMName | VMID |
|---|---|---|---|
| 29208 | 3902238 | win7_32_sp1 | 3 |
vmray-get-submission
Retrieves the results of a submission.
Base Command
vmray-get-submission
Input
| Argument Name | Description | Required |
|---|---|---|
| submission_id | ID of the submission. Can be obtained by running the ‘vmray-upload-sample’ or ‘vmray-upload-url’ command. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| VMRay.Submission.IsFinished | Boolean | Whether the submission is finished (true or false). |
| VMRay.Submission.HasErrors | Boolean | Whether there are any errors in the submission (true or false). |
| VMRay.Submission.SubmissionID | Number | ID of the sample in the submission. |
| VMRay.Submission.SubmissionURL | String | URL of submission page. |
| VMRay.Submission.MD5 | String | MD5 hash of the sample in the submission. |
| VMRay.Submission.SHA1 | String | SHA1 hash of the sample in the submission. |
| VMRay.Submission.SHA256 | String | SHA256 hash of the sample in the submission. |
| VMRay.Submission.SSDeep | String | ssdeep hash of the sample in the submission. |
| VMRay.Submission.Verdict | String | Verdict for the sample (Malicious, Suspicious, Clean, Not Available). |
| VMRay.Submission.VerdictReason | String | Description of the Verdict Reason. |
| VMRay.Submission.Severity | String | Severity of the sample in the submission (Malicious, Suspicious, Good, Blacklisted, Whitelisted, Unknown). Deprecated. |
| VMRay.Submission.SampleID | Number | ID of the sample in the submission. |
Command Example
vmray-get-submission submission_id=4569262
Context Example
{
"DBotScore": [
{
"Indicator": "2e0499dc90c2d715a53e05b1890e0442",
"Score": 3,
"Type": "hash",
"Vendor": "VMRay"
},
{
"Indicator": "b8a4b647e56cb71773d0086b51906b902a7ccafe699f4068da4cb5cd234d9d66",
"Score": 3,
"Type": "hash",
"Vendor": "VMRay"
},
{
"Indicator": "868a53c394f29f8d3aac7b0a20a371999045b6ed",
"Score": 3,
"Type": "hash",
"Vendor": "VMRay"
},
{
"Indicator": "1536:Hg8ktOZtz+PZvpJyrOM1GhFNkYL2BxNRjWW:H/kY0Z3yrOMGTkrNRjH",
"Score": 3,
"Type": "hash",
"Vendor": "VMRay"
}
],
"VMRay.Submission": {
"SampleID": 3902238,
"SHA1": "868a53c394f29f8d3aac7b0a20a371999045b6ed",
"HasErrors": true,
"SubmissionID": 4569262,
"SubmissionURL": "https://cloud.vmray.com/user/sample/view?id=3902238",
"SHA256": "b8a4b647e56cb71773d0086b51906b902a7ccafe699f4068da4cb5cd234d9d66",
"SSDeep": "1536:Hg8ktOZtz+PZvpJyrOM1GhFNkYL2BxNRjWW:H/kY0Z3yrOMGTkrNRjH",
"Verdict": "Malicious",
"IsFinished": true,
"VerdictReason": null,
"Severity": "Malicious",
"MD5": "2e0499dc90c2d715a53e05b1890e0442"
}
}
Human Readable Output
Submission results from VMRay for ID 3902238 with verdict of Malicious
| Attribute | Value |
|---|---|
| IsFinished | true |
| Verdict | Malicious |
| HasErrors | true |
| MD5 | 2e0499dc90c2d715a53e05b1890e0442 |
| SHA1 | 868a53c394f29f8d3aac7b0a20a371999045b6ed |
| SHA256 | b8a4b647e56cb71773d0086b51906b902a7ccafe699f4068da4cb5cd234d9d66 |
| SSDeep | 1536:Hg8ktOZtz+PZvpJyrOM1GhFNkYL2BxNRjWW:H/kY0Z3yrOMGTkrNRjH |
| SubmissionURL | https://cloud.vmray.com/user/sample/view?id=3902238 |
vmray-get-sample
Retrieves a sample using the sample ID.
Base Command
vmray-get-sample
Input
| Argument Name | Description | Required |
|---|---|---|
| sample_id | ID of the sample. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| VMRay.Sample.SampleID | Number | ID of the sample. |
| VMRay.Sample.SampleURL | String | URL to sample page. |
| VMRay.Sample.FileName | String | File name of the sample. |
| VMRay.Sample.MD5 | String | MD5 hash of the sample. |
| VMRay.Sample.SHA1 | String | SHA1 hash of the sample. |
| VMRay.Sample.SHA256 | String | SHA256 hash of the sample. |
| VMRay.Sample.SSDeep | String | ssdeep hash of the sample. |
| VMRay.Sample.Verdict | String | Verdict for the sample (Malicious, Suspicious, Clean, Not Available). |
| VMRay.Sample.VerdictReason | String | Description of the Verdict Reason. |
| VMRay.Sample.Severity | String | Severity of the sample in the submission (Malicious, Suspicious, Good, Blacklisted, Whitelisted, Unknown). Deprecated. |
| VMRay.Sample.Type | String | File type. |
| VMRay.Sample.Created | Date | Timestamp of sample creation. |
| VMRay.Sample.Classifications | String | Classifications of the sample. |
| VMRay.Sample.ChildSampleIDs | Number | List of child sample IDs. |
| VMRay.Sample.ParentSampleIDs | Number | List of parent sample IDs. |
| VMRay.Sample.URL | String | The sample URL. |
Command Example
!vmray-get-sample sample_id=3902238
Context Example
{
"DBotScore": [
{
"Indicator": "2e0499dc90c2d715a53e05b1890e0442",
"Score": 3,
"Type": "hash",
"Vendor": "VMRay"
},
{
"Indicator": "b8a4b647e56cb71773d0086b51906b902a7ccafe699f4068da4cb5cd234d9d66",
"Score": 3,
"Type": "hash",
"Vendor": "VMRay"
},
{
"Indicator": "868a53c394f29f8d3aac7b0a20a371999045b6ed",
"Score": 3,
"Type": "hash",
"Vendor": "VMRay"
},
{
"Indicator": "1536:Hg8ktOZtz+PZvpJyrOM1GhFNkYL2BxNRjWW:H/kY0Z3yrOMGTkrNRjH",
"Score": 3,
"Type": "hash",
"Vendor": "VMRay"
}
],
"VMRay.Sample": {
"SampleID": 3902238,
"SampleURL": "https://cloud.vmray.com/user/sample/view?id=3902238",
"SHA1": "868a53c394f29f8d3aac7b0a20a371999045b6ed",
"Classification": [],
"SHA256": "b8a4b647e56cb71773d0086b51906b902a7ccafe699f4068da4cb5cd234d9d66",
"FileName": "pafish.exe",
"Created": "2018-03-20T15:06:49",
"SSDeep": "1536:Hg8ktOZtz+PZvpJyrOM1GhFNkYL2BxNRjWW:H/kY0Z3yrOMGTkrNRjH",
"Verdict": "Malicious",
"Type": "Windows Exe (x86-32)",
"VerdictReason": null,
"Severity": "Malicious",
"MD5": "2e0499dc90c2d715a53e05b1890e0442",
"ChildSampleIDs": [20, 21, 22],
"ParentSampleIDs": [18],
"URL": null
}
}
Human Readable Output
Results for sample id: 3902238 with verdict Malicious
| Attribute | Value |
|---|---|
| FileName | pafish.exe |
| Type | Windows Exe (x86-32) |
| MD5 | 2e0499dc90c2d715a53e05b1890e0442 |
| SHA1 | 868a53c394f29f8d3aac7b0a20a371999045b6ed |
| SHA256 | b8a4b647e56cb71773d0086b51906b902a7ccafe699f4068da4cb5cd234d9d66 |
| SSDeep | 1536:Hg8ktOZtz+PZvpJyrOM1GhFNkYL2BxNRjWW:H/kY0Z3yrOMGTkrNRjH |
| SampleURL | https://cloud.vmray.com/user/sample/view?id=3902238 |
vmray-get-sample-by-hash
Retrieves sample information by hash.
Base Command
vmray-get-sample-by-hash
Input
| Argument Name | Description | Required |
|---|---|---|
| hash | MD5, SHA1 or SHA256 hash of the sample. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| File.Name | String | The full file name (including file extension). |
| File.MD5 | String | The MD5 hash of the file. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.SSDeep | String | The SSDeep hash of the file. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| VMRay.Sample.SampleID | Number | ID of the sample. |
| VMRay.Sample.SampleURL | String | URL to sample page. |
| VMRay.Sample.FileName | String | File name of the sample. |
| VMRay.Sample.MD5 | String | MD5 hash of the sample. |
| VMRay.Sample.SHA1 | String | SHA1 hash of the sample. |
| VMRay.Sample.SHA256 | String | SHA256 hash of the sample. |
| VMRay.Sample.SSDeep | String | ssdeep hash of the sample. |
| VMRay.Sample.Verdict | String | Verdict for the sample (Malicious, Suspicious, Clean, Not Available). |
| VMRay.Sample.VerdictReason | String | Description of the Verdict Reason. |
| VMRay.Sample.Severity | String | Severity of the sample in the submission (Malicious, Suspicious, Good, Blacklisted, Whitelisted, Unknown). Deprecated. |
| VMRay.Sample.Type | String | File type. |
| VMRay.Sample.Created | Date | Timestamp of sample creation. |
| VMRay.Sample.Classifications | String | Classifications of the sample. |
| VMRay.Sample.ChildSampleIDs | Number | List of child sample IDs. |
| VMRay.Sample.ParentSampleIDs | Number | List of parent sample IDs. |
Command Example
!vmray-get-sample-by-hash hash=124f46228d1e220d88ae5e9a24d6e713039a64f9
Context Example
{
"DBotScore": [
{
"Indicator": "9159edb64c4a21d8888d088bf2db23f3",
"Score": 3,
"Type": "hash",
"Vendor": "VMRay"
},
{
"Indicator": "2180f4a13add5e346e8cf6994876a9d2f5eac3fcb695db8569537010d24cd6d5",
"Score": 3,
"Type": "hash",
"Vendor": "VMRay"
},
{
"Indicator": "124f46228d1e220d88ae5e9a24d6e713039a64f9",
"Score": 3,
"Type": "hash",
"Vendor": "VMRay"
},
{
"Indicator": "1536:tI05L48IVDAQVzZpJyrOM1GhFNkYL2BxNRj:tI05LBIDAuztyrOMGTkrNRj",
"Score": 3,
"Type": "hash",
"Vendor": "VMRay"
}
],
"VMRay.Sample": [
{
"ParentSampleIDs": [],
"SampleID": 6822,
"SHA1": "124f46228d1e220d88ae5e9a24d6e713039a64f9",
"SampleURL": "https://cloud.vmray.com/user/sample/view?id=6822",
"Classification": [],
"SHA256": "2180f4a13add5e346e8cf6994876a9d2f5eac3fcb695db8569537010d24cd6d5",
"FileName": "pafish.exe",
"Created": "2021-06-24T15:06:04",
"SSDeep": "1536:tI05L48IVDAQVzZpJyrOM1GhFNkYL2BxNRj:tI05LBIDAuztyrOMGTkrNRj",
"ChildSampleIDs": [],
"Verdict": "Malicious",
"Type": "Windows Exe (x86-32)",
"VerdictReason": null,
"Severity": "Malicious",
"MD5": "9159edb64c4a21d8888d088bf2db23f3"
}
]
}
Human Readable Output
Results for sha1 hash 124f46228d1e220d88ae5e9a24d6e713039a64f9:
| Attribute | Value |
|---|---|
| SampleID | 5948 |
| FileName | pafish.exe |
| Type | Windows Exe (x86-32) |
| Verdict | Malicious |
| SampleURL | https://cloud.vmray.com/user/sample/view?id=5948 |
vmray-get-threat-indicators
Retrieves threat indicators (VTI).
Base Command
vmray-get-threat-indicators
Input
| Argument Name | Description | Required |
|---|---|---|
| sample_id | ID of the sample. Can be obtained from the ‘VMRay.Sample.ID’ output. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| VMRay.ThreatIndicator.AnalysisID | Number | List of connected analysis IDs. |
| VMRay.ThreatIndicator.Category | String | Category of threat indicators. |
| VMRay.ThreatIndicator.Classification | String | Classifications of threat indicators. |
| VMRay.ThreatIndicator.ID | Number | ID of a threat indicator. |
| VMRay.ThreatIndicator.Operation | String | Operation the indicators caused. |
Command Example
!vmray-get-threat-indicators sample_id=3902238
Context Output
Omitted for brevity.
Human Readable Output
Omitted for brevity.
vmray-add-tag
Adds a tag to an analysis and/or a submission.
Base Command
vmray-add-tag
Input
| Argument Name | Description | Required |
|---|---|---|
| submission_id | ID of the submission to which to add tags. | Optional |
| analysis_id | ID of the analysis from which to add tags. | Optional |
| tag | Tag to add. | Optional |
Context Output
There is no context output for this command.
Command Example
!vmray-add-tag submission_id=4569262 tag=faulty
Human Readable Output
Tags: faulty has been added to submission: 4569262
vmray-delete-tag
Deletes tags from an analysis and/or a submission.
Base Command
vmray-delete-tag
Input
| Argument Name | Description | Required |
|---|---|---|
| analysis_id | ID of the analysis from which to delete a tag. | Optional |
| submission_id | ID of the submission from which to delete a tag. | Optional |
| tag | Tag to delete. | Optional |
Context Output
There is no context output for this command.
Command Example
!vmray-delete-tag submission_id=4569262 tag=faulty
Human Readable Output
Tags: faulty has been removed from submission: 4569262
vmray-get-iocs
Retrieves Indicators of Compromise for a specified sample.
Base Command
vmray-get-iocs
Input
| Argument Name | Description | Required |
|---|---|---|
| sample_id | ID of the sample. | Required |
| all_artifacts | Whether all artifacts should be returned or only Indicators of Compromise. Possible values are: true, false. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| Domain.Name | String | The domain name |
| IP.Address | String | IP address |
| URL.Data | String | The URL |
| Email.Address | String | The Email address |
| File.Path | String | The full file path. |
| File.MD5 | String | The MD5 hash of the file. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.SSDeep | String | The SSDeep hash of the file. |
| VMRay.Sample.IOC.Domain.AnalysisID | Number | IDs of other analyses that contain the domain. |
| VMRay.Sample.IOC.Domain.Countries | String | Countries associated with the domain. |
| VMRay.Sample.IOC.Domain.CountryCodes | String | ISO 3166-1 two-letter country codes associated with the domain. |
| VMRay.Sample.IOC.Domain.Domain | String | Domain. |
| VMRay.Sample.IOC.Domain.ID | Number | ID of the domain. (deprecated; is always 0) |
| VMRay.Sample.IOC.Domain.IsIOC | Boolean | Whether this artifact is an Indicator of Compromise (IOC). |
| VMRay.Sample.IOC.Domain.IOCType | String | Type of IOC. |
| VMRay.Sample.IOC.Domain.IpAddresses | String | IP addresses associated with the domain. |
| VMRay.Sample.IOC.Domain.OriginalDomains | String | Original domains associated with the domain. |
| VMRay.Sample.IOC.Domain.ParentProcesses | String | Full commandline of processes where the domain was used. |
| VMRay.Sample.IOC.Domain.ParentProcessesNames | String | Names of processes where the domain was used. |
| VMRay.Sample.IOC.Domain.Protocols | String | The protocols used for the domain in a request. |
| VMRay.Sample.IOC.Domain.Sources | String | The sources where the domain was obtained from. |
| VMRay.Sample.IOC.Domain.Type | String | Type of domain. |
| VMRay.Sample.IOC.Domain.Verdict | String | Verdict for the artifact (Malicious, Suspicious, Clean, Not Available). |
| VMRay.Sample.IOC.Domain.VerdictReason | String | Description of the Verdict Reason. |
| VMRay.Sample.IOC.EmailAddress.AnalysisID | Number | IDs of other analyses that contain the email address. |
| VMRay.Sample.IOC.EmailAddress.Classifications | String | The classifications of the email address. |
| VMRay.Sample.IOC.EmailAddress.EmailAddress | String | The email address. |
| VMRay.Sample.IOC.EmailAddress.IsIOC | Boolean | Whether this artifact is an Indicator of Compromise (IOC). |
| VMRay.Sample.IOC.EmailAddress.IsRecipient | Boolean | Indicates whether this email address was used as a recipient email. |
| VMRay.Sample.IOC.EmailAddress.IsSender | Boolean | Indicates whether this email address was used as a sender email. |
| VMRay.Sample.IOC.EmailAddress.IOCType | String | Type of IOC. |
| VMRay.Sample.IOC.EmailAddress.Subjects | String | Email subjects this email address was used in. |
| VMRay.Sample.IOC.EmailAddress.ThreatNames | String | The threat names of the email address. |
| VMRay.Sample.IOC.EmailAddress.Type | String | Type of email address. |
| VMRay.Sample.IOC.EmailAddress.Verdict | String | Verdict for the artifact (Malicious, Suspicious, Clean, Not Available). |
| VMRay.Sample.IOC.EmailAddress.VerdictReason | String | Description of the Verdict Reason. |
| VMRay.Sample.IOC.Email.AnalysisID | Number | IDs of other analyses that contain the email. |
| VMRay.Sample.IOC.Email.AttachmentTypes | String | MIME types of attachments found in this email. |
| VMRay.Sample.IOC.Email.Classifications | String | The classifications of the email. |
| VMRay.Sample.IOC.Email.Hashes.MD5 | String | MD5 of given email. |
| VMRay.Sample.IOC.Email.Hashes.SSDeep | String | SSDeep of given email. |
| VMRay.Sample.IOC.Email.Hashes.SHA256 | String | SHA256 of given email. |
| VMRay.Sample.IOC.Email.Hashes.SHA1 | String | SHA1 of given email. |
| VMRay.Sample.IOC.Email.IsIOC | Boolean | Whether this artifact is an Indicator of Compromise (IOC). |
| VMRay.Sample.IOC.Email.IOCType | String | Type of IOC. |
| VMRay.Sample.IOC.Email.NrAttachments | Number | Number of attachments found in the email. |
| VMRay.Sample.IOC.Email.NrLinks | Number | Number of links found in the email. |
| VMRay.Sample.IOC.Email.Recipients | String | The email recipients. |
| VMRay.Sample.IOC.Email.Sender | String | Sender of the email. |
| VMRay.Sample.IOC.Email.Subject | String | Subject of the email. |
| VMRay.Sample.IOC.Email.ThreatNames | String | The threat names of the email. |
| VMRay.Sample.IOC.Email.Type | String | Type of email. |
| VMRay.Sample.IOC.Email.Verdict | String | Verdict for the artifact (Malicious, Suspicious, Clean, Not Available). |
| VMRay.Sample.IOC.Email.VerdictReason | String | Description of the Verdict Reason. |
| VMRay.Sample.IOC.Filename.AnalysisID | Number | IDs of other analyses that contain the filename. |
| VMRay.Sample.IOC.Filename.Categories | String | The filename categories. |
| VMRay.Sample.IOC.Filename.Classifications | String | The classifications of the filename. |
| VMRay.Sample.IOC.Filename.Filename | String | The filename. |
| VMRay.Sample.IOC.Filename.IsIOC | Boolean | Whether this artifact is an Indicator of Compromise (IOC). |
| VMRay.Sample.IOC.Filename.IOCType | String | Type of IOC. |
| VMRay.Sample.IOC.Filename.Operations | String | The filename operations that were performed, e.g., access, create, read, write, and delete. |
| VMRay.Sample.IOC.Filename.ThreatNames | String | The threat names of the filename. |
| VMRay.Sample.IOC.Filename.Type | String | Type of filename. |
| VMRay.Sample.IOC.Filename.Verdict | String | Verdict for the artifact (Malicious, Suspicious, Clean, Not Available). |
| VMRay.Sample.IOC.Filename.VerdictReason | String | Description of the Verdict Reason. |
| VMRay.Sample.IOC.File.AnalysisID | Number | IDs of other analyses that contain the file. |
| VMRay.Sample.IOC.File.Categories | String | The file categories. |
| VMRay.Sample.IOC.File.Classifications | String | The classifications of the file. |
| VMRay.Sample.IOC.File.FileSize | Number | The original size of the file in bytes. |
| VMRay.Sample.IOC.File.Filename | String | Name of the file. |
| VMRay.Sample.IOC.File.Filenames | String | All known names of the file. |
| VMRay.Sample.IOC.File.Hashes.MD5 | String | MD5 hash of the file. |
| VMRay.Sample.IOC.File.Hashes.SSDeep | String | SSDeep hash of the file. |
| VMRay.Sample.IOC.File.Hashes.SHA256 | String | SHA256 hash of the file. |
| VMRay.Sample.IOC.File.Hashes.SHA1 | String | SHA1 hash of the file. |
| VMRay.Sample.IOC.File.ID | Number | ID of the file. (deprecated; is always 0) |
| VMRay.Sample.IOC.File.IsIOC | Boolean | Whether this artifact is an Indicator of Compromise (IOC). |
| VMRay.Sample.IOC.File.IOCType | String | Type of IOC. |
| VMRay.Sample.IOC.File.MIMEType | String | The MIME type of the file. |
| VMRay.Sample.IOC.File.Name | String | Same as Filename. |
| VMRay.Sample.IOC.File.NormFilename | String | Normalized name of the file. |
| VMRay.Sample.IOC.File.Operation | String | Same as Operations, left in for backwards compatibility. |
| VMRay.Sample.IOC.File.Operations | String | The file operations which were performed, e.g., access, create, read, write, and delete. |
| VMRay.Sample.IOC.File.ParentFiles | String | Files where this file was contained in. |
| VMRay.Sample.IOC.File.ParentProcesses | String | Full commandline of processes where the file was referenced. |
| VMRay.Sample.IOC.File.ParentProcessesNames | String | Names of processes where the file was referenced. |
| VMRay.Sample.IOC.File.ResourceURL | String | URL of where the file was downloaded. |
| VMRay.Sample.IOC.File.ThreatNames | String | The threat names of the file. |
| VMRay.Sample.IOC.File.Type | String | Type of file. |
| VMRay.Sample.IOC.File.Verdict | String | Verdict for the artifact (Malicious, Suspicious, Clean, Not Available). |
| VMRay.Sample.IOC.File.VerdictReason | String | Description of the Verdict Reason. |
| VMRay.Sample.IOC.IP.AnalysisID | Number | IDs of other analyses that contain the IP address. |
| VMRay.Sample.IOC.IP.Countries | String | Countries associated with the IP address. |
| VMRay.Sample.IOC.IP.CountryCodes | String | ISO 3166-1 two-letter country codes associated with the IP address. |
| VMRay.Sample.IOC.IP.Domains | String | Domains associated with the IP address. |
| VMRay.Sample.IOC.IP.IP | String | The IP address. |
| VMRay.Sample.IOC.IP.ID | Number | ID of the IP address. (deprecated; is always 0) |
| VMRay.Sample.IOC.IP.IsIOC | Boolean | Whether this artifact is an Indicator of Compromise (IOC). |
| VMRay.Sample.IOC.IP.IOCType | String | Type of IOC. |
| VMRay.Sample.IOC.IP.Operation | String | Deprecated, always empty. |
| VMRay.Sample.IOC.IP.ParentProcesses | String | Full commandline of processes where the IP address was referenced. |
| VMRay.Sample.IOC.IP.ParentProcessesNames | String | Names of processes where the IP address was referenced. |
| VMRay.Sample.IOC.IP.Protocols | String | Protocols used in communication with this IP. |
| VMRay.Sample.IOC.IP.Sources | String | The sources where the IP address was obtained from. |
| VMRay.Sample.IOC.IP.Type | String | Type of IP address. |
| VMRay.Sample.IOC.IP.Verdict | String | Verdict for the artifact (Malicious, Suspicious, Clean, Not Available). |
| VMRay.Sample.IOC.IP.VerdictReason | String | Description of the Verdict Reason. |
| VMRay.Sample.IOC.Mutex.AnalysisID | Number | IDs of other analyses that contain the mutex. |
| VMRay.Sample.IOC.Mutex.Classifications | String | The mutex classifications. |
| VMRay.Sample.IOC.Mutex.ID | Number | ID of the mutex. (deprecated; is always 0) |
| VMRay.Sample.IOC.Mutex.IsIOC | Boolean | Whether this artifact is an Indicator of Compromise (IOC). |
| VMRay.Sample.IOC.Mutex.IOCType | String | Type of IOC. |
| VMRay.Sample.IOC.Mutex.Name | String | Name of the mutex. |
| VMRay.Sample.IOC.Mutex.Operation | String | Same as Operations, left in for backwards compatibility. |
| VMRay.Sample.IOC.Mutex.Operation | String | The mutex operations that were performed, e.g., access, create, read, write, and delete. |
| VMRay.Sample.IOC.Mutex.ParentProcesses | String | Full commandline of processes where the mutex was used. |
| VMRay.Sample.IOC.Mutex.ParentProcessesNames | Unknown | Names of processes where the mutex was used. |
| VMRay.Sample.IOC.Mutex.ThreatNames | String | The threat names of the mutex. |
| VMRay.Sample.IOC.Mutex.Type | String | Type of mutex. |
| VMRay.Sample.IOC.Mutex.Verdict | String | Verdict for the artifact (Malicious, Suspicious, Clean, Not Available). |
| VMRay.Sample.IOC.Mutex.VerdictReason | String | Description of the Verdict Reason. |
| VMRay.Sample.IOC.Process.AnalysisID | Number | IDs of other analyses that contain the process. |
| VMRay.Sample.IOC.Process.Classifications | String | The process classifications. |
| VMRay.Sample.IOC.Process.CmdLine | String | Command line of the process. |
| VMRay.Sample.IOC.Process.ImageNames | String | Names of the process executable. |
| VMRay.Sample.IOC.Process.IsIOC | Boolean | Whether this artifact is an Indicator of Compromise (IOC). |
| VMRay.Sample.IOC.Process.IOCType | String | Type of IOC. |
| VMRay.Sample.IOC.Process.ParentProcesses | String | Full commandline of parent processes. |
| VMRay.Sample.IOC.Process.ParentProcessesNames | String | Names of parent processes. |
| VMRay.Sample.IOC.Process.ProcessNames | String | Names of the processes. |
| VMRay.Sample.IOC.Process.ThreatNames | String | The threat names of the process. |
| VMRay.Sample.IOC.Process.Type | String | Type of process. |
| VMRay.Sample.IOC.Process.Verdict | String | Verdict for the artifact (Malicious, Suspicious, Clean, Not Available). |
| VMRay.Sample.IOC.Process.VerdictReason | String | Description of the Verdict Reason. |
| VMRay.Sample.IOC.Registry.AnalysisID | Number | IDs of other analyses that contain the registry key. |
| VMRay.Sample.IOC.Registry.Classifications | String | The registry key classifications. |
| VMRay.Sample.IOC.Registry.ID | Number | ID of the registry key. (deprecated; is always 0) |
| VMRay.Sample.IOC.Registry.IsIOC | Boolean | Whether this artifact is an Indicator of Compromise (IOC). |
| VMRay.Sample.IOC.Registry.IOCType | String | Type of IOC. |
| VMRay.Sample.IOC.Registry.Name | String | The normalized registry key name. |
| VMRay.Sample.IOC.Registry.Operation | String | Same as Operations, left in for backwards compatibility. |
| VMRay.Sample.IOC.Registry.Operation | String | The registry operations that were performed, e.g., access, create, read, write, and delete. |
| VMRay.Sample.IOC.Registry.ParentProcesses | String | Full commandline of processes where the registry key was referenced. |
| VMRay.Sample.IOC.Registry.ParentProcessesNames | String | Names of processes where the registry key was referenced. |
| VMRay.Sample.IOC.Registry.ThreatNames | String | The threat names of the registry key. |
| VMRay.Sample.IOC.Registry.Type | String | Type of registry key. |
| VMRay.Sample.IOC.Registry.ValueTypes | String | The registry key value type. |
| VMRay.Sample.IOC.Registry.Verdict | String | Verdict for the artifact (Malicious, Suspicious, Clean, Not Available). |
| VMRay.Sample.IOC.Registry.VerdictReason | String | Description of the Verdict Reason. |
| VMRay.Sample.IOC.URL.AnalysisID | Number | IDs of other analyses that contain the given URL. |
| VMRay.Sample.IOC.URL.Categories | String | The URL categories. |
| VMRay.Sample.IOC.URL.ContentTypes | String | Content types associated with the URL. |
| VMRay.Sample.IOC.URL.Countries | String | Countries associated with the URL. |
| VMRay.Sample.IOC.URL.CountryCodes | String | ISO 3166-1 two-letter country codes associated with the URL. |
| VMRay.Sample.IOC.URL.ID | Number | ID of the URL. (deprecated; is always 0) |
| VMRay.Sample.IOC.URL.IPAddresses | String | IP addresses associated with the URL. |
| VMRay.Sample.IOC.URL.Methods | String | Methods of HTTP requests directed at this URL. |
| VMRay.Sample.IOC.URL.Operation | String | Deprecated, always empty. |
| VMRay.Sample.IOC.URL.OriginalURLs | String | The origin URLs the malware used in the artifact operation. |
| VMRay.Sample.IOC.URL.ParentFiles | String | Names of files where the URL was referenced. |
| VMRay.Sample.IOC.URL.ParentProcesses | String | Full commandline of processes where the URL was referenced. |
| VMRay.Sample.IOC.URL.ParentProcessesNames | String | Names of processes where the URL was referenced. |
| VMRay.Sample.IOC.URL.Referrers | String | Other URLs that referred to this URL. |
| VMRay.Sample.IOC.URL.Source | String | The sources where the URL was obtained from. |
| VMRay.Sample.IOC.URL.Type | String | Type of the URL. |
| VMRay.Sample.IOC.URL.URL | String | The URL. |
| VMRay.Sample.IOC.URL.UserAgents | String | User agents used to connect to this URL. |
| VMRay.Sample.IOC.URL.Verdict | String | Verdict for the artifact (Malicious, Suspicious, Clean, Not Available). |
| VMRay.Sample.IOC.URL.VerdictReason | String | Description of the Verdict Reason. |
Command Example
!vmray-get-iocs sample_id=3902238
Context Example
Omitted for brevity.
Human Readable Output
Omitted for brevity.
vmray-get-job-by-id
Retrieves a job by job ID.
Base Command
vmray-get-job-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| job_id | ID of a job. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| VMRay.Job.JobID | Number | ID of the job. |
| VMRay.Job.SampleID | Number | Sample ID of the job. |
| VMRay.Job.SubmissionID | Number | ID of the submission. |
| VMRay.Job.MD5 | String | MD5 hash of the sample in the job. |
| VMRay.Job.SHA1 | String | SHA1 hash of the sample in the job. |
| VMRay.Job.SHA256 | String | SHA256 hash of the sample in the job. |
| VMRay.Job.SSDeep | String | ssdeep hash of the sample in the job. |
| VMRay.Job.VMName | String | Name of the virtual machine. |
| VMRay.Job.VMID | Number | ID of the virtual machine. |
| VMRay.Job.Status | String | Status of the job. |
Command Example
!vmray-get-job-by-id job_id=365547
Context Example
{
"VMRay.Job": {
"VMName": "win7_32_sp1",
"SampleID": 3902238,
"SHA1": "868a53c394f29f8d3aac7b0a20a371999045b6ed",
"SubmissionID": 4569262,
"SHA256": "b8a4b647e56cb71773d0086b51906b902a7ccafe699f4068da4cb5cd234d9d66",
"SSDeep": "1536:Hg8ktOZtz+PZvpJyrOM1GhFNkYL2BxNRjWW:H/kY0Z3yrOMGTkrNRjH",
"Status": "inwork",
"VMID": 3,
"JobID": 365547,
"MD5": "2e0499dc90c2d715a53e05b1890e0442"
}
}
Human Readable Output
Job results for job id: 365547
| Attribute | Value |
|---|---|
| JobID | 365547 |
| SampleID | 3902238 |
| VMName | win7_32_sp1 |
| VMID | 3 |
vmray-get-summary
Retrieves the Summary JSON v2 for a specific analysis.
Base Command
vmray-get-summary
Input
| Argument Name | Description | Required |
|---|---|---|
| analysis_id | ID of the analysis from which to retrieve the Summary JSON v2 from (analysis ID is returned e.g. from vmray-get-analysis-by-sample). | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| InfoFile.Name | string | Filename |
| InfoFile.EntryID | string | The EntryID of the Summary JSON v2 |
| InfoFile.Size | number | The file size of the Summary JSON v2 |
| InfoFile.Info | string | MIME type of the Summary JSON v2 |
Command Example
!vmray-get-summary analysis_id=2779353
Context Example
{
"InfoFile": {
"EntryID": "407@21232f297a57a5a743894a0e4a801fc3$&$9c7fe1a0-4045-4b69-8257-08ef3306318a",
"Extension": "json",
"Info": "application/json",
"Name": "summary_v2.json",
"Size": 37630,
"Type": "ASCII text, with very long lines"
}
}
Human Readable Output
Returned file: summary_v2.json Download
vmray-get-screenshots
Retrieves screenshots taken during a specific dynamic analysis. The screenshots are stored with file names like ‘analysis_5_screenshot_2.png’. In this example, ‘5’ represents the analysis ID from which the screenshot came, and ‘2’ indicates that it’s the third screenshot taken during the analysis, in chronological order.
Base Command
vmray-get-screenshots
Input
| Argument Name | Description | Required |
|---|---|---|
| analysis_id | ID of the analysis from which to retrieve the screenshots from (analysis ID is returned e.g. from vmray-get-analysis-by-sample). | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| InfoFile.Name | string | Filename |
| InfoFile.EntryID | string | The EntryID of the file |
| InfoFile.Size | number | The file size of the file |
| InfoFile.Info | string | MIME type of the file |
Command example
!vmray-get-screenshots analysis_id="50615"
Context Example
{
"InfoFile": [
{
"EntryID": "488@b7d0844f-d230-402a-81de-154dc1c57cc9",
"Extension": "png",
"Info": "image/png",
"Name": "analysis_50615_screenshot_0.png",
"Size": 753660,
"Type": "PNG image data, 800 x 600, 8-bit/color RGB, non-interlaced"
},
{
"EntryID": "489@b7d0844f-d230-402a-81de-154dc1c57cc9",
"Extension": "png",
"Info": "image/png",
"Name": "analysis_50615_screenshot_1.png",
"Size": 412598,
"Type": "PNG image data, 800 x 600, 8-bit/color RGB, non-interlaced"
}
]
}
vmray-get-license-usage-verdicts
Gets the usage of verdicts from VMRay.
Base Command
vmray-get-license-usage-verdicts
Input
There is no input for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| VMRay.VerdictQuota.PeriodEndDate | string | License end date. |
| VMRay.VerdictQuota.VerdictQuota | number | Total number of available verdicts (per month). |
| VMRay.VerdictQuota.VerdictRemaining | number | Remaining number of verdicts (per month). |
| VMRay.VerdictQuota.VerdictUsage | number | Percentages used. |
Command Example
#### Context Example
```json
{
"VMRay.VerdictQuota": {
"PeriodEndDate": "2024-02-03 14:12 (UTC+1)",
"VerdictQuota": 100,
"VerdictRemaining": 90,
"VerdictUsage": 10
}
}
Human Readable Output
| VerdictQuota | 100 |
| VerdictRemaining | 90 |
| VerdictUsage | 10.0 |
| PeriodEndDate | 2024-02-03 14:12 (UTC+1) |
vmray-get-license-usage-reports
Gets the usage of reports from VMRay.
Base Command
vmray-get-license-usage-reports
Input
There is no input for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| VMRay.ReportQuota.PeriodEndDate | string | License end date. |
| VMRay.ReportQuota.VerdictQuota | number | Total number of available reports (per month). |
| VMRay.ReportQuota.VerdictRemaining | number | Remaining number of reports (per month). |
| VMRay.ReportQuota.VerdictUsage | number | Percentages used. |
Context Example
{
"VMRay.ReportsQuota": {
"PeriodEndDate": "2024-02-03 14:12 (UTC+1)",
"ReportQuota": 100,
"ReportRemaining": 90,
"ReportUsage": 10
}
}
Command Example
vmray-get-license-usage-reports
Human Readable Output
| ReportQuota | 100 |
| ReportRemaining | 90 |
| ReportUsage | 10.0 |
| PeriodEndDate | 2024-02-03 14:12 (UTC+1) |
vmray-get-pdf-report
Retrieves the PDF report for a specific sample.
Base Command
vmray-get-pdf-report
Input
| Argument Name | Description | Required |
|---|---|---|
| sample_id | ID of the sample from which to retrieve the PDF report. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| InfoFile.Name | string | Filename. |
| InfoFile.EntryID | string | The EntryID of the PDF report. |
| InfoFile.Size | number | The file size of the PDF report. |
| InfoFile.Info | string | MIME type of the PDF report. |
Configuration parameters
integrationReliability— Source Reliabilityserver— Server URL (e.g., https://cloud.vmray.com) (required)credentials—proxy— Use system proxy settingsinsecure— Trust any certificate (not secure)retry_on_rate_limit— Retry requests when API is rate limitedapi_key— API Key (Deprecated)
Commands (20)
-
get_job_sampleDeprecatedThis command performs a function similar to the 'vmray-get-job-by-sample' command.
-
get_resultsDeprecatedsimilar to vmray-get-sample.
-
upload_sampleDeprecatedRetrieves a sample using the sample ID. (Deprecated).
-
vmray-add-tagAdds a tag to an analysis and/or a submission.
-
vmray-delete-tagDeletes tags from an analysis and/or a submission.
-
vmray-get-analysis-by-sampleRetrieves all analysis details for a specified sample.
-
vmray-get-iocsRetrieves Indicators of Compromise for a specified sample.
-
vmray-get-job-by-idRetrieves a job by job ID.
-
vmray-get-job-by-sampleRetrieves details for all jobs for a specified sample.
-
vmray-get-license-usage-reportsGet the used quota of reports.
-
vmray-get-license-usage-verdictsGet the used quota of verdicts.
-
vmray-get-pdf-reportRetrieves the PDF report for a specific sample.
-
vmray-get-sampleRetrieves a sample using the sample ID.
-
vmray-get-sample-by-hashRetrieves sample information by hash.
-
vmray-get-screenshotsRetrieves screenshots taken during a specific dynamic analysis. The screenshots are stored with file names like 'analysis_5_screenshot_2.png'. In this example, '5' represents the analysis ID from which the screenshot came, and '2' indicates that it's the third screenshot taken during the analysis, in chronological order.
-
vmray-get-submissionRetrieves the results of a submission.
-
vmray-get-summaryRetrieves the Summary JSON v2 for a specific analysis.
-
vmray-get-threat-indicatorsRetrieves threat indicators (VTI).
-
vmray-upload-sampleSubmits a sample to VMRay for analysis.
-
vmray-upload-urlSubmits a URL for analysis.
import io import os from dataclasses import dataclass from zipfile import ZipFile import demistomock as demisto # noqa: F401 import urllib3 from CommonServerPython import * # noqa: F401 """ GLOBAL PARAMS """ API_KEY = demisto.params().get("api_key") or demisto.params().get("credentials", {}).get("password") if not API_KEY: raise ValueError("The API Key parameter is required.") SERVER = ( demisto.params()["server"][:-1] if (demisto.params()["server"] and demisto.params()["server"].endswith("/")) else demisto.params()["server"] ) RETRY_ON_RATE_LIMIT = demisto.params().get("retry_on_rate_limit", True) SERVER += "/rest/" USE_SSL = not demisto.params().get("insecure", False) PROXY = demisto.params().get("proxy", True) HEADERS = {"Authorization": f"api_key {API_KEY}", "User-Agent": "Cortex XSOAR/1.1.11"} ERROR_FORMAT = "Error in API call to VMRay [{}] - {}" RELIABILITY = demisto.params().get("integrationReliability", DBotScoreReliability.C) or DBotScoreReliability.C INDEX_LOG_DELIMITER = "|" VENDOR_NAME = "vmray" # Disable insecure warnings urllib3.disable_warnings() """ HELPER DICTS """ SEVERITY_DICT = { "malicious": "Malicious", "suspicious": "Suspicious", "not_suspicious": "Good", "blacklisted": "Blacklisted", "whitelisted": "Whitelisted", "unknown": "Unknown", None: "Unknown", } VERDICT_DICT = { "malicious": "Malicious", "suspicious": "Suspicious", "clean": "Benign", "not_available": "Not Available", None: "Not Available", } DBOTSCORE = { "Malicious": 3, "Suspicious": 2, "Clean": 1, "Benign": 1, "Not Available": 0, } RATE_LIMIT_REACHED = 429 MAX_RETRIES = 10 """ HELPER CLASSES """ @dataclass class ScreenshotLogEntry: timestamp: int file_size: int md5: str sha1: str sha256: str filename: str @classmethod def parse(cls, line: bytes) -> "ScreenshotLogEntry": """Parse a log line and return a ScreenshotLogEntry instance.""" parts = [part.strip() for part in line.decode("utf-8", errors="replace").split(INDEX_LOG_DELIMITER)] if len(parts) != 4: raise ValueError(f"Expected 4 parts separated by `{INDEX_LOG_DELIMITER}`, got {len(parts)}") timestamp = int(parts[0]) file_size = int(parts[1]) filename = parts[3] # Parse the hash string hashes = {} for hash_pair in parts[2].split(","): key, value = hash_pair.split("=") hashes[key] = value return cls( timestamp=timestamp, file_size=file_size, md5=hashes["md5"], sha1=hashes["sha1"], sha256=hashes["sha256"], filename=filename, ) """ HELPER FUNCTIONS """ def is_json(response): """Checks if response is jsonable Args: response (requests.Response): Returns: bool: true if object is jsonable """ try: response.json() except ValueError: return False return True def check_id(id_to_check: int | str) -> bool: """Checks if parameter id_to_check is a number Args: id_to_check (int or str): Returns: bool: True if is a number, else returns error """ if isinstance(id_to_check, int) or (isinstance(id_to_check, str) and id_to_check.isdigit()): return True raise ValueError(f"Invalid ID `{id_to_check}` provided.") def get_billing_type(analysis_id: int) -> str | None: """Try to read the billing type from the analysis.""" response = http_request("GET", f"analysis/{analysis_id}") if (analysis_data := response.get("data")) is not None: return analysis_data.get("analysis_billing_type") return None def build_errors_string(errors): """ Args: errors (list, dict or unicode): Returns: str: error message """ if isinstance(errors, str): return str(errors) elif isinstance(errors, list): err_str = "" for error in errors: err_str += error.get("error_msg") + ".\n" else: err_str = errors.get("error_msg") return err_str def http_request(method, url_suffix, params=None, files=None, get_raw=False, ignore_errors=False): """General HTTP request. Args: ignore_errors (bool): method: (str) 'GET', 'POST', 'DELETE' 'PUT' url_suffix: (str) params: (dict) files: (dict) get_raw: (bool) return raw data instead of dict Returns: dict: response json """ def find_error(may_be_error_inside): """Function will search for dict with 'errors' or 'error_msg' key Args: may_be_error_inside: object, any object Returns: None if no error presents Errors list/string if errors inside. """ if isinstance(may_be_error_inside, list): for obj in may_be_error_inside: ans = find_error(obj) if ans: return ans return None if isinstance(may_be_error_inside, dict): if "error_msg" in may_be_error_inside: return may_be_error_inside["error_msg"] if "errors" in may_be_error_inside and may_be_error_inside.get("errors"): return may_be_error_inside["errors"] for value in may_be_error_inside.values(): err_r = find_error(value) if err_r: return err_r return None def error_handler(res): # pragma: no cover if res.status_code == RATE_LIMIT_REACHED and "Retry-After" in res.headers: return_error(f"Rate limit exceeded! Please wait {res.headers.get('Retry-After', 0)} seconds and re-run.") if res.status_code in {405, 401}: return_error(ERROR_FORMAT.format(res.status_code, "Token may be invalid")) try: res = generic_http_request( method=method, server_url=SERVER, verify=USE_SSL, proxy=PROXY, client_headers=HEADERS, url_suffix=url_suffix, files=files, params=params, retries=MAX_RETRIES, error_handler=error_handler, resp_type="response", ok_codes=(200, 201, 202, 204), status_list_to_retry=[429], ) if not get_raw and not is_json(res): raise ValueError response = res.json() if not get_raw else res.content if res.status_code not in {200, 201, 202, 204} and not ignore_errors: if get_raw and isinstance(response, str): # this might be json even if get_raw is True because the API will return errors as json try: response = json.loads(response) except ValueError: pass err = find_error(response) if not err: err = res.text return_error(ERROR_FORMAT.format(res.status_code, err)) err = find_error(response) if err: if "no jobs were created" in build_errors_string(err): err_message = ( err[0].get("error_msg") + ". There is a possibility this file has been analyzed " "before. Please change the Analysis Caching mode for this " 'API key to something other than "Legacy" in the VMRay ' "Web Interface." ) err[0]["error_msg"] = err_message return_error(ERROR_FORMAT.format(res.status_code, err)) return response except ValueError: # If no JSON is present, must be an error that can't be ignored return_error(ERROR_FORMAT.format(res.status_code, res.text)) except Exception as e: return_error(str(e)) def dbot_score_by_hash(data): """Gets a dict containing MD5/SHA1/SHA256/SSDeep and return dbotscore Args: data: (dict) Returns: list: dbot scores """ hashes = ["MD5", "SHA256", "SHA1", "SSDeep"] scores = [] for hash_type in hashes: if hash_type in data: scores.append( { "Indicator": data.get(hash_type), "Type": "hash", "Vendor": VENDOR_NAME, "Score": DBOTSCORE.get(data.get("Verdict", 0)), "Reliability": RELIABILITY, } ) return scores def build_job_data(data): """ Args: data: any kind of object. Returns: list: list of jobs """ def build_entry(entry_data): entry = {} entry["JobID"] = entry_data.get("job_id") entry["SampleID"] = entry_data.get("job_sample_id") entry["SubmissionID"] = entry_data.get("job_submission_id") entry["MD5"] = entry_data.get("job_sample_md5") entry["SHA1"] = entry_data.get("job_sample_sha1") entry["SHA256"] = entry_data.get("job_sample_sha256") entry["SSDeep"] = entry_data.get("job_sample_ssdeep") entry["VMName"] = entry_data.get("job_vm_name") entry["VMID"] = entry_data.get("job_vm_id") entry["Status"] = entry_data.get("job_status") return entry jobs_list = [] if isinstance(data, list): for item in data: jobs_list.append(build_entry(item)) elif isinstance(data, dict): jobs_list = build_entry(data) return jobs_list def build_finished_job(job_id, sample_id): entry = {} entry["JobID"] = job_id entry["SampleID"] = sample_id entry["Status"] = "Finished/NotExists" return entry def build_analysis_data(analyses): """ Args: analyses: (dict) of analysis Returns: dict: formatted entry context """ entry_context = {} entry_context["VMRay.Analysis(val.AnalysisID === obj.AnalysisID)"] = [ { "AnalysisID": analysis.get("analysis_id"), "AnalysisURL": analysis.get("analysis_webif_url"), "SampleID": analysis.get("analysis_sample_id"), "Verdict": VERDICT_DICT.get(analysis.get("analysis_verdict")), "VerdictReason": analysis.get("analysis_verdict_reason_description"), "Severity": SEVERITY_DICT.get(analysis.get("analysis_severity")), "JobCreated": analysis.get("analysis_job_started"), "SHA1": analysis.get("analysis_sample_sha1"), "MD5": analysis.get("analysis_sample_md5"), "SHA256": analysis.get("analysis_sample_sha256"), } for analysis in analyses ] scores = [] # type: list for analysis in entry_context: scores.extend(dbot_score_by_hash(analysis)) entry_context[outputPaths["dbotscore"]] = scores return entry_context def build_upload_params(): """Builds params for upload_file Returns: dict: params """ # additional params doc_pass = demisto.args().get("document_password") arch_pass = demisto.args().get("archive_password") sample_type = demisto.args().get("sample_type") shareable = demisto.args().get("shareable") max_jobs = demisto.args().get("max_jobs") tags = demisto.args().get("tags") net_scheme_name = demisto.args().get("net_scheme_name") params = {} if doc_pass: params["document_password"] = doc_pass if arch_pass: params["archive_password"] = arch_pass if sample_type: params["sample_type"] = sample_type params["shareable"] = shareable == "true" if max_jobs: if (isinstance(max_jobs, str) and max_jobs.isdigit()) or isinstance(max_jobs, int): params["max_jobs"] = int(max_jobs) else: raise ValueError("max_jobs arguments isn't a number") if tags: params["tags"] = tags if net_scheme_name: params["user_config"] = '{"net_scheme_name": "' + str(net_scheme_name) + '"}' return params def test_module(): """Simple get request to see if connected""" response = http_request("GET", "analysis?_limit=1") if response.get("result"): demisto.results("ok") else: raise ValueError(f"Can't authenticate: {response}") def submit(params, files=None): """Submit a file/URL to VMRay Platform Args: params: (dict) files: (dict) Returns: dict: response """ suffix = "sample/submit" results = http_request("POST", url_suffix=suffix, params=params, files=files) return results def build_submission_data(raw_response, type_): """Process a submission response from VMRay Platform Args: raw_response: (dict) type_: (str) """ data = raw_response.get("data") jobs_list = [] jobs = data.get("jobs", []) for job in jobs: if isinstance(job, dict): job_entry = {} job_entry["JobID"] = job.get("job_id") job_entry["Created"] = job.get("job_created") job_entry["SampleID"] = job.get("job_sample_id") job_entry["VMName"] = job.get("job_vm_name") job_entry["VMID"] = job.get("job_vm_id") job_entry["JobRuleSampleType"] = job.get("job_jobrule_sampletype") jobs_list.append(job_entry) samples_list = [] samples = data.get("samples", []) for sample in samples: if isinstance(sample, dict): sample_entry = {} sample_entry["SampleID"] = sample.get("sample_id") sample_entry["SampleURL"] = sample.get("sample_webif_url") sample_entry["Created"] = sample.get("sample_created") sample_entry["FileName"] = sample.get("submission_filename") sample_entry["FileSize"] = sample.get("sample_filesize") sample_entry["SSDeep"] = sample.get("sample_ssdeephash") sample_entry["SHA1"] = sample.get("sample_sha1hash") samples_list.append(sample_entry) submissions_list = [] submissions = data.get("submissions", []) for submission in submissions: if isinstance(submission, dict): submission_entry = {} submission_entry["SubmissionID"] = submission.get("submission_id") submission_entry["SubmissionURL"] = submission.get("submission_webif_url") submission_entry["SampleID"] = submission.get("submission_sample_id") submissions_list.append(submission_entry) entry_context = {} entry_context["VMRay.Job(val.JobID === obj.JobID)"] = jobs_list entry_context["VMRay.Sample(val.SampleID === obj.SampleID)"] = samples_list entry_context["VMRay.Submission(val.SubmissionID === obj.SubmissionID)"] = submissions_list table = { "Jobs ID": [job.get("JobID") for job in jobs_list], "Samples ID": [sample.get("SampleID") for sample in samples_list], "Submissions ID": [submission.get("SubmissionID") for submission in submissions_list], "Sample URL": [sample.get("SampleURL") for sample in samples_list], } human_readable = tableToMarkdown( type_ + " submitted to VMRay", t=table, headers=["Jobs ID", "Samples ID", "Submissions ID", "Sample URL"], ) return_outputs(readable_output=human_readable, outputs=entry_context, raw_response=raw_response) def encode_file_name(file_name): """ encodes the file name - i.e ignoring invalid chars and removing backslashes Args: file_name (str): name of the file Returns: encoded file name """ file_name = file_name.translate(dict.fromkeys(map(ord, '<>:"/\\|?*'))) return file_name.encode("utf-8", "ignore") def upload_sample_command(): """Uploads a file to vmray""" # Preserve BC file_id = demisto.args().get("entry_id") if demisto.args().get("entry_id") else demisto.args().get("file_id") params = build_upload_params() file_obj = demisto.getFilePath(file_id) # Ignoring non ASCII file_name = encode_file_name(file_obj["name"]) file_path = file_obj["path"] with open(file_path, "rb") as f: files = {"sample_file": (file_name, f)} # Request call raw_response = submit(params, files=files) return build_submission_data(raw_response, "File") def upload_url_command(): """upload a URL to VMRay""" args = demisto.args() url = args.get("url") if isinstance(url, str): url = str(url) params = build_upload_params() params["sample_url"] = url raw_response = submit(params) return build_submission_data(raw_response, "URL") def get_analysis(sample, params=None): """Uploading sample to vmray Args: sample (str): sample id params (dict): dict of params Returns: dict: response """ suffix = f"analysis/sample/{sample}" response = http_request("GET", suffix, params=params) return response def get_analysis_command(): sample_id = demisto.args().get("sample_id") check_id(sample_id) limit = demisto.args().get("limit") params = {"_limit": limit} raw_response = get_analysis(sample_id, params) data = raw_response.get("data") if data: entry_context = build_analysis_data(data) human_readable = tableToMarkdown( f"Analysis results from VMRay for ID {sample_id}:", entry_context.get("VMRay.Analysis(val.AnalysisID === obj.AnalysisID)"), headers=["AnalysisID", "SampleID", "Verdict", "AnalysisURL"], ) return_outputs(human_readable, entry_context, raw_response=raw_response) else: return_outputs(f"#### No analysis found for sample id {sample_id}", None) def get_submission(submission_id): """ Args: submission_id (str): if of submission Returns: dict: response """ suffix = f"submission/{submission_id}" response = http_request("GET", url_suffix=suffix) return response def get_submission_command(): submission_id = demisto.args().get("submission_id") check_id(submission_id) demisto.info(f"Getting submission for {submission_id}") try: raw_response = get_submission(submission_id) except Exception as err: demisto.error(str(err)) raise err data = raw_response.get("data") if data: # Build entry entry = {} entry["IsFinished"] = data.get("submission_finished") entry["HasErrors"] = data.get("submission_has_errors") entry["SubmissionID"] = data.get("submission_id") entry["SubmissionURL"] = data.get("submission_webif_url") entry["MD5"] = data.get("submission_sample_md5") entry["SHA1"] = data.get("submission_sample_sha1") entry["SHA256"] = data.get("submission_sample_sha256") entry["SSDeep"] = data.get("submission_sample_ssdeep") entry["Verdict"] = VERDICT_DICT.get(data.get("submission_verdict")) entry["VerdictReason"] = data.get("submission_verdict_reason_description") entry["Severity"] = SEVERITY_DICT.get(data.get("submission_severity")) entry["SampleID"] = data.get("submission_sample_id") scores = dbot_score_by_hash(entry) entry_context = { "VMRay.Submission(val.SubmissionID === obj.SubmissionID)": entry, outputPaths.get("dbotscore"): scores, } human_readable = tableToMarkdown( "Submission results from VMRay for ID {} with verdict of {}".format(submission_id, entry.get("Verdict", "Unknown")), entry, headers=[ "IsFinished", "Verdict", "HasErrors", "MD5", "SHA1", "SHA256", "SSDeep", "SubmissionURL", ], ) return_outputs(human_readable, entry_context, raw_response=raw_response) else: return_outputs( f"No submission found in VMRay for submission id: {submission_id}", {}, ) def get_sample(sample_id): """building http request for get_sample_command Args: sample_id (str, int): Returns: dict: data from response """ suffix = f"sample/{sample_id}" response = http_request("GET", suffix) return response def create_sample_entry(data): """Construct output dict from api response data Args: data (dict): Returns: dict: entry """ entry = {} entry["SampleID"] = data.get("sample_id") entry["SampleURL"] = data.get("sample_webif_url") entry["FileName"] = data.get("sample_filename") entry["MD5"] = data.get("sample_md5hash") entry["SHA1"] = data.get("sample_sha1hash") entry["SHA256"] = data.get("sample_sha256hash") entry["SSDeep"] = data.get("sample_ssdeephash") entry["Verdict"] = VERDICT_DICT.get(data.get("sample_verdict")) entry["VerdictReason"] = data.get("sample_verdict_reason_description") entry["Severity"] = SEVERITY_DICT.get(data.get("sample_severity")) entry["Type"] = data.get("sample_type") entry["Created"] = data.get("sample_created") entry["Classification"] = data.get("sample_classifications") entry["ChildSampleIDs"] = data.get("sample_child_sample_ids") entry["ParentSampleIDs"] = data.get("sample_parent_sample_ids") entry["URL"] = data.get("sample_url") return entry def get_sample_command(): sample_id = demisto.args().get("sample_id") check_id(sample_id) # query API raw_response = get_sample(sample_id) # build response dict data = raw_response.get("data") entry = create_sample_entry(data) scores = dbot_score_by_hash(entry) entry_context = { "VMRay.Sample(val.SampleID === obj.SampleID)": entry, outputPaths.get("dbotscore"): scores, } header_type_name = "FileName" score = DBOTSCORE.get(entry.get("Verdict", "Not Available"), 0) if (url := entry.get("URL")) is not None: dbot_score = Common.DBotScore( indicator=url, indicator_type="url", integration_name=VENDOR_NAME, score=score, reliability=RELIABILITY, ) url_ctx = Common.URL(url=url, dbot_score=dbot_score) entry_context.update(url_ctx.to_context()) header_type_name = "URL" else: dbot_score = Common.DBotScore( indicator=entry["SHA256"], indicator_type="file", integration_name=VENDOR_NAME, score=score, reliability=RELIABILITY, ) file_ctx = Common.File( dbot_score=dbot_score, md5=entry["MD5"], sha1=entry["SHA1"], sha256=entry["SHA256"], ssdeep=entry["SSDeep"], name=entry["FileName"], ) entry_context.update(file_ctx.to_context()) human_readable = tableToMarkdown( "Results for sample id: {} with verdict {}".format(entry.get("SampleID"), entry.get("Verdict", "Unknown")), entry, headers=[header_type_name, "Type", "MD5", "SHA1", "SHA256", "SSDeep", "SampleURL"], ) return_outputs(human_readable, entry_context, raw_response=raw_response) def get_sample_by_hash(hash_type, hash): """building http request for get_sample_by_hash_command Args: hash_type (str) hash (str) Returns: list[dict]: list of matching samples """ suffix = f"sample/{hash_type}/{hash}" response = http_request("GET", suffix) return response def get_sample_by_hash_command(): hash = demisto.args().get("hash").strip() hash_type_lookup = {32: "md5", 40: "sha1", 64: "sha256"} hash_type = hash_type_lookup.get(len(hash)) if hash_type is None: error_string = " or ".join(f"{len_} ({type_})" for len_, type_ in hash_type_lookup.items()) raise ValueError(f"Invalid hash provided, must be of length {error_string}. Provided hash had a length of {len(hash)}.") # query API raw_response = get_sample_by_hash(hash_type, hash) # build response dict samples = raw_response.get("data") if samples: # VMRay outputs entry_context = {} context_key = f"VMRay.Sample(val.{hash.upper()} === obj.{hash.upper()})" entry_context[context_key] = [create_sample_entry(sample) for sample in samples] # DBotScore output scores = [] # type: list for sample in entry_context[context_key]: scores += dbot_score_by_hash(sample) entry_context[outputPaths["dbotscore"]] = scores # Indicator output # just use the first sample that is returned by the API for now entry = entry_context[context_key][0] file = Common.File( None, md5=entry["MD5"], sha1=entry["SHA1"], sha256=entry["SHA256"], ssdeep=entry["SSDeep"], name=entry["FileName"] ) entry_context.update(file.to_context()) human_readable = tableToMarkdown( f"Results for {hash_type} hash {hash}:", entry_context[context_key], headers=["SampleID", "FileName", "Type", "Verdict", "SampleURL"], ) return_outputs(human_readable, entry_context, raw_response=raw_response) else: return_outputs( f"No samples found for {hash_type} hash {hash}", {}, ) def get_job(job_id, sample_id): """ Args: sample_id (str): job_id (str): Returns: dict of response, if not exists returns: { 'error_msg': 'No such element' 'result': 'error' } """ suffix = f"job/{job_id}" if job_id else f"job/sample/{sample_id}" response = http_request("GET", suffix, ignore_errors=True) return response def get_job_command(): job_id = demisto.args().get("job_id") sample_id = demisto.args().get("sample_id") if sample_id: check_id(sample_id) else: check_id(job_id) vmray_id = job_id if job_id else sample_id title = "job" if job_id else "sample" raw_response = get_job(job_id=job_id, sample_id=sample_id) data = raw_response.get("data") if not data or raw_response.get("result") == "error": entry = build_finished_job(job_id=job_id, sample_id=sample_id) human_readable = f"#### Couldn't find a job for the {title}: {vmray_id}. Either the job completed, or does not exist." else: entry = build_job_data(data) sample = entry[0] if isinstance(entry, list) else entry human_readable = tableToMarkdown( f"Job results for {title} id: {vmray_id}", sample, headers=["JobID", "SampleID", "VMName", "VMID"], ) entry_context = {"VMRay.Job(val.JobID === obj.JobID && val.SampleID === obj.SampleID)": entry} return_outputs(human_readable, entry_context, raw_response=raw_response) def get_threat_indicators(sample_id): """ Args: sample_id (str): Returns: dict: response """ suffix = f"sample/{sample_id}/threat_indicators" response = http_request("GET", suffix).get("data") return response def get_threat_indicators_command(): sample_id = demisto.args().get("sample_id") check_id(sample_id) raw_response = get_threat_indicators(sample_id) data = raw_response.get("threat_indicators") # Build Entry Context if data and isinstance(data, list): entry_context_list = [] for indicator in data: entry = {} entry["AnalysisID"] = indicator.get("analysis_ids") entry["Category"] = indicator.get("category") entry["Classification"] = indicator.get("classifications") entry["ID"] = indicator.get("id") entry["Operation"] = indicator.get("operation") entry_context_list.append(entry) human_readable = tableToMarkdown( f"Threat indicators for sample ID: {sample_id}:", entry_context_list, headers=["ID", "AnalysisID", "Category", "Classification", "Operation"], ) entry_context = {"VMRay.ThreatIndicator(obj.ID === val.ID)": entry_context_list} return_outputs(human_readable, entry_context, raw_response={"threat_indicators": data}) else: return_outputs( f"No threat indicators for sample ID: {sample_id}", {}, raw_response=raw_response, ) def post_tags_to_analysis(analysis_id, tag): """ Args: analysis_id (str): tag (str): Returns: dict: """ suffix = f"analysis/{analysis_id}/tag/{tag}" response = http_request("POST", suffix) return response def post_tags_to_submission(submission_id, tag): """ Args: submission_id (str): tag (str): Returns: dict: """ suffix = f"submission/{submission_id}/tag/{tag}" response = http_request("POST", suffix) return response def post_tags(): analysis_id = demisto.args().get("analysis_id") submission_id = demisto.args().get("submission_id") tag = demisto.args().get("tag") if not submission_id and not analysis_id: raise ValueError("No submission ID or analysis ID has been provided") if analysis_id: analysis_status = post_tags_to_analysis(analysis_id, tag) if analysis_status.get("result") == "ok": return_outputs( f"Tags: {tag} has been added to analysis: {analysis_id}", {}, raw_response=analysis_status, ) if submission_id: submission_status = post_tags_to_submission(submission_id, tag) if submission_status.get("result") == "ok": return_outputs( f"Tags: {tag} has been added to submission: {submission_id}", {}, raw_response=submission_status, ) def delete_tags_from_analysis(analysis_id, tag): suffix = f"analysis/{analysis_id}/tag/{tag}" response = http_request("DELETE", suffix) return response def delete_tags_from_submission(submission_id, tag): suffix = f"submission/{submission_id}/tag/{tag}" response = http_request("DELETE", suffix) return response def delete_tags(): analysis_id = demisto.args().get("analysis_id") submission_id = demisto.args().get("submission_id") tag = demisto.args().get("tag") if not submission_id and not analysis_id: raise ValueError("No submission ID or analysis ID has been provided") if submission_id: submission_status = delete_tags_from_submission(submission_id, tag) if submission_status.get("result") == "ok": return_outputs( f"Tags: {tag} has been removed from submission: {submission_id}", {}, raw_response=submission_status, ) if analysis_id: analysis_status = delete_tags_from_analysis(analysis_id, tag) if analysis_status.get("result") == "ok": return_outputs( f"Tags: {tag} has been removed from analysis: {analysis_id}", {}, raw_response=analysis_status, ) def get_iocs(sample_id, all_artifacts): """ Args: sample_id (str): Returns: dict: response """ suffix = f"sample/{sample_id}/iocs" if all_artifacts: suffix += "?all_artifacts=true" response = http_request("GET", suffix) return response def get_iocs_command(): # pragma: no cover def get_hashed(lst): """ Args: lst (List[dict]): list of hashes attributes Returns: List[dict]:list of hashes attributes in demisto's favor """ hashes_dict = {"MD5": "md5_hash", "SHA1": "sha1_hash", "SHA256": "sha256_hash", "SSDeep": "ssdeep_hash"} return [{k: hashes.get(v) for k, v in hashes_dict.items()} for hashes in lst] sample_id = demisto.args().get("sample_id") check_id(sample_id) all_artifacts = demisto.args().get("all_artifacts", "false").lower() == "true" raw_response = get_iocs(sample_id, all_artifacts) data = raw_response.get("data", {}).get("iocs", {}) command_results_list = [] indicator_types = { # mapping of # VMRay artifact type -> XSOAR score type, Indicator class, Main value key, Headers "Domain": (DBotScoreType.DOMAIN, Common.Domain, "Domain", ["OriginalDomains", "Countries"]), # noqa: E241, E501 "EmailAddress": (DBotScoreType.EMAIL, Common.EMAIL, "EmailAddress", ["IsRecipient", "IsSender", "Subjects"]), # noqa: E241, E501 "Email": ( None, None, "Subject", [ "Subject", "Sender", "Recipients", # noqa: E241, E501 "NrAttachments", "NrLinks", ], ), "Filename": (None, None, "Filename", ["Operations"]), # noqa: E241 "File": ( DBotScoreType.FILE, None, "Filename", [ "Filenames", "MD5", "SHA1", "SHA256", # noqa: E241, E501 "Operations", ], ), "IP": (DBotScoreType.IP, Common.IP, "IP", ["Domains", "Countries", "Protocols"]), # noqa: E241, E501 "Mutex": (None, None, "Name", ["Operations", "ParentProcessesNames"]), # noqa: E241, E501 "Process": (None, None, "ProcessNames", ["CmdLine"]), # noqa: E241 "Registry": ( None, None, "Name", [ "ValueTypes", "Operations", # noqa: E241, E501 "ParentProcessesNames", ], ), "URL": ( DBotScoreType.URL, Common.URL, "URL", [ "OriginalURLs", "Categories", # noqa: E241, E501 "Countries", "Methods", "IPAddresses", "ParentProcessesNames", ], ), } # this will be extended with every call to generate_results # we need to keep the state and always add new items to it, so that new results don't replace information from # older ones context_output = {"SampleID": sample_id, "IOC": {}} artifact_type = "artifact" if all_artifacts else "IOC" # helper function to generate the CommandResults objects from the IOC information def generate_results(vmray_type, objects): res = [] dbot_score_type, indicator_class, key_field, headers = indicator_types[vmray_type] for object in objects: key_value = object[key_field] indicator = None if dbot_score_type == DBotScoreType.FILE: # special handing for File indicators since they need a hash as the indicator... hashes = object.get("Hashes", [{}])[0] dbot_score = Common.DBotScore( indicator=hashes.get("MD5"), indicator_type=dbot_score_type, integration_name=VENDOR_NAME, score=DBOTSCORE.get(object["Verdict"], 0), reliability=RELIABILITY, ) # ... and have multiple parameters indicator = Common.File( dbot_score, path=key_value, size=object.get("FileSize"), md5=hashes.get("MD5"), sha1=hashes.get("SHA1"), sha256=hashes.get("SHA256"), ssdeep=hashes.get("SSDeep"), file_type=object.get("MIMEType"), ) elif dbot_score_type is not None and indicator_class: # Generic handling for IOCs which have a corresponding Indicator type in XSOAR dbot_score = Common.DBotScore( indicator=key_value, indicator_type=dbot_score_type, integration_name=VENDOR_NAME, score=DBOTSCORE.get(object["Verdict"], 0), reliability=RELIABILITY, ) # first argument must always be the "main" value and second arg the score indicator = indicator_class(key_value, dbot_score) # fields that should be shown in human-readable output table_headers = [key_field, "IsIOC"] + headers + ["Verdict", "VerdictReason"] # add IOC to the final context output if vmray_type in context_output["IOC"]: context_output["IOC"][vmray_type].append(object) else: context_output["IOC"][vmray_type] = [object] if dbot_score_type == DBotScoreType.FILE: # for files we put the hashes manually in the readable output info = object.copy() info.update(info.get("Hashes", [{}])[0]) else: info = object try: # tableToMarkdown sometimes chokes on unicode input readable_output = tableToMarkdown(vmray_type + " " + artifact_type, info, headers=table_headers, removeNull=True) except UnicodeEncodeError: readable_output = " " res.append( CommandResults( outputs_prefix="VMRay.Sample", outputs_key_field="SampleID", outputs=context_output, readable_output=readable_output, indicator=indicator, ) ) return res domains = data.get("domains", []) command_results_list.append( generate_results( "Domain", [ { "AnalysisID": domain.get("analysis_ids"), "Countries": domain.get("countries"), "CountryCodes": domain.get("country_codes"), "Domain": domain.get("domain"), "ID": 0, # deprecated "IsIOC": domain.get("ioc"), "IOCType": domain.get("ioc_type"), "IpAddresses": domain.get("ip_addresses"), "OriginalDomains": domain.get("original_domains"), "ParentProcesses": domain.get("parent_processes"), "ParentProcessesNames": domain.get("parent_processes_names"), "Protocols": domain.get("protocols"), "Sources": domain.get("sources"), "Type": domain.get("type"), "Verdict": VERDICT_DICT.get(domain.get("verdict")), "VerdictReason": domain.get("verdict_reason"), } for domain in domains if domain.get("domain") ], ) ) email_addresses = data.get("email_addresses", []) command_results_list.append( generate_results( "EmailAddress", [ { "AnalysisID": email_address.get("analysis_ids"), "Classifications": email_address.get("classifications"), "EmailAddress": email_address.get("email_address"), "IsIOC": email_address.get("ioc"), "IsRecipient": email_address.get("recipient"), "IsSender": email_address.get("sender"), "IOCType": email_address.get("ioc_type"), "Subjects": email_address.get("subjects"), "ThreatNames": email_address.get("threat_names"), "Type": email_address.get("type"), "Verdict": VERDICT_DICT.get(email_address.get("verdict")), "VerdictReason": email_address.get("verdict_reason"), } for email_address in email_addresses if email_address.get("email_address") ], ) ) emails = data.get("emails", []) command_results_list.append( generate_results( "Email", [ { "AnalysisID": email.get("analysis_ids"), "AttachmentTypes": email.get("attachment_types"), "Classifications": email.get("classifications"), "Hashes": get_hashed(email.get("hashes")), "IsIOC": email.get("ioc"), "IOCType": email.get("ioc_type"), "NrAttachments": email.get("nr_attachments"), "NrLinks": email.get("nr_links"), "Recipients": email.get("recipients"), "Sender": email.get("sender"), "Subject": email.get("subject"), "ThreatNames": email.get("threat_names"), "Type": email.get("type"), "Verdict": VERDICT_DICT.get(email.get("verdict")), "VerdictReason": email.get("verdict_reason"), } for email in emails ], ) ) filenames = data.get("filenames", []) command_results_list.append( generate_results( "Filename", [ { "AnalysisID": filename.get("analysis_ids"), "Categories": filename.get("categories"), "Classifications": filename.get("classifications"), "Filename": filename.get("filename"), "IsIOC": filename.get("ioc"), "IOCType": filename.get("ioc_type"), "Operations": filename.get("operations"), "ThreatNames": filename.get("threat_names"), "Type": filename.get("type"), "Verdict": VERDICT_DICT.get(filename.get("verdict")), "VerdictReason": filename.get("verdict_reason"), } for filename in filenames if filename.get("filename") ], ) ) files = data.get("files", []) command_results_list.append( generate_results( "File", [ { "AnalysisID": file.get("analysis_ids"), "Categories": file.get("categories"), "Classifications": file.get("classifications"), "FileSize": file.get("file_size"), "Filename": file.get("filename"), "Filenames": file.get("filenames"), "Hashes": get_hashed(file.get("hashes")), "ID": 0, # deprecated "IsIOC": file.get("ioc"), "IOCType": file.get("ioc_type"), "MIMEType": file.get("mime_type"), "Name": file.get("filename"), # for backwards compatibility "NormFilename": file.get("norm_filename"), "Operation": file.get("operations"), # typo "Operations": file.get("operations"), "ParentFiles": file.get("parent_files"), "ParentProcesses": file.get("parent_processes"), "ParentProcessesNames": file.get("parent_processes_names"), "ResourceURL": file.get("resource_url"), "ThreatNames": file.get("threat_names"), "Type": file.get("type"), "Verdict": VERDICT_DICT.get(file.get("verdict")), "VerdictReason": file.get("verdict_reason"), } for file in files ], ) ) ips = data.get("ips", []) command_results_list.append( generate_results( "IP", [ { "AnalysisID": ip.get("analysis_ids"), "Country": ip.get("country"), "CountryCode": ip.get("country_code"), "Domains": ip.get("domains"), "IP": ip.get("ip_address"), "ID": 0, # deprecated "IsIOC": ip.get("ioc"), "IOCType": ip.get("ioc_type"), "Operation": None, # deprecated "ParentProcesses": ip.get("parent_processes"), "ParentProcessesNames": ip.get("parent_processes_names"), "Protocols": ip.get("protocols"), "Sources": ip.get("sources"), "Type": ip.get("type"), "Verdict": VERDICT_DICT.get(ip.get("verdict")), "VerdictReason": ip.get("verdict_reason"), } for ip in ips if ip.get("ip_address") ], ) ) mutexes = data.get("mutexes", []) command_results_list.append( generate_results( "Mutex", [ { "AnalysisID": mutex.get("analysis_ids"), "Classifications": mutex.get("classifications"), "ID": 0, # deprecated "IsIOC": mutex.get("ioc"), "IOCType": mutex.get("ioc_type"), "Name": mutex.get("mutex_name"), "Operation": mutex.get("operations"), # typo "Operations": mutex.get("operations"), "ParentProcesses": mutex.get("parent_processes"), "ParentProcessesNames": mutex.get("parent_processes_names"), "ThreatNames": mutex.get("threat_names"), "Type": mutex.get("type"), "Verdict": VERDICT_DICT.get(mutex.get("verdict")), "VerdictReason": mutex.get("verdict_reason"), } for mutex in mutexes if mutex.get("mutex_name") ], ) ) processes = data.get("processes", []) command_results_list.append( generate_results( "Process", [ { "AnalysisID": process.get("analysis_ids"), "Classifications": process.get("classifications"), "CmdLine": process.get("cmd_line"), "ImageNames": process.get("image_names"), "IsIOC": process.get("ioc"), "IOCType": process.get("ioc_type"), "ParentProcesses": process.get("parent_processes"), "ParentProcessesNames": process.get("parent_processes_names"), "ProcessNames": process.get("process_names"), "ThreatNames": process.get("threat_names"), "Type": process.get("type"), "Verdict": VERDICT_DICT.get(process.get("verdict")), "VerdictReason": process.get("verdict_reason"), } for process in processes if process.get("process_names") ], ) ) registry = data.get("registry", []) command_results_list.append( generate_results( "Registry", [ { "AnalysisID": reg.get("analysis_ids"), "Classifications": reg.get("classifications"), "ID": 0, # deprecated "IsIOC": reg.get("ioc"), "IOCType": reg.get("ioc_type"), "Name": reg.get("reg_key_name"), "Operation": reg.get("operations"), # typo "Operations": reg.get("operations"), "ParentProcesses": reg.get("parent_processes"), "ParentProcessesNames": reg.get("parent_processes_names"), "ThreatNames": reg.get("threat_names"), "Type": reg.get("type"), "ValueTypes": reg.get("reg_key_value_types"), "Verdict": VERDICT_DICT.get(reg.get("verdict")), "VerdictReason": reg.get("verdict_reason"), } for reg in registry if reg.get("reg_key_name") ], ) ) urls = data.get("urls", []) command_results_list.append( generate_results( "URL", [ { "AnalysisID": url.get("analysis_ids"), "Categories": url.get("categories"), "ContentTypes": url.get("content_types"), "Countries": url.get("countries"), "CountryCodes": url.get("country_codes"), "ID": 0, # deprecated "IPAddresses": url.get("ip_addresses"), "Methods": url.get("methods"), "Operation": None, # deprecated "OriginalURLs": url.get("original_urls"), "ParentFiles": url.get("parent_files"), "ParentProcesses": url.get("parent_processes"), "ParentProcessesNames": url.get("parent_processes_names"), "Referrers": url.get("referrers"), "Source": url.get("sources"), "Type": url.get("type"), "URL": url.get("url"), "UserAgents": url.get("user_agents"), "Verdict": VERDICT_DICT.get(url.get("verdict")), "VerdictReason": url.get("verdict_reason"), } for url in urls if url.get("url") ], ) ) return_results(command_results_list) def get_summary(analysis_id): """ Args: analysis_id (str): Returns: str: response """ suffix = f"analysis/{analysis_id}/archive/logs/summary_v2.json" response = http_request("GET", suffix, get_raw=True) return response def get_screenshots(analysis_id): """ Args: analysis_id (str): Returns: str: response """ suffix = f"analysis/{analysis_id}/archive?filenames=screenshots/*" response = http_request("GET", suffix, get_raw=True) return response def get_summary_command(): analysis_id = demisto.args().get("analysis_id") check_id(analysis_id) billing_type = get_billing_type(analysis_id) if billing_type == "detector": raise ValueError( "The current billing plan has no permissions to generate or download reports. " "If you want more information about the sample, use " "`vmray-get-threat-indicators` or `vmray-get-iocs` instead." ) summary_data = get_summary(analysis_id) file_entry = fileResult(filename="summary_v2.json", data=summary_data, file_type=EntryType.ENTRY_INFO_FILE) return_results(file_entry) def get_screenshots_command(): analysis_id = demisto.args().get("analysis_id") check_id(analysis_id) screenshots_data = get_screenshots(analysis_id) file_results = [] processed_screenshots = [] screenshot_counter = 0 try: with ZipFile(io.BytesIO(screenshots_data), "r") as screenshots_zip: index_log_data = screenshots_zip.read("screenshots/index.log") for line in index_log_data.splitlines(): log_entry = ScreenshotLogEntry.parse(line) if log_entry.sha256 in processed_screenshots: continue extension = os.path.splitext(log_entry.filename)[1] screenshot_data = screenshots_zip.read(f"screenshots/{log_entry.filename}") file_results.append( fileResult( filename=f"analysis_{analysis_id}_screenshot_{screenshot_counter}{extension}", data=screenshot_data, file_type=EntryType.IMAGE, ) ) processed_screenshots.append(log_entry.sha256) screenshot_counter += 1 except Exception as exc: # noqa demisto.error(f"Failed to read screenshots.zip, error: {exc}") raise exc else: demisto.debug(f"Successfully read screenshots.zip, found {screenshot_counter} screenshots") return_results(file_results) def vmray_get_license_usage_verdicts_command(): # pragma: no cover """ Returns: dict: response """ suffix = "billing_info" raw_response = http_request("GET", suffix) data = raw_response.get("data") entry = {} entry["VerdictsQuota"] = data.get("verdict_quota") entry["VerdictsRemaining"] = data.get("verdict_remaining") entry["VerdictsUsage"] = round( (100 / float(data.get("verdict_quota"))) * (float(data.get("verdict_quota")) - float(data.get("verdict_remaining"))), 2 ) entry["PeriodEndDate"] = data.get("end_date") markdown = tableToMarkdown( "VMRay Verdicts Quota Information", entry, headers=["VerdictsQuota", "VerdictsRemaining", "VerdictsUsage", "PeriodEndDate"], ) results = CommandResults( readable_output=markdown, outputs_prefix="VMRay.VerdicsQuota", outputs_key_field="PeriodEndDate", outputs=entry ) return_results(results) def vmray_get_license_usage_reports_command(): # pragma: no cover """ Returns: dict: response """ suffix = "billing_info" raw_response = http_request("GET", suffix) data = raw_response.get("data") entry = {} entry["ReportQuota"] = data.get("report_quota") entry["ReportRemaining"] = data.get("report_remaining") entry["ReportUsage"] = round( (100 / float(data.get("report_quota"))) * (float(data.get("report_quota")) - float(data.get("report_remaining"))), 2 ) entry["PeriodEndDate"] = data.get("end_date") markdown = tableToMarkdown( "VMRay Reports Quota Information", entry, headers=["ReportQuota", "ReportRemaining", "ReportUsage", "PeriodEndDate"] ) results = CommandResults( readable_output=markdown, outputs_prefix="VMRay.ReportsQuota", outputs_key_field="PeriodEndDate", outputs=entry ) return_results(results) def get_pdf_report(sample_id): """ Args: sample_id (str): Returns: str: response """ suffix = f"sample/{sample_id}/report" response = http_request("GET", suffix, get_raw=True) return response def vmray_get_pdf_report_command(): # pragma: no cover """ Returns: dict: response """ sample_id = demisto.args().get("sample_id") check_id(sample_id) pdf_report = get_pdf_report(sample_id) file_entry = fileResult(filename=f"{sample_id}_report.pdf", data=pdf_report, file_type=EntryType.ENTRY_INFO_FILE) return_results(file_entry) def main(): # pragma: no cover try: command = demisto.command() if command == "test-module": # This is the call made when pressing the integration test button. test_module() elif command in ("upload_sample", "vmray-upload-sample", "file"): upload_sample_command() elif command == "vmray-upload-url": upload_url_command() elif command == "vmray-get-submission": get_submission_command() elif command in ("get_results", "vmray-get-analysis-by-sample"): get_analysis_command() elif command == "vmray-get-sample": get_sample_command() elif command == "vmray-get-sample-by-hash": get_sample_by_hash_command() elif command in ( "vmray-get-job-by-sample", "get_job_sample", "vmray-get-job-by-id", ): get_job_command() elif command == "vmray-get-threat-indicators": get_threat_indicators_command() elif command == "vmray-add-tag": post_tags() elif command == "vmray-delete-tag": delete_tags() elif command == "vmray-get-iocs": get_iocs_command() elif command == "vmray-get-summary": get_summary_command() elif command == "vmray-get-screenshots": get_screenshots_command() elif command == "vmray-get-license-usage-verdicts": vmray_get_license_usage_verdicts_command() elif command == "vmray-get-license-usage-reports": vmray_get_license_usage_reports_command() elif command == "vmray-get-pdf-report": vmray_get_pdf_report_command() except Exception as exc: return_error(f"Failed to execute `{demisto.command()}` command. Error: {exc!s}") if __name__ in ("__builtin__", "builtins", "__main__"): main()