棧溢出原理筆記(一)

系統棧的工做原理

1.內存的不一樣用途
        簡單來講,緩衝區溢出就是在大緩衝區的數據複製到小緩衝區中,因爲沒注意小緩衝區的邊界,」撐爆「了小緩衝區。從而沖掉了小緩衝區相鄰內存區域的數據。
根據不一樣的操做系統,一個進程可能被分配到不一樣內存區域中去執行,可是無論什麼樣的系統,什麼計算機架構,進程使用的內存均可以按照功能分爲4部分:
        代碼區:可執行指令
        數據區:用於存儲全局變量
        堆區:  進程能夠在堆區動態的請求必定大小的內存,並在用完以後歸還給堆區。動態分配和回收是堆區的特色
        棧區:  用於動態的存儲函數之間的調用關係,以保證被調用函數返回時恢復到母函數中繼續執行
        這只是簡單的內存劃分,若是想了解關於內存更詳細的論述,請參考《深刻理解計算機系統》,windows下,PE文件代碼段中包含的二進制機器代碼會被裝入內存的代碼區,處理器將到這裏一條一條的取出指令和操做數,送入算術邏輯單元運算,若是代碼請求開闢動態內存,則會在內存的堆區分配一塊區域返回給代碼區的代碼使用,當函數調用發生時,函數的調用關係等信息會動態的保存在棧區。
程序中所使用的緩衝區能夠是在堆區、棧區、數據區,不一樣地方的緩衝區利用方法不一樣。
2.棧與系統棧
        棧是一種數據結構,是一種先進後出的數據表,用於標識棧的屬性兩個:棧頂、棧底 。內存中的棧區指的就是系統棧,由系統自動維護。
3.函數調用時發生了什麼
        請看以下C代碼:
        int B(int b1,int b2){
                int var_b1=b1+b2;
                int var_b2=b1-b2;
                return var_b1*var_b2;
        }
        int A(int a1,int a2){
                int var_a1;
                var_a=B(a1,a2)+a1;
                return a1;               
        }
        int main(int argc,char **argv,char **envp){
                int var_main;
                var_main=A(4,3);
                return var_main;
        }
        根據操做系統的不一樣、編譯器和編譯選項的不一樣,同一文件不一樣函數的代碼在內存代碼區中的分佈可能相鄰,也可能不相鄰,可能有前後順序,也可能沒有,但他們都是在代碼所映射的節裏
函數調用時,伴隨的系統棧中的操做以下:
在main函數調用A的時候,首先在本身的棧幀中壓入函數返回地址,而後位A建立新棧幀並壓入系統棧 ,
在函數A調用B的時候,一樣先在本身的棧幀中壓入返回地址,而後爲B建立新棧幀並壓入系統棧
B返回時,B的棧幀被彈出系統棧,A棧幀的返回地址被露在棧頂,處理器跳到返回地址處執行
在A返回時,A的棧幀被彈出系統棧,main函數棧幀中的返回地址被露在棧頂。處理器跳到返回地址執行
4.寄存器與函數棧幀
        每個函數獨佔本身的棧幀空間,當前正在運行的函數老是在棧頂,win32系統提供兩個寄存器用於標識位於系統棧頂端的棧幀
         ESP:棧指針寄存器,存放一個指針,該指針永遠指向系統棧最上面的棧幀的棧頂
         EBP:基址指針寄存器,該指針永遠指向系統棧最上面的棧幀的底部
         函數棧幀:ESP和EBP之間內存空間爲當前棧幀
         在函數棧幀中通常包含如下幾種信息:、
         局部變量:爲函數舉報變量開闢的內存空間
         棧幀狀態值:保存前棧幀的頂部和底部(實際上只保存前棧幀的底部,前棧幀的頂部能夠經過堆棧平衡獲得)
         函數返回地址:保存當前函數調用前的「斷點」信息,也就是函數調用前的指令位置
         函數棧幀的大小不固定,通常和局部變量的多少有關
5.函數調用約定與相關指令
        調用約定描述了函數傳遞參數的方式和棧協同工做的技術細節,下面列出幾種調用方式:
                                C                Syscall                Stdcall                BASIC                FORTRAN                PASCAL
參數入棧順序 右→左         右→左                右→左                左→右                 左→右                左→右
誰恢復棧平衡 母函數                子函數                子函數                子函數                子函數                子函數
        對於Visual C++,支持3種函數調用約定:
       
        調用約定聲明                參數入棧順序                誰恢復棧平衡
        __cdecl                                右→左                                母函數
        __fastcall                        右→左                                子函數
        __stdcall                        右→左                                子函數
        除了入棧方向和恢復平衡不一樣以外,參數傳遞有時也會有所不一樣。例如,每個C++類成員函數都有一個this指針,在windows下,這個指針保存在ECX中
,但若是用GCC編譯,這個指針會做爲最後一個參數入棧

        函數調用大體包括如下幾個步驟:
         參數入棧
         返回地址入棧
         代碼區跳轉
         棧幀調整:具體包括
         保存當前棧幀狀態值(push ebp)
         將當前棧幀切換到新棧幀(mov ebp,esp)
         給新棧幀分配空間(把ESP減去所需空間大小,擡高棧頂)
         
        函數返回大體包括如下幾個步驟:
         保存返回值(一般保存在EAX中)
         彈出當前棧幀,恢復上一個棧幀:具體包括
         在堆棧平衡的基礎上給ESP加上棧幀的大小,下降棧頂,回收當前棧幀空間
         將當前棧幀底部保存的前棧幀EBP值彈入EBP,恢復出上一個棧幀
         將函數返回地址彈給EIPwindows

    跳轉數據結構

相關文章
相關標籤/搜索