zoukankan      html  css  js  c++  java
  • GS安全编译选项原理分析

    GS编译选项的文件为gs_support.c 这是源码

    /***
    *gs_support.c - initialize the global buffer overrun security cookie
    *
    *       Copyright (c) Microsoft Corporation.  All rights reserved.
    *
    *Purpose:
    *       Define __security_init_cookie, which is called at startup to initialize
    *       the global buffer overrun security cookie used by the /GS compile flag.
    *
    *******************************************************************************/
    
    #include <Windows.h>
    
    #if defined (_M_IX86) && defined (_CRTBLD) && defined (_DEBUG)
    /*
     * __security_init_cookie must be called before any exception handlers using
     * the cookie are registered.  We do a spot check for this condition in the
     * debug version of the x86 CRT.
     */
    
    #define CHECK_FOR_LATE_COOKIE_INIT
    
    #define EXCEPTION_CHAIN_END ((struct _EXCEPTION_REGISTRATION_RECORD * POINTER_32)-1)
    
    EXCEPTION_DISPOSITION __cdecl
    _except_handler4(
        IN struct _EXCEPTION_RECORD *ExceptionRecord,
        IN PVOID EstablisherFrame,
        IN OUT struct _CONTEXT *ContextRecord,
        IN OUT PVOID DispatcherContext
        );
    
    #endif  /* defined (_M_IX86) && defined (_CRTBLD) && defined (_DEBUG) */
    
    /*
     * Default value used for the global /GS security cookie, defined here and
     * in gs_cookie.c (since standalone SDK build can't use CRT's internal.h).
     */
    
    #ifdef _WIN64
    #define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232
    #else  /* _WIN64 */
    #define DEFAULT_SECURITY_COOKIE 0xBB40E64E
    #endif  /* _WIN64 */
    
    /*
     * The global security cookie.  This name is known to the compiler.
     */
    extern UINT_PTR __security_cookie;
    extern UINT_PTR __security_cookie_complement;
    
    /*
     * Union to facilitate converting from FILETIME to unsigned __int64
     */
    typedef union {
        unsigned __int64 ft_scalar;
        FILETIME ft_struct;
    } FT;
    
    /***
    *__get_entropy() - retrieve entropy from the underlying OS.
    *
    *Purpose:
    *       Static helper to encapsulate entropy extraction from the OS.
    *       Combine a number of sources of randomness.
    *
    *Entry:
    *
    *Exit:
    *
    *Exceptions:
    *
    *******************************************************************************/
    
    /*
    * Enclaves initialize the stack cookie in the loader (similar to all
    * modern platforms), but do not expose entropy. No attempt should be made
    * to reinitialize the cookie by harvesting new entropy.
    */
    #if defined (_SCRT_ENCLAVE_BUILD)
    
    static UINT_PTR __get_entropy(void)
    {
        return DEFAULT_SECURITY_COOKIE;
    }
    
    #else
    
    static UINT_PTR __get_entropy(void)
    {
        UINT_PTR cookie;
        FT systime = { 0 };
        LARGE_INTEGER perfctr;
    
        GetSystemTimeAsFileTime(&systime.ft_struct);
    #if defined (_WIN64)
        cookie = systime.ft_scalar;
    #else  /* defined (_WIN64) */
        cookie = systime.ft_struct.dwLowDateTime;
        cookie ^= systime.ft_struct.dwHighDateTime;
    #endif  /* defined (_WIN64) */
    
        cookie ^= GetCurrentThreadId();
        cookie ^= GetCurrentProcessId();
    
    #if _CRT_NTDDI_MIN >= NTDDI_VISTA
    #if defined (_WIN64)
        cookie ^= (((UINT_PTR)GetTickCount64()) << 56);
    #endif  /* defined (_WIN64) */
        cookie ^= (UINT_PTR)GetTickCount64();
    #endif  /* _CRT_NTDDI_MIN >= NTDDI_VISTA  */
    
        QueryPerformanceCounter(&perfctr);
    #if defined (_WIN64)
        cookie ^= (((UINT_PTR)perfctr.LowPart << 32) ^ perfctr.QuadPart);
    #else  /* defined (_WIN64) */
        cookie ^= perfctr.LowPart;
        cookie ^= perfctr.HighPart;
    #endif  /* defined (_WIN64) */
    
        /*
        * Increase entropy using ASLR relocation
        */
        cookie ^= (UINT_PTR)&cookie;
    
    #if defined (_WIN64)
        /*
        * On Win64, generate a cookie with the most significant word set to zero,
        * as a defense against buffer overruns involving null-terminated strings.
        * Don't do so on Win32, as it's more important to keep 32 bits of cookie.
        */
        cookie &= 0x0000FFFFffffFFFFi64;
    #endif  /* defined (_WIN64) */
    
        return cookie;
    }
    
    #endif
    
    /***
    *__security_init_cookie() - init buffer overrun security cookie.
    *
    *Purpose:
    *       Initialize the global buffer overrun security cookie which is used by
    *       the /GS compile switch to detect overwrites to local array variables
    *       that potentially corrupt the return address.  This routine is called
    *       at EXE/DLL startup.
    *
    *Entry:
    *
    *Exit:
    *
    *Exceptions:
    *
    *******************************************************************************/
    
    void __cdecl __security_init_cookie(void)
    {
        UINT_PTR cookie;
    
        /*
         * Do nothing if the global cookie has already been initialized.  On x86,
         * reinitialize the cookie if it has been previously initialized to a
         * value with the high word 0x0000.  Some versions of Windows will init
         * the cookie in the loader, but using an older mechanism which forced the
         * high word to zero.
         */
    
        if (__security_cookie != DEFAULT_SECURITY_COOKIE
    #if defined (_M_IX86)
            && (__security_cookie & 0xFFFF0000) != 0
    #endif  /* defined (_M_IX86) */
           )
        {
            __security_cookie_complement = ~__security_cookie;
            return;
        }
    
    
        /*
         * Initialize the global cookie with an unpredictable value which is
         * different for each module in a process.
         */
        cookie = __get_entropy();
    
        /*
         * Make sure the cookie is initialized to a value that will prevent us from
         * reinitializing it if this routine is ever called twice.
         */
    
        if (cookie == DEFAULT_SECURITY_COOKIE)
        {
            cookie = DEFAULT_SECURITY_COOKIE + 1;
        }
    #if defined (_M_IX86)
        else if ((cookie & 0xFFFF0000) == 0)
        {
            cookie |= ( (cookie|0x4711) << 16);
        }
    #endif  /* defined (_M_IX86) */
    
        __security_cookie = cookie;
        __security_cookie_complement = ~cookie;
    
    }

    要说的是 32位默认的值是0xBB40E64E  64位0x00002B992DDFA232

     直接看反汇编也很明显

    .text:004135E0 PerformanceCount= LARGE_INTEGER ptr -14h
    .text:004135E0 SystemTimeAsFileTime= _FILETIME ptr -0Ch
    .text:004135E0 var_4           = dword ptr -4
    .text:004135E0
    .text:004135E0                 push    ebp
    .text:004135E1                 mov     ebp, esp
    .text:004135E3                 sub     esp, 14h
    .text:004135E6                 xor     eax, eax
    .text:004135E8                 mov     [ebp+SystemTimeAsFileTime.dwLowDateTime], eax
    .text:004135EB                 mov     [ebp+SystemTimeAsFileTime.dwHighDateTime], eax
    .text:004135EE                 lea     ecx, [ebp+SystemTimeAsFileTime]
    .text:004135F1                 push    ecx             ; lpSystemTimeAsFileTime
    .text:004135F2                 call    ds:GetSystemTimeAsFileTime
    .text:004135F8                 mov     edx, [ebp+SystemTimeAsFileTime.dwLowDateTime]
    .text:004135FB                 mov     [ebp+var_4], edx
    .text:004135FE                 mov     eax, [ebp+var_4]
    .text:00413601                 xor     eax, [ebp+SystemTimeAsFileTime.dwHighDateTime]
    .text:00413604                 mov     [ebp+var_4], eax
    .text:00413607                 call    ds:GetCurrentThreadId
    .text:0041360D                 xor     eax, [ebp+var_4]
    .text:00413610                 mov     [ebp+var_4], eax
    .text:00413613                 call    ds:GetCurrentProcessId
    .text:00413619                 xor     eax, [ebp+var_4]
    .text:0041361C                 mov     [ebp+var_4], eax
    .text:0041361F                 lea     ecx, [ebp+PerformanceCount]
    .text:00413622                 push    ecx             ; lpPerformanceCount
    .text:00413623                 call    ds:QueryPerformanceCounter
    .text:00413629                 mov     edx, [ebp+var_4]
    .text:0041362C                 xor     edx, dword ptr [ebp+PerformanceCount]
    .text:0041362F                 mov     [ebp+var_4], edx
    .text:00413632                 mov     eax, [ebp+var_4]
    .text:00413635                 xor     eax, dword ptr [ebp+PerformanceCount+4]
    .text:00413638                 mov     [ebp+var_4], eax
    .text:0041363B                 mov     ecx, [ebp+var_4]
    .text:0041363E                 lea     edx, [ebp+var_4]
    .text:00413641                 xor     ecx, edx
    .text:00413643                 mov     [ebp+var_4], ecx
    .text:00413646                 mov     eax, [ebp+var_4]
    .text:00413649                 mov     esp, ebp
    .text:0041364B                 pop     ebp
    .text:0041364C                 retn
    .text:0041364C sub_4135E0      endp
    .text:0041364C

    security_cookie 32位计算方式就是

    1. 获得 system time
    2. 与 GetCurrentProcessId() 异或
    3. 与 GetCurrentThreadId() 异或
    4. 与 GetTickCount() 异或
    5. 与 QueryPerformanceCounter()异或

    64位的可以看原码大同小异

    绕过方法也大同小异

    1虚表,

    2攻击seh,

    3读到security_cookie,

    4在运行前篡改security_cookie,

    5劫持GetSystemTimeAsFileTime,

    6,溢出1字节篡改security_cookie,在启动是就不会重新刷新cookie 第二次攻击就可以溢出

     这里通过第三方劫持篡改security_cookie的值  

    从此山高路远,纵马扬鞭。愿往后旅途,三冬暖,春不寒,天黑有灯,下雨有伞。此生尽兴,不负勇往。
  • 相关阅读:
    Linux系统编程 —互斥量mutex
    Linux系统编程 —读写锁rwlock
    Linux系统编程—条件变量
    Linux系统编程—信号量
    SkyWalking 源码的整体结构
    带拼音插件的索引和映射创建
    磁盘扩容后文件目录迁移步骤
    应用注册Eureka配置
    StringUtils.hasText()
    Java后台进行分页参数类封装
  • 原文地址:https://www.cnblogs.com/feizianquan/p/15601713.html
Copyright © 2011-2022 走看看