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

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

📁 csdn10年中间经典帖子
💻 HTM
📖 第 1 页 / 共 5 页
字号:
            &lt;SetBuffer__9BaseClassPc&gt;<BR>0x8049466 
            &lt;main+102&gt;: &nbsp;add  $0x8,%esp<BR>0x8049469 
            &lt;main+105&gt;: &nbsp;push &nbsp;$0x804cdaa<BR>---Type 
            &lt;return&gt; to continue, or q &lt;return&gt; to 
            quit---<BR>0x804946e 
            &lt;main+110&gt;: &nbsp;mov  0xfffffffc(%ebp),%eax<BR>0x8049471 
            &lt;main+113&gt;: &nbsp;push &nbsp;%eax<BR>0x8049472 
            &lt;main+114&gt;: &nbsp;call &nbsp;0x804c930 
            &lt;SetBuffer__9BaseClassPc&gt;<BR>0x8049477 
            &lt;main+119&gt;: &nbsp;add  $0x8,%esp<BR>0x804947a 
            &lt;main+122&gt;: &nbsp;mov  0xfffffff8(%ebp),%edx<BR>0x804947d 
            &lt;main+125&gt;: &nbsp;mov  0x20(%edx),%eax<BR>0x8049480 
            &lt;main+128&gt;: &nbsp;add  $0x8,%eax<BR>0x8049483 
            &lt;main+131&gt;: &nbsp;mov  0xfffffff8(%ebp),%edx<BR>0x8049486 
            &lt;main+134&gt;: &nbsp;push &nbsp;%edx<BR>0x8049487 
            &lt;main+135&gt;: &nbsp;mov  (%eax),%edi<BR>0x8049489 
            &lt;main+137&gt;: &nbsp;call &nbsp;*%edi<BR>0x804948b 
            &lt;main+139&gt;: &nbsp;add  $0x4,%esp<BR>0x804948e 
            &lt;main+142&gt;: &nbsp;mov  0xfffffffc(%ebp),%edx<BR>0x8049491 
            &lt;main+145&gt;: &nbsp;mov  0x20(%edx),%eax<BR>0x8049494 
            &lt;main+148&gt;: &nbsp;add  $0x8,%eax<BR>0x8049497 
            &lt;main+151&gt;: &nbsp;mov  0xfffffffc(%ebp),%edx<BR>0x804949a 
            &lt;main+154&gt;: &nbsp;push &nbsp;%edx<BR>0x804949b 
            &lt;main+155&gt;: &nbsp;mov  (%eax),%edi<BR>0x804949d 
            &lt;main+157&gt;: &nbsp;call &nbsp;*%edi<BR>0x804949f 
            &lt;main+159&gt;: &nbsp;add  $0x4,%esp<BR>0x80494a2 
            &lt;main+162&gt;: &nbsp;xor  %eax,%eax<BR>0x80494a4 
            &lt;main+164&gt;: &nbsp;jmp  0x80494d0 &lt;main+208&gt;<BR>0x80494a6 
            &lt;main+166&gt;: &nbsp;jmp  0x80494d0 &lt;main+208&gt;<BR>0x80494a8 
            &lt;main+168&gt;: &nbsp;push &nbsp;%ebx<BR>0x80494a9 
            &lt;main+169&gt;: &nbsp;call &nbsp;0x804b4f0 
            &lt;__builtin_delete&gt;<BR>0x80494ae 
            &lt;main+174&gt;: &nbsp;add  $0x4,%esp<BR>0x80494b1 
            &lt;main+177&gt;: &nbsp;jmp  0x8049424 &lt;main+36&gt;<BR>0x80494b6 
            &lt;main+182&gt;: &nbsp;push &nbsp;%esi<BR>0x80494b7 
            &lt;main+183&gt;: &nbsp;call &nbsp;0x804b4f0 
            &lt;__builtin_delete&gt;<BR>0x80494bc 
            &lt;main+188&gt;: &nbsp;add  $0x4,%esp<BR>0x80494bf 
            &lt;main+191&gt;: &nbsp;jmp  0x8049450 &lt;main+80&gt;<BR>0x80494c1 
            &lt;main+193&gt;: &nbsp;jmp  0x80494c8 &lt;main+200&gt;<BR>0x80494c3 
            &lt;main+195&gt;: &nbsp;call &nbsp;0x8049c3c 
            &lt;__throw&gt;<BR>0x80494c8 
            &lt;main+200&gt;: &nbsp;call &nbsp;0x8049fc0 
            &lt;terminate__Fv&gt;<BR>0x80494cd 
            &lt;main+205&gt;: &nbsp;lea  0x0(%esi),%esi<BR>0x80494d0 
            &lt;main+208&gt;: &nbsp;lea  0xffffffec(%ebp),%esp<BR>0x80494d3 
            &lt;main+211&gt;: &nbsp;pop  %ebx<BR>0x80494d4 
            &lt;main+212&gt;: &nbsp;pop  %esi<BR>0x80494d5 
            &lt;main+213&gt;: &nbsp;pop  %edi<BR>---Type &lt;return&gt; to 
            continue, or q &lt;return&gt; to quit---<BR>0x80494d6 
            &lt;main+214&gt;: &nbsp;leave <BR>0x80494d7 
            &lt;main+215&gt;: &nbsp;ret  <BR>0x80494d8 
            &lt;main+216&gt;: &nbsp;nop  <BR>0x80494d9 
            &lt;main+217&gt;: &nbsp;nop  <BR>0x80494da 
            &lt;main+218&gt;: &nbsp;nop  <BR>0x80494db 
            &lt;main+219&gt;: &nbsp;nop  <BR>0x80494dc 
            &lt;main+220&gt;: &nbsp;nop  <BR>0x80494dd 
            &lt;main+221&gt;: &nbsp;nop  <BR>0x80494de 
            &lt;main+222&gt;: &nbsp;nop  <BR>0x80494df 
            &lt;main+223&gt;: &nbsp;nop  <BR>End of assembler 
            dump.<BR>(gdb)<BR><BR>  以下是对该程序汇编代码的解释:<BR><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><BR>  构建堆栈。为Object[]数组保留8个字节(即两个4字节指针地址),则Object[0]的指针存放在0xfffffff8(%ebp),Object[1]的指针存放在0fffffffc(%ebp)。接着保存寄存器。<BR><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><BR>  首先调用__builtin_new,在堆(heap)中分配0x24(36字节)给Object[0],并将其首地址保存到EAX寄存器中。这36字节中前32字节是Buffer变量的,后4字节由VPTR占用。<BR><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><BR>  将对象的首地址压栈,然后调用__8MyClass1函数。这其实是MyClass1对象的构造函数(constructor)。<BR><BR>(gdb) 
            disassemble __8MyClass1<BR>Dump of assembler code for function 
            __8MyClass1:<BR>0x804c90c 
            &lt;__8MyClass1&gt;:    push &nbsp;%ebp<BR>0x804c90d 
            &lt;__8MyClass1+1&gt;:   mov  %esp,%ebp<BR>0x804c90f 
            &lt;__8MyClass1+3&gt;:   push &nbsp;%ebx<BR>0x804c910 
            &lt;__8MyClass1+4&gt;:   mov  0x8(%ebp),%ebx<BR><BR>  寄存器EBX现在存放着指向分配的36个字节的指针(在C++语言中,称之为"This"指针)。<BR><BR>0x804c913 
            &lt;__8MyClass1+7&gt;:   push &nbsp;%ebx<BR>0x804c914 
            &lt;__8MyClass1+8&gt;:   call &nbsp;0x804c958 
            &lt;__9BaseClass&gt;<BR>0x804c919 
            &lt;__8MyClass1+13&gt;:  &nbsp;add  $0x4,%esp<BR><BR>  首先调用基类BaseClass的构造函数。<BR><BR>(gdb) 
            disassemble __9BaseClass<BR>Dump of assembler code for function 
            __9BaseClass:<BR>0x804c958 
            &lt;__9BaseClass&gt;:   &nbsp;push &nbsp;%ebp<BR>0x804c959 
            &lt;__9BaseClass+1&gt;:  &nbsp;mov  %esp,%ebp<BR>0x804c95b 
            &lt;__9BaseClass+3&gt;:  &nbsp;mov  0x8(%ebp),%edx<BR><BR>  寄存器EDX现在存放着指向分配的36个字节的指针("This"指针)。<BR><BR>0x804c95e 
            &lt;__9BaseClass+6&gt;:  &nbsp;movl &nbsp;$0x804e01c,0x20(%edx)<BR><BR>  将0x804e01c存放到EDX+0x20(=EDX+32)。让我们看看该0x804e01c地址内存数据:<BR><BR>(gdb) 
            x 0x804e01c<BR>0x804e01c 
            &lt;__vt_9BaseClass&gt;:  0x00000000<BR><BR>  可以看到这个存放到EDX+0x20(即该对象的VPTR位置)的地址是基类BaseClass的VTABLE地址。<BR>  现在回到MyClass1对象的构造函数:<BR><BR>0x804c91c 
            &lt;__8MyClass1+16&gt;:  &nbsp;movl &nbsp;$0x804e010,0x20(%ebx)<BR><BR>  将0x804e010存放到EBX+0x20(即VPTR)。同样让我们看看该0x804e010地址内存数据:<BR><BR>(gdb) 
            x 0x804e010<BR>0x804e010 
            &lt;__vt_8MyClass1&gt;:  &nbsp;0x00000000<BR><BR>  现在,我们知道VPTR被改写了,再在它的内容是MyClass1对象的VTABLE地址。当返回到main()函数时寄存器EAX中存放着该对象在内存中的指针。<BR><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><BR>  将得到的地址指针赋予Object[0]。然后程序对Object[1]进行同样的处理,只不过返回的地址不同罢了。在经过以上对象初始化处理后,将执行以下指令:<BR><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><BR>  将0x804cda2和Object[0]的值压栈。观察一下0x804cda2的内容:<BR><BR>(gdb) 
            x/s 0x804cda2<BR>0x804cda2 
            &lt;_IO_stdin_used+30&gt;: &nbsp;"string1"<BR><BR>  可知该地址存放了将要通过基类BaseClass的SetBuffer函数拷贝到Buffer中的字符串"string1"。<BR><BR>0x8049461 
            &lt;main+97&gt;:  call &nbsp;0x804c930 
            &lt;SetBuffer__9BaseClassPc&gt;<BR>0x8049466 
            &lt;main+102&gt;: &nbsp;add  $0x8,%esp<BR><BR>  调用基类BaseClass的SetBuffer()方法。注意到这种SetBuffer方法的调用是“静态绑定”(因为它不是虚拟方法)。对Object[1]的处理也是一样的。<BR><BR>  为了验证这两个对象在运行时都被正确地初始化,我们将要设置如下断点:<BR><BR>0x8049410: 
            获得第一个对象的地址。<BR>0x804943a: 获得第二个对象的地址。<BR>0x804947a: 
            检验对象的初始化是否正确。<BR><BR>(gdb) break *0x8049410<BR>Breakpoint 1 at 
            0x8049410<BR>(gdb) break *0x804943a<BR>Breakpoint 2 at 
            0x804943a<BR>(gdb) break *0x804947a<BR>Breakpoint 3 at 
            0x804947a<BR><BR>  现在运行这个程序:<BR><BR>St<BR></P></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR>
<TABLE align=center bgColor=#006699 border=0 cellPadding=0 cellSpacing=0 
width=770>
  <TBODY>
  <TR bgColor=#006699>
    <TD align=middle bgColor=#006699 id=white><FONT 
    color=#ffffff>对该文的评论</FONT></TD>
    <TD align=middle>
      <SCRIPT 
      src="CSDN_文档中心_突破C++的虚拟指针--C++程序的缓冲区溢出攻击.files/readnum.htm"></SCRIPT>
    </TD></TR></TBODY></TABLE>
<TABLE align=center bgColor=#666666 border=0 cellPadding=2 cellSpacing=1 
width=770>
  <TBODY>
  <TR>
    <TD bgColor=#cccccc colSpan=3><SPAN style="COLOR: #cccccc"><IMG height=16 
      hspace=1 src="CSDN_文档中心_突破C++的虚拟指针--C++程序的缓冲区溢出攻击.files/ico_pencil.gif" 
      width=16> </SPAN>&nbsp;&nbsp;&nbsp;&nbsp; ghj1976 <I>(2000-12-21 
      15:47:57)</I> </TD></TR>
  <TR>
    <TD bgColor=#ffffff colSpan=3 width=532><BR>现在运行这个程序: Starting program: 
      /home/backend/test/bo2 Breakpoint 1, 0x8049410 in main () 
        查看EAX寄存器,将得到第一个对象的地址: (gdb) info reg eax eax      0x804f870    134543472 
        接着运行到下一个断点: (gdb) cont Continuing. Breakpoint 2, 0x804943a in main () 
        查看第二个对象的地址: (gdb) info reg eax eax      0x804f898    134543512 
        继续运行,直到对象的构造函数和SetBuffer()方法均已执行。 (gdb) cont Continuing. Breakpoint 3, 
      0x804947a in main ()   这两个对象实例的内存地址分别为0x804f870和0x804f898。然而,0x804f898 - 
      0x804f870 = 0x28(40),这表明在第一个对象与第二个对象之间多了4个字节的内容。让我们看看是什么: (gdb) x/aw 
      0x804f898-4 0x804f894:   0x29   原来是0x29。第二个对象的结尾也有这种特殊的数据: (gdb) x/xb 
      0x804f898+32+4 0x804f8bc:   0x49   下面我们来看一下初始化后这两个对象的结构内容: (gdb) x/s 
      0x804f870 0x804f870:    “string1“ (gdb) x/a 0x804f870+32 
      0x804f890:   0x8048948 &lt;__vt_8MyClass1&gt; (gdb) x/s 0x804f898 
      0x804f898:    “string2“ (gdb) x/a 0x804f898+32 0x804f8b8:   0x804e004 
      &lt;force_to_data&gt;   再看一下这两个对象实例的VTABLE中的内容: (gdb) x/a 0x804e010 
      0x804e010 &lt;__vt_8MyClass1&gt;:   0x0 (gdb) x/a 0x804e010+4 0x804e014 
      &lt;__vt_8MyClass1+4&gt;:  0x804ca10 &lt;__tf8MyClass1&gt; (gdb) x/a 
      0x804e010+8 0x804e018 &lt;__vt_8MyClass1+8&gt;:  0x804c9e0 
      &lt;PrintBuffer__8MyClass1&gt; (gdb) x/a 0x804e004 0x804e004 
      &lt;force_to_data&gt;:   0x0 (gdb) x/a 0x804e004+4 0x804e008 
      &lt;force_to_data+4&gt;:  0x804c9a0 &lt;__tf8MyClass2&gt; (gdb) x/a 
      0x804e004+8 0x804e00c &lt;force_to_data+8&gt;:  0x804c970 

⌨️ 快捷键说明

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