学习中级ROP:
__libc_csu_init 函数实现对libc的初始化操作,在 libc_csu_init 中我们主要利用了以下寄存器:利用尾部代码控制了 rbx,rbp,r12,r13,r14,r15。
利用中间部分的代码控制了 rdx,rsi,edi。
那一道题实践下:ret2csu
栈溢出漏洞,栈大小为40:
一开始的思路是puts那么多,泄露got表直接刚,后来发现不行,got表地址都是0,原因在这里:
这里直接设置为0,就是不让你用got表,没办法了,题目是中级ROP技术,去学了一波,回来自己做了下:
但是发现get不到shell,就很佛了,迷......
下面是看大佬博客才悟到的!查找了一波发现是setbuf搞的鬼?!
这里直接用初始化的函数代替了,试了下,ok!
要么是0x600E10,要么是0x600E18,二选一,其他的不行~
总结:
这道题难在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),长度都是对齐的。
一开始检查程序的保护机制:
只有堆栈不可执行的权限,可以改got表,没有栈溢出保护(可能有栈溢出漏洞)
ida分析:
明显的栈溢出漏洞,通过爆破可以检测出栈大小:136(覆盖ebp)
思路:
这里假设不能使用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技术),这样搞清楚了,接下来就是敲代码的事了。
没有合适的ROP
有合适的ROP,接下来就是写脚本了:
中级ROP技术我们用一个函数来整理(因为会多次用到)
最后实现各种操作:
先本地测试:
最后远程getsehll:
总结:中级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。