C++中通过溢出覆盖虚函数指针列表执行代码

作者:凯旋网络来源:凯旋网络

1.配置交换机
  将交换机端口配置<!--StartFragment-->目录:=版权所有  软件 下载  学院  版权所有=

  1.  C++中虚函数的静态联编和动态联编
  2.  VC中对象的空间组织和溢出试验
  3.  GCC中对象的空间组织和溢出试验
  4.  参考


<一> C++中虚函数的静态联编和动态联编

      C++中的一大法宝就是虚函数,简单来说就是加virtual要害字定义的函数。
  其特性就是支持动态联编。现在C++开发的大型软件中几乎已经离不开虚函数的
  使用,一个典型的例子就是虚函数是MFC的基石之一。

     这里有两个概念需要先解释:=版权所有  软件 下载  学院  版权所有=

  静态联编:通俗点来讲就是程序编译时确定调用目标的地址。
  动态联编:程序运行阶段确定调用目标的地址。
    
     在C++中通常的函数调用都是静态联编,但假如定义函数时加了virtual要害
  字,并且在调用函数时是通过指针或引用调用,那么此时就是采用动态联编。

      一个简单例子:
// test.cpp
#include<iostream.h>
class ClassA
{
public:
  int num1;
  ClassA(){ num1=0xffff; };
  virtual void test1(void){};
  virtual void test2(void){};
};
ClassA objA,* pobjA;

int main(void)
{
  pobjA=&objA;
  objA.test1();
  objA.test2();
  pobjA->test1();
  pobjA->test2();
  return 0;
}



 
使用VC编译:
开一个命令行直接在命令行调用cl来编译: (假如你安装vc时没有选择注册环境
变量,那么先在命令行运行VC目录下bin\VCVARS32.BAT )

cl test.cpp /Fa
产生test.asm中间汇编代码

接下来就看看asm里有什么玄虚,分析起来有点长,要有耐心 !

我们来看看:

数据定义:

_BSS    SEGMENT
?objA@@3VClassA@@A DQ 01H DUP (?)    ;objA  64位
?pobjA@@3PAVClassA@@A DD 01H DUP (?) ;pobjA 一个地址32位
_BSS    ENDS

看到objA为64位,里边存放了哪些内容呢? 接着看看构造函数:

_this$ = -4
??0ClassA@@QAE@XZ PROC NEAR ; ClassA::ClassA() 定义了一个变量 _this ?!
; File test.cpp
; Line 6
    push    ebp
    mov    ebp, esp
    push    ecx
    mov    DWord PTR _this$[ebp], ecx  ; ecx 赋值给 _this ?? 不明白??

    mov    eax, DWORD PTR _this$[ebp]
    mov    DWORD PTR [eax], OFFSET FLAT:??_7ClassA@@6B@
           ; ClassA::`vftable''

; 前面的部分都是编译器加的东东,我们的赋值在这里

    mov    ecx, DWORD PTR _this$[ebp]
    mov    DWORD PTR [ecx+4], 65535   ;0xffff  num1=0xffff;
; 看来 _this+4就是num1的地址

    mov    eax, DWORD PTR _this$[ebp]
    mov    esp, ebp
    pop    ebp
    ret    0
??0ClassA@@QAE@XZ ENDP

那个_this和mov    DWORD PTR _this$[ebp], ecx 让人比较郁闷了吧,不急看看何
处调用的构造函数
  • 广告推荐