能力值:
( LV12,RANK:450 )
|
-
-
2 楼
哦,刚看了一下,VTBL主要是在rdata段中.一会再研究一下看有没有什么规律,直接从rdata段开始在idapro中手动浏览好象也不是特别费劲.
|
能力值:
( LV4,RANK:50 )
|
-
-
3 楼
不大清楚,刚才逆向了VC的Dialog看看,如果要找窗口的CDialog类的话,只要在IDA的字符串中搜索 "CDialog",然后取两次引用,就会看到这样的表
.rdata:100356F0 CDlgBasic dd offset ClassName ; DATA XREF: sub_10001700+2Do
.rdata:100356F4 dd offset sub_10001750
.rdata:100356F8 dd offset nullsub_11
.rdata:100356FC dd offset sub_1002C945
.rdata:10035700 dd offset sub_1002DED0
.rdata:10035704 dd offset sub_1002C5C4
.rdata:10035708 dd offset sub_1002ECC4
.rdata:1003570C dd offset sub_1002C5CA
.rdata:10035710 dd offset sub_1002C5CA
.rdata:10035714 dd offset sub_1002C5CD
.rdata:10035718 dd offset sub_10001800
.rdata:1003571C dd offset sub_1002C653
.rdata:10035720 dd offset sub_1002C605
.rdata:10035724 dd offset sub_1002C64D
.rdata:10035728 dd offset sub_1002C611
.rdata:1003572C dd offset sub_1002C60B
.rdata:10035730 dd offset sub_1002C649
.rdata:10035734 dd offset sub_1002ECC4
.rdata:10035738 dd offset sub_1002ECC4
.rdata:1003573C dd offset sub_1002ECC4
.rdata:10035740 dd offset nullsub_4
.rdata:10035744 dd offset sub_1002DCD7
.rdata:10035748 dd offset sub_1002DEE1
.rdata:1003574C dd offset sub_1002DCB7
.rdata:10035750 dd offset sub_1002ECC9
.rdata:10035754 dd offset sub_1002DFEF
.rdata:10035758 dd offset sub_1002ECC4
.rdata:1003575C dd offset sub_1002E2D4
.rdata:10035760 dd offset sub_1002F81B
.rdata:10035764 dd offset sub_1002F822
.rdata:10035768 dd offset sub_1002E9DC
.rdata:1003576C dd offset sub_1002EA68
.rdata:10035770 dd offset sub_1002DF75
.rdata:10035774 dd offset sub_100017A0
.rdata:10035778 dd offset sub_100016E0
.rdata:1003577C dd offset sub_100016F0
.rdata:10035780 dd offset sub_1002C8AC
.rdata:10035784 dd offset sub_1002FC26
.rdata:10035788 dd offset sub_1002E3FC
.rdata:1003578C dd offset sub_1002E440
.rdata:10035790 dd offset sub_1002DF2E
.rdata:10035794 dd offset nullsub_4
.rdata:10035798 dd offset sub_1002EE07
.rdata:1003579C dd offset sub_1002D0BB
.rdata:100357A0 dd offset sub_1002C5CA
.rdata:100357A4 dd offset sub_1002CCEE
.rdata:100357A8 dd offset sub_1002CDB0
.rdata:100357AC dd offset OnInitDialog
.rdata:100357B0 dd offset nullsub_12
.rdata:100357B4 dd offset sub_1002D09A
.rdata:100357B8 dd offset sub_1002D0B3
ClassName 就是指向CDialog的类名,下边大多数是CDialog类继承来的成员,自己写的成员函数一般在该表的最下边
|
能力值:
( LV12,RANK:450 )
|
-
-
4 楼
这样可以通过类名来查找的应该是加了RTTI编译的吧,一般的程序好象加RTTI信息的不多.
|
能力值:
( LV12,RANK:450 )
|
-
-
5 楼
我写了一个IDC脚本,用于将rdata段中可能的vtbl写到一个文件中,每个vtbl的开始以@标注,脚本内容如下:(idapro4.9的SegByName函数有BUG,或者是根本没实现,返回总是0xffffffff,只好遍历搜索了)
auto s,a,e,fp,i,name,lastIsNull;
a=FirstSeg();
s=SegName(a);
while(s!=".rdata")
{
a=NextSeg(a);
s=SegName(a);
}
e=NextSeg(a);
Message("找到.rdata段:%8.8X-%8.8X,现在开始将其中可能的VTBL写入文件...\r\n",a,e);
lastIsNull=1;
fp=fopen("c:\\vtbl.txt","w");
for(i=a;i<e;)
{
s=GetDisasm(i);
if(strstr(s,"dd offset")>=0)
{
name=Name(i);
if(name!="")
{
writestr(fp,form("@ %s\r\n",s));
}
else
{
writestr(fp,form(" %s\r\n",s));
}
lastIsNull=0;
}
else if(!lastIsNull)
{
writestr(fp,"\r\n");
lastIsNull=1;
}
i=FindData(i,1);
}
fclose(fp);
Message("文件构造完毕!\r\n");
这样子先截出VTBL来了,然后再想办法分析继承关系了,我现在的想法是比较各个VTBL的函数地址,然后按vtbl长度排序,有公共函数的vtbl可认为是一个簇的类,vtbl尺寸越小的越可能是基类,同样尺寸的按函数被引用次数递减排序,引用次数多的是基类的可能性大.这个工作手工做有点费劲,得再写脚本了(不过idc脚本的功能有点弱,得换别的脚本做这些分析了).
|
能力值:
( LV9,RANK:170 )
|
-
-
6 楼
《Hacker.Disassembling》
好像对面向对象的程序反汇编有比较深入的研究
|
能力值:
( LV4,RANK:50 )
|
-
-
7 楼
好象这句很特别
mov dword ptr [esi], offset CDlgBasic
我看VC的类都是这样放进去的
“.rdata:100356F0 CDlgBasic dd offset ClassName ; DATA XREF: sub_10001700+2Do
.rdata:100356F4 dd offset sub_10001750
.rdata:100356F8 dd offset nullsub_11
.rdata:100356FC dd offset sub_1002C945”
|
能力值:
( LV12,RANK:450 )
|
-
-
8 楼
呵呵,突然想起MFC从VC4.0起不再使用RTTI了,它使用的CRuntimeClass的第一个成员就是指向类名的指针.
不过你列出的列表与使用RTTI的C++类的虚函数表布局特别相似,不知道是怎么回事了.
|
能力值:
( LV12,RANK:450 )
|
-
-
9 楼
《Hacker.Disassembling》
这书在哪儿能找到?
刚从网上搜到了,谢谢了.
|
能力值:
( LV4,RANK:50 )
|
-
-
10 楼
最初由 dreaman 发布 呵呵,突然想起MFC从VC4.0起不再使用RTTI了,它使用的CRuntimeClass的第一个成员就是指向类名的指针. 不过你列出的列表与使用RTTI的C++类的虚函数表布局特别相似,不知道是怎么回事了.
追述到CDialog的祖宗类CObject,第一个成员CRuntimeClass指针就是指向类名。 我帖出的那段是用VC6建立的Dialog based窗口,逆向出来后看到就是这样了,列表下边大多数是CDialog类继承来的成员,一路一路的排下来,如果再在此CDialog类中添加虚函数的话,就会继续往那列表下边加偏移地址
|
能力值:
( LV12,RANK:450 )
|
-
-
11 楼
如果不是CObject继承的类,应该就没有类名这样的信息了.那样就不太好分析了.
(晕倒,我今天的发贴数居然满了,只能在这个贴里发了.)
|
能力值:
( LV12,RANK:450 )
|
-
-
12 楼
昨天研究了一下idapro 4.9的SDK,没想到IDC脚本的内部函数可以很方便的直接调用,所以就顺便写了一个用DHTML作脚本的idapro 4.9插件 IdaHTML,直接将IDC脚本的内部函数用作DHTML的API了,之后我重写了一下取VTBL的代码,这回是用javascript,写完才发觉,IDC的语法与javascript咋就那么像呢:)(c系语言真的太相似了!)
var s,a,e,fp,i,name,lastIsNull;
a=app.FirstSeg();
s=app.SegName(a);
while(s!=".rdata")
{
a=app.NextSeg(a);
s=app.SegName(a);
}
e=app.NextSeg(a);
app.Message("找到.rdata段:%8.8X-%8.8X,现在开始将其中可能的VTBL写入文件...\r\n",a,e);
lastIsNull=1;
fp=app.fopen("c:\\vtbl.txt","w");
for(i=a;i<e;)
{
s=app.GetDisasm(i);
if(app.strstr(s,"dd offset")>=0)
{
//取出VTBL中的一项,查看是否函数
var v=app.Dword(i);
var f=app.GetFlags(v);
//查看是否有名称,有名称的表明有被引用,可能是VTBL的开始
name=app.Name(i);
if(typeof(name)=="string" && name!="")//如果是RTTI或MFC动态类,则第一项可能不是函数
{
app.writestr(fp,app.form("@ %s\r\n",s));
lastIsNull=0;
}
else if((f& MS_CLS)==FF_CODE)
{
app.writestr(fp,app.form(" %s\r\n",s));
lastIsNull=0;
}
else if(!lastIsNull)
{
app.writestr(fp,"\r\n");
lastIsNull=1;
}
}
else if(!lastIsNull)
{
app.writestr(fp,"\r\n");
lastIsNull=1;
}
i=app.ItemEnd(i);/*app.FindData(i,1); */
}
app.fclose(fp);
app.Message("文件构造完毕!\r\n");
修改了一下,有BUG.
|
能力值:
( LV12,RANK:450 )
|
-
-
13 楼
晕倒,今天的发贴机会又用完了.
呵呵,接下来的打算:
1、基于VTBL写分析类簇的脚本;
2、分析各个虚函数间的交叉引用;
3、绘制虚函数间的调用关系图;
4、绘制类的继承关系图。
巨晕!在分析函数间调用关系时idapro不响应了,突然意识到函数太多了,看了一下列表,4500多个函数,如果每个函数200行汇编码,则需要检查4500*200次,每次检查需要调五六个API函数外加一次5以内循环,性能问题严重了。
|
能力值:
( LV2,RANK:10 )
|
-
-
14 楼
有两种情况:
1\当程序new一个对象时,在调用虚函数时,一般在ECX中传递一个对象的指针,然后出现call [ecx+xxx]时,就是在调用某个虚函数了.
2\当程序在堆栈中建立对象时,对象就是一个局部变量,在CALL这种对象的虚函数之前,一定会LEA到ECX这个局部变量.
|