Пример #1
0
def _pyintelowl_logic(args, logger):
    md5 = None
    results = []
    elapsed_time = None
    get_configuration_only = False
    try:
        filename = None
        binary = None
        if args.command == "file":
            if not os.path.exists(args.file):
                raise IntelOwlClientException(f"{args.file} does not exists")
            with open(args.file, "rb") as f:
                binary = f.read()
                filename = os.path.basename(f.name)
            md5 = hashlib.md5(binary).hexdigest()
        elif args.command == "observable":
            args.value = args.value.lower()
            md5 = hashlib.md5(args.value.encode("utf-8")).hexdigest()
        elif args.get_configuration:
            get_configuration_only = True
        else:
            raise IntelOwlClientException(
                "you must specify the type of the analysis: [observable, file]"
            )

        pyintelowl_client = IntelOwl(args.api_token_file, args.certificate,
                                     args.instance, args.debug)

        if get_configuration_only:
            api_request_result = pyintelowl_client.get_analyzer_configs()
            errors = api_request_result.get("errors", [])
            if errors:
                logger.error(
                    f"API get_analyzer_configs failed. Errors: {errors}")
            analyzers_config = api_request_result.get("answer", {})
            logger.info(
                f"extracted analyzer_configuration: {analyzers_config}")
            pprint(analyzers_config)
            exit(0)

        analysis_available = False
        if not args.skip_check_analysis_availability:
            job_id_to_get = None
            # first step: ask analysis availability
            logger.info(
                f"[STARTED] request ask_analysis_availability for md5: {md5}, analyzers: {args.analyzers_list}"
            )

            api_request_result = pyintelowl_client.ask_analysis_availability(
                md5,
                args.analyzers_list,
                args.run_all_available_analyzers,
                args.check_reported_analysis_too,
            )
            errors = api_request_result.get("errors", [])
            if errors:
                raise IntelOwlClientException(
                    f"API ask_analysis_availability failed. Errors: {errors}")
            answer = api_request_result.get("answer", {})
            status = answer.get("status", None)
            if not status:
                raise IntelOwlClientException(
                    "API ask_analysis_availability gave result without status!?!?"
                    f" Answer: {answer}")
            if status != "not_available":
                analysis_available = True
                job_id_to_get = answer.get("job_id", "")
                if job_id_to_get:
                    logger.info(
                        f"[INFO] already existing Job(#{job_id_to_get}, md5: {md5},"
                        f" status: {status}) with analyzers: {args.analyzers_list}"
                    )
                else:
                    raise IntelOwlClientException(
                        "API ask_analysis_availability gave result without job_id!?!?"
                        f" Answer:{answer}")

        # second step: in case there are no analysis available, start a new analysis
        if not analysis_available:

            if args.command == "file":
                api_request_result = pyintelowl_client.send_file_analysis_request(
                    md5,
                    args.analyzers_list,
                    filename,
                    binary,
                    args.force_privacy,
                    args.private_job,
                    args.disable_external_analyzers,
                    args.run_all_available_analyzers,
                )
            elif args.command == "observable":
                api_request_result = pyintelowl_client.send_observable_analysis_request(
                    md5,
                    args.analyzers_list,
                    args.value,
                    args.force_privacy,
                    args.private_job,
                    args.disable_external_analyzers,
                    args.run_all_available_analyzers,
                )
            else:
                raise NotImplementedError()

            # both cases share the same logic for the management of the result retrieved from the API
            errors = api_request_result.get("errors", [])
            if errors:
                raise IntelOwlClientException(
                    f"API send_analysis_request failed. Errors: {errors}")
            answer = api_request_result.get("answer", {})
            logger.info(
                f"[INFO] md5: {md5} received response from intel_owl: {answer}"
            )
            status = answer.get("status", None)
            if not status:
                raise IntelOwlClientException(
                    "API send_analysis_request gave result without status!?"
                    f" Answer:{answer}")
            if status != "accepted":
                raise IntelOwlClientException(
                    f"API send_analysis_request gave unexpected result status: {status}"
                )
            job_id_to_get = answer.get("job_id", None)
            analyzers_running = answer.get("analyzers_running", None)
            warnings = answer.get("warnings", [])
            if job_id_to_get:
                logger.info(
                    f"[STARTED] Job(#{job_id_to_get}, md5: {md5}, status: {status})"
                    f" -> analyzers: {analyzers_running}. Warnings: {warnings}"
                )
            else:
                raise IntelOwlClientException(
                    f"API send_analysis_request gave result without job_id!?!?"
                    f"answer:{answer}")

        # third step: at this moment we must have a job_id to check for results
        polling_max_tries = 60 * 20
        polling_interval = 1
        logger.info("[STARTED] polling...")
        for chance in range(polling_max_tries):
            time.sleep(polling_interval)
            api_request_result = pyintelowl_client.ask_analysis_result(
                job_id_to_get)
            errors = api_request_result.get("errors", [])
            if errors:
                raise IntelOwlClientException(
                    f"API ask_analysis_result failed. Errors: {errors}")
            answer = api_request_result.get("answer", {})
            status = answer.get("status", None)
            if not status:
                raise IntelOwlClientException(
                    f"API ask_analysis_result gave result without status!?!?"
                    f" job_id:{job_id_to_get} answer:{answer}")
            if status in ["invalid_id", "not_available"]:
                raise IntelOwlClientException(
                    f"API send_analysis_request gave status {status}")
            if status == "running":
                continue
            if status == "pending":
                logger.warning(
                    f"API ask_analysis_result check job in status 'pending'. Maybe it is stuck"
                    f"job_id:{job_id_to_get} md5:{md5} analyzer_list:{args.analyzers_list}"
                )
            elif status in [
                    "reported_without_fails", "reported_with_fails", "failed"
            ]:
                logger.info(
                    f"[FINISHED] Job(#{job_id_to_get}, md5: {md5}, status: {status})"
                    f" -> analyzer_list:{args.analyzers_list}")
                results = answer.get("results", [])
                elapsed_time = answer.get("elapsed_time_in_seconds", [])
                break
        if not results:
            raise IntelOwlClientException(
                f"[ENDED] Reached polling timeout without results. Job_id: {job_id_to_get}"
            )

    except IntelOwlClientException as e:
        logger.error(f"Error: {e} md5: {md5}")
    except requests.exceptions.HTTPError as e:
        logger.exception(e)
    except IntelOwlInvalidAPITokenException as e:
        logger.exception(e)
        exit(-1)
    except Exception as e:
        logger.exception(e)

    logger.info(f"Elapsed time: {elapsed_time}")
    logger.info("Results:")
    if args.show_colors:
        checkers = Checkers(results, args.value)
        observable = get_observable_classification(args.value)
        if "domain" in observable:
            checkers.check_domain()
        elif "hash" in observable:
            checkers.check_hash()
        elif "url" in observable:
            checkers.check_url()
        else:
            checkers.check_ip()
    else:
        pprint(results)
