在研究一个Borland C++写的软件时,遇到以下问题:在主EXE文件和一个DLL中包含有大量的字符串资源,包括各种提示及错误信息。代码中使用这些资源的方式基本一致,即构造一个OWL的TStringIDS对象,把资源ID作为参数传入。在IDA中,为以下格式:
push nResourceID
一开始,遇到这样的代码,我用ResHacker手工查找,把资源字符串作为相应代码的注释。这样做效率实在太低,转念一想,干嘛不试试IDC Script,要是能把所有的push nResourceID自动做上注释,无疑能大大增加代码的可读性。
注意:这样做出的注释,可能有一些错误,把与资源访问无关的代码也进行解释。对于Resource ID在10以下的,最好不要用。比如 push 1 的意思可能是 push true。还有一些地方,是在调用new操作符分配内存,也会push一个立即数。不过这种注释错误一般能看出来,还是利大于弊。
我的IDB文件为9MB多,在AMD 1700+上跑1次约5分钟。
几句说明:
1. 用ResHacker打开该DLL,将字符串资源另存到单独的.RC文件中。用Notepad删除资源描
述语句。得到的数据格式如下(test.rc):
0, "test1"
1, "test2"
2, "test3"
...
2. 用FindBinary直接查找push指令的Opcode。当操作数为立即数时,对应的代码有
0x6A,0x68两个。所以写成的Script在执行一次后,修改一下查找字符串再跑一次。
3.从RC文件中取出资源ID,转换为long进行比较,匹配即作注释。
代码如下:
#include <idc.idc>
static main()
{
auto nStartAddr; //起始地址=0x401000
auto nResult; //找到的地址
auto szFile; //
auto hFile;
auto szData;
//RC文件的1行
auto nPos; //
auto szOperandInFile; //RC文件1行的ResourceID部分
auto szComment; //RC文件1行的字符串部分
auto bFound;
auto nOperand; //当前地址的第1个operand
auto nOperandInDataFile; //RC文件1行的ResourceID部分转换出的long值
auto nOperandType; //当前operand类型,5为Immediate
//选择RC文件
szFile=AskFile(0,"*.rc","Select
a data file");
hFile=fopen(szFile,"r");
if(0==hFile)
{
Message("Failed to open the file");
return;
}
nStartAddr=0x401000;
do //扫描IDB的CODE段
{
nResult=FindBinary(nStartAddr,SEARCH_NEXT|SEARCH_DOWN,"6A");
//
//用"68"再做一遍
if(nResult!=BADADDR)
{
nOperandType=GetOpType(nResult,0); //测试operand类型
if(nOperandType==5) //Immediate
{
nOperand=GetOperandvalue(nResult,0);
//在RC文件中搜索
fseek(hFile,0,0);
bFound=0;
do
{
szData=readstr(hFile);
if(szData != -1) //文件尾
{
nPos=strstr(szData,",");
//分成2部分
szOperandInFile=substr(szData,0,nPos);
szComment=substr(szData,nPos+3,-1);
nOperandInDataFile=atol(szOperandInFile);
if(nOperand==nOperandInDataFile) //匹配?
{
Message(form("\nFound
at %X",nResult));
MakeComm(nResult,szComment);
//注释
bFound=1;
//找到则退出do-while
}
}
}while((szData!= -1)&&(bFound==0));
}
}
nStartAddr=NextAddr(nResult); //更新地址
}while((nStartAddr<0x48D000)&&(nResult!=BADADDR)); //在DATA段前结束
fclose(hFile);
Message("\n");
Message(form("%s processed successfully!",szFile));
}