| ||||||||||||||||
The IDA Plugin framework
by roy g biv
The IDA Plugin framework roy g biv / 29A Former DOS/Win16 virus writer, author of several virus families, including Ginger (see Coderz #1 zine for terrible buggy example, contact me for better sources ;), and Virus Bulletin 9/95 for a description of what they called Rainbow. Co-author of world's first virus using circular partition trick (Orsam, coded with Prototype in 1993). Designer of world's first XMS swapping virus (John Galt, coded by RT Fishel in 1995, only 30 bytes stub, the rest is swapped out). Author of world's first virus using Thread Local Storage for replication (Shrug, see Virus Bulletin 6/02 for a description, but they call it Chiton), world's first virus using Visual Basic 5/6 language extensions for replication (OU812), world's first Native executable virus (Chthon), world's first virus using process co-operation to prevent termination (Gemini, see Virus Bulletin 9/02 for a description), world's first virus using polymorphic SMTP headers (JunkMail, see Virus Bulletin 11/02 for a description), world's first viruses that can convert any data files to infectable objects (Pretext), world's first 32/64-bit parasitic EPO .NET virus (Croissant, see Virus Bulletin 11/04 for a description, but they call it Impanate), world's first virus using self-executing HTML (JunkHTMaiL, see Virus Bulletin 7/03 for a description), world's first virus for Win64 on Intel Itanium (Shrug, see Virus Bulletin 6/04 for a description, but they call it Rugrat), world's first virus for Win64 on AMD AMD64 (Shrug), world's first cross-infecting virus for Intel IA32 and AMD AMD64 (Shrug), world's first viruses that infect Office applications and script files using the same code (Macaroni), and world's first viruses that can infect both VBS and JScript using the same code (ACDC). Author of various retrovirus articles (eg see Vlad #7 for the strings that make your code invisible to TBScan). Went to sleep for a number of years. This is my ninth virus for Win32. It is the world's first IDA plugin virus. What is it? Many people know about the Interactive Disassembler. It is a great tool for disassembling many different file formats for many different CPUs. It even has a debugger now, so it can be used for all kinds of reverse-engineering, unpacking, decrypting, etc. In case that was not enough functionality, it also supports plugins. Plugins For some years, I wondered if an IDA virus could be possible. I tried in the IDC scripting language first, because there is lots of documentation for it and it is easy to program. There were some problems, though. The first problem is that IDA opens a file with full sharing, but the IDC language does not support doing that, so it is not possible to infect the file that is being examined. That leaves as an option to find other files to infect, but there is no enumeration function in the IDC language. That means that we can infect only the files that we know to exist, and that wasn't interesting to me. Eventually, I noticed the plugins directory, but there was no documentation in IDA about how to write one. I was able to reverse-engineer the format very easily, but I had no understanding of what I was seeing, until one day when I heard about the IDA SDK. I searched on the Internet for it and found one for an old version of IDA. Since for my purposes, nothing but the version number had changed, it became very easy. Here is the description of that: IDA Plugins are DLL files with a special extension. The extension to use depends on the operating system and CPU to support. For 32-bit Windows and Linux, and 64-bit Linux on AMD AMD64, it's "plx". For 64-bit Windows on AMD AMD64, it's "x64". For 64-bit Windows on Intel EM64T, it's "p64". For 64-bit Linux on Intel EM64T, it's "plx64". The plugin must contain one export. This export must be called "_PLUGIN" or "PLUGIN" or it must be ordinal 1. The export points to a structure. The structure is byte-packed and it has this format: struct plugin_t { int version; int flags; int (idaapi* init)(void); void (idaapi* term)(void); void (idaapi* run)(int arg); char *comment; char *help; char *wanted_name; char *wanted_hotkey; }; The version is the version number of the SDK. I was told 75 for IDA 4.8. (Now is November, and I am told that IDA 4.9 has 76 for the version number) The flags are for some behaviours mostly to do with debugging. The init function is the only necessary function. It is called by IDA when the plugin is loaded, which occurs after the file to disassemble has been opened. If the init function returns 0, then IDA will discard the plugin and not call any of the other functions. If the function returns another value, then IDA will keep the plugin and call the other functions as required. The term function is called by IDA to terminate the plugin when IDA is exiting. The run function is called whenever the plugin is invoked. There is also a callback mechanism with so many events that can be hooked, I cannot list them all here. None of them fitted my purpose, anyway. GetModuleFileName When the init function is called, the file to dissasemble can be accessed, if its name is known. The problem is to find out the name. Amazingly, there seems to be no public function to do that. After much reading, I found a way to do it. It is achieved by passing the RootNode netnode to the function called _netnode_value@4(). That returns the full ASCII pathname of the file. From there, is it possible to open the file and infect it. The RootNode and _netnode_value@4 are exports from the ida.wll file. Since they are exported by ordinal only, so they are subject to change, but since the SDK version number is required to match, nothing would be gained by exporting by name. (Now is November, and IDA 4.9 changed some things. The _netnode_value@4 was renamed to "netnode_valstr". Both RootNode and netnode_valstr are exported by name, so the ida.lib is not required anymore to build. The parameters for the netnode_valstr function are also different from previously. Now is required to pass the buffer and its length to receive the name). What about stealth? An obvious extension to the infection via plugin is to stealth the result. As it is right now, the changes don't show until the file is opened again, but by the time the plugin is loaded, IDA has decided where the entrypoint is, and I couldn't find a way to change that, or to hide the code. That's for someone else to discover. ;) Greets to friendly people (A-Z): Active - Benny - Obleak - Prototype - Ratter - Ronin - RT Fishel - sars - SPTH - The Gingerbread Man - Ultras - uNdErX - Vallez - Vecna - VirusBuster - Whitehead rgb/29A sep/nov 2005 iam_rgb@hotmail.com |