学习中级ROP:
__libc_csu_init 函数实现对libc的初始化操作,在 libc_csu_init 中我们主要利用了以下寄存器:利用尾部代码控制了 rbx,rbp,r12,r13,r14,r15。
利用中间部分的代码控制了 rdx,rsi,edi。
![](https://img.haomeiwen.com/i9085575/ec62debdf655421f.png)
那一道题实践下:ret2csu
![](https://img.haomeiwen.com/i9085575/efc57f9a0fd4a4a8.png)
![](https://img.haomeiwen.com/i9085575/e065c9301b5df400.png)
栈溢出漏洞,栈大小为40:
一开始的思路是puts那么多,泄露got表直接刚,后来发现不行,got表地址都是0,原因在这里:
![](https://img.haomeiwen.com/i9085575/9b032646237f3676.png)
这里直接设置为0,就是不让你用got表,没办法了,题目是中级ROP技术,去学了一波,回来自己做了下:
![](https://img.haomeiwen.com/i9085575/656090b8e7a00438.png)
但是发现get不到shell,就很佛了,迷......
![](https://img.haomeiwen.com/i9085575/7e01f1bc4422a560.png)
下面是看大佬博客才悟到的!查找了一波发现是setbuf搞的鬼?!
![](https://img.haomeiwen.com/i9085575/72f9cf14324b11a3.png)
这里直接用初始化的函数代替了,试了下,ok!
![](https://img.haomeiwen.com/i9085575/8134eabb595638a6.png)
要么是0x600E10,要么是0x600E18,二选一,其他的不行~
![](https://img.haomeiwen.com/i9085575/751d17c6fd20ae51.png)
总结:
这道题难在got无法直接用的情况下用中级ROP技术,找__libc_csu_init中的ROP链,R12是关键!(关系到函数调用),这里由于R12的参数会受setbuf的影响,所以用初始化的参数去代替,程序便正常运行了,相当于用替身绕过阻拦,先把参数放好,然后再回去找替身调用就OK了。
这里学到一个技巧,查看一堆内存:tel 0xxxxx
下面上一道中级ROP+mprotect的OJ,level5:
这里假设system和execve被禁用,实际上这种情况很常见,利用mprotect和mmap来解决
简单来说mmap函数创建一块内存区域,将一个文件映射到该区域,进程可以像操作内存一样操作文件。mprotect函数可以改变一块内存区域的权限(以页为单位),这里通常把bss的权限改为可读可写可执行,一般来说64位下mprotect(0x600000,0x1000,7)(起始地址,长度,权限)32位下mprotect(0x804A000,0x400,7),长度都是对齐的。
一开始检查程序的保护机制:
![](https://img.haomeiwen.com/i9085575/026da22a3f97e426.png)
只有堆栈不可执行的权限,可以改got表,没有栈溢出保护(可能有栈溢出漏洞)
ida分析:
![](https://img.haomeiwen.com/i9085575/863e01b59571448d.png)
![](https://img.haomeiwen.com/i9085575/1f824ed5e9cb3aed.png)
明显的栈溢出漏洞,通过爆破可以检测出栈大小:136(覆盖ebp)
![](https://img.haomeiwen.com/i9085575/376c7ddfd0e2886c.png)
![](https://img.haomeiwen.com/i9085575/25db336e41ca40ef.png)
思路:
这里假设不能使用system和execve函数的话,想到是自己生成shellcode,放在bss段中,然而bss是不可执行的,要改写那个权限,就要用到mprotect和mmap,64位下我们优先使用mprotcet,需要先求出这个mprotect函数的真实地址,然后在got表中调用,然而原本的got表是没有的,所以我们要覆盖已有函数A的got表地址,这样下一次调用A函数就直接调用mprotect函数。然后我们再覆盖B函数的got为bss段的地址,调用B函数就可以运行bss段中的shellcode了。还有一个问题,64位下的ROP gadget
发现没有三个参数同时满足的,想到可以使用__libc_csu_init里面的那个rop链(如不懂请看中级ROP技术),这样搞清楚了,接下来就是敲代码的事了。
![](https://img.haomeiwen.com/i9085575/24729c2d160ee1a5.png)
没有合适的ROP
![](https://img.haomeiwen.com/i9085575/b26e94b5d31d4845.png)
有合适的ROP,接下来就是写脚本了:
![](https://img.haomeiwen.com/i9085575/2bf82ef70c622188.png)
中级ROP技术我们用一个函数来整理(因为会多次用到)
![](https://img.haomeiwen.com/i9085575/c973325eddbe36b5.png)
最后实现各种操作:
![](https://img.haomeiwen.com/i9085575/47794724f35921d0.png)
先本地测试:
![](https://img.haomeiwen.com/i9085575/8920d0a6594eab07.png)
最后远程getsehll:
![](https://img.haomeiwen.com/i9085575/effad98643120a6d.png)
总结:中级ROP适用于64位下的需要3位参数的函数,一般在ROPGadget中很难找齐,就可以这么用,方便,同时掌握改写内存权限和覆盖got表的能力,一举三得!能力得到提升,继续加油。
这里介绍下Brop:
BROP 是没有对应应用程序的源代码或者二进制文件下,对程序进行攻击,劫持程序的执行流。
攻击条件 :
- 源程序必须存在栈溢出漏洞,以便于攻击者可以控制程序流程。
- 服务器端的进程在崩溃之后会重新启动,并且重新启动的进程的地址与先前的地址一样(这也就是说即使程序有 ASLR 保护,但是其只是在程序最初启动的时候有效果)。目前 nginx, MySQL, Apache, OpenSSH 等服务器应用都是符合这种特性的。
基本思路
在 BROP 中,基本的遵循的思路如下:
- 判断栈溢出长度
- 暴力枚举
- Stack Reading
- 获取栈上的数据来泄露 canaries,以及 ebp 和返回地址。
- Blind ROP
- 找到足够多的 gadgets 来控制输出函数的参数,并且对其进行调用,比如说常见的 write 函数以及 puts 函数。
- Build the exploit
- 利用输出函数来 dump 出程序以便于来找到更多的 gadgets,从而可以写出最后的 exploit。
具体的操作和详细说明:https://www.jianshu.com/p/2bd323e7e97f
- 利用输出函数来 dump 出程序以便于来找到更多的 gadgets,从而可以写出最后的 exploit。
网友评论