ANYRUN Deprecated

Deprecated. Use ANY.RUN TI Feeds, ANY.RUN TI Lookup, ANY.RUN Cloud Sandbox instead.

Forensics & Malware Analysis · ANY.RUN

Details

IDANYRUN
ProviderAnyRun
CategoryForensics & Malware Analysis
From Version5.0.0
Docker Imagedemisto/python3:3.12.8.3296088
Supported ModulesAgentix XSIAM EDR Cortex Cloud Cloud Runtime Security

README

ANY.RUN is a cloud-based sanbox with interactive access.

Use Cases

  1. Submit a file, remote file, or URL to ANY.RUN for analysis.
  2. Retrieve report details for a given analysis task ID.
  3. View history of analysis tasks.

Configure ANYRUN on Cortex XSOAR

  1. Navigate to Settings > Integrations > Servers & Services.
  2. Search for ANYRUN.
  3. Click Add instance to create and configure a new integration instance.

    Parameter Required
    Server URL True
    Username True
    Password True
    Trust any certificate (not secure) False
    Use system proxy settings False
  4. If using API Key authentication method, insert the text _token into the Username parameter and the API key you have into the Password.

  5. Click Test to validate the URLs, token, and connection.

Commands

You can execute these commands from the Cortex XSOAR 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.
The commands allow you to launch and download only your own tasks, public submissions are not available at this point.

anyrun-get-history


Get analysis history.

Base Command

anyrun-get-history

Input

Argument Name Description Required
team If true, gets team history. If empty, gets your submitted analyses history. Possible values are: true, false. Default is false. Optional
skip The number of analyses to skip. Possible values are: . Default is 0. Optional
limit Limits the history retrieved/searched to the specified number of executed analyses. The range is 1-100. Default is 25. Optional
filter File name, hash, or task ID by which to filter the task history. Optional

Context Output

Path Type Description
ANYRUN.Task.Name String Task name.
ANYRUN.Task.Verdict String ANY.RUN verdict for the submitted file’s status.
ANYRUN.Task.Related String ANY.RUN link to a related file.
ANYRUN.Task.File String ANY.RUN link to download the submitted file.
ANYRUN.Task.Date Date The date that the file was submitted for analysis.
ANYRUN.Task.Hash.MD5 String MD5 hash of the submitted file.
ANYRUN.Task.Hash.SHA1 String SHA1 hash of the submitted file.
ANYRUN.Task.Hash.SHA256 String SHA256 hash of the submitted file.
ANYRUN.Task.Hash.HeadHash String Head hash of the submitted file.
ANYRUN.Task.Hash.SSDeep String SSDeep hash of the submitted file.

Command Example

anyrun-get-history skip=0 team=false filter=scribbles2.txt.zip

Context Example

{
    "ANYRUN.Task": [
        {
            "Hash": {
                "HeadHash": "e61fcc6a06420106fa6642ef833b9c38", 
                "SHA1": "475d7efc7983357e51ea780e350b0efe6a5ba2e2", 
                "SHA256": "1832caedd2f87b3c2d5c7dcc5c5f844a1479d3a7868570241656b1516607dbb1", 
                "SSDeep": "24:9YQxEcNJQGgrtSuJDWDRzvu4H2ANvg0JvWH2Rb:9xNJKrtSuxOT9", 
                "MD5": "e61fcc6a06420106fa6642ef833b9c38"
            }, 
            "Name": "scribbles2.txt.zip", 
            "Related": "[https://app.any.run/tasks/892455a2-8c96-45fb-9f2a-18ca4ef184f9](https://app.any.run/tasks/892455a2-8c96-45fb-9f2a-18ca4ef184f9)", 
            "Verdict": "No threats detected", 
            "File": "https://content.any.run/tasks/892455a2-8c96-45fb-9f2a-18ca4ef184f9/download/files/afca4a63-9fe0-461c-8e73-c8fd784cf90e", 
            "Date": "2019-04-24T07:13:06.087Z", 
            "ID": "892455a2-8c96-45fb-9f2a-18ca4ef184f9"
        }, 
        {
            "Hash": {
                "HeadHash": "e61fcc6a06420106fa6642ef833b9c38", 
                "SHA1": "475d7efc7983357e51ea780e350b0efe6a5ba2e2", 
                "SHA256": "1832caedd2f87b3c2d5c7dcc5c5f844a1479d3a7868570241656b1516607dbb1", 
                "SSDeep": "24:9YQxEcNJQGgrtSuJDWDRzvu4H2ANvg0JvWH2Rb:9xNJKrtSuxOT9", 
                "MD5": "e61fcc6a06420106fa6642ef833b9c38"
            }, 
            "Name": "scribbles2.txt.zip", 
            "Related": "[https://app.any.run/tasks/fe7c63ef-2b7f-4e70-b50c-996ae34b28ef](https://app.any.run/tasks/fe7c63ef-2b7f-4e70-b50c-996ae34b28ef)", 
            "Verdict": "No threats detected", 
            "File": "https://content.any.run/tasks/fe7c63ef-2b7f-4e70-b50c-996ae34b28ef/download/files/227a7bd4-5baa-477b-b319-58d7619b79ef", 
            "Date": "2019-04-24T07:02:38.747Z", 
            "ID": "fe7c63ef-2b7f-4e70-b50c-996ae34b28ef"
        }, 
        {
            "Hash": {
                "HeadHash": "e61fcc6a06420106fa6642ef833b9c38", 
                "SHA1": "475d7efc7983357e51ea780e350b0efe6a5ba2e2", 
                "SHA256": "1832caedd2f87b3c2d5c7dcc5c5f844a1479d3a7868570241656b1516607dbb1", 
                "SSDeep": "24:9YQxEcNJQGgrtSuJDWDRzvu4H2ANvg0JvWH2Rb:9xNJKrtSuxOT9", 
                "MD5": "e61fcc6a06420106fa6642ef833b9c38"
            }, 
            "Name": "scribbles2.txt.zip", 
            "Related": "[https://app.any.run/tasks/81bb80cd-3bcf-41b3-aac5-c3e35a39ba0d](https://app.any.run/tasks/81bb80cd-3bcf-41b3-aac5-c3e35a39ba0d)", 
            "Verdict": "No threats detected", 
            "File": "https://content.any.run/tasks/81bb80cd-3bcf-41b3-aac5-c3e35a39ba0d/download/files/0c5c1527-b50b-483e-84e1-7b4b8f82d26b", 
            "Date": "2019-04-23T13:46:47.372Z", 
            "ID": "81bb80cd-3bcf-41b3-aac5-c3e35a39ba0d"
        }, 
        {
            "Hash": {
                "HeadHash": "e61fcc6a06420106fa6642ef833b9c38", 
                "SHA1": "475d7efc7983357e51ea780e350b0efe6a5ba2e2", 
                "SHA256": "1832caedd2f87b3c2d5c7dcc5c5f844a1479d3a7868570241656b1516607dbb1", 
                "SSDeep": "24:9YQxEcNJQGgrtSuJDWDRzvu4H2ANvg0JvWH2Rb:9xNJKrtSuxOT9", 
                "MD5": "e61fcc6a06420106fa6642ef833b9c38"
            }, 
            "Name": "scribbles2.txt.zip", 
            "Related": "[https://app.any.run/tasks/07d4d230-9638-4f04-a226-c7b18a81c329](https://app.any.run/tasks/07d4d230-9638-4f04-a226-c7b18a81c329)", 
            "Verdict": "No threats detected", 
            "File": "https://content.any.run/tasks/07d4d230-9638-4f04-a226-c7b18a81c329/download/files/69dcf7f0-69c2-432e-8d30-3e2f630e0aae", 
            "Date": "2019-04-23T08:11:17.460Z", 
            "ID": "07d4d230-9638-4f04-a226-c7b18a81c329"
        }, 
        {
            "Hash": {
                "HeadHash": "e61fcc6a06420106fa6642ef833b9c38", 
                "SHA1": "475d7efc7983357e51ea780e350b0efe6a5ba2e2", 
                "SHA256": "1832caedd2f87b3c2d5c7dcc5c5f844a1479d3a7868570241656b1516607dbb1", 
                "SSDeep": "24:9YQxEcNJQGgrtSuJDWDRzvu4H2ANvg0JvWH2Rb:9xNJKrtSuxOT9", 
                "MD5": "e61fcc6a06420106fa6642ef833b9c38"
            }, 
            "Name": "scribbles2.txt.zip", 
            "Related": "[https://app.any.run/tasks/411fe6a6-ca36-4322-8f1d-f5ec67c6346d](https://app.any.run/tasks/411fe6a6-ca36-4322-8f1d-f5ec67c6346d)", 
            "Verdict": "No threats detected", 
            "File": "https://content.any.run/tasks/411fe6a6-ca36-4322-8f1d-f5ec67c6346d/download/files/a006642b-956b-4a9d-a72c-0affdd2dd6c8", 
            "Date": "2019-04-22T12:16:13.302Z", 
            "ID": "411fe6a6-ca36-4322-8f1d-f5ec67c6346d"
        }
    ]
}

