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.


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
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.


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