IDA Pro外掛試刀

看雪資料發表於2015-11-15

在研究一個採用Flexlm進行保護的軟體時,當使用了相應版本Flexlm SDK的Sig檔案後,IDA Pro順利地識別出了若干符號。美中不足的是,大部分符號(函式名)被做成了repeatable comment。函式名字仍然是類似sub_45A7F8或unknown_libname_15的東西。要是能用對應的註釋為函式命名,就可以使用相應的外掛,實現在SoftIce中進行符號化除錯。

  這樣的註釋太多,手工完成是不明智的。第一想法是用IDC Script來做這件事。但嘗試了幾次,結果總是不如人意。用IDC的幾個內建函式(如NextFunction,FindFuncEnd等等)遍歷IDB檔案中的函式時,不知什麼原因,總是有不少函式會被漏掉。另外,在我的IDA Pro 4.3.0.740a上,無論是用IDC Script的Message函式還是外掛的msg函式在狀態視窗中輸出資訊時,經常出錯,象是越界訪問陣列。程式碼看起來沒什麼錯,不知道是否有bug。

  以下用外掛來實現,查詢所有具有library屬性的函式(從Sig檔案中得到的符號,都有此屬性?)。檢查函式名,若為sub_XXXX或unknown_libname_XX形式,則取其repeatable註釋。若存在,將函式改為此名。注意有的註釋不止一行,如該vendor daemon中42C41B處的註釋為:

  _reg
    _l_timer_signal

      在命名函式時,不允許存在回車換行符。對這種情況,只用最後一行。對於重名函式,後續命名時使用遞增的函式名,如_l_timer_signal_1,_l_timer_signal_2。在除錯程式碼時發現,若要使用儲存在由IDA分配的記憶體中的資料時,必須及時儲存,否則該資料可能會損壞。

  我不知道IDA的Script和Plugin有什麼區別?請高手指教。好象Plugin功能更強,可以完成Script的功能,提供了更多的函式。因為可在VC中程式設計,還可使用IDA SDK以外的函式。

  以下的程式碼針對具體的應用,並不具有通用性,只是探討Plugin的應用。所有的程式碼都在run函式中。直接從SDK的sample修改而來。經過以下處理,該vendor daemon中沒有明確命名的函式已所剩無幾。

  
#include <ida.hpp>
#include <idp.hpp>
#include <bytes.hpp>
#include <loader.hpp>
#include <kernwin.hpp>
#include <name.hpp>

...

int init(void)
{
    return PLUGIN_OK;
}


void run(int arg)
{
     func_t * pFunc_t;
     ea_t nStart;          //函式地址
   char szAnswer[256];   //原來的函式名
   char szOrigCmt[256];  //函式的repeatable註釋
   char szTemp[256];
    char szNewCmt[256];   //調整後的註釋(重名函式用)
    char szAsc[10];

    int nCounter=0;  //累加
   char * lpszCmt=0;    //指向函式註釋的指標
   char * lpszDelimiter=0;  //分隔符(換行=0xA)
    bool bRet;

  
    int nNumOfFuncs=get_func_qty();  //取函式總數

   for(int i=0;i<nNumOfFuncs;i++)
   {
       pFunc_t=getn_func(i);
       if(pFunc_t->flags & FUNC_LIB)  //只處理庫函式
     {
               nStart=pFunc_t->startEA;

               get_func_name(nStart,szAnswer,sizeof(szAnswer));

               if((0==strncmp(szAnswer,"sub_",4))||
   (0==strncmp(szAnswer,"unkn",4)))  //函式名以"sub_"或"unkn"打頭嗎    
         {
        szOrigCmt[0]=0;   //清當前內容
        
      lpszCmt=get_func_comment(pFunc_t,true);  //取註釋

      if(!lpszCmt) continue;   //無註釋
        
      strcpy(szOrigCmt,lpszCmt);  //儲存當前註釋
  
      //檢查註釋是否不止1行

      lpszDelimiter=0;
       szTemp[0]=0;

                     if(lpszDelimiter=strrchr(szOrigCmt,0xA)) //查詢換行符
     {
            strcpy(szTemp,lpszDelimiter+1);
        
                          szOrigCmt[0]=0;
            strcpy(szOrigCmt,szTemp);   //用最後1行
      }

      bRet=set_name(nStart,szOrigCmt);
    
      nCounter=0;
          while(0==bRet) //命名失敗(函式名已被使用)
      {
    szAsc[0]=0;
    _itoa(++nCounter,szAsc,10);
            
    szNewCmt[0]=0;
    strcpy(szNewCmt,szOrigCmt);
    strcat(szNewCmt,"_");
    strcat(szNewCmt,szAsc);  //建立遞增的函式名
            
    bRet=set_name(nStart,szNewCmt);
                     }
                }
          }
     }
}

char comment[] = "My first plugin";

char help[] =
        "A sample plugin module
"
        "
"
        "This module shows you how to create plugin modules.
"
        "
"
        "It does nothing useful - just prints a message that is was called
"
        "and shows the current address.
";

char wanted_name[] = "My first plugin";

char wanted_hotkey[] = "Alt-0";

extern "C" plugin_t PLUGIN = {
  IDP_INTERFACE_VERSION,
  0,                    // plugin flags
  init,                 // initialize

  term,              // terminate. this pointer may be NULL.

  run,                // invoke plugin

  comment,       // long comment about the plugin
                        // it could appear in the status line
                        // or as a hint

  help,                 // multiline help about the plugin

  wanted_name,          // the preferred short name of the plugin
  wanted_hotkey         // the preferred hotkey to run the plugin
};

相關文章