Trend Micro Deep Discovery Analyzer

TrendAI™ Deep Discovery™ Analyzer is a turnkey appliance that uses virtual images of endpoint configurations to analyze and detect targeted attacks.

Forensics & Malware Analysis · TrendAI™ Deep Discovery™ Analyzer

Details

IDTrend Micro Deep Discovery Analyzer
ProviderTrendAI™
CategoryForensics & Malware Analysis
From Version5.0.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

trendmicro-dda-get-sample


Retrieves a sample

Base Command

trendmicro-dda-get-sample

Input

Argument Name Description Required
sha1 The SHA1 of the sample to get. Required
type The export data type. Possible values are: tgz, zip. Default is zip. Optional
encrypted 0 (not encrypted) or 1 (Encrypted with password “virus”). Possible values are: 0, 1. Default is 0. Optional
archive_name A name for the retrieved archive. Optional

Context Output

Path Type Description
File.EntryID string Demisto entry ID of archive
File.Size number File size
File.SHA1 string File SHA1
File SHA256 string File SHA256
File.Name string File name
File.SSDeep string File SSDeep
File.Info string File info
File.Type string File type
File.MD5 string File MD5
File.Extension string File extension

trendmicro-dda-get-report


Retrieves XML report of a given submission

Base Command

trendmicro-dda-get-report

Input

Argument Name Description Required
sha1 The SHA1 of the submission. Required
threshold DDA severity score (greater or equal to) for which the submission will be considered malicious. Possible values are: 0, 1, 2, 3. Default is 1. Optional
verbose Return detailed report. Possible values are: false, true. Default is false. Optional

Context Output

Path Type Description
TrendMicroDDA.Submission.Status string The status of the submission
TrendMicroDDA.Submission.SHA1 string SHA1 of the submission
TrendMicroDDA.Submission.RiskLevel number The Risk Level of the submission
DBotScore.Score number The actual score
DBotScore.Indicator string The indicator we tested
DBotScore.Type string The type of the indicator
DBotScore.Vendor string Vendor used to calculate the score
InfoFile.MD5 string MD5 hash of the report file
InfoFile.SHA1 string SHA1 hash of the report file
InfoFile.SHA256 string SHA256 hash of the report file
InfoFile.Name string Report file name
InfoFile.Type string Report file type e.g. “PE”
InfoFile.Size number Report file size
File.Malicious.Vendor string For malicious files, the vendor that made the decision
File.Malicious.Description string For malicious files, the reason for the vendor to make the decision
IP.Address string IPs relevant to the submission
Domain.Name string Domains relevant to the submission
URL.Data string URL data
File.MD5 string MD5 hash of the file
File.SHA1 string SHA1 hash of the file
File.SHA256 string SHA256 hash of the file
File.Size number File size
File.Name string File name
TrendMicroDDA.Submission.SHA256 string SHA256 of the submission
TrendMicroDDA.Submission.MD5 string MD5 of the submission
TrendMicroDDA.Submission.VirusDetected boolean True if virus detected, else Flase
TrendMicroDDA.Submission.DownloadURL string Download URL address of files

trendmicro-dda-get-sample-list


Retrieves a list of SHA1 of samples submitted within the given time interval

Base Command

trendmicro-dda-get-sample-list

Input

Argument Name Description Required
interval_start Interval start time, given in format ~~YYYY-MM-DD HH:MM:SS, e.g. 2008-11-22 19:53:42. Required
interval_end Interval end time, given in format YYYY-MM-DD HH:MM:SS, e.g. 2008-11-22 19:53:42. Required
interval_type 0: Submission time, 1: Completion time. Possible values are: 0, 1. Default is 0. Optional

Context Output

There is no context output for this command.

trendmicro-dda-check-status


Checks the analysis status of the submissions

Base Command

trendmicro-dda-check-status

Input

Argument Name Description Required
sha1 The SHA1 of the submissions. Example: “2492A18532745251FBC5DAF7160DAA49B90DBBE1, 52483514F07EB14570142F6927B77DEB7B4DA99F”. Required

Context Output

Path Type Description
TrendMicroDDA.Submission.Status string The status of the submission
TrendMicroDDA.Submission.SHA1 string The SHA1 of the submission

trendmicro-dda-upload-url


Upload a URL to TrendAI™ DDA

Base Command

trendmicro-dda-upload-url

Input

Argument Name Description Required
url The URL to upload. Required

Context Output

Path Type Description
TrendMicroDDA.Submission.SHA1 string The SHA1 of the submission
TrendMicroDDA.Submission.URL string The submitted URL

trendmicro-dda-upload-file


Upload a file to TrendAI™ DDA

Base Command

trendmicro-dda-upload-file

Input

Argument Name Description Required
entryID EntryID of the file to upload. Required

