像溢出攻擊,雖然已經是發展了那么多年了,但其shellcode編寫也差不多是那么一個模式。寫出匯編,編譯,得到二進制代碼,修改匯編,編譯,再得到二進制代碼,最后用\xaa\xbb的形式把二進制代碼寫到攻擊程序里面。這在unix等下面一般shellcode要求比較簡單,那還勉強過得去,但如果應用限制,shellcode代碼不能包含一些特殊字符那又是一個麻煩的調試、修改過程。還有溢出攻擊的溢出點、怎么跳到shellcode,雖然unix下面已經比較多的辦法了,但感覺也沒怎么統一的考慮過,很多人也沒有去理解溢出攻擊。還有溢出過程形參被覆蓋后不能返回的情況,也沒怎么仔細考慮。
個人的理解溢出攻擊只是通過外部條進改變了程序原來流程,而考慮改變程序流程的辦法就不只是溢出了,溢出攻擊只是一個比較容易讓程序流程改變并且按我們意愿運行的比較方便的辦法,還有一些邊界條進,函數指針等都可能引起程序流程改變。像緩沖溢出覆蓋形式參數不能返回的問題,我們攻擊是改變的程序流程,這個流程方向不能返回了,那到底有別的流程沒有?就可以考慮程序流程的別的線。這點unix下面有信號機制,WINDOWS下面也有異常結構處理,這些都是程序運行的另一個隱蔽的流程。想到這了就可以有解決辦法了。其實UNIX等下面發展的比較好的一些保護緩沖溢出的辦法很多也相應有了一些破解思路。像堆棧里面加上隨機數等的辦法,就是檢測溢出后不讓其返回到溢出代碼,這與形參被覆蓋不能返回不就是一樣的嗎。這在windows下面就很好的可以繞過了,UNIX沒有具體看代碼,還沒有實現細節。
下面程序有溢出,但因為檢測了變量j,發現有溢出就提示后退出,用于模擬一些溢出保護或者因形參被覆蓋不能返回的情況。對于這個程序我們一般的溢出攻擊就不能成功。
|
/* 利用異常結構繞過溢出保護攻擊的有問題的例子程序except.c。 vc6.0下編譯。 yuange@nsfocus.com */#include <windows.h>#include <winsock.h>#include <stdio.h> int main(int argc, char **argv){ int j; char *str; char buff1[0x0f80]; char buff2[0x1000]; struct sockaddr_in s_in; struct sockaddr addr; SOCKET fd ,fd1; u_short port; result = WSAStartup(MAKEWORD(1, 1), &wsaData); if (result != 0) { printf("\n SOCKET err!\n "); exit(1); } j=0; str=argv[0]; if(argc>1) port=atoi(argv[1]); else port=1080; fd = socket(AF_INET, SOCK_STREAM,0); s_in.sin_family = AF_INET; s_in.sin_port = htons(port); s_in.sin_addr.s_addr = 0; bind(fd,&s_in,sizeof(s_in)); listen(fd,10); i=sizeof(addr); fd1=accept(fd,&addr,&i); recvbytes=recv(fd1,buff2,0x1000,0); if(recvbytes>0){ buff2[recvbytes]=0; buff2[0x1000-1]=0; printf("\n recv 0x%x bytes \n",recvbytes); strcpy(buff1,buff2); printf("\n the program %s recv :\n %s \n ",argv[0],buff2); } closesocket(fd1); closesocket(fd); WSACleanup( ); if(j!=0){/*溢出后會覆蓋j,被檢測到,這就相當于一些溢出保護*/ printf("\n the program %s buffover err !",argv[0]);/*這兒溢出后可能因為argv[0]被覆蓋,而發生異常,具體環境這代碼可能在前面。這就相當于形參被破壞。*/ exit(1); } } |
下面是攻擊程序:
| 共2頁: 1 [2] 下一頁 | ||
|


