突破C++的虚拟指针--C++程序的缓冲区溢出攻击

    技术2022-05-11  164

    作者:rix (rix@securiweb.net)

    backend注:本文来自Phrack56期的《SMASHING C++ VPTRS》。正如大多数国外黑客的文章,技术原理及应用都讲得比较详细,但所提供的源代码似乎总是会存在不大不小的问题。这也许是因为他们觉得应该让读者自己去研究和调试,以更好地掌握这些技术。或许以后我也会这样做。;)测试环境:  操作系统:Red Hat 6.1 (i386)  内核版本:Kernel 2.2.14  内核补丁:None        Non-executable stack patch (by Solar Design)  C++编译器:gcc  ---[[ 前言 ]]--------------------------------------  到目前为止,我所掌握的缓冲区溢出程序都是针对C编程语言的。虽然C语言编程在UNIX系统中几乎无处不在,但越来越多的C++程序也开始出现了。对于大多数情况,C语言的溢出技术对于C++语言也是适用的,但C++的面向对象的特性也导致了新的缓冲区溢出技术。下面以x86 Linux系统和C++ GNU编译器为平台进行分析。---[[ 基础--简单的C++程序 ]]--------------------------------------  我不愿在这里浪费时间讲解太多的C++语言基础。如果你对C++或面向对象编程技术一无所知,请先找本这方面的书籍看看。在继续往下看之前,请确认你已经掌握或了解以下C++术语:    1、Class(类)  2、Object(对象)  3、Method(方法)  4、Virtual(虚拟)  5、Inherit(继承)  6、Derivative(派生)  接着,把下面的两个程序看完,确认你了解每条语句的含义和作用:  // bo1.cpp// C++基础程序#include <stdio.h>#include <string.h>class MyClass{  private:    char Buffer[32];  public:    void SetBuffer(char *String)    {      strcpy(Buffer, String);    }    void PrintBuffer()    {      printf("%s/n", Buffer);    }};void main(){   MyClass Object;   Object.SetBuffer("string");   Object.PrintBuffer();}===========================================================// bo2.cpp// 有缓冲区溢出漏洞的常见C++程序#include <stdio.h>#include <string.h>class BaseClass{  private:    char Buffer[32];  public:    void SetBuffer(char *String)    {      strcpy(Buffer,String); // 存在缓冲区溢出漏洞    }    virtual void PrintBuffer()    {      printf("%s/n",Buffer);    }};class MyClass1:public BaseClass{  public:    void PrintBuffer()    {      printf("MyClass1: ");      BaseClass::PrintBuffer();    }};class MyClass2:public BaseClass{  public:    void PrintBuffer()    {      printf("MyClass2: ");      BaseClass::PrintBuffer();    }};void main(){  BaseClass *Object[2];  Object[0] = new MyClass1;  Object[1] = new MyClass2;  Object[0]->SetBuffer("string1");  Object[1]->SetBuffer("string2");  Object[0]->PrintBuffer();  Object[1]->PrintBuffer();}  以下是bo2.cpp编译后的运行结果:[backend@isbase test]> ./bo2MyClass1: string1MyClass2: string2[backend@isbase test]>  再一次提醒,在继续往下看时,确信你读懂了上面的程序,特别是对象虚拟(virtual)方法PrintBuffer()。与SetBuffer()方法不同,PrintBuffer方法必须在基类BaseClass的派生类MyClass1和MyClass2中声明并实现。这使得SetBuffer与PrintBuffer方法在运行时的处理会有所不同。---[[ C++的虚拟指针(Virtual PoinTeR,VPTR)]]--------------------------------------  我们知道,虚拟方法与非虚拟方法的一个不同之处是,非虚拟方法的调用是在编译时确定(通常称为“静态绑定”),而虚拟方法的调用却是在程序时确定的(通常称为“动态绑定”)。下面以上例中的BaseClass基类及其派生类为例,对动态绑定的机制做一些解释。  编译器在编译时首先检查BaseClass基类的声明。在本例,编译器首先为私有变量Buffer(字符串型)保留32个字节,接着为非虚拟方法SetBuffer()计算并指定相应的调用地址(静态绑定处理),最后在检查到虚拟方法PrintBuffer()时,将做动态绑定处理,即在类中分配4个字节用以存放该虚拟方法的指针。结构如下:    BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBVVVV说明: B 变量Buffer占用。    V 虚拟方法指针占用。  这个指针通常被称为“VPTR”(Virtual Pointer),它指向一个“VTABLE”结构中的函数入口之一。每一个类都有一个VTABLE。如下图所示:Object[0]: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBVVVV                      =+==            |     +------------------------------+     |     +--> VTABLE_MyClass1: IIIIIIIIIIIIPPPPObject[1]: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBWWWW                      =+==            |     +------------------------------+     |     +--> VTABLE_MyClass2: IIIIIIIIIIIIQQQQ说明: B 变量Buffer占用。    V 指向VTABLE_MyClass1的VPTR指针占用。    W 指向VTABLE_MyClass2的VPTR指针占用。    I 其它用途的数据    P MyClass1对象实例的PrintBuffer()方法的地址指针。    Q MyClass2对象实例的PrintBuffer()方法的地址指针。  我们可以发现,VPTR位于进程内存中Buffer变量之后。即当调用危险的strcpy()函数时有可能覆盖VPTR的内容!    根据rix的研究测试,对于Windows平台上的Visual C++ 6.0,VPTR位于对象的起始位置,因此这里提到的技术无法产生作用。这点与GNU C++有很大的不同。---[[ 剖析VPTR ]]--------------------------------------  在Linux下当然是使用GDB来分析了:[backend@isbase test]> gcc -o bo2 bo2.cpp[backend@isbase test]> gdb bo2GNU gdb 4.18Copyright 1998 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB. Type "show warranty" for details.This GDB was configured as "i386-redhat-linux"...(gdb) disassemble mainDump of assembler code for function main:0x8049400 <main>:    push  

    转载请注明原文地址: https://ibbs.8miu.com/read-1818.html

    最新回复(0)