Customizing Existing Processors

Perhaps you are considering developing a processor module, but you notice that an existing processor module does almost everything that you need. If you have the source code for the processor module, then you might easily modify it to suit your needs. On the other hand, if you don’t have the source code, you might feel that you are out of luck. Fortunately, IDA offers a mechanism for customizing existing processors through the use of plug-ins. By hooking the appropriate processor notifications, a plug-in module can intercept calls to one or more of an existing processor’s analyzer, emulator, and outputter stages. Potential applications for customizing a processor include the following:

  • Extending the capabilities of an existing processor to recognize additional instructions

  • Correcting broken behavior in an existing processor module (though it is probably faster just to let Ilfak know you found a bug)

  • Customizing the output of an existing processor module to suit your particular needs

The following notification codes, declared in processor_t and discussed in idp.hpp, may be hooked by plug-ins that want to intercept calls to various stages of a processor:

custom_ana Behaves as u_ana; however, any new instructions must use a cmd.itype value of 0x8000 or higher.
custom_emu Provides emulation for custom instruction types. You may call (*ph.u_emu)() if you wish to invoke the processor’s existing emulator.
custom_out Generates output for custom instructions or provides custom output for existing instructions. You may call (*ph.u_out)() if you wish to invoke the processor’s out function.
custom_outop Outputs a single custom operand. You may call (*ph.u_outop)(op) if you wish to invoke the processor’s existing outop function.
custom_mnem Generates the mnemonic for a custom instruction.

The following code excerpts are from a plug-in that modifies the output of the x86 processor module to replace the leave instruction with a cya instruction and to swap the display order for instructions that have two operands (similar to the AT&T-style syntax):

int idaapi init(void) {
    if (ph.id != PLFM_386) return PLUGIN_SKIP;
    hook_to_notification_point(HT_IDP, hook, NULL);
     return PLUGIN_KEEP;
  }

  int idaapi hook(void *user_data, int notification_code, va_list va) {
     switch (notification_code) {
        case processor_t::custom_out: {
         if (cmd.itype == NN_leave) {  //intercept the leave instruction
            MakeLine(SCOLOR_ON SCOLOR_INSN "cya" SCOLOR_OFF);
              return 2;
           }
           else if (cmd.Op2.type != o_void) {
              //intercept 2 operand instructions
              op_t op1 = cmd.Op1;
              op_t op2 = cmd.Op2;
              cmd.Op1 = op2;
              cmd.Op2 = op1;
               (*ph.u_out)();
              cmd.Op1 = op1;
              cmd.Op2 = op2;
              return 2;
           }
        }
     }
     return 0;
  }
    plugin_t PLUGIN = {
    IDP_INTERFACE_VERSION,
   PLUGIN_PROC | PLUGIN_HIDE | PLUGIN_MOD,  // plugin flags
    init,                 // initialize
    term,                 // terminate. this pointer may be NULL.
    run,                  // invoke plugin
    comment,              // long comment about the plugin
    help,                 // multiline help about the plugin
    wanted_name,          // the preferred short name of the plugin
    wanted_hotkey         // the preferred hotkey to run the plugin
  };

The plug-in’s init function verifies that the current processor is the x86 processor and then hooks processor notifications . In the callback hook function, the plug-in processes the custom_out notification to recognize the leave instruction and generates an alternative output line . For two operand instructions, the hook function temporarily saves the operands associated with the current command, before swapping them within the command just prior to invoking the x86 processor’s u_out function to handle all of the details of printing the line. Upon return, the command’s operands are swapped back to their original order. Finally, the plug-in’s flags specify that the plug-in should be loaded when a processor is loaded, should not be listed on the Edit ▸ Plugins menu, and modifies the database. The following output shows the effects of the customizations performed by the plug-in:

.text:00401350            push    ebp
 .text:00401351            mov     400000h, edx
  .text:00401356            mov     esp, ebp
 .text:00401358            mov     offset unk_402060, eax
 .text:0040135D            sub     0Ch, esp
  .text:00401360            mov     edx, [esp+8]
  .text:00401364            mov     eax, [esp+4]
 .text:00401368            mov     offset unk_402060, [esp]
  .text:0040136F            call    sub_401320
 .text:00401374            cya
  .text:00401375            retn

You can observe the plug-in’s effects by noting that constants appear as the first operand in four instructions and that the cya instruction is used in place of the leave instruction .

In Chapter 21, we will look at using a custom processor plug-in to aid in the analysis of certain types of obfuscated binaries.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.36.231