從頭說起—淺談Linux ShellCode

來源:互聯網
上載者:User


Author: wangweinoo1[A.X.D]
EMail: wangweinoo1@gmail.com
Date: 2009.1.14
Note:本人首發於shudoo,後由原創作者提交至邪八,轉載請註明

文章目錄:
1.什麼是ShellCode
2.Shellcode編寫考慮因素
3.從Windows ShellCode說起
4.正題開始——Linux系統調用
5.第一個Linux ShellCode
6.綁定連接埠的shellcode
7.總結

一、什麼是ShellCode
    讓我們從一個經典的故事開始ShellCode之旅
    話說某天某愛國駭客編譯了一個Nday溢出利用程式來攻擊CNN,輸入IP並且enter之後發現目標伺服器沒有反應,於是拿出sniffer抓包分析...“Oh ,my dog!居然沒有帶shellcode!”為什麼 shellcode對於一個exploit來說這麼重要呢?Shellcode到底是什麼東西呢?
    簡單的說,Shellcode是一段能夠完成某種特定功能的二進位代碼。具體完成什麼任務是由攻擊者決定的,可能是開啟一個新的shell或者下載某個特定的程式也或者向攻擊者返回一個shell等等。
    Shellcode是溢出程式和蠕蟲的核心,提到它自然就會和漏洞聯想在一起,畢竟Shellcode只對沒有打補丁的主機有用武之地。網路上數以萬計帶著漏洞頑強運行著的伺服器給hacker和Vxer豐盛的晚餐。漏洞利用中最關鍵的是Shellcode的編寫。由於漏洞發現者在漏洞發現之初並不會給出完整Shellcode,因此掌握Shellcode編寫技術就顯得尤為重要。
    因為shellcode將會直接操作寄存器和一些系統調用,所以對於shellcode的編寫基本上是用進階語言編寫一段程式然後編譯,反組譯碼從而得到16進位的作業碼,當然也可以直接寫彙編然後從二進位檔案中提取出16進位的作業碼。
    接下來就一起來解開shellcode的神秘面紗吧~

二、Shellcode編寫考慮因素
    Shellcode一般作為資料發送給服務端造成溢出,不同資料對資料要求不同,因此,Shellcode也不一定相同。但Shellcode在編寫過程中,有些問題是一致的:
    1.Shellcode的編寫語言
    用什麼語言編寫最適合Shellcode呢?這個問題沒有定論。Shellcode本質上可以使用任何程式設計語言,但我們需要的是提取其中的機器碼。Shellcode使用組合語言編寫是最具可控性的,因為我們完全可以通過指令控制碼產生,缺點就是需要大量的時間,而且還要你深入瞭解彙編。如果你想追求速度,C是不錯的選擇。C語言編寫起來較為省力,但Shellcode提取較為複雜,不過,一旦寫好模板,就省事許多。例如,這裡有一個寫好的模板:複製內容到剪貼簿代碼:
        void Shellcode()
       {
           __asm
       {
           nop
           nop
           nop
           nop
           nop
           nop
           nop
           nop
        }
        }然後在main()中用函數指標操作和memcmp定位shellcode,用pintf之類函數將shellcode打出來或儲存即可。範例程式碼我就不寫了。縱觀當前shellcode,大部分是由C完成的,因此,想來大家已經取捨完了吧?
    2.Shellcode本身代碼的重定位。Shellcode的流程式控制制,即如何通過溢出使控制權落在Shellcode手中
    3.Shellcode中使用的API地址定位。
    4.Shellcode編碼問題。
    5.多態技術躲避IDS檢測。
    這些問題我將在後面幾章與大家探討


三、從Windows ShellCode說起
    在本章,我將和大家談談關於程式EIP的擷取、API的地址定位、ShellCode編碼
    1.Shellcode代碼地址定位,擷取程式EIP
     為什麼要擷取EIP呢?原因是,我們需要我們的Shellcode能夠執行,對病毒技術有瞭解的話,應該知道他們是怎麼
定位的:利用CALL/POP來實現。 這裡就不得不提到兩種方法:JMP ESP和CALL/POP EBX。這是人們在對windows熟悉之後的方法,成功率非常高。(感謝各位逆向大牛。。。)我們的方法時通過Shellcode地址覆蓋返回地址,在溢出後即可跳轉到我們的代碼中,以擷取許可權。而Shellcode
在記憶體中的地址並不固定,因此我們利用系統的DLL檔案中的JMP ESP或CALL ESP、CALL EBP來實現對Shellcode地址
的間接跳轉。這樣有兩個好處,一是不必準確定位Shellcode地址;二是可以防止strcpy對00位元組的截斷,因為DLL文
件中,地址一般為7FXXXXXX。具體細節,限於篇幅,就不在這裡贅述了,大家可以baidu一下。
    2.Shellcode中的API地址定位
    Shellcode代碼的運行環境和病毒在某些方面是類似的,由於系統不同,Api的地址也不盡相同。因此,要想讓
Shellcode在不同Windows下運行就必須解決Api的定位問題。API定位的關鍵是瞭解Windows DLL映像檔案格式,即PE
檔案格式,然後通過搜尋函數的Export表擷取API地址。定位方法有暴力搜尋法、從進程PEB中擷取和遍曆SEH鏈法。我
們這裡使用從進程PEB中擷取,範例程式碼如下:複製內容到剪貼簿代碼:
__asm
{
push ebp;
sub esp, 0x40;
mov ebp,esp;

push ebp;
mov eax, fs:0x30 ;PEB
mov eax, [eax + 0x0c] ;Ldr
mov esi, [eax + 0x1c] ;Flink
lodsd
mov edi, [eax + 0x08] ;edi就是kernel32.dll的地址

mov eax, [edi+3Ch] ;eax = PE首部
mov edx,[edi+eax+78h]
add edx,edi ;edx = 輸出表地址
mov ecx,[edx+18h] ;ecx = 輸出函數的個數
mov ebx,[edx+20h]
add ebx,edi ;ebx =函數名地址,AddressOfName
search:
dec ecx
mov esi,[ebx+ecx*4]
add esi,edi ;依次找每個函數名稱
;GetProcAddress
mov eax,0x50746547
cmp [esi], eax; PteG
jne search
mov eax,0x41636f72
cmp [esi+4],eax; Acor
jne search

;如果是GetProcA,表示找到了
mov ebx,[edx+24h]
add ebx,edi ;ebx = 索引號地址,AddressOf
mov cx,[ebx+ecx*2] ;ecx = 計算出的索引號值
mov ebx,[edx+1Ch]
add ebx,edi ;ebx = 函數地址的起始位置,AddressOfFunction
mov eax,[ebx+ecx*4]
add eax,edi ;利用索引值,計算出GetProcAddress的地址


mov [ebp+40h], eax ;把GetProcAddress的地址存在 ebp+40中接下來是使用GetProcAddress()和LoadLibraryA()擷取其他需要函數了,和C沒什麼兩樣,略過了吧,細節才是最麻煩的。。。。
    3.Shellcode的編碼問題
    這是讓俺們這些菜菜寫ShellCode最頭疼的東西了。。。例如:strcpy函數中不能有0x00,RPC DOCM溢出時不能用0x5c等等。因為假如有這些字元,會導致服務中斷Shellcode,溢出失敗。不同溢出對shellcode要求不同,當然需要精選字元來達到目的,這樣太累了些,簡單點就是寫一段代碼,樣本如下:複製內容到剪貼簿代碼:
for(i=0;i ch=sc_buff^Enc_key;
//對可能字元進行替換
if(ch<=0x1f||ch== ||ch==.||ch==/||ch==\||ch==0||ch==?||ch==%||ch==+)
{
buff=0;
++k;
ch+=0x31;
}
//將編碼Code放在DecryptSc後
buff[k]=ch;
++k;
}
解碼時代碼 解碼時代碼,樣本如下:
jmp next
getEncodeAddr:
pop edi
push edi
pop esi
xor ecx,ecx
Decrypt_lop:
loasb
cmp al,cl
jz shell
cmp al,0x30 //判斷是否為特殊字元
jz specal_char_clean
store:
xor al,Enc_key
stosb
jmp Decrypt_lop
special_char_clean:
lodsb
sub al,0x31
jmp store
next:
call getEncodeAddr這裡只給了一個簡單的例子,面對對Unicode編碼有要求的,限於篇幅,這裡就不詳解了
    原本不想把Windows shell寫這麼多的,寫寫就寫多了,唉,果然沒有什麼經驗。本章最後再說一點RP問題。ShellCode寫起來會很辛苦,夠俺這種菜菜一個code得寫N天天。。。但寫罷,你就會知道成就感是什麼了。。。^_^另外這裡不是教你做EXP去害人,只是從研究角度出發,讓大家瞭解這種技術,從而加以防範,為網路和平安寧奉獻自己的力量。

四、正題開始——Linux系統調用
    為什麼編寫shellcode需要瞭解系統調用呢?因為系統調用是 使用者態和核心態之間的一座橋樑。大多數作業系統都提供了很多應用程式可以訪問到的核心函數,shellcode當然也需要調用這些 核心函數。Linux系統提供的核心函數可以方便的實現用來訪問檔案,執行命令,網路通訊等等功能。這些函數就被成為系統調用(System Call)。
    想知道系統上到底有哪些系統調用可以用,直接查看核心代碼即可得到。Linux的系統調用在以下檔案中定義:/usr/include/asm-i386 /unistd.h,該檔案包含了系統中每個可用的系統調用的定義,內容大概如下:複製內容

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.