|
import sys |
|
import shutil |
|
import pathlib |
|
import ida_pro |
|
import importlib |
|
import subprocess |
|
import ida_diskio |
|
import ida_idaapi |
|
import ida_kernwin |
|
|
|
class MinscEnforce(ida_idaapi.plugin_t): |
|
# ---------------------------------------------------------------------------- # |
|
flags = \ |
|
ida_idaapi.PLUGIN_HIDE \ |
|
| ida_idaapi.PLUGIN_FIX \ |
|
| ida_idaapi.PLUGIN_MULTI |
|
# ---------------------------------------------------------------------------- # |
|
repository = "https://github.com/arizvisa/ida-minsc" |
|
comment = "install IDA-minsc already bozo..." |
|
help = "github.com/arizvisa/ida-minsc" |
|
wanted_name = "minsc-enforce" |
|
wanted_hotkey = "" |
|
# ---------------------------------------------------------------------------- # |
|
|
|
@staticmethod |
|
def copy_folder(src: pathlib.Path, dst: pathlib.Path) -> None: |
|
# iterate through source dir & copy to dst folder. |
|
for c in src.iterdir(): |
|
p = dst.joinpath(c.name) |
|
# create subdirectories as needed by pathlib. |
|
p.parent.mkdir(parents=True, exist_ok=True) |
|
c.rename(p) |
|
|
|
def git_clone_repo(self, repo: str) -> None: |
|
# get user idadir and construct temp folder path. |
|
idau = ida_diskio.get_user_idadir() |
|
idau = pathlib.Path(idau).resolve() |
|
tmpf = (idau.parent / "tmp") |
|
|
|
try: |
|
# copy out contents of idadir and clone IDA-minsc. |
|
MinscEnforce.copy_folder(idau, tmpf) |
|
|
|
subprocess.call(f"git clone --recursive {repo} .", shell=True, cwd=idau) |
|
subprocess.call(f"pip install --user -r 'requirements.txt'", shell=True, cwd=idau) |
|
|
|
# reinstate any existing files from tmp to idadir. |
|
MinscEnforce.copy_folder(tmpf, idau) |
|
shutil.rmtree(tmpf) |
|
|
|
except Exception: |
|
if tmpf.exists(): |
|
shutil.rmtree(tmpf) |
|
|
|
# ida64.exe+0x57EE9: 40 57 48 81 EC 10 |
|
def interr(self, err: int) -> None: |
|
# mimic STDERR message print as seen in ida64.dll. |
|
print(f"Oops! internal error 0x{err:X} occured.", file=sys.stderr) |
|
|
|
# pretend INTERR crash dialog as seen in ida64.exe. |
|
res = ida_kernwin.ask_buttons( |
|
"~C~reate a crash dump and exit IDA", |
|
"Just ~e~xit IDA", |
|
"~D~ownload IDA-minsc", |
|
-1, |
|
f"ICON ERROR\n" + |
|
f"TITLE Internal IDA Error\n" + |
|
f"Oops! internal error 0x{err:X} occurred.\n" + |
|
f"Further work is not possible without IDA-minsc installed. \n" + |
|
f"Would you like to create a crash dump for a bug report?" |
|
) |
|
|
|
# if download button pressed open repo & attempt install. |
|
if (res == -1): |
|
ida_kernwin.open_url(self.repository) |
|
self.git_clone_repo (f"{self.repository}.git") |
|
|
|
# if crash dump or exit button pressed, crash dump IDA. |
|
else: |
|
ida_pro.qexit(1) |
|
|
|
# ---------------------------------------------------------------------------- # |
|
|
|
def init(self): |
|
# construct path to idadir -> minsc. |
|
idau = ida_diskio.get_user_idadir() |
|
idau = pathlib.Path(idau).resolve() |
|
minsc = (idau / "plugins" / "minsc.py") |
|
|
|
# is minsc plugin found & database class exists in current spec. |
|
if not minsc.exists() or not importlib.util.find_spec("database"): |
|
self.interr(0x6D696E7363) |
|
|
|
# skip plugin loading as nothing implemented. |
|
return ida_idaapi.PLUGIN_SKIP |
|
|
|
def term(self): |
|
return None |
|
|
|
def run(self, arg): |
|
return None |
|
|
|
def PLUGIN_ENTRY(): |
|
return MinscEnforce() |