在研究一個採用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
};