ret2lib bypass dep 学习笔记(0day2Edition NtSetInformationProcess)

DEP绕过ROP(ret2lib)技术总结

样本空间

测试环境

  • 操作系统:windows xp sp3
  • 工具:immunity debugger

mona可以自动生成rop链,但是有些链还需要修改,所以本文就从原理上讲了下链的形成。

样本源码:

 #include <stdio.h>
 #include <string.h>
 #include <windows.h>

 char shellcode[]=
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6C\x8B\xC4\x53\x50\x50"
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8" // 168 字节的弹窗 shellcode
"\x90\x90\x90\x90"
"\x52\xe2\x92\x7c"
"\x02\x07\x76\x7d"
"\x55\x54\x19\x77"
"\xff\xb9\xd3\x7d"
"\x24\xcd\x93\x7c"
"\xe9\x3b\xff\xff\xff"
"\x90\x90\x90"
;
 void test(char* input)
 {
 char buf[168];
 strcpy(buf,input);
 }

 int main(int argc, char* v[])
 {
 LoadLibrary("shell32.dll");
 test(shellcode);
 return 0;
 }

“\x90\x90\x90\x90” 1

“\x52\xe2\x92\x7c” 2 mov eax,1 ret (EIP)

“\x02\x07\x76\x7d” 3 push esp,pop ebp,ret4 (EIP)

“\x55\x54\x19\x77” 4 ret28 (EIP)

“\xff\xb9\xd3\x7d” 5 jmp esp (EIP)

“\x24\xcd\x93\x7c” 6 EntryOfCloseDep (leave and ret4)

“\xe9\x3b\xff\xff\xff” 7 alreay stackExc,just jmp to the payload.

“\x90\x90\x90”

执行顺序: 2->3->4->6->5->7

实验如果按照这些代码去做,即使非常绕,也能做出来效果,但是要说明的问题很多,这些都是关于rop编写的例子:

ret的影响范围:

0x00 最简单的ret没有带数字,eip内的操作分别为mov eax,1 ret; mov ebx,1 ret; mov ecx,1,ret; mov edx,1,ret;..

eip1 (其他内存页指令,不包含对栈的操作,或者栈平衡,不会影响到esp,ebp原值,ret)

eip2 (其他内存页指令,不包含对栈的操作,或者栈平衡,不会影响到esp,ebp原值,ret)

eip3 。。。

eip4 。。。

eip5 (其他内存页指令,不包含对栈的操作,或者栈平衡,不会影响到esp,ebp原值,ret)

那么函数返回后的执行顺序就是eip1(&rop1),eip2(&rop2),eip3(&rop3),eip4(&rop4),eip5(&rop5)…

函数的返回标志只有ret一个,所以可以认为函数的ret开启了rop链。当执行到ret时,会将栈顶元素弹出到eip中,也就是说,在上述描述过程中,eip1执行时,栈内为(eip2-5),eip2执行时,栈内为(eip3-5),eip3执行时,栈内为(eip4-5)。。注意在此过程中,ebp没有改变,esp一直在减。

0x01 retN个数,以ret4为例。

eip1 (mov eax,1 ret)

eip2 (mov ebx,1 ret4)

eip3 (mov ecx,1 ret)

eip4 (mov edx,1 ret)

eip5 (mov esi,1 ret)

指令的执行顺序又会是怎样:

eip1->eip2->eip3->eip5 , eip4不见了,出现了偏移。

为什么eip2 明明是(mov ebx,1 ret4),而eip3会执行,不是esp已经偏移为8了嘛,eip4不会执行?

这样理解:retN指令在执行过程中是:ret(pop eip)后,再sub esp,N

所以rop链中出现retN,那么影响的不是下一条指令,而是下下一条指令。offset值为N/4.

“\x90\x90\x90\x90” 1

“\x52\xe2\x92\x7c”2 mov eax,1 ret

“\x02\x07\x76\x7d” *3*push esp,pop ebp,ret4

“\x55\x54\x19\x77”4 ret28

“\xff\xb9\xd3\x7d” 5 jmp esp

“\x24\xcd\x93\x7c” 6 EntryOfCloseDep

“\xe9\x3b\xff\xff\xff”*7*alreay stackExc,just jmp to the payload.

“\x90\x90\x90”

还是来看这条rop链。首先函数ret时栈为2-7.2执行完毕之后,ret将3弹出到eip中,所以3执行。3执行完毕之后,先ret ,所以4会执行,在4未开始的时候,又sub esp,4了所以,4开始的时候esp指向6.

怎么分析,ret4分为两步,先将esp的值弹出到eip中,所以eip中为4,但是4还没有执行,esp先得再sub esp,4后,4才会执行。

所以应该是这样的:

ret -pop eip, then eip execute:

ret4->pop eip, sub esp,4 then eip execute:

ret28->pop eip,sub esp,28 then eip execute.

顺序很重要,不是pop eip,eip开始执行,然后sub esp,28.

要不然很乱的。

比如3中,看到ret4 就会想到esp减8,正好到5上,所以5会执行。

有两处错误:不是先sub,后ret.一个ret等于sub esp,4.但是它又和sub esp,4不同就是它先压栈。而是先ret后sub。

第二处错误是ret4时,esp会指向5,不是5,是6.为什么。因为3执行时(3以上面的ret开始),此时栈中为4,而不是3开始。即执行ret4的时候,esp已经执行4了。

怎么说呢,就是当eip执行时,栈永远在它的下方,而不是和它平齐,一般push pop操作平衡的话。

分析的时候思路为eip执行前,eip执行到ret时,eip执行ret后。下一个eip要开始执行时的栈结构。

偏移对我来说真的很痛苦。

因为栈操作和ret需要一直跟进esp,所以看到ret28就很头痛。但是最终看0day2第一个bypass dep的时候,发现在函数ret前有个leave指令。

这个leave指令真的是谢天谢地的恩人。所以,即使当时ret40000了(夸张),但是当leave时,会mov esp,ebp.所以这时候看ebp就可以了。

之前使用的是push esp ,pop ebp. ret。那么此时esp(new)就是ebp-4.因为leave还要pop ebp,此时ebp变了。但是只要在esp之后就行了。

回头来看,esp此时就是3执行时候的esp,所以是指向了4.但是还没有pop ebp,所以esp又变成了5.执行5开始时,6操作的ret带了4.所以esp还得再减4,esp指向了7.因此jmp esp可以到7.

执行7的时候已经在栈上了,此时dep已经关闭了,就可以跳转了。

0x02

总结如下:

- 1. retN = pop eip&sub esp,4 ; sub esp,N ;then eip start.

- 2. 当N为0,即ret时,为pop eip &(sub esp,4) then eip start.

- 3. leave = mov esp,ebp (所以esp随便调配,只要ebp记录了当时为了不影响压栈时的esp值(push esp,pop ebp)) && pop ebp

- 4. 分析rop链时,应该这样分析: 指令开始时,esp在哪里。(指令开始,即此时eip已经被弹出)

- 5. retN是先弹eip后sub,不是先sub后弹eip。

时间: 2024-08-29 21:16:05

ret2lib bypass dep 学习笔记(0day2Edition NtSetInformationProcess)的相关文章

CVE-2012-0497 漏洞利用学习笔记

前面一篇学习了下怎么用ClassName或者title来进行占位,现在学习下如何利用该漏洞 对于UAF漏洞的利用,最简单的就是通过Heap Spary来实现了,国外的大神也提出了一种不用Heap Spary,直接构造一个对象来利用的方法 现在学习一下这两种方法,漏洞利用环境为win7 32位+ie8,我们需要解决的问题有: 1.如果精确进行Heap Spary 2.如何bypass DEP 3.解决ALSR 接下来一个个解决这3个问题: 一.如何精确进行Heap Spary 有关这个问题,泉哥翻

