简单来说就是可以直接加载可读内存中的加密 ShellCode,不需要解密,不需要申请新的内存,也不需要改可执行权限。应用不仅仅在上线,上线后的各种功能都可以通过 ShellCode 实现
1.查杀点
现状
在加载 ShellCode、使用 BOF 等时候,经常需要将机器码密文解密写入可写权限的内存,再改为可执行权限来运行
弊端
需要经常进行内存属性修改的敏感行为,并且机器码明文处于可执行权限的内存中,迟早会被查杀
2.规避查杀点
目标
不使用 RWX、不修改内存属性、不解密 ShellCode,就可以加载 ShellCode
解决方案
代码编写 -> 提取 ShellCode -> 机器码转汇编 -> 汇编转换自定义语言 -> 通过解释器运行
3.解释器实现
解释器和编译器的区别
编译器就类似常规的 ShellCode 加载方式,去运行机器码
解释器是去解析你自定义的语言来进行对应的操作
实现原理
一步一步讲
获取 ShellCode 汇编
ShellCode.c:
生成 ShellCode.exe 后提取 ShellCode (ctrl+shift+c),粘贴至 asm.txt
机器码转汇编.py:
输出 (保存到 ShellCode.txt):
分析 ShellCode 调用过程
ShellCodeLoader.c:
调试转到反汇编
发现在进入 ShellCode 内联汇编前将 MessageBox 地址和 call 的下一行地址入栈了
进入内联汇编后,除了平栈就是继续构造 Windows API 的栈区域
实现调用过程
只要能将 Windows API 的栈区域正确构建出来,就可以正确调用 Windows API
实现一个虚拟环境,包含虚拟寄存器、虚拟栈
将进入内联汇编前的真实环境状态复制到虚拟环境
解析内联汇编的指令文本,在虚拟环境中构建出正确的 Windows API 栈区域
调用 call 前,已经将 Windows API 的栈区域正确构建出来了
之后想成功 call Windows API 只需要将真实环境中的栈移到虚拟环境中,调用完再移回来就可以了
步骤总结
ShellCode 汇编指令文本 -> ShellCode.txt
解释器:构造初始虚拟环境 -> 读取汇编指令文本 -> 遍历指令 -> 解析指令调用对应指令的处理器 -> 处理器继续构造栈区域 -> 栈进入虚拟环境调用 Windows API -> 处理器继续收尾工作