-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathsymless_plugin.py
More file actions
156 lines (125 loc) · 4.77 KB
/
symless_plugin.py
File metadata and controls
156 lines (125 loc) · 4.77 KB
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
import base64
import collections
import importlib
import os
import pkgutil
import sys
import traceback
from typing import Collection
import idaapi
import symless
import symless.plugins as plugins
import symless.utils.utils as utils
class fixedBtn(idaapi.Form.ButtonInput):
def __init__(self, plugin: "SymlessPlugin", form: "SymlessInfoForm"):
super().__init__(self.reload, "0")
self.plugin = plugin
self.form = form
def reload(self, code):
idaapi.show_wait_box("Reloading Symless..")
try:
# terminate all extensions
self.plugin.term()
remove_old_modules()
# rebind all extensions
self.plugin.find_extensions(reload=True)
except Exception as e:
idaapi.hide_wait_box()
utils.g_logger.critical(repr(e) + "\n" + traceback.format_exc())
else:
idaapi.hide_wait_box()
self.form.Close(1)
def get_tag(self):
return "<Reload:%s%d:%s%s:%s:%s>" % (
self.tp,
self.id,
"+" if self.is_relative_offset else "",
self.width,
self.swidth,
":" if self.hlp is None else self.hlp,
)
class SymlessInfoForm(idaapi.Form):
def __init__(self, plugin: "SymlessPlugin"):
icon_path = os.path.join(os.path.abspath(symless.__path__[0]), "resources", "bigger_champi.png")
with open(icon_path, "rb") as file:
icon_b64 = base64.b64encode(file.read()).decode()
img_html = "<img src='data:image/png;base64,%s'>" % icon_b64
info_html = """
<div style='text-align: center; margin: 6px; font-size: 16px;'>
<pre style='font-size: 72px;'>Symless</pre>
<pre style='font-size: 16px; text-align: left;'>%s<br><br>Version: <b>%.1f</b></pre>
</div>
""" % (
symless.PLUGIN_DESC,
symless.PLUGIN_VERSION,
)
super().__init__(
"BUTTON YES NONE\nBUTTON CANCEL NONE\nSymless plugin\n{img}<|>{info}\n{reload}",
{
"img": idaapi.Form.StringLabel(img_html, tp=idaapi.Form.FT_HTML_LABEL, size=None),
"info": idaapi.Form.StringLabel(info_html, tp=idaapi.Form.FT_HTML_LABEL, size=None),
"reload": fixedBtn(plugin, self),
},
)
# Symless plugin
class SymlessPlugin(idaapi.plugin_t):
flags = idaapi.PLUGIN_MOD | idaapi.PLUGIN_PROC # | idaapi.PLUGIN_HIDE
comment = "Symless interactive plugin"
wanted_name = "Symless"
help = "" # not used, IDA < 7.6 compatibility
wanted_hotkey = "" # not used, IDA < 7.6 compatibility
# find & initialize all extensions
def init(self) -> idaapi.plugmod_t:
self.ext: Collection[plugins.plugin_t] = collections.deque()
self.find_extensions()
return idaapi.PLUGIN_KEEP
# find and load extensions from symless plugins folder
def find_extensions(self, reload: bool = False):
for mod_info in pkgutil.walk_packages(plugins.__path__, prefix="symless.plugins."):
if mod_info.ispkg:
continue
spec = mod_info.module_finder.find_spec(mod_info.name)
module = importlib.util.module_from_spec(spec)
# module is already loaded
if module.__name__ in sys.modules:
module = sys.modules[module.__name__]
# load the module
else:
sys.modules[module.__name__] = module
try:
spec.loader.exec_module(module)
except BaseException as e:
sys.modules.pop(module.__name__)
utils.g_logger.error(f"Error while loading extension {mod_info.name}:")
utils.g_logger.error(repr(e) + "\n" + traceback.format_exc())
continue
# module defines an extension
if not hasattr(module, "get_plugin"):
continue
ext: plugins.plugin_t = module.get_plugin()
# notify the extension that it has been reloaded
if reload:
ext.reload()
self.ext.append(ext)
# display info panel
def run(self, args):
info = SymlessInfoForm(self)
info.Compile()
info.Execute()
info.Free()
# term all extensions
def term(self):
while len(self.ext) > 0:
ext = self.ext.pop()
ext.term()
def PLUGIN_ENTRY() -> idaapi.plugin_t:
return SymlessPlugin()
# remove old symless modules from loaded modules
def remove_old_modules():
to_remove = set()
for k in sys.modules.keys():
if k.startswith("symless"):
to_remove.add(k)
for r in to_remove:
print(f"Removing old {r} ..")
del sys.modules[r]