go-shellcode 是一个 Windows Shellcode 运行器及支持工具的仓库。这些应用程序使用各种 API 调用或技术来加载和执行 Shellcode。
可用的 Shellcode 运行器包括:
此应用程序利用 Windows 的 CreateFiber 函数(来自 Kernel32.dll)在该应用程序的进程内执行 shellcode。当您希望避免远程进程注入并避免调用 CreateThread 时,这很有用。此应用程序不使用 golang.org/x/sys/windows 包中的函数。最显著的区别是,此应用程序自行加载所有必要的 DLL 和过程,并使用过程的 Call() 函数。
注意: 我尚未找到让进程退出的方法,您必须手动终止它。
可以使用以下命令在 Windows 主机上从项目根目录编译该应用程序:
set GOOS=windows GOARCH=amd64;go build -o CreateFiber.exe .\cmd\CreateFiber\main.go
此应用程序利用 Windows 的 CreateProcess 函数(来自 Kernel32.dll)。进程以挂起状态创建,更新 IMAGE_OPTIONAL_HEADER 结构中的 AddressOfEntryPoint 以在子进程中执行 shellcode,然后恢复进程。这是一种进程镂空技术,但现有的 PE 没有被取消映射,且 ThreadContext 没有被更新。提供的 shellcode 架构(即 x86 或 x64)必须与子进程的架构匹配。
可以使用以下命令在 Windows 主机上从项目根目录编译该应用程序:
set GOOS=windows GOARCH=amd64;go build -o CreateProcess.exe .\cmd\CreateProcess\main.go
此应用程序利用 Windows 的 CreateProcess 函数(来自 Kernel32.dll)。进程以挂起状态创建,更新 IMAGE_OPTIONAL_HEADER 结构中的 AddressOfEntryPoint 以在子进程中执行 shellcode,然后恢复进程。这是一种进程镂空技术,但现有的 PE 没有被取消映射,且 ThreadContext 没有被更新。提供的 shellcode 架构(即 x86 或 x64)必须与子进程的架构匹配。
此应用程序与 CreateProcess 的不同之处在于,它会收集子进程中写入 STDOUT 或 STDERR 的任何数据,并将其返回给父进程。通过使用 CreatePipe 函数创建匿名管道,父进程和子进程通过该管道进行通信来收集数据。当使用像 Donut 这样的工具在子进程中以 shellcode 形式执行 .NET 程序集并检索执行程序的输出时,这很有用。以下命令可用于生成位置无关的 shellcode,以使用 Donut v0.9.3 运行 Seatbelt:
.\donut.exe -o donut_v0.9.3_Seatbelt.bin -x 2 -c Seatbelt.Program -m Main -p "ARPTable" Seatbelt.exe
可以使用以下命令在 Windows 主机上从项目根目录编译该应用程序:
set GOOS=windows GOARCH=amd64;go build -o CreateProcessWithPipe.exe .\cmd\CreateProcessWithPipe\main.go
此应用程序利用 Windows 的 CreateRemoteThread 函数(来自 Kernel32.dll)在远程进程中执行 shellcode。该应用程序要求目标注入进程必须已运行。可以使用 -pid 命令行参数在运行时提供目标进程 ID (PID) 以进行测试。在实际使用中,通过将以下代码行中的 0 替换为目标 PID 来硬编码 PID:
pid := flag.Int("pid", 0, "要注入 shellcode 的进程 ID")
此应用程序在可行的情况下使用 golang.org/x/sys/windows 包中的函数,例如 windows.OpenProcess()。可以使用以下命令在 Windows 主机上从项目根目录编译该应用程序:
set GOOS=windows GOARCH=amd64;go build -o CreateRemoteThread.exe .\cmd\CreateRemoteThread\main.go
此应用程序利用 Windows 的 CreateRemoteThread 函数(来自 Kernel32.dll)在远程进程中执行 shellcode。该应用程序要求目标注入进程必须已运行。可以使用 -pid 命令行参数在运行时提供目标进程 ID (PID) 以进行测试。在实际使用中,通过将以下代码行中的 0 替换为目标 PID 来硬编码 PID:
pid := flag.Int("pid", 0, "要注入 shellcode 的进程 ID")
此应用程序不使用 golang.org/x/sys/windows 包中的函数。最显著的区别是,此应用程序自行加载所有必要的 DLL 和过程,并使用过程的 Call() 函数。可以使用以下命令在 Windows 主机上从项目根目录编译该应用程序:
set GOOS=windows GOARCH=amd64;go build -o CreateRemoteThreadNative.exe .\cmd\CreateRemoteThreadNative\main.go
此应用程序利用 Windows 的 CreateThread 函数(来自 Kernel32.dll)在该应用程序的进程内执行 shellcode。当您希望避免远程进程注入时,这很有用。此应用程序在可行的情况下使用 golang.org/x/sys/windows 包中的函数,例如 windows.VirtualAlloc()。可以使用以下命令在 Windows 主机上从项目根目录编译该应用程序:
set GOOS=windows GOARCH=amd64;go build -o CreateThread.exe .\cmd\CreateThread\main.go
此应用程序利用 Windows 的 CreateThread 函数(来自 Kernel32.dll)在该应用程序的进程内执行 shellcode。当您希望避免远程进程注入时,这很有用。此应用程序不使用 golang.org/x/sys/windows 包中的函数。最显著的区别是,此应用程序自行加载所有必要的 DLL 和过程,并使用过程的 Call() 函数。可以使用以下命令在 Windows 主机上从项目根目录编译该应用程序:
set GOOS=windows GOARCH=amd64;go build -o CreateThreadNative.exe .\cmd\CreateThreadNative\main.go
该应用程序利用 Windows 的 CreateProcess 函数以挂起状态创建一个进程。子进程挂起后,使用 Windows 的 QueueUserAPC 函数向子进程添加一个指向已分配 shellcode 的用户 APC。接下来,调用 ResumeThread,它会依次调用未文档化的 NtTestAlert 函数,该函数将执行创建的 UserAPC 并进而执行 shellcode。这很有用,因为 shellcode 将在 AV/EDR 能够挂钩函数以支持检测之前执行。参考 发现新的 'Early Bird' 代码注入技术。可以使用以下命令在 Windows 主机上从项目根目录编译该应用程序:
export GOOS=windows GOARCH=amd64;go build -o goEarlyBird.exe cmd\EarlyBird\main.go
此应用程序利用 Windows 的 EtwpCreateEtwThread 函数(来自 ntdll.dll)在该应用程序的进程内执行 shellcode。原始工作由 TheWover 完成。当您希望避免远程进程注入时,这很有用。此应用程序不使用 golang.org/x/sys/windows 包中的函数。最显著的区别是,此应用程序自行加载所有必要的 DLL 和过程,并使用过程的 Call() 函数。可以使用以下命令在 Windows 主机上从项目根目录编译该应用程序:
set GOOS=windows GOARCH=amd64;go build -o EtwpCreateEtwThread.exe .\cmd\EtwpCreateEtwThread\main.go
此应用程序使用未文档化的 NtQueueApcThreadEx 在当前进程的当前线程中创建一个“特殊用户 APC”以执行 shellcode。由于 shellcode 在当前进程中加载并执行,因此是“本地”的。同样的技术也可以用于远程进程。注意: 这仅在 Windows 7 或更高版本上有效。参考 APC 系列:用户 APC API。
export GOOS=windows GOARCH=amd64;go build -o goNtQueueApcThreadEx-Local.exe cmd\NtQueueApcThreadEx-Local\main.go
此应用程序利用 Windows 的 RtlCreateUserThread 函数(来自 ntdll.dll)在远程进程中执行 shellcode。该应用程序要求目标注入进程必须已运行。可以使用 -pid 命令行参数在运行时提供目标进程 ID (PID) 以进行测试。在实际使用中,通过将以下代码行中的 0 替换为目标 PID 来硬编码 PID:
pid := flag.Int("pid", 0, "要注入 shellcode 的进程 ID")
此应用程序不使用 golang.org/x/sys/windows 包中的函数。最显著的区别是,此应用程序自行加载所有必要的 DLL 和过程,并使用过程的 Call() 函数。可以使用以下命令在 Windows 主机上从项目根目录编译该应用程序:
set GOOS=windows GOARCH=amd64;go build -o RtlCreateUserThread.exe .\cmd\RtlCreateUserThread\main.go
此应用程序通过直接对 Shellcode 的入口点进行系统调用来在当前运行进程中执行 Shellcode。此应用程序不使用 golang.org/x/sys/windows 包中的函数。可以使用以下命令在 Windows 主机上从项目根目录编译该应用程序:
set GOOS=windows GOARCH=amd64;go build -o Syscall.exe .\cmd\Syscall\main.go