-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathIDAscope.py
275 lines (241 loc) · 10.6 KB
/
IDAscope.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#!/usr/bin/python
########################################################################
# Copyright (c) 2012
# Daniel Plohmann <daniel.plohmann<at>gmail<dot>com>
# Alexander Hanel <alexander.hanel<at>gmail<dot>com>
# All rights reserved.
########################################################################
#
# This file is part of IDAscope
#
# IDAscope is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
# <http://www.gnu.org/licenses/>.
#
########################################################################
import idascope.core.helpers.QtShim as QtShim
QtGui = QtShim.get_QtGui()
QtCore = QtShim.get_QtCore()
QtWidgets = QtShim.get_QtWidgets()
import idc
import idaapi
from idaapi import PluginForm, plugin_t
import idascope.config as config
from idascope.core.helpers.ClassCollection import ClassCollection
from idascope.core.structures.IDAscopeConfiguration import IDAscopeConfiguration
from idascope.core.SemanticIdentifier import SemanticIdentifier
from idascope.core.DocumentationHelper import DocumentationHelper
from idascope.core.WinApiProvider import WinApiProvider
from idascope.core.CryptoIdentifier import CryptoIdentifier
from idascope.core.YaraScanner import YaraScanner
from idascope.core.IdaProxy import IdaProxy
from idascope.core.SemanticExplorer import SemanticExplorer
from idascope.widgets.FunctionInspectionWidget import FunctionInspectionWidget
from idascope.widgets.WinApiWidget import WinApiWidget
from idascope.widgets.CryptoIdentificationWidget import CryptoIdentificationWidget
from idascope.widgets.YaraScannerWidget import YaraScannerWidget
from idascope.widgets.SemanticExplorerWidget import SemanticExplorerWidget
################################################################################
# Core of the IDAscope GUI.
################################################################################
HOTKEYS = None
IDASCOPE = None
NAME = "simpliFiRE.IDAscope v1.3.1"
class IDAscopeForm(PluginForm):
"""
This class contains the main window of IDAscope
Setup of core modules and widgets is performed in here.
"""
def __init__(self):
super(IDAscopeForm, self).__init__()
global HOTKEYS
HOTKEYS = []
self.idascope_widgets = []
self.cc = ClassCollection()
self.ensureRootPathSanity(config.configuration)
self.config = IDAscopeConfiguration(config.configuration, self.cc)
self.icon = self.cc.QIcon(self.config.icon_file_path + "idascope.png")
def ensureRootPathSanity(self, configuration):
try:
root_dir = configuration["paths"]["idascope_root_dir"]
if not self.cc.os.path.exists(root_dir) or not "IDAscope.py" in self.cc.os.listdir(root_dir):
print("[!] IDAscope.py is not present in root directory specified in \"config.py\", " \
+ "trying to resolve path...")
resolved_pathname = self.cc.os.path.dirname(self.cc.sys.argv[0])
if "IDAscope.py" in self.cc.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.")
self.cc.sys.exit(-1)
def setupSharedModules(self):
"""
Setup shared IDAscope modules.
"""
time_before = self.cc.time.time()
print("[/] setting up shared modules...")
self.semantic_explorer = SemanticExplorer(self)
self.documentation_helper = DocumentationHelper(self.config)
self.semantic_identifier = SemanticIdentifier(self.config)
self.winapi_provider = WinApiProvider(self.config)
self.crypto_identifier = CryptoIdentifier(self.config)
self.yara_scanner = YaraScanner(self.config)
print("[\\] this took %3.2f seconds.\n" % (self.cc.time.time() - time_before))
def setupWidgets(self):
"""
Setup IDAscope widgets.
"""
time_before = self.cc.time.time()
print("[/] setting up widgets...")
self.idascope_widgets.append(SemanticExplorerWidget(self))
self.idascope_widgets.append(FunctionInspectionWidget(self))
self.idascope_widgets.append(WinApiWidget(self))
self.idascope_widgets.append(CryptoIdentificationWidget(self))
self.idascope_widgets.append(YaraScannerWidget(self))
self.setupIDAscopeForm()
print("[\\] this took %3.2f seconds.\n" % (self.cc.time.time() - time_before))
def setupIDAscopeForm(self):
"""
Orchestrate the already initialized widgets in tabs on the main window.
"""
self.tabs = self.cc.QTabWidget()
self.tabs.setTabsClosable(False)
for widget in self.idascope_widgets:
self.tabs.addTab(widget, widget.icon, widget.name)
layout = self.cc.QVBoxLayout()
layout.addWidget(self.tabs)
self.parent.setLayout(layout)
def OnCreate(self, form):
"""
When creating the form, setup the shared modules and widgets
"""
self.printBanner()
# compatibility with IDA < 6.9
try:
self.parent = self.FormToPySideWidget(form)
except Exception as exc:
self.parent = self.FormToPyQtWidget(form)
self.parent.setWindowIcon(self.icon)
self.setupSharedModules()
self.setupWidgets()
def printBanner(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.
"""
global IDASCOPE
del IDASCOPE
def Show(self):
if self.cc.ida_proxy.GetInputMD5() is None:
return
else:
options = 0
if self.cc.ida_proxy.idaapi.IDA_SDK_VERSION < 700:
options = PluginForm.FORM_CLOSE_LATER | PluginForm.FORM_RESTORE | PluginForm.FORM_SAVE
else:
options = PluginForm.WCLS_CLOSE_LATER | PluginForm.WOPN_RESTORE | PluginForm.WCLS_SAVE
return PluginForm.Show(self,
NAME,
options=options)
################################################################################
# functionality offered to IDAscope's widgets
################################################################################
def setTabFocus(self, widget_name):
"""
Can be used by IDAscope widgets to set focus to a widget, identified by name.
@param widget_name: A widget name
@type widget_name: str
"""
for widget in self.idascope_widgets:
if widget.name == widget_name:
tab_index = self.tabs.indexOf(widget)
self.tabs.setCurrentIndex(tab_index)
return
def registerHotkey(self, shortcut, py_function_pointer):
"""
Can be used by IDAscope widgets to register hotkeys.
Uses a global list HOTKEYS of function pointers that link to the desired functionality.
Right now, linked functions cannot take parameters and should scrape all information they need by themselves.
@param shortcut: A string describing a shortcut, e.g. "ctrl+F3"
@type shortcut: str
@param py_function_pointer: a python function that shall be called when the shortcut is triggered.
@type py_function_pointer: a pointer to a python function
"""
global HOTKEYS
hotkey_index = len(HOTKEYS)
hotkey_name = "idascope_HOTKEY_%d" % hotkey_index
HOTKEYS.append(py_function_pointer)
self.cc.ida_proxy.CompileLine('static %s() { RunPythonStatement("HOTKEYS[%d]()"); }' % (hotkey_name, hotkey_index))
self.cc.ida_proxy.AddHotkey(shortcut, hotkey_name)
################################################################################
# Usage as plugin
################################################################################
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 = "IDAscope - Different tools to ease reverse engineering."
wanted_name = "IDAscope"
wanted_hotkey = "Ctrl-F4"
def init(self):
# Some initialization
self.icon_id = 0
return idaapi.PLUGIN_OK
def run(self, arg=0):
# Create form
f = IDAscopeForm()
# Show the form
f.Show()
return
def term(self):
pass
################################################################################
# Usage as script
################################################################################
def main():
global IDASCOPE
try:
IDASCOPE
IDASCOPE.OnClose(IDASCOPE)
print("reloading IDAscope")
IDASCOPE = IDAscopeForm()
return
except Exception:
IDASCOPE = IDAscopeForm()
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__":
main()