转:虚拟方法跳过父类继承调用祖父类的代码 --值得试一试

网友说是 hack 手段,还没有时间深入了解,不明觉厉。

[沪]风舞轻扬(81924320) 2016-10-25 16:59:08

 

TGrandpaObject = class
public
  procedure AVirtualMethod; virtual;
end;

TParentObject = class(TGrandpaObject)
public
  procedure AVirtualMethod; override;
end;

TCurrentObject = class(TParentObject)
public
  procedure AVirtualMethod; override;
end;

TCurrentObject的AVirtualMethod虚拟方法不希望调用父类TParentObject的AVirtualMethod方法的实现代码,而要直接继承调用祖父类TGrandpaObject的AVirtualMethod方法代码。
类的继承体系中,在VMT中,子类的VMT完全包含父类的VMT,而自身的虚拟方法则是附着在VMT父类虚拟方法表的后面,也就是说子类虚拟方法和父类虚拟方法的相对偏移量是相同的,只是子类的虚拟方法有覆盖时,子类VMT中该虚拟方法的地址被覆盖啦。因此,要跳过父类的虚拟方法而直接调用祖父类的虚拟方法代码,那么只要通过VMT的虚拟方法的相对偏移量找到祖父类的虚拟方法地址,然后调用即可。
procedure TCurrentObject.AVirtualMethod;
begin
  asm
        MOV     EDX,VMTOFFSET AVirtualMethod // 虚拟方法VMT偏移量
        MOV     EAX,Self                     // 对象实例 => EAX
        MOV     ECX,[EAX]                    // 类VMT => ECX
        MOV     ECX,[ECX].vmtParent
        MOV     ECX,[ECX]                    // 父类VMT => ECX
        MOV     ECX,[ECX].vmtParent
        MOV     ECX,[ECX]                    // 祖父类VMT => ECX
        MOV     ECX,[ECX+EDX]                // 祖父类虚拟方法地址 => ECX
        CALL    ECX                          // 方法调用
  end;
end;

 

posted @ 2016-10-26 10:03  海蓝7  阅读(427)  评论(0编辑  收藏  举报