首页
社区
课程
招聘
[分享]同时替换栈和.data数据节中的Cookie突破GS安全机制
发表于: 2018-6-1 20:34 6528

[分享]同时替换栈和.data数据节中的Cookie突破GS安全机制

2018-6-1 20:34
6528

这段时间在学习windows平台的漏洞知识,前几天弄明白了GS,写下来与大家分享,希望对像我一样的初学者有帮助^_^。

实验环境:XPSP2,VS2008(禁用优化选项),build版本:release版本;

工具:OD,IDA。

参考书籍:《0day2:软件漏洞分析技术》第二版

      首先说明一下GS的来源:针对缓冲区溢出时覆盖函数返回地址这种情况,微软在编译程序是加入了一个安全校验选项—GS。基本的使用方法是这样:函数调用发生的时候系统为该函数开辟一个新的栈帧,然后参数,返回地址,EBP入栈,之后再在EBP的上方加入一个双字大小的随机数,称为Security Cookie,这个随机数是用来自.data数据节中的开头四个字节(种子)与EBP异或得到,因为程序每次运行的时候种子都是随机的,所以Security Cookie也是随机的。最后在函数准备返回之前,将Security Cookie与EBP异或,再与.data的种子比较,如果二者相同,函数正常返回。如果Security Cookie的值被溢出的数据覆盖,那它与EBP异或的结果也就不会跟种子一样,Security Cookie就是用来防止栈溢出被利用。GS使得栈溢出利用的难度提高了很多,但也不是完全没有办法。

通过学习GS的原理可以知道,函数要正常返回需要满足的条件是:函数在返回之前Security Cookie xor EBP == 种子。

由此可以做一个假设,在函数返回之前同时修改Security Cookie和.data数据节的种子,使得函数返回的时候;Security Cookie xor EBP == 种子,就可以突破GS了。

     这里我们编写一个存在栈溢出的程序来说明这种方法。栈溢出需要关注的有这么几个位置,产生溢出的数组(缓冲区)的位置,函数返回地址,这里还需要知道Security Cookie的位置和.data数据节种子的位置。先把这几个位置确定了再来组织shellcode。这里先用8个字节的NOP填充缓冲区。

#include <stdafx.h>

#include <string.h>

#include <stdlib.h>

char shellcode[]="\x90\x90\x90\x90"//用NOP修改种子

"\x90\x90\x90\x90";

void test(char * str, int i, char * src)

{

       char dest[200];

       if(i<0x9995)

       {

              char * buf=str+i;//指向.data,i的值是main函数中申请的内存的起始地址到种子的距离

              *buf=*src;//修改.data的第一个字节

              *(buf+1)=*(src+1); //修改.data的第二个字节

              *(buf+2)=*(src+2); //修改.data的第三个字节

              *(buf+3)=*(src+3); //修改.data的第四个字节

           strcpy(dest,src);//这个函数产生溢出

       }

}

void main()

{

       char * str=(char *)malloc(0x10000);//申请一片内存,并用test函数来使用

       test(str,0xFFFF2FB8,shellcode);  

}

      将这段程序按实验环境要求编译生成一个可执行程序,载入IDA,Ctrl+L得知main函数的位置是0x004010E0。再载入OD中,Ctrl+G输入0x004010E0,来到main函数的入口,

     在OD中可以看到main函数中的两个函数。在0x004010E0下一个断点,然后F9运行到断点处,接着F8直接步过malloc()函数,在EAX中可以看到由malloc()申请的内存的起始位置是0x00410048。



      接着F8执行到test函数,缓冲区溢出发生在test函数,这里就要F7跟进去,在OD中右下角的栈区可以看到test函数的从右向左依次入栈的参数:shellcode的地址0x00403018,0xFFFF2FB8和一开始申请的内存的起始地址0x00410048。接着是函数返回地址0x00401108,在左上角的反汇编窗口中可以在0x00401013处看到“if i<0x9995”对应的汇编指令。


      在0x00401009的指令将.data开头四个字节的值,也就是种子的值赋给EAX,再与EBP异或,得到Security Cookie=0xF60A313E,并放在EBP的上面,这个时候再去test函数的栈中查看,发现EBP的上面多了一个0xF60A313E,这个值就是Security Cookie。到现在函数返回地址,.data数据节的起始位置,和Security Cookie的位置都已经知道,再往下执行就会发现缓冲区的位置,这里就是dest数组。


      前面已经知道了种子的位置是0x00403000,也知道了main函数中malloc函数申请的内存的起始地址是0x00410048,位置差为FFFF2FB8(十进制的-53320),代码中char * buf=str+i这一句的作用就是根据这个差值找到种子的位置,接着将al的值赋为NOP(0x90),然后通过al开始修改0x00403000处的种子的值


     接着是将shellcode数组的8个NOP传给test函数中的数组dest,可以在右下角的栈中看到0x0012FE94是dest数组在栈中的位置。自此,我们需要的几个位置都知道了; 


     接下来重新组织shellcode。

#include <stdafx.h>


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2018-6-10 19:28 被fuckCC编辑 ,原因:
上传的附件:
收藏
免费 1
支持
分享
最新回复 (10)
雪    币: 576
活跃值: (2035)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
很详细
2018-6-1 22:10
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
感谢分享!
2018-6-4 10:06
0
雪    币: 714
活跃值: (82)
能力值: ( LV3,RANK:35 )
在线值:
发帖
回帖
粉丝
4
文中提到“这个随机数是用来自.data数据节中的开头四个字节(种子)与EBP异或得到,因为程序每次运行的时候种子都是随机的,所以Security Cookie也是随机的”,这里我有点不明白:程序每次运行的时候种子都是随机的,那么也就是说.data数据节中的开头四个字节(种子)就是随机的,可是.data节中的数据不是固定的吗?是我哪里理解错了吗?
2018-6-8 11:07
0
雪    币: 2
活跃值: (44)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
5
xyy吸氧羊 文中提到“这个随机数是用来自.data数据节中的开头四个字节(种子)与EBP异或得到,因为程序每次运行的时候种子都是随机的,所以Security Cookie也是随机的”,这里我有点不明白:程序每次运 ...
.data数据节的开头四个字节是干嘛用的可以不用管,但如果这四个字节是个固定值的话,Security  Cookie也容易计算得到,shellcode的设计也变得容易了,只是在EBP上面加上一个已知的值,这样的话GS安全机制还有用吗?这也说明,种子的随即性很大程度的保障了GS的可靠性。
最后于 2018-6-8 18:00 被fuckCC编辑 ,原因:
2018-6-8 18:00
0
雪    币: 1795
活跃值: (63)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
xyy吸氧羊 文中提到“这个随机数是用来自.data数据节中的开头四个字节(种子)与EBP异或得到,因为程序每次运行的时候种子都是随机的,所以Security Cookie也是随机的”,这里我有点不明白:程序每次运 ...
.data前四字节是固定的,但为什么会有随机这个说法呢?
因为保存在栈中的数是.data前四字节  xor  ebp。再加上ASLR机制,这个随机就能得到保证了。
2018-6-8 19:52
0
雪    币: 714
活跃值: (82)
能力值: ( LV3,RANK:35 )
在线值:
发帖
回帖
粉丝
7
myangel .data前四字节是固定的,但为什么会有随机这个说法呢? 因为保存在栈中的数是.data前四字节 xor ebp。再加上ASLR机制,这个随机就能得到保证了。
你一说ASLR我有点明白。但是你说.data前四个字节是固定的和5楼说的不一致啊,5楼说种子(也就是.data前四个字节)是随机的
2018-6-9 00:19
0
雪    币: 714
活跃值: (82)
能力值: ( LV3,RANK:35 )
在线值:
发帖
回帖
粉丝
8
大晟 xyy吸氧羊 文中提到“这个随机数是用来自.data数据节中的开头四个字节(种子)与EBP异或得到,因为程序每次运行的时候种子都是随机的,所以Security ...
我说的“固定”的意思是指,相对于某个程序来说,.data节的数据不应该是固定的吗?不是说所有程序的.data节的前四个字节是固定的。所以我的问题就是为什么“程序每次运行的时候种子(也就是.data前四个字节)都是随机的”?
2018-6-9 00:22
0
雪    币: 714
活跃值: (82)
能力值: ( LV3,RANK:35 )
在线值:
发帖
回帖
粉丝
9
楼主能不能把调试的EXE上传一下,我用VS编译出来的程序在调试的时候出现很多偏差
2018-6-10 18:58
0
雪    币: 2
活跃值: (44)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
10
xyy吸氧羊 楼主能不能把调试的EXE上传一下,我用VS编译出来的程序在调试的时候出现很多偏差[em_16]
上传了,你看一下
2018-6-10 19:28
0
雪    币: 15
活跃值: (337)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
"\xF4\x6F\x82\x90"//result of \x90\x90\x90\x90 xor EBP        楼主你这种方法要事先知道ebp的值啊,万一ebp的值不确定呢
2019-3-25 13:01
0
游客
登录 | 注册 方可回帖
返回
//