Human Readable Output

Results

Name ID File Hash Verdict Related Date
scribbles2.txt.zip 892455a2-8c96-45fb-9f2a-18ca4ef184f9 https://content.any.run/tasks/892455a2-8c96-45fb-9f2a-18ca4ef184f9/download/files/afca4a63-9fe0-461c-8e73-c8fd784cf90e MD5: e61fcc6a06420106fa6642ef833b9c38
SHA1: 475d7efc7983357e51ea780e350b0efe6a5ba2e2
SHA256: 1832caedd2f87b3c2d5c7dcc5c5f844a1479d3a7868570241656b1516607dbb1
HeadHash: e61fcc6a06420106fa6642ef833b9c38
SSDeep: 24:9YQxEcNJQGgrtSuJDWDRzvu4H2ANvg0JvWH2Rb:9xNJKrtSuxOT9
No threats detected https://app.any.run/tasks/892455a2-8c96-45fb-9f2a-18ca4ef184f9”>https://app.any.run/tasks/892455a2-8c96-45fb-9f2a-18ca4ef184f9 2019-04-24T07:13:06.087Z
scribbles2.txt.zip fe7c63ef-2b7f-4e70-b50c-996ae34b28ef https://content.any.run/tasks/fe7c63ef-2b7f-4e70-b50c-996ae34b28ef/download/files/227a7bd4-5baa-477b-b319-58d7619b79ef MD5: e61fcc6a06420106fa6642ef833b9c38
SHA1: 475d7efc7983357e51ea780e350b0efe6a5ba2e2
SHA256: 1832caedd2f87b3c2d5c7dcc5c5f844a1479d3a7868570241656b1516607dbb1
HeadHash: e61fcc6a06420106fa6642ef833b9c38
SSDeep: 24:9YQxEcNJQGgrtSuJDWDRzvu4H2ANvg0JvWH2Rb:9xNJKrtSuxOT9
No threats detected https://app.any.run/tasks/fe7c63ef-2b7f-4e70-b50c-996ae34b28ef”>https://app.any.run/tasks/fe7c63ef-2b7f-4e70-b50c-996ae34b28ef 2019-04-24T07:02:38.747Z
scribbles2.txt.zip 81bb80cd-3bcf-41b3-aac5-c3e35a39ba0d https://content.any.run/tasks/81bb80cd-3bcf-41b3-aac5-c3e35a39ba0d/download/files/0c5c1527-b50b-483e-84e1-7b4b8f82d26b MD5: e61fcc6a06420106fa6642ef833b9c38
SHA1: 475d7efc7983357e51ea780e350b0efe6a5ba2e2
SHA256: 1832caedd2f87b3c2d5c7dcc5c5f844a1479d3a7868570241656b1516607dbb1
HeadHash: e61fcc6a06420106fa6642ef833b9c38
SSDeep: 24:9YQxEcNJQGgrtSuJDWDRzvu4H2ANvg0JvWH2Rb:9xNJKrtSuxOT9
No threats detected https://app.any.run/tasks/81bb80cd-3bcf-41b3-aac5-c3e35a39ba0d”>https://app.any.run/tasks/81bb80cd-3bcf-41b3-aac5-c3e35a39ba0d 2019-04-23T13:46:47.372Z
scribbles2.txt.zip 07d4d230-9638-4f04-a226-c7b18a81c329 https://content.any.run/tasks/07d4d230-9638-4f04-a226-c7b18a81c329/download/files/69dcf7f0-69c2-432e-8d30-3e2f630e0aae MD5: e61fcc6a06420106fa6642ef833b9c38
SHA1: 475d7efc7983357e51ea780e350b0efe6a5ba2e2
SHA256: 1832caedd2f87b3c2d5c7dcc5c5f844a1479d3a7868570241656b1516607dbb1
HeadHash: e61fcc6a06420106fa6642ef833b9c38
SSDeep: 24:9YQxEcNJQGgrtSuJDWDRzvu4H2ANvg0JvWH2Rb:9xNJKrtSuxOT9
No threats detected https://app.any.run/tasks/07d4d230-9638-4f04-a226-c7b18a81c329”>https://app.any.run/tasks/07d4d230-9638-4f04-a226-c7b18a81c329 2019-04-23T08:11:17.460Z
scribbles2.txt.zip 411fe6a6-ca36-4322-8f1d-f5ec67c6346d https://content.any.run/tasks/411fe6a6-ca36-4322-8f1d-f5ec67c6346d/download/files/a006642b-956b-4a9d-a72c-0affdd2dd6c8 MD5: e61fcc6a06420106fa6642ef833b9c38
SHA1: 475d7efc7983357e51ea780e350b0efe6a5ba2e2
SHA256: 1832caedd2f87b3c2d5c7dcc5c5f844a1479d3a7868570241656b1516607dbb1
HeadHash: e61fcc6a06420106fa6642ef833b9c38
SSDeep: 24:9YQxEcNJQGgrtSuJDWDRzvu4H2ANvg0JvWH2Rb:9xNJKrtSuxOT9
No threats detected https://app.any.run/tasks/411fe6a6-ca36-4322-8f1d-f5ec67c6346d”>https://app.any.run/tasks/411fe6a6-ca36-4322-8f1d-f5ec67c6346d 2019-04-22T12:16:13.302Z

