pwn入門:sploitfun-典型的基於堆棧的緩衝區溢出詳解

虛擬機環境:Ubuntu 14.04(x86)

本文是基於sploitfun系列教程的詳細解析,sploitfun對於純新手而言,其中有些東西還是不夠詳細,新手不能很好的接觸到其中原理,故作此文進行補充

編譯代碼第一行,表示關閉ASLR(地址空間佈局隨機化)。kernel.randomize_va_space堆棧地址隨機初始化,很好理解,就是在每次將程序加載到內存時,進程地址空間的堆棧起始地址都不一樣,動態變化,導致猜測或找出地址來執行shellcode 變得非常困難。

編譯代碼第二行表示,gcc編譯時,關閉DEP和棧保護。

當-f-stack-protector啓用時(CANNARY棧保護),當其檢測到緩衝區溢出時(例如,緩衝區溢出攻擊)時會立即終止正在執行的程序,並提示其檢測到緩衝區存在的溢出的問題。這是gcc編譯器專門爲防止緩衝區溢出而採取的保護措施,具體方法是gcc首先在緩衝區被寫入之前在buf的結束地址之後返回地址之前放入隨機的gs驗證碼,並在緩衝區寫入操作結束時檢驗該值。通常緩衝區溢出會從低地址到高地址覆寫內存,所以如果要覆寫返回地址,則需要覆寫該gs驗證碼。這樣就可以通過比較寫入前和寫入後gs驗證碼的數據,判斷是否產生溢出。

NX即No-execute(不可執行)的意思,NX(DEP)的基本原理是將數據所在內存頁標識爲不可執行,當程序溢出成功轉入shellcode時,程序會嘗試在數據頁面上執行指令,此時CPU就會拋出異常,而不是去執行惡意指令。

工作原理如下圖:

 

Gcc默認開啓NX選項,如果需要關閉NX選項可以給gcc編譯器添加-z  execstack參數

編譯代碼第三至第五行。更改文件權限

chgrp命令,改變文件或目錄所屬的組。

chown命令,chown將指定文件的擁有者改爲指定的用戶或組。用戶可以是用戶名或用戶ID。組可以是組名或組ID。文件是以空格分開的要改變權限的文件列表,支持通配符。

Chown +s命令,爲了方便普通用戶執行一些特權命令,SUID/SGID程序允許普通用戶以root身份暫時執行該程序,並在執行結束後再恢復身份。chmod +s 就是給某個程序或者教本以suid權限

 

上述漏洞代碼的第【2】行,可能造成緩衝區溢出錯誤。這個bug可能導致任意代碼執行,因爲源緩衝區內容是用戶輸入的!

我們通過覆蓋返回地址,可以實現任意代碼執行。

先反彙編main函數,disassemble main或者disass main

下面是收集到的棧溢出背景知識:

函數狀態主要涉及三個寄存器--esp,ebp,eip。esp 用來存儲函數調用棧的棧頂地址,在壓棧和退棧時發生變化。ebp 用來存儲當前函數狀態的基地址,在函數運行時不變,可以用來索引確定函數參數或局部變量的位置。eip 用來存儲即將執行的程序指令的地址,cpu 依照 eip 的存儲內容讀取指令並執行,eip 隨之指向相鄰的下一條指令,如此反覆,程序就得以連續執行指令。

 

下面讓我們來看看發生函數調用時,棧頂函數狀態以及上述寄存器的變化。變化的核心任務是將調用函數(caller)的狀態保存起來,同時創建被調用函數(callee)的狀態。

 

首先將被調用函數(callee)的參數按照逆序依次壓入棧內。如果被調用函數(callee)不需要參數,則沒有這一步驟。這些參數仍會保存在調用函數(caller)的函數狀態內,之後壓入棧內的數據都會作爲被調用函數(callee)的函數狀態來保存。

 

如上述介紹,彙編代碼含義如圖

前七句,爲開始的初始化,第八到第十句爲strcpy準備參數,第十一句調用strcpy函數,第十二到十四句爲printf準備參數,第十五句調用printf函數,後面就是清理棧和return的收尾3環節

此時棧的分佈大致如圖所示: 

測試步驟1:是否可以覆蓋返回地址?

以Python命令運行,輸入300個A,結果如圖,p查看寄存器,/x以十六進制,看到指令寄存器已經被AAAA覆蓋,確定覆蓋返回地址是可能的。

接下來,我們要確定Return Address相對於buf ends的偏移量,首先caller’s EBP有0x4個偏移量,但是由於有一個棧平衡操作,所以buf ends和caller’s EBP之間還可能存在對其空間,但是我們不知道具體空間,可以自己填充來一點點嘗試,如下圖

 

我們獲得了返回地址距目標緩衝區buf的偏移量0x10c,

0x10c=0x100+0x8+0x4,0x100是buf大小,0x8是對其空間,0x4是ebp

 

這裏繼續補充一點shellcode的背景知識。

shellcode--修改返回地址,讓其指向溢出數據中的一段指令。

 

我們要完成的任務包括:在溢出數據內包含一段攻擊指令,用攻擊指令的起始地址覆蓋掉返回地址。攻擊指令一般都是用來打開 shell,從而可以獲得當前進程的控制權,所以這類指令片段也被成爲“shellcode”。shellcode 可以用彙編語言來寫再轉成對應的機器碼,也可以上網搜索直接複製粘貼,這裏就不再贅述。下面我們先寫出溢出數據的組成,再確定對應的各部分填充進去。

 

構造shellcode代碼 

完成圖

這裏給幾處解釋說明

先是struct.pack(“<I”, num),<表示小端序,I表示無符號整型

詳情見:https://blog.csdn.net/weiwangchao_/article/details/80395941

Shellcode,詳情見:http://blog.nsfocus.net/easy-implement-shellcode-xiangjie/

 背景知識,詳情見:https://zhuanlan.zhihu.com/p/25816426

 

 

本人文章首發在安全客,轉載自:https://www.anquanke.com/post/id/176283 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章