爲了防止緩衝區溢出時覆蓋函數返回地址,編譯器使用了很酷的編譯選項——GS,GS工作原理如下:
1、在進程調用start( )函數時先初始化.data節區一個叫___security_cookie的變量(一個進程只用這一個___security_cookie值,不會有第二個)
2、在函數調用期間使用___security_cookie和ebp或者esp做亦或操作,並把結果保存在這個函數棧相對靠下的位置
3、這個函數調用結束後,拿步驟2中的變量再和ebp或者esp做亦或操作,結果和___security_cookie作比較,相同則此次函數調用棧未發生溢出,否則發生溢出,結束程序
那麼GS使用的___security_cookie是如何被初始化、發生溢出時又是如何結束進程的?
1、start( )函數第一條指令call ___security_init_cookie,如圖:
___security_init_cookie函數主要代碼:
調用了GetSystemTimeAsFileTime( )、GetTickCount( )、QueryPerformanceCounter( ),GetCurrentProcessId( )、GetCurrentThreadId( )函數,把返回的dword值做多次亦或操作。
2、在函數調用結束判斷棧是否溢出時調用@__security_check_cookie@4函數,如圖:
@__security_check_cookie@4函數代碼:
若發生棧溢出就轉向函數___report_gsfailure( ),___report_gsfailure( )函數最後幾行代碼:
以上測試環境Windows XP(sp3) VS2010