Commits

Daniel Plohmann committed 5487b9f

Implemented plugin-mode and added a signature for a quick and dirty PRNG

Comments (0)

Files changed (4)

 ########################################################################
 
 import os
+import sys
 import time
 
+import idc
 import idaapi
 from idaapi import PluginForm, plugin_t
 from PySide import QtGui
 from PySide.QtGui import QIcon
 
+import idascope.config as config
 from idascope.core.structures.IDAscopeConfiguration import IDAscopeConfiguration
 from idascope.core.SemanticIdentifier import SemanticIdentifier
 from idascope.core.DocumentationHelper import DocumentationHelper
 
     def __init__(self):
         super(IDAscopeForm, self).__init__()
-        banner = "#############################################\n" \
-               + "  ___ ____    _                             \n" \
-               + " |_ _|  _ \  / \   ___  ___ ___  _ __   ___ \n" \
-               + "  | || | | |/ _ \ / __|/ __/ _ \\| '_ \\ / _ \\\n" \
-               + "  | || |_| / ___ \\\\__ \\ (_| (_) | |_) |  __/\n" \
-               + " |___|____/_/   \\_\\___/\\___\\___/| .__/ \\___|\n" \
-               + "                                |_|         \n" \
-               + "#############################################\n" \
-               + " by Daniel Plohmann and Alexander Hanel      \n" \
-               + "#############################################\n"
-        print banner
-        print ("[+] Loading simpliFiRE.IDAscope")
         global HOTKEYS
         HOTKEYS = []
         self.idascope_widgets = []
-        self.root_file_path = \
-                os.path.realpath(__file__)[:os.path.realpath(__file__).rfind(os.sep) + 1]
-        self.config = IDAscopeConfiguration(self.root_file_path + os.sep + "config.json")
+        self.ensureRootPathSanity(config.configuration)
+        self.config = IDAscopeConfiguration(config.configuration)
         self.icon = QIcon(self.config.icon_file_path + "idascope.png")
 
+    def ensureRootPathSanity(self, configuration):
+        try:
+            root_dir = configuration["paths"]["idascope_root_dir"]
+            if not os.path.exists(root_dir) or not "IDAscope.py" in os.listdir(root_dir):
+                print "[!] IDAscope.py is not present in root directory specified in \"config.py\", " \
+                     + "trying to resolve path..."
+                resolved_pathname = os.path.dirname(sys.argv[0])
+                if "IDAscope.py" in os.listdir(resolved_pathname):
+                    print "[+] IDAscope root directory successfully resolved."
+                    configuration["paths"]["idascope_root_dir"] = resolved_pathname
+                else:
+                    print "[-] IDAscope.py is not resolvable!"
+                    raise Exception()
+        except:
+            print "[!] IDAscope config is broken. Could not locate root directory. " \
+                 + "Try setting the field \"idascope_root_dir\" to the path where \"IDAscope.py\" is located."
+            sys.exit(-1)
+
     def setup_shared_modules(self):
         """
         Setup shared IDAscope modules.
         """
         When creating the form, setup the shared modules and widgets
         """
+        self.print_banner()
         self.parent = self.FormToPySideWidget(form)
         self.parent.setWindowIcon(self.icon)
         self.setup_shared_modules()
         self.setup_widgets()
 
+    def print_banner(self):
+        banner = "#############################################\n" \
+               + "  ___ ____    _                             \n" \
+               + " |_ _|  _ \  / \   ___  ___ ___  _ __   ___ \n" \
+               + "  | || | | |/ _ \ / __|/ __/ _ \\| '_ \\ / _ \\\n" \
+               + "  | || |_| / ___ \\\\__ \\ (_| (_) | |_) |  __/\n" \
+               + " |___|____/_/   \\_\\___/\\___\\___/| .__/ \\___|\n" \
+               + "                                |_|         \n" \
+               + "#############################################\n" \
+               + " by Daniel Plohmann and Alexander Hanel      \n" \
+               + "#############################################\n"
+        print banner
+        print ("[+] Loading simpliFiRE.IDAscope")
+
     def OnClose(self, form):
         """
         Perform cleanup.
         del IDASCOPE
 
     def Show(self):
-        return PluginForm.Show(self,
-            NAME,
-            options=(PluginForm.FORM_CLOSE_LATER | PluginForm.FORM_RESTORE | PluginForm.FORM_SAVE))
+        if idc.GetInputMD5() == None:
+            return
+        else:
+            return PluginForm.Show(self,
+                NAME,
+                options=(PluginForm.FORM_CLOSE_LATER | PluginForm.FORM_RESTORE | PluginForm.FORM_SAVE))
 
 ################################################################################
 # functionality offered to IDAscope's widgets
 ################################################################################
 
 
