(二)簡易實現棧溢位實驗(OllyDbg)

2020-10-13 12:00:38

開頭

上一篇部落格講到了棧溢位,關於做棧溢位實驗,可使用的工具是反組合工具。
之前講到了IDA的實現:

點選進入IDA實現棧溢位部落格

感興趣的也可以看看。
~
現在說到老師上課可能更喜歡用的反組合軟體OllyDbg,來實現一下簡單的棧溢位實驗。
~

軟體介紹:OllyDbg

在這裡插入圖片描述
在這裡插入圖片描述

摘自百度:

<<<OD,是一個反組合工具,又叫OllyDebug,一個新的動態追蹤工具,將IDA與SoftICE結合起來的思想,Ring 3 級的偵錯程式,己代替SoftICE成為當今最為流行的偵錯解密工具了。同時還支援外掛擴充套件功能,是目前最強大的偵錯工具。基本上,偵錯自己的程式因為有原始碼,一般用vc,破解別人的程式用OllyDebug。>>>

~
~~下面簡稱OD
~

IDA與OD

~
說簡單點,OD是一款火爆的反組合工具,免費也是其特點,優點可能對電腦環境要求並不高,缺點是其執行很複雜,函數名之類的資訊不清晰,等於要自己找。
IDA相比於OD,更加方便,這點可以從我上一篇部落格看出,同時IDA操作簡單,但要付費。即使其破解版在機房的電腦上一般不好執行,所以導致學校老師教學一般用OD。這裡開講,怎麼用更復雜的OD(ollydbg).
~

1.開啟軟體

在這裡插入圖片描述
可以清楚看到介面:
看到很多框體,再細看一下:
在這裡插入圖片描述

2.準備好要執行的程式

即準備好實現棧溢位的程式碼,和上一篇部落格程式碼一樣,可以對比:
~

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void attack()
{
	printf("This is attack.\n");       //attack函數
}
void func()                     //func函數
{
	char password[6] = "ABCDE";
	char str[6];
	FILE *fp;
	if(!(fp=fopen("D:\\password.txt","r"))) //開啟D槽的password.txt檔案
		exit(0);
	fscanf(fp,"%s",str);           //將str的內容寫入fp
	str[5]='\0';
	if(strcmp(str,password)==0)    //判斷str是否與password相同
		printf("OK.\n");
	else
		printf("NO.\n");
}
int main()
{
	func();          //執行func函數
	return 0;
}

~
同樣上面的fscanf函數是導致棧溢位的問題所在,也就是說當fscanf讀取了大於str容量的字串,導致了其資料在棧上的溢位,從而影響函數的正常執行。
類似的,像gets,strcpy等函數,當讀取比設定的容量大時,都會發生棧溢位。
~

注意:

~
為防止棧溢位漏洞出現,最近的vs系列,vs2018,2019等都會提醒不要使用不安全的函數,而使用安全的會進行邊界檢查的函數。所以棧溢位實驗無法在vs系列上實現。
~
vc 6.0 和 codeblocks上依舊可以進行棧溢位實驗。可以在這兩個編譯器上實現該實驗。

3.程式碼執行

在這裡插入圖片描述
在記事本中輸入AAAAAA…執行程式,由於其與password不同,所以輸出「NO」

4.OD開始反組合

將該程式的可執行檔案拖入OD:
在這裡插入圖片描述
出現了很多複雜的資料。其實現在只需要關注左上角的區域即可:(放大來看)
這是各區域的程式碼

1,首先看左邊紅色區域:大家應該很熟悉,這是16進位制碼
2,中間藍色的區域:這是組合程式碼,學過組合的人看得出來。
3. 右邊紫色框選的區域:可以看作為虛擬碼,(個人認為)可以看到出現了一些程式中有的字串和一些類似的細節。
~
相當於中間是組合程式碼,即該exe檔案轉換為的組合程式碼,左邊是該行對應的16進位製程式碼,右邊是虛擬碼。
~
這裡和IDA的分析結果一樣,都通過反組合,讓你得以檢視可執行檔案的組合程式碼和虛擬碼,當然也能檢視棧。
~
IDA是分散的框體。而OD把其放在了一起。
~
這裡就要說到IDA的函數名很方便查詢,而OD得函數名只能自己從上表中分析,甚至沒有明確的函數名。
~
但是
~
OD可以進行動態偵錯,而IDA只能靜態,這是截然不同的,但又相互聯絡。

