⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 csdn_文档中心_突破c++的虚拟指针--c++程序的缓冲区溢出攻击.htm

📁 csdn10年中间经典帖子
💻 HTM
📖 第 1 页 / 共 5 页
字号:
			document.write(".");
			document.write(month);
			document.write(".");
			document.write(date);
			// -->
			</SCRIPT>
      </B>&nbsp;&nbsp;</TD></TR>
  <TR bgColor=#999999>
    <TD colSpan=3 height=1></TD></TR></TBODY></TABLE>
<TABLE border=0 width=770>
  <TBODY>
  <TR>
    <TD align=middle bgColor=#fafafa class=td1 vAlign=top width=150><BR>
      <SCRIPT 
      src="CSDN_文档中心_突破C++的虚拟指针--C++程序的缓冲区溢出攻击.files/microsoft.js"></SCRIPT>
    </TD>
    <TD align=middle width=620>
      <TABLE bgColor=#eeeeee border=0 cellPadding=0 cellSpacing=0 width=600>
        <TBODY>
        <TR bgColor=#ffffff>
          <TD align=middle height=10 width=50></TD>
          <TD align=right><A href="http://www.csdn.net/">CSDN</A> - <A 
            href="http://www.csdn.net/develop/">文档中心</A> - <FONT 
            color=#003399>Visual C++</FONT>&nbsp;&nbsp;&nbsp;&nbsp; </TD></TR>
        <TR>
          <TD align=middle height=5></TD>
          <TD align=middle width=500></TD></TR>
        <TR>
          <TD align=middle bgColor=#003399 height=10><FONT 
            color=#ffffff>标题</FONT></TD>
          <TD><B>&nbsp;&nbsp;&nbsp;&nbsp;突破C++的虚拟指针--C++程序的缓冲区溢出攻击</B>&nbsp;&nbsp;&nbsp;&nbsp;ghj1976(转贴) 
          </TD></TR>
        <TR>
          <TD align=middle height=5></TD>
          <TD align=middle width=500></TD></TR>
        <TR>
          <TD align=middle bgColor=#003399><FONT color=#ffffff>关键字</FONT></TD>
          <TD 
