通过滥用矢量异常处理 (VEH) 来绕过 Windows 中的用户态 EDR 挂钩,从而生成合法的调用堆栈框架以及间接系统调用。
随附的博客文章可以在此处找到:LayeredSyscall – 滥用 VEH 绕过 EDR
用法
在源代码中包含文件FuncWrappers.h和FuncWrappers.cpp 。
确保在主代码的开始和结束时IntializeHooks()使用调用来初始化和销毁钩子。DestroyHooks()
为了该工具执行规避,请在要使用的系统调用名称开头添加前缀“wrp”。例如,
NtCreateUserProcess() -> wrpNtCreateUserProcess()
在该工具的当前版本中,用户还可以更改他们想要使用的合法调用堆栈。他们所要做的就是更改 中的 Windows APIdemofunction()调用HookModule.cpp。
void demofunction() {
// You can change this call to any other Windows API call you like
MessageBox(
NULL,
(LPCWSTR)L"Resource not availablenDo you want to try again?",
(LPCWSTR)L"Account Details",
MB_ICONWARNING | MB_CANCELTRYCONTINUE | MB_DEFBUTTON2
);
}
下面是一个演示代码,展示如何使用该工具,完整代码可以在这里找到。
int main(int argc, char* argv[]) {
printf("[*] Program Startedn");
IntializeHooks();
WCHAR image_path[] = L"\??\C:\Windows\System32\calc.exe";
UNICODE_STRING NtImagePath;
RtlInitUnicodeString(&NtImagePath, (PWSTR)L"\??\C:\Windows\System32\calc.exe");
// Create the process parameters
PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
RtlCreateProcessParametersEx(&ProcessParameters, &NtImagePath, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, RTL_USER_PROCESS_PARAMETERS_NORMALIZED);
// Initialize the PS_CREATE_INFO structure
PS_CREATE_INFO CreateInfo = { 0 };
CreateInfo.Size = sizeof(CreateInfo);
CreateInfo.State = PsCreateInitialState;
// Initialize the PS_ATTRIBUTE_LIST structure
PPS_ATTRIBUTE_LIST AttributeList = (PS_ATTRIBUTE_LIST*)RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PS_ATTRIBUTE));
AttributeList->TotalLength = sizeof(PS_ATTRIBUTE_LIST) - sizeof(PS_ATTRIBUTE);
AttributeList->Attributes[0].Attribute = PS_ATTRIBUTE_IMAGE_NAME;
AttributeList->Attributes[0].Size = NtImagePath.Length;
AttributeList->Attributes[0].Value = (ULONG_PTR)NtImagePath.Buffer;
HANDLE hProcess, hThread = NULL;
BOOL success = FALSE;
LPVOID remote_base_addr = NULL;
CONTEXT thread_context = { 0 };
// create the target process in a suspended state so we can modify its memory and the context of its main thread
if (wrpNtCreateUserProcess(&hProcess, &hThread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS, NULL, NULL,
NULL, NULL, ProcessParameters, &CreateInfo, AttributeList))
{
printf("CreateProcessA() Failed with error: %dn", GetLastError());
return -1;
}
DestroyHooks();
printf("[*] Program Endedn");
return 1;
}
待办事项
-
提供全局堆栈欺骗选项,而不仅仅是每个 API 堆栈欺骗
-
除工具中已有的选项外,还提供随机合法 Windows API 调用的选项
结果
调用堆栈分析
执行间接系统调用时未显示合法的调用堆栈
使用该工具后的合法调用堆栈
潜在检测
到目前为止,针对此技术的检测需要检查特定程序中是否存在恶意注册的异常处理程序。其他检测方法还包括通过对 Windows API 生成的已知调用堆栈实施启发式方法来标记异常堆栈行为。
项目地址:
https://github.com/WKL-Sec/LayeredSyscall
原文始发于微信公众号(Ots安全):LayeredSyscall – 滥用向量异常处理来绕过 EDR
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论