Пример #2
0
 def setUp(self):
     self.client = IntelOwl(secrets.get_secret("TEST_TOKEN"), False,
                            "http://nginx", True)
Пример #3
0
def intel_owl_client():

    parser = argparse.ArgumentParser(description='Intel Owl classic client.')
    parser.add_argument("-k",
                        "--api-key",
                        required=True,
                        help="your Intel Owl API key")
    parser.add_argument("-c",
                        "--certificate",
                        default=False,
                        help="path to Intel Owl certificate")
    parser.add_argument("-i",
                        "--instance",
                        required=True,
                        help="your instance URL")
    parser.add_argument("-d",
                        "--debug",
                        action="store_true",
                        default=False,
                        help="debug mode")
    parser.add_argument("-l", "--log-to-file", help="log to specified file")
    parser.add_argument("-a",
                        "--analyzers-list",
                        required=True,
                        action='append',
                        help="list of analyzers to launch")
    parser.add_argument("-p",
                        "--force-privacy",
                        action="store_true",
                        default=False,
                        help="disable analyzers that could impact privacy")
    parser.add_argument("-e",
                        "--disable-external-analyzers",
                        action="store_true",
                        default=False,
                        help="disable analyzers that use external services")
    parser.add_argument(
        "-r",
        "--check-reported-analysis-too",
        action="store_true",
        default=False,
        help="check reported analysis too, not only 'running' ones")
    parser.add_argument("-s",
                        "--skip-check-analysis-availability",
                        action="store_true",
                        default=False,
                        help="skip check analysis availability")

    subparsers = parser.add_subparsers(help='choose type of analysis',
                                       dest='command')
    parser_sample = subparsers.add_parser('file', help='File analysis')
    parser_observable = subparsers.add_parser('observable',
                                              help='Observables analysis')

    parser_sample.add_argument("-f",
                               "--file",
                               required=True,
                               help="file to analyze")
    parser_observable.add_argument("-v",
                                   "--value",
                                   required=True,
                                   help="observable to analyze")

    args = parser.parse_args()

    logger = get_logger(args.debug, args.log_to_file)

    md5 = None
    results = []
    elapsed_time = None
    try:
        filename = None
        binary = None
        if args.command == 'file':
            if not os.path.exists(args.file):
                raise IntelOwlClientException("{} does not exists".format(
                    args.file))
            with open(args.file, "rb") as f:
                binary = f.read()
                filename = os.path.basename(f.name)
            md5 = hashlib.md5(binary).hexdigest()
        elif args.command == 'observable':
            md5 = hashlib.md5(args.value.encode('utf-8')).hexdigest()
        else:
            raise IntelOwlClientException(
                "you must specify the type of the analysis: [observable, file]"
            )

        pyintelowl_client = IntelOwl(args.api_key, args.certificate,
                                     args.instance, args.debug)

        analysis_available = False
        if not args.skip_check_analysis_availability:
            job_id_to_get = None
            # first step: ask analysis availability
            logger.info(
                "about to request ask_analysis_availability for md5: {}, analyzers: {}"
                "".format(md5, args.analyzers_list))

            api_request_result = pyintelowl_client.ask_analysis_availability(
                md5, args.analyzers_list, args.check_reported_analysis_too)
            errors = api_request_result.get('errors', [])
            if errors:
                raise IntelOwlClientException(
                    "API ask_analysis_availability failed. Errors: {}"
                    "".format(errors))
            answer = api_request_result.get('answer', {})
            status = answer.get('status', '')
            if not status:
                raise IntelOwlClientException(
                    "API ask_analysis_availability gave result without status!?!?"
                    "answer:{}".format(answer))
            elif status != 'not_available':
                analysis_available = True
                job_id_to_get = answer.get('job_id', '')
                if job_id_to_get:
                    logger.info(
                        "found already existing job with id {} and status {} for md5 {} and analyzers {}"
                        "".format(job_id_to_get, status, md5,
                                  args.analyzers_list))
                else:
                    raise IntelOwlClientException(
                        "API ask_analysis_availability gave result without job_id!?!? answer:{}"
                        "".format(answer))

        # second step: in case there are no analysis available, start a new analysis
        if not analysis_available:

            if args.command == 'file':
                api_request_result = pyintelowl_client.send_file_analysis_request(
                    md5, args.analyzers_list, filename, binary,
                    args.force_privacy, args.disable_external_analyzers)
            elif args.command == 'observable':
                api_request_result = pyintelowl_client.send_observable_analysis_request(
                    md5, args.analyzers_list, args.value, args.force_privacy,
                    args.disable_external_analyzers)
            else:
                raise NotImplementedError()

            # both cases share the same logic for the management of the result retrieved from the API
            errors = api_request_result.get('errors', [])
            if errors:
                raise IntelOwlClientException(
                    "API send_analysis_request failed. Errors: {}"
                    "".format(errors))
            answer = api_request_result.get('answer', {})
            logger.info("md5 {} received response from intel_owl: {}".format(
                md5, answer))
            status = answer.get('status', '')
            if not status:
                raise IntelOwlClientException(
                    "API send_analysis_request gave result without status!?!? answer:{}"
                    "".format(answer))
            elif status != "accepted":
                raise IntelOwlClientException(
                    "API send_analysis_request gave unexpected result status:{}"
                    "".format(status))
            else:
                job_id_to_get = answer.get('job_id', '')
                analyzers_running = answer.get('analyzers_running', '')
                warnings = answer.get('warnings', [])
                if job_id_to_get:
                    logger.info(
                        "started job with id {} and status {} for md5 {} and analyzers {}. Warnings:{}"
                        "".format(job_id_to_get, status, md5,
                                  analyzers_running, warnings))
                else:
                    raise IntelOwlClientException(
                        "API send_analysis_request gave result without job_id!?!?"
                        "answer:{}".format(answer))

        # third step: at this moment we must have a job_id to check for results
        polling_max_tries = 60 * 20
        polling_interval = 1
        logger.info("started polling")
        for chance in range(polling_max_tries):
            time.sleep(polling_interval)
            api_request_result = pyintelowl_client.ask_analysis_result(
                job_id_to_get)
            errors = api_request_result.get('errors', [])
            if errors:
                raise IntelOwlClientException(
                    "API ask_analysis_result failed. Errors: {}"
                    "".format(errors))
            answer = api_request_result.get('answer', {})
            status = answer.get('status', '')
            if not status:
                raise IntelOwlClientException(
                    "API ask_analysis_result gave result without status!?!? job_id:{} answer:{}"
                    "".format(job_id_to_get, answer))
            elif status in ['invalid_id', 'not_available']:
                raise IntelOwlClientException(
                    "API send_analysis_request gave status {}".format(status))
            elif status == 'running':
                continue
            elif status == 'pending':
                logger.warning(
                    "API ask_analysis_result check job in status 'pending'. Maybe it is stuck"
                    "job_id:{} md5:{} analyzer_list:{}".format(
                        job_id_to_get, md5, args.analyzers_list))
            elif status in [
                    'reported_without_fails', 'reported_with_fails', 'failed'
            ]:
                logger.info("job_id {} Analysis finished. Status: {} "
                            "md5:{} analyzer_list:{}".format(
                                job_id_to_get, status, md5,
                                args.analyzers_list))
                results = answer.get('results', [])
                elapsed_time = answer.get('elapsed_time_in_seconds', [])
                break
        if not results:
            raise IntelOwlClientException(
                "reached polling timeout without results. Job_id {}"
                "".format(job_id_to_get))

    except IntelOwlClientException as e:
        logger.error("Error:{} md5:{}".format(e, md5))
    except requests.exceptions.HTTPError as e:
        logger.error(e)
    except Exception as e:
        logger.exception(e)

    logger.info("elapsed time: {}".format(elapsed_time))
    logger.info("results:")
    pprint.pprint(results)
