DErDYAST1R/NmiCallbackBlocker

GitHub: DErDYAST1R/NmiCallbackBlocker

通过修改内核 NMI 回调链和处理器亲和性来阻断反作弊系统 NMI 扫描的 Windows 内核驱动概念验证项目。

Stars: 167 | Forks: 17

# 警告 ⚠️ ***本项目不包含任何反作弊保护措施,请使用一个已有的、未被检测的基础驱动程序,这只是一个概念验证项目。*** # 说明 该漏洞利用方式涉及在内核内存中扫描特定特征码,并修改处理器关联掩码以阻止 NMI 执行。该方法采用了规避检测和追踪的技术。 # 功能 1. 我使用 23H2 版本的 NMI_IN_PROGRESS 特征码对其进行特征扫描,并将该结构导入为 (PKNMI_HANDLER_CALLBACK) 以便进行 DKOM 修改。 ``` // nmi_in_progress function (signature) char NmiSignature[] = "\x81\x25\x00\x00\x00\x00\x00\x00\x00\x00\xB9\x00\x00\x00\x00"; // use XOR to encrypt this (will get sig scanned by ac) char NmiSignatureMask[] = "xx????????x????"; // use XOR to encrypt this (will get sig scanned by ac) uintptr_t nmi_in_progress = modules::find_pattern(ntos_base_address, NmiSignature, NmiSignatureMask); return reinterpret_cast(nmi_in_progress); ``` 2. 导入结构后,我遍历 KiNmiCallbackList 并更改特定资产的进程亲和性,以阻止 NMI 执行。 ``` PKNMI_HANDLER_CALLBACK KiNmiCallbackListHead = nullptr; extern "C" NTSTATUS PreventNMIExecution() { KiNmiCallbackListHead = SigscanKiNmiCallbackListHead(); PKNMI_HANDLER_CALLBACK CurrentNMI = KiNmiCallbackListHead; while (CurrentNMI) { uint8_t* nmi_in_progress = reinterpret_cast(KiNmiCallbackListHead); while (*nmi_in_progress != 0x48) { ++nmi_in_progress; } nmi_in_progress = reinterpret_cast(reinterpret_cast(nmi_in_progress) + 3); auto irql = KfRaiseIrql(0); // Use Udman Spoof to not get logged by this ULONG cores = KeQueryActiveProcessorCount(NULL); // Use Udman Spoof to not get logged by this for (auto i = 0ul; i < cores; ++i) { KeInterlockedSetProcessorAffinityEx((PKAFFINITY_EX)nmi_in_progress, i); // Use Udman Spoof to not get logged by this InterlockedBitTestAndSet64(reinterpret_cast(nmi_in_progress), i); } KeLowerIrql(irql); // Use Udman Spoof to not get logged by this CurrentNMI = CurrentNMI->Next; } return STATUS_SUCCESS; } ``` # EAC NMI Walker ``` BOOLEAN EAC::NmiCallbackRoutine( PVOID Context, BOOLEAN Handled ) { auto* callback_context = reinterpret_cast< EAC_NMI_CALLBACK_CONTEXT* >( Context ); auto* data = &callback_context->data_blocks[ KeGetCurrentProcessorNumberEx( NULL ) ]; if ( !data->gdtr_value.base ) { const auto* current_thread = PsGetCurrentThread(); __sgdt( &data->gdtr_value ); data->thread_id = PsGetCurrentThreadId(); data->thread_process_id = PsGetThreadProcessId( current_thread ); data->thread_SystemCallNumber = current_thread->SystemCallNumber; data->thread_StartAddress = current_thread->StartAddress; data->thread_StackLimit = current_thread->StackLimit; data->thread_StackBase = current_thread->StackBase; data->pcr_HalReserved_8 = KeGetPcr()->HalReserved[ 8 ]; data->cr3_value = __readcr3(); data->stack_copy_number_of_bytes = 1024; std::memcpy( &data->stack_copy, _AddressOfReturnAddress(), 1024 ); _InterlockedIncrement( &callback_context->counter ); } return TRUE; } // Not My Code ``` # 注意事项 你需要添加并使用,因为默认情况下这会被检测用于追踪和跟踪调用(如果使用标准的 NtLoad 或标准服务运行)。 - 使用 Udman 欺骗调用 以避免追踪 - 对字符串和特征码使用 XOR 加密 - SpoofCall 和 SpoofFunc 函数 # PatchGuard & HVCI 这将触发 PatchGuard 保护,如果试图绕过 PatchGuard 将触发 HyperGuard 高级保护;如果你还使用了 HVCI(例如在 Valorant/VGK 中),这将导致蓝屏死机 (BSOD) 或阻止修改 NMI 列表的请求,从而导致没有任何变化。我已经在我个人的驱动程序中独立解决了这些问题,但如果你有针对 PatchGuard / HyperGuard 的绕过方法且不使用 HVCI 保护(针对 BE/EAC),这将有效。 # 联系方式 Discord 用户名;bloodieys
标签:0day挖掘, DKOM, DOM解析, EDR对抗, NMI回调, rootkit, T1059, UML, Web报告查看器, Windows内核, 内核内存操作, 内核利用, 内核回调阻断, 内核安全, 反作弊, 反调试, 处理器亲和性, 字典生成, 安全攻防, 游戏安全, 特征扫描, 白帽子, 网络安全监控, 驱动开发