Context Output

Path Type Description
TrendMicroDDA.Submission.SHA1 string The SHA1 of the submission

trendmicro-dda-get-brief-report


Retrieves a brief XML report of a given submission

Base Command

trendmicro-dda-get-brief-report

Input

Argument Name Description Required
sha1 SHA1 of the submission. Required
threshold DDA severity score (greater or equal to) for which the submission will be considered malicious. Possible values are: 0, 1, 2, 3. Default is 1. Optional

Context Output

There is no context output for this command.

Configuration parameters

  • server — DDA Server and Port (e.g https://192.168.0.1:<port>) (required)
  • ip_address — Internal IP address (only needed if the server URL is external)
  • apiKey — API Key
  • credentials_api_key
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings
  • protocol_version — Protocol Version

Commands (8)

  • trendmicro-dda-check-status

    Checks the analysis status of the submissions

  • trendmicro-dda-get-brief-report

    Retrieves a brief XML report of a given submission

  • trendmicro-dda-get-openioc Deprecated

    Retrieves IOC for a given submission, returns an error if submission has no IOC

  • trendmicro-dda-get-report

    Retrieves XML report of a given submission

  • trendmicro-dda-get-sample

    Retrieves a sample

  • trendmicro-dda-get-sample-list

    Retrieves a list of SHA1 of samples submitted within the given time interval

  • trendmicro-dda-upload-file

    Upload a file to TrendAI™ DDA

  • trendmicro-dda-upload-url

    Upload a URL to TrendAI™ DDA

import copy
import hashlib
import json
import os.path
import platform
import re
import uuid
from datetime import datetime

import demistomock as demisto  # noqa: F401
import requests
from CommonServerPython import *  # noqa: F401

# disable insecure warnings
requests.packages.urllib3.disable_warnings()  # type: ignore[attr-defined]  # pylint: disable=no-member

if not demisto.params().get("proxy", True):
    # Remove proxy environment variables if they exist
    for proxy_var in ["HTTP_PROXY", "HTTPS_PROXY", "http_proxy", "https_proxy"]:
        os.environ.pop(proxy_var, None)

# HELPER FUNCTIONS #


def load_host_url():
    """loads the host url from the configuration or strips the server url to get valid host url"""
    host = demisto.params()["ip_address"]
    if host:
        # strip https://www. of the server address //disable-secrets-detection
        url = re.compile(r"https?://(www\.)?")
        host = url.sub("", demisto.params()["server"]).strip().strip("/")
        # strip :{port} of the server address
        host = host.split(":")[0]
    return host


def hash_file(filename):
    """Calculate the SHA1 of a file"""
    # The function was taken from here:
    # https://stackoverflow.com/questions/3431825/generating-an-md5-checksum-of-a-file#answer-3431838
    h = hashlib.sha1()  # nosec
    with open(filename, "rb") as f:
        for chunk in iter(lambda: f.read(1024), b""):
            h.update(chunk)
    return h.hexdigest()


def hash_url(url):
    """Calculate the SHA1 of a URL"""
    h = hashlib.sha1()  # nosec
    h.update(url.encode("utf-8"))
    return h.hexdigest()


def get_epoch_time():
    """Get the epoch time (for the X-DTAS-Time header value."""
    epoch_time = str(int(time.time()))
    return epoch_time


def get_epoch_from_datetime(dt):
    """Calculate epoch time from a datetime object"""
    epoch_format = str(int(time.mktime(dt.timetuple())))
    return epoch_format


def calculate_checksum(api_key, headers, body=""):
    """Generates a Checksum for the api call"""
    if not API_KEY:
        raise DemistoException("API key must be provided.")
    temp = api_key
    if "X-DTAS-ChecksumCalculatingOrder" in headers:
        x_dtas_checksum_calculating_order_list = headers["X-DTAS-ChecksumCalculatingOrder"].split(",")
        for key in x_dtas_checksum_calculating_order_list:
            temp += headers[key]
    else:
        for key, value in headers.items():
            if "X-DTAS-" in key and "X-DTAS-Checksum" not in key and "X-DTAS-ChecksumCalculatingOrder" not in key:
                temp += value

    temp += body
    return hashlib.sha1(temp.encode("utf-8"))  # nosec


def http_request(uri, method, headers, body={}, params={}, files={}):
    """Makes an API call to the server URL with the supplied uri, method, headers, body and params"""
    url = f"{SERVER_URL}/{uri}"
    if method not in ["put", "post"]:
        body = json.dumps(body)
    res = requests.request(method, url, headers=headers, data=body, verify=USE_SSL, params=params, files=files)

    if res.status_code != 102 and (res.status_code < 200 or res.status_code >= 300):
        raise Exception(
            "Got status code " + str(res.status_code) + " with body " + str(res.content) + " with headers " + str(res.headers)
        )
    return res


def file_uploaded_to_incident(file, file_sha1):
    """Converts an uploaded file to a Demisto incident"""
    incident = {}  # type: Dict[str, Any]
    incident["name"] = f"Incident: {file_sha1} "
    incident["occurred"] = str(CURRENT_TIME)
    incident["rawJSON"] = "TODO"

    labels = []  # type: list
    incident["labels"] = labels
    return incident


def binary_to_boolean_str(binary):
    if binary == "0":
        return "False"
    else:
        return "True"


def binary_to_boolean(binary):
    return binary == "0"


# GLOBAL VARIABLES #
API_KEY = demisto.params().get("credentials_api_key", {}).get("password") or demisto.params().get("apiKey")
PROTOCOL_VERSION = demisto.params()["protocol_version"]
SERVER_URL = demisto.params()["server"][:-1] if demisto.params()["server"].endswith("/") else demisto.params()["server"]
USE_SSL = not demisto.params().get("insecure", True)
UUID = str(uuid.uuid4())
HOST = load_host_url()

DEFAULT_HEADERS = {
    "X-DTAS-ProtocolVersion": PROTOCOL_VERSION,
    "X-DTAS-ClientUUID": UUID,
    "X-DTAS-Time": get_epoch_time(),
    "X-DTAS-Challenge": str(uuid.uuid4()),
    "X-DTAS-ProductName": "TDA",
    "X-DTAS-ClientHostname": platform.node(),
    "X-DTAS-SourceID": "1",
    "X-DTAS-SourceName": "DemistoIntegration",
}
if HOST:
    DEFAULT_HEADERS["Host"] = HOST


# for fetch incident
CURRENT_TIME = datetime.utcnow()

# COMMAND FUNCTIONS #


def register():
    headers_register = copy.deepcopy(DEFAULT_HEADERS)
    tmp_checksum = calculate_checksum(API_KEY, headers_register)
    headers_register["X-DTAS-Checksum"] = tmp_checksum.hexdigest()
    http_request("web_service/sample_upload/register", "get", headers_register)


def unregister():
    headers_unregister = copy.deepcopy(DEFAULT_HEADERS)
    tmp_checksum = calculate_checksum(API_KEY, headers_unregister)
    headers_unregister["X-DTAS-Checksum"] = tmp_checksum.hexdigest()
    http_request("web_service/sample_upload/unregister", "get", headers_unregister)


def test():
    headers_test = copy.deepcopy(DEFAULT_HEADERS)
    tmp_checksum = calculate_checksum(API_KEY, headers_test)
    headers_test["X-DTAS-Checksum"] = tmp_checksum.hexdigest()
    http_request("web_service/sample_upload/test_connection", "get", headers_test)
    demisto.results("ok")


def prettify_simple_upload_sample_file(sha1):
    pretty_sample = {"SHA1": sha1.upper()}
    return pretty_sample


def simple_upload_sample_file(sample_file):
    """Upload a file to Deep Discovery Analyzer for analysis"""
    with open(demisto.getFilePath(sample_file)["path"], "rb") as f:
        headers_simple_upload_sample_file = {
            "X-DTAS-ProtocolVersion": PROTOCOL_VERSION,
            "X-DTAS-ClientUUID": UUID,
            "X-DTAS-SourceID": "1",
            "X-DTAS-SourceName": "DemistoIntegration",
            "X-DTAS-SHA1": hash_file(demisto.getFilePath(sample_file)["path"]),
            "X-DTAS-Time": get_epoch_time(),
            "X-DTAS-SampleType": "0",  # 0 for file, 1 for URL
            "X-DTAS-Challenge": str(uuid.uuid4()),
            "X-DTAS-ChecksumCalculatingOrder": "X-DTAS-ProtocolVersion,X-DTAS-ClientUUID,X-DTAS-SourceID,X-DTAS-SourceName,"
            + "X-DTAS-SHA1,X-DTAS-Time,X-DTAS-SampleType,X-DTAS-Challenge",
        }
        tmp_checksum = calculate_checksum(API_KEY, headers_simple_upload_sample_file)
        headers_simple_upload_sample_file["X-DTAS-Checksum"] = tmp_checksum.hexdigest()
        cmd_url = "web_service/sample_upload/simple_upload_sample"
        res = http_request(cmd_url, "post", headers_simple_upload_sample_file, files={"uploadsample": f})
    pretty_res = prettify_simple_upload_sample_file(headers_simple_upload_sample_file["X-DTAS-SHA1"])
    return res, pretty_res


def simple_upload_sample_file_command():
    sample_file = demisto.args().get("entryID")
    res, pretty_res = simple_upload_sample_file(sample_file)

    demisto.results(
        {
            "Type": entryTypes["note"],
            "ContentsFormat": formats["text"],
            "Contents": "File was uploaded to Trend Micro DDA successfully",
            "EntryContext": {"TrendMicroDDA.Submission(val.SHA1 && val.SHA1==obj.SHA1)": pretty_res},
        }
    )


def prettify_simple_upload_sample_url(url, sha1):
    pretty_sample = {"SHA1": sha1.upper(), "URL": url}
    return pretty_sample


def simple_upload_sample_url(sample_url):
    """Upload a URL to Analyzer for analysis"""
    headers_simple_upload_sample_url = {
        "X-DTAS-ProtocolVersion": PROTOCOL_VERSION,
        "X-DTAS-ClientUUID": UUID,
        "X-DTAS-SourceID": "1",
        "X-DTAS-SourceName": "DemistoIntegration",
        "X-DTAS-SHA1": hash_url(sample_url),
        "X-DTAS-Time": get_epoch_time(),
        "X-DTAS-SampleType": "1",  # 0 for file, 1 for URL
        "X-DTAS-Challenge": str(uuid.uuid4()),
        "X-DTAS-ChecksumCalculatingOrder": "X-DTAS-ProtocolVersion,X-DTAS-ClientUUID,X-DTAS-SourceID,X-DTAS-SourceName,"
        + "X-DTAS-SHA1,X-DTAS-Time,X-DTAS-SampleType,X-DTAS-Challenge",
    }
    tmp_checksum = calculate_checksum(API_KEY, headers_simple_upload_sample_url)
    headers_simple_upload_sample_url["X-DTAS-Checksum"] = tmp_checksum.hexdigest()

    cmd_url = "web_service/sample_upload/simple_upload_sample"
    res = http_request(cmd_url, "post", headers_simple_upload_sample_url, files={"uploadsample": sample_url})

    pretty_res = prettify_simple_upload_sample_url(sample_url, headers_simple_upload_sample_url["X-DTAS-SHA1"])
    return res, pretty_res


def simple_upload_sample_url_command():
    sample_url = demisto.args().get("url")
    res, pretty_res = simple_upload_sample_url(sample_url)

    demisto.results(
        {
            "Type": entryTypes["note"],
            "Contents": str(res.headers),
            "ContentsFormat": formats["text"],
            "ReadableContentsFormat": formats["markdown"],
            "HumanReadable": tableToMarkdown("URL was uploaded to Trend Micro DDA successfully", pretty_res),
            "EntryContext": {"TrendMicroDDA.Submission(val.SHA1 && val.SHA1==obj.SHA1)": pretty_res},
        }
    )


def get_sample(sha1, archive_type, archive_encrypted, archive_name):
    """Issue a request to retrieve an archive of the sample given its SHA1 hash"""
    if not (re.match(r"\b[0-9a-fA-F]{40}\b", sha1)):
        return_error(f"Provided SHA1: {sha1} is unvalid.")

    headers_get_sample = copy.deepcopy(DEFAULT_HEADERS)
    headers_get_sample["X-DTAS-SHA1"] = sha1  # SHA1 of the file/URL to download
    headers_get_sample["X-DTAS-ArchiveType"] = archive_type
    headers_get_sample["X-DTAS-ArchiveEncrypted"] = archive_encrypted

    tmp_checksum = calculate_checksum(API_KEY, headers_get_sample)
    headers_get_sample["X-DTAS-Checksum"] = tmp_checksum.hexdigest()

    cmd_url = "web_service/sample_upload/get_sample"
    res = http_request(cmd_url, "get", headers_get_sample)
    file = fileResult(archive_name, res.content)

    return res, file


def get_sample_command():
    sha1 = demisto.args()["sha1"]
    archive_type = demisto.args()["type"]
    archive_encrypted = demisto.args()["encrypted"]
    archive_name = demisto.args().get("archive_name", sha1)
    archive_name += f".{archive_type}"
    res, file = get_sample(sha1, archive_type, archive_encrypted, archive_name)

    return demisto.results(file)


def get_sample_list(interval_start, interval_end, interval_type):
    try:
        interval_start_dt = datetime.strptime(interval_start, "%Y-%m-%d %H:%M:%S")
        interval_end_dt = datetime.strptime(interval_end, "%Y-%m-%d %H:%M:%S")
    except BaseException:
        return_error(
            "Given interval times are not in the required format, which is: YYYY-MM-DD HH:MM:SS, " + "e.g. 2008-11-22 19:53:42"
        )

    headers_get_sample_list = copy.deepcopy(DEFAULT_HEADERS)
    headers_get_sample_list["X-DTAS-IntervalStartingPoint"] = get_epoch_from_datetime(interval_start_dt)
    headers_get_sample_list["X-DTAS-IntervalEndPoint"] = get_epoch_from_datetime(interval_end_dt)
    headers_get_sample_list["X-DTAS-IntervalType"] = interval_type

    tmp_checksum = calculate_checksum(API_KEY, headers_get_sample_list)
    headers_get_sample_list["X-DTAS-Checksum"] = tmp_checksum.hexdigest()

    cmd_url = "web_service/sample_upload/get_sample_list"
    res = http_request(cmd_url, "get", headers_get_sample_list)

    return res  # returns a list of SHA1 of the samples


def get_sample_list_command():
    """Issue a request to get a semi-colon separated values list of submissions within the given time interval"""
    interval_start = demisto.args()["interval_start"]
    interval_end = demisto.args()["interval_end"]
    interval_type = demisto.args()["interval_type"]
    result = get_sample_list(interval_start, interval_end, interval_type)
    if result.text:
        sha1_list = result.text.split(";")
        hr = "### Trend Micro DDA submissions SHA1\n"
        for sha1 in sha1_list:
            hr += f"- {sha1}\n"

        demisto.results(
            {
                "Type": entryTypes["note"],
                "ContentsFormat": formats["text"],
                "Contents": result.text,
                "ReadableContentsFormat": formats["markdown"],
                "HumanReadable": hr,
            }
        )
    else:
        demisto.results("No results found.")


def build_report(res, threshold, status, verbose):
    report_json = json.loads(xml2json(res.text.encode("utf-8")))
    reports = report_json["REPORTS"]
    # true if list, false if dict
    reports_type_is_list = isinstance(reports["FILE_ANALYZE_REPORT"], list)
    hr = {}  # type: Dict[str, Union[str, Dict[str, str]]]

    if isinstance(reports, dict):
        image_type_dict = reports.get("IMAGE_TYPE", {})
        if isinstance(image_type_dict, dict):
            image_type_dict = image_type_dict.get("TYPE", {})

            if isinstance(image_type_dict, dict):
                image_type = image_type_dict.get("#text", "Unknown")
            else:
                image_type = "Unknown"

        else:
            image_type = "Unknown"
    else:
        image_type = "Unknown"

    hr_headers = {
        "Risk Level": reports["OVERALL_RISK_LEVEL"],
        "Image Type": image_type,
        "Sum of Files Analyzed": (len(reports["FILE_ANALYZE_REPORT"])) if reports_type_is_list else "1",
    }

    context = {}  # type: Dict[str, Any]
    dbot_score = 0
    context["DBotScore"] = {
        "Vendor": "Trend Micro DDA",
        "Score": dbot_score,  # check that------------------ TODO --------------------
        "Type": "hash",
        "Indicator": reports["FILE_ANALYZE_REPORT"]["FileSHA1"]
        if not reports_type_is_list
        else reports["FILE_ANALYZE_REPORT"][0]["FileSHA1"],
    }
    # if type is list, the submission was divided to sub-files and the first file_analyze_report is of the main submission
    # context['DBotScore.Indicator'] = reports['FILE_ANALYZE_REPORT']['FileSHA1']
    # if not reports_type_is_list else reports['FILE_ANALYZE_REPORT'][0]['FileSHA1']

    if not reports_type_is_list:  # if the submission doesn't have sub-files
        file_analyze_report = reports["FILE_ANALYZE_REPORT"]
        hr["File Name"] = file_analyze_report["OrigFileName"]
        hr["Malware Source IP"] = file_analyze_report["MalwareSourceIP"]
        hr["Malware Source Host"] = file_analyze_report["MalwareSourceHost"]
        hr["Total Dropped Files"] = file_analyze_report["DroppedFiles"]["@Total"]
        hr["Deny List"] = binary_to_boolean_str(file_analyze_report["IsDenylisted"])
        hr["White List"] = binary_to_boolean_str(file_analyze_report["IsWhitelisted"])

        if "#text" in file_analyze_report["VirusName"]:  # the submission has a detection
            hr["Detection Name"] = file_analyze_report["VirusName"]["#text"]
        # set the filename
        filename = hr["Detection Name"] if ("Detection Name" in hr) else file_analyze_report["FileSHA1"]
        if filename and "." not in filename:
            filename = str(filename) + ".txt"

        # add data regarding the submission to the context
        context["TrendMicroDDA.Submission(val.SHA1 && val.SHA1==obj.SHA1)"] = {
            "Status": status,
            "RiskLevel": reports["OVERALL_RISK_LEVEL"],
            "SHA1": file_analyze_report["FileSHA1"],
            "SHA256": file_analyze_report["FileSHA256"],
            "MD5": file_analyze_report["FileMD5"],
            "VirusDetected": binary_to_boolean(file_analyze_report["VirusDetected"]),
        }

        if file_analyze_report["TrueFileType"] == "URL":
            # add the URL address
            context[outputPaths["url"]] = {"Data": file_analyze_report["OrigFileName"]}
        else:
            context[outputPaths["file"]] = {
                "MD5": file_analyze_report["FileMD5"],
                "SHA1": file_analyze_report["FileSHA1"],
                "SHA256": file_analyze_report["FileSHA256"],
                "Size": file_analyze_report["FileSize"],
                "Name": file_analyze_report["OrigFileName"],
            }

        # add data regarding the submission to the context if file is malicious
        if reports["OVERALL_RISK_LEVEL"] >= threshold:
            if file_analyze_report["TrueFileType"] == "URL":
                context[outputPaths["url"]].update(
                    {"Malicious": {"Vendor": "Trend Micro DDA", "Description": "RiskLevel: " + reports["OVERALL_RISK_LEVEL"]}}
                )
            else:
                context[outputPaths["file"]].update(
                    {"Malicious": {"Vendor": "Trend Micro DDA", "Description": "RiskLevel: " + reports["OVERALL_RISK_LEVEL"]}}
                )

        # extracting IP and Domains from the report
        if file_analyze_report["MalwareSourceIP"]:
            context["IP.Address(val.Address && val.Address == obj.Address)"] = file_analyze_report["MalwareSourceIP"]
        if file_analyze_report["MalwareSourceHost"]:
            context["Domain.Name(val.Name && val.Name == obj.Name)"] = file_analyze_report["MalwareSourceHost"]
        if verbose == "true":
            dropped_files = file_analyze_report["DroppedFiles"]
            if "FileItem" in dropped_files and "DownloadURL" in dropped_files["FileItem"]:
                context["URL.Data(val.Data && val.Data == obj.Data)"] = dropped_files["FileItem"]["DownloadURL"]
                hr["Download URL"] = dropped_files["FileItem"]["DownloadURL"]
                context["TrendMicroDDA.Submission"].update({"DownloadURL": dropped_files["FileItem"]["DownloadURL"]})

    else:  # if the submission have sub-files
        main_file_analyze_report = reports["FILE_ANALYZE_REPORT"][0]

        # add data to the war room
        hr = copy.deepcopy(reports["FILE_ANALYZE_REPORT"])
        for item in hr:
            item["File Name"] = item["OrigFileName"]  # type: ignore
            item["Detection Name"] = item["VirusName"].get("#text", None)  # type: ignore
            item["Malware Source IP"] = item["MalwareSourceIP"]  # type: ignore
            item["Malware Source Host"] = item["MalwareSourceHost"]  # type: ignore
            if verbose == "true":
                item["Download URL"] = item["DroppedFiles"].get("FileItem")  # type: ignore
            item["Deny List"] = binary_to_boolean_str(item["IsDenylisted"]) if item["IsDenylisted"] else None  # type: ignore
            item["White List"] = binary_to_boolean_str(item["IsWhitelisted"]) if item["IsWhitelisted"] else None  # type: ignore

        # set the filename
        filename = main_file_analyze_report["OrigFileName"]
        if filename and "." not in filename:
            filename = str(filename) + ".txt"

        # This section was commented out because it used an undefined variable download_url_list.
        # Need to check again if it should be moving to GA.

        # if verbose == 'true':
        #     hr['Download URL'] = download_url_list
        #     context['URL.Data(val.Data && val.Data == obj.Data)'] = download_url_list
        #     context['TrendMicroDDA.Submission'].update({
        #         'DownloadURL': download_url_list
        #     })

        # add data regarding the submission to the context
        file_analyzed_list = []
        for file_analyzed in reports["FILE_ANALYZE_REPORT"][1:]:  # iterate over all the subfiles excluding the main file
            file_analyzed_dict = {
                "SHA1": file_analyzed["FileSHA1"],
                "SHA256": file_analyzed["FileSHA256"],
                "MD5": file_analyzed["FileMD5"],
                "Name": file_analyzed["VirusName"].get("#text", ""),
                "VirusDetected": binary_to_boolean(file_analyzed["VirusDetected"]),
            }
            if file_analyzed["TrueFileType"] == "URL":
                # add the URL address
                context[outputPaths["url"]] = {"Data": file_analyzed["OrigFileName"]}
            else:
                context[outputPaths["file"]] = {
                    "MD5": file_analyzed["FileMD5"],
                    "SHA1": file_analyzed["FileSHA1"],
                    "SHA256": file_analyzed["FileSHA256"],
                    "Size": file_analyzed["FileSize"],
                    "Name": file_analyzed["VirusName"].get("#text", ""),
                    # add score of some sort from virusdetected? ask michal.------------------ TODO --------------------
                }
            file_analyzed_list.append(file_analyzed_dict)

        context["TrendMicroDDA.Submission(val.SHA1 && val.SHA1==obj.SHA1)"] = {
            "Status": status,
            "RiskLevel": reports["OVERALL_RISK_LEVEL"],
            "SHA1": main_file_analyze_report["FileSHA1"],
            "SHA256": main_file_analyze_report["FileSHA256"],
            "MD5": main_file_analyze_report["FileMD5"],
            "VirusDetected": binary_to_boolean(main_file_analyze_report["VirusDetected"]),
            "FileAnalyzed": file_analyzed_list,
        }
        if main_file_analyze_report["TrueFileType"] == "URL":
            context["URL(val.Data && val.Data==obj.Data)"] = {
                "Data": main_file_analyze_report["OrigFileName"],
            }
        else:
            context["File(val.SHA1 && val.SHA1==obj.SHA1)"] = {
                "MD5": main_file_analyze_report["FileMD5"],
                "SHA1": main_file_analyze_report["FileSHA1"],
                "SHA256": main_file_analyze_report["FileSHA256"],
                "Size": main_file_analyze_report["FileSize"],
                "Name": main_file_analyze_report["VirusName"].get("#text", ""),
            }
        # add data regarding the submission to the context if it is malicious
        if reports["OVERALL_RISK_LEVEL"] >= threshold:
            context["DBotScore.Score"] = 3
            if main_file_analyze_report["TrueFileType"] == "URL":
                context[outputPaths["url"]] = {
                    "Malicious": {"Vendor": "Trend Micro DDA", "Description": "RiskLevel: " + reports["OVERALL_RISK_LEVEL"]}
                }
            else:
                context[outputPaths["file"]] = {
                    "Malicious": {"Vendor": "Trend Micro DDA", "Description": "RiskLevel: " + reports["OVERALL_RISK_LEVEL"]}
                }

        # extracting IP and Domains from the report
        if main_file_analyze_report["MalwareSourceIP"]:
            context["IP.Address(val.Address && val.Address == obj.Address)"] = main_file_analyze_report["MalwareSourceIP"]
        if main_file_analyze_report["MalwareSourceHost"]:
            context["Domain.Name(val.Name && val.Name == obj.Name)"] = main_file_analyze_report["MalwareSourceHost"]

    return context, hr, hr_headers, filename


def get_report(sha1):
    """Issue a request to retrieve XML report for a given SHA1"""
    if not (re.match(r"\b[0-9a-fA-F]{40}\b", sha1)):
        return_error(f"Provided SHA1: {sha1} is unvalid.")

    headers_get_report = copy.deepcopy(DEFAULT_HEADERS)
    headers_get_report["X-DTAS-SHA1"] = sha1  # SHA1 of the file/URL to download
    headers_get_report["X-DTAS-Time"] = get_epoch_time()

    tmp_checksum = calculate_checksum(API_KEY, headers_get_report)
    headers_get_report["X-DTAS-Checksum"] = tmp_checksum.hexdigest()

    cmd_url = "web_service/sample_upload/get_report"
    res = http_request(cmd_url, "get", headers_get_report)

    return res


def get_report_command():
    sha1 = demisto.args()["sha1"]
    threshold = demisto.args()["threshold"]
    verbose = demisto.args()["verbose"]
    res = get_report(sha1)

    if res.status_code == 102:
        ec = {"Status": "Analyzing", "SHA1": sha1}
        demisto.results(
            {
                "Type": entryTypes["note"],
                "ContentsFormat": formats["text"],
                "Content": {"value": res},
                "HumanReadable": "Submission analyzation was not finished yet.",
                "EntryContext": {"TrendMicroDDA.Submission(val.SHA1 && val.SHA1==obj.SHA1)": ec},
            }
        )
    else:
        status = "Completed"

        context, hr, hr_headers, filename = build_report(res, threshold, status, verbose)
        markdown_table_headers = ["File Name", "Detection Name", "Malware Source IP", "Malware Source Host"]
        if verbose == "true":
            markdown_table_headers.append("Download URL")
        markdown_table_headers.extend(("Deny List", "White List"))

        tmp_file = fileResult(filename, res.text)

        demisto.results(
            {  # add context and the Report File to the war room
                "Type": entryTypes["file"],
                "FileID": tmp_file.get("FileID"),
                "Contents": "",
                "ContentsFormat": formats["text"],
                "File": tmp_file.get("File"),
                "EntryContext": context,
            }
        )
        demisto.results(
            {  # add table to the war room
                "Type": entryTypes["note"],
                "Contents": res.text,
                "ContentsFormat": formats["text"],
                "HumanReadableFormat": formats["markdown"],
                "HumanReadable": "## Submission Report from TrendMicroDDA\n"
                + "### Risk Level: {}, Sum of Files Analyzed: {}, Image Type: {}\n".format(
                    hr_headers["Risk Level"], hr_headers["Sum of Files Analyzed"], hr_headers["Image Type"]
                )
                + tableToMarkdown("Report Summary", hr, headers=markdown_table_headers),
            }
        )


def build_brief_report(res, sha1, threshold):
    report_json = json.loads(xml2json(res.text))
    brief_report_json = report_json.get("REPORT", {}).get("BRIEF_REPORT", {})
    hr = {
        "SHA1": sha1,
        "Risk Level": brief_report_json.get("RiskLevel"),
        "Status": brief_report_json.get("STATUS"),
    }
    return hr


def get_brief_report(sha1):
    if not (re.match(r"\b[0-9a-fA-F]{40}\b", sha1)):
        return_error("Provided SHA1 is unvalid.")

    headers_get_brief_report = {
        "Content-Type": "text/plain",
        "X-DTAS-ProtocolVersion": PROTOCOL_VERSION,
        "X-DTAS-ClientUUID": UUID,
        "X-DTAS-Time": get_epoch_time(),
        "X-DTAS-Challenge": str(uuid.uuid4()),
        "X-DTAS-ChecksumCalculatingOrder": "X-DTAS-ProtocolVersion,X-DTAS-ClientUUID,X-DTAS-Time,X-DTAS-Challenge",
    }
    sha1_list = argToList(sha1)
    data = ";".join(sha1_list)
    tmp_checksum = calculate_checksum(API_KEY, headers_get_brief_report, data)
    headers_get_brief_report["X-DTAS-Checksum"] = tmp_checksum.hexdigest()

    cmd_url = "web_service/sample_upload/get_brief_report"
    res = http_request(cmd_url, "put", headers=headers_get_brief_report, body=data)
    return res


def get_brief_report_command():
    """Issue a request to retrieve the brief XML report for a given SHA1"""
    sha1 = demisto.args()["sha1"]
    threshold = demisto.args()["threshold"]
    res = get_brief_report(sha1)

    hr = build_brief_report(res, sha1, threshold)
    demisto.results(
        {
            "Type": entryTypes["note"],
            "ContentsFormat": formats["text"],
            "Contents": res.text,
            "HumanReadableFormat": formats["markdown"],
            "HumanReadable": tableToMarkdown("Sample Brief Report from TrendMicroDDA", hr, removeNull=True),
            # 'EntryContext': {
            #    'TrendMicroDDA.Submission(val.SHA1 && val.SHA1==obj.SHA1)': context
            # }
        }
    )


def check_status(sha1_list):
    for sha1 in sha1_list:
        if not (re.match(r"\b[0-9a-fA-F]{40}\b", sha1)):
            return_error(f"Provided SHA1: {sha1} is unvalid.")
    manyRes = []
    manyEC = []

    for sha1 in sha1_list:
        res = get_report(sha1)
        manyRes.append(res.text)
        if res.status_code == 102:
            manyEC.append({"Status": "Analyzing", "SHA1": sha1})
        else:
            manyEC.append({"Status": "Completed", "SHA1": sha1})

    return manyRes, manyEC


def check_status_command():
    sha1_list = argToList(demisto.args()["sha1"])
    (
        manyRes,
        manyEC,
    ) = check_status(sha1_list)

    demisto.results(
        {
            "Type": entryTypes["note"],
            "Contents": manyRes,
            "ContentsFormat": formats["json"],
            "ReadableContentsFormat": formats["markdown"],
            "HumanReadable": tableToMarkdown("Status of the submissions in TrendMicroDDA", manyEC),
            "EntryContext": {"TrendMicroDDA.Submission(val.SHA1 && val.SHA1==obj.SHA1)": manyEC},
        }
    )


# EXECUTION
LOG(f"command is {demisto.command()}")

try:
    register()
    if demisto.command() == "test-module":
        test()

    elif demisto.command() == "trendmicro-dda-upload-file":
        simple_upload_sample_file_command()

    elif demisto.command() == "trendmicro-dda-upload-url":
        simple_upload_sample_url_command()

    elif demisto.command() == "trendmicro-dda-get-sample":
        get_sample_command()

    elif demisto.command() == "trendmicro-dda-check-status":
        check_status_command()

    elif demisto.command() == "trendmicro-dda-get-brief-report":
        get_brief_report_command()

    elif demisto.command() == "trendmicro-dda-get-report":  # add !file !url command? ask anar
        get_report_command()

    elif demisto.command() == "trendmicro-dda-get-openioc":
        # get_openioc_report_command()
        return_error("Deprecated command")

    elif demisto.command() == "trendmicro-dda-get-sample-list":
        get_sample_list_command()

except Exception as e:
    LOG(str(e))
    LOG.print_log()
    raise

finally:
    unregister()