您的位置:首页 > 其它

[教程]逆向反汇编第六课

2010-11-27 12:43 477 查看
既然要玩逆向,驱动那我们就算不懂但至少要了解下C/C++语言,C++是一门支持OO的语言,对面想对象的软件开发提供了丰富的支持库.但要高效 正确的使用C++中的继承 多态等语言的特性,必须对这些特性性的底层实现有一定得了解.

其实就核心概念而言,C++的对象模型的核心概念并不多,但最核心的是虚函数.虚函数是在程序运行时刻定义的函数,虚函数的地址是不能在编译时刻确定的,它只能在调用即将进行之前加以确定.对所有虚函数引用通常放在一个专用数组--虚函数表中,每个至少使用一个虚函数的对象里面都具有虚函数表指针.虚函数通常通过指向虚函数表的指针间接的加以调用.

将实例的普通成员改编为虚函数调用,来看看VC在虚函数上面是如何处理的.

view plaincopy to clipboardprint?

class CSum

{

public:

virtual int Add(int a,int b)

{

return (a+b);

}

virtual int Sub(int a,int b)

{

return (a-b);

}

};

void main()

{

CSum* pCSum =new CSum;

pCSum->Add(1,2);

pCSum->Sub(1,2);

}

class CSum
{
public:
virtual int Add(int a,int b)
{
return (a+b);
}
virtual int Sub(int a,int b)
{
return (a-b);
}
};
void main()
{
CSum* pCSum =new CSum;
pCSum->Add(1,2);
pCSum->Sub(1,2);
}


这是C的一个简单代码,我们看反汇编后的代码是如何的样式,

view plaincopy to clipboardprint?

push esi

push 4

call 00401060

add esp,4 ;为新建对象实力分配4字节内存

test eax,eax

je short 00401019

mov dword ptr [eax],4050A0 ;将4050A0h写入创建的对象实例中4050A0h是CSum类虚函数表的指针,表中的元素是CSum类的虚函数,他们指向CSum函数的成员

mov esi,eax ;esi是4050A0hCSum类虚函数表的指针

jmp short 0040101B

xor esi,esi ;用NULL指向对象实例指针,该分支在内存分配失败才会来到,空指针将激活SEH

0040101B:

mov eax,dword ptr [esi] ;eax=**Add[]

push 2

push 1

mov ecx,esi ;ecx=this

call dword ptr [eax] ;对虚函数的调用,此时eax=**Add(),也就是CALL 401040

mov edx,dword ptr [esi]

push 2

push 1

mov ecx,esi

call dword ptr [edx+4]

pop esi

retn

push    esi
push    4
call    00401060
add        esp,4            ;为新建对象实力分配4字节内存
test    eax,eax
je        short 00401019
mov        dword ptr [eax],4050A0    ;将4050A0h写入创建的对象实例中4050A0h是CSum类虚函数表的指针,表中的元素是CSum类的虚函数,他们指向CSum函数的成员
mov        esi,eax            ;esi是4050A0hCSum类虚函数表的指针
jmp        short 0040101B
xor        esi,esi            ;用NULL指向对象实例指针,该分支在内存分配失败才会来到,空指针将激活SEH
0040101B:
mov        eax,dword ptr [esi]        ;eax=**Add[]
push    2
push    1
mov        ecx,esi            ;ecx=this
call    dword ptr [eax]            ;对虚函数的调用,此时eax=**Add(),也就是CALL 401040
mov        edx,dword ptr [esi]
push    2
push    1
mov        ecx,esi
call    dword ptr [edx+4]
pop        esi
retn


这段代码首先调用new函数分配class所需内存,调用成功后,eax保存了分配的内存指针,然后将对象实例指向CSum类虚函数表4050A0h.
VTBL里有两组数据
[VTBL]=401040h
[VTBL+4]=401050h

进一步看看这两个指针是什么内容,

;401040h内容如下:Add函数

view plaincopy to clipboardprint?

mov eax,dword ptr [esp+8]

mov ecx,dword ptr [esp+4]

add eax,ecx

retn 8

mov        eax,dword ptr [esp+8]
mov        ecx,dword ptr [esp+4]
add        eax,ecx
retn    8


401050h函数如下:Sub 函数

view plaincopy to clipboardprint?

mov eax,dword ptr [esp+4]

mov ecx,dword ptr [esp+8]

sub eax,ecx

retn 8

mov        eax,dword ptr [esp+4]
mov        ecx,dword ptr [esp+8]
sub        eax,ecx
retn  8


原来虚函数是通过浙西iangxuhanshubiaode指针间接地加以调用的,程序仍然使用ecx作为this指针的载体传递给虚成员函数,并且利用两次间接寻址,得到虚函数的正确地址,从而执行

view plaincopy to clipboardprint?

mov eax,dword ptr [esi] ;eax=*指针=**Add()

push 2

push 1

mov ecx,esi ;ecx=this

call dword ptr [eax]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: