This is a guest entry written by Elias Bachaalany. His views and opinions are his own, and not those of Hex-Rays. Any technical or maintenance issues regarding the code herein should be directed to him.
ida-qscripts or QScripts is a productivity plugin for better/faster scripting and coding workflow/experience for IDA.
IDA provides two methods to script: script files and script snippets.
For native programming (writing plugins using the C++ SDK), the development workflow is equally slow. You have to build your plugin, deploy it in the plugins folder, and often times restart IDA for your native plugin’s new version to be loaded.
With QScripts, all you need to do is activate a script and it will be monitored for changes. When the script (its dependencies or trigger file) is modified, then qscripts will automatically re-run the script for you.
The following are some of the important features and options in QScripts:
msg_clear()
call before the script is executed.QScripts is an open-source project hosted at https://github.com/0xeb/ida-qscripts. Grab a build from the releases page and place it in your plugins folder. Alternatively, just build it from sources.
Install QScripts and open it with the default Alt–Shift–F9 hotkey:
If the window is empty, it means that you never ran scripts before. Just press Ins to browse a script and load it. Double-click on the script to activate it. Below, we can see hello.py activated:
Any changes to this file will cause qscripts to run it automatically. Like this, you don’t have to leave your editor. The ideal setup is to have IDA and your editor side by side:
To stop the script monitor, just select your script and press Ctrl–D:
If your scripts have dependencies, then you must create and configure an additional file with the same name and extension as your input script with the additional .deps.qscripts suffix.
For example, hello.py‘s dependency file should be called hello.py.deps.qscripts:
This tells qscripts that hello.py depends on myotherscript.py. If myotherscript.py also has its own myotherscript.py.deps.qscripts then hello.py will inherit its dependent’s dependencies.
If you prefer to prototype in C++ using the full power of the IDA SDK, then qscripts also lets you stay in your favorite IDE and edit/build/run the plugin continuously. Check the video below for a demo.
First, let’s discuss some background information to explain how hot-reloading works in IDA.
IDA plugins use a plugin descriptor structure called plugin_t
. It has the flags
field which can have the PLUGIN_UNL
flag that allows hot-reloading of the plugins in a edit/build/run fashion.
When IDA runs, the plugin’s binary (*.so, 64*.dll, *.dll
) will be loaded and held by IDA. Once you invoke the plugin the first time, its run()
will be invoked, then IDA will unload the plugin. This will be your chance to re-compile the modified plugin before re-invoking it in IDA (from the menu) or programmatically via the load_and_run_plugin()
.
Now that we know how hot-reloading works in IDA, we can leverage qscripts and its trigger files feature to allow native plugins development and prototyping in a convenient manner.
To begin, create a simple Python script with the following contents:
Then also write its dependency file with a trigger file that is the actual compiled plugin binary. For instance:
Finally, activate hello_cpp.py from qscripts.
Now, everytime the compiled plugin binary changes, the Python script will ask IDA to load and run it again!
Conveniently, qscripts ships with a bunch of templates that lets you focus on the code rather than on the mechanics/plumbing code of a plugin:
load_file()
and accept_file()
callbacks. Implement and quickly test these methods before you transfer this code to a real file loader module.That’s all, happy and productive coding!