因为代码非常好理解,我将不浪费时间逐行解释它了,使用JMP/CALL技巧能在运行时得到shellcode和密钥的地址,然后在shellcode和密钥的每个字节之间执行一个逻辑XOR操作,每次解密密钥到末尾,它将重置密钥为它的起始地址,在完成解码操作后,将跳转到shellcode,使用更长的XOR密钥能提高shellcode的随机性,但是也提高了代码块的熵,因此要避免使用太长的解码密钥,使用基础的逻辑操作(如XOR,NOT,ADD,SUB,ROR,ROL)能有几百种方式编码shellcode,在每种编码器中有无穷可能的shellcode输出,AV产品在解码序列之前检测到任何shellcode的特征的概率很低,因为这种AV产品也开发了启发式引擎,它能够检测解密和代码块中的解码循环。当编写shellcode编码器时,几乎没有用于绕过用于检测解码循环的静态方法的有效方式。
不常见的寄存器的使用:
在x86架构中,所有的寄存器有一个特定的目的,例如ECX表示扩展计数寄存器,且它通常用于循环计数。当我们编写一个基础的循环条件时,编译器可能使用ECX寄存器作为循环计数器变量,在一个代码块中找到连续增长的ECX寄存器强烈暗示了一个循环,这个问题的解决方案非常简单,不使用ECX作为循环计数器,这只是一个例子,但是它对于所有的其它类型的代码片段(如函数epilogue/prologue等)也非常有效。大量的代码识别机制依赖寄存器的使用,使用不常见的寄存器编写汇编代码将减小被检测率。
垃圾代码填充:
在代码块中可能有几百种方法识别解码器,且几乎每个AV产品使用不同的方式,但是最终他们都不得不将可能的解码器的代码块生成一个特征,在解码器代码中使用随机的NOP指令是绕过静态特征分析的一种非常好的方式,不一定要使用NOP指令,可以是任何维持原有功能的其他指令,目标是增加垃圾指令以便破环代码块的恶意的特征。另一个关于编写shellcode重要的事是大小,因此避免使用太大的垃圾混淆代码否则将增加整体大小。
实现这种方法的代码如下:
唯一的改变在于EAX和ECX寄存器,现在在shellcode中负责计数的寄存器是EAX,且在每个XOR和MOV指令之间插入一些NOP填充,通过这个教程使用的shellcode是Windows Meterpreter反向TCP,在使用一个10字节长的随机XOR密钥加密shellcode后,一起放置在解码器中,使用nasm –f bin Decoder.asm命令汇编解码器为二进制格式(不要忘了移除shellcode中的换行符,否则nasm不能汇编它)。
下面是编码前shellcode的AV扫描结果,
如你所见,大量的AV扫描器识别了shellcode。下面是shellcode编码后的扫描结果。
0x07 对抗利用缓解措施
绕过AV产品有很多中方法,但是对抗利用缓解措施导致形式变了,2009年微软宣称EMET,它是一个工具包,来帮助阻止在软件中的漏洞利用,它有下面几种机制:
动态数据执行保护(DEP)
结构化异常处理覆盖保护(SEHOP)
NullPage分配
堆喷射保护
导出地址表地址过滤(EAF)
强制ASLR
导出地址表地址过滤增强版(EAF )
ROP缓解措施
加载库校验
内存保护校验
调用者校验
模拟执行流
Stack pivot
Attack Surface Reduction(ASR)
在这些缓解措施中EAF,EAF 和调用者校验使我们最关心的。正如早前解释的,在metasploit框架中几乎所有的shellcode使用Stephen Fewer的HASH API,且因为Hash API使用了PEB/EAT解析技术,EMET能简单的检测到并阻止shellcode的执行。
0x08 绕过EMET
在EMET中的调用者校验检查进程中的Windows API调用,它能阻止API函数中的RET和JMP指令,以便阻止使用ROP方式的所有的利用,在HASH API中,在找到需要的API函数地址后,使用JMP指令执行函数,不幸的是这将触发EMET调用者校验,为了绕过调用者校验,应该避免使用JMP和RET指令指向API函数,使用CALL代替JMP指令执行API函数,Hash API应该绕过调用者校验,但是当我们看到EAF/EAF 缓解机制时,它们根据调用的代码阻止访问导出地址表(EAT),并且它检查栈寄存器是否在允许的边界内,或者它尝试读MZ/PE头和KERNELBASE,对于阻止EAT解析技术这是非常有效的缓解措施,但是EAT不是唯一一个包含函数地址的结构,导入地址表(IAT)也保存程序使用的API函数的地址,如果应用程序也使用我们需要的函数,在IAT结构中获得函数地址是可能的,一个叫Joshua Pitts的安全研究员最近开发一种新的IAT解析的方法,它在IAT中找到LoadLibraryA和GetProcAddress的地址,在获得这些函数的地址,能从任何库中得到任何函数,他也为Stephen Fewer的Hash API写了一个称为fibo的工具,且使用他写的IAT解析代码代替,如果你想阅读这种方法的更多细节,参见这里。
0x09 参考
https://msdn.microsoft.com/en-us/library/ms809762.aspx
https://en.wikipedia.org/wiki/Process_Environment_Block
https://support.microsoft.com/en-us/help/875352/a-detailed-description-of-the-data-execution-prevention-dep-feature-in-windows-xp-service-pack-2,-windows-xp-tablet-pc-edition-2005,-and-windows-server-2003
https://en.wikipedia.org/wiki/Portable_Executable
https://en.wikipedia.org/wiki/Address_space_layout_randomization
https://en.wikipedia.org/wiki/X86_calling_conventions
http://www.vividmachines.com/shellcode/shellcode.html
https://github.com/secretsquirrel/fido
https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/x86/src/block/block_api.asm
https://www.amazon.com/Shellcoders-Handbook-Discovering-Exploiting-Security/dp/047008023X
https://www.amazon.com/Sockets-Shellcode-Porting-Coding-Professionals/dp/1597490059