From 8e5783e65d7d40c0fee03a6e452f7c974911044c Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Thu, 15 Jan 2026 15:12:57 +0000 Subject: [PATCH 01/18] fixing os.path problem in Windows --- plugin/virustotal/vt_ida/plugin_loader.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/plugin/virustotal/vt_ida/plugin_loader.py b/plugin/virustotal/vt_ida/plugin_loader.py index 6a53495..4af4d69 100644 --- a/plugin/virustotal/vt_ida/plugin_loader.py +++ b/plugin/virustotal/vt_ida/plugin_loader.py @@ -22,6 +22,7 @@ import logging import os import requests +import pathlib import threading from virustotal import config from virustotal import vtgrep @@ -60,18 +61,25 @@ def calculate_hash(input_file): """Return hash if the file hash has been properly calculated.""" file_hash = None + + # Use pathlib for better cross-platform path handling (especially on Windows) + try: + path_obj = pathlib.Path(input_file) + except Exception: + logging.debug('[VT Plugin] Invalid path format: %s', input_file) + path_obj = None - if os.path.isfile(input_file): + if path_obj and path_obj.is_file(): hash_f = hashlib.sha256() logging.debug('[VT Plugin] Input file available.') - with open(input_file, 'rb') as file_r: - try: + try: + with path_obj.open('rb') as file_r: for file_buffer in iter(lambda: file_r.read(8192), b''): hash_f.update(file_buffer) - file_hash = hash_f.hexdigest() - logging.debug('[VT Plugin] Input file hash been calculated.') - except: - logging.debug('[VT Plugin] Can\'t load the input file.') + file_hash = hash_f.hexdigest() + logging.debug('[VT Plugin] Input file hash been calculated.') + except: + logging.debug('[VT Plugin] Can\'t load the input file.') else: logging.debug('[VT Plugin] Input file not available.') tmp_hash = idautils.GetInputFileMD5() From c31d6991d109e1b276011fdd36b638e8207a5b5f Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Thu, 15 Jan 2026 15:27:49 +0000 Subject: [PATCH 02/18] updated to v1.07 --- README.md | 2 +- VERSION | 2 +- ida-plugin.json | 2 +- plugin/virustotal/vt_ida/plugin_loader.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9376958..71c9ef6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # VirusTotal Plugin for IDA Pro -This is the official VirusTotal plugin for Hex-Rays IDA Pro, version **1.06**. It seamlessly integrates VirusTotal's powerful analysis capabilities directly into your reverse engineering workflow. +This is the official VirusTotal plugin for Hex-Rays IDA Pro, version **1.07**. It seamlessly integrates VirusTotal's powerful analysis capabilities directly into your reverse engineering workflow. The plugin offers two core functionalities: 1. **Code Similarity Search**: Perform advanced searches for code, bytes, and strings across VirusTotal's massive dataset directly from IDA's disassembly and strings views. diff --git a/VERSION b/VERSION index 3515b60..a2a169c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.06 \ No newline at end of file +1.07 \ No newline at end of file diff --git a/ida-plugin.json b/ida-plugin.json index 5fc51dc..c4fcecb 100644 --- a/ida-plugin.json +++ b/ida-plugin.json @@ -3,7 +3,7 @@ "plugin": { "name": "vt-ida-plugin", "entryPoint": "plugin/vt.py", - "version": "1.0.6", + "version": "1.0.7", "idaVersions": ">=8", "description": "Integrates VirusTotal's powerful analysis capabilities directly into your reverse engineering workflow.", "license": "Apache 2.0", diff --git a/plugin/virustotal/vt_ida/plugin_loader.py b/plugin/virustotal/vt_ida/plugin_loader.py index 4af4d69..a7952ea 100644 --- a/plugin/virustotal/vt_ida/plugin_loader.py +++ b/plugin/virustotal/vt_ida/plugin_loader.py @@ -38,7 +38,7 @@ except ImportError: import configparser -VT_IDA_PLUGIN_VERSION = '1.06' +VT_IDA_PLUGIN_VERSION = '1.07' widget_panel = VTPanel() if config.DEBUG: From 9f5cf74ee0ead3545cc64f0e75ebd5085d5d0551 Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Fri, 16 Jan 2026 15:43:37 +0000 Subject: [PATCH 03/18] minor fixes --- plugin/virustotal/vt_ida/plugin_loader.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/virustotal/vt_ida/plugin_loader.py b/plugin/virustotal/vt_ida/plugin_loader.py index a7952ea..6a51e1f 100644 --- a/plugin/virustotal/vt_ida/plugin_loader.py +++ b/plugin/virustotal/vt_ida/plugin_loader.py @@ -62,7 +62,6 @@ def calculate_hash(input_file): file_hash = None - # Use pathlib for better cross-platform path handling (especially on Windows) try: path_obj = pathlib.Path(input_file) except Exception: From f1b7ed25d82bb7293fc7de13ac6d29e40c824c5e Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Mon, 19 Jan 2026 11:24:37 +0000 Subject: [PATCH 04/18] ADding Gustavo to the list of owners --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index e10987a..484f11c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -2,5 +2,5 @@ # Each line is a file pattern followed by one or more owners. # These owners will be the default owners for everything in the repo. -* @gerardofn @winden-g @escipion +* @gerardofn @winden-g @escipion @guspascual From 1955fa62379a2fb51d6e649d03a0649a72cbc054 Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Mon, 19 Jan 2026 11:43:25 +0000 Subject: [PATCH 05/18] Updating license --- plugin/virustotal/ci_notebook.py | 2 +- plugin/virustotal/codeinsight.py | 2 +- plugin/virustotal/vt_ida/disassembler.py | 2 +- plugin/virustotal/vt_ida/plugin_loader.py | 2 +- plugin/virustotal/vt_ida/ui/qt5logo.py | 1 + plugin/virustotal/vt_ida/ui/qt5panel.py | 1 + plugin/virustotal/vt_ida/ui/qt6logo.py | 1 + plugin/virustotal/vt_ida/ui/qt6panel.py | 1 + plugin/virustotal/vt_ida/vtpanel.py | 2 +- plugin/virustotal/vt_ida/vtwidgets.py | 2 +- plugin/virustotal/vtgrep.py | 2 +- plugin/vt.py | 2 +- 12 files changed, 12 insertions(+), 8 deletions(-) diff --git a/plugin/virustotal/ci_notebook.py b/plugin/virustotal/ci_notebook.py index 62b29af..021ec54 100644 --- a/plugin/virustotal/ci_notebook.py +++ b/plugin/virustotal/ci_notebook.py @@ -1,4 +1,4 @@ -# Copyright 2025 Google Inc. All Rights Reserved. +# Copyright 2026 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/plugin/virustotal/codeinsight.py b/plugin/virustotal/codeinsight.py index 47f4f6b..02593cb 100644 --- a/plugin/virustotal/codeinsight.py +++ b/plugin/virustotal/codeinsight.py @@ -1,4 +1,4 @@ -# Copyright 2025 Google Inc. All Rights Reserved. +# Copyright 2026 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/plugin/virustotal/vt_ida/disassembler.py b/plugin/virustotal/vt_ida/disassembler.py index 72f785e..8d21985 100644 --- a/plugin/virustotal/vt_ida/disassembler.py +++ b/plugin/virustotal/vt_ida/disassembler.py @@ -1,4 +1,4 @@ -# Copyright 2020 Google Inc. All Rights Reserved. +# Copyright 2026 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/plugin/virustotal/vt_ida/plugin_loader.py b/plugin/virustotal/vt_ida/plugin_loader.py index 6a51e1f..4ff13b2 100644 --- a/plugin/virustotal/vt_ida/plugin_loader.py +++ b/plugin/virustotal/vt_ida/plugin_loader.py @@ -1,4 +1,4 @@ -# Copyright 2025 Google Inc. All Rights Reserved. +# Copyright 2026 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/plugin/virustotal/vt_ida/ui/qt5logo.py b/plugin/virustotal/vt_ida/ui/qt5logo.py index 4b5c501..d70213b 100644 --- a/plugin/virustotal/vt_ida/ui/qt5logo.py +++ b/plugin/virustotal/vt_ida/ui/qt5logo.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# Copyright 2026 Google LLC. All Rights Reserved. # Resource object code # diff --git a/plugin/virustotal/vt_ida/ui/qt5panel.py b/plugin/virustotal/vt_ida/ui/qt5panel.py index b32bdb0..b07f922 100644 --- a/plugin/virustotal/vt_ida/ui/qt5panel.py +++ b/plugin/virustotal/vt_ida/ui/qt5panel.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# Copyright 2026 Google LLC. All Rights Reserved. # Form implementation generated from reading ui file 'vtpanel.ui' # diff --git a/plugin/virustotal/vt_ida/ui/qt6logo.py b/plugin/virustotal/vt_ida/ui/qt6logo.py index 7d6798b..21ae417 100644 --- a/plugin/virustotal/vt_ida/ui/qt6logo.py +++ b/plugin/virustotal/vt_ida/ui/qt6logo.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# Copyright 2026 Google LLC. All Rights Reserved. # Resource object code # diff --git a/plugin/virustotal/vt_ida/ui/qt6panel.py b/plugin/virustotal/vt_ida/ui/qt6panel.py index 14725c3..986f976 100644 --- a/plugin/virustotal/vt_ida/ui/qt6panel.py +++ b/plugin/virustotal/vt_ida/ui/qt6panel.py @@ -1,3 +1,4 @@ +# Copyright 2026 Google LLC. All Rights Reserved. # Form implementation generated from reading ui file 'vtpanel.ui' # # Created by: PyQt6 UI code generator 6.9.1 diff --git a/plugin/virustotal/vt_ida/vtpanel.py b/plugin/virustotal/vt_ida/vtpanel.py index 4803e33..41d7c25 100644 --- a/plugin/virustotal/vt_ida/vtpanel.py +++ b/plugin/virustotal/vt_ida/vtpanel.py @@ -1,4 +1,4 @@ -# Copyright 2025 Google Inc. All Rights Reserved. +# Copyright 2026 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/plugin/virustotal/vt_ida/vtwidgets.py b/plugin/virustotal/vt_ida/vtwidgets.py index ebb24f9..da9490d 100644 --- a/plugin/virustotal/vt_ida/vtwidgets.py +++ b/plugin/virustotal/vt_ida/vtwidgets.py @@ -1,4 +1,4 @@ -# Copyright 2025 Google Inc. All Rights Reserved. +# Copyright 2026 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/plugin/virustotal/vtgrep.py b/plugin/virustotal/vtgrep.py index c53e6a8..4bdddd4 100644 --- a/plugin/virustotal/vtgrep.py +++ b/plugin/virustotal/vtgrep.py @@ -1,4 +1,4 @@ -# Copyright 2025 Google Inc. All Rights Reserved. +# Copyright 2026 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/plugin/vt.py b/plugin/vt.py index fd47982..ae8eceb 100644 --- a/plugin/vt.py +++ b/plugin/vt.py @@ -1,5 +1,5 @@ -# Copyright 2025 Google Inc. All Rights Reserved. +# Copyright 2026 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at From afbfbe77fb0e6a296480158d46e7cb6532f104ca Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Mon, 19 Jan 2026 12:54:29 +0000 Subject: [PATCH 06/18] fixing license years --- plugin/virustotal/ci_notebook.py | 2 +- plugin/virustotal/codeinsight.py | 2 +- plugin/virustotal/vt_ida/disassembler.py | 2 +- plugin/virustotal/vt_ida/plugin_loader.py | 2 +- plugin/virustotal/vt_ida/ui/qt5logo.py | 2 +- plugin/virustotal/vt_ida/ui/qt5panel.py | 2 +- plugin/virustotal/vt_ida/ui/qt6logo.py | 2 +- plugin/virustotal/vt_ida/ui/qt6panel.py | 2 +- plugin/virustotal/vt_ida/vtpanel.py | 2 +- plugin/virustotal/vt_ida/vtwidgets.py | 2 +- plugin/virustotal/vtgrep.py | 2 +- plugin/vt.py | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/plugin/virustotal/ci_notebook.py b/plugin/virustotal/ci_notebook.py index 021ec54..ce417c1 100644 --- a/plugin/virustotal/ci_notebook.py +++ b/plugin/virustotal/ci_notebook.py @@ -1,4 +1,4 @@ -# Copyright 2026 Google LLC. All Rights Reserved. +# Copyright 2025 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/plugin/virustotal/codeinsight.py b/plugin/virustotal/codeinsight.py index 02593cb..09dbf31 100644 --- a/plugin/virustotal/codeinsight.py +++ b/plugin/virustotal/codeinsight.py @@ -1,4 +1,4 @@ -# Copyright 2026 Google LLC. All Rights Reserved. +# Copyright 2025 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/plugin/virustotal/vt_ida/disassembler.py b/plugin/virustotal/vt_ida/disassembler.py index 8d21985..3bef7eb 100644 --- a/plugin/virustotal/vt_ida/disassembler.py +++ b/plugin/virustotal/vt_ida/disassembler.py @@ -1,4 +1,4 @@ -# Copyright 2026 Google LLC. All Rights Reserved. +# Copyright 2019 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/plugin/virustotal/vt_ida/plugin_loader.py b/plugin/virustotal/vt_ida/plugin_loader.py index 4ff13b2..627514e 100644 --- a/plugin/virustotal/vt_ida/plugin_loader.py +++ b/plugin/virustotal/vt_ida/plugin_loader.py @@ -1,4 +1,4 @@ -# Copyright 2026 Google LLC. All Rights Reserved. +# Copyright 2019 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/plugin/virustotal/vt_ida/ui/qt5logo.py b/plugin/virustotal/vt_ida/ui/qt5logo.py index d70213b..4332746 100644 --- a/plugin/virustotal/vt_ida/ui/qt5logo.py +++ b/plugin/virustotal/vt_ida/ui/qt5logo.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2026 Google LLC. All Rights Reserved. +# Copyright 2025 Google LLC. All Rights Reserved. # Resource object code # diff --git a/plugin/virustotal/vt_ida/ui/qt5panel.py b/plugin/virustotal/vt_ida/ui/qt5panel.py index b07f922..688b8f8 100644 --- a/plugin/virustotal/vt_ida/ui/qt5panel.py +++ b/plugin/virustotal/vt_ida/ui/qt5panel.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2026 Google LLC. All Rights Reserved. +# Copyright 2025 Google LLC. All Rights Reserved. # Form implementation generated from reading ui file 'vtpanel.ui' # diff --git a/plugin/virustotal/vt_ida/ui/qt6logo.py b/plugin/virustotal/vt_ida/ui/qt6logo.py index 21ae417..b36936c 100644 --- a/plugin/virustotal/vt_ida/ui/qt6logo.py +++ b/plugin/virustotal/vt_ida/ui/qt6logo.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2026 Google LLC. All Rights Reserved. +# Copyright 2025 Google LLC. All Rights Reserved. # Resource object code # diff --git a/plugin/virustotal/vt_ida/ui/qt6panel.py b/plugin/virustotal/vt_ida/ui/qt6panel.py index 986f976..ccb6cf7 100644 --- a/plugin/virustotal/vt_ida/ui/qt6panel.py +++ b/plugin/virustotal/vt_ida/ui/qt6panel.py @@ -1,4 +1,4 @@ -# Copyright 2026 Google LLC. All Rights Reserved. +# Copyright 2025 Google LLC. All Rights Reserved. # Form implementation generated from reading ui file 'vtpanel.ui' # # Created by: PyQt6 UI code generator 6.9.1 diff --git a/plugin/virustotal/vt_ida/vtpanel.py b/plugin/virustotal/vt_ida/vtpanel.py index 41d7c25..d34c2b4 100644 --- a/plugin/virustotal/vt_ida/vtpanel.py +++ b/plugin/virustotal/vt_ida/vtpanel.py @@ -1,4 +1,4 @@ -# Copyright 2026 Google LLC. All Rights Reserved. +# Copyright 2025 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/plugin/virustotal/vt_ida/vtwidgets.py b/plugin/virustotal/vt_ida/vtwidgets.py index da9490d..b9ddd92 100644 --- a/plugin/virustotal/vt_ida/vtwidgets.py +++ b/plugin/virustotal/vt_ida/vtwidgets.py @@ -1,4 +1,4 @@ -# Copyright 2026 Google LLC. All Rights Reserved. +# Copyright 2025 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/plugin/virustotal/vtgrep.py b/plugin/virustotal/vtgrep.py index 4bdddd4..1d2fcf9 100644 --- a/plugin/virustotal/vtgrep.py +++ b/plugin/virustotal/vtgrep.py @@ -1,4 +1,4 @@ -# Copyright 2026 Google LLC. All Rights Reserved. +# Copyright 2019 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/plugin/vt.py b/plugin/vt.py index ae8eceb..d590fa2 100644 --- a/plugin/vt.py +++ b/plugin/vt.py @@ -1,5 +1,5 @@ -# Copyright 2026 Google LLC. All Rights Reserved. +# Copyright 2019 Google LLC. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at From 6e46b66211251b309887d43500bb57b38a186239 Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Mon, 19 Jan 2026 12:57:49 +0000 Subject: [PATCH 07/18] fixing CODEOWNERS file --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 484f11c..1c24bae 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -2,5 +2,5 @@ # Each line is a file pattern followed by one or more owners. # These owners will be the default owners for everything in the repo. -* @gerardofn @winden-g @escipion @guspascual +* @gerardofn @escipion @guspascual From 894a1b9ea13fef3282bf86f1dd1d8e97d198827d Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Mon, 19 Jan 2026 16:42:44 +0000 Subject: [PATCH 08/18] Improving error detection --- plugin/virustotal/codeinsight.py | 7 ++++--- plugin/virustotal/vt_ida/plugin_loader.py | 18 ++++++++++-------- plugin/virustotal/vt_ida/vtpanel.py | 11 ++++++----- plugin/virustotal/vtgrep.py | 2 +- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/plugin/virustotal/codeinsight.py b/plugin/virustotal/codeinsight.py index 09dbf31..13fbd3b 100644 --- a/plugin/virustotal/codeinsight.py +++ b/plugin/virustotal/codeinsight.py @@ -14,6 +14,7 @@ __author__ = 'gerardofn@virustotal.com' import logging +import binascii import requests from virustotal import config from virustotal.vt_ida.disassembler import Disassembler @@ -133,7 +134,7 @@ def _process_output(self, response): try: decoded_str = base64.urlsafe_b64decode(answer) - except: + except (binascii.Error, ValueError): logging.debug('[VT Plugin] ERROR decoding Code Insight response: %s', response) return None @@ -195,7 +196,7 @@ def run(self): try: response = requests.post(f'{API_URL}/{endpoint}', json = {'data': payload}, headers=headers_apiv3) - except: + except requests.RequestException: logging.debug('[VT Plugin] ERROR: unable to connect to Code Insight') self._error_msg = 'ERROR: unable to connect to Code Insight' return @@ -376,7 +377,7 @@ def askCI(self, *args, **kwargs): if json_str: try: return_msg = json.loads(json_str) - except: + except json.JSONDecodeError: logging.debug('[CodeInsight] Error processing the returned json file.') return return_msg else: diff --git a/plugin/virustotal/vt_ida/plugin_loader.py b/plugin/virustotal/vt_ida/plugin_loader.py index 627514e..2ee148a 100644 --- a/plugin/virustotal/vt_ida/plugin_loader.py +++ b/plugin/virustotal/vt_ida/plugin_loader.py @@ -64,7 +64,7 @@ def calculate_hash(input_file): try: path_obj = pathlib.Path(input_file) - except Exception: + except TypeError: logging.debug('[VT Plugin] Invalid path format: %s', input_file) path_obj = None @@ -77,7 +77,7 @@ def calculate_hash(input_file): hash_f.update(file_buffer) file_hash = hash_f.hexdigest() logging.debug('[VT Plugin] Input file hash been calculated.') - except: + except OSError: logging.debug('[VT Plugin] Can\'t load the input file.') else: logging.debug('[VT Plugin] Input file not available.') @@ -469,7 +469,7 @@ def check_file_missing_in_VT(self): logging.debug('[VT Plugin] Checking hash: %s', self.file_hash) try: response = requests.get(url, headers=headers) - except: + except requests.RequestException: logging.error('[VT Plugin] Unable to connect to VirusTotal.com') return False @@ -503,8 +503,9 @@ def upload_file_to_VT(self): try: response = requests.post(url, files=files, headers=headers) - except: + except requests.RequestException: logging.error('[VT Plugin] Unable to connect to VirusTotal.com') + return if response.ok: logging.debug('[VT Plugin] Uploaded successfully.') @@ -555,7 +556,7 @@ def read_config(self): else: self.auto_upload = False return True - except: + except configparser.Error: logging.error('[VT Plugin] Error reading the user config file.') return False @@ -571,7 +572,7 @@ def write_config(self): parser.set('General', 'auto_upload', str(self.auto_upload)) parser.write(config_file) config_file.close() - except: + except (OSError, configparser.Error): logging.error('[VT Plugin] Error while creating the user config file.') return False return True @@ -608,7 +609,7 @@ def check_version(self): try: response = requests.get(url, headers=headers) - except: + except requests.RequestException: logging.error('[VT Plugin] Unable to check for updates.') return False @@ -763,8 +764,9 @@ def init(self): VTGrepBytes.register(self, 'Search for bytes') VTGrepStrings.register(self, 'Search for string') - except: + except Exception: logging.error('[VT Plugin] Unable to register popups actions.') + return else: logging.info('[VT Plugin] Plugin disabled, restart IDA to proceed. ') ida_kernwin.warning('Plugin disabled, restart IDA to proceed.') diff --git a/plugin/virustotal/vt_ida/vtpanel.py b/plugin/virustotal/vt_ida/vtpanel.py index d34c2b4..8555226 100644 --- a/plugin/virustotal/vt_ida/vtpanel.py +++ b/plugin/virustotal/vt_ida/vtpanel.py @@ -118,8 +118,9 @@ def _load(self): logging.debug('[VT Plugin] Loading CodeInsight Notebook file: %s', filename) with open(filename, 'r', encoding='utf-8') as f: imported_json = json.load(f) - except: - logging.error('[VT Plugin] ERROR importing file: %s', filename) + except (OSError, json.JSONDecodeError): + logging.error('[VT Plugin] ERROR importing file: %s', filename) + return ci_notebook.import_data(imported_json) self._read_notebook() @@ -145,7 +146,7 @@ def _export(self): logging.debug('[VT Plugin] Exporting CodeInsight Notebook to file: %s', filename) with open(filename, 'w', encoding='utf-8') as f: json.dump(ci_notebook.show_pages(), f) - except: + except OSError: logging.error('[VT Plugin] ERROR saving file: %s', filename) @@ -199,7 +200,7 @@ def _askCI_Disassembled(self, code_src): try: self.summary = self.ci_report['summary'] self.description = self.ci_report['description'] - except: + except (KeyError, TypeError): logging.error('[VT Plugin] Invalid answer received from Code Insight') return False @@ -221,7 +222,7 @@ def _askCI_Decompiled(self, code_src): try: self.summary = self.ci_report['summary'] self.description = self.ci_report['description'] - except: + except (KeyError, TypeError): logging.error('[VT Plugin] Invalid answer received from Code Insight') return False diff --git a/plugin/virustotal/vtgrep.py b/plugin/virustotal/vtgrep.py index 1d2fcf9..021e2a7 100644 --- a/plugin/virustotal/vtgrep.py +++ b/plugin/virustotal/vtgrep.py @@ -347,6 +347,6 @@ def search(self, wildcards=False, strict=False): try: webbrowser.open_new(url) - except: + except webbrowser.Error: logging.error('[VTGREP] Error while opening the web browser.') VTWidgets.show_warning('Error while opening the web browser.') From c21bb4120b8b308b96f31ce72fba3c7333883d3d Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Tue, 20 Jan 2026 13:15:43 +0000 Subject: [PATCH 09/18] improved error handling --- plugin/virustotal/ci_notebook.py | 6 +++++- plugin/virustotal/codeinsight.py | 7 ++++++- plugin/virustotal/vt_ida/vtpanel.py | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/plugin/virustotal/ci_notebook.py b/plugin/virustotal/ci_notebook.py index ce417c1..c901d8f 100644 --- a/plugin/virustotal/ci_notebook.py +++ b/plugin/virustotal/ci_notebook.py @@ -90,7 +90,11 @@ def encode_response(summary, description): "summary": summary, "description": description } - response_str = json.dumps(response) + try: + response_str = json.dumps(response) + except TypeError: + logging.error('[VT Plugin] ERROR encoding CI response (not serializable).') + response_str = "{}" encoded_response = base64.b64encode(response_str.encode('utf-8')) return encoded_response.decode('ascii') diff --git a/plugin/virustotal/codeinsight.py b/plugin/virustotal/codeinsight.py index 13fbd3b..8d90376 100644 --- a/plugin/virustotal/codeinsight.py +++ b/plugin/virustotal/codeinsight.py @@ -379,6 +379,7 @@ def askCI(self, *args, **kwargs): return_msg = json.loads(json_str) except json.JSONDecodeError: logging.debug('[CodeInsight] Error processing the returned json file.') + return_msg = None return return_msg else: self.error_msg = ci.get_error_msg() @@ -464,7 +465,11 @@ def askCI(self, *args, **kwargs): self.encoded_src = ci.get_encoded_src() if json_str: - return json.loads(json_str) + try: + return json.loads(json_str) + except json.JSONDecodeError: + logging.debug('[CodeInsight] Error processing the returned json file.') + return None else: self.error_msg = ci.get_error_msg() diff --git a/plugin/virustotal/vt_ida/vtpanel.py b/plugin/virustotal/vt_ida/vtpanel.py index 8555226..9a129b7 100644 --- a/plugin/virustotal/vt_ida/vtpanel.py +++ b/plugin/virustotal/vt_ida/vtpanel.py @@ -146,7 +146,7 @@ def _export(self): logging.debug('[VT Plugin] Exporting CodeInsight Notebook to file: %s', filename) with open(filename, 'w', encoding='utf-8') as f: json.dump(ci_notebook.show_pages(), f) - except OSError: + except (OSError, TypeError): logging.error('[VT Plugin] ERROR saving file: %s', filename) From 1e182bbe607a2063e7edcada90da7dfa3cd4e0d2 Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Tue, 20 Jan 2026 13:18:04 +0000 Subject: [PATCH 10/18] updated version number in the changelog --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 71c9ef6..2d78f3f 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,7 @@ While other architectures may work, they have not been officially tested. Raw by Check IDA Pro's output window for any message that may need your attention. ## Changelog +- v1.07 : Improved error handling - v1.06 : Updated plugin metadata to support HCLI Plugin Manager ecosystem - v1.05 : Fixes crash when Code Insight returns an invalid response - v1.04 : Fixes issue that left IDA hanging while a query was being performed. From ede48ed826bfb967b88abfea035795bc4c01818d Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Thu, 22 Jan 2026 11:19:02 +0000 Subject: [PATCH 11/18] improved exception handling --- README.md | 2 +- plugin/virustotal/vt_ida/plugin_loader.py | 51 +++++++++++++---------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 2d78f3f..cb175d8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # VirusTotal Plugin for IDA Pro -This is the official VirusTotal plugin for Hex-Rays IDA Pro, version **1.07**. It seamlessly integrates VirusTotal's powerful analysis capabilities directly into your reverse engineering workflow. +This is the official VirusTotal plugin for Hex-Rays IDA Pro. It seamlessly integrates VirusTotal's powerful analysis capabilities directly into your reverse engineering workflow. The plugin offers two core functionalities: 1. **Code Similarity Search**: Perform advanced searches for code, bytes, and strings across VirusTotal's massive dataset directly from IDA's disassembly and strings views. diff --git a/plugin/virustotal/vt_ida/plugin_loader.py b/plugin/virustotal/vt_ida/plugin_loader.py index 2ee148a..5d7ef88 100644 --- a/plugin/virustotal/vt_ida/plugin_loader.py +++ b/plugin/virustotal/vt_ida/plugin_loader.py @@ -684,6 +684,13 @@ class VTplugin(idaapi.plugin_t): vtpanel = None vtsetup = None + def _safe_register_action(self, action_cls, label): + """Helper to safely register an action, logging any failures without crashing.""" + try: + action_cls.register(self, label) + except Exception: + logging.exception('[VT Plugin] Failed to register action: %s', label) + def init(self): """Set up menu hooks and implements search methods.""" @@ -724,16 +731,18 @@ def init(self): arch_info = idaapi.get_inf_structure() proc_name = get_procname(arch_info) - try: - logging.debug('[VT Plugin] Processor detected by IDA: %s', proc_name) - if (proc_name in self.SEARCH_STRICT_SUPPORTED) | (proc_name in self.SEARCH_CODE_SUPPORTED): - VTGrepWildcards.register(self, 'Search for similar code') - VTGrepWildCardsFunction.register(self, 'Search for similar functions') - if len(config.API_KEY) > 0: - CodeInsightASM.register(self, 'Ask Code Insight') - CodeInsightDecompiled.register(self, 'Ask Code Insight') - - ### Register menu entry + logging.debug('[VT Plugin] Processor detected by IDA: %s', proc_name) + + if (proc_name in self.SEARCH_STRICT_SUPPORTED) | (proc_name in self.SEARCH_CODE_SUPPORTED): + self._safe_register_action(VTGrepWildcards, 'Search for similar code') + self._safe_register_action(VTGrepWildCardsFunction, 'Search for similar functions') + + if len(config.API_KEY) > 0: + self._safe_register_action(CodeInsightASM, 'Ask Code Insight') + self._safe_register_action(CodeInsightDecompiled, 'Ask Code Insight') + + ### Register menu entry + try: current_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '.')) file_icon = os.path.join(current_path, 'ui', @@ -754,19 +763,19 @@ def init(self): 'View/Open subviews/', 'my:vtpanel', idaapi.SETMENU_APP) + except Exception: + logging.exception('[VT Plugin] Failed to register VirusTotal menu icon/action.') - if proc_name in self.SEARCH_STRICT_SUPPORTED: - VTGrepWildCardsStrict.register(self, 'Search for similar code (strict)') + if proc_name in self.SEARCH_STRICT_SUPPORTED: + self._safe_register_action(VTGrepWildCardsStrict, 'Search for similar code (strict)') + + else: + logging.info('\n - Processor detected: %s', get_procname(arch_info)) + logging.info(' - Searching for similar code is not available.') + + self._safe_register_action(VTGrepBytes, 'Search for bytes') + self._safe_register_action(VTGrepStrings, 'Search for string') - else: - logging.info('\n - Processor detected: %s', get_procname(arch_info)) - logging.info(' - Searching for similar code is not available.') - - VTGrepBytes.register(self, 'Search for bytes') - VTGrepStrings.register(self, 'Search for string') - except Exception: - logging.error('[VT Plugin] Unable to register popups actions.') - return else: logging.info('[VT Plugin] Plugin disabled, restart IDA to proceed. ') ida_kernwin.warning('Plugin disabled, restart IDA to proceed.') From 808b04004354cc8de9bf4b701404f98800786443 Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Thu, 22 Jan 2026 11:28:18 +0000 Subject: [PATCH 12/18] handling register exception handling --- plugin/virustotal/vt_ida/plugin_loader.py | 48 +++++++++++++---------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/plugin/virustotal/vt_ida/plugin_loader.py b/plugin/virustotal/vt_ida/plugin_loader.py index 5d7ef88..d4d2079 100644 --- a/plugin/virustotal/vt_ida/plugin_loader.py +++ b/plugin/virustotal/vt_ida/plugin_loader.py @@ -742,29 +742,35 @@ def init(self): self._safe_register_action(CodeInsightDecompiled, 'Ask Code Insight') ### Register menu entry + vticon_data = None + current_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '.')) + file_icon = os.path.join(current_path, + 'ui', + 'resources', + 'vt_icon.png') try: - current_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '.')) - file_icon = os.path.join(current_path, - 'ui', - 'resources', - 'vt_icon.png') vticon_data = open(file_icon, 'rb').read() - vtmenu = idaapi.load_custom_icon(data=vticon_data) - action_desc = idaapi.action_desc_t( - 'my:vtpanel', - 'VirusTotal', - MenuVTPanel(), - '', - 'Show VirusTotal panel with information about the current file', - vtmenu) - - idaapi.register_action(action_desc) - idaapi.attach_action_to_menu( - 'View/Open subviews/', - 'my:vtpanel', - idaapi.SETMENU_APP) - except Exception: - logging.exception('[VT Plugin] Failed to register VirusTotal menu icon/action.') + except OSError: + logging.error('[VT Plugin] Failed to load icon file: %s', file_icon) + + if vticon_data: + try: + vtmenu = idaapi.load_custom_icon(data=vticon_data) + action_desc = idaapi.action_desc_t( + 'my:vtpanel', + 'VirusTotal', + MenuVTPanel(), + '', + 'Show VirusTotal panel with information about the current file', + vtmenu) + + idaapi.register_action(action_desc) + idaapi.attach_action_to_menu( + 'View/Open subviews/', + 'my:vtpanel', + idaapi.SETMENU_APP) + except Exception: + logging.exception('[VT Plugin] Failed to register VirusTotal menu icon/action.') if proc_name in self.SEARCH_STRICT_SUPPORTED: self._safe_register_action(VTGrepWildCardsStrict, 'Search for similar code (strict)') From 0facae5b4657db9143980281546180782489afa0 Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Thu, 22 Jan 2026 11:34:39 +0000 Subject: [PATCH 13/18] fixed error detecting the cpu architecture --- plugin/virustotal/vt_ida/plugin_loader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/virustotal/vt_ida/plugin_loader.py b/plugin/virustotal/vt_ida/plugin_loader.py index d4d2079..8ed8d41 100644 --- a/plugin/virustotal/vt_ida/plugin_loader.py +++ b/plugin/virustotal/vt_ida/plugin_loader.py @@ -776,7 +776,7 @@ def init(self): self._safe_register_action(VTGrepWildCardsStrict, 'Search for similar code (strict)') else: - logging.info('\n - Processor detected: %s', get_procname(arch_info)) + logging.info('\n - Processor detected: %s', proc_name) logging.info(' - Searching for similar code is not available.') self._safe_register_action(VTGrepBytes, 'Search for bytes') From 934d3c81b361d697483c11e8cfe429e8358e2bd9 Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Thu, 22 Jan 2026 11:41:12 +0000 Subject: [PATCH 14/18] allow to use CodeInsight with other CPU architectures --- plugin/virustotal/vt_ida/plugin_loader.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/plugin/virustotal/vt_ida/plugin_loader.py b/plugin/virustotal/vt_ida/plugin_loader.py index 8ed8d41..e9fd6e2 100644 --- a/plugin/virustotal/vt_ida/plugin_loader.py +++ b/plugin/virustotal/vt_ida/plugin_loader.py @@ -732,16 +732,12 @@ def init(self): proc_name = get_procname(arch_info) logging.debug('[VT Plugin] Processor detected by IDA: %s', proc_name) - - if (proc_name in self.SEARCH_STRICT_SUPPORTED) | (proc_name in self.SEARCH_CODE_SUPPORTED): - self._safe_register_action(VTGrepWildcards, 'Search for similar code') - self._safe_register_action(VTGrepWildCardsFunction, 'Search for similar functions') - - if len(config.API_KEY) > 0: - self._safe_register_action(CodeInsightASM, 'Ask Code Insight') - self._safe_register_action(CodeInsightDecompiled, 'Ask Code Insight') - ### Register menu entry + if len(config.API_KEY) > 0: + self._safe_register_action(CodeInsightASM, 'Ask Code Insight') + self._safe_register_action(CodeInsightDecompiled, 'Ask Code Insight') + + ### Register VirusTotal menu entry vticon_data = None current_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '.')) file_icon = os.path.join(current_path, @@ -772,6 +768,10 @@ def init(self): except Exception: logging.exception('[VT Plugin] Failed to register VirusTotal menu icon/action.') + if (proc_name in self.SEARCH_STRICT_SUPPORTED) | (proc_name in self.SEARCH_CODE_SUPPORTED): + self._safe_register_action(VTGrepWildcards, 'Search for similar code') + self._safe_register_action(VTGrepWildCardsFunction, 'Search for similar functions') + if proc_name in self.SEARCH_STRICT_SUPPORTED: self._safe_register_action(VTGrepWildCardsStrict, 'Search for similar code (strict)') From 9a4170511dc194bf9f3929a9d63df264eeb99806 Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Thu, 22 Jan 2026 11:49:47 +0000 Subject: [PATCH 15/18] minor fixes --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index cb175d8..329fabf 100644 --- a/README.md +++ b/README.md @@ -116,12 +116,12 @@ While other architectures may work, they have not been officially tested. Raw by Check IDA Pro's output window for any message that may need your attention. ## Changelog -- v1.07 : Improved error handling -- v1.06 : Updated plugin metadata to support HCLI Plugin Manager ecosystem -- v1.05 : Fixes crash when Code Insight returns an invalid response +- v1.07 : Improved error handling, allow to use CodeInsight with other CPU architectures identified by IDA Pro. +- v1.06 : Updated plugin metadata to support HCLI Plugin Manager ecosystem. +- v1.05 : Fixes crash when Code Insight returns an invalid response. - v1.04 : Fixes issue that left IDA hanging while a query was being performed. -- v1.03 : BUG fixed (wrongly showing an invalid api key msg) +- v1.03 : BUG fixed (wrongly showing an invalid api key msg). - v1.02 : Added support for IDA Pro 9.2 -- v1.00 : Added Code Insight panel +- v1.00 : Added Code Insight panel. - v0.11 : Added support for IDA Pro 8.x -- v0.10 : Initial release \ No newline at end of file +- v0.10 : Initial release. \ No newline at end of file From fdbec72db49fdba83b07459da71f3d16e527a75a Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Thu, 22 Jan 2026 11:53:22 +0000 Subject: [PATCH 16/18] minor fixes --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 329fabf..5129167 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ While other architectures may work, they have not been officially tested. Raw by Check IDA Pro's output window for any message that may need your attention. ## Changelog -- v1.07 : Improved error handling, allow to use CodeInsight with other CPU architectures identified by IDA Pro. +- v1.07 : Improved error handling, now CodeInsight works with other CPU architectures identified by IDA Pro. - v1.06 : Updated plugin metadata to support HCLI Plugin Manager ecosystem. - v1.05 : Fixes crash when Code Insight returns an invalid response. - v1.04 : Fixes issue that left IDA hanging while a query was being performed. From 7938a30ceb2c1425f45634af35e9e36c23c04067 Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Thu, 22 Jan 2026 15:01:17 +0000 Subject: [PATCH 17/18] fixing exception handling --- plugin/virustotal/codeinsight.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/plugin/virustotal/codeinsight.py b/plugin/virustotal/codeinsight.py index 8d90376..468de91 100644 --- a/plugin/virustotal/codeinsight.py +++ b/plugin/virustotal/codeinsight.py @@ -376,11 +376,9 @@ def askCI(self, *args, **kwargs): if json_str: try: - return_msg = json.loads(json_str) + return json.loads(json_str) except json.JSONDecodeError: - logging.debug('[CodeInsight] Error processing the returned json file.') - return_msg = None - return return_msg + logging.debug('[CodeInsight] Error processing the returned json file.') else: self.error_msg = ci.get_error_msg() @@ -469,7 +467,6 @@ def askCI(self, *args, **kwargs): return json.loads(json_str) except json.JSONDecodeError: logging.debug('[CodeInsight] Error processing the returned json file.') - return None else: self.error_msg = ci.get_error_msg() From d888e0e9a214e274a8b67a5128746fed9cc7bb4c Mon Sep 17 00:00:00 2001 From: "Gerardo Fdez." <49400257+gerardofn@users.noreply.github.com> Date: Thu, 22 Jan 2026 15:14:20 +0000 Subject: [PATCH 18/18] minor fixes --- plugin/virustotal/vt_ida/plugin_loader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/virustotal/vt_ida/plugin_loader.py b/plugin/virustotal/vt_ida/plugin_loader.py index e9fd6e2..65cde13 100644 --- a/plugin/virustotal/vt_ida/plugin_loader.py +++ b/plugin/virustotal/vt_ida/plugin_loader.py @@ -776,7 +776,7 @@ def init(self): self._safe_register_action(VTGrepWildCardsStrict, 'Search for similar code (strict)') else: - logging.info('\n - Processor detected: %s', proc_name) + logging.info(' - Processor detected: %s', proc_name) logging.info(' - Searching for similar code is not available.') self._safe_register_action(VTGrepBytes, 'Search for bytes')