一、漏洞
是計算機系統(tǒng)的硬件、軟件、協(xié)議在系統(tǒng)設計、具體實現(xiàn)、系統(tǒng)配置或安全策略上存在的缺陷
漏洞是計算機系統(tǒng)本身存在的缺陷,漏洞存在和利用都有一定的環(huán)境要求,漏洞本身是沒有危害的,只有被攻擊者惡意利用,才能給計算機系統(tǒng)帶來威脅和損失。

漏洞是攻擊的一個入口

二、漏洞分類

根據(jù)漏洞形成的原因進行分類
輸入驗證錯誤漏洞
緩沖區(qū)溢出漏洞
輸入的數(shù)據(jù)超過其規(guī)定長度,造成緩沖區(qū)溢出,破壞程序正常的堆棧,使程序執(zhí)行其他指令
設計錯誤漏洞
設計不合理
意外情況處理錯誤漏洞
一些意外情況沒有考慮到
訪問驗證錯誤漏洞
訪問驗證部分存在錯誤
配置錯誤漏洞
配置參數(shù)、訪問權限、策略安裝位置有誤
競爭條件漏洞
環(huán)境錯誤漏洞
外部數(shù)據(jù)被異常執(zhí)行漏洞
用戶在外部非法輸入的數(shù)據(jù),被系統(tǒng)作為代碼解釋執(zhí)行,典型的有SQL注入和XSS等。



根據(jù)漏洞的生命周期不同階段
0day漏洞
還處于未公開狀態(tài)的漏洞。危害比較大
1day漏洞
通常指發(fā)布補丁時間不長的漏洞,但是安裝這些補丁的人并不多,這種漏洞仍存在一定的危害
以公開漏洞
大多數(shù)用戶已經(jīng)打過補丁的漏洞

。



三、公開的漏洞庫
CVE NVD BugTraq CNNVD CNVD
漏洞庫提供了操作系統(tǒng)和應用程序特定版本所包含的漏洞信息,部分漏洞的專家建議、修復辦法和專門的補丁程序,極少數(shù)的漏洞庫還提供了檢測、測試漏洞的樣本驗證代碼POC

POC (proof of concepts,為觀點提供漏洞)
樣本驗證代碼,POC是為了驗證漏洞是否存在的代碼

CVE 行業(yè)標準
CVE (common vulnerabilities and Exposures)通用漏洞列表,相當于軟件漏洞的行業(yè)標準。
實現(xiàn)了安全漏洞命名機制的規(guī)范化和標準化。

NVD 美國的 世界上最大的
NVD 美國國家漏洞數(shù)據(jù)庫
CNNVD
中國國家信息安全漏洞庫 隸屬于中國信息安全測評中心,測評
CNVD
國家信息安全漏洞共享平臺,是國家互聯(lián)網(wǎng)應急中心CN CERT /CC維護的漏洞庫,致力于建設信息安全漏洞共享知識庫


針對漏洞的應急響應機構
美國 US-CERT
中國 國家互聯(lián)網(wǎng)應急中心 CNCERT 或者簡稱CC
是漏洞數(shù)據(jù)的主要提供者或漏洞庫的主要維護者

四、第一個漏洞 (VC2005)
溢出漏洞 。通過緩沖區(qū)溢出來更改返回地址的值,導致程序執(zhí)行的流程發(fā)生改變。
#include<iostream>
using namespace std;
void why_here() {
printf("why u r here?\n");
exit(0);
}
void f() {
int buf[1];
//函數(shù)名表示函數(shù)在代碼空間的地址
//編譯器沒有對邊界值進行檢測
buf[2] = (int)why_here;
}
int main() {
f();
return 0;
}

溢出漏洞 造成了返回地址被修改
指令寄存器EIP沒有跳轉到主函數(shù)而是跳轉到why_here中去了。
對下列程序進程修改,從而造成溢出漏洞

填*(p+2) 或p[2] (指向的內容進行修改)
原因:局部變量按照聲明的順序來申請空間

修改(p+2)指向的內容
五緩沖區(qū)溢出漏洞
緩沖區(qū):緩沖區(qū)是一塊連續(xù)的內存區(qū)域,用于存放程序運行時加載到內存的運行代碼和數(shù)據(jù)。
緩沖區(qū)溢出:緩沖區(qū)溢出是指程序運行時,向固定大小的緩沖區(qū)寫入超過其容量的數(shù)據(jù),多余的數(shù)據(jù)會越過緩沖區(qū)的邊界覆蓋相鄰內存空間,從而造成溢出。

緩沖區(qū)溢出產(chǎn)生的根本原因:出于效率的考慮,部分函數(shù)不對數(shù)組邊界條件和函數(shù)指針引用進行邊界檢查。檢查交給程序員來進行

1棧溢出
寫入數(shù)據(jù)的長度,大于棧幀的基址ebp到esp之間預留的保存局部變量的空間


棧溢出漏洞的利用
修改返回地址



輸入 AAAABBBBCCCCDDDD
修改臨接變量的值(落后)


漏洞:在調用strcpy函數(shù)時,沒有對password進行長度檢查,導致buffer申請的空間溢出,覆蓋掉了authenticated的部分值
攻擊方法:輸入一個長度為8位的字符串,這樣buffer[8]就變成了0(0是字符串的結束標識符)用來覆蓋相鄰的局部變量,同時輸入的字符串要大于PASSWORD這樣局部變量的初值才能是1,用buff[8]來覆蓋局部變量10000中的1。


是小端存儲
這種方法已經(jīng)落后了,現(xiàn)在變量之間會有一些隨機數(shù),這樣溢出時,只會修改隨機數(shù)的值,不會影響鄰接變量
2堆溢出
在堆中發(fā)生的緩沖區(qū)溢出。棧溢出隨著編譯器的各種安全措施,越來越難實現(xiàn)。堆溢出已經(jīng)成為緩沖區(qū)溢出的主要方式之一,利用堆溢出可以有效地繞過基于棧溢出的防護措施。

動態(tài)申請8個字節(jié)的空間,但是在這8個空間中放入24個字節(jié),從而造成了堆溢出,覆蓋了堆管理結構


ecx為可分配堆區(qū)塊的前指針,edi為可分配堆區(qū)塊的后指針,現(xiàn)在ecx已經(jīng)被CCCC覆蓋edi被DDDD覆蓋
mov dword ptr [edi] ,ecx 把ecx中雙字型(32位)數(shù)據(jù)賦給edi
堆溢出 修改了堆管理結構的指針的值,從而造成了可以向任意內存單元寫入任意數(shù)據(jù)

3單字節(jié)溢出
是指程序中的緩沖區(qū)僅能溢出一個字節(jié),可以用來修改臨接變量或者函數(shù)返回值(必須緊挨棧幀指針ebp)


格式化串漏洞
什么是格式化串呢?
printf () 等系列函數(shù)可以按照一定的格式將數(shù)據(jù)進行輸出
一般形式為
printf( "format",輸出列表) //format就是格式化串


在printf中如果只提供了格式化符號串(例如%d %s等)沒有提供參數(shù)(輸出列表),那么函數(shù)會將格式化字符
串后面的多個棧的內容彈出來作為參數(shù),并根據(jù)格式化符號將其輸出。

char *buf 對應的輸入類型是諸如 "%x%x%x%x...%x"等

%n不是格式化操作,而是將到%n為止的字符串的長度寫入到參數(shù)指定的位置

利用%n可以實現(xiàn)像任意地址寫入任意的數(shù)
例如 sprintf函數(shù)的作用是把格式化的數(shù)據(jù)寫入某個字符緩沖區(qū)。
int sprintf(緩沖區(qū),格式化字符串,參數(shù))

調用這段程序時,用aaaabbbcc%n作為命令行參數(shù),沒有對應的參數(shù),那么棧就會彈出已經(jīng)讀取的字符作為參數(shù),所以把aaaa彈出作為了參數(shù),由于aaaabbbbcc長度為10,那么最終10就會被寫入到aaaa對應的地址中去


六、漏洞利用 expliot
Expliot漏洞利用,有漏洞不一定就有利用,但是有漏洞利用expliot就有漏洞
漏洞利用的手段
如何向進程中植入一段用于獲得shell的代碼,并且將這段植入進程的代碼稱為shellcode
shell
shell是系統(tǒng)的用戶界面,提供了用戶與內核進行交互操作的一種接口。它接收用戶輸入的命令并把它送入內核去執(zhí)行
實際上shell是一個命令解釋器,它解釋由用戶輸入的命令并且把它們送到內核。
漏洞利用的核心
漏洞利用的核心就是利用程序漏洞去執(zhí)行shellcode(shellcode是向進程中植入的代碼)以便劫持進程的控制權。要達到該目的,需要通過代碼植入的方式來完成,其目的是淹沒返回地址,以便劫持進程的控制權,讓程序跳轉去執(zhí)行shellcode

漏洞:verify函數(shù)沒有對輸入的字符長度進行檢查,可能會發(fā)生溢出


漏洞的利用:可以選擇覆蓋flag的值從而通過驗證,也可以選擇覆蓋返回地址植入代碼從而改變程序

掩蓋flag
輸入48個字符從而淹沒flag的值,最后4個字符的值全0,其它字符任意

植入代碼
植入方法:直接輸入機器代碼(語言)(相當于直接輸入指令)





最后用buffer的地址來覆蓋返回地址是因為,之前輸入的機器代碼都存放在buffer數(shù)組中,當前函數(shù)結束后轉跳到buffer數(shù)組就可以開始執(zhí)行這些機器代碼,從而達到注入的效果
不過winxp之后 上述代碼就不能用了,因為只有在winxp中 API的地址才是靜態(tài)的,也就是說在別的系統(tǒng)中window函數(shù)的入口地址都是動態(tài)變化的。
高級語言、匯編語言和機器語言區(qū)別
機器語言:是二進制代碼語言,能夠被計算機直接執(zhí)行。
匯編語言:是通過助記符來表示機器語言的符號語言,匯編語言和機器語言一一對應,一個匯編指令對應唯一的機器代碼
高級語言:更加自然地語言,通俗易懂。
通常運行一個由高級語言編寫的程序,需要先通過編譯器轉化為匯編語言,然后匯編語言跟機器語言一一對應,翻譯為機器能夠直接執(zhí)行的機器語言。
七shellcode的編寫 pwn
編寫難題

第一步:先用高級語言書寫要執(zhí)行的shellcode

第二步:換成對應的匯編代碼

第三步:根據(jù)匯編代碼,找到對應地址中的機器碼

\x是轉義字符,告訴編譯器需要用特殊的方式進行處理。\x表示后面的字符是十六進制數(shù),\0表示后面的字符是八進制數(shù)。
"\x33" //告訴編譯器這個字符是16進制數(shù)