重要:OllyDbg的相關快捷鍵

這個是很重要的OD的操作快捷鍵,其實更多的功能,自己可以試出來,這裡只說必須的:
~
(1)F2(左鍵雙擊):設定斷點
~
在這裡插入圖片描述
在這裡插入圖片描述

雙擊或F2的位置變紅了,當程式再執行時,會自動執行到斷點處,則不會再往下執行。用於動態分析檢視。 再按F2取消斷點。 或者點選右鍵選擇–>breakpoint–>toggle.
~
(2) F7,選中的區域向下,但碰到子程式時會進入其中,可以檢視子程式資訊。
~
(3) F8,單純地向下一個資訊移動。
~
(4)Ctrl+F12, 即為"restart"重新開始執行程式, 但會在斷點處停住:
在這裡插入圖片描述
(5)F9 繼續執行函數,直至斷點:
在這裡插入圖片描述

4.開始分析如何「棧溢位」

這個框體裡的內容很多,向下滾輪,在最右邊的虛擬碼中尋找與程式碼有關的內容,人看的懂的內容。在往下滾時,看到了"this is attack","password"字樣,說明找到了func()和attack()函數(見下圖)
在這裡插入圖片描述
那麼下圖框選的"PUSH EBP"應該是attack(),func()函數的開頭,記下函數入口地址:
~
attack()地址: 00401350
func()函數地址:00401365
~
在這裡插入圖片描述
再稍微往下一劃,看到"fopen,fscanf"等函數,以及"OK"和"NO"的程式碼區
棧溢位發生在fscanf函數處,不如在fscanf下,strcmp之上,設定一個斷點,再次執行後,函數會停在那裡。
在這裡插入圖片描述
之後,按「F7」向下執行,碰到子程式,就會自動進入子程式。果然在"004013D1"處發生了跳轉,其組合程式碼中CALL也是一種跳轉的程式碼。檢視到了str所在的棧。
注意:在這裡設定一個斷點
在這裡插入圖片描述

5.看到棧的資訊

可以看到文字檔案輸入的"AAAAA…「在棧道中一目瞭然:
這裡就是OD中棧的資訊:
~
該結構與之前的類似:
左邊的"41414141"是16進位制,中間的「AAA」是你輸入的字串,右邊類似虛擬碼
~
在這裡插入圖片描述
當你在文字中輸入不同數目的A時,你會發現A是從上往下增長的,輸入不同的A,然後restart重新執行,再按F9 .
~
A明顯從「0060FEE0」處往下增長,
~
在棧中看到(下圖)在「0060FEFC」處存的是"RETURN from"函數,可以得知函數執行到此處時會進行跳轉,這就是所謂的"ret」,跳轉地址。
~

在這裡插入圖片描述
在上圖可以看到「RETURN」右邊的地址為「00401407」說明函數執行到這裡會跳轉到「00401407」,從「RETURN…」一串英文的意思也可以看出。那麼只要將文字中輸入的A的數量增加,那麼,A就會覆蓋其正確的地址。
~
「0060FEFC」處存放了要返回的地址,而其上面就是文字輸入的A,A往下溢位會影響其地址。
~
因為A會往下堆積,溢位到「RETURN 」處,只要將A們的最後四位改成其他地址,那麼函數就會跳轉到別的地方。
~
在這裡插入圖片描述

6.修改文字,製造棧溢位

從上圖看出從開頭的地址到跳轉地址有7行,即28個十六進位制。
~
那麼,在文字中先輸入28個A,再加入attack()函數的地址,返回地址就會被覆蓋。
~
用HxD進行編輯:
在這裡插入圖片描述
編譯後,再用OD,Ctrl+F2,重新來過,不停按F9,來到這裡:
在這裡插入圖片描述
可以看到原本的「0060FEFC」即返回地址,已經變成了,attack()函數的入口,上面全是AAAAA,而這地址就是剛剛輸入的。
~
再看看函數的執行結果:
果然
~

7. 結果

在這裡插入圖片描述
成功了。原理與上次的一樣,有點複雜,大家想的話可以細看。感謝閱讀。