One of the oldest and most popular reversing tools is IDA Pro (usually bundled with its multiple decompilers&plug-ins). Over the years, the creators of this tool introduced a lot of substantial changes to this software, and in parallel, a lot of changes have been introduced to the programming frameworks newer IDA Pro versions rely on (namely, Python).
I bet some old OG IDA Pro users and reversers still remember the time they spent writing their first IDC scripts… and I bet some younger OGs reminisce similar memorable moments and feels about their early idapython scripts based on Python 2.x. Unfortunately, with many changes introduced to Python and IdaPython over the years we now live in a world where multiple parallel IDA Pro universes exist. The world in which many very useful plug-ins, scripts that just… used to ‘work’… today fail to work and they do so miserably…
Over the last 10 years or so, I’ve spent a substantial amount of time trying to port many of these older IDA Python-based plug-ins/scripts to that ‘latest, newest version’ of IDAPython du jour. It actually takes a lot of time, and it’s mainly because I am not the best person to be tasked with this upgrading task, plus the frequent changes on so many fronts are really hard to keep up with, so… in many of these past instances where I actually tried, I often did end up just throwing a towel in the end… It’s just not worth it, and I must say here that I have arrived at this sad conclusion on more than just one occasion…
BUT I STILL LOVE SOME OF THESE OLD PLUG-INS!
Then one day it hit me.
The answer to all our IDA Plugin code incompatibility problems is… keeping multiple IDA Pro versions installed at the same time! And then, using an appropriate IDA Pro version for which these plug-ins or scripts were created for – run them, collect their output and… incorporate this output into our ‘working’ IDA database, typically created by ‘the latest and greatest’ version of IDA.
It may sound stupid, but it actually does work quite well!
Today I temporarily install older IDA Pro versions on my test malware box on regular basis — they are often a few years old, totally obsolete, but they offer one important feature to me – they still run that specific old plug-in/script code for me!
How does it work in practice?
In generic terms, you just install the old version of IDA, open the sample you are working on in that old IDA version, and then you run the actual code (plug-in or script) that this particular IDA Pro version supports. After that, you export the IDC script from the database (File -> Produce File -> Dump database to IDC file). Then you edit that exported IDC script to only call out to the functions or snippets of code that introduce changes you want… Then you import it into your ‘current’/’working’ IDA database….
And yeah, at first sight, this exported IDC script may look messy, but it’s easy to navigate, plus we can quickly notice that we can comment out all the unnecessary function calls inside its main function, and then we just focus on the functions we really want to execute – some of them adding structures, enums, naming locations, adding comments, etc.
The main function of a typical IDA-exported IDC script looks like this:
static main(void) { // set 'loading idc file' mode set_inf_attr(INF_GENFLAGS, INFFL_LOADIDC|get_inf_attr(INF_GENFLAGS)); GenInfo(); // various settings Segments(); // segmentation Enums(); // enumerations Structures(); // structure types ApplyStrucTInfos(); // structure type infos Patches(); // manual patches SegRegs(); // segment register values Bytes(); // individual bytes (code,data) Functions(); // function definitions // clear 'loading idc file' mode set_inf_attr(INF_GENFLAGS, ~INFFL_LOADIDC&get_inf_attr(INF_GENFLAGS)); }
Many of these high-level functions include call outs to similarly named, second-level functions – it’s actually really easy to follow and edit them. For example, if the main function calls out a Bytes function it’s most likely we will see it making call outs to multiple functions prefixed with the word Bytes:
static Bytes(void) { Bytes_0(); Bytes_1(); Bytes_2(); Bytes_3(); Bytes_4(); end_type_updating(UTP_STRUCT); }
You can quickly eyeball all of these functions’ bodies and decide which code/function call to comment out…
It usually takes less than 5-10 minutes to do so, and as a result you cherry-pick the exact metadata you want to import into your ‘working’ database (usually the one created with the latest available version of IDA Pro).
In the last few years I have used this approach many times, often during time-sensitive malware analysis engagements, and am happy to report that it does work quite well.
Aka: don’t fight the system, use it.
The other avenue to pursue here is to introduce subtle, cosmetic modifications to the old plug-ins’ code that can you modify to generate a code that is ‘compatible’ with the most up-to-date version of Ida and its IdaPython modules.
We can do it, because the output of many reversing IDA Python scrips is pretty predictable:
It’s actually very easy to add small code snippets to the old plug-ins that will generate a precise list of instructions encoded using the latest version of IdaPython, then save them into a temporary IdaPython script file that is compatible with the latest and greatest version of IDA Python. Such dynamically generated code can be then executed within a context of the database opened with the latest version of Ida Pro. Easy Peasy.
The bottom line is this: