1. 程式人生 > >security cookie 機制(2)--- 初始化___security_cookie

security cookie 機制(2)--- 初始化___security_cookie

在 cookie 檢查中,必定先要取出初始的 cookie 值:

0011392E A1 14 70 11 00       mov         eax,dword ptr [___security_cookie (117014h)]  
00113933 33 C5                xor         eax,ebp  
00113935 89 45 FC             mov         dword ptr [ebp-4],eax 

這個 cookie 值是屬於使用者程序的,在這裡是 helloworld.exe 映像

現在我們來看看這個 cookie 值被初始化什麼,在哪裡初始化?

0:000:x86> uf 0xb21221
helleworld!wWinMainCRTStartup [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 361]:
  361 00b22090 8bff            mov     edi,edi
  361 00b22092 55              push    ebp
  361 00b22093 8bec            mov     ebp,esp
  368 00b22095 e8c5efffff     call    helleworld!ILT+90(___security_init_cookie) (00b2105f)


  370 00b2209a e811000000      call    helleworld!__tmainCRTStartup (00b220b0)
  371 00b2209f 5d              pop     ebp
  371 00b220a0 c3              ret

helleworld!ILT+540(_wWinMainCRTStartup):
00b21221 e96a0e0000     jmp     helleworld!wWinMainCRTStartup (00b22090)

在 helloworld 的 wWinMainCRTStrartup() 啟動例程裡,首先呼叫 __security_init_cookie()例程進行 cookie 初始化,然後跳轉到 __tmainCRTStartup() 最後流轉到使用者 wWinMain(),這些例程都是在使用者空間,屬於使用者程序的。它們是 visual c++ 編譯器為使用者程式安插的啟動例程,並且它們都是有原始碼提供,在 VC 的執行時庫例程裡可以找到原始碼。

下面我們來看看__security_init_cookie()例程是怎樣運作的,在我目錄是:C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\crt\src 下的檔案 gs_support.c

#ifdef _WIN64
#define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232
#else 
#define DEFAULT_SECURITY_COOKIE 0xBB40E64E
#endif 


extern UINT_PTR __security_cookie;
extern UINT_PTR __security_cookie_complement;


typedef union {
    unsigned __int64 ft_scalar;
    FILETIME ft_struct;
} FT;

void __cdecl __security_init_cookie(void)
{
    UINT_PTR cookie;
    FT systime={0};
    LARGE_INTEGER perfctr;

   

    if (__security_cookie != DEFAULT_SECURITY_COOKIE
#if defined (_X86_)
        && (__security_cookie & 0xFFFF0000) != 0
#endif 
       )
    {
        __security_cookie_complement = ~__security_cookie;
        return;
    }


   

    GetSystemTimeAsFileTime(&systime.ft_struct);
#if defined (_WIN64)
    cookie = systime.ft_scalar;
#else 
    cookie = systime.ft_struct.dwLowDateTime;
    cookie ^= systime.ft_struct.dwHighDateTime;
#endif 

    cookie ^= GetCurrentProcessId();
    cookie ^= GetCurrentThreadId();
    cookie ^= GetTickCount();

    QueryPerformanceCounter(&perfctr);
#if defined (_WIN64)
    cookie ^= perfctr.QuadPart;
#else 
    cookie ^= perfctr.LowPart;
    cookie ^= perfctr.HighPart;
#endif 

#if defined (_WIN64)
   
    cookie &= 0x0000FFFFffffFFFFi64;
#endif 

   

    if (cookie == DEFAULT_SECURITY_COOKIE)
    {
        cookie = DEFAULT_SECURITY_COOKIE + 1;
    }
#if defined (_X86_)
    else if ((cookie & 0xFFFF0000) == 0)
    {
        cookie |= ( (cookie|0x4711) << 16);
    }
#endif 

    __security_cookie = cookie;
    __security_cookie_complement = ~cookie;

}

__security_cookie 在 CRT 庫裡是全域性變數,見於另一個檔案 gs_cookie.c

#ifdef _WIN64
#define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232
#else 
#define DEFAULT_SECURITY_COOKIE 0xBB40E64E
#endif 

DECLSPEC_SELECTANY UINT_PTR __security_cookie = DEFAULT_SECURITY_COOKIE;

DECLSPEC_SELECTANY UINT_PTR __security_cookie_complement = ~(DEFAULT_SECURITY_COOKIE);

CRT 庫的 __security_cookie 的值就是 DEFAULT_SECURITY_COOKIE,在 Win32 下被定義為 0xBB40E64E,在 Win64 下被定義為 0x00002B992DDFA232

但是使用者程序的 __security_cookie 值,需進行下面的設定:

  1. 獲得 system time
  2. 與 GetCurrentProcessId() 異或
  3. 與 GetCurrentThreadId() 異或
  4. 與 GetTickCount() 異或
  5. 與 QueryPerformanceCounter()異或

經過一系列異或使用者的 __security_cookie 值就出來,我們大概可以猜到 DEFAULT_SECURITY_COOKIE 這個值就是根據這樣算出來的,因此如果算出來結果還是等於 DEFAULT_SECURITY_COOKIE 那麼就需要加上1


版權 mik 所有,轉載請註明出處