+def PLUGIN_ENTRY():
+    return IDAscopePlugin()
+
+
 class IDAscopePlugin(plugin_t):
     """
     Plugin version of IDAscope. Use this to deploy IDAscope via IDA plugins folder.
     """
     flags = idaapi.PLUGIN_UNL
     comment = NAME
-    help = "A plugin to help to identify the relevant parts"
+    help = "IDAscope - Different tools to ease reverse engineering."
     wanted_name = "IDAscope"
     wanted_hotkey = "Ctrl-F4"
 
     def run(self, arg=0):
         # Create form
         f = IDAscopeForm()
-
         # Show the form
-        exit_code = f.Show()
-        if exit_code == 0:
-            f.Free()
-            return
-
-        f.Free()
+        f.Show()
         return
 
     def term(self):
         pass
 
-
-def PLUGIN_ENTRY():
-    return IDAscopePlugin()
-
 ################################################################################
 # Usage as script
 ################################################################################
 
 def main():
     global IDASCOPE
-
     try:
         IDASCOPE
         IDASCOPE.OnClose(IDASCOPE)
     except Exception:
         IDASCOPE = IDAscopeForm()
 
-    IDASCOPE.Show()
+    if IDASCOPE.config.idascope_plugin_only:
+        print "IDAscope: configured as plugin-only mode, ignoring main function of script. " \
+             + "This can be changed in \"idascope/config.py\"."
+    else:
+        IDASCOPE.Show()
 
 
 if __name__ == "__main__":

idascope/config.py

+configuration = {
+    "config_path_sep": "\\",
+    "plugin_only": False,
+    "paths": {
+        # "idascope_root_dir": "C:\\Program Files\\IDA 6.3\\plugins",
+        "idascope_root_dir": "",
+        "semantics_file": "idascope\\data\\semantics.json",
+        "winapi_keywords_file": "idascope\\data\\winapi_keywords.json",
+        "winapi_rootdir": "C:\\WinAPI\\"
+        },
+    "winapi": {
+        "search_hotkey": "ctrl+y",
+        "load_keyword_database": True,
+        "online_enabled": True
+        }
+}

idascope/core/helpers/PatternManager.py

         MutablePattern("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\x08\x00\x00\x00\x09\x00\x00\x00\x09\x00\x00\x00\x0a\x00\x00\x00\x0a\x00\x00\x00\x0b\x00\x00\x00\x0b\x00\x00\x00\x0c\x00\x00\x00\x0c\x00\x00\x00\x0d\x00\x00\x00\x0d\x00\x00\x00"): "ZLIB distance extra bits",
         MutablePattern("\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x07\x00\x00\x00\x09\x00\x00\x00\x0d\x00\x00\x00\x11\x00\x00\x00\x19\x00\x00\x00\x21\x00\x00\x00\x31\x00\x00\x00\x41\x00\x00\x00\x61\x00\x00\x00\x81\x00\x00\x00\xc1\x00\x00\x00\x01\x01\x00\x00\x81\x01\x00\x00\x01\x02\x00\x00\x01\x03\x00\x00\x01\x04\x00\x00\x01\x06\x00\x00\x01\x08\x00\x00\x01\x0c\x00\x00\x01\x10\x00\x00\x01\x18\x00\x00\x01\x20\x00\x00\x01\x30\x00\x00\x01\x40\x00\x00\x01\x60\x00\x00"): "ZLIB distance starts",
 
-        ################ by DP others
+        ################ by DP
 
         MutablePattern("\xF1\xFF\x00\x00"): "ADLER32",
         MutablePattern("\x20\x83\xb8\xed"): "CRC32 Generator",
         MutablePattern("\x00\x00\x00\x00\x99\x79\x82\x5a\xa1\xeb\xd9\x6e\xdc\xbc\x1b\x8f\x4e\xfd\x53\xa9\xe6\x8b\xa2\x50\x24\xd1\x4d\x5c\xf3\x3e\x70\x6d\xe9\x76\x6d\x7a\x00\x00\x00\x00"): "ripe_md160",
         MutablePattern("\x04\x0a\x09\x02\x0d\x08\x00\x0e\x06\x0b\x01\x0c\x07\x0f\x05\x03\x0e\x0b\x04\x0c\x06\x0d\x0f\x0a\x02\x03\x08\x01\x00\x07\x05\x09\x05\x08\x01\x0d\x0a\x03\x04\x02\x0e\x0f\x0c\x07\x06\x00\x09\x0b\x07\x0d\x0a\x01\x00\x08\x09\x0f\x0e\x04\x06\x0c\x0b\x02\x05\x03\x06\x0c\x07\x01\x05\x0f\x0d\x08\x04\x0a\x09\x0e\x00\x03\x0b\x02\x04\x0b\x0a\x00\x07\x02\x01\x0d\x03\x06\x08\x05\x09\x0c\x0f\x0e\x0d\x0b\x04\x01\x03\x0f\x05\x09\x00\x0a\x0e\x07\x06\x08\x02\x0c\x01\x0f\x0d\x00\x05\x07\x0a\x04\x09\x02\x03\x0e\x06\x0b\x08\x0c"): "GOST Sbox",
 
