软件安全实验——pre9(堆栈保护机制return-to-libc预习)
Posted 大灬白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了软件安全实验——pre9(堆栈保护机制return-to-libc预习)相关的知识,希望对你有一定的参考价值。
1、网上搜索并且阅读
Four different tricks to bypass StackShield and StackGuard
protection这篇文章,描述这些现有保护机制的弱点。
答:
堆栈屏蔽(StackShield)保护,在最初的形式中,它们只保护返回地址覆盖,而不是普通的堆栈销毁攻击。文章中所研究的三种保护方法有两种不同的设计限制只保护内存中比第一个安全保护地址更高的数据。而且,最糟糕的是,只有在函数完成之后,以及从函数返回之前,才检查攻击。此外, StackGuard和StackShield还有一个实现或技术缺陷:它们保护从返回地址开始的堆栈,而不保护保存的帧指针。
1、StackGuard的保护工作原理
这也是我们可以理解三种不同缺陷的地方:buf(var1)之后的局部变量完全不受保护,局部变量可能不被保护,这种情况可以被利用,利用堆栈缓冲区溢位基于保护程序。在这里,一个本地指针用于覆盖任意内存。。保存的帧指针也可以被修改,函数的参数也可以被控制,检查只会在函数完成后被检测到,给攻击者个代码窗口。
当我们试图进行帧指针覆盖攻击时,我们可以成功地改变保存的帧指针而不改变金丝雀。然而,我们需要第二次返回来激活新的返回地址。在标准编译的C code5中,函数的参数位于堆栈中的地址比返回地址高(我们将说在后面),返回地址是在保存的帧指针之后,该帧指针总是在本地变量之后。当存在基于堆栈的缓冲区溢出条件时,我们可以控制函数的参数,这可能会使受保护的程序变成易受攻击的程序。
在这里,通过覆盖比返回地址更远的地方,我们控制msg,通过它,我们可以将这个缓冲区溢出转换为write-any -anywhere。当然, 我们正在修改canany和return address。保护方法将检测到它,但是在函数中使用参数,并且在函数完成后进行检查…太迟了。
如果使用StackGuard,就会调用canary death handler, 并使用几个库函数,因此,例如,写openlog()的或exit)的GOT entry(注意 下划线)将允许我们连接执行流。在这种情况下, 如果我们不知道get的地址是什么, 因为我们可以覆盖超过4个字节的内存,我们可以“填满所有的内存,希望我们能找到它,就像我们在下一个伪利用(您可能需要使用转义$符号)中所做的那样。
2、由于StackShield不使用任何canaries,因此StackShield保护的函数的堆栈布局与未保护的函数的堆栈布局相同。
还有一个保护是可用的,默认情况下是启用的。它添加了一个检查,以查看间接函数调用(通过函数指针进行)是否针对shield数据库下面的地址。我们认为这不是一个坏主意,但它的主要问题是函数指针通常滥用当编码利用libc的一部分(atexit’s, malloc hook, free hook, .dtors, etc.)或动态链接机制的一部分(GOT),而不是使用StackShield除非你编译时保护一切。即使你这样做了 ,我们也认为它不会起作用,因为函数指针的所有默认值(例如在get中)都比Kshield数据库高。
另一方面如果使用StackShield,程序会继续好像什么事都没有发生我们需要检查一些库函数被称为进一步弱势项目,使用另一种方法,如改变atexit功能”,或简单地覆盖克隆返回地址保存在retarray如果我们有一些线索 在内存中找到。 如果使用-d命令开关,StackShield只会发出一个SYS退出系统调用,而不会在结束进程之前在用户空间调用任何其他代码。在最后一种情况下,如果在write any -anywhere操作之后没有进行库调用,也没有使用函数指针,那么我们将无法利用这个程序,除非我们能够用它的原始值覆盖返回地址(实际上不改变它),从而欺骗StackShield的攻击检测代码。要使用相同的伪利用,请删除Cnry,如果使用-d,请用正确的值替换RET。
如果StackShield在自动返回地址恢复模式下使用,我们不仅可以控制当前帧的局部变量和函数参数,还可以改变和滥用对之前帧的控制,提高成功利用的可能性。
3、微软/GS保护
微软的保护有一个很大的区别:它确实保护了框架指针,在它和本地变量之间放置了一个随机canary4。启用GS选项之后,会在函数执行一开始先往栈上保存一个数据,等函数返回时候检查这个数据,若不一致则为被覆盖,这样就跳转进入相应的处理过程,不再返回,因此shellcode也就无法被执行,这个值被称为“Security cookie”。使用IDA便可以看软件到调用Check_ Security_ Cookie()检查栈是否被覆盖。可是他们忽略了异常处理SEH链也在栈上因此可以覆盖SEH链为jmp esp的地址,之后触发异常跳转到esp执行shellcode。
如果金丝雀的随机性良好,这将有效地阻止文章中描述的攻击。另一方面,如果可以预测canaries,那么不仅可以完成这里描述的所有攻击,还可以使用标准的返回地址覆盖攻击。
2、阅读下面这篇文章:
Bypassing non-executable-stack during exploitation using
return-to-libc.
http://www.infosecwriters.com/text_resources/pdf/return-to-libc.pdf
Returning to libc是利用系统上的缓冲区溢出的一种方法
有一个非可执行的堆栈,它非常类似于一个标准的缓冲区溢出,在返回地址被更改为指向一个新的位置,我们可以控制。然而,由于堆栈中不允许有可执行代码,我们不能只在shellcode中标记。
这就是我们使用Returning to libc技巧并使用库提供的函数的原因。我们仍然用libc中的一个函数覆盖返回地址,传递正确的参数并让它为我们执行。由于这些函数并不驻留在堆栈中,所以我们可以绕过堆栈保护和执行代码。
3、阅读这个链接的第3章
解释怎样构造 return2libc 的访问链 http://www.phrack.org/issues.html?issue=58&id=4
答:
return-to-libc攻击不需要一个栈可以执行,甚至不需要一个shellcode。取而代之的是我们让漏洞程序调转到现存的代码(比如已经载入内存的libc库中的system()函数等)来实现我们的攻击。
下图是return-to-libc的调用栈格式如下:
从图中我们可以看出,我们应该在bof的返回地址(即&buf[16])处放置system的入口地址,system的参数的地址放在与入口地址相隔四个字节的位置(即&buf[24]),中间的这四个字节应该放置exit函数的入口地址,这样这在system函数执行完毕之后,就会调用exit函数。
4、阅读这个链接
https://bbs.pediy.com/thread-224643.htm
一般的思路是先leak出canary的cookie,然后在payload里,把原来的canary位置的cookie用我们leak出的正确的cookie写入,之后就是正常的rop。
不过这题,emmm,有个fork呀……参考这篇文章http://0x48.pw/2017/03/14这是个32位的程序,所以canary有4个字节,最低位一定是\\x00,所以只需要爆破三个字节即可。
以上是关于软件安全实验——pre9(堆栈保护机制return-to-libc预习)的主要内容,如果未能解决你的问题,请参考以下文章
软件安全实验——lab5(Buffer_Overflow缓冲区溢出攻击)