anyrun-get-report


Gets the report of a task created for a submitted file or URL.

Note: This command can only get reports for files or URLs deployed by the integration account. It cannot pull reports on public submissions.

Base Command

anyrun-get-report

Input

Argument Name Description Required
task Unique task ID. A task ID is returned when submitting a file or URL for analysis using the anyrun-run-analysis command. Task IDs can also be located in the ID field of the output of executing the anyrun-get-history command. Required

Context Output

Path Type Description
ANYRUN.Task.AnalysisDate String Date and time the analysis was executed.
ANYRUN.Task.Behavior.Category String Category of a process behavior.
ANYRUN.Task.Behavior.Action String Actions performed by a process.
ANYRUN.Task.Behavior.ThreatLevel Number Threat score associated with a process behavior.
ANYRUN.Task.Behavior.ProcessUUID String Unique ID of the process whose behaviors are being profiled.
ANYRUN.Task.Connection.Reputation String Connection reputation.
ANYRUN.Task.Connection.ProcessUUID String ID of the process that created the connection.
ANYRUN.Task.Connection.ASN String Connection autonomous system network.
ANYRUN.Task.Connection.Country String Connection country.
ANYRUN.Task.Connection.Protocol String Connection protocol.
ANYRUN.Task.Connection.Port Number Connection port number.
ANYRUN.Task.Connection.IP String Connection IP number.
ANYRUN.Task.DnsRequest.Reputation String Reputation of the DNS request.
ANYRUN.Task.DnsRequest.IP Unknown IP addresses associated with a DNS request.
ANYRUN.Task.DnsRequest.Domain String Domain resolution of a DNS request.
ANYRUN.Task.Threat.ProcessUUID String Unique process ID from where the threat originated.
ANYRUN.Task.Threat.Msg String Threat message.
ANYRUN.Task.Threat.Class String Class of the threat.
ANYRUN.Task.Threat.SrcPort Number Port on which the threat originated.
ANYRUN.Task.Threat.DstPort Number Destination port of the threat.
ANYRUN.Task.Threat.SrcIP String Source IP address where the threat originated.
ANYRUN.Task.Threat.DstIP String Destination IP address of the threat.
ANYRUN.Task.HttpRequest.Reputation String Reputation of the HTTP request.
ANYRUN.Task.HttpRequest.Country String HTTP request country.
ANYRUN.Task.HttpRequest.ProcessUUID String ID of the process making the HTTP request.
ANYRUN.Task.HttpRequest.Body Unknown HTTP request body parameters and details.
ANYRUN.Task.HttpRequest.HttpCode Number HTTP request response code.
ANYRUN.Task.HttpRequest.Status String Status of the HTTP request.
ANYRUN.Task.HttpRequest.ProxyDetected Boolean Whether the HTTP request was made through a proxy.
ANYRUN.Task.HttpRequest.Port Number HTTP request port.
ANYRUN.Task.HttpRequest.IP String HTTP request IP address.
ANYRUN.Task.HttpRequest.URL String HTTP request URL.
ANYRUN.Task.HttpRequest.Host String HTTP request host.
ANYRUN.Task.HttpRequest.Method String HTTP request method type.
ANYRUN.Task.FileInfo String Details of the submitted file.
ANYRUN.Task.OS String OS of the sandbox in which the file was analyzed.
ANYRUN.Task.ID String The unique ID of the task.
ANYRUN.Task.MIME String The MIME of the file submitted for analysis.
ANYRUN.Task.MD5 String The MD5 hash of the file submitted for analysis.
ANYRUN.Task.SHA1 String The SHA1 hash of the file submitted for analysis.
ANYRUN.Task.SHA256 String The SHA256 hash of the file submitted for analysis.
ANYRUN.Task.SSDeep String SSDeep hash of the file submitted for analysis.
ANYRUN.Task.Verdict String ANY.RUN verdict for the maliciousness of the submitted file or URL.
ANYRUN.Task.Process.FileName String File name of the process.
ANYRUN.Task.Process.PID Number Process identification number.
ANYRUN.Task.Process.PPID Number Parent process identification number.
ANYRUN.Task.Process.ProcessUUID String Unique process ID (used by ANY.RUN).
ANYRUN.Task.Process.CMD String Process command.
ANYRUN.Task.Process.Path String Path of the executed command.
ANYRUN.Task.Process.User String User who executed the command.
ANYRUN.Task.Process.IntegrityLevel String The process integrity level.
ANYRUN.Task.Process.ExitCode Number Process exit code.
ANYRUN.Task.Process.MainProcess Boolean Whether the process is the main process.
ANYRUN.Task.Process.Version.Company String Company responsible for the program executed.
ANYRUN.Task.Process.Version.Description String Description of the type of program.
ANYRUN.Task.Process.Version.Version String Version of the program executed.
DBotScore.Indicator String The indicator that was tested.
DBotScore.Score Number The actual score.
DBotScore.Type String Type of indicator.
DBotScore.Vendor String Vendor used to calculate the score.
File.Extension String Extension of the file submitted for analysis.
File.Name String The name of the file submitted for analysis.
File.MD5 String MD5 hash of the file submitted for analysis.
File.SHA1 String SHA1 hash of the file submitted for analysis.
File.SHA256 String SHA256 hash of the file submitted for analysis.
File.SSDeep String SSDeep hash of the file submitted for analysis.
File.Malicious.Vendor String For malicious files, the vendor that made the decision.
File.Malicious.Description String For malicious files, the reason that the vendor made the decision.
URL.Data String URL data.
URL.Malicious.Vendor String For malicious URLs, the vendor that made the decision.
URL.Malicious.Description String For malicious URLs, the reason that the vendor made the decision.
ANYRUN.Task.Status String Task analysis status.

