C ++黑客类简析

来源:互联网 发布:https是哪个端口 编辑:程序博客网 时间:2024/06/04 19:32

今天无意中在CSDN上看到一篇文章,名叫 C++语言的“黑客类”行为简析。全文链接地址为:http://student.csdn.net/space.php?uid=112600&do=blog&id=6424。看了以后,发现作者最后给出的一段代码有点迷惑,于是copy到VS里面,产生并分析了一下汇编代码,得到一些结论。

      作者给出的代码参照以上链接,我要说的是 pfunc(&o); 这一句,似乎作者的意思是把o对象的地址保存下来,当成this指针,以便调用pfunc的时候,访问到数据成员d。但实际上作者给出的代码,虽然可以调用到私有成员 foo函数,但访问的数据却是错误的,因为没有正确设置 this指针,所以程序运行后输出的数据是一个很大的数字,而不是100。下面是我改进后的代码:

 Coo o;  
 int *p = (int *)(&o); 
 int addr = *(int *)(*p);      

 typedef void (* PFUNC)();  
 PFUNC pfunc = (PFUNC)(addr);  
 __asm MOV ECX,p
 pfunc();   

为什么要这么改呢!我把作者的Coo*参数去掉了,因为作者的方法,不论加不加这个参数,程序运行结果都是一样的。我只是在pfunc()调用之前,加了一条嵌入汇编指令。原因如下:

; 28   :  Coo o;  

  0001e 8d 4d f4  lea  ecx, DWORD PTR _o$[ebp]
  00021 e8 00 00 00 00  call  ??0Coo@@QAE@XZ  ; Coo::Coo

以上是构造o对象时的汇编代码,可以看到,编译器做的操作是先把对象o的地址存入ECX寄存器,然后再调用Coo类的构造函数。这也是任何类的非静态成员函数的调用方法,也就是this指针的实现方式。

所以我作上面的修改的原因很明显:由于pfunc是通过强制的方法进行转换得到的foo函数地址,所以对它进行调用,编译器显然不知道要保存 this指针。这里用手动的方法去实现。可以看到程序运行后,输出的数字正是d 的值100了。

 

结论:任何类如果存在私有的虚成员函数,可以通过上面的方法打破这种语法上的限制,调用到私有成员函数。当然因为非虚成员函数没有一个虚函数表来找到其地址,所以也就无法实现这样的调用操作了。

原创粉丝点击