Windows下GS保护机制详情及其绕过
字数 1337 2025-08-23 18:31:24

Windows下GS保护机制及其绕过技术详解

一、GS保护机制概述

GS(Buffer Security Check)是微软针对栈溢出攻击设计的一种保护机制,其核心思想是通过在栈帧中插入一个随机值(称为Security Cookie或Canary)来检测缓冲区溢出。

1. GS保护机制工作原理

  • Canary布局:在栈帧中,Canary被放置在局部变量和返回地址之间

  • 典型栈布局

    ... 变量a ...
    ... 变量 ...
    ... 变量 ...
    Canary
    EBP
    返回地址
    
  • Canary生成与验证过程

    1. 取出.data节的第一个双字作为Cookie种子
    2. 将Cookie种子与ESP异或
    3. 将异或后的值存入Canary地址
    4. 函数返回前进行逆过程验证

2. 变量重排技术

GS还采用了变量重排技术来防止覆盖其他变量:

重排前

Buff (字符串类型)
Char
Int

重排后

Char
Int
Buff
Canary
EBP
返回地址

二、不会启用GS的情况

以下情况编译器不会为函数启用GS保护:

  1. 函数不包含缓冲区
  2. 函数被定义为具有变量参数列表
  3. 函数使用无保护关键字标记
  4. 函数在第一个语句中包含内嵌汇编代码
  5. 缓冲区不是8字节类型并且不大于4字节

强制启用GS

#pragma strict_gs_check(on)

三、GS保护机制的绕过技术

1. 攻击未启用GS的函数

直接寻找并攻击程序中未启用GS保护的函数进行溢出攻击。

2. 覆盖虚函数绕过GS

原理:在Canary检查之前劫持程序流程,利用C++虚函数机制实现。

示例代码

class GSVirtual {
public:
    void gsv(char *src) {
        char buf[200];
        memcpy(buf, src, 204); // 溢出点
        MyFunc(); // 虚函数调用
    }
    virtual void MyFunc() {}
};

攻击步骤

  1. 通过溢出覆盖对象的虚函数表指针
  2. 将虚函数表指针指向攻击者控制的数据
  3. 精心构造数据使程序执行攻击代码

Payload构造要点

  • 前4字节设置为shellcode地址
  • 后续数据包含实际shellcode
  • 覆盖虚表指针使其指向攻击数据

3. 攻击异常处理绕过GS

原理:GS不保护SEH(结构化异常处理),通过覆盖异常处理指针实现攻击。

示例代码

void test(char *szBuffer) {
    char buf[200]{0};
    strcpy(buf, szBuffer); // 溢出点
    strcat(buf, szBuffer);
}

攻击步骤

  1. 计算异常处理指针相对于缓冲区的偏移
  2. 构造超长字符串覆盖异常处理指针
  3. 触发异常使程序执行攻击代码

Payload构造要点

  • 在异常处理指针偏移处放置shellcode地址
  • 确保触发异常(如非法内存访问)

4. 同时替换栈和.data中的Cookie绕过GS

原理:同时修改栈中的Canary和.data中的Cookie种子,使验证通过。

示例代码

void test(char *s, int i, char *src) {
    char dest[200]{0};
    if(i < 0x9995) {
        char *buf = s + i;
        *buf = *src;
        *(buf+1) = *(src+1);
        *(buf+2) = *(src+2);
        *(buf+3) = *(src+3);
        memcpy(dest, (char*)(src+8), 212); // 溢出点
    }
}

攻击步骤

  1. 计算堆地址到.data节Cookie种子的偏移
  2. 构造Payload:
    • 前4字节:期望的Cookie值(通常为0x90909090 ^ EBP)
    • 4-8字节:指向.data节Cookie种子的偏移
    • 后续数据:shellcode和返回地址覆盖

Payload示例

unsigned char hexData[212] = {
    0x10,0x6D,0x89,0x90, // 修改后的Cookie值
    0x54,0x01,0xE7,0xFF, // 指向.data的偏移
    // 后续为shellcode...
};

四、实验环境配置

为进行GS绕过实验,需进行以下VS配置:

  1. 在C/C++ → 常规属性中关闭SDL检查
  2. 在代码生成中将基本运行时检查设置为默认值
  3. 运行库修改为MTD
  4. 禁用Spectre缓解(如安装了驱动开发)
  5. 在所有选项中关闭控制流防护
  6. 禁用安全检查(/GS-)(仅用于测试特定绕过方法)

五、总结

GS保护机制虽然有效,但仍存在多种绕过方法。安全防护与攻击技术总是在不断对抗中发展,理解这些机制和绕过技术对于二进制安全研究至关重要。随着防护技术的演进,如CFG(控制流防护)等新机制的引入,攻击技术也在不断发展,安全研究人员需要持续学习和跟进最新技术发展。

Windows下GS保护机制及其绕过技术详解 一、GS保护机制概述 GS(Buffer Security Check)是微软针对栈溢出攻击设计的一种保护机制,其核心思想是通过在栈帧中插入一个随机值(称为Security Cookie或Canary)来检测缓冲区溢出。 1. GS保护机制工作原理 Canary布局 :在栈帧中,Canary被放置在局部变量和返回地址之间 典型栈布局 : Canary生成与验证过程 : 取出.data节的第一个双字作为Cookie种子 将Cookie种子与ESP异或 将异或后的值存入Canary地址 函数返回前进行逆过程验证 2. 变量重排技术 GS还采用了变量重排技术来防止覆盖其他变量: 重排前 : 重排后 : 二、不会启用GS的情况 以下情况编译器不会为函数启用GS保护: 函数不包含缓冲区 函数被定义为具有变量参数列表 函数使用无保护关键字标记 函数在第一个语句中包含内嵌汇编代码 缓冲区不是8字节类型并且不大于4字节 强制启用GS : 三、GS保护机制的绕过技术 1. 攻击未启用GS的函数 直接寻找并攻击程序中未启用GS保护的函数进行溢出攻击。 2. 覆盖虚函数绕过GS 原理 :在Canary检查之前劫持程序流程,利用C++虚函数机制实现。 示例代码 : 攻击步骤 : 通过溢出覆盖对象的虚函数表指针 将虚函数表指针指向攻击者控制的数据 精心构造数据使程序执行攻击代码 Payload构造要点 : 前4字节设置为shellcode地址 后续数据包含实际shellcode 覆盖虚表指针使其指向攻击数据 3. 攻击异常处理绕过GS 原理 :GS不保护SEH(结构化异常处理),通过覆盖异常处理指针实现攻击。 示例代码 : 攻击步骤 : 计算异常处理指针相对于缓冲区的偏移 构造超长字符串覆盖异常处理指针 触发异常使程序执行攻击代码 Payload构造要点 : 在异常处理指针偏移处放置shellcode地址 确保触发异常(如非法内存访问) 4. 同时替换栈和.data中的Cookie绕过GS 原理 :同时修改栈中的Canary和.data中的Cookie种子,使验证通过。 示例代码 : 攻击步骤 : 计算堆地址到.data节Cookie种子的偏移 构造Payload: 前4字节:期望的Cookie值(通常为0x90909090 ^ EBP) 4-8字节:指向.data节Cookie种子的偏移 后续数据:shellcode和返回地址覆盖 Payload示例 : 四、实验环境配置 为进行GS绕过实验,需进行以下VS配置: 在C/C++ → 常规属性中关闭SDL检查 在代码生成中将基本运行时检查设置为默认值 运行库修改为MTD 禁用Spectre缓解(如安装了驱动开发) 在所有选项中关闭控制流防护 禁用安全检查(/GS-)(仅用于测试特定绕过方法) 五、总结 GS保护机制虽然有效,但仍存在多种绕过方法。安全防护与攻击技术总是在不断对抗中发展,理解这些机制和绕过技术对于二进制安全研究至关重要。随着防护技术的演进,如CFG(控制流防护)等新机制的引入,攻击技术也在不断发展,安全研究人员需要持续学习和跟进最新技术发展。