Command Example

anyrun-get-report task=fe7c63ef-2b7f-4e70-b50c-996ae34b28ef

Context Example

{
    "ANYRUN.Task": {
        "HttpRequest": [], 
        "SSDeep": "24:9YQxEcNJQGgrtSuJDWDRzvu4H2ANvg0JvWH2Rb:9xNJKrtSuxOT9", 
        "Status": "done", 
        "SHA1": "475d7efc7983357e51ea780e350b0efe6a5ba2e2", 
        "Threat": [], 
        "Process": [
            {
                "CMD": "\"C:\\Program Files\\WinRAR\\WinRAR.exe\" \"C:\\Users\\admin\\AppData\\Local\\Temp\\scribbles2.txt.zip\"", 
                "IntegrityLevel": "MEDIUM", 
                "PID": 916, 
                "MainProcess": true, 
                "FileName": "WinRAR.exe", 
                "Version": {
                    "Company": "Alexander Roshal", 
                    "Version": "5.60.0", 
                    "Description": "WinRAR archiver"
                }, 
                "ProcessUUID": "8834c75a-ceba-4ae3-83e6-87b8b460ff82", 
                "User": "admin", 
                "Path": "C:\\Program Files\\WinRAR\\WinRAR.exe", 
                "PPID": 2044, 
                "ExitCode": null
            }
        ], 
        "ID": "fe7c63ef-2b7f-4e70-b50c-996ae34b28ef", 
        "Connection": [], 
        "MIME": "application/zip", 
        "Behavior": [], 
        "Verdict": "No threats detected", 
        "FileInfo": "Zip archive data, at least v2.0 to extract", 
        "SHA256": "1832caedd2f87b3c2d5c7dcc5c5f844a1479d3a7868570241656b1516607dbb1", 
        "OS": "Windows 7 Professional Service Pack 1 (build: 7601, 32 bit)", 
        "DnsRequest": [], 
        "AnalysisDate": "2019-04-24T07:02:38.747Z", 
        "MD5": "e61fcc6a06420106fa6642ef833b9c38"
    }, 
    "DBotScore": {
        "Vendor": "ANYRUN", 
        "Indicator": "1832caedd2f87b3c2d5c7dcc5c5f844a1479d3a7868570241656b1516607dbb1", 
        "Score": 1, 
        "Type": "hash"
    }, 
    "File": {
        "SHA1": "475d7efc7983357e51ea780e350b0efe6a5ba2e2", 
        "Name": "scribbles2.txt.zip", 
        "Extension": "zip", 
        "SSDeep": "24:9YQxEcNJQGgrtSuJDWDRzvu4H2ANvg0JvWH2Rb:9xNJKrtSuxOT9", 
        "SHA256": "1832caedd2f87b3c2d5c7dcc5c5f844a1479d3a7868570241656b1516607dbb1", 
        "MD5": "e61fcc6a06420106fa6642ef833b9c38"
    }
}

Human Readable Output

Results