width=500>&nbsp;&nbsp;&nbsp;&nbsp;突破C++的虚拟指针--C++程序的缓冲区溢出攻击</TD></TR>
        <TR>
          <TD align=middle height=5></TD>
          <TD align=middle width=500></TD></TR>
        <TR>
          <TD align=middle bgColor=#003399 height=10><FONT 
            color=#ffffff>出处</FONT></TD>
          <TD height=10>&nbsp;&nbsp;&nbsp;&nbsp;<A 
            href="http://www.isbase.com/">http://www.isbase.com/</A></TD></TR>
        <TR>
          <TD align=middle height=10></TD>
          <TD height=10></TD></TR></TBODY></TABLE><!--文章说明信息结束//-->
      <TABLE border=0 width=600>
        <TBODY>
        <TR>
          <TD align=left><BR>
            <P><BR><BR>作者:rix (<A 
            href="mailto:rix@securiweb.net">rix@securiweb.net</A>)<BR></P>
            <P><BR>backend注:本文来自Phrack56期的《SMASHING C++ 
            VPTRS》。正如大多数国外黑客的文章,技术原理及应用都讲得比较详细,但所提供的源代码似乎总是会存在不大不小的问题。这也许是因为他们觉得应该让读者自己去研究和调试,以更好地掌握这些技术。或许以后我也会这样做。;)<BR><BR>测试环境:<BR><BR>  操作系统:Red 
            Hat 6.1 (i386)<BR>  内核版本:Kernel 
            2.2.14<BR>  内核补丁:None       &nbsp;Non-executable stack patch (by 
            Solar Design)<BR>  C++编译器:gcc<BR>  <BR><BR>---[[ 前言 
            ]]--------------------------------------<BR><BR>  到目前为止,我所掌握的缓冲区溢出程序都是针对C编程语言的。虽然C语言编程在UNIX系统中几乎无处不在,但越来越多的C++程序也开始出现了。对于大多数情况,C语言的溢出技术对于C++语言也是适用的,但C++的面向对象的特性也导致了新的缓冲区溢出技术。下面以x86 
            Linux系统和C++ GNU编译器为平台进行分析。<BR><BR><BR>---[[ 基础--简单的C++程序 
            ]]--------------------------------------<BR><BR>  我不愿在这里浪费时间讲解太多的C++语言基础。如果你对C++或面向对象编程技术一无所知,请先找本这方面的书籍看看。在继续往下看之前,请确认你已经掌握或了解以下C++术语:<BR>  <BR>  1、Class(类)<BR>  2、Object(对象)<BR>  3、Method(方法)<BR>  4、Virtual(虚拟)<BR>  5、Inherit(继承)<BR>  6、Derivative(派生)<BR><BR>  接着,把下面的两个程序看完,确认你了解每条语句的含义和作用:<BR>  <BR>// 
            bo1.cpp<BR>// C++基础程序<BR><BR>#include &lt;stdio.h&gt;<BR>#include 
            &lt;string.h&gt;<BR><BR>class MyClass<BR>{<BR>  private:<BR>    char 
            Buffer[32];<BR>  public:<BR>    void SetBuffer(char 
            *String)<BR>    {<BR>      strcpy(Buffer, 
            String);<BR>    }<BR>    void 
            PrintBuffer()<BR>    {<BR>      printf("%s\n", 
            Buffer);<BR>    }<BR>};<BR><BR>void main()<BR>{<BR>  &nbsp;MyClass 
            Object;<BR><BR>  &nbsp;Object.SetBuffer("string");<BR>  &nbsp;Object.PrintBuffer();<BR>}<BR><BR>===========================================================<BR><BR>// 
            bo2.cpp<BR>// 有缓冲区溢出漏洞的常见C++程序<BR><BR>#include 
            &lt;stdio.h&gt;<BR>#include &lt;string.h&gt;<BR><BR>class 
            BaseClass<BR>{<BR>  private:<BR>    char 
            Buffer[32];<BR>  public:<BR>    void SetBuffer(char 
            *String)<BR>    {<BR>      strcpy(Buffer,String); // 
            存在缓冲区溢出漏洞<BR>    }<BR>    virtual void 
            PrintBuffer()<BR>    {<BR>      printf("%s\n",Buffer);<BR>    }<BR>};<BR><BR>class 
            MyClass1:public BaseClass<BR>{<BR>  public:<BR>    void 
            PrintBuffer()<BR>    {<BR>      printf("MyClass1: 
            ");<BR>      BaseClass::PrintBuffer();<BR>    }<BR>};<BR><BR>class 
            MyClass2:public BaseClass<BR>{<BR>  public:<BR>    void 
            PrintBuffer()<BR>    {<BR>      printf("MyClass2: 
            ");<BR>      BaseClass::PrintBuffer();<BR>    }<BR>};<BR><BR>void 
            main()<BR>{<BR>  BaseClass *Object[2];<BR><BR>  Object[0] = new 
            MyClass1;<BR>  Object[1] = new 
            MyClass2;<BR><BR>  Object[0]-&gt;SetBuffer("string1");<BR>  Object[1]-&gt;SetBuffer("string2");<BR>  Object[0]-&gt;PrintBuffer();<BR>  Object[1]-&gt;PrintBuffer();<BR>}<BR><BR>  以下是bo2.cpp编译后的运行结果:<BR><BR>[backend@isbase 
            test]&gt; ./bo2<BR>MyClass1: string1<BR>MyClass2: 
            string2<BR>[backend@isbase 
            test]&gt;<BR><BR>  再一次提醒,在继续往下看时,确信你读懂了上面的程序,特别是对象虚拟(virtual)方法PrintBuffer()。与SetBuffer()方法不同,PrintBuffer方法必须在基类BaseClass的派生类MyClass1和MyClass2中声明并实现。这使得SetBuffer与PrintBuffer方法在运行时的处理会有所不同。<BR><BR><BR>---[[ 
            C++的虚拟指针(Virtual 
            PoinTeR,VPTR)]]--------------------------------------<BR><BR>  我们知道,虚拟方法与非虚拟方法的一个不同之处是,非虚拟方法的调用是在编译时确定(通常称为“静态绑定”),而虚拟方法的调用却是在程序时确定的(通常称为“动态绑定”)。下面以上例中的BaseClass基类及其派生类为例,对动态绑定的机制做一些解释。<BR><BR>  编译器在编译时首先检查BaseClass基类的声明。在本例,编译器首先为私有变量Buffer(字符串型)保留32个字节,接着为非虚拟方法SetBuffer()计算并指定相应的调用地址(静态绑定处理),最后在检查到虚拟方法PrintBuffer()时,将做动态绑定处理,即在类中分配4个字节用以存放该虚拟方法的指针。结构如下:<BR><BR>    BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBVVVV<BR><BR>说明: 
            B 变量Buffer占用。<BR>   &nbsp;V 
            虚拟方法指针占用。<BR><BR>  这个指针通常被称为“VPTR”(Virtual 
            Pointer),它指向一个“VTABLE”结构中的函数入口之一。每一个类都有一个VTABLE。如下图所示:<BR><BR>Object[0]: 
            BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBVVVV<BR>                     &nbsp;=+==<BR>            |<BR>    &nbsp;+------------------------------+<BR>    &nbsp;|<BR>    &nbsp;+--&gt; 
            VTABLE_MyClass1: IIIIIIIIIIIIPPPP<BR><BR>Object[1]: 
            BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBWWWW<BR>                     &nbsp;=+==<BR>            |<BR>    &nbsp;+------------------------------+<BR>    &nbsp;|<BR>    &nbsp;+--&gt; 
            VTABLE_MyClass2: IIIIIIIIIIIIQQQQ<BR><BR>说明: B 
            变量Buffer占用。<BR>   &nbsp;V 指向VTABLE_MyClass1的VPTR指针占用。<BR>   &nbsp;W 
            指向VTABLE_MyClass2的VPTR指针占用。<BR>   &nbsp;I 其它用途的数据<BR>   &nbsp;P 
            MyClass1对象实例的PrintBuffer()方法的地址指针。<BR>   &nbsp;Q 
            MyClass2对象实例的PrintBuffer()方法的地址指针。<BR><BR>  我们可以发现,VPTR位于进程内存中Buffer变量之后。即当调用危险的strcpy()函数时有可能覆盖VPTR的内容!<BR>  <BR>  根据rix的研究测试,对于Windows平台上的Visual 
            C++ 6.0,VPTR位于对象的起始位置,因此这里提到的技术无法产生作用。这点与GNU 
            C++有很大的不同。<BR><BR><BR>---[[ 剖析VPTR 
            ]]--------------------------------------<BR><BR>  在Linux下当然是使用GDB来分析了:<BR><BR>[backend@isbase 
            test]&gt; gcc -o bo2 bo2.cpp<BR>[backend@isbase test]&gt; gdb 
            bo2<BR>GNU gdb 4.18<BR>Copyright 1998 Free Software Foundation, 
            Inc.<BR>GDB is free software, covered by the GNU General Public 
            License, and you are<BR>welcome to change it and/or distribute 
            copies of it under certain conditions.<BR>Type "show copying" to see 
            the conditions.<BR>There is absolutely no warranty for GDB. Type 
            "show warranty" for details.<BR>This GDB was configured as 
            "i386-redhat-linux"...<BR>(gdb) disassemble main<BR>Dump of 
            assembler code for function main:<BR>0x8049400 
            &lt;main&gt;:   &nbsp;push &nbsp;%ebp<BR>0x8049401 
            &lt;main+1&gt;:  &nbsp;mov  %esp,%ebp<BR>0x8049403 
            &lt;main+3&gt;:  &nbsp;sub  $0x8,%esp<BR>0x8049406 
            &lt;main+6&gt;:  &nbsp;push &nbsp;%edi<BR>0x8049407 
            &lt;main+7&gt;:  &nbsp;push &nbsp;%esi<BR>0x8049408 
            &lt;main+8&gt;:  &nbsp;push &nbsp;%ebx<BR>0x8049409 
            &lt;main+9&gt;:  &nbsp;push &nbsp;$0x24<BR>0x804940b 
            &lt;main+11&gt;:  call &nbsp;0x804b580 
            &lt;__builtin_new&gt;<BR>0x8049410 
            &lt;main+16&gt;:  add  $0x4,%esp<BR>0x8049413 
            &lt;main+19&gt;:  mov  %eax,%eax<BR>0x8049415 
            &lt;main+21&gt;:  mov  %eax,%ebx<BR>0x8049417 
            &lt;main+23&gt;:  push &nbsp;%ebx<BR>0x8049418 
            &lt;main+24&gt;:  call &nbsp;0x804c90c 
            &lt;__8MyClass1&gt;<BR>0x804941d 
            &lt;main+29&gt;:  add  $0x4,%esp<BR>0x8049420 
            &lt;main+32&gt;:  mov  %eax,%esi<BR>0x8049422 
            &lt;main+34&gt;:  jmp  0x8049430 &lt;main+48&gt;<BR>0x8049424 
            &lt;main+36&gt;:  call &nbsp;0x8049c3c &lt;__throw&gt;<BR>0x8049429 
            &lt;main+41&gt;:  lea  0x0(%esi,1),%esi<BR>0x8049430 
            &lt;main+48&gt;:  mov  %esi,0xfffffff8(%ebp)<BR>0x8049433 
            &lt;main+51&gt;:  push &nbsp;$0x24<BR>0x8049435 
            &lt;main+53&gt;:  call &nbsp;0x804b580 
            &lt;__builtin_new&gt;<BR>0x804943a 
            &lt;main+58&gt;:  add  $0x4,%esp<BR>0x804943d 
            &lt;main+61&gt;:  mov  %eax,%eax<BR>0x804943f 
            &lt;main+63&gt;:  mov  %eax,%esi<BR>0x8049441 
            &lt;main+65&gt;:  push &nbsp;%esi<BR>0x8049442 
            &lt;main+66&gt;:  call &nbsp;0x804c8ec 
            &lt;__8MyClass2&gt;<BR>0x8049447 
            &lt;main+71&gt;:  add  $0x4,%esp<BR>0x804944a 
            &lt;main+74&gt;:  mov  %eax,%edi<BR>0x804944c 
            &lt;main+76&gt;:  jmp  0x8049455 &lt;main+85&gt;<BR>0x804944e 
            &lt;main+78&gt;:  mov  %esi,%esi<BR>0x8049450 
            &lt;main+80&gt;:  call &nbsp;0x8049c3c &lt;__throw&gt;<BR>0x8049455 
            &lt;main+85&gt;:  mov  %edi,0xfffffffc(%ebp)<BR>0x8049458 
            &lt;main+88&gt;:  push &nbsp;$0x804cda2<BR>0x804945d 
            &lt;main+93&gt;:  mov  0xfffffff8(%ebp),%eax<BR>0x8049460 
            &lt;main+96&gt;:  push &nbsp;%eax<BR>0x8049461 
            &lt;main+97&gt;:  call &nbsp;0x804c930 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -