如何编写自己的缓冲区溢出利用程序文档格式.docx

上传人:b****7 文档编号:22097326 上传时间:2023-02-02 格式:DOCX 页数:12 大小:23.73KB
下载 相关 举报
如何编写自己的缓冲区溢出利用程序文档格式.docx_第1页
第1页 / 共12页
如何编写自己的缓冲区溢出利用程序文档格式.docx_第2页
第2页 / 共12页
如何编写自己的缓冲区溢出利用程序文档格式.docx_第3页
第3页 / 共12页
如何编写自己的缓冲区溢出利用程序文档格式.docx_第4页
第4页 / 共12页
如何编写自己的缓冲区溢出利用程序文档格式.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

如何编写自己的缓冲区溢出利用程序文档格式.docx

《如何编写自己的缓冲区溢出利用程序文档格式.docx》由会员分享,可在线阅读,更多相关《如何编写自己的缓冲区溢出利用程序文档格式.docx(12页珍藏版)》请在冰豆网上搜索。

如何编写自己的缓冲区溢出利用程序文档格式.docx

即:

主函数main调用函数func_1;

函数func_1调用函数func_2;

函数func_2调用函数func_3

当程序被操作系统调入内存运行, 

其相对应的进程在内存中的影像如下图所示.

(内存高址)

+--------------------------------------+

...... 

... 

省略了一些我们不需要关心的区

env 

strings 

(环境变量字串) 

\

+--------------------------------------+ 

argv 

(命令行字串) 

pointers 

(环境变量指针) 

SHELL的环境变量和命令行参数保存区

/

(命令行参数指针) 

argc 

(命令行参数个数) 

main 

函数的栈帧 

func_1 

func_2 

func_3 

Stack 

(栈)

+......................................+ 

Heap 

(堆) 

Uninitialised 

(BSS) 

data 

非初始化数据(BSS)区

Initialised 

初始化数据区

Text 

文本区

(内存低址)

这里需要说明的是:

i) 

随着函数调用层数的增加, 

函数栈帧是一块块地向内存低地址方向延伸的.

随着进程中函数调用层数的减少, 

即各函数调用的返回, 

栈帧会一块块地

被遗弃而向内存的高址方向回缩.

各函数的栈帧大小随着函数的性质的不同而不等, 

由函数的局部变量的数目决定.

ii) 

进程对内存的动态申请是发生在Heap(堆)里的. 

也就是说, 

随着系统动态分

配给进程的内存数量的增加, 

Heap(堆)有可能向高址或低址延伸, 

依赖于不

同CPU的实现. 

但一般来说是向内存的高地址方向增长的.

iii) 

在BSS数据或者Stack(栈)的增长耗尽了系统分配给进程的自由内存的情况下,

进程将会被阻塞, 

重新被操作系统用更大的内存模块来调度运行.

(虽然和exploit没有关系, 

但是知道一下还是有好处的)

iv) 

函数的栈帧里包含了函数的参数(至于被调用函数的参数是放在调用函数的栈

帧还是被调用函数栈帧, 

则依赖于不同系统的实现),

它的局部变量以及恢复调用该函数的函数的栈帧(也就是前一个栈帧)所需要的

数据, 

其中包含了调用函数的下一条执行指令的地址.

v) 

非初始化数据(BSS)区用于存放程序的静态变量, 

这部分内存都是被初始化为零的.

初始化数据区用于存放可执行文件里的初始化数据.

这两个区统称为数据区.

vi) 

Text(文本区)是个只读区, 

任何尝试对该区的写操作会导致段违法出错. 

是被多个运行该可执行文件的进程所共享的. 

文本区存放了程序的代码.

2) 

函数的栈帧.

函数调用时所建立的栈帧包含了下面的信息:

函数的返回地址. 

返回地址是存放在调用函数的栈帧还是被调用函数的栈帧里,

取决于不同系统的实现.

调用函数的栈帧信息, 

即栈顶和栈底.

为函数的局部变量分配的空间

为被调用函数的参数分配的空间--取决于不同系统的实现.

3) 

缓冲区溢出的利用.

从函数的栈帧结构可以看出:

由于函数的局部变量的内存分配是发生在栈帧里的, 

所以如果我们在某一个函数里定义

了缓冲区变量, 

则这个缓冲区变量所占用的内存空间是在该函数被调用时所建立的栈帧里.

由于对缓冲区的潜在操作(比如字串的复制)都是从内存低址到高址的, 

而内存中所保存

的函数调用返回地址往往就在该缓冲区的上方(高地址)--这是由于栈的特性决定的, 

就为复盖函数的返回地址提供了条件. 

当我们有机会用大于目标缓冲区大小的内容来向

缓冲区进行填充时, 

就有可以改写函数保存在函数栈帧中的返回地址, 

从而使程序的执

行流程随着我们的意图而转移. 

换句话来说, 

进程接受了我们的控制. 

我们可以让进程

改变原来的执行流程, 

去执行我们准备好的代码.

这是冯.诺曼计算机体系结构的缺陷.

下面是缓冲区溢出利用的示意图:

函数对字串缓冲区的操作, 

方向一般都是从内存低址向高址的.

如:

strcpy(s, 

"

AAA....."

);

s+1 

s+2 

s+3 

...

+---+---+---+--------+---+...+

(内存低址) 

|...| 

函数返回地址的复盖

+--------------------+

调用函数栈帧 

0x41414141 

|

调用函数的返回地址

\+--------------------+

/| 

+--------------------+ 

s+8

s+4

被调用函数栈帧 

s

\| 

+....................+

注:

字符A的十六进制ASCII码值为0x41.

从上图可以看出:

如果我们用的是进程可以访问的某个地址而不是0x41414141

来改写调用函数的返回地址, 

而这个地址正好是我们准备好的代码的入口, 

那么

进程将会执行我们的代码. 

否则, 

如果用的是进程无法访问的段的地址, 

将会导

致进程崩馈--Segment 

Fault 

Core 

dumped 

(段出错内核转储);

如果该地址处有

无效的机器指令数据, 

将会导致非法指令(Illigal 

Instruction)错误, 

等等.

4) 

缓冲区在Heap(堆)区或BBS区的情况

如果缓冲区的内存空间是在函数里通过动态申请得到的(如:

用malloc()函数申请), 

么在函数的栈帧中只是分配了存放指向Heap(堆)中相应申请到的内存空间的指针. 

这种

情况下, 

溢出是发生在(Heap)堆中的, 

想要复盖相应的函数返回地址, 

看来几乎是不可

能的. 

这种情况的利用可能性要看具体情形, 

但不是不可能的.

如果缓冲区在函数中定义为静态(static), 

则缓冲区内存空间的位置在非初始化(BBS)区,

和在Heap(堆)中的情况差不多, 

利用是可能的. 

但还有一种特姝情况, 

就是可以利用它来

复盖函数指针, 

让进程后来调用相应的函数变成调用我们所指定的代码.

3. 

从缓冲区溢出的利用可以得到什么?

从上文我们看到, 

缓冲区溢出的利用可以使我们能够改写相关内存的内容及函数的返回地址, 

从而

改变代码的执行流程, 

让进程去执行我们准备好的代码.

但是, 

进程是以我们当前登录的用户身份来运行的. 

能够执行我们准备好的代码又怎样呢?

我们还

是无法突破系统对当前用户的权限设置, 

无法干超越权限的事.

要想利用缓冲区溢出得到更高的权限, 

我们还得利用系统的一些特性.

对于UNIX来讲, 

有两个特性可以利用.

SUID及SGID程序

UNIX是允许其他用户可以以某个可执行文件的文件拥有者的用户ID或用户组ID的身份来执行该

文件的,这是通过设置该可执行文件的文件属性为SUID或SGID来实现的.

也就是说如果某个可执行文件被设了SUID或SGID, 

那么当系统中其他用户执行该文件时就相当

于以该文件属主的用户或用户组身份来执行该文件.

如果某个可执行文件的属主是root, 

而这个文件被设了SUID, 

那么如果该可执行文件存在可利

用的缓冲区溢出漏洞, 

我们就可以利用它来以root的身份执行我们准备好的代码. 

没有比让它

为我们产生一个具有超级用户root身份的SHELL更吸引人了, 

是不是?

各种端口守护(服务)进程

UNIX中有不少守护(服务)进程是以root的身份运行的, 

如果这些程序存在可利用的缓冲区溢出,

那么我们就可以让它们以当前运行的用户身份--root去执行我们准备被好的代码.

由于守护进程已经以root的身份在运行, 

我们并不需要相对应的可执行文件为SUID或SGID属性.

又由于此类利用通常是从远程机器上向目标机器上的端口发送有恶意的数据造成的, 

所以叫做

远程溢出"

利用.

4. 

一个有问题的程序

以下例程纯属虚构, 

如有雷同, 

纯属巧合.

/*

文件名 

:

p.c

编译 

gcc 

-o 

*/

#include 

<

stdio.h>

void 

vulFunc(char* 

s)

{

char 

buf[10];

strcpy(buf, 

s);

printf("

String=%s\n"

 

buf);

}

main(int 

argc, 

char* 

argv[])

if(argc 

== 

2)

vulFunc(argv[1]);

else

Usage:

%s 

string>

\n"

argv[0]);

这个例程接受用户在命令行的字串输入, 

然后在标准输出(屏幕)上打印出来. 

我们可以看出在

vulFunc()这个函数里, 

定义了一个最多可以装十个字符的缓冲区buf. 

如果我们在命令行输入

小于等于十个字符的字串, 

则一切都很正常. 

如果我们输入的字串长度大于十呢?

情况

会怎样?

缓冲区太小装不下了, 

所以溢出了?

答案有待于具体分析一下才知道.

对于这个程序在不同操作系统下的分析和模拟攻击. 

请看第二部份基楚篇

第二部份 

基楚篇

5. 

Linux 

x86 

平台

本文使用了如下Linux平台:

Red 

Hat 

release 

6.2 

(Zoot)

Kernel 

2.2.14-12 

on 

an 

i586

所使用的编译器及版本:

bash$ 

-v

Reading 

specs 

from 

/usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/specs

version 

egcs-2.91.66 

19990314/Linux 

(egcs-1.1.2 

release)

注意:

不同版本的编译器编译相同代码所生成的机器指令可能不同.

例程p.c在Linux 

x86平台下的剖析.

首先我们编译p.c并用gdb对相关函数进行反汇编

结果见如下清单:

gdb 

p

GNU 

19991004

Copyright 

1998 

Free 

Software 

Foundation, 

Inc.

GDB 

is 

free 

software, 

covered 

by 

the 

General 

Public 

License, 

and 

you 

are

welcome 

to 

change 

it 

and/or 

distribute 

copies 

of 

under 

certain 

conditions.

Type 

show 

copying"

see 

There 

absolutely 

no 

warranty 

for 

GDB. 

warranty"

details.

This 

was 

configured 

as 

i386-redhat-linux"

(gdb) 

disas 

main

Dump 

assembler 

code 

function 

main:

0x804842c 

main>

push 

%ebp

0x804842d 

main+1>

mov 

%esp,%ebp

0x804842f 

main+3>

cmpl 

$0x2,0x8(%ebp)

0x8048433 

main+7>

jne 

0x8048448 

main+28>

0x8048435 

main+9>

0xc(%ebp),%eax

0x8048438 

main+12>

add 

$0x4,%eax

0x804843b 

main+15>

(%eax),%edx

0x804843d 

main+17>

%edx

0x804843e 

main+18>

call 

0x8048400 

vulFunc>

0x8048443 

main+23>

$0x4,%esp

0x8048446 

main+26>

jmp 

0x804845b 

main+47>

0x804844b 

main+31>

0x804844d 

main+33>

0x804844e 

main+34>

$0x80484bb

0x8048453 

main+39>

0x8048330 

printf>

0x8048458 

main+44>

$0x8,%esp

leave

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 艺术

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1