+        MutablePattern("\x0D\x66\x19\x00"): "\"Quick and Dirty\" PRNG from \"Numerical Recipes in C\"",
+        MutablePattern("\x5F\xF3\x6E\x3C"): "\"Quick and Dirty\" PRNG from \"Numerical Recipes in C\"",
+
         VariablePattern("30 82 ? ? 30 82 ? ?"): "PKCS: X.509 Certificate",
         VariablePattern("30 82 ? ? 02 01 00 02 41"): "PKCS: Private-Key (512 bit)",
         VariablePattern("30 82 ? ? 02 01 00 02 81 81"): "PKCS: Private-Key (1024 bit)",

idascope/core/structures/IDAscopeConfiguration.py

 ########################################################################
 
 import os
-import json
-
-from idascope.core.helpers import JsonHelper
 
 
 class IDAscopeConfiguration():
     This class is an information container for a segment.
     """
 
-    def __init__(self, config_filename, os_ref=None):
-        self.json = json
+    def __init__(self, configuration, os_ref=None):
         if os_ref is not None:
             self.os = os_ref
         else:
             self.os = os
         # FIXME: second level path problem of referencing modules when accessing os.path.*
         try:
-            self.os_path_split = self.os.path.split
             self.os_path_normpath = self.os.path.normpath
         except:
-            self.os_path_split = None
             self.os_path_normpath = None
+        # default configuration
+        self.idascope_plugin_only = False
         self.root_file_path = ""
         self.icon_file_path = ""
         self.semantics_file = ""
         self.winapi_shortcut = "ctrl+y"
         self.winapi_load_keyword_database = False
         self.winapi_online_enabled = False
-        self._loadConfig(config_filename)
+        self._loadConfig(configuration)
 
-    def _loadConfig(self, config_filename):
-        # extract the root file dir from the path to the config file
-        if self.os_path_split is not None:
-            self.root_file_path = self.os_path_split(config_filename)[0] + self.os.sep
-        else:
-            # print "This path has", self.root_file_path
-            self.root_file_path = config_filename.split(self.os.sep)[0] + self.os.sep
-        # load config
-        config = self.json.loads(open(config_filename, "r").read(), object_hook=JsonHelper.decode_dict)
+    def _loadConfig(self, configuration):
+        self.root_file_path = configuration["paths"]["idascope_root_dir"]
+        # options directly affecting IDAscope
+        self.idascope_plugin_only = configuration["plugin_only"]
         # file path to the directory containing icons used by IDAscope
-        self.icon_file_path = self.root_file_path + "idascope" + self.os.sep + "icons" + self.os.sep
+        self.icon_file_path = self.root_file_path + self.os.sep \
+            + "idascope" + self.os.sep + "icons" + self.os.sep
         # parse other paths
-        self.config_path_sep = config["config_path_sep"]
-        self.semantics_file = self.root_file_path + self._normalizePath(config["paths"]["semantics_file"])
-        self.winapi_keywords_file = self.root_file_path + self._normalizePath(config["paths"]["winapi_keywords_file"])
-        self.winapi_rootdir = self._normalizePath(config["paths"]["winapi_rootdir"]) + self.os.sep
+        self.config_path_sep = configuration["config_path_sep"]
+        self.semantics_file = self.root_file_path + self.os.sep \
+            + self._normalizePath(configuration["paths"]["semantics_file"])
+        self.winapi_keywords_file = self.root_file_path + self.os.sep + \
+            self._normalizePath(configuration["paths"]["winapi_keywords_file"])
+        self.winapi_rootdir = self._normalizePath(configuration["paths"]["winapi_rootdir"]) + self.os.sep
         # widget related configurations
-        self.winapi_shortcut = config["winapi"]["search_hotkey"]
-        self.winapi_load_keyword_database = config["winapi"]["load_keyword_database"]
-        self.winapi_online_enabled = config["winapi"]["online_enabled"]
+        self.winapi_shortcut = configuration["winapi"]["search_hotkey"]
+        self.winapi_load_keyword_database = configuration["winapi"]["load_keyword_database"]
+        self.winapi_online_enabled = configuration["winapi"]["online_enabled"]
 
     def _normalizePath(self, path):
         if self.os_path_normpath is None:
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.