OS AnalysisDate Verdict MIME FileInfo Process Status MD5 SHA1 SHA256 SSDeep
Windows 7 Professional Service Pack 1 (build: 7601, 32 bit) 2019-04-24T07:02:38.747Z No threats detected application/zip Zip archive data, at least v2.0 to extract FileName: WinRAR.exe, PID: 916, PPID: 2044, ProcessUUID: 8834c75a-ceba-4ae3-83e6-87b8b460ff82, CMD: \C:\Program Files\WinRAR\WinRAR.exe\ \C:\Users\admin\AppData\Local\Temp\scribbles2.txt.zip, Path: C:\Program Files\WinRAR\WinRAR.exe, User: admin, IntegrityLevel: MEDIUM, ExitCode: null, MainProcess: true, Version: {Company: Alexander Roshal, Description: WinRAR archiver, Version: 5.60.0 done e61fcc6a06420106fa6642ef833b9c38 475d7efc7983357e51ea780e350b0efe6a5ba2e2 1832caedd2f87b3c2d5c7dcc5c5f844a1479d3a7868570241656b1516607dbb1 24:9YQxEcNJQGgrtSuJDWDRzvu4H2ANvg0JvWH2Rb:9xNJKrtSuxOT9

anyrun-run-analysis


Submit a file or url for analysis.

Base Command

anyrun-run-analysis

Input

Argument Name Description Required
obj_type Type of new task. Possible values are: file, url, remote file. Default is file. Optional
file EntryID of the file to analyze. Optional
obj_url URL, used only if ‘obj_type’ command argument is ‘url’ or ‘download’. Permitted size is 5-512 characters long. Optional
env_bitness Bitness of OS. Possible values are: 32, 64. Default is 32. Optional
env_version Version of Windows OS. Possible values are: Windows Vista, Windows 7, Windows 8.1, Windows 10, Windows 11. Default is Windows 7. Optional
env_type Environment preset type. Possible values are: complete, clean, office. Default is complete. Optional
opt_network_connect Network connection state. Possible values are: true, false. Default is true. Optional
opt_kernel_heavyevasion Heavy evasion option. Possible values are: true, false. Default is false. Optional
opt_privacy_type Privacy settings for generated task. Possible values are: owner, bylink, public, byteam. Default is owner. Optional
obj_ext_browser Browser name, used only for “url” type. Possible values are: Internet Explorer, Google Chrome, Mozilla Firefox, Opera, Microsoft Edge. Optional
obj_ext_cmd Command line, used only if ‘obj_type’ command argument is ‘file’ or ‘download’. Permitted size is 2-256 characters long. Optional

Context Output

Path Type Description
ANYRUN.Task.ID String ID of the task created to analyze the submission.

Command Example

anyrun-run-analysis obj_type=file file=693@66884384-c643-4343-8cf7-26f59e62a88e env_bitness=64

Context Example

{
    "ANYRUN.Task": {
        "ID": "e04b401f-9396-4183-ad00-b6ed34c023e3"
    }
}

Human Readable Output

Results

Task
e04b401f-9396-4183-ad00-b6ed34c023e3

Configuration parameters

  • url — Server URL (required)
  • credentials — Username (required)
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (3)

  • anyrun-get-history

    Get analysis history.

  • anyrun-get-report

    Gets the report of a task created for a submitted file or URL.

  • anyrun-run-analysis

    Submit a file or url for analysis.

import demistomock as demisto
from CommonServerPython import *

from CommonServerUserPython import *

""" IMPORTS """

import json
import os
import re
from base64 import b64encode

import requests
import urllib3

""" GLOBAL VARS / INSTANCE CONFIGURATION """

PARAMS = demisto.params()
USERNAME = PARAMS.get("credentials", {}).get("identifier", "")
PASSWORD = PARAMS.get("credentials", {}).get("password", "")
if USERNAME == "_token":
    AUTHORIZATION = f"API-Key {PASSWORD}"
else:
    AUTH = (USERNAME + ":" + PASSWORD).encode("utf-8")
    AUTHORIZATION = "Basic " + b64encode(AUTH).decode()
# Remove trailing slash to prevent wrong URL path to service
SERVER = PARAMS.get("url", "")
SERVER = SERVER[:-1] if (SERVER and SERVER.endswith("/")) else SERVER
# Service base URL
BASE_URL = SERVER + "/v1/"
# Should we use SSL
USE_SSL = not PARAMS.get("insecure", False)
PROXY = PARAMS.get("proxy", False)
# Headers to be sent in requests
HEADERS = {"Authorization": AUTHORIZATION}
# Context fields that should always be uppercase
ALWAYS_UPPER_CASE = {"md5", "sha1", "sha256", "sha512", "pcap", "ip", "url", "id", "pid", "ppid", "uuid", "asn", "mime"}
THREAT_TEXT_TO_DBOTSCORE = {"no threats detected": 1, "suspicious activity": 2, "malicious activity": 3}

""" SETUP """

# Disable insecure warnings
urllib3.disable_warnings()

# Remove proxy if not set to true in params
if not PROXY:
    os.environ.pop("HTTP_PROXY", "")
    os.environ.pop("HTTPS_PROXY", "")
    os.environ.pop("http_proxy", "")
    os.environ.pop("https_proxy", "")

""" HELPER FUNCTIONS """


def underscore_to_camel_case(s):
    """
    Convert an underscore separated string to camel case, leaving one-word strings untouched

    Parameters
    ----------
    s : str
        The string to convert (e.g. heLLo_world) (required).

    Returns
    -------
    str
        The converted string (e.g. heLLoWorld).
    """

    if not isinstance(s, str):
        return s
    components = s.split("_")
    return "".join(x.title() if i != 0 else x for i, x in enumerate(components))


def make_upper(string):
    """
    Make argument uppercase if it is a member of 'ALWAYS_UPPER_CASE' global variable

    Parameters
    ----------
    string : str
        The string to check and potentially make uppercase.

    Returns
    -------
    str
        Uppercased string (or original string if it didn't match the criteria).
    """

    if isinstance(string, str):
        if string.casefold() in ALWAYS_UPPER_CASE:
            return string.upper()
        elif string.casefold() == "ssdeep":  # special case
            return "SSDeep"
        else:
            return string
    else:
        return string


def make_capital(string):
    """Capitalize first letter of a string, leaving the rest of the string as is

    Parameters
    ----------
    string : str
        The string to capitalize (e.g. 'foRUm').

    Returns
    -------
    str
        The capitalized string (e.g. 'FoRUm').
    """

    if isinstance(string, str) and string:
        return string[:1].upper() + string[1:]
    else:
        return string


def make_singular(word):
    """Relatively naive/imperfect function to make a word singular

    Parameters
    ----------
    word : str
        The string to make singular (e.g. 'zebras').

    Returns
    -------
    str
        The string in singular form (e.e. 'zebra').
    """

    if not isinstance(word, str) or not word:
        return word

    word_as_lower = word.casefold()
    # Not a plural
    if not word_as_lower.endswith("s"):
        return word
    # Word ends in 's' and is therefore possibly plural
    else:
        es_endings = ("sses", "shes", "ches", "xes", "zes")
        if word_as_lower.endswith(es_endings):
            # Then the word was pluralized by adding 'es'
            return word[:-2]
        elif word_as_lower.endswith("ss"):
            # Then it's probably not a plural, e.g. 'assess' or 'process'
            return word
        elif len(word) <= 2:
            # Then it's probably not a plural, e.g. 'OS'
            return word
        elif word_as_lower.endswith(("sis", "us")):
            # Then it's probably singular like 'analysis' and 'cactus' and 'focus'
            return word
        else:
            # Assume regular noun pluralization of adding an 's'
            return word[:-1]


def travel_object(obj, key_functions=[], val_functions=[]):
    """Recursively apply functions to the keys and values of a dictionary

    Parameters
    ----------
    obj : dict/list
        List or dict to recurse through.
    key_functions : list
        Functions to apply to the keys in 'obj'.
    val_functions : list
        Functions to apply to the values in 'obj'

    Returns
    -------
    list/dict
        A list or dict in which all nested keys and values have been
        altered by the key_functions and val_functions respectively.
    """

    def operate_on_dict(the_dict):
        new_dict = {}
        for key, val in the_dict.items():
            new_key = key
            for key_func in key_functions:
                new_key = key_func(new_key)
            if isinstance(val, dict | list):
                new_val = travel_object(val, key_functions=key_functions, val_functions=val_functions)
            else:
                new_val = val
                for val_func in val_functions:
                    new_val = val_func(val)
            new_dict[new_key] = new_val
        return new_dict

    if isinstance(obj, list):
        new_list = []
        for item in obj:
            new_item = operate_on_dict(item) if isinstance(item, dict) else item
            new_list.append(new_item)
        return new_list
    elif isinstance(obj, dict):
        altered_dict = operate_on_dict(obj)
        return altered_dict
    else:
        err_msg = 'Invalid type: the passed "obj" argument was not of type "dict" or "list".'
        raise TypeError(err_msg)


def generate_dbotscore(response):
    """Creates DBotScore object based on the contents of 'response' argument

    Parameters
    ----------
    response : dict
        Object returned by ANYRUN API call in 'get_report' function.

    Returns
    -------
    dict
        A DBotScore object.
    """

    analysis = response.get("data", {}).get("analysis", {})
    main_object = analysis.get("content", {}).get("mainObject", {})
    submission_type = main_object.get("type")
    submission_type = "hash" if submission_type in {"file", "download"} else submission_type
    threat_text = analysis.get("scores", {}).get("verdict", {}).get("threatLevelText", "").casefold()
    if submission_type == "hash":
        hashes = main_object.get("hashes", {})
        indicator = hashes.get("sha256", hashes.get("sha1", hashes.get("md5")))
    else:
        indicator = main_object.get("url")
    dbot_score = {
        "DBotScore": {
            "Indicator": indicator,
            "Type": submission_type,
            "Vendor": "ANYRUN",
            "Score": THREAT_TEXT_TO_DBOTSCORE.get(threat_text, 0),
        }
    }
    return dbot_score


def add_malicious_key(entity, verdict):
    """Return the entity with the additional 'Malicious' key if determined as such by ANYRUN

    Parameters
    ----------
    entity : dict
        File or URL object.
    verdict : dict
        Task analysis verdict for a detonated file or url.

    Returns
    -------
    dict
        The modified entity if it was malicious, otherwise the original entity.
    """

    threat_level_text = verdict.get("threatLevelText", "")

    if threat_level_text.casefold() == "malicious activity":
        entity["Malicious"] = {"Vendor": "ANYRUN", "Description": threat_level_text}
    return entity


def ec_file(main_object):
    """Return File entity in Demisto format for use in entry context

    Parameters
    ----------
    main_object : dict
        The main object from a report's contents.

    Returns
    -------
    dict
        File object populated by report contents.
    """

    name = main_object.get("filename")
    hashes = main_object.get("hashes", {})
    md5 = hashes.get("md5")
    sha1 = hashes.get("sha1")
    sha256 = hashes.get("sha256")
    ssdeep = hashes.get("ssdeep")
    ext = main_object.get("info", {}).get("ext")

    file_ec = {"File": {"Name": name, "MD5": md5, "SHA1": sha1, "SHA256": sha256, "SSDeep": ssdeep, "Extension": ext}}
    return file_ec


def ec_url(main_object):
    """Return URL entity in Demisto format for use in entry context

    Parameters
    ----------
    main_object : dict
        The main object from a report's contents.

    Returns
    -------
    dict
        URL object populated by report contents.
    """

    url = main_object.get("url")

    url_ec = {"URL": {"Data": url}}
    return url_ec


def ec_entity(response):
    """
    Return URL or File entity in Demisto format for use in entry
    context depending on data in 'response' (the report)

    Parameters
    ----------
    response : dict
        Object returned by ANYRUN API call in 'get_report' function.

    Returns
    -------
    dict
        File or URL object populated by report contents.
    """

    analysis = response.get("data", {}).get("analysis", {})
    verdict = analysis.get("scores", {}).get("verdict", {})
    main_object = analysis.get("content", {}).get("mainObject", {})
    submission_type = main_object.get("type")
    entity = None
    if submission_type == "url":
        entity = ec_url(main_object)
        entity["URL"] = add_malicious_key(entity.get("URL", {}), verdict)
    else:
        entity = ec_file(main_object)
        entity["File"] = add_malicious_key(entity.get("File", {}), verdict)
    return entity


def taskid_from_url(anyrun_url):
    """Extract task ID from ANYRUN url inside a 'task' result returned by the get_history command

    Parameters
    ----------
    anyrun_url : str
        URL that contains an ANYRUN task ID.

    Returns
    -------
    str
        An ANYRUN task ID.
    """

    pattern = r"tasks/(.*?)/"
    match = re.search(pattern, anyrun_url)
    if match:
        task_id = match.groups()[0]
    else:
        task_id = None
    return task_id


def images_from_report(response):
    """Retrieve images from an ANYRUN report

    Parameters
    ----------
    response : dict
        Object returned by ANYRUN API call in 'get_report' function.

    Returns
    -------
    list
        List of images from ANYRUN report.
    """

    data = response.get("data", {})
    analysis = data.get("analysis", {})
    content = analysis.get("content", {})
    screenshots = content.get("screenshots", [])

    screen_captures = []
    for idx, shot in enumerate(screenshots):
        screen_cap_url = shot.get("permanentUrl")
        img_response = requests.request("GET", screen_cap_url, verify=USE_SSL, headers=HEADERS)
        stored_img = fileResult(f"screenshot{idx}.png", img_response.content)
        img_entry = {
            "Type": entryTypes["image"],
            "ContentsFormat": formats["text"],
            "File": stored_img["File"],
            "FileID": stored_img["FileID"],
            "Contents": "",
        }
        screen_captures.append(img_entry)
    return screen_captures


def contents_from_report(response):
    """Selectively retrieve content from an ANYRUN report

    Parameters
    ----------
    response : dict
        Object returned by ANYRUN API call in 'get_report' function.

    Returns
    -------
    dict
        Selected content from ANYRUN report.
    """

    data = response.get("data", {})
    environment = data.get("environments", {})
    analysis = data.get("analysis", {})
    processes = data.get("processes", [])
    incidents = data.get("incidents", [])
    status = data.get("status")

    # Retrieve environment info from response
    os = environment.get("os", {}).get("title")

    # Retrieve threat score + info from response
    score = analysis.get("scores", {})
    verdict = score.get("verdict", {})
    threat_level_text = verdict.get("threatLevelText")

    # Retrieve analysis time stuff
    start_text = analysis.get("creationText")

    # Retrieve submitted file info from response
    content = analysis.get("content", {})
    main_object = content.get("mainObject", {})
    info = main_object.get("info", {})
    mime = info.get("mime")
    file_info = info.get("file")
    hashes = main_object.get("hashes")

    # Retrieve network details
    network = data.get("network", {})
    threats = network.get("threats", [])
    connections = network.get("connections", [])
    http_reqs = network.get("httpRequests", [])
    dns_requests = network.get("dnsRequests", [])

    reformatted_threats = []
    for threat in threats:
        reformatted_threat = {
            "ProcessUUID": threat.get("process"),
            "Message": threat.get("msg"),
            "Class": threat.get("class"),
            "SrcPort": threat.get("srcport"),
            "DstPort": threat.get("dstport"),
            "SrcIP": threat.get("srcip"),
            "DstIP": threat.get("dstip"),
        }
        reformatted_threats.append(reformatted_threat)
    network["threats"] = reformatted_threats

    reformatted_connections = []
    for connection in connections:
        reformatted_connection = {
            "Reputation": connection.get("reputation"),
            "ProcessUUID": connection.get("process"),
            "ASN": connection.get("asn"),
            "Country": connection.get("country"),
            "Protocol": connection.get("protocol"),
            "Port": connection.get("port"),
            "IP": connection.get("ip"),
        }
        reformatted_connections.append(reformatted_connection)
    network["connections"] = reformatted_connections

    reformatted_http_reqs = []
    for http_req in http_reqs:
        reformatted_http_req = {
            "Reputation": http_req.get("reputation"),
            "Country": http_req.get("country"),
            "ProcessUUID": http_req.get("process"),
            "Body": http_req.get("body"),
            "HttpCode": http_req.get("httpCode"),
            "Status": http_req.get("status"),
            "ProxyDetected": http_req.get("proxyDetected"),
            "Port": http_req.get("port"),
            "IP": http_req.get("ip"),
            "URL": http_req.get("url"),
            "Host": http_req.get("host"),
            "Method": http_req.get("method"),
        }
        reformatted_http_reqs.append(reformatted_http_req)
    network["httpRequests"] = reformatted_http_reqs

    reformatted_dns_requests = []
    for dns_request in dns_requests:
        reformatted_dns_request = {
            "Reputation": dns_request.get("reputation"),
            "IP": dns_request.get("ips"),
            "Domain": dns_request.get("domain"),
        }
        reformatted_dns_requests.append(reformatted_dns_request)
    network["dnsRequests"] = reformatted_dns_requests

    # Retrieve process details
    reformatted_processes = []
    for process in processes:
        context = process.get("context", {})
        reformatted_process = {
            "FileName": process.get("fileName"),
            "PID": process.get("pid"),
            "PPID": process.get("ppid"),
            "ProcessUUID": process.get("uuid"),
            "CMD": process.get("commandLine"),
            "Path": process.get("image"),
            "User": context.get("userName"),
            "IntegrityLevel": context.get("integrityLevel"),
            "ExitCode": process.get("exitCode"),
            "MainProcess": process.get("mainProcess"),
            "Version": process.get("versionInfo", {}),
        }
        reformatted_processes.append(reformatted_process)

    # Retrieve incident details
    reformatted_incidents = []
    for incident in incidents:
        reformatted_incident = {
            "ProcessUUID": incident.get("process"),
            "Category": incident.get("desc"),
            "Action": incident.get("title"),
            "ThreatLevel": incident.get("threatLevel"),
        }
        reformatted_incidents.append(reformatted_incident)

    contents = {
        "OS": os,
        "AnalysisDate": start_text,
        "Verdict": threat_level_text,
        "MIME": mime,
        "FileInfo": file_info,
        "Process": reformatted_processes,
        "Behavior": reformatted_incidents,
        "Status": status,
    }
    if hashes:
        for key, val in hashes.items():
            contents[key] = val
    if network:
        for key, val in network.items():
            contents[key] = val

    return contents


def humanreadable_from_report_contents(contents):
    """Make the selected contents pulled from a report suitable for war room output

    Parameters
    ----------
    contents : dict
        Contents selected from an ANYRUN report for Demisto output.

    Returns
    -------
    dict
        Contents formatted so that nested dicts/lists appear nicely in a war room
        entry.
    """

    def dict_to_string(nested_dict):
        return json.dumps(nested_dict).lstrip("{").rstrip("}").replace("'", "").replace('"', "")

    humanreadable_contents = {}
    for key, val in contents.items():
        if isinstance(val, dict):
            humanreadable_contents[key] = dict_to_string(val)
        elif isinstance(val, list):
            humanreadable_vals = []
            for item in val:
                if isinstance(item, dict):
                    humanreadable_vals.append(dict_to_string(item))
                else:
                    humanreadable_vals.append(item)
            humanreadable_contents[key] = humanreadable_vals
        else:
            humanreadable_contents[key] = val
    return humanreadable_contents


def contents_from_history(filter, response):
    """Return desired fields from filtered response

    Parameters
    ----------
    filter : str
        File name (for a file analysis), URL (for a URL analysis),
        Task ID, or hash by which to filter task history.
    response : dict
        Object returned by ANYRUN API call in 'get_history' function.

    Returns
    -------
    list
        List of Task summaries matching the filter.
    """

    # Filter response
    tasks = response.get("data", {}).get("tasks", {})
    desired_fields = {"related", "verdict", "date"}
    filtered_tasks = []
    for task in tasks:
        # First fetch fields that we can filter on
        name = task.get("name")
        hashes = task.get("hashes")
        file_url = task.get("file")
        task_id = taskid_from_url(file_url)

        if filter and filter not in {name, task_id, *hashes.values()}:
            continue

        # Reconstruct task dict with desired output fields if filter satisfied
        filtered_task = {"name": name, "id": task_id, "file": file_url, "hashes": hashes}
        for field in task:
            if field in desired_fields:
                filtered_task[field] = task.get(field)
        filtered_tasks.append(filtered_task)

    return filtered_tasks


def http_request(method, url_suffix, params=None, data=None, files=None):
    """
    A wrapper for requests lib to send our requests and handle requests
    and responses better

    Parameters
    ----------
    method : str
        HTTP method, e.g. 'GET', 'POST' ... etc.
    url_suffix : str
        API endpoint.
    params : dict
        URL parameters.
    data : dict
        Data to be sent in a 'POST' request.
    files : dict
        File data to be sent in a 'POST' request.

    Returns
    -------
    dict
        Response JSON from having made the request.
    """
    try:
        res = requests.request(
            method,
            BASE_URL + url_suffix,
            verify=USE_SSL,
            params=params,
            data=data,
            files=files,
            headers=HEADERS,
        )

        # Handle error responses gracefully
        if res.status_code not in {200, 201}:
            err_msg = f"Error in ANYRUN Integration API call [{res.status_code}] - {res.reason}"
            try:
                if res.json().get("error"):
                    err_msg += "\n{}".format(res.json().get("message"))
                raise DemistoException(err_msg, res=res)
            except json.decoder.JSONDecodeError:
                raise DemistoException(err_msg, res=res)

        return res.json()

    except requests.exceptions.ConnectionError:
        err_msg = "Connection Error - Check that the Server URL parameter is correct."
        raise DemistoException(err_msg)


""" COMMANDS + REQUESTS FUNCTIONS """


def test_module():
    """Performs get_history API call to verify integration is operational

    Returns
    -------
    str
        'ok' message.
    """

    get_history(args={"limit": 1})
    demisto.results("ok")


def get_history(args={}):
    """Make API call to ANYRUN to get analysis history

    Parameters
    ----------
    args : dict
        URL parameters that determine which, and how many results are
        returned in the response.

    Returns
    -------
    dict
        Response JSON from ANYRUN API call.
    """

    url_suffix = "analysis/"
    params = args
    response = http_request("GET", url_suffix=url_suffix, params=params)
    return response


def get_history_command():
    """Return ANYRUN task analysis history to Demisto"""

    args = demisto.args()
    filter = args.pop("filter", None)
    response = get_history(args)
    contents = contents_from_history(filter, response)

    formatting_funcs = [underscore_to_camel_case, make_capital, make_singular, make_upper]
    formatted_contents = travel_object(contents, key_functions=formatting_funcs)
    if contents:
        entry_context: dict | None = {"ANYRUN.Task(val.ID && val.ID === obj.ID)": formatted_contents}
        title = f'Task History - Filtered By "{filter}"' if filter else "Task History"
        # Make Related Clickable
        for task in formatted_contents:
            related = task.get("Related", "")
            task["Related"] = f"[{related}]({related})"
        human_readable = tableToMarkdown(title, formatted_contents, removeNull=True)
    else:
        human_readable = "No results found."
        entry_context = None

    return_outputs(readable_output=human_readable, outputs=entry_context, raw_response=response)


def get_report(task_id):
    """Make API call to ANYRUN to get task report

    Parameters
    ----------
    task_id : str
        The unique task ID of the analysis whose report to fetch.

    Returns
    -------
    dict
        Response JSON from ANYRUN API call.
    """

    try:
        # according to the any-run documentation, this request should work:
        # https://any.run/api-documentation/#api-Analysis-GetReport
        url_suffix = f"analysis/{task_id}"
        response = http_request("GET", url_suffix=url_suffix)
    except DemistoException as exc:
        if exc.res and exc.res.status_code != 403:
            raise

        # in case of 403, try a work-around suggested by customer
        url_suffix = "analysis/"
        params = {
            "task": task_id,
        }
        response = http_request("GET", url_suffix=url_suffix, params=params)

    return response


def get_report_command():
    """Return ANYRUN analysis report to Demisto"""
    args = demisto.args()
    task_id = args.get("task")
    response = get_report(task_id)

    images = images_from_report(response)
    contents = contents_from_report(response)
    formatting_funcs = [underscore_to_camel_case, make_capital, make_singular, make_upper]
    formatted_contents = travel_object(contents, key_functions=formatting_funcs)

    dbot_score = generate_dbotscore(response)
    entity = ec_entity(response)

    entry_context = {"ANYRUN.Task(val.ID && val.ID === obj.ID)": {"ID": task_id, **formatted_contents}, **dbot_score, **entity}

    title = f"Report for Task {task_id}"
    human_readable_content = humanreadable_from_report_contents(formatted_contents)
    human_readable = tableToMarkdown(title, human_readable_content, removeNull=True)
    return_outputs(readable_output=human_readable, outputs=entry_context, raw_response=response)
    if images:
        demisto.results(images)


def run_analysis(args):
    """Make API call to ANYRUN to submit file or url for analysis

    Parameters
    ----------
    args : dict
        The analysis specifications and data.

    Returns
    -------
    dict
        Response JSON from ANYRUN API call.
    """

    try:
        entry_id = args.pop("file", None)
        obj_url = args.get("obj_url")
        obj_type = args.get("obj_type")
        obj_ext_cmd = args.get("obj_ext_cmd")
        if obj_type == "remote file":
            obj_type = "download"
            args["obj_type"] = "download"
        # In the case only a url was entered but the object type arg wasn't changed
        if not entry_id and obj_url and obj_type == "file":
            args["obj_type"] = obj_type = "url"
        files = None
        if obj_type == "file":
            cmd_res = demisto.getFilePath(entry_id)
            file_path = cmd_res.get("path")
            name = cmd_res.get("name")
            files = {"file": (name, open(file_path, "rb"))}

        # Format command arguments to API's parameter expectations
        env_bitness = int(args.get("env_bitness", 32))
        args["env_bitness"] = env_bitness
        env_version = args.get("env_version").lower()
        if env_version == "windows vista":
            args["env_version"] = "vista"
        elif env_version == "windows 8.1":
            args["env_version"] = "8.1"
        elif env_version == "windows 10":
            args["env_version"] = "10"
        elif env_version == "windows 11":
            args["env_version"] = "11"
        else:
            args["env_version"] = "7"
        if obj_ext_cmd and (obj_type == "file" or obj_type == "download"):
            args["obj_ext_cmd"] = args.get("obj_ext_cmd")
        url_suffix = "analysis"
        response = http_request("POST", url_suffix, data=args, files=files)
        return response
    except ValueError:
        err_msg = "Invalid entryID - File not found for the given entryID"
        return_error(err_msg)


def run_analysis_command():
    """Submit file or URL to ANYRUN for analysis and return task ID to Demisto"""

    args = demisto.args()
    response = run_analysis(args)
    task_id = response.get("data", {}).get("taskid")
    title = "Submission Successful"
    human_readable = tableToMarkdown(title, {"Task": task_id}, removeNull=True)
    entry_context = {"ANYRUN.Task(val.ID && val.ID === obj.ID)": {"ID": task_id}}
    return_outputs(readable_output=human_readable, outputs=entry_context, raw_response=response)


""" COMMANDS MANAGER / SWITCH PANEL """

COMMANDS = {
    "test-module": test_module,
    "anyrun-get-history": get_history_command,
    "anyrun-get-report": get_report_command,
    "anyrun-run-analysis": run_analysis_command,
}

""" EXECUTION """


def main():
    """Main Execution block"""

    try:
        cmd_name = demisto.command()
        LOG(f"Command being called is {cmd_name}")
        handle_proxy()

        if cmd_name in COMMANDS:
            COMMANDS[cmd_name]()

    except Exception as e:
        return_error(str(e), error=traceback.format_exc())


# python2 uses __builtin__ python3 uses builtins
if __name__ in ("__builtin__", "builtins"):
    main()