NSURLSession学习笔记

NSURLSession学习笔记(一)简介 一.URL Session的基本概念 1.三种工作模式: 默认会话模式(default):工作模式类似于原来的NSURLConnection,使用的是基于磁盘缓存的持久化策略,使用用户keychain中保存的证书进行认证授权. 瞬时会话模式(ephemeral):该模式不使用磁盘保存任何数据.所有和会话相关的caches,证书,cookies等都被保存在RAM中,因此当程序使会话无效,这些缓存的数据就会被自动清空. 后台会话模式(background)

SAS学习笔记

一.            在SAS中进行随机抽样: 1. 在实际数据处理中常常需要进行样本抽样,在实践中主要有两种情况: (1)简单无重复抽样(2)分层抽样   a.等比例分层抽样  b. 不等比例分层抽样: 2.SAS 中可以利用PROC suveryselect 过程实现各种抽样: 其一般形式是: PROC SURVEYSELECT  data=<源数据集名> method = <srslursl sys >  out=<抽取样本存放的数据集> n=<抽取数

AMD规范学习笔记

背景 NodeJS的一套比较简洁 Moudles 规范, 使得在服务器端的模块化变得更加简单.很长一段时间,很多公司或者项目都有自己的一套模块化机制, 却未能形成一套统一的标准, NodeJS的Moudles规范如果运用在浏览器端会存在一些问题,如 服务器端JS模块文件就在本地,浏览器端则需要通过网络请求 服务器端可以很容易的实现同步或异步请求模块,浏览器端代价会比较大 采用XHR的方式实现同步请求模块,存在明显的跨域缺陷,而使用script的方式,默认是异步的. 在这样的背景下, Common

CCIE学习笔记之EEM

当内存使用到一定程度生成日志并发邮件: 注册applet并进入applet配置模式: Router(config)# event manager appletmemory-fail 定义触发事件: event snmp oid oid-value get-type{exact|next} entry-op operator entry-val entry-value[exit-comb| and}] [exit-opoperator] [exit-val exit-value] [exit-ti

CCIE学习笔记之特性集

etherchannel loadbalance  dst –mac 以太网隧道负载方式基于目标MAC MST (config)# spanning -tree mode mst (config)# spanning -tree mst configuration (config-mst )#  name CCIE (config-mst )#  instance 1 vlan 20,40,60 spanning -tree mst 3 root primary spanning -tree m

【大话存储】学习笔记(7,8章),FC协议

Fibre Channnel 我们之前引入了SAN的概念,SAN首先是个网络,而不是存储设备.这个网络是专门来给主机连接存储设备用的. 我们知道按照SCSI总线16个节点的限制,不可能接入很多的磁盘,要扩大SAN的规模,只使用SCSI总线是不行的,所以必须找到一种可寻址容量大.稳定性强.速度块.传输距离远的网络结构.FC网络就应运而生. FC网络 Fibre Channnel也就是网状通道,FC协议从1988年出现,最开始作为高速骨干网技术. 任何互联系统都逃不过OSI模型,所以我们可以用OSI

vector 学习笔记

vector 使用练习: /**************************************** * File Name: vector.cpp * Author: sky0917 * Created Time: 2014年04月27日 11:07:33 ****************************************/ #include <iostream> #include <vector> using namespace std; int main

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则 用了几天时间看了一下开源框架Caliburn.Micro 这是他源码的地址http://caliburnmicro.codeplex.com/ 文档也写的很详细,自己在看它的文档和代码时写了一些demo和笔记,还有它实现的原理记录一下 学习Caliburn.Micro要有MEF和MVVM的基础 先说一下他的命名规则和引导类 以后我会把Caliburn.Micro的 Actions IResult,IHandle ICondu