Пример #4
0
class ApiTests(TestCase):
    def setUp(self):
        self.client = IntelOwl(secrets.get_secret("TEST_TOKEN"), False,
                               "http://nginx", True)

    def test_ask_analysis_availability(self):
        md5 = os.environ.get("TEST_MD5", "")
        analyzers_needed = ["Fortiguard", "CIRCLPassiveDNS"]
        api_request_result = self.client.ask_analysis_availability(
            md5, analyzers_needed)
        answer = api_request_result.get('answer', {})
        print(answer)
        errors = api_request_result.get('errors', [])
        self.assertFalse(errors)

    def test_send_corrupted_sample_pe(self):
        filename = "non_valid_pe.exe"
        test_file = "{}/test_files/{}".format(settings.PROJECT_LOCATION,
                                              filename)
        with open(test_file, "rb") as f:
            binary = f.read()
        md5 = hashlib.md5(binary).hexdigest()
        analyzers_requested = [
            "File_Info", "PE_Info", "Strings_Info_Classic", "Signature_Info"
        ]
        api_request_result = self.client.send_file_analysis_request(
            md5, analyzers_requested, filename, binary, False)
        answer = api_request_result.get('answer', {})
        print(answer)
        errors = api_request_result.get('errors', [])
        self.assertFalse(errors)

    def test_send_analysis_request_sample(self):
        filename = "file.exe"
        test_file = "{}/test_files/{}".format(settings.PROJECT_LOCATION,
                                              filename)
        with open(test_file, "rb") as f:
            binary = f.read()
        md5 = hashlib.md5(binary).hexdigest()
        analyzers_requested = [
            "Yara_Scan", "HybridAnalysis_Get_File", "Cuckoo_ScanClassic",
            "Intezer_Scan", "VirusTotal_v3_Get_File",
            "VirusTotal_v3_Scan_File", "File_Info", "PE_Info", "Doc_Info",
            "PDF_Info", "Strings_Info_Classic", "Strings_Info_ML"
        ]
        api_request_result = self.client.send_file_analysis_request(
            md5, analyzers_requested, filename, binary, False)
        answer = api_request_result.get('answer', {})
        print(answer)
        errors = api_request_result.get('errors', [])
        self.assertFalse(errors)

    def test_send_analysis_request_domain(self):
        analyzers_requested = [
            "Fortiguard", "CIRCLPassiveDNS", "GoogleSafebrowsing",
            "Robtex_Forward_PDNS_Query", "OTXQuery",
            "VirusTotal_v3_Get_Observable", "HybridAnalysis_Get_Observable"
        ]
        observable_name = os.environ.get("TEST_DOMAIN", "")
        md5 = hashlib.md5(observable_name.encode('utf-8')).hexdigest()
        api_request_result = self.client.send_observable_analysis_request(
            md5, analyzers_requested, observable_name, False)
        answer = api_request_result.get('answer', {})
        print(answer)
        errors = api_request_result.get('errors', [])
        self.assertFalse(errors)

    def test_send_analysis_request_ip(self):
        analyzers_requested = [
            "TorProject", "AbuseIPDB", "Shodan", "MaxMindGeoIP",
            "CIRCLPassiveSSL", "GreyNoiseAlpha", "GoogleSafebrowsing",
            "Robtex_IP_Query", "Robtex_Reverse_PDNS_Query", "TalosReputation",
            "OTXQuery", "VirusTotal_Get_v2_Observable",
            "HybridAnalysis_Get_Observable", "Hunter", "HoneyDB"
        ]
        observable_name = os.environ.get("TEST_IP", "")
        md5 = hashlib.md5(observable_name.encode('utf-8')).hexdigest()
        api_request_result = self.client.send_observable_analysis_request(
            md5, analyzers_requested, observable_name, False)
        answer = api_request_result.get('answer', {})
        print(answer)
        errors = api_request_result.get('errors', [])
        self.assertFalse(errors)

    def test_ask_analysis_result(self):
        # put your test job_id
        job_id = os.environ.get("TEST_JOB_ID", "")
        api_request_result = self.client.ask_analysis_result(job_id)
        answer = api_request_result.get('answer', {})
        print(answer)
        errors = api_request_result.get('errors', [])
        self.assertFalse(errors)
Пример #5
0
def _pyintelowl_logic(args, logger):
    md5 = None
    results = []
    elapsed_time = None
    get_configuration_only = False
    try:
        filename = None
        binary = None
        if args.command == 'file':
            if not os.path.exists(args.file):
                raise IntelOwlClientException("{} does not exists".format(args.file))
            with open(args.file, "rb") as f:
                binary = f.read()
                filename = os.path.basename(f.name)
            md5 = hashlib.md5(binary).hexdigest()
        elif args.command == 'observable':
            args.value = args.value.lower()
            md5 = hashlib.md5(args.value.encode('utf-8')).hexdigest()
        elif args.get_configuration:
            get_configuration_only = True
        else:
            raise IntelOwlClientException("you must specify the type of the analysis: [observable, file]")

        pyintelowl_client = IntelOwl(args.api_token_file, args.certificate, args.instance, args.debug)

        if get_configuration_only:
            api_request_result = pyintelowl_client.get_analyzer_configs()
            errors = api_request_result.get('errors', [])
            if errors:
                logger.error("API get_analyzer_configs failed. Errors: {}".format(errors))
            analyzers_config = api_request_result.get('answer', {})
            logger.info("extracted analyzer_configuration: {}".format(analyzers_config))
            pprint(analyzers_config)
            exit(0)

        analysis_available = False
        if not args.skip_check_analysis_availability:
            job_id_to_get = None
            # first step: ask analysis availability
            logger.info("about to request ask_analysis_availability for md5: {}, analyzers: {}"
                        "".format(md5, args.analyzers_list))

            api_request_result = \
                pyintelowl_client.ask_analysis_availability(md5, args.analyzers_list,
                                                            args.run_all_available_analyzers,
                                                            args.check_reported_analysis_too)
            errors = api_request_result.get('errors', [])
            if errors:
                raise IntelOwlClientException("API ask_analysis_availability failed. Errors: {}"
                                              "".format(errors))
            answer = api_request_result.get('answer', {})
            status = answer.get('status', '')
            if not status:
                raise IntelOwlClientException("API ask_analysis_availability gave result without status!?!?"
                                              "answer:{}".format(answer))
            if status != 'not_available':
                analysis_available = True
                job_id_to_get = answer.get('job_id', '')
                if job_id_to_get:
                    logger.info("found already existing job with id {} and status {} for md5 {} and analyzers {}"
                                "".format(job_id_to_get, status, md5, args.analyzers_list))
                else:
                    raise IntelOwlClientException(
                        "API ask_analysis_availability gave result without job_id!?!? answer:{}"
                        "".format(answer))

        # second step: in case there are no analysis available, start a new analysis
        if not analysis_available:

            if args.command == 'file':
                api_request_result = pyintelowl_client.send_file_analysis_request(md5, args.analyzers_list, filename,
                                                                                  binary, args.force_privacy,
                                                                                  args.disable_external_analyzers,
                                                                                  args.run_all_available_analyzers)
            elif args.command == 'observable':
                api_request_result = pyintelowl_client.send_observable_analysis_request(md5, args.analyzers_list,
                                                                                        args.value, args.force_privacy,
                                                                                        args.disable_external_analyzers,
                                                                                        args.run_all_available_analyzers)
            else:
                raise NotImplementedError()

            # both cases share the same logic for the management of the result retrieved from the API
            errors = api_request_result.get('errors', [])
            if errors:
                raise IntelOwlClientException("API send_analysis_request failed. Errors: {}"
                                              "".format(errors))
            answer = api_request_result.get('answer', {})
            logger.info("md5 {} received response from intel_owl: {}".format(md5, answer))
            status = answer.get('status', '')
            if not status:
                raise IntelOwlClientException(
                    "API send_analysis_request gave result without status!?!? answer:{}"
                    "".format(answer))
            if status != "accepted":
                raise IntelOwlClientException("API send_analysis_request gave unexpected result status:{}"
                                              "".format(status))
            job_id_to_get = answer.get('job_id', '')
            analyzers_running = answer.get('analyzers_running', '')
            warnings = answer.get('warnings', [])
            if job_id_to_get:
                logger.info("started job with id {} and status {} for md5 {} and analyzers {}. Warnings:{}"
                            "".format(job_id_to_get, status, md5, analyzers_running, warnings))
            else:
                raise IntelOwlClientException("API send_analysis_request gave result without job_id!?!?"
                                              "answer:{}".format(answer))

        # third step: at this moment we must have a job_id to check for results
        polling_max_tries = 60 * 20
        polling_interval = 1
        logger.info("started polling")
        for chance in range(polling_max_tries):
            time.sleep(polling_interval)
            api_request_result = pyintelowl_client.ask_analysis_result(job_id_to_get)
            errors = api_request_result.get('errors', [])
            if errors:
                raise IntelOwlClientException("API ask_analysis_result failed. Errors: {}"
                                              "".format(errors))
            answer = api_request_result.get('answer', {})
            status = answer.get('status', '')
            if not status:
                raise IntelOwlClientException(
                    "API ask_analysis_result gave result without status!?!? job_id:{} answer:{}"
                    "".format(job_id_to_get, answer))
            if status in ['invalid_id', 'not_available']:
                raise IntelOwlClientException("API send_analysis_request gave status {}".format(status))
            if status == 'running':
                continue
            if status == 'pending':
                logger.warning("API ask_analysis_result check job in status 'pending'. Maybe it is stuck"
                               "job_id:{} md5:{} analyzer_list:{}".format(job_id_to_get, md5, args.analyzers_list))
            elif status in ['reported_without_fails', 'reported_with_fails', 'failed']:
                logger.info("job_id {} Analysis finished. Status: {} "
                            "md5:{} analyzer_list:{}".format(job_id_to_get, status, md5, args.analyzers_list))
                results = answer.get('results', [])
                elapsed_time = answer.get('elapsed_time_in_seconds', [])
                break
        if not results:
            raise IntelOwlClientException("reached polling timeout without results. Job_id {}"
                                          "".format(job_id_to_get))

    except IntelOwlClientException as e:
        logger.error("Error:{} md5:{}".format(e, md5))
    except requests.exceptions.HTTPError as e:
        logger.exception(e)
    except IntelOwlInvalidAPITokenException as e:
        logger.exception(e)
        exit(-1)
    except Exception as e:
        logger.exception(e)
    
    logger.info("elapsed time: {}".format(elapsed_time))
    logger.info("results:")
    if args.show_json:
        pprint(results)
        sys.exit()
    
    checkers = Checkers(results, args.value)
    
    observable = get_observable_classification(args.value)
    if 'domain' in observable:
        checkers.check_domain()
    elif 'hash' in observable:
        checkers.check_hash()
    else:
